commit 721d9fd98ee50c9f9c6a5020a2fc943ed00b70dd Author: Liangxinwei <623847317@qq.com> Date: Tue Oct 14 11:14:54 2025 +0800 初始提交: UE5.3项目基础框架 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9dd6036 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +* text=auto +*.uproject text eol=lf +*.sln text eol=lf +*.vsconfig text eol=lf +*.ini text eol=lf +*.target text eol=lf +*.modules text eol=lf \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..715b38f --- /dev/null +++ b/.gitignore @@ -0,0 +1,76 @@ +# ---> UnrealEngine +# Visual Studio 2015 user specific files +.vs/ + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +*.ipa + +# These project files can be generated by the engine +*.xcodeproj +*.xcworkspace +*.sln +*.suo +*.opensdf +*.sdf +*.VC.db +*.VC.opendb + +# Precompiled Assets +SourceArt/**/*.png +SourceArt/**/*.tga + +# Binary Files +Binaries/* +Plugins/**/Binaries/* + +# Builds +Build/* + +# Whitelist PakBlacklist-.txt files +!Build/*/ +Build/*/** +!Build/*/PakBlacklist*.txt + +# Don't ignore icon files in Build +!Build/**/*.ico + +# Built data for maps +*_BuiltData.uasset + +# Configuration files generated by the Editor +Saved/* + +# Compiled source files for the engine to use +Intermediate/* +Plugins/**/Intermediate/* + +# Cache files for the editor to use +DerivedDataCache/* + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..1f86227 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "BXSSP_Andriod"] + path = BXSSP_Andriod + url = http://xny.yj-3d.com:3000/Liangxinwei/BXSSP_Andriod.git diff --git a/.vsconfig b/.vsconfig new file mode 100644 index 0000000..41c868c --- /dev/null +++ b/.vsconfig @@ -0,0 +1,14 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.Net.Component.4.6.2.TargetingPack", + "Microsoft.VisualStudio.Component.VC.14.36.17.6.x86.x64", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "Microsoft.VisualStudio.Component.Windows10SDK.22000", + "Microsoft.VisualStudio.Workload.CoreEditor", + "Microsoft.VisualStudio.Workload.ManagedDesktop", + "Microsoft.VisualStudio.Workload.NativeCrossPlat", + "Microsoft.VisualStudio.Workload.NativeDesktop", + "Microsoft.VisualStudio.Workload.NativeGame" + ] +} diff --git a/BXSSP.uproject b/BXSSP.uproject new file mode 100644 index 0000000..0bbfbc1 --- /dev/null +++ b/BXSSP.uproject @@ -0,0 +1,45 @@ +{ + "FileVersion": 3, + "EngineAssociation": "5.3", + "Category": "", + "Description": "", + "Modules": [ + { + "Name": "BXSSP", + "Type": "Runtime", + "LoadingPhase": "Default", + "AdditionalDependencies": [ + "Engine" + ] + } + ], + "Plugins": [ + { + "Name": "ModelingToolsEditorMode", + "Enabled": true, + "TargetAllowList": [ + "Editor" + ] + }, + { + "Name": "UNTLink", + "Enabled": true + }, + { + "Name": "CesiumForUnreal", + "Enabled": true, + "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/87b0d05800a545d49bf858ef3458c4f7", + "SupportedTargetPlatforms": [ + "Win64", + "Mac", + "Linux", + "Android", + "IOS" + ] + }, + { + "Name": "GeometryScripting", + "Enabled": true + } + ] +} \ No newline at end of file diff --git a/BXSSP_Andriod b/BXSSP_Andriod new file mode 160000 index 0000000..173fff9 --- /dev/null +++ b/BXSSP_Andriod @@ -0,0 +1 @@ +Subproject commit 173fff9de18ef0905f25bf67017f5d3856c00a65 diff --git a/Config/DefaultEditor.ini b/Config/DefaultEditor.ini new file mode 100644 index 0000000..e69de29 diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini new file mode 100644 index 0000000..f630b2a --- /dev/null +++ b/Config/DefaultEngine.ini @@ -0,0 +1,295 @@ + + +[/Script/EngineSettings.GameMapsSettings] +EditorStartupMap=/Game/Game/Maps/AndroidMap02.AndroidMap02 +LocalMapOptions= +TransitionMap=None +bUseSplitscreen=False +TwoPlayerSplitscreenLayout=Horizontal +ThreePlayerSplitscreenLayout=FavorTop +FourPlayerSplitscreenLayout=Grid +bOffsetPlayerGamepadIds=False +GameInstanceClass=/Script/Engine.GameInstance +GameDefaultMap=/Game/Game/Maps/AndroidMap02.AndroidMap02 +ServerDefaultMap=/Engine/Maps/Entry.Entry +GlobalDefaultGameMode=/Script/Engine.GameModeBase +GlobalDefaultServerGameMode=None + +[/Script/WindowsTargetPlatform.WindowsTargetSettings] +DefaultGraphicsRHI=DefaultGraphicsRHI_DX12 +-D3D12TargetedShaderFormats=PCD3D_SM5 ++D3D12TargetedShaderFormats=PCD3D_SM6 +-D3D11TargetedShaderFormats=PCD3D_SM5 ++D3D11TargetedShaderFormats=PCD3D_SM5 +Compiler=Default +AudioSampleRate=48000 +AudioCallbackBufferFrameSize=1024 +AudioNumBuffersToEnqueue=1 +AudioMaxChannels=0 +AudioNumSourceWorkers=4 +SpatializationPlugin= +SourceDataOverridePlugin= +ReverbPlugin= +OcclusionPlugin= +CompressionOverrides=(bOverrideCompressionTimes=False,DurationThreshold=5.000000,MaxNumRandomBranches=0,SoundCueQualityIndex=0) +CacheSizeKB=65536 +MaxChunkSizeOverrideKB=0 +bResampleForDevice=False +MaxSampleRate=48000.000000 +HighSampleRate=32000.000000 +MedSampleRate=24000.000000 +LowSampleRate=12000.000000 +MinSampleRate=8000.000000 +CompressionQualityModifier=1.000000 +AutoStreamingThreshold=0.000000 +SoundCueCookQualityIndex=-1 + +[/Script/HardwareTargeting.HardwareTargetingSettings] +TargetedHardwareClass=Mobile +AppliedTargetedHardwareClass=Mobile +DefaultGraphicsPerformance=Scalable +AppliedDefaultGraphicsPerformance=Scalable + +[/Script/Engine.RendererSettings] +r.Mobile.ShadingPath=0 +r.Mobile.AllowDeferredShadingOpenGL=False +r.Mobile.SupportGPUScene=False +r.Mobile.AntiAliasing=1 +r.Mobile.FloatPrecisionMode=0 +r.Mobile.AllowDitheredLODTransition=False +r.Mobile.VirtualTextures=False +r.DiscardUnusedQuality=False +r.AllowOcclusionQueries=True +r.MinScreenRadiusForLights=0.030000 +r.MinScreenRadiusForDepthPrepass=0.030000 +r.MinScreenRadiusForCSMDepth=0.010000 +r.PrecomputedVisibilityWarning=False +r.TextureStreaming=True +Compat.UseDXT5NormalMaps=False +r.VirtualTextures=False +r.VT.EnableAutoImport=True +r.VirtualTexturedLightmaps=False +r.VT.AnisotropicFiltering=False +bEnableVirtualTextureOpacityMask=True +r.VT.TileSize=128 +r.VT.TileBorderSize=4 +r.vt.FeedbackFactor=16 +WorkingColorSpaceChoice=sRGB +RedChromaticityCoordinate=(X=0.640000,Y=0.330000) +GreenChromaticityCoordinate=(X=0.300000,Y=0.600000) +BlueChromaticityCoordinate=(X=0.150000,Y=0.060000) +WhiteChromaticityCoordinate=(X=0.312700,Y=0.329000) +r.ClearCoatNormal=False +r.DynamicGlobalIlluminationMethod=1 +r.ReflectionMethod=1 +r.ReflectionCaptureResolution=128 +r.ReflectionEnvironmentLightmapMixBasedOnRoughness=True +r.Lumen.HardwareRayTracing=False +r.Lumen.HardwareRayTracing.LightingMode=0 +r.Lumen.TranslucencyReflections.FrontLayer.EnableForProject=False +r.Lumen.TraceMeshSDFs=1 +r.Shadow.Virtual.Enable=1 +r.RayTracing=False +r.RayTracing.Shadows=False +r.RayTracing.UseTextureLod=False +r.PathTracing=True +r.GenerateMeshDistanceFields=True +r.DistanceFields.DefaultVoxelDensity=0.200000 +r.Nanite.ProjectEnabled=True +r.AllowStaticLighting=True +r.NormalMapsForStaticLighting=False +r.ForwardShading=False +r.VertexFoggingForOpaque=True +r.SeparateTranslucency=False +r.TranslucentSortPolicy=0 +TranslucentSortAxis=(X=0.000000,Y=-1.000000,Z=0.000000) +xr.VRS.FoveationLevel=0 +xr.VRS.DynamicFoveation=False +r.CustomDepth=1 +r.CustomDepthTemporalAAJitter=True +r.PostProcessing.PropagateAlpha=0 +r.DefaultFeature.Bloom=False +r.DefaultFeature.AmbientOcclusion=False +r.DefaultFeature.AmbientOcclusionStaticFraction=True +r.DefaultFeature.AutoExposure=False +r.DefaultFeature.AutoExposure.Method=0 +r.DefaultFeature.AutoExposure.Bias=1.000000 +r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True +r.DefaultFeature.LocalExposure.HighlightContrastScale=0.800000 +r.DefaultFeature.LocalExposure.ShadowContrastScale=0.800000 +r.DefaultFeature.MotionBlur=False +r.DefaultFeature.LensFlare=False +r.TemporalAA.Upsampling=True +r.AntiAliasingMethod=0 +r.MSAACount=4 +r.DefaultFeature.LightUnits=1 +r.DefaultBackBufferPixelFormat=4 +r.ScreenPercentage.Default=100.000000 +r.ScreenPercentage.Default.Desktop.Mode=1 +r.ScreenPercentage.Default.Mobile.Mode=0 +r.ScreenPercentage.Default.VR.Mode=0 +r.ScreenPercentage.Default.PathTracer.Mode=0 +r.Shadow.UnbuiltPreviewInGame=True +r.StencilForLODDither=False +r.EarlyZPass=3 +r.EarlyZPassOnlyMaterialMasking=False +r.Shadow.CSMCaching=False +r.DBuffer=True +r.ClearSceneMethod=1 +r.VelocityOutputPass=0 +r.Velocity.EnableVertexDeformation=2 +r.SelectiveBasePassOutputs=False +bDefaultParticleCutouts=False +fx.GPUSimulationTextureSizeX=1024 +fx.GPUSimulationTextureSizeY=1024 +r.AllowGlobalClipPlane=False +r.GBufferFormat=1 +r.MorphTarget.Mode=True +r.GPUCrashDebugging=False +vr.InstancedStereo=False +r.MobileHDR=True +vr.MobileMultiView=False +r.Mobile.UseHWsRGBEncoding=False +vr.RoundRobinOcclusion=False +r.MeshStreaming=False +r.HeterogeneousVolumes=True +r.WireframeCullThreshold=5.000000 +r.SupportStationarySkylight=True +r.SupportLowQualityLightmaps=True +r.SupportPointLightWholeSceneShadows=True +r.SupportSkyAtmosphere=True +r.SupportSkyAtmosphereAffectsHeightFog=True +r.SupportCloudShadowOnForwardLitTranslucent=False +r.Shadow.TranslucentPerObject.ProjectEnabled=False +r.Water.SingleLayerWater.SupportCloudShadow=False +r.Substrate=False +r.Substrate.OpaqueMaterialRoughRefraction=False +r.Substrate.Debug.AdvancedVisualizationShaders=False +r.Material.RoughDiffuse=False +r.Material.EnergyConservation=False +r.OIT.SortedPixels=False +r.SkinCache.CompileShaders=False +r.SkinCache.SkipCompilingGPUSkinVF=False +r.SkinCache.DefaultBehavior=1 +r.SkinCache.SceneMemoryLimitInMB=128.000000 +r.Mobile.EnableStaticAndCSMShadowReceivers=True +r.Mobile.EnableMovableLightCSMShaderCulling=True +r.Mobile.Forward.EnableLocalLights=True +r.Mobile.Forward.EnableClusteredReflections=False +r.Mobile.EnableNoPrecomputedLightingCSMShader=False +r.Mobile.AllowDistanceFieldShadows=True +r.Mobile.AllowMovableDirectionalLights=True +r.Mobile.EnableMovableSpotlightsShadow=False +r.GPUSkin.Support16BitBoneIndex=False +r.GPUSkin.Limit2BoneInfluences=False +r.SupportDepthOnlyIndexBuffers=True +r.SupportReversedIndexBuffers=True +r.Mobile.AmbientOcclusion=False +r.GPUSkin.UnlimitedBoneInfluences=False +r.GPUSkin.UnlimitedBoneInfluencesThreshold=8 +DefaultBoneInfluenceLimit=(Default=0,PerPlatform=()) +MaxSkinBones=(Default=65536,PerPlatform=(("Mobile", 256))) +r.Mobile.PlanarReflectionMode=0 +r.Mobile.SupportsGen4TAA=True +bStreamSkeletalMeshLODs=(Default=False,PerPlatform=()) +bDiscardSkeletalMeshOptionalLODs=(Default=False,PerPlatform=()) +VisualizeCalibrationColorMaterialPath=/Engine/EngineMaterials/PPM_DefaultCalibrationColor.PPM_DefaultCalibrationColor +VisualizeCalibrationCustomMaterialPath=None +VisualizeCalibrationGrayscaleMaterialPath=/Engine/EngineMaterials/PPM_DefaultCalibrationGrayscale.PPM_DefaultCalibrationGrayscale + +[/Script/WorldPartitionEditor.WorldPartitionEditorSettings] +CommandletClass=Class'/Script/UnrealEd.WorldPartitionConvertCommandlet' + +[/Script/Engine.UserInterfaceSettings] +bAuthorizeAutomaticWidgetVariableCreation=False +FontDPIPreset=Standard +FontDPI=72 + +[/Script/Engine.Engine] ++ActiveGameNameRedirects=(OldGameName="TP_Blank",NewGameName="/Script/AndroidCesiumTest") ++ActiveGameNameRedirects=(OldGameName="/Script/TP_Blank",NewGameName="/Script/AndroidCesiumTest") + +[/Script/Slate.SlateSettings] +bExplicitCanvasChildZOrder=True + +[/Script/Engine.PhysicsSettings] ++DefaultChannelResponses=(Channel=ECC_GameTraceChannel1, DefaultResponse=ECR_Block) ++DefaultChannelResponses=(Channel=ECC_GameTraceChannel2, DefaultResponse=ECR_Overlap) + +[/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings] +bEnablePlugin=True +bAllowNetworkConnection=True +SecurityToken=0E04F4DF4E61A956B7901CB14DF888E4 +bIncludeInShipping=False +bAllowExternalStartInShipping=False +bCompileAFSProject=False +bUseCompression=False +bLogFiles=False +bReportStats=False +ConnectionType=USBOnly +bUseManualIPAddress=False +ManualIPAddress= + +[/Script/Engine.CollisionProfile] +-Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision",bCanModify=False) +-Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +-Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +-Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldDynamic",CustomResponses=,HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +-Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +-Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ",bCanModify=False) +-Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ",bCanModify=False) +-Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic",Response=ECR_Block),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.",bCanModify=False) +-Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors",bCanModify=False) +-Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors",bCanModify=False) +-Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.",bCanModify=False) +-Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.",bCanModify=False) +-Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="UI",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Block),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) ++Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision") ++Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=,HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.") ++Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ") ++Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ") ++Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic"),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.") ++Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.") ++Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors") ++Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors") ++Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.") ++Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.") ++Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.") ++Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.") ++Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.") ++Profiles=(Name="UI",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="WaterBodyCollision",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="",CustomResponses=((Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="Default Water Collision Profile (Created by Water Plugin)") ++DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Move") +-ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall") +-ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn") +-ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic") +-ProfileRedirects=(OldName="SkeletalMeshActor",NewName="PhysicsActor") +-ProfileRedirects=(OldName="InvisibleActor",NewName="InvisibleWallDynamic") ++ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall") ++ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn") ++ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic") ++ProfileRedirects=(OldName="SkeletalMeshActor",NewName="PhysicsActor") ++ProfileRedirects=(OldName="InvisibleActor",NewName="InvisibleWallDynamic") +-CollisionChannelRedirects=(OldName="Static",NewName="WorldStatic") +-CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic") +-CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle") +-CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn") ++CollisionChannelRedirects=(OldName="Static",NewName="WorldStatic") ++CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic") ++CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle") ++CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn") + +[/Script/AndroidRuntimeSettings.AndroidRuntimeSettings] +bPackageDataInsideApk=True + +[CoreRedirects] ++ClassRedirects=(OldName="/Script/AndroidCesiumTest, NewName="/Script/BXSSP") \ No newline at end of file diff --git a/Config/DefaultGame.ini b/Config/DefaultGame.ini new file mode 100644 index 0000000..fa8e1e9 --- /dev/null +++ b/Config/DefaultGame.ini @@ -0,0 +1,3 @@ + +[/Script/EngineSettings.GeneralProjectSettings] +ProjectID=197B06B848D00120F369D2988D0C3E6B diff --git a/Config/DefaultInput.ini b/Config/DefaultInput.ini new file mode 100644 index 0000000..f81c3fc --- /dev/null +++ b/Config/DefaultInput.ini @@ -0,0 +1,85 @@ +[/Script/Engine.InputSettings] +-AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) +-AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) +-AxisConfig=(AxisKeyName="Mouse2D",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) ++AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Mouse2D",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MouseWheelAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_LeftTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_RightTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_Special_Left_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Gamepad_Special_Left_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) +bAltEnterTogglesFullscreen=True +bF11TogglesFullscreen=True +bUseMouseForTouch=True +bEnableMouseSmoothing=True +bEnableFOVScaling=True +bCaptureMouseOnLaunch=True +bEnableLegacyInputScales=True +bEnableMotionControls=True +bFilterInputByPlatformUser=False +bShouldFlushPressedKeysOnViewportFocusLost=True +bAlwaysShowTouchInterface=False +bShowConsoleOnFourFingerTap=True +bEnableGestureRecognizer=False +bUseAutocorrect=False +DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown +DefaultViewportMouseLockMode=LockOnCapture +FOVScale=0.011110 +DoubleClickTime=0.200000 +DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput +DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent +DefaultTouchInterface=None +-ConsoleKeys=Tilde ++ConsoleKeys=Tilde ++ConsoleKeys=Caret + diff --git a/Content/CesiumSettings/CesiumIonServers/CesiumIonSaaS.uasset b/Content/CesiumSettings/CesiumIonServers/CesiumIonSaaS.uasset new file mode 100644 index 0000000..f1b0541 Binary files /dev/null and b/Content/CesiumSettings/CesiumIonServers/CesiumIonSaaS.uasset differ diff --git a/Content/Game/BP/BP_AssistMoveLeftMoveActor.uasset b/Content/Game/BP/BP_AssistMoveLeftMoveActor.uasset new file mode 100644 index 0000000..24079e8 Binary files /dev/null and b/Content/Game/BP/BP_AssistMoveLeftMoveActor.uasset differ diff --git a/Content/Game/BP/BP_MainHUDN.uasset b/Content/Game/BP/BP_MainHUDN.uasset new file mode 100644 index 0000000..a5fe441 Binary files /dev/null and b/Content/Game/BP/BP_MainHUDN.uasset differ diff --git a/Content/Game/BP/BP_RoverControllerN.uasset b/Content/Game/BP/BP_RoverControllerN.uasset new file mode 100644 index 0000000..6e4b5d3 Binary files /dev/null and b/Content/Game/BP/BP_RoverControllerN.uasset differ diff --git a/Content/Game/BP/BP_RoverGamemodeN.uasset b/Content/Game/BP/BP_RoverGamemodeN.uasset new file mode 100644 index 0000000..f9e6e39 Binary files /dev/null and b/Content/Game/BP/BP_RoverGamemodeN.uasset differ diff --git a/Content/Game/BP/BP_RoverN.uasset b/Content/Game/BP/BP_RoverN.uasset new file mode 100644 index 0000000..d8619b6 Binary files /dev/null and b/Content/Game/BP/BP_RoverN.uasset differ diff --git a/Content/Game/Input/BaseMoveInput.uasset b/Content/Game/Input/BaseMoveInput.uasset new file mode 100644 index 0000000..bad48d1 Binary files /dev/null and b/Content/Game/Input/BaseMoveInput.uasset differ diff --git a/Content/Game/Input/GamePadLookUp.uasset b/Content/Game/Input/GamePadLookUp.uasset new file mode 100644 index 0000000..af74db6 Binary files /dev/null and b/Content/Game/Input/GamePadLookUp.uasset differ diff --git a/Content/Game/Input/GamePadTurn.uasset b/Content/Game/Input/GamePadTurn.uasset new file mode 100644 index 0000000..fc1afcf Binary files /dev/null and b/Content/Game/Input/GamePadTurn.uasset differ diff --git a/Content/Game/Input/LookUp.uasset b/Content/Game/Input/LookUp.uasset new file mode 100644 index 0000000..08d515c Binary files /dev/null and b/Content/Game/Input/LookUp.uasset differ diff --git a/Content/Game/Input/MouseLeftKey.uasset b/Content/Game/Input/MouseLeftKey.uasset new file mode 100644 index 0000000..a9fe46c Binary files /dev/null and b/Content/Game/Input/MouseLeftKey.uasset differ diff --git a/Content/Game/Input/MouseMiddle.uasset b/Content/Game/Input/MouseMiddle.uasset new file mode 100644 index 0000000..480ab8f Binary files /dev/null and b/Content/Game/Input/MouseMiddle.uasset differ diff --git a/Content/Game/Input/MouseRightKey.uasset b/Content/Game/Input/MouseRightKey.uasset new file mode 100644 index 0000000..c716566 Binary files /dev/null and b/Content/Game/Input/MouseRightKey.uasset differ diff --git a/Content/Game/Input/MouseRoll.uasset b/Content/Game/Input/MouseRoll.uasset new file mode 100644 index 0000000..d5c250f Binary files /dev/null and b/Content/Game/Input/MouseRoll.uasset differ diff --git a/Content/Game/Input/MoveForward.uasset b/Content/Game/Input/MoveForward.uasset new file mode 100644 index 0000000..b791b78 Binary files /dev/null and b/Content/Game/Input/MoveForward.uasset differ diff --git a/Content/Game/Input/MoveRight.uasset b/Content/Game/Input/MoveRight.uasset new file mode 100644 index 0000000..ef27626 Binary files /dev/null and b/Content/Game/Input/MoveRight.uasset differ diff --git a/Content/Game/Input/TS_TwoTouch.uasset b/Content/Game/Input/TS_TwoTouch.uasset new file mode 100644 index 0000000..33a2c1b Binary files /dev/null and b/Content/Game/Input/TS_TwoTouch.uasset differ diff --git a/Content/Game/Input/ThroughWall.uasset b/Content/Game/Input/ThroughWall.uasset new file mode 100644 index 0000000..9458530 Binary files /dev/null and b/Content/Game/Input/ThroughWall.uasset differ diff --git a/Content/Game/Input/Turn.uasset b/Content/Game/Input/Turn.uasset new file mode 100644 index 0000000..2442ecb Binary files /dev/null and b/Content/Game/Input/Turn.uasset differ diff --git a/Content/Game/Maps/AndroidMap02.umap b/Content/Game/Maps/AndroidMap02.umap new file mode 100644 index 0000000..a9b7c6d Binary files /dev/null and b/Content/Game/Maps/AndroidMap02.umap differ diff --git a/Content/Game/UMG/WBP_MainUI.uasset b/Content/Game/UMG/WBP_MainUI.uasset new file mode 100644 index 0000000..428acb8 Binary files /dev/null and b/Content/Game/UMG/WBP_MainUI.uasset differ diff --git a/Content/MapBorderCollection/Blueprints/BP_Blocking_Border.uasset b/Content/MapBorderCollection/Blueprints/BP_Blocking_Border.uasset new file mode 100644 index 0000000..4cb74c5 Binary files /dev/null and b/Content/MapBorderCollection/Blueprints/BP_Blocking_Border.uasset differ diff --git a/Content/MapBorderCollection/Blueprints/BP_Decal_Border.uasset b/Content/MapBorderCollection/Blueprints/BP_Decal_Border.uasset new file mode 100644 index 0000000..7cc0d30 Binary files /dev/null and b/Content/MapBorderCollection/Blueprints/BP_Decal_Border.uasset differ diff --git a/Content/MapBorderCollection/Blueprints/BP_Mesh_Border.uasset b/Content/MapBorderCollection/Blueprints/BP_Mesh_Border.uasset new file mode 100644 index 0000000..93229ff Binary files /dev/null and b/Content/MapBorderCollection/Blueprints/BP_Mesh_Border.uasset differ diff --git a/Content/MapBorderCollection/Blueprints/BP_Sphere_Border.uasset b/Content/MapBorderCollection/Blueprints/BP_Sphere_Border.uasset new file mode 100644 index 0000000..a535788 Binary files /dev/null and b/Content/MapBorderCollection/Blueprints/BP_Sphere_Border.uasset differ diff --git a/Content/MapBorderCollection/Blueprints/BP_Spline_Blocking_Border.uasset b/Content/MapBorderCollection/Blueprints/BP_Spline_Blocking_Border.uasset new file mode 100644 index 0000000..023094f Binary files /dev/null and b/Content/MapBorderCollection/Blueprints/BP_Spline_Blocking_Border.uasset differ diff --git a/Content/MapBorderCollection/Blueprints/BP_Spline_Border.uasset b/Content/MapBorderCollection/Blueprints/BP_Spline_Border.uasset new file mode 100644 index 0000000..a0d4cd2 Binary files /dev/null and b/Content/MapBorderCollection/Blueprints/BP_Spline_Border.uasset differ diff --git a/Content/MapBorderCollection/Blueprints/BP_Spline_Decal_Border.uasset b/Content/MapBorderCollection/Blueprints/BP_Spline_Decal_Border.uasset new file mode 100644 index 0000000..af95ec2 Binary files /dev/null and b/Content/MapBorderCollection/Blueprints/BP_Spline_Decal_Border.uasset differ diff --git a/Content/MapBorderCollection/Materials/DecalBorder/M_Border_Decal_Corner.uasset b/Content/MapBorderCollection/Materials/DecalBorder/M_Border_Decal_Corner.uasset new file mode 100644 index 0000000..023578f Binary files /dev/null and b/Content/MapBorderCollection/Materials/DecalBorder/M_Border_Decal_Corner.uasset differ diff --git a/Content/MapBorderCollection/Materials/DecalBorder/M_Border_Decal_Line.uasset b/Content/MapBorderCollection/Materials/DecalBorder/M_Border_Decal_Line.uasset new file mode 100644 index 0000000..4567f1b Binary files /dev/null and b/Content/MapBorderCollection/Materials/DecalBorder/M_Border_Decal_Line.uasset differ diff --git a/Content/MapBorderCollection/Materials/DecalBorder/M_Border_Decal_Spline.uasset b/Content/MapBorderCollection/Materials/DecalBorder/M_Border_Decal_Spline.uasset new file mode 100644 index 0000000..db70cac Binary files /dev/null and b/Content/MapBorderCollection/Materials/DecalBorder/M_Border_Decal_Spline.uasset differ diff --git a/Content/MapBorderCollection/Materials/Gradients/CA_Gradients.uasset b/Content/MapBorderCollection/Materials/Gradients/CA_Gradients.uasset new file mode 100644 index 0000000..4fd7f26 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Gradients/CA_Gradients.uasset differ diff --git a/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_01.uasset b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_01.uasset new file mode 100644 index 0000000..6516699 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_01.uasset differ diff --git a/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_02.uasset b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_02.uasset new file mode 100644 index 0000000..4b9015c Binary files /dev/null and b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_02.uasset differ diff --git a/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_03.uasset b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_03.uasset new file mode 100644 index 0000000..24dd5c2 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_03.uasset differ diff --git a/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_04.uasset b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_04.uasset new file mode 100644 index 0000000..466b0d3 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_04.uasset differ diff --git a/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_05.uasset b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_05.uasset new file mode 100644 index 0000000..f3bf122 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_05.uasset differ diff --git a/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_06.uasset b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_06.uasset new file mode 100644 index 0000000..5104e45 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_06.uasset differ diff --git a/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_07.uasset b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_07.uasset new file mode 100644 index 0000000..366721c Binary files /dev/null and b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_07.uasset differ diff --git a/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_08.uasset b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_08.uasset new file mode 100644 index 0000000..1ae84e3 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_08.uasset differ diff --git a/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_09.uasset b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_09.uasset new file mode 100644 index 0000000..6e7a960 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Gradients/CC_Gradient_09.uasset differ diff --git a/Content/MapBorderCollection/Materials/M_Border_Anim.uasset b/Content/MapBorderCollection/Materials/M_Border_Anim.uasset new file mode 100644 index 0000000..8c8149e Binary files /dev/null and b/Content/MapBorderCollection/Materials/M_Border_Anim.uasset differ diff --git a/Content/MapBorderCollection/Materials/M_Border_Anim_B.uasset b/Content/MapBorderCollection/Materials/M_Border_Anim_B.uasset new file mode 100644 index 0000000..63ec272 Binary files /dev/null and b/Content/MapBorderCollection/Materials/M_Border_Anim_B.uasset differ diff --git a/Content/MapBorderCollection/Materials/M_Border_Anim_C.uasset b/Content/MapBorderCollection/Materials/M_Border_Anim_C.uasset new file mode 100644 index 0000000..77b7fed Binary files /dev/null and b/Content/MapBorderCollection/Materials/M_Border_Anim_C.uasset differ diff --git a/Content/MapBorderCollection/Materials/M_Border_Fog.uasset b/Content/MapBorderCollection/Materials/M_Border_Fog.uasset new file mode 100644 index 0000000..f232b85 Binary files /dev/null and b/Content/MapBorderCollection/Materials/M_Border_Fog.uasset differ diff --git a/Content/MapBorderCollection/Materials/M_Border_Fog_Decal_A.uasset b/Content/MapBorderCollection/Materials/M_Border_Fog_Decal_A.uasset new file mode 100644 index 0000000..97cd190 Binary files /dev/null and b/Content/MapBorderCollection/Materials/M_Border_Fog_Decal_A.uasset differ diff --git a/Content/MapBorderCollection/Materials/M_Border_Fog_Pattern_A.uasset b/Content/MapBorderCollection/Materials/M_Border_Fog_Pattern_A.uasset new file mode 100644 index 0000000..0b6415b Binary files /dev/null and b/Content/MapBorderCollection/Materials/M_Border_Fog_Pattern_A.uasset differ diff --git a/Content/MapBorderCollection/Materials/M_Border_Fog_Pattern_B.uasset b/Content/MapBorderCollection/Materials/M_Border_Fog_Pattern_B.uasset new file mode 100644 index 0000000..524bcfc Binary files /dev/null and b/Content/MapBorderCollection/Materials/M_Border_Fog_Pattern_B.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialFunctions/MF_CameraAndCursorFade.uasset b/Content/MapBorderCollection/Materials/MaterialFunctions/MF_CameraAndCursorFade.uasset new file mode 100644 index 0000000..c45e6b7 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialFunctions/MF_CameraAndCursorFade.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_01.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_01.uasset new file mode 100644 index 0000000..c988065 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_01.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_02.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_02.uasset new file mode 100644 index 0000000..58ef684 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_02.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_03.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_03.uasset new file mode 100644 index 0000000..31820ff Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_03.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_04.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_04.uasset new file mode 100644 index 0000000..455f5b4 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_04.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_05.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_05.uasset new file mode 100644 index 0000000..bf8cecf Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_05.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_06.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_06.uasset new file mode 100644 index 0000000..c3c7b23 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_06.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_07.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_07.uasset new file mode 100644 index 0000000..80d14bb Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_07.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_08.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_08.uasset new file mode 100644 index 0000000..aeace5d Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_08.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_09.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_09.uasset new file mode 100644 index 0000000..515049f Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_09.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_10.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_10.uasset new file mode 100644 index 0000000..666ddbd Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_10.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_11.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_11.uasset new file mode 100644 index 0000000..562fea9 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_11.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_12.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_12.uasset new file mode 100644 index 0000000..09accc9 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_12.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_13.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_13.uasset new file mode 100644 index 0000000..2b26bca Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_13.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_14.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_14.uasset new file mode 100644 index 0000000..7e40419 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_14.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_15.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_15.uasset new file mode 100644 index 0000000..79e6919 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_15.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_16.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_16.uasset new file mode 100644 index 0000000..2da7fab Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_16.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_17.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_17.uasset new file mode 100644 index 0000000..0825f6a Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_17.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_18.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_18.uasset new file mode 100644 index 0000000..cab3993 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_18.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_19.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_19.uasset new file mode 100644 index 0000000..a9a8389 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_19.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_20.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_20.uasset new file mode 100644 index 0000000..6ac427a Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_20.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_21.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_21.uasset new file mode 100644 index 0000000..3ec824f Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_21.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_22.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_22.uasset new file mode 100644 index 0000000..64a04c6 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_22.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_23.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_23.uasset new file mode 100644 index 0000000..8e91bb8 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_23.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_24.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_24.uasset new file mode 100644 index 0000000..bb99792 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_24.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_25.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_25.uasset new file mode 100644 index 0000000..ab3d310 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_25.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_26.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_26.uasset new file mode 100644 index 0000000..684b460 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_26.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_27.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_27.uasset new file mode 100644 index 0000000..ffdf1bf Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_27.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_28.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_28.uasset new file mode 100644 index 0000000..010db8a Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_28.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_29.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_29.uasset new file mode 100644 index 0000000..6a966ec Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_29.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_30.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_30.uasset new file mode 100644 index 0000000..f94d5ea Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_30.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_31.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_31.uasset new file mode 100644 index 0000000..574b064 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_31.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_32.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_32.uasset new file mode 100644 index 0000000..7c3c302 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_32.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_33.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_33.uasset new file mode 100644 index 0000000..667222b Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_33.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_34.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_34.uasset new file mode 100644 index 0000000..19241d8 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_34.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_35.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_35.uasset new file mode 100644 index 0000000..8bc2cc6 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_35.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_Black.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_Black.uasset new file mode 100644 index 0000000..2150457 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_Black.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_Gray.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_Gray.uasset new file mode 100644 index 0000000..2c84c21 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_Gray.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_White.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_White.uasset new file mode 100644 index 0000000..af922c7 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/MI_Fog_White.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_01.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_01.uasset new file mode 100644 index 0000000..1172a9b Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_01.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_02.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_02.uasset new file mode 100644 index 0000000..7b54906 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_02.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_03.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_03.uasset new file mode 100644 index 0000000..1adba1a Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_03.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_04.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_04.uasset new file mode 100644 index 0000000..484e64e Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_04.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_05.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_05.uasset new file mode 100644 index 0000000..518fc2e Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Decal_A_05.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_A_Stars.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_A_Stars.uasset new file mode 100644 index 0000000..1a26a80 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_A_Stars.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_01.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_01.uasset new file mode 100644 index 0000000..3d9d5f1 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_01.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_02.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_02.uasset new file mode 100644 index 0000000..72bf631 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_02.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_03.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_03.uasset new file mode 100644 index 0000000..b1dd47a Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_03.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_04.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_04.uasset new file mode 100644 index 0000000..cc85809 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_04.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_05.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_05.uasset new file mode 100644 index 0000000..306ec28 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_05.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_06.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_06.uasset new file mode 100644 index 0000000..d43d079 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Dots_06.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_01.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_01.uasset new file mode 100644 index 0000000..39acc18 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_01.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_02.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_02.uasset new file mode 100644 index 0000000..7c53839 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_02.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_03.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_03.uasset new file mode 100644 index 0000000..6b85eae Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_03.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_04.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_04.uasset new file mode 100644 index 0000000..8213f7a Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_04.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_05.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_05.uasset new file mode 100644 index 0000000..ff945cd Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_05.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_06.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_06.uasset new file mode 100644 index 0000000..0b06f87 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/Fog/M_Border_Fog_Pattern_B_Lines_06.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_01.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_01.uasset new file mode 100644 index 0000000..07bfd9c Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_01.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_02.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_02.uasset new file mode 100644 index 0000000..c29ef14 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_02.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_03.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_03.uasset new file mode 100644 index 0000000..111d69e Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_03.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_04.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_04.uasset new file mode 100644 index 0000000..c32ad0e Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_04.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_05.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_05.uasset new file mode 100644 index 0000000..dfbd1de Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_05.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_06.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_06.uasset new file mode 100644 index 0000000..d65c2b2 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_06.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_07.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_07.uasset new file mode 100644 index 0000000..0f0cc04 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_07.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_08.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_08.uasset new file mode 100644 index 0000000..9805bbf Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_08.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_09.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_09.uasset new file mode 100644 index 0000000..01ab7c7 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_09.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_10.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_10.uasset new file mode 100644 index 0000000..76ae9db Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_10.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_11.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_11.uasset new file mode 100644 index 0000000..b107640 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_11.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_12.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_12.uasset new file mode 100644 index 0000000..70dfb17 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_12.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_13.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_13.uasset new file mode 100644 index 0000000..777f56e Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_13.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_14.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_14.uasset new file mode 100644 index 0000000..7a5b6a9 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_14.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_15.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_15.uasset new file mode 100644 index 0000000..7e056b5 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_15.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_16.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_16.uasset new file mode 100644 index 0000000..588fd2f Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_16.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_17.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_17.uasset new file mode 100644 index 0000000..0fc0ff1 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_17.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_18.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_18.uasset new file mode 100644 index 0000000..67da5c6 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_18.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_19.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_19.uasset new file mode 100644 index 0000000..1cd6c80 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_19.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_20.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_20.uasset new file mode 100644 index 0000000..0894bb4 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_20.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_21.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_21.uasset new file mode 100644 index 0000000..0d6b240 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_21.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_22.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_22.uasset new file mode 100644 index 0000000..cac9fac Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_22.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_23.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_23.uasset new file mode 100644 index 0000000..4cb3158 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_23.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_24.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_24.uasset new file mode 100644 index 0000000..74bf048 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_24.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_25.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_25.uasset new file mode 100644 index 0000000..24b9fff Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_25.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_26.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_26.uasset new file mode 100644 index 0000000..a40ac2c Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_26.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_27.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_27.uasset new file mode 100644 index 0000000..55ed2bc Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_27.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_28.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_28.uasset new file mode 100644 index 0000000..0968679 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_28.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_29.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_29.uasset new file mode 100644 index 0000000..9f3a262 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_29.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_30.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_30.uasset new file mode 100644 index 0000000..a2d0e66 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_30.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_31.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_31.uasset new file mode 100644 index 0000000..e0b1a72 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_31.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_32.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_32.uasset new file mode 100644 index 0000000..5211169 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_32.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_33.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_33.uasset new file mode 100644 index 0000000..b7fe682 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_33.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_34.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_34.uasset new file mode 100644 index 0000000..46d68c0 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_34.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_35.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_35.uasset new file mode 100644 index 0000000..f327670 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_35.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_36.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_36.uasset new file mode 100644 index 0000000..eb686b8 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_36.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_37.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_37.uasset new file mode 100644 index 0000000..a81056c Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_37.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_38.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_38.uasset new file mode 100644 index 0000000..93932bc Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_38.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_39.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_39.uasset new file mode 100644 index 0000000..da2e846 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_39.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_40.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_40.uasset new file mode 100644 index 0000000..8ce1f95 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_40.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_41.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_41.uasset new file mode 100644 index 0000000..d6c802c Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/MI_Anim_41.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_01.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_01.uasset new file mode 100644 index 0000000..612bf64 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_01.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_02.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_02.uasset new file mode 100644 index 0000000..4d06bfa Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_02.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_03.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_03.uasset new file mode 100644 index 0000000..f545381 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_03.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_04.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_04.uasset new file mode 100644 index 0000000..1e7032a Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_04.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_05.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_05.uasset new file mode 100644 index 0000000..9d6023b Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_05.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_06.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_06.uasset new file mode 100644 index 0000000..c044fb7 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_06.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_07.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_07.uasset new file mode 100644 index 0000000..786ff6b Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_07.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_08.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_08.uasset new file mode 100644 index 0000000..21c0522 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_08.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_09.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_09.uasset new file mode 100644 index 0000000..10574ec Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_09.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_10.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_10.uasset new file mode 100644 index 0000000..cce16af Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_10.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_11.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_11.uasset new file mode 100644 index 0000000..8f48f97 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_11.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_12.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_12.uasset new file mode 100644 index 0000000..dd3242f Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_12.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_13.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_13.uasset new file mode 100644 index 0000000..4e24060 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_13.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_14.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_14.uasset new file mode 100644 index 0000000..4de1ada Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_14.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_15.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_15.uasset new file mode 100644 index 0000000..e37188e Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_15.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_16.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_16.uasset new file mode 100644 index 0000000..b79d927 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_16.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_17.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_17.uasset new file mode 100644 index 0000000..0ff95bf Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_17.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_18.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_18.uasset new file mode 100644 index 0000000..70d64b2 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_18.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_19.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_19.uasset new file mode 100644 index 0000000..5a960ab Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_19.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_20.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_20.uasset new file mode 100644 index 0000000..4255d51 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_20.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_21.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_21.uasset new file mode 100644 index 0000000..7bfd529 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_21.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_22.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_22.uasset new file mode 100644 index 0000000..e15fdcd Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_22.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_23.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_23.uasset new file mode 100644 index 0000000..dc0fd04 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_23.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_24.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_24.uasset new file mode 100644 index 0000000..c77be0e Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_24.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_25.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_25.uasset new file mode 100644 index 0000000..bb09104 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_25.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_26.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_26.uasset new file mode 100644 index 0000000..00d3e0c Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_26.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_27.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_27.uasset new file mode 100644 index 0000000..1c5a723 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_27.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_28.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_28.uasset new file mode 100644 index 0000000..66d269d Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_28.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_29.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_29.uasset new file mode 100644 index 0000000..f004c74 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_29.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_30.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_30.uasset new file mode 100644 index 0000000..2bdb015 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_30.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_31.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_31.uasset new file mode 100644 index 0000000..9ef4701 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_31.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_32.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_32.uasset new file mode 100644 index 0000000..594bb4d Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_B_32.uasset differ diff --git a/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_C_01.uasset b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_C_01.uasset new file mode 100644 index 0000000..e224216 Binary files /dev/null and b/Content/MapBorderCollection/Materials/MaterialsExamples/M_Border_Anim_C_01.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Border.uasset b/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Border.uasset new file mode 100644 index 0000000..519688d Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Border.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Border_Blocking.uasset b/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Border_Blocking.uasset new file mode 100644 index 0000000..d3a7df8 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Border_Blocking.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Border_Decal.uasset b/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Border_Decal.uasset new file mode 100644 index 0000000..89d6189 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Border_Decal.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Border_Spline.uasset b/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Border_Spline.uasset new file mode 100644 index 0000000..70e5aaa Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Border_Spline.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Sphere_Border.uasset b/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Sphere_Border.uasset new file mode 100644 index 0000000..d56f47a Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/Sprites/T_Icon_Sphere_Border.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Stars.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Stars.uasset new file mode 100644 index 0000000..93a73df Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Stars.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_01.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_01.uasset new file mode 100644 index 0000000..e21fc1c Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_01.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_02.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_02.uasset new file mode 100644 index 0000000..76860c2 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_02.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_03.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_03.uasset new file mode 100644 index 0000000..be6c559 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_03.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_04.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_04.uasset new file mode 100644 index 0000000..804a68b Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_04.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_05.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_05.uasset new file mode 100644 index 0000000..225b8e0 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_05.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_06.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_06.uasset new file mode 100644 index 0000000..ed4fc66 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_06.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_07.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_07.uasset new file mode 100644 index 0000000..a66e6f6 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_07.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_08.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_08.uasset new file mode 100644 index 0000000..1edc252 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_08.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_09.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_09.uasset new file mode 100644 index 0000000..37c4903 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_09.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_10.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_10.uasset new file mode 100644 index 0000000..2b9da95 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_10.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_11.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_11.uasset new file mode 100644 index 0000000..8337907 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_11.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_13.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_13.uasset new file mode 100644 index 0000000..7fc582b Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_13.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_14.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_14.uasset new file mode 100644 index 0000000..8404529 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_14.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_15.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_15.uasset new file mode 100644 index 0000000..eba2b60 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_15.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_16.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_16.uasset new file mode 100644 index 0000000..060b2c5 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_16.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_17.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_17.uasset new file mode 100644 index 0000000..e39a379 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_17.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_18.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_18.uasset new file mode 100644 index 0000000..67ab0bc Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_18.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_19.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_19.uasset new file mode 100644 index 0000000..656ed79 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_19.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_20.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_20.uasset new file mode 100644 index 0000000..82ca1e1 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_20.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_21.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_21.uasset new file mode 100644 index 0000000..1ea0084 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_21.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_22.uasset b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_22.uasset new file mode 100644 index 0000000..6d7b6f5 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Border_Tile_22.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_Debug_Grid.uasset b/Content/MapBorderCollection/Materials/Textures/T_Debug_Grid.uasset new file mode 100644 index 0000000..d4e6d83 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_Debug_Grid.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_23.uasset b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_23.uasset new file mode 100644 index 0000000..c07fdfa Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_23.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_24.uasset b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_24.uasset new file mode 100644 index 0000000..9f3c538 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_24.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_25.uasset b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_25.uasset new file mode 100644 index 0000000..8a332cb Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_25.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_26.uasset b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_26.uasset new file mode 100644 index 0000000..96a4844 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_26.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_27.uasset b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_27.uasset new file mode 100644 index 0000000..205ea4a Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_27.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_28.uasset b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_28.uasset new file mode 100644 index 0000000..6b129ba Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_28.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_29.uasset b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_29.uasset new file mode 100644 index 0000000..f10a161 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_29.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_30.uasset b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_30.uasset new file mode 100644 index 0000000..03ce27e Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_30.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_31.uasset b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_31.uasset new file mode 100644 index 0000000..2e0d53a Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_31.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_32.uasset b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_32.uasset new file mode 100644 index 0000000..b4bbdf4 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_LineTrace_Point_32.uasset differ diff --git a/Content/MapBorderCollection/Materials/Textures/T_White_Square.uasset b/Content/MapBorderCollection/Materials/Textures/T_White_Square.uasset new file mode 100644 index 0000000..9634cd6 Binary files /dev/null and b/Content/MapBorderCollection/Materials/Textures/T_White_Square.uasset differ diff --git a/Content/MapBorderCollection/Meshes/SM_Border_Corner.uasset b/Content/MapBorderCollection/Meshes/SM_Border_Corner.uasset new file mode 100644 index 0000000..af49872 Binary files /dev/null and b/Content/MapBorderCollection/Meshes/SM_Border_Corner.uasset differ diff --git a/Content/MapBorderCollection/Meshes/SM_Border_Plane.uasset b/Content/MapBorderCollection/Meshes/SM_Border_Plane.uasset new file mode 100644 index 0000000..db93baf Binary files /dev/null and b/Content/MapBorderCollection/Meshes/SM_Border_Plane.uasset differ diff --git a/Content/MapBorderCollection/Meshes/SM_Border_Round.uasset b/Content/MapBorderCollection/Meshes/SM_Border_Round.uasset new file mode 100644 index 0000000..4bcb0b4 Binary files /dev/null and b/Content/MapBorderCollection/Meshes/SM_Border_Round.uasset differ diff --git a/Content/MapBorderCollection/Meshes/SM_Sphere_Inverse.uasset b/Content/MapBorderCollection/Meshes/SM_Sphere_Inverse.uasset new file mode 100644 index 0000000..fb30656 Binary files /dev/null and b/Content/MapBorderCollection/Meshes/SM_Sphere_Inverse.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/BP_Demo_Spectator.uasset b/Content/MapBorderCollection/Overview/Blueprints/BP_Demo_Spectator.uasset new file mode 100644 index 0000000..d9387f1 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/BP_Demo_Spectator.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/GM_DemoGameMode.uasset b/Content/MapBorderCollection/Overview/Blueprints/GM_DemoGameMode.uasset new file mode 100644 index 0000000..be576c7 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/GM_DemoGameMode.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/Helper/BP_Helper.uasset b/Content/MapBorderCollection/Overview/Blueprints/Helper/BP_Helper.uasset new file mode 100644 index 0000000..994e918 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/Helper/BP_Helper.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/Helper/M_HelperDecal.uasset b/Content/MapBorderCollection/Overview/Blueprints/Helper/M_HelperDecal.uasset new file mode 100644 index 0000000..af18e76 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/Helper/M_HelperDecal.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview.uasset new file mode 100644 index 0000000..b3a7138 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Blocking_Border.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Blocking_Border.uasset new file mode 100644 index 0000000..0a7bf03 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Blocking_Border.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Decal_Border.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Decal_Border.uasset new file mode 100644 index 0000000..2249135 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Decal_Border.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Fade.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Fade.uasset new file mode 100644 index 0000000..80c3879 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Fade.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Material_Parametrs.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Material_Parametrs.uasset new file mode 100644 index 0000000..f9c0d35 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Material_Parametrs.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Mesh_Border.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Mesh_Border.uasset new file mode 100644 index 0000000..530b1ff Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Mesh_Border.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Round_Borders.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Round_Borders.uasset new file mode 100644 index 0000000..f6fa09d Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Round_Borders.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Sphere_Border.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Sphere_Border.uasset new file mode 100644 index 0000000..49ab1da Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Sphere_Border.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Spline_Blocking_Border.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Spline_Blocking_Border.uasset new file mode 100644 index 0000000..fb23449 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Spline_Blocking_Border.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Spline_Border.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Spline_Border.uasset new file mode 100644 index 0000000..6328b26 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Spline_Border.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Spline_Decal_Border.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Spline_Decal_Border.uasset new file mode 100644 index 0000000..6de5536 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Spline_Decal_Border.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Swap_Material.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Swap_Material.uasset new file mode 100644 index 0000000..c07034c Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/BP_Overview_Swap_Material.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/T_Icon_Border_Tutorial.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/T_Icon_Border_Tutorial.uasset new file mode 100644 index 0000000..0bf2cef Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/T_Icon_Border_Tutorial.uasset differ diff --git a/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/WB_Demo_UI.uasset b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/WB_Demo_UI.uasset new file mode 100644 index 0000000..2429645 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Blueprints/OverviewBlueprints/WB_Demo_UI.uasset differ diff --git a/Content/MapBorderCollection/Overview/Maps/Overview.umap b/Content/MapBorderCollection/Overview/Maps/Overview.umap new file mode 100644 index 0000000..9d054f5 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Maps/Overview.umap differ diff --git a/Content/MapBorderCollection/Overview/Maps/Scene/MI_Grid_01.uasset b/Content/MapBorderCollection/Overview/Maps/Scene/MI_Grid_01.uasset new file mode 100644 index 0000000..c95e020 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Maps/Scene/MI_Grid_01.uasset differ diff --git a/Content/MapBorderCollection/Overview/Maps/Scene/M_3Planar_Scale_Grid.uasset b/Content/MapBorderCollection/Overview/Maps/Scene/M_3Planar_Scale_Grid.uasset new file mode 100644 index 0000000..b8f31b9 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Maps/Scene/M_3Planar_Scale_Grid.uasset differ diff --git a/Content/MapBorderCollection/Overview/Maps/Scene/SM_Box_100x100.uasset b/Content/MapBorderCollection/Overview/Maps/Scene/SM_Box_100x100.uasset new file mode 100644 index 0000000..a008559 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Maps/Scene/SM_Box_100x100.uasset differ diff --git a/Content/MapBorderCollection/Overview/Maps/Scene/SM_Char_Run.uasset b/Content/MapBorderCollection/Overview/Maps/Scene/SM_Char_Run.uasset new file mode 100644 index 0000000..a753ab9 Binary files /dev/null and b/Content/MapBorderCollection/Overview/Maps/Scene/SM_Char_Run.uasset differ diff --git a/Content/ToolFunction/00Components/ToolFunctionComponent.uasset b/Content/ToolFunction/00Components/ToolFunctionComponent.uasset new file mode 100644 index 0000000..ae2e7c7 Binary files /dev/null and b/Content/ToolFunction/00Components/ToolFunctionComponent.uasset differ diff --git a/Content/ToolFunction/01Actors/BP_MarkActor.uasset b/Content/ToolFunction/01Actors/BP_MarkActor.uasset new file mode 100644 index 0000000..41a4adf Binary files /dev/null and b/Content/ToolFunction/01Actors/BP_MarkActor.uasset differ diff --git a/Content/ToolFunction/01Actors/BP_MarkLine.uasset b/Content/ToolFunction/01Actors/BP_MarkLine.uasset new file mode 100644 index 0000000..18ed644 Binary files /dev/null and b/Content/ToolFunction/01Actors/BP_MarkLine.uasset differ diff --git a/Content/ToolFunction/01Actors/BP_MarkLineDecal.uasset b/Content/ToolFunction/01Actors/BP_MarkLineDecal.uasset new file mode 100644 index 0000000..5df38ca Binary files /dev/null and b/Content/ToolFunction/01Actors/BP_MarkLineDecal.uasset differ diff --git a/Content/ToolFunction/01Actors/BP_MarkPoint.uasset b/Content/ToolFunction/01Actors/BP_MarkPoint.uasset new file mode 100644 index 0000000..db05b44 Binary files /dev/null and b/Content/ToolFunction/01Actors/BP_MarkPoint.uasset differ diff --git a/Content/ToolFunction/01Actors/BP_MarkPolygon.uasset b/Content/ToolFunction/01Actors/BP_MarkPolygon.uasset new file mode 100644 index 0000000..d4473f5 Binary files /dev/null and b/Content/ToolFunction/01Actors/BP_MarkPolygon.uasset differ diff --git a/Content/ToolFunction/01Actors/BP_MarkPolygonDecal.uasset b/Content/ToolFunction/01Actors/BP_MarkPolygonDecal.uasset new file mode 100644 index 0000000..717e00d Binary files /dev/null and b/Content/ToolFunction/01Actors/BP_MarkPolygonDecal.uasset differ diff --git a/Content/ToolFunction/01Actors/BP_Spline_Decal_Border_Child.uasset b/Content/ToolFunction/01Actors/BP_Spline_Decal_Border_Child.uasset new file mode 100644 index 0000000..ee48574 Binary files /dev/null and b/Content/ToolFunction/01Actors/BP_Spline_Decal_Border_Child.uasset differ diff --git a/Content/ToolFunction/01Actors/SceneCapture/Polygon/BP_PolygonCapture.uasset b/Content/ToolFunction/01Actors/SceneCapture/Polygon/BP_PolygonCapture.uasset new file mode 100644 index 0000000..676e7bf Binary files /dev/null and b/Content/ToolFunction/01Actors/SceneCapture/Polygon/BP_PolygonCapture.uasset differ diff --git a/Content/ToolFunction/02UMG/SceneWidget/WIdget_MarkPoint.uasset b/Content/ToolFunction/02UMG/SceneWidget/WIdget_MarkPoint.uasset new file mode 100644 index 0000000..0dfbabc Binary files /dev/null and b/Content/ToolFunction/02UMG/SceneWidget/WIdget_MarkPoint.uasset differ diff --git a/Content/ToolFunction/03Textures/02.uasset b/Content/ToolFunction/03Textures/02.uasset new file mode 100644 index 0000000..22ca222 Binary files /dev/null and b/Content/ToolFunction/03Textures/02.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Ellipse_1_3x.uasset b/Content/ToolFunction/03Textures/20240619/Ellipse_1_3x.uasset new file mode 100644 index 0000000..cbdf24b Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Ellipse_1_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/Danger-提示框背景.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/Danger-提示框背景.uasset new file mode 100644 index 0000000..7b6bd4b Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/Danger-提示框背景.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/Success-提示框背景.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/Success-提示框背景.uasset new file mode 100644 index 0000000..8d610a6 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/Success-提示框背景.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/Warning-提示框背景.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/Warning-提示框背景.uasset new file mode 100644 index 0000000..06c3fe8 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/Warning-提示框背景.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/error_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/error_4x.uasset new file mode 100644 index 0000000..635265a Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/error_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/info_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/info_4x.uasset new file mode 100644 index 0000000..d9e9d25 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/info_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/success_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/success_4x.uasset new file mode 100644 index 0000000..9066974 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/success_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/warring_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/warring_4x.uasset new file mode 100644 index 0000000..98addc2 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/warring_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/全屏_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/全屏_4x.uasset new file mode 100644 index 0000000..7760831 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/全屏_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/关机_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/关机_3x.uasset new file mode 100644 index 0000000..b52522d Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/关机_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/关闭_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/关闭_4x.uasset new file mode 100644 index 0000000..4056a40 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/关闭_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/剖面分析.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/剖面分析.uasset new file mode 100644 index 0000000..90836ef Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/剖面分析.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/可视域分析_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/可视域分析_4x.uasset new file mode 100644 index 0000000..d59b35e Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/可视域分析_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/土方分析_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/土方分析_4x.uasset new file mode 100644 index 0000000..016fefa Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/土方分析_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/坡度坡向_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/坡度坡向_4x.uasset new file mode 100644 index 0000000..1fec0b3 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/坡度坡向_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/天际线分析_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/天际线分析_3x.uasset new file mode 100644 index 0000000..b40435d Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/天际线分析_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/淹没分析_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/淹没分析_4x.uasset new file mode 100644 index 0000000..a8ab641 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/淹没分析_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/清除测量_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/清除测量_4x.uasset new file mode 100644 index 0000000..7172e67 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/清除测量_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/等高线_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/等高线_4x.uasset new file mode 100644 index 0000000..1a92bca Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/等高线_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/通视_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/通视_4x.uasset new file mode 100644 index 0000000..01903ac Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/分析/通视_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/删除_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/删除_4x.uasset new file mode 100644 index 0000000..640a9ca Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/删除_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/北斗_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/北斗_4x.uasset new file mode 100644 index 0000000..101696e Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/北斗_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/双箭头_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/双箭头_4x.uasset new file mode 100644 index 0000000..717a8ae Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/双箭头_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/圆_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/圆_4x.uasset new file mode 100644 index 0000000..e87027d Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/圆_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/天气02.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/天气02.uasset new file mode 100644 index 0000000..2777013 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/天气02.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/天气_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/天气_4x.uasset new file mode 100644 index 0000000..8d23cf6 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/天气_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/剖切.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/剖切.uasset new file mode 100644 index 0000000..59ddf72 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/剖切.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/圆形统计_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/圆形统计_3x.uasset new file mode 100644 index 0000000..b134a7b Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/圆形统计_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/地形开挖.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/地形开挖.uasset new file mode 100644 index 0000000..b4f30d7 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/地形开挖.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/坐标定位.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/坐标定位.uasset new file mode 100644 index 0000000..77e9f2d Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/坐标定位.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/多边形统计_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/多边形统计_3x.uasset new file mode 100644 index 0000000..fce7b88 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/多边形统计_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/工具icon_视频录制_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/工具icon_视频录制_3x.uasset new file mode 100644 index 0000000..32af190 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/工具icon_视频录制_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/度分秒转换.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/度分秒转换.uasset new file mode 100644 index 0000000..2e5dcc1 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/度分秒转换.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/投影转换_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/投影转换_3x.uasset new file mode 100644 index 0000000..afde170 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/投影转换_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/模型压平.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/模型压平.uasset new file mode 100644 index 0000000..9ae7131 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/模型压平.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/涂鸦.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/涂鸦.uasset new file mode 100644 index 0000000..6d48319 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/涂鸦.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/清除涂鸦.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/清除涂鸦.uasset new file mode 100644 index 0000000..f2ca72a Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/清除涂鸦.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/清除轨迹.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/清除轨迹.uasset new file mode 100644 index 0000000..2164fec Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/清除轨迹.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/照片定位.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/照片定位.uasset new file mode 100644 index 0000000..6d91d5f Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/照片定位.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/路径规划.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/路径规划.uasset new file mode 100644 index 0000000..a4360f2 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/路径规划.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游__4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游__4x.uasset new file mode 100644 index 0000000..7e453d1 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游__4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游小图标/圆角_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游小图标/圆角_3x.uasset new file mode 100644 index 0000000..52c1f2e Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游小图标/圆角_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游小图标/播放_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游小图标/播放_4x.uasset new file mode 100644 index 0000000..386a7fd Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游小图标/播放_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游小图标/直角_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游小图标/直角_3x.uasset new file mode 100644 index 0000000..ce2ffdd Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游小图标/直角_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游小图标/设置视角_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游小图标/设置视角_3x.uasset new file mode 100644 index 0000000..8f9da62 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/飞行漫游小图标/设置视角_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/高清出图.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/高清出图.uasset new file mode 100644 index 0000000..cbf1792 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/高清出图.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/高清截图_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/高清截图_4x.uasset new file mode 100644 index 0000000..c240fce Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/高清截图_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/鼠标定位.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/鼠标定位.uasset new file mode 100644 index 0000000..c89c83c Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/工具/鼠标定位.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/放大_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/放大_4x.uasset new file mode 100644 index 0000000..d05f717 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/放大_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/乡道_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/乡道_4x.uasset new file mode 100644 index 0000000..883242f Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/乡道_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/交警_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/交警_4x.uasset new file mode 100644 index 0000000..53beab9 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/交警_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/人民币.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/人民币.uasset new file mode 100644 index 0000000..37452d2 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/人民币.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/保安_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/保安_4x.uasset new file mode 100644 index 0000000..71124d8 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/保安_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/停车场_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/停车场_4x.uasset new file mode 100644 index 0000000..2cb6d53 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/停车场_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/充电桩_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/充电桩_4x.uasset new file mode 100644 index 0000000..377456b Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/充电桩_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/光伏板.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/光伏板.uasset new file mode 100644 index 0000000..a14cc52 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/光伏板.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/公交_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/公交_4x.uasset new file mode 100644 index 0000000..420a47e Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/公交_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/公共座椅_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/公共座椅_4x.uasset new file mode 100644 index 0000000..7725bcc Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/公共座椅_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/公园_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/公园_4x.uasset new file mode 100644 index 0000000..f790f96 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/公园_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/写字楼_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/写字楼_4x.uasset new file mode 100644 index 0000000..7f88ec1 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/写字楼_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/农民_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/农民_4x.uasset new file mode 100644 index 0000000..dcc8799 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/农民_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/冰雹_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/冰雹_4x.uasset new file mode 100644 index 0000000..196eafa Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/冰雹_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/加油机_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/加油机_4x.uasset new file mode 100644 index 0000000..86e54b6 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/加油机_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/化工制品工厂.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/化工制品工厂.uasset new file mode 100644 index 0000000..03cde92 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/化工制品工厂.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/医院_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/医院_4x.uasset new file mode 100644 index 0000000..068f344 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/医院_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/厕所_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/厕所_4x.uasset new file mode 100644 index 0000000..13c00ba Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/厕所_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/厨师_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/厨师_4x.uasset new file mode 100644 index 0000000..be34d5c Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/厨师_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/县道_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/县道_4x.uasset new file mode 100644 index 0000000..4a649ae Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/县道_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/咖啡店_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/咖啡店_4x.uasset new file mode 100644 index 0000000..f2d7353 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/咖啡店_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/国道_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/国道_4x.uasset new file mode 100644 index 0000000..bc3b968 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/国道_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/地裂缝_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/地裂缝_4x.uasset new file mode 100644 index 0000000..8bf4648 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/地裂缝_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/地铁站_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/地铁站_4x.uasset new file mode 100644 index 0000000..73a0bc9 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/地铁站_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/地震_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/地震_4x.uasset new file mode 100644 index 0000000..265294f Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/地震_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/地面塌陷_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/地面塌陷_4x.uasset new file mode 100644 index 0000000..bb1ad36 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/地面塌陷_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/大雾_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/大雾_4x.uasset new file mode 100644 index 0000000..0e810c9 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/大雾_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/女厕所_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/女厕所_4x.uasset new file mode 100644 index 0000000..f854658 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/女厕所_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/学校_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/学校_4x.uasset new file mode 100644 index 0000000..9353cd8 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/学校_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/寒潮_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/寒潮_4x.uasset new file mode 100644 index 0000000..43d37dc Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/寒潮_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/小区_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/小区_4x.uasset new file mode 100644 index 0000000..2727ddd Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/小区_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/工程员_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/工程员_4x.uasset new file mode 100644 index 0000000..8dad58c Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/工程员_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/干旱_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/干旱_4x.uasset new file mode 100644 index 0000000..e8e4a0f Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/干旱_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/快餐店_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/快餐店_4x.uasset new file mode 100644 index 0000000..f5dc3d6 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/快餐店_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/搏击_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/搏击_4x.uasset new file mode 100644 index 0000000..937c0a8 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/搏击_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/摄像头_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/摄像头_4x.uasset new file mode 100644 index 0000000..d9d349d Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/摄像头_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/摩托车_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/摩托车_4x.uasset new file mode 100644 index 0000000..3dc4ebc Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/摩托车_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/攀登_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/攀登_4x.uasset new file mode 100644 index 0000000..56df7f3 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/攀登_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/政府_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/政府_4x.uasset new file mode 100644 index 0000000..1c4fd68 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/政府_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/政府人员_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/政府人员_4x.uasset new file mode 100644 index 0000000..0564428 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/政府人员_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/救护车_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/救护车_3x.uasset new file mode 100644 index 0000000..e485c89 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/救护车_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/新能源汽车_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/新能源汽车_4x.uasset new file mode 100644 index 0000000..38f65c0 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/新能源汽车_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/方向通道_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/方向通道_4x.uasset new file mode 100644 index 0000000..cc98fa8 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/方向通道_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/无人机_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/无人机_4x.uasset new file mode 100644 index 0000000..13d7d25 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/无人机_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/日元.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/日元.uasset new file mode 100644 index 0000000..bd6c75e Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/日元.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/暴雨_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/暴雨_4x.uasset new file mode 100644 index 0000000..7e78e71 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/暴雨_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/服务区_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/服务区_4x.uasset new file mode 100644 index 0000000..ca60836 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/服务区_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/核能发电.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/核能发电.uasset new file mode 100644 index 0000000..671455f Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/核能发电.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/欧元.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/欧元.uasset new file mode 100644 index 0000000..c05cef7 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/欧元.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/水电站.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/水电站.uasset new file mode 100644 index 0000000..5da5788 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/水电站.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/汽车_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/汽车_4x.uasset new file mode 100644 index 0000000..93a0f69 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/汽车_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/汽车制造工厂.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/汽车制造工厂.uasset new file mode 100644 index 0000000..8e312f3 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/汽车制造工厂.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/法院_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/法院_4x.uasset new file mode 100644 index 0000000..f5b87f0 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/法院_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/泥石流_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/泥石流_4x.uasset new file mode 100644 index 0000000..465afda Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/泥石流_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意信号灯_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意信号灯_4x.uasset new file mode 100644 index 0000000..54011cd Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意信号灯_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意儿童_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意儿童_4x.uasset new file mode 100644 index 0000000..83577d3 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意儿童_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意横风_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意横风_4x.uasset new file mode 100644 index 0000000..c741518 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意横风_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意牲畜_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意牲畜_4x.uasset new file mode 100644 index 0000000..02572b6 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意牲畜_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意落水_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意落水_4x.uasset new file mode 100644 index 0000000..a961816 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/注意落水_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/洪涝_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/洪涝_4x.uasset new file mode 100644 index 0000000..9d1b370 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/洪涝_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/海军_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/海军_4x.uasset new file mode 100644 index 0000000..1ddc9aa Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/海军_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/海啸__4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/海啸__4x.uasset new file mode 100644 index 0000000..30dfcbb Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/海啸__4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/消防栓_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/消防栓_4x.uasset new file mode 100644 index 0000000..02142d0 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/消防栓_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/消防站_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/消防站_4x.uasset new file mode 100644 index 0000000..bd2275b Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/消防站_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/消防车_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/消防车_4x.uasset new file mode 100644 index 0000000..168ed44 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/消防车_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/游泳_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/游泳_4x.uasset new file mode 100644 index 0000000..ff451d5 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/游泳_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/滑坡_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/滑坡_4x.uasset new file mode 100644 index 0000000..c235f82 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/滑坡_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/滑雪_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/滑雪_4x.uasset new file mode 100644 index 0000000..f1856ee Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/滑雪_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/潮汐通道_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/潮汐通道_4x.uasset new file mode 100644 index 0000000..fa4459f Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/潮汐通道_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/火力发电站.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/火力发电站.uasset new file mode 100644 index 0000000..2e3ad3b Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/火力发电站.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/火山_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/火山_4x.uasset new file mode 100644 index 0000000..388dc53 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/火山_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/灭火器_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/灭火器_4x.uasset new file mode 100644 index 0000000..624b32a Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/灭火器_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/特警_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/特警_4x.uasset new file mode 100644 index 0000000..64d3f45 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/特警_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/电动车_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/电动车_4x.uasset new file mode 100644 index 0000000..813df95 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/电动车_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/电塔.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/电塔.uasset new file mode 100644 index 0000000..5174741 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/电塔.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/电子制造工厂.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/电子制造工厂.uasset new file mode 100644 index 0000000..3885b56 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/电子制造工厂.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/电线.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/电线.uasset new file mode 100644 index 0000000..6592ec9 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/电线.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/男厕所_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/男厕所_4x.uasset new file mode 100644 index 0000000..aeffcbe Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/男厕所_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/直升机_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/直升机_4x.uasset new file mode 100644 index 0000000..6b63037 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/直升机_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/省道_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/省道_4x.uasset new file mode 100644 index 0000000..231e9b8 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/省道_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止右转_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止右转_4x.uasset new file mode 100644 index 0000000..4178c13 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止右转_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止左转_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止左转_4x.uasset new file mode 100644 index 0000000..d9e8481 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止左转_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止掉头_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止掉头_4x.uasset new file mode 100644 index 0000000..43c7886 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止掉头_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止直行与右转_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止直行与右转_4x.uasset new file mode 100644 index 0000000..7d1d592 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止直行与右转_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止融合_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止融合_4x.uasset new file mode 100644 index 0000000..71f1364 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止融合_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止超车_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止超车_4x.uasset new file mode 100644 index 0000000..3fcac38 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止超车_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止载人_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止载人_4x.uasset new file mode 100644 index 0000000..e782d2f Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止载人_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止通行_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止通行_4x.uasset new file mode 100644 index 0000000..d8b8b20 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止通行_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止驶入_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止驶入_4x.uasset new file mode 100644 index 0000000..acc94a5 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/禁止驶入_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/空军_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/空军_4x.uasset new file mode 100644 index 0000000..3eefeb8 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/空军_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/篮球场_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/篮球场_4x.uasset new file mode 100644 index 0000000..8c949e5 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/篮球场_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/纺织工厂.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/纺织工厂.uasset new file mode 100644 index 0000000..bc4019a Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/纺织工厂.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/缆车_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/缆车_4x.uasset new file mode 100644 index 0000000..5e6f212 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/缆车_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/美元.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/美元.uasset new file mode 100644 index 0000000..596a4d1 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/美元.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/自行车_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/自行车_4x.uasset new file mode 100644 index 0000000..f7aa81a Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/自行车_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/航母_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/航母_4x.uasset new file mode 100644 index 0000000..aad877c Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/航母_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/船_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/船_4x.uasset new file mode 100644 index 0000000..126a065 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/船_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/警察_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/警察_4x.uasset new file mode 100644 index 0000000..fbdcee5 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/警察_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/警察局_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/警察局_4x.uasset new file mode 100644 index 0000000..7217dc4 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/警察局_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/警车_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/警车_4x.uasset new file mode 100644 index 0000000..8018bf6 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/警车_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/货车_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/货车_4x.uasset new file mode 100644 index 0000000..4c6cdff Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/货车_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/超市_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/超市_4x.uasset new file mode 100644 index 0000000..956f274 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/超市_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/道路变窄_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/道路变窄_4x.uasset new file mode 100644 index 0000000..b7a708d Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/道路变窄_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/酒店_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/酒店_4x.uasset new file mode 100644 index 0000000..cd143be Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/酒店_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/钓鱼_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/钓鱼_4x.uasset new file mode 100644 index 0000000..f551c67 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/钓鱼_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/银行_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/银行_4x.uasset new file mode 100644 index 0000000..f086da3 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/银行_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/霜冻_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/霜冻_4x.uasset new file mode 100644 index 0000000..a2f591a Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/霜冻_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/韩元.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/韩元.uasset new file mode 100644 index 0000000..6e0101c Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/韩元.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/风力发电.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/风力发电.uasset new file mode 100644 index 0000000..76e806d Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/风力发电.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/飞机场_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/飞机场_4x.uasset new file mode 100644 index 0000000..cc9dfd0 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/飞机场_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/飞机起飞_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/飞机起飞_4x.uasset new file mode 100644 index 0000000..2df8c79 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/飞机起飞_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/骑行_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/骑行_4x.uasset new file mode 100644 index 0000000..0dc8ff6 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/骑行_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/骑马_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/骑马_4x.uasset new file mode 100644 index 0000000..9bc9bf2 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/骑马_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/龙卷风_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/龙卷风_4x.uasset new file mode 100644 index 0000000..303c3fe Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/标注/龙卷风_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/正常-提示框背景.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/正常-提示框背景.uasset new file mode 100644 index 0000000..6392a1f Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/正常-提示框背景.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/三角测量.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/三角测量.uasset new file mode 100644 index 0000000..db14bee Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/三角测量.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/坐标测量.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/坐标测量.uasset new file mode 100644 index 0000000..8a3cfa6 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/坐标测量.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/夹角测量.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/夹角测量.uasset new file mode 100644 index 0000000..6a7cfa4 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/夹角测量.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/投影面积.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/投影面积.uasset new file mode 100644 index 0000000..46617da Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/投影面积.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/方位角.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/方位角.uasset new file mode 100644 index 0000000..4cf50b1 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/方位角.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/贴地距离.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/贴地距离.uasset new file mode 100644 index 0000000..a17b31e Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/贴地距离.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/高度测量.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/高度测量.uasset new file mode 100644 index 0000000..296dd1d Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/测量/高度测量.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/添加设备_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/添加设备_4x.uasset new file mode 100644 index 0000000..a2b9567 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/添加设备_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/点_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/点_4x.uasset new file mode 100644 index 0000000..19ef7d3 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/点_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/水_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/水_4x.uasset new file mode 100644 index 0000000..01e53c2 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/水_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/水面_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/水面_4x.uasset new file mode 100644 index 0000000..d60b042 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/水面_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/火焰_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/火焰_4x.uasset new file mode 100644 index 0000000..98fca58 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/火焰_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/烟雾_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/烟雾_4x.uasset new file mode 100644 index 0000000..c0f7837 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/烟雾_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/爆炸_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/爆炸_4x.uasset new file mode 100644 index 0000000..5423d26 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/爆炸_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/特效库icon_扩散火焰_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/特效库icon_扩散火焰_3x.uasset new file mode 100644 index 0000000..94489bd Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/特效库icon_扩散火焰_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/特效库icon_线性火焰_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/特效库icon_线性火焰_3x.uasset new file mode 100644 index 0000000..51306e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/特效库icon_线性火焰_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/特效库icon_面状火焰_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/特效库icon_面状火焰_3x.uasset new file mode 100644 index 0000000..31f69e9 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/特效库icon_面状火焰_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/电子围墙_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/电子围墙_4x.uasset new file mode 100644 index 0000000..b3b5cc8 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/电子围墙_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/轨迹运动_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/轨迹运动_4x.uasset new file mode 100644 index 0000000..8ab87e0 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/特效/轨迹运动_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/矩形_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/矩形_3x.uasset new file mode 100644 index 0000000..6bd6120 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/矩形_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/立体文字_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/立体文字_4x.uasset new file mode 100644 index 0000000..08fcd65 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/立体文字_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/箭头_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/箭头_4x.uasset new file mode 100644 index 0000000..b5edae5 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/箭头_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/系统设置_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/系统设置_4x.uasset new file mode 100644 index 0000000..c0e4e15 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/系统设置_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/线_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/线_4x.uasset new file mode 100644 index 0000000..086cc29 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/线_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/vector02_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/vector02_3x.uasset new file mode 100644 index 0000000..1df1ad5 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/vector02_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/vector_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/vector_3x.uasset new file mode 100644 index 0000000..f28fd28 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/vector_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/三角形_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/三角形_3x.uasset new file mode 100644 index 0000000..a23b1c3 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/三角形_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/减去顶层_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/减去顶层_3x.uasset new file mode 100644 index 0000000..ee93ec7 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/减去顶层_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/微信截图_20240620183906.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/微信截图_20240620183906.uasset new file mode 100644 index 0000000..8007f66 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/微信截图_20240620183906.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/拼合图形_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/拼合图形_3x.uasset new file mode 100644 index 0000000..3f32579 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/拼合图形_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/矩形_11_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/矩形_11_3x.uasset new file mode 100644 index 0000000..19e7feb Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/矩形_11_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/矩形_18_2x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/矩形_18_2x.uasset new file mode 100644 index 0000000..dfa0819 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/矩形_18_2x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/矩形_8_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/矩形_8_3x.uasset new file mode 100644 index 0000000..42eac09 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/矩形_8_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/背景虚化.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/背景虚化.uasset new file mode 100644 index 0000000..687a3b3 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/背景虚化.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/设置导航菜单.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/设置导航菜单.uasset new file mode 100644 index 0000000..0ae4ed7 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/设置导航菜单.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/路径_32_2x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/路径_32_2x.uasset new file mode 100644 index 0000000..55f77e8 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/细节面板/路径_32_2x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/编辑_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/编辑_4x.uasset new file mode 100644 index 0000000..2d56c20 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/编辑_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/贴地文字_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/贴地文字_4x.uasset new file mode 100644 index 0000000..b4c736d Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/贴地文字_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/退出登录_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/退出登录_4x.uasset new file mode 100644 index 0000000..4233a8c Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/退出登录_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/重置_4x(2).uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/重置_4x(2).uasset new file mode 100644 index 0000000..281e143 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/重置_4x(2).uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/集结地_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/集结地_3x.uasset new file mode 100644 index 0000000..619b6a0 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/集结地_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleIcon/面_4x.uasset b/Content/ToolFunction/03Textures/20240619/LittleIcon/面_4x.uasset new file mode 100644 index 0000000..6269d04 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleIcon/面_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleMenu/jct_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleMenu/jct_3x.uasset new file mode 100644 index 0000000..6e75e0d Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleMenu/jct_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/LittleMenu/编辑节点_3x.uasset b/Content/ToolFunction/03Textures/20240619/LittleMenu/编辑节点_3x.uasset new file mode 100644 index 0000000..9566ee3 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/LittleMenu/编辑节点_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Mouse02.uasset b/Content/ToolFunction/03Textures/20240619/Mouse02.uasset new file mode 100644 index 0000000..df63744 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Mouse02.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/A-blu-blank.uasset b/Content/ToolFunction/03Textures/20240619/Point/A-blu-blank.uasset new file mode 100644 index 0000000..009939b Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/A-blu-blank.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/BottonArrow.uasset b/Content/ToolFunction/03Textures/20240619/Point/BottonArrow.uasset new file mode 100644 index 0000000..c1cd80b Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/BottonArrow.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/HeadFrame.uasset b/Content/ToolFunction/03Textures/20240619/Point/HeadFrame.uasset new file mode 100644 index 0000000..f3d1af8 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/HeadFrame.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/MiddleFrame.uasset b/Content/ToolFunction/03Textures/20240619/Point/MiddleFrame.uasset new file mode 100644 index 0000000..937066b Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/MiddleFrame.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/PointFrame.uasset b/Content/ToolFunction/03Textures/20240619/Point/PointFrame.uasset new file mode 100644 index 0000000..d9b3526 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/PointFrame.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/TailFrame.uasset b/Content/ToolFunction/03Textures/20240619/Point/TailFrame.uasset new file mode 100644 index 0000000..32529a6 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/TailFrame.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/中心.uasset b/Content/ToolFunction/03Textures/20240619/Point/中心.uasset new file mode 100644 index 0000000..08dbe58 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/中心.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/分组_37_3x.uasset b/Content/ToolFunction/03Textures/20240619/Point/分组_37_3x.uasset new file mode 100644 index 0000000..c05559b Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/分组_37_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/分组_4.uasset b/Content/ToolFunction/03Textures/20240619/Point/分组_4.uasset new file mode 100644 index 0000000..cd5b387 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/分组_4.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/分组_56_3x.uasset b/Content/ToolFunction/03Textures/20240619/Point/分组_56_3x.uasset new file mode 100644 index 0000000..9da8724 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/分组_56_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/微信图片_20250117142336.uasset b/Content/ToolFunction/03Textures/20240619/Point/微信图片_20250117142336.uasset new file mode 100644 index 0000000..96c5ce9 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/微信图片_20250117142336.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/微信图片_20250117142339.uasset b/Content/ToolFunction/03Textures/20240619/Point/微信图片_20250117142339.uasset new file mode 100644 index 0000000..4c65d4c Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/微信图片_20250117142339.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/标注icon_飞机起飞_3x.uasset b/Content/ToolFunction/03Textures/20240619/Point/标注icon_飞机起飞_3x.uasset new file mode 100644 index 0000000..6beb6af Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/标注icon_飞机起飞_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/Point/画板_1.uasset b/Content/ToolFunction/03Textures/20240619/Point/画板_1.uasset new file mode 100644 index 0000000..a5d4b8d Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/Point/画板_1.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/二三维.uasset b/Content/ToolFunction/03Textures/20240619/二三维.uasset new file mode 100644 index 0000000..7cd1b96 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/二三维.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/关闭卷帘_3x.uasset b/Content/ToolFunction/03Textures/20240619/关闭卷帘_3x.uasset new file mode 100644 index 0000000..4a501d9 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/关闭卷帘_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/军标.uasset b/Content/ToolFunction/03Textures/20240619/军标.uasset new file mode 100644 index 0000000..f753399 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/军标.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/军标_1_4x.uasset b/Content/ToolFunction/03Textures/20240619/军标_1_4x.uasset new file mode 100644 index 0000000..e013e79 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/军标_1_4x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/军标图片外框_3x.uasset b/Content/ToolFunction/03Textures/20240619/军标图片外框_3x.uasset new file mode 100644 index 0000000..1f90a5c Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/军标图片外框_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/分析.uasset b/Content/ToolFunction/03Textures/20240619/分析.uasset new file mode 100644 index 0000000..4d05f01 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/分析.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/分组_11_2x.uasset b/Content/ToolFunction/03Textures/20240619/分组_11_2x.uasset new file mode 100644 index 0000000..4082723 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/分组_11_2x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/分组_14.uasset b/Content/ToolFunction/03Textures/20240619/分组_14.uasset new file mode 100644 index 0000000..9286844 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/分组_14.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/分组_18_3x.uasset b/Content/ToolFunction/03Textures/20240619/分组_18_3x.uasset new file mode 100644 index 0000000..80e0eb5 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/分组_18_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/分组_1_2x.uasset b/Content/ToolFunction/03Textures/20240619/分组_1_2x.uasset new file mode 100644 index 0000000..d90cb57 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/分组_1_2x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/分组_2.uasset b/Content/ToolFunction/03Textures/20240619/分组_2.uasset new file mode 100644 index 0000000..5bb68b5 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/分组_2.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/分组_60.uasset b/Content/ToolFunction/03Textures/20240619/分组_60.uasset new file mode 100644 index 0000000..c210976 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/分组_60.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/双箭头.uasset b/Content/ToolFunction/03Textures/20240619/双箭头.uasset new file mode 100644 index 0000000..82e6162 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/双箭头.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/工具.uasset b/Content/ToolFunction/03Textures/20240619/工具.uasset new file mode 100644 index 0000000..0a3f410 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/工具.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/搜索索引_3x.uasset b/Content/ToolFunction/03Textures/20240619/搜索索引_3x.uasset new file mode 100644 index 0000000..2349370 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/搜索索引_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/收缩.uasset b/Content/ToolFunction/03Textures/20240619/收缩.uasset new file mode 100644 index 0000000..15fe554 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/收缩.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/无框全屏.uasset b/Content/ToolFunction/03Textures/20240619/无框全屏.uasset new file mode 100644 index 0000000..0765714 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/无框全屏.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/无框退出全屏.uasset b/Content/ToolFunction/03Textures/20240619/无框退出全屏.uasset new file mode 100644 index 0000000..cb16bc7 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/无框退出全屏.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/暂无数据_3x.uasset b/Content/ToolFunction/03Textures/20240619/暂无数据_3x.uasset new file mode 100644 index 0000000..34c0428 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/暂无数据_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/模型库.uasset b/Content/ToolFunction/03Textures/20240619/模型库.uasset new file mode 100644 index 0000000..9b1ae95 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/模型库.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/测量.uasset b/Content/ToolFunction/03Textures/20240619/测量.uasset new file mode 100644 index 0000000..4170de7 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/测量.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/添加图标.uasset b/Content/ToolFunction/03Textures/20240619/添加图标.uasset new file mode 100644 index 0000000..b3a14c4 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/添加图标.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/添加设备02_3x.uasset b/Content/ToolFunction/03Textures/20240619/添加设备02_3x.uasset new file mode 100644 index 0000000..0ce2be3 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/添加设备02_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/添加设备03_3x.uasset b/Content/ToolFunction/03Textures/20240619/添加设备03_3x.uasset new file mode 100644 index 0000000..bd6ae6e Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/添加设备03_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/添加设备_3x.uasset b/Content/ToolFunction/03Textures/20240619/添加设备_3x.uasset new file mode 100644 index 0000000..b8f1209 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/添加设备_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/点.uasset b/Content/ToolFunction/03Textures/20240619/点.uasset new file mode 100644 index 0000000..b8b20a5 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/点.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/特效库.uasset b/Content/ToolFunction/03Textures/20240619/特效库.uasset new file mode 100644 index 0000000..050be43 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/特效库.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/画板_1.uasset b/Content/ToolFunction/03Textures/20240619/画板_1.uasset new file mode 100644 index 0000000..2e31962 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/画板_1.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/矩形_19_2x.uasset b/Content/ToolFunction/03Textures/20240619/矩形_19_2x.uasset new file mode 100644 index 0000000..5e817ac Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/矩形_19_2x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/矩形_6_3x.uasset b/Content/ToolFunction/03Textures/20240619/矩形_6_3x.uasset new file mode 100644 index 0000000..d998158 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/矩形_6_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/箭头.uasset b/Content/ToolFunction/03Textures/20240619/箭头.uasset new file mode 100644 index 0000000..2bece4b Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/箭头.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/线.uasset b/Content/ToolFunction/03Textures/20240619/线.uasset new file mode 100644 index 0000000..08103ca Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/线.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/结束.uasset b/Content/ToolFunction/03Textures/20240619/结束.uasset new file mode 100644 index 0000000..c5b9eeb Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/结束.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/路径_1_3x.uasset b/Content/ToolFunction/03Textures/20240619/路径_1_3x.uasset new file mode 100644 index 0000000..bf02f59 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/路径_1_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/退出全屏_3x.uasset b/Content/ToolFunction/03Textures/20240619/退出全屏_3x.uasset new file mode 100644 index 0000000..344b717 Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/退出全屏_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/20240619/面.uasset b/Content/ToolFunction/03Textures/20240619/面.uasset new file mode 100644 index 0000000..97159fd Binary files /dev/null and b/Content/ToolFunction/03Textures/20240619/面.uasset differ diff --git a/Content/ToolFunction/03Textures/256.uasset b/Content/ToolFunction/03Textures/256.uasset new file mode 100644 index 0000000..efd8998 Binary files /dev/null and b/Content/ToolFunction/03Textures/256.uasset differ diff --git a/Content/ToolFunction/03Textures/300.uasset b/Content/ToolFunction/03Textures/300.uasset new file mode 100644 index 0000000..b2c4df7 Binary files /dev/null and b/Content/ToolFunction/03Textures/300.uasset differ diff --git a/Content/ToolFunction/03Textures/3DPanel/3DNormal_3x.uasset b/Content/ToolFunction/03Textures/3DPanel/3DNormal_3x.uasset new file mode 100644 index 0000000..8752d57 Binary files /dev/null and b/Content/ToolFunction/03Textures/3DPanel/3DNormal_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/3DPanel/3D_3x.uasset b/Content/ToolFunction/03Textures/3DPanel/3D_3x.uasset new file mode 100644 index 0000000..2986d22 Binary files /dev/null and b/Content/ToolFunction/03Textures/3DPanel/3D_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/3DPanel/Ellipse_1_3x.uasset b/Content/ToolFunction/03Textures/3DPanel/Ellipse_1_3x.uasset new file mode 100644 index 0000000..1e74e14 Binary files /dev/null and b/Content/ToolFunction/03Textures/3DPanel/Ellipse_1_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/72.uasset b/Content/ToolFunction/03Textures/72.uasset new file mode 100644 index 0000000..3724b91 Binary files /dev/null and b/Content/ToolFunction/03Textures/72.uasset differ diff --git a/Content/ToolFunction/03Textures/Circle.uasset b/Content/ToolFunction/03Textures/Circle.uasset new file mode 100644 index 0000000..e763913 Binary files /dev/null and b/Content/ToolFunction/03Textures/Circle.uasset differ diff --git a/Content/ToolFunction/03Textures/Destination.uasset b/Content/ToolFunction/03Textures/Destination.uasset new file mode 100644 index 0000000..7827b7a Binary files /dev/null and b/Content/ToolFunction/03Textures/Destination.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_Color.uasset b/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_Color.uasset new file mode 100644 index 0000000..3e1a726 Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_Color.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_Displacement.uasset b/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_Displacement.uasset new file mode 100644 index 0000000..5ce8414 Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_Displacement.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_NormalDX.uasset b/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_NormalDX.uasset new file mode 100644 index 0000000..990877b Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_NormalDX.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_NormalGL.uasset b/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_NormalGL.uasset new file mode 100644 index 0000000..aab3ba8 Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_NormalGL.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_Roughness.uasset b/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_Roughness.uasset new file mode 100644 index 0000000..2b2c725 Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/Wall/Bricks/Bricks054_2K-JPG_Roughness.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/Wall/Facade02/Facade006_2K-JPG_Color.uasset b/Content/ToolFunction/03Textures/Effect/Wall/Facade02/Facade006_2K-JPG_Color.uasset new file mode 100644 index 0000000..1b942ae Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/Wall/Facade02/Facade006_2K-JPG_Color.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/Wall/Facade02/Facade006_2K-JPG_Metalness.uasset b/Content/ToolFunction/03Textures/Effect/Wall/Facade02/Facade006_2K-JPG_Metalness.uasset new file mode 100644 index 0000000..2d2b8e6 Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/Wall/Facade02/Facade006_2K-JPG_Metalness.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/Wall/Facade02/Facade006_2K-JPG_Roughness.uasset b/Content/ToolFunction/03Textures/Effect/Wall/Facade02/Facade006_2K-JPG_Roughness.uasset new file mode 100644 index 0000000..b73b95d Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/Wall/Facade02/Facade006_2K-JPG_Roughness.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/Wall/保安亭.uasset b/Content/ToolFunction/03Textures/Effect/Wall/保安亭.uasset new file mode 100644 index 0000000..400cc4b Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/Wall/保安亭.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/Wall/保安亭MetalL.uasset b/Content/ToolFunction/03Textures/Effect/Wall/保安亭MetalL.uasset new file mode 100644 index 0000000..d2b130b Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/Wall/保安亭MetalL.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/卷帘影像.uasset b/Content/ToolFunction/03Textures/Effect/卷帘影像.uasset new file mode 100644 index 0000000..89076ab Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/卷帘影像.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/扩散光波.uasset b/Content/ToolFunction/03Textures/Effect/扩散光波.uasset new file mode 100644 index 0000000..a07a809 Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/扩散光波.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/水面.uasset b/Content/ToolFunction/03Textures/Effect/水面.uasset new file mode 100644 index 0000000..3dc7d11 Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/水面.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/火焰.uasset b/Content/ToolFunction/03Textures/Effect/火焰.uasset new file mode 100644 index 0000000..3f4b821 Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/火焰.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/电子围墙.uasset b/Content/ToolFunction/03Textures/Effect/电子围墙.uasset new file mode 100644 index 0000000..a60ec14 Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/电子围墙.uasset differ diff --git a/Content/ToolFunction/03Textures/Effect/轨迹运动.uasset b/Content/ToolFunction/03Textures/Effect/轨迹运动.uasset new file mode 100644 index 0000000..08dd41b Binary files /dev/null and b/Content/ToolFunction/03Textures/Effect/轨迹运动.uasset differ diff --git a/Content/ToolFunction/03Textures/Fire/弹坑.uasset b/Content/ToolFunction/03Textures/Fire/弹坑.uasset new file mode 100644 index 0000000..d54929e Binary files /dev/null and b/Content/ToolFunction/03Textures/Fire/弹坑.uasset differ diff --git a/Content/ToolFunction/03Textures/Fire/烧焦01.uasset b/Content/ToolFunction/03Textures/Fire/烧焦01.uasset new file mode 100644 index 0000000..7ae49fe Binary files /dev/null and b/Content/ToolFunction/03Textures/Fire/烧焦01.uasset differ diff --git a/Content/ToolFunction/03Textures/HDRI/20120900_19_797.uasset b/Content/ToolFunction/03Textures/HDRI/20120900_19_797.uasset new file mode 100644 index 0000000..a89165c Binary files /dev/null and b/Content/ToolFunction/03Textures/HDRI/20120900_19_797.uasset differ diff --git a/Content/ToolFunction/03Textures/HDRI/20120900_22_511.uasset b/Content/ToolFunction/03Textures/HDRI/20120900_22_511.uasset new file mode 100644 index 0000000..58aaa64 Binary files /dev/null and b/Content/ToolFunction/03Textures/HDRI/20120900_22_511.uasset differ diff --git a/Content/ToolFunction/03Textures/HDRI/20120900_23_369.uasset b/Content/ToolFunction/03Textures/HDRI/20120900_23_369.uasset new file mode 100644 index 0000000..cdf5f30 Binary files /dev/null and b/Content/ToolFunction/03Textures/HDRI/20120900_23_369.uasset differ diff --git a/Content/ToolFunction/03Textures/HoneyComb.uasset b/Content/ToolFunction/03Textures/HoneyComb.uasset new file mode 100644 index 0000000..872e590 Binary files /dev/null and b/Content/ToolFunction/03Textures/HoneyComb.uasset differ diff --git a/Content/ToolFunction/03Textures/LittleArrow.uasset b/Content/ToolFunction/03Textures/LittleArrow.uasset new file mode 100644 index 0000000..2abe826 Binary files /dev/null and b/Content/ToolFunction/03Textures/LittleArrow.uasset differ diff --git a/Content/ToolFunction/03Textures/Mosaic.uasset b/Content/ToolFunction/03Textures/Mosaic.uasset new file mode 100644 index 0000000..9823c0e Binary files /dev/null and b/Content/ToolFunction/03Textures/Mosaic.uasset differ diff --git a/Content/ToolFunction/03Textures/Origin.uasset b/Content/ToolFunction/03Textures/Origin.uasset new file mode 100644 index 0000000..1b6523b Binary files /dev/null and b/Content/ToolFunction/03Textures/Origin.uasset differ diff --git a/Content/ToolFunction/03Textures/Play.uasset b/Content/ToolFunction/03Textures/Play.uasset new file mode 100644 index 0000000..2ad9cca Binary files /dev/null and b/Content/ToolFunction/03Textures/Play.uasset differ diff --git a/Content/ToolFunction/03Textures/PointImage.uasset b/Content/ToolFunction/03Textures/PointImage.uasset new file mode 100644 index 0000000..540890d Binary files /dev/null and b/Content/ToolFunction/03Textures/PointImage.uasset differ diff --git a/Content/ToolFunction/03Textures/Reset.uasset b/Content/ToolFunction/03Textures/Reset.uasset new file mode 100644 index 0000000..8b232bd Binary files /dev/null and b/Content/ToolFunction/03Textures/Reset.uasset differ diff --git a/Content/ToolFunction/03Textures/Roundness.uasset b/Content/ToolFunction/03Textures/Roundness.uasset new file mode 100644 index 0000000..1bd16d2 Binary files /dev/null and b/Content/ToolFunction/03Textures/Roundness.uasset differ diff --git a/Content/ToolFunction/03Textures/SVG/测绘导航.uasset b/Content/ToolFunction/03Textures/SVG/测绘导航.uasset new file mode 100644 index 0000000..50eef57 Binary files /dev/null and b/Content/ToolFunction/03Textures/SVG/测绘导航.uasset differ diff --git a/Content/ToolFunction/03Textures/SimpleMark/1单箭头.uasset b/Content/ToolFunction/03Textures/SimpleMark/1单箭头.uasset new file mode 100644 index 0000000..290d79d Binary files /dev/null and b/Content/ToolFunction/03Textures/SimpleMark/1单箭头.uasset differ diff --git a/Content/ToolFunction/03Textures/SimpleMark/1单箭头描边.uasset b/Content/ToolFunction/03Textures/SimpleMark/1单箭头描边.uasset new file mode 100644 index 0000000..581b296 Binary files /dev/null and b/Content/ToolFunction/03Textures/SimpleMark/1单箭头描边.uasset differ diff --git a/Content/ToolFunction/03Textures/SimpleMark/1双箭头.uasset b/Content/ToolFunction/03Textures/SimpleMark/1双箭头.uasset new file mode 100644 index 0000000..abbe250 Binary files /dev/null and b/Content/ToolFunction/03Textures/SimpleMark/1双箭头.uasset differ diff --git a/Content/ToolFunction/03Textures/SimpleMark/1双箭头描边.uasset b/Content/ToolFunction/03Textures/SimpleMark/1双箭头描边.uasset new file mode 100644 index 0000000..f186ee1 Binary files /dev/null and b/Content/ToolFunction/03Textures/SimpleMark/1双箭头描边.uasset differ diff --git a/Content/ToolFunction/03Textures/SimpleMark/1集结地.uasset b/Content/ToolFunction/03Textures/SimpleMark/1集结地.uasset new file mode 100644 index 0000000..97f4021 Binary files /dev/null and b/Content/ToolFunction/03Textures/SimpleMark/1集结地.uasset differ diff --git a/Content/ToolFunction/03Textures/SimpleMark/1集结地描边.uasset b/Content/ToolFunction/03Textures/SimpleMark/1集结地描边.uasset new file mode 100644 index 0000000..c7a4935 Binary files /dev/null and b/Content/ToolFunction/03Textures/SimpleMark/1集结地描边.uasset differ diff --git a/Content/ToolFunction/03Textures/SmallWhite.uasset b/Content/ToolFunction/03Textures/SmallWhite.uasset new file mode 100644 index 0000000..e15d3ac Binary files /dev/null and b/Content/ToolFunction/03Textures/SmallWhite.uasset differ diff --git a/Content/ToolFunction/03Textures/Soldier.uasset b/Content/ToolFunction/03Textures/Soldier.uasset new file mode 100644 index 0000000..bc7c887 Binary files /dev/null and b/Content/ToolFunction/03Textures/Soldier.uasset differ diff --git a/Content/ToolFunction/03Textures/StartScreen/CheckOff_3x.uasset b/Content/ToolFunction/03Textures/StartScreen/CheckOff_3x.uasset new file mode 100644 index 0000000..0412230 Binary files /dev/null and b/Content/ToolFunction/03Textures/StartScreen/CheckOff_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/StartScreen/KeyIcon.uasset b/Content/ToolFunction/03Textures/StartScreen/KeyIcon.uasset new file mode 100644 index 0000000..7400dce Binary files /dev/null and b/Content/ToolFunction/03Textures/StartScreen/KeyIcon.uasset differ diff --git a/Content/ToolFunction/03Textures/StartScreen/NameIcon.uasset b/Content/ToolFunction/03Textures/StartScreen/NameIcon.uasset new file mode 100644 index 0000000..f9fdf47 Binary files /dev/null and b/Content/ToolFunction/03Textures/StartScreen/NameIcon.uasset differ diff --git a/Content/ToolFunction/03Textures/StartScreen/TrueIcon.uasset b/Content/ToolFunction/03Textures/StartScreen/TrueIcon.uasset new file mode 100644 index 0000000..3c5c2c1 Binary files /dev/null and b/Content/ToolFunction/03Textures/StartScreen/TrueIcon.uasset differ diff --git a/Content/ToolFunction/03Textures/StartScreen/check_3x.uasset b/Content/ToolFunction/03Textures/StartScreen/check_3x.uasset new file mode 100644 index 0000000..8550599 Binary files /dev/null and b/Content/ToolFunction/03Textures/StartScreen/check_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/StartScreen/image_png_png_3x.uasset b/Content/ToolFunction/03Textures/StartScreen/image_png_png_3x.uasset new file mode 100644 index 0000000..1d20678 Binary files /dev/null and b/Content/ToolFunction/03Textures/StartScreen/image_png_png_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/StartScreen/开启_3x.uasset b/Content/ToolFunction/03Textures/StartScreen/开启_3x.uasset new file mode 100644 index 0000000..f3d4321 Binary files /dev/null and b/Content/ToolFunction/03Textures/StartScreen/开启_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/StartScreen/微信截图_20241104160241.uasset b/Content/ToolFunction/03Textures/StartScreen/微信截图_20241104160241.uasset new file mode 100644 index 0000000..614a686 Binary files /dev/null and b/Content/ToolFunction/03Textures/StartScreen/微信截图_20241104160241.uasset differ diff --git a/Content/ToolFunction/03Textures/StartScreen/登录页面1_0_3x.uasset b/Content/ToolFunction/03Textures/StartScreen/登录页面1_0_3x.uasset new file mode 100644 index 0000000..2d7e0b2 Binary files /dev/null and b/Content/ToolFunction/03Textures/StartScreen/登录页面1_0_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/StartScreen/系统设置_3x.uasset b/Content/ToolFunction/03Textures/StartScreen/系统设置_3x.uasset new file mode 100644 index 0000000..acf9d88 Binary files /dev/null and b/Content/ToolFunction/03Textures/StartScreen/系统设置_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/StartScreen/路径_1_3x.uasset b/Content/ToolFunction/03Textures/StartScreen/路径_1_3x.uasset new file mode 100644 index 0000000..2b60348 Binary files /dev/null and b/Content/ToolFunction/03Textures/StartScreen/路径_1_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/Stop.uasset b/Content/ToolFunction/03Textures/Stop.uasset new file mode 100644 index 0000000..4d572a9 Binary files /dev/null and b/Content/ToolFunction/03Textures/Stop.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/Head2.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/Head2.uasset new file mode 100644 index 0000000..ec4b9e2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/Head2.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/遮罩_3x.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/遮罩_3x.uasset new file mode 100644 index 0000000..684211b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/遮罩_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00000.uasset new file mode 100644 index 0000000..26b2328 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00000_Sprite.uasset new file mode 100644 index 0000000..75062ec Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00001.uasset new file mode 100644 index 0000000..ac37a95 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00001_Sprite.uasset new file mode 100644 index 0000000..6c03c09 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00002.uasset new file mode 100644 index 0000000..cb7c0fc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00002_Sprite.uasset new file mode 100644 index 0000000..e4ede1a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00003.uasset new file mode 100644 index 0000000..9ed76c4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00003_Sprite.uasset new file mode 100644 index 0000000..f740840 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00004.uasset new file mode 100644 index 0000000..e70d20f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00004_Sprite.uasset new file mode 100644 index 0000000..1667120 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00005.uasset new file mode 100644 index 0000000..980e16a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00005_Sprite.uasset new file mode 100644 index 0000000..b0188e0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00006.uasset new file mode 100644 index 0000000..cc4146a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00006_Sprite.uasset new file mode 100644 index 0000000..8fbf72c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00007.uasset new file mode 100644 index 0000000..3797a36 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00007_Sprite.uasset new file mode 100644 index 0000000..378243e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00008.uasset new file mode 100644 index 0000000..dcceb12 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00008_Sprite.uasset new file mode 100644 index 0000000..4223b32 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00009.uasset new file mode 100644 index 0000000..d3d13df Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00009_Sprite.uasset new file mode 100644 index 0000000..a14e4c7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00010.uasset new file mode 100644 index 0000000..bd6a96d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00010_Sprite.uasset new file mode 100644 index 0000000..d6c2f02 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00011.uasset new file mode 100644 index 0000000..824f81f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00011_Sprite.uasset new file mode 100644 index 0000000..f33ef81 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00012.uasset new file mode 100644 index 0000000..55d8d35 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00012_Sprite.uasset new file mode 100644 index 0000000..5f2a42f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00013.uasset new file mode 100644 index 0000000..e24a25d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00013_Sprite.uasset new file mode 100644 index 0000000..a345997 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00014.uasset new file mode 100644 index 0000000..1fe7650 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00014_Sprite.uasset new file mode 100644 index 0000000..001b1d0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00015.uasset new file mode 100644 index 0000000..3c2d266 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00015_Sprite.uasset new file mode 100644 index 0000000..e6c3293 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00016.uasset new file mode 100644 index 0000000..5030e2f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00016_Sprite.uasset new file mode 100644 index 0000000..1abecb8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00017.uasset new file mode 100644 index 0000000..467675a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00017_Sprite.uasset new file mode 100644 index 0000000..0d169d3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00018.uasset new file mode 100644 index 0000000..3477fb0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00018_Sprite.uasset new file mode 100644 index 0000000..b68dd99 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00019.uasset new file mode 100644 index 0000000..0e86a67 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00019_Sprite.uasset new file mode 100644 index 0000000..23e4cef Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00020.uasset new file mode 100644 index 0000000..c419939 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00020_Sprite.uasset new file mode 100644 index 0000000..0e4e2ad Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00021.uasset new file mode 100644 index 0000000..6942097 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00021_Sprite.uasset new file mode 100644 index 0000000..16b70e2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00022.uasset new file mode 100644 index 0000000..07677fe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00022_Sprite.uasset new file mode 100644 index 0000000..f5b53ee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00023.uasset new file mode 100644 index 0000000..7390852 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00023_Sprite.uasset new file mode 100644 index 0000000..6dbfb66 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00024.uasset new file mode 100644 index 0000000..b8d766f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00024_Sprite.uasset new file mode 100644 index 0000000..ba21c26 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00025.uasset new file mode 100644 index 0000000..419a46e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00025_Sprite.uasset new file mode 100644 index 0000000..1f1d95f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00026.uasset new file mode 100644 index 0000000..ff584a7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00026_Sprite.uasset new file mode 100644 index 0000000..5672aa1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00027.uasset new file mode 100644 index 0000000..9ae134a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00027_Sprite.uasset new file mode 100644 index 0000000..eece586 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00028.uasset new file mode 100644 index 0000000..c8de0a6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00028_Sprite.uasset new file mode 100644 index 0000000..ca27fa1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00029.uasset new file mode 100644 index 0000000..a66a849 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00029_Sprite.uasset new file mode 100644 index 0000000..60efb51 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00030.uasset new file mode 100644 index 0000000..d95ea14 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00030_Sprite.uasset new file mode 100644 index 0000000..1204a16 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00031.uasset new file mode 100644 index 0000000..9a0f3bd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00031_Sprite.uasset new file mode 100644 index 0000000..720d287 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00032.uasset new file mode 100644 index 0000000..c0dee95 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00032_Sprite.uasset new file mode 100644 index 0000000..f3fa161 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00033.uasset new file mode 100644 index 0000000..b464310 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00033_Sprite.uasset new file mode 100644 index 0000000..9e127b6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00034.uasset new file mode 100644 index 0000000..9f5c677 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00034_Sprite.uasset new file mode 100644 index 0000000..c1b730b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00035.uasset new file mode 100644 index 0000000..fa6f5d8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00035_Sprite.uasset new file mode 100644 index 0000000..26c796b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00036.uasset new file mode 100644 index 0000000..2dfd24e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00036_Sprite.uasset new file mode 100644 index 0000000..a4da290 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00037.uasset new file mode 100644 index 0000000..d2dab57 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00037_Sprite.uasset new file mode 100644 index 0000000..7e5ea4d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00038.uasset new file mode 100644 index 0000000..be0542d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00038_Sprite.uasset new file mode 100644 index 0000000..309c992 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00039.uasset new file mode 100644 index 0000000..52fbdff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00039_Sprite.uasset new file mode 100644 index 0000000..9c8196a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00040.uasset new file mode 100644 index 0000000..ead72b4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00040_Sprite.uasset new file mode 100644 index 0000000..1e72977 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00041.uasset new file mode 100644 index 0000000..2613df4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00041_Sprite.uasset new file mode 100644 index 0000000..d71dd29 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00042.uasset new file mode 100644 index 0000000..76f8da5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00042_Sprite.uasset new file mode 100644 index 0000000..9f5470e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00043.uasset new file mode 100644 index 0000000..126d619 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00043_Sprite.uasset new file mode 100644 index 0000000..6a32c39 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00044.uasset new file mode 100644 index 0000000..24cb363 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00044_Sprite.uasset new file mode 100644 index 0000000..251e3f2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00045.uasset new file mode 100644 index 0000000..a377b55 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00045_Sprite.uasset new file mode 100644 index 0000000..8c39751 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00046.uasset new file mode 100644 index 0000000..31387b9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00046_Sprite.uasset new file mode 100644 index 0000000..9530072 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00047.uasset new file mode 100644 index 0000000..17098dd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00047_Sprite.uasset new file mode 100644 index 0000000..4b70d0f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00048.uasset new file mode 100644 index 0000000..33e71d5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00048_Sprite.uasset new file mode 100644 index 0000000..b3590d4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00049.uasset new file mode 100644 index 0000000..70ef77f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00049_Sprite.uasset new file mode 100644 index 0000000..a6129ed Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00050.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00050.uasset new file mode 100644 index 0000000..33f455d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00050.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00050_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00050_Sprite.uasset new file mode 100644 index 0000000..90a6236 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00050_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00051.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00051.uasset new file mode 100644 index 0000000..debc051 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00051.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00051_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00051_Sprite.uasset new file mode 100644 index 0000000..432cfac Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00051_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00052.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00052.uasset new file mode 100644 index 0000000..e69587a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00052.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00052_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00052_Sprite.uasset new file mode 100644 index 0000000..badd54c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00052_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00053.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00053.uasset new file mode 100644 index 0000000..12459d6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00053.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00053_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00053_Sprite.uasset new file mode 100644 index 0000000..692c650 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00053_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00054.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00054.uasset new file mode 100644 index 0000000..a866622 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00054.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00054_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00054_Sprite.uasset new file mode 100644 index 0000000..e62988c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00054_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00055.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00055.uasset new file mode 100644 index 0000000..ece3d0c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00055.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00055_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00055_Sprite.uasset new file mode 100644 index 0000000..8a68ef5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00055_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00056.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00056.uasset new file mode 100644 index 0000000..9744c8e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00056.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00056_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00056_Sprite.uasset new file mode 100644 index 0000000..28b48ed Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00056_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00057.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00057.uasset new file mode 100644 index 0000000..0e3565b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00057.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00057_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00057_Sprite.uasset new file mode 100644 index 0000000..42ae72c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00057_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00058.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00058.uasset new file mode 100644 index 0000000..666b9e5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00058.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00058_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00058_Sprite.uasset new file mode 100644 index 0000000..ca478fb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/Head2/�ϳ�_2_00058_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向.uasset new file mode 100644 index 0000000..1696a36 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00000.uasset new file mode 100644 index 0000000..da5881d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00000_Sprite.uasset new file mode 100644 index 0000000..c64bf3b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00001.uasset new file mode 100644 index 0000000..31bb82a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00001_Sprite.uasset new file mode 100644 index 0000000..97d8adb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00002.uasset new file mode 100644 index 0000000..0856581 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00002_Sprite.uasset new file mode 100644 index 0000000..37b3991 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00003.uasset new file mode 100644 index 0000000..e838db0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00003_Sprite.uasset new file mode 100644 index 0000000..794f2df Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00004.uasset new file mode 100644 index 0000000..34525f5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00004_Sprite.uasset new file mode 100644 index 0000000..d69de12 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00005.uasset new file mode 100644 index 0000000..398809a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00005_Sprite.uasset new file mode 100644 index 0000000..9e0bf7e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00006.uasset new file mode 100644 index 0000000..c3dce28 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00006_Sprite.uasset new file mode 100644 index 0000000..5c827ef Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00007.uasset new file mode 100644 index 0000000..c1b5ec3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00007_Sprite.uasset new file mode 100644 index 0000000..422b6c3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00008.uasset new file mode 100644 index 0000000..4f5b269 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00008_Sprite.uasset new file mode 100644 index 0000000..65875bc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00009.uasset new file mode 100644 index 0000000..a43cbee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00009_Sprite.uasset new file mode 100644 index 0000000..7b45a60 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00010.uasset new file mode 100644 index 0000000..de6dfdf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00010_Sprite.uasset new file mode 100644 index 0000000..e64d43f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00011.uasset new file mode 100644 index 0000000..f5e2bcf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00011_Sprite.uasset new file mode 100644 index 0000000..7448398 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00012.uasset new file mode 100644 index 0000000..da62721 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00012_Sprite.uasset new file mode 100644 index 0000000..bb80122 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00013.uasset new file mode 100644 index 0000000..5c3a749 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00013_Sprite.uasset new file mode 100644 index 0000000..7a5cdda Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00014.uasset new file mode 100644 index 0000000..4ccd413 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00014_Sprite.uasset new file mode 100644 index 0000000..9033d10 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00015.uasset new file mode 100644 index 0000000..375c9aa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00015_Sprite.uasset new file mode 100644 index 0000000..7a4d3f1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00016.uasset new file mode 100644 index 0000000..0a1bdb2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00016_Sprite.uasset new file mode 100644 index 0000000..d1b061a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00017.uasset new file mode 100644 index 0000000..edc4ff3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00017_Sprite.uasset new file mode 100644 index 0000000..2be7d40 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00018.uasset new file mode 100644 index 0000000..256de8c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00018_Sprite.uasset new file mode 100644 index 0000000..0c6ebde Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00019.uasset new file mode 100644 index 0000000..a3246f9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00019_Sprite.uasset new file mode 100644 index 0000000..650d3fc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00020.uasset new file mode 100644 index 0000000..ac51992 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00020_Sprite.uasset new file mode 100644 index 0000000..6464320 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00021.uasset new file mode 100644 index 0000000..c6e8b5e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00021_Sprite.uasset new file mode 100644 index 0000000..b4c4c3a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00022.uasset new file mode 100644 index 0000000..0e51eb7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00022_Sprite.uasset new file mode 100644 index 0000000..a65b313 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00023.uasset new file mode 100644 index 0000000..2a711bd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00023_Sprite.uasset new file mode 100644 index 0000000..7a00be9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00024.uasset new file mode 100644 index 0000000..853730d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00024_Sprite.uasset new file mode 100644 index 0000000..5984e84 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00025.uasset new file mode 100644 index 0000000..73643e6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00025_Sprite.uasset new file mode 100644 index 0000000..5610a13 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00026.uasset new file mode 100644 index 0000000..1fb05c5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00026_Sprite.uasset new file mode 100644 index 0000000..90a21c6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00027.uasset new file mode 100644 index 0000000..c94d16d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00027_Sprite.uasset new file mode 100644 index 0000000..2ac31eb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00028.uasset new file mode 100644 index 0000000..44e2b6a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00028_Sprite.uasset new file mode 100644 index 0000000..5ade763 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00029.uasset new file mode 100644 index 0000000..b4d89d9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00029_Sprite.uasset new file mode 100644 index 0000000..705a729 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00030.uasset new file mode 100644 index 0000000..63a2c5b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00030_Sprite.uasset new file mode 100644 index 0000000..3f947f5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00031.uasset new file mode 100644 index 0000000..5465aee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00031_Sprite.uasset new file mode 100644 index 0000000..edab13a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00032.uasset new file mode 100644 index 0000000..6fc4f6b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00032_Sprite.uasset new file mode 100644 index 0000000..1391218 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00033.uasset new file mode 100644 index 0000000..0903d0a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00033_Sprite.uasset new file mode 100644 index 0000000..e8fa507 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00034.uasset new file mode 100644 index 0000000..2a7ac60 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00034_Sprite.uasset new file mode 100644 index 0000000..ec23b25 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00035.uasset new file mode 100644 index 0000000..d08f578 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00035_Sprite.uasset new file mode 100644 index 0000000..8f3d3b7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00036.uasset new file mode 100644 index 0000000..3e60ffe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00036_Sprite.uasset new file mode 100644 index 0000000..b65f8c8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00037.uasset new file mode 100644 index 0000000..c4e15b8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00037_Sprite.uasset new file mode 100644 index 0000000..eb3bcb9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00038.uasset new file mode 100644 index 0000000..4e84676 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00038_Sprite.uasset new file mode 100644 index 0000000..8bf7b56 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00039.uasset new file mode 100644 index 0000000..3145e19 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00039_Sprite.uasset new file mode 100644 index 0000000..d6b997a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00040.uasset new file mode 100644 index 0000000..d344564 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00040_Sprite.uasset new file mode 100644 index 0000000..088bf44 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00041.uasset new file mode 100644 index 0000000..bf922f7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00041_Sprite.uasset new file mode 100644 index 0000000..c204452 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00042.uasset new file mode 100644 index 0000000..de9e468 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00042_Sprite.uasset new file mode 100644 index 0000000..d5d0ccf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00043.uasset new file mode 100644 index 0000000..6765fa5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00043_Sprite.uasset new file mode 100644 index 0000000..d7ec9c7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00044.uasset new file mode 100644 index 0000000..d920aa0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00044_Sprite.uasset new file mode 100644 index 0000000..565f030 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00045.uasset new file mode 100644 index 0000000..3280e8d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00045_Sprite.uasset new file mode 100644 index 0000000..634b979 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00046.uasset new file mode 100644 index 0000000..95967d4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00046_Sprite.uasset new file mode 100644 index 0000000..1662622 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00047.uasset new file mode 100644 index 0000000..51727d6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00047_Sprite.uasset new file mode 100644 index 0000000..2dffd0d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00048.uasset new file mode 100644 index 0000000..29c743d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00048_Sprite.uasset new file mode 100644 index 0000000..7b422b9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00049.uasset new file mode 100644 index 0000000..de1087c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00049_Sprite.uasset new file mode 100644 index 0000000..193da6d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00050.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00050.uasset new file mode 100644 index 0000000..d3b9755 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00050.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00050_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00050_Sprite.uasset new file mode 100644 index 0000000..2c3b2a7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/坡度坡向/坡度坡向_00050_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/FB_DeleteMeasure.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/FB_DeleteMeasure.uasset new file mode 100644 index 0000000..f29cb31 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/FB_DeleteMeasure.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00000.uasset new file mode 100644 index 0000000..d389ca6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00000_Sprite.uasset new file mode 100644 index 0000000..45707c8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00001.uasset new file mode 100644 index 0000000..afee50e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00001_Sprite.uasset new file mode 100644 index 0000000..f7691b7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00002.uasset new file mode 100644 index 0000000..a1010b5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00002_Sprite.uasset new file mode 100644 index 0000000..01f7017 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00003.uasset new file mode 100644 index 0000000..6444041 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00003_Sprite.uasset new file mode 100644 index 0000000..2d46563 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00004.uasset new file mode 100644 index 0000000..2747206 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00004_Sprite.uasset new file mode 100644 index 0000000..825e2f0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00005.uasset new file mode 100644 index 0000000..3a76716 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00005_Sprite.uasset new file mode 100644 index 0000000..6916b29 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00006.uasset new file mode 100644 index 0000000..0b63d3b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00006_Sprite.uasset new file mode 100644 index 0000000..8beab09 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00007.uasset new file mode 100644 index 0000000..26a4a99 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00007_Sprite.uasset new file mode 100644 index 0000000..1afb7ce Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00008.uasset new file mode 100644 index 0000000..043f4a6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00008_Sprite.uasset new file mode 100644 index 0000000..54d23b2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00009.uasset new file mode 100644 index 0000000..0b67eac Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00009_Sprite.uasset new file mode 100644 index 0000000..fed79ba Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00010.uasset new file mode 100644 index 0000000..4d4694c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00010_Sprite.uasset new file mode 100644 index 0000000..61496d6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00011.uasset new file mode 100644 index 0000000..8cffff7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00011_Sprite.uasset new file mode 100644 index 0000000..6caab34 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00012.uasset new file mode 100644 index 0000000..30b2a27 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00012_Sprite.uasset new file mode 100644 index 0000000..5e7460b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00013.uasset new file mode 100644 index 0000000..0618bb2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00013_Sprite.uasset new file mode 100644 index 0000000..048b19a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00014.uasset new file mode 100644 index 0000000..e1e6247 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00014_Sprite.uasset new file mode 100644 index 0000000..1f4f481 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00015.uasset new file mode 100644 index 0000000..e04e138 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00015_Sprite.uasset new file mode 100644 index 0000000..d94a28b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00016.uasset new file mode 100644 index 0000000..4e5644e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00016_Sprite.uasset new file mode 100644 index 0000000..9010e36 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00017.uasset new file mode 100644 index 0000000..ec4ab46 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00017_Sprite.uasset new file mode 100644 index 0000000..3772aff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00018.uasset new file mode 100644 index 0000000..4561d91 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00018_Sprite.uasset new file mode 100644 index 0000000..53f645d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00019.uasset new file mode 100644 index 0000000..7c467fd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00019_Sprite.uasset new file mode 100644 index 0000000..13ab4db Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00020.uasset new file mode 100644 index 0000000..e806dd7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00020_Sprite.uasset new file mode 100644 index 0000000..7d026d3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00021.uasset new file mode 100644 index 0000000..fe71a49 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00021_Sprite.uasset new file mode 100644 index 0000000..79e353f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00022.uasset new file mode 100644 index 0000000..cb69282 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00022_Sprite.uasset new file mode 100644 index 0000000..d392e6b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00023.uasset new file mode 100644 index 0000000..5d1cc85 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00023_Sprite.uasset new file mode 100644 index 0000000..6f179f0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00024.uasset new file mode 100644 index 0000000..13d381f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00024_Sprite.uasset new file mode 100644 index 0000000..005d989 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00025.uasset new file mode 100644 index 0000000..5da0330 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00025_Sprite.uasset new file mode 100644 index 0000000..7228ff0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00026.uasset new file mode 100644 index 0000000..9ffc83a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00026_Sprite.uasset new file mode 100644 index 0000000..75983ff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00027.uasset new file mode 100644 index 0000000..36a4ae3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00027_Sprite.uasset new file mode 100644 index 0000000..f26cb9c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00028.uasset new file mode 100644 index 0000000..fd38792 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00028_Sprite.uasset new file mode 100644 index 0000000..1e876af Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00029.uasset new file mode 100644 index 0000000..3dc2655 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00029_Sprite.uasset new file mode 100644 index 0000000..e86a195 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00030.uasset new file mode 100644 index 0000000..cfd78ec Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00030_Sprite.uasset new file mode 100644 index 0000000..3f5c7fc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00031.uasset new file mode 100644 index 0000000..a1dbfbf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00031_Sprite.uasset new file mode 100644 index 0000000..2e38e35 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00032.uasset new file mode 100644 index 0000000..b7512a4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00032_Sprite.uasset new file mode 100644 index 0000000..f1d8cc7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00033.uasset new file mode 100644 index 0000000..242173d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00033_Sprite.uasset new file mode 100644 index 0000000..90b742e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00034.uasset new file mode 100644 index 0000000..25cef9e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00034_Sprite.uasset new file mode 100644 index 0000000..b3a13ab Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00035.uasset new file mode 100644 index 0000000..c198cc6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00035_Sprite.uasset new file mode 100644 index 0000000..a20087d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00036.uasset new file mode 100644 index 0000000..bff2450 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00036_Sprite.uasset new file mode 100644 index 0000000..30dd3cf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00037.uasset new file mode 100644 index 0000000..2e4a1cb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00037_Sprite.uasset new file mode 100644 index 0000000..44065b6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00038.uasset new file mode 100644 index 0000000..5ae5281 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00038_Sprite.uasset new file mode 100644 index 0000000..3a8f433 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00039.uasset new file mode 100644 index 0000000..dacd528 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00039_Sprite.uasset new file mode 100644 index 0000000..11b3efb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00040.uasset new file mode 100644 index 0000000..63d8da7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00040_Sprite.uasset new file mode 100644 index 0000000..f8ccf15 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00041.uasset new file mode 100644 index 0000000..a3af3b6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00041_Sprite.uasset new file mode 100644 index 0000000..04a8410 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00042.uasset new file mode 100644 index 0000000..686137d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00042_Sprite.uasset new file mode 100644 index 0000000..634f191 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00043.uasset new file mode 100644 index 0000000..0829248 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00043_Sprite.uasset new file mode 100644 index 0000000..b34a3d7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00044.uasset new file mode 100644 index 0000000..8315534 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00044_Sprite.uasset new file mode 100644 index 0000000..3000ae7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00045.uasset new file mode 100644 index 0000000..4476d02 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00045_Sprite.uasset new file mode 100644 index 0000000..493e3e9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00046.uasset new file mode 100644 index 0000000..4397b86 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00046_Sprite.uasset new file mode 100644 index 0000000..a58df1a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00047.uasset new file mode 100644 index 0000000..3ea7151 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00047_Sprite.uasset new file mode 100644 index 0000000..8d243fc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00048.uasset new file mode 100644 index 0000000..d3aa51d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00048_Sprite.uasset new file mode 100644 index 0000000..80f07c9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00049.uasset new file mode 100644 index 0000000..3350f0d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00049_Sprite.uasset new file mode 100644 index 0000000..db17091 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00050.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00050.uasset new file mode 100644 index 0000000..b09588b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00050.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00050_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00050_Sprite.uasset new file mode 100644 index 0000000..0c4046d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/分析/清除测量/清除测量_00050_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/FB_TrangleMeasure.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/FB_TrangleMeasure.uasset new file mode 100644 index 0000000..b8f710e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/FB_TrangleMeasure.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00000.uasset new file mode 100644 index 0000000..a84420f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00000_Sprite.uasset new file mode 100644 index 0000000..83878a5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00001.uasset new file mode 100644 index 0000000..e66dccb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00001_Sprite.uasset new file mode 100644 index 0000000..ed3372e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00002.uasset new file mode 100644 index 0000000..5bbac30 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00002_Sprite.uasset new file mode 100644 index 0000000..6b14a86 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00003.uasset new file mode 100644 index 0000000..0e70485 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00003_Sprite.uasset new file mode 100644 index 0000000..f1bb8f9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00004.uasset new file mode 100644 index 0000000..375f868 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00004_Sprite.uasset new file mode 100644 index 0000000..9b38d4a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00005.uasset new file mode 100644 index 0000000..bb9d1b2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00005_Sprite.uasset new file mode 100644 index 0000000..2402ac0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00006.uasset new file mode 100644 index 0000000..18dab49 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00006_Sprite.uasset new file mode 100644 index 0000000..966deab Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00007.uasset new file mode 100644 index 0000000..e78d4be Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00007_Sprite.uasset new file mode 100644 index 0000000..da18124 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00008.uasset new file mode 100644 index 0000000..956f6b5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00008_Sprite.uasset new file mode 100644 index 0000000..1984076 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00009.uasset new file mode 100644 index 0000000..c9ae13a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00009_Sprite.uasset new file mode 100644 index 0000000..c02beea Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00010.uasset new file mode 100644 index 0000000..080227d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00010_Sprite.uasset new file mode 100644 index 0000000..64d8bfe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00011.uasset new file mode 100644 index 0000000..78b70d9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00011_Sprite.uasset new file mode 100644 index 0000000..c069571 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00012.uasset new file mode 100644 index 0000000..0233b52 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00012_Sprite.uasset new file mode 100644 index 0000000..086c7aa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00013.uasset new file mode 100644 index 0000000..80a5901 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00013_Sprite.uasset new file mode 100644 index 0000000..36d5f6c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00014.uasset new file mode 100644 index 0000000..78effff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00014_Sprite.uasset new file mode 100644 index 0000000..3e34917 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00015.uasset new file mode 100644 index 0000000..15c2e96 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00015_Sprite.uasset new file mode 100644 index 0000000..8bf37c0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00016.uasset new file mode 100644 index 0000000..8505ca6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00016_Sprite.uasset new file mode 100644 index 0000000..629f2df Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00017.uasset new file mode 100644 index 0000000..bf4f15a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00017_Sprite.uasset new file mode 100644 index 0000000..4397d4f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00018.uasset new file mode 100644 index 0000000..17c0b7e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00018_Sprite.uasset new file mode 100644 index 0000000..b627e66 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00019.uasset new file mode 100644 index 0000000..4e044ff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00019_Sprite.uasset new file mode 100644 index 0000000..7cafd3a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00020.uasset new file mode 100644 index 0000000..14bd993 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00020_Sprite.uasset new file mode 100644 index 0000000..19e5f25 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00021.uasset new file mode 100644 index 0000000..db897c3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00021_Sprite.uasset new file mode 100644 index 0000000..7220b8a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00022.uasset new file mode 100644 index 0000000..e8bf638 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00022_Sprite.uasset new file mode 100644 index 0000000..4b44da1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00023.uasset new file mode 100644 index 0000000..370def6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00023_Sprite.uasset new file mode 100644 index 0000000..6b1e305 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00024.uasset new file mode 100644 index 0000000..84c4766 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00024_Sprite.uasset new file mode 100644 index 0000000..2cf2416 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00025.uasset new file mode 100644 index 0000000..300a20e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00025_Sprite.uasset new file mode 100644 index 0000000..cdad9e8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00026.uasset new file mode 100644 index 0000000..28041a5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00026_Sprite.uasset new file mode 100644 index 0000000..8bb6d1b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00027.uasset new file mode 100644 index 0000000..f16aa11 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00027_Sprite.uasset new file mode 100644 index 0000000..370cc67 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00028.uasset new file mode 100644 index 0000000..ff2a0ad Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00028_Sprite.uasset new file mode 100644 index 0000000..5d565d6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00029.uasset new file mode 100644 index 0000000..dc05dfd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00029_Sprite.uasset new file mode 100644 index 0000000..c59de3f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00030.uasset new file mode 100644 index 0000000..247fa4a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00030_Sprite.uasset new file mode 100644 index 0000000..05ac864 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00031.uasset new file mode 100644 index 0000000..a79fc82 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00031_Sprite.uasset new file mode 100644 index 0000000..cdfb614 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00032.uasset new file mode 100644 index 0000000..028ea8a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00032_Sprite.uasset new file mode 100644 index 0000000..5d991d6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00033.uasset new file mode 100644 index 0000000..1e1284e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00033_Sprite.uasset new file mode 100644 index 0000000..1e64661 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00034.uasset new file mode 100644 index 0000000..49ffcdb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00034_Sprite.uasset new file mode 100644 index 0000000..e1bfbb2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00035.uasset new file mode 100644 index 0000000..18d4036 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00035_Sprite.uasset new file mode 100644 index 0000000..892413d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00036.uasset new file mode 100644 index 0000000..de9cbf9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00036_Sprite.uasset new file mode 100644 index 0000000..6b7ca57 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00037.uasset new file mode 100644 index 0000000..798204c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00037_Sprite.uasset new file mode 100644 index 0000000..20d2254 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00038.uasset new file mode 100644 index 0000000..9e3e7c2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00038_Sprite.uasset new file mode 100644 index 0000000..194335a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00039.uasset new file mode 100644 index 0000000..dd7baa7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00039_Sprite.uasset new file mode 100644 index 0000000..6c53ae5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00040.uasset new file mode 100644 index 0000000..2cfcc72 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00040_Sprite.uasset new file mode 100644 index 0000000..6c420f0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00041.uasset new file mode 100644 index 0000000..f6bf2e0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00041_Sprite.uasset new file mode 100644 index 0000000..6e9ce75 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00042.uasset new file mode 100644 index 0000000..f37d4c5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00042_Sprite.uasset new file mode 100644 index 0000000..d2f1a33 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00043.uasset new file mode 100644 index 0000000..e1cfaa3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00043_Sprite.uasset new file mode 100644 index 0000000..d1aa00b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00044.uasset new file mode 100644 index 0000000..d51d4e2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00044_Sprite.uasset new file mode 100644 index 0000000..3192e64 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00045.uasset new file mode 100644 index 0000000..1e2e89c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00045_Sprite.uasset new file mode 100644 index 0000000..2d4e937 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00046.uasset new file mode 100644 index 0000000..a3e6e18 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00046_Sprite.uasset new file mode 100644 index 0000000..5a3f10f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00047.uasset new file mode 100644 index 0000000..af02c38 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00047_Sprite.uasset new file mode 100644 index 0000000..3bd1fac Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00048.uasset new file mode 100644 index 0000000..af75017 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00048_Sprite.uasset new file mode 100644 index 0000000..49019d9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00049.uasset new file mode 100644 index 0000000..016fc1c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00049_Sprite.uasset new file mode 100644 index 0000000..b05b08f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00050.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00050.uasset new file mode 100644 index 0000000..a004f17 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00050.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00050_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00050_Sprite.uasset new file mode 100644 index 0000000..7a675b0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00050_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00051.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00051.uasset new file mode 100644 index 0000000..07e3e3c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00051.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00051_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00051_Sprite.uasset new file mode 100644 index 0000000..f4fbcf7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00051_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00052.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00052.uasset new file mode 100644 index 0000000..cd9abb8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00052.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00052_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00052_Sprite.uasset new file mode 100644 index 0000000..725235b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00052_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00053.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00053.uasset new file mode 100644 index 0000000..d9905f6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00053.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00053_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00053_Sprite.uasset new file mode 100644 index 0000000..f5ab03c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00053_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00054.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00054.uasset new file mode 100644 index 0000000..4160296 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00054.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00054_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00054_Sprite.uasset new file mode 100644 index 0000000..92b81d1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00054_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00055.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00055.uasset new file mode 100644 index 0000000..ccb0d36 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00055.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00055_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00055_Sprite.uasset new file mode 100644 index 0000000..0387519 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00055_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00056.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00056.uasset new file mode 100644 index 0000000..5a864e5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00056.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00056_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00056_Sprite.uasset new file mode 100644 index 0000000..3cd402e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00056_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00057.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00057.uasset new file mode 100644 index 0000000..b568b25 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00057.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00057_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00057_Sprite.uasset new file mode 100644 index 0000000..d7f6aa4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00057_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00058.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00058.uasset new file mode 100644 index 0000000..b21d3e1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00058.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00058_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00058_Sprite.uasset new file mode 100644 index 0000000..d5c8bbe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00058_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00059.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00059.uasset new file mode 100644 index 0000000..6159958 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00059.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00059_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00059_Sprite.uasset new file mode 100644 index 0000000..7d7da4f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00059_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00060.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00060.uasset new file mode 100644 index 0000000..e4aee02 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00060.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00060_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00060_Sprite.uasset new file mode 100644 index 0000000..1fb72cf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00060_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00061.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00061.uasset new file mode 100644 index 0000000..5024ce2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00061.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00061_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00061_Sprite.uasset new file mode 100644 index 0000000..cd3d317 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00061_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00062.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00062.uasset new file mode 100644 index 0000000..9ded0dc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00062.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00062_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00062_Sprite.uasset new file mode 100644 index 0000000..8b46793 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00062_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00063.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00063.uasset new file mode 100644 index 0000000..0174fed Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00063.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00063_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00063_Sprite.uasset new file mode 100644 index 0000000..738b48d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00063_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00064.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00064.uasset new file mode 100644 index 0000000..84e9fbd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00064.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00064_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00064_Sprite.uasset new file mode 100644 index 0000000..c9a0fb5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00064_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00065.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00065.uasset new file mode 100644 index 0000000..8e3c017 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00065.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00065_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00065_Sprite.uasset new file mode 100644 index 0000000..ac981d0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00065_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00066.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00066.uasset new file mode 100644 index 0000000..4986162 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00066.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00066_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00066_Sprite.uasset new file mode 100644 index 0000000..f9d59ce Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00066_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00067.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00067.uasset new file mode 100644 index 0000000..858bf1d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00067.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00067_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00067_Sprite.uasset new file mode 100644 index 0000000..b7bbefa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00067_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00068.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00068.uasset new file mode 100644 index 0000000..271986c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00068.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00068_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00068_Sprite.uasset new file mode 100644 index 0000000..32f0a17 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00068_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00069.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00069.uasset new file mode 100644 index 0000000..308b976 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00069.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00069_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00069_Sprite.uasset new file mode 100644 index 0000000..26977f7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00069_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00070.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00070.uasset new file mode 100644 index 0000000..4cce102 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00070.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00070_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00070_Sprite.uasset new file mode 100644 index 0000000..eecd9ea Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00070_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00071.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00071.uasset new file mode 100644 index 0000000..be54f76 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00071.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00071_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00071_Sprite.uasset new file mode 100644 index 0000000..ba4db28 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00071_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00072.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00072.uasset new file mode 100644 index 0000000..fdc8ae6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00072.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00072_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00072_Sprite.uasset new file mode 100644 index 0000000..0c1c936 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00072_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00073.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00073.uasset new file mode 100644 index 0000000..c154bc5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00073.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00073_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00073_Sprite.uasset new file mode 100644 index 0000000..dae792a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00073_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00074.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00074.uasset new file mode 100644 index 0000000..32fc0af Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00074.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00074_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00074_Sprite.uasset new file mode 100644 index 0000000..7d702e6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00074_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00075.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00075.uasset new file mode 100644 index 0000000..4b3d51c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00075.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00075_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00075_Sprite.uasset new file mode 100644 index 0000000..b031dc7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00075_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00076.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00076.uasset new file mode 100644 index 0000000..c286a63 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00076.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00076_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00076_Sprite.uasset new file mode 100644 index 0000000..a88d668 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00076_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00077.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00077.uasset new file mode 100644 index 0000000..818f920 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00077.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00077_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00077_Sprite.uasset new file mode 100644 index 0000000..312e177 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00077_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00078.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00078.uasset new file mode 100644 index 0000000..038e9fc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00078.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00078_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00078_Sprite.uasset new file mode 100644 index 0000000..72f9218 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00078_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00079.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00079.uasset new file mode 100644 index 0000000..f3f9316 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00079.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00079_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00079_Sprite.uasset new file mode 100644 index 0000000..c820b85 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00079_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00080.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00080.uasset new file mode 100644 index 0000000..2df9284 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00080.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00080_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00080_Sprite.uasset new file mode 100644 index 0000000..f4ac2c1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00080_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00081.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00081.uasset new file mode 100644 index 0000000..de51529 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00081.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00081_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00081_Sprite.uasset new file mode 100644 index 0000000..a3f5111 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00081_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00082.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00082.uasset new file mode 100644 index 0000000..bfb7096 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00082.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00082_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00082_Sprite.uasset new file mode 100644 index 0000000..2f4c2d5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00082_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00083.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00083.uasset new file mode 100644 index 0000000..e6c2631 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00083.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00083_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00083_Sprite.uasset new file mode 100644 index 0000000..b4f2dea Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00083_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00084.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00084.uasset new file mode 100644 index 0000000..b321b1e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00084.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00084_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00084_Sprite.uasset new file mode 100644 index 0000000..8abd3ca Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00084_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00085.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00085.uasset new file mode 100644 index 0000000..e139b74 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00085.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00085_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00085_Sprite.uasset new file mode 100644 index 0000000..d551208 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00085_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00086.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00086.uasset new file mode 100644 index 0000000..f51bd9c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00086.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00086_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00086_Sprite.uasset new file mode 100644 index 0000000..839a788 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00086_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00087.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00087.uasset new file mode 100644 index 0000000..19ebc2b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00087.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00087_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00087_Sprite.uasset new file mode 100644 index 0000000..f3911b0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00087_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00088.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00088.uasset new file mode 100644 index 0000000..9258a16 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00088.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00088_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00088_Sprite.uasset new file mode 100644 index 0000000..de7d861 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00088_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00089.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00089.uasset new file mode 100644 index 0000000..46373ba Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00089.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00089_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00089_Sprite.uasset new file mode 100644 index 0000000..ce532ae Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00089_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00090.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00090.uasset new file mode 100644 index 0000000..ecf05bb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00090.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00090_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00090_Sprite.uasset new file mode 100644 index 0000000..35443cd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00090_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00091.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00091.uasset new file mode 100644 index 0000000..71fea1e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00091.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00091_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00091_Sprite.uasset new file mode 100644 index 0000000..cc613fb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00091_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00092.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00092.uasset new file mode 100644 index 0000000..4c6c021 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00092.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00092_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00092_Sprite.uasset new file mode 100644 index 0000000..3b57418 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00092_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00093.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00093.uasset new file mode 100644 index 0000000..c87ccbb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00093.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00093_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00093_Sprite.uasset new file mode 100644 index 0000000..e93809d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00093_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00094.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00094.uasset new file mode 100644 index 0000000..639276a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00094.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00094_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00094_Sprite.uasset new file mode 100644 index 0000000..2f3f34e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00094_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00095.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00095.uasset new file mode 100644 index 0000000..188c5ed Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00095.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00095_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00095_Sprite.uasset new file mode 100644 index 0000000..e366eee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00095_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00096.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00096.uasset new file mode 100644 index 0000000..77c07a9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00096.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00096_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00096_Sprite.uasset new file mode 100644 index 0000000..bea0576 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00096_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00097.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00097.uasset new file mode 100644 index 0000000..8eac93f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00097.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00097_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00097_Sprite.uasset new file mode 100644 index 0000000..90a2e55 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00097_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00098.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00098.uasset new file mode 100644 index 0000000..5d2acb7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00098.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00098_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00098_Sprite.uasset new file mode 100644 index 0000000..05465e7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00098_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00099.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00099.uasset new file mode 100644 index 0000000..e30e717 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00099.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00099_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00099_Sprite.uasset new file mode 100644 index 0000000..458335b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/三角测量/三角测量_00099_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/FB_PointMeasure.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/FB_PointMeasure.uasset new file mode 100644 index 0000000..56d07d8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/FB_PointMeasure.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00000.uasset new file mode 100644 index 0000000..d0bcf2c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00000_Sprite.uasset new file mode 100644 index 0000000..d5dbf96 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00001.uasset new file mode 100644 index 0000000..e31cb40 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00001_Sprite.uasset new file mode 100644 index 0000000..e3b45bd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00002.uasset new file mode 100644 index 0000000..0b2e93c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00002_Sprite.uasset new file mode 100644 index 0000000..172d24f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00003.uasset new file mode 100644 index 0000000..f41fd2c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00003_Sprite.uasset new file mode 100644 index 0000000..971f1cd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00004.uasset new file mode 100644 index 0000000..692bac7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00004_Sprite.uasset new file mode 100644 index 0000000..f8fc29e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00005.uasset new file mode 100644 index 0000000..471aa0c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00005_Sprite.uasset new file mode 100644 index 0000000..9067e54 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00006.uasset new file mode 100644 index 0000000..775a420 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00006_Sprite.uasset new file mode 100644 index 0000000..7d9b644 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00007.uasset new file mode 100644 index 0000000..44288f4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00007_Sprite.uasset new file mode 100644 index 0000000..20f4cb2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00008.uasset new file mode 100644 index 0000000..d6a8b3c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00008_Sprite.uasset new file mode 100644 index 0000000..01a9e1c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00009.uasset new file mode 100644 index 0000000..ca8ab59 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00009_Sprite.uasset new file mode 100644 index 0000000..be130fd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00010.uasset new file mode 100644 index 0000000..7660ea7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00010_Sprite.uasset new file mode 100644 index 0000000..abf7089 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00011.uasset new file mode 100644 index 0000000..fa52b28 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00011_Sprite.uasset new file mode 100644 index 0000000..59b10a8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00012.uasset new file mode 100644 index 0000000..5c611b5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00012_Sprite.uasset new file mode 100644 index 0000000..9fd0de1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00013.uasset new file mode 100644 index 0000000..8cf7f59 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00013_Sprite.uasset new file mode 100644 index 0000000..1d7099d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00014.uasset new file mode 100644 index 0000000..4724856 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00014_Sprite.uasset new file mode 100644 index 0000000..ff0112b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00015.uasset new file mode 100644 index 0000000..db82f91 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00015_Sprite.uasset new file mode 100644 index 0000000..b5de13b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00016.uasset new file mode 100644 index 0000000..0cc8b7e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00016_Sprite.uasset new file mode 100644 index 0000000..2a6050a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00017.uasset new file mode 100644 index 0000000..cb48042 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00017_Sprite.uasset new file mode 100644 index 0000000..f3a0b8f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00018.uasset new file mode 100644 index 0000000..2fa39f0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00018_Sprite.uasset new file mode 100644 index 0000000..e936e61 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00019.uasset new file mode 100644 index 0000000..03d0794 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00019_Sprite.uasset new file mode 100644 index 0000000..7c0e07c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00020.uasset new file mode 100644 index 0000000..a7a1f21 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00020_Sprite.uasset new file mode 100644 index 0000000..c59d21f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00021.uasset new file mode 100644 index 0000000..c2d520f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00021_Sprite.uasset new file mode 100644 index 0000000..a0e7908 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00022.uasset new file mode 100644 index 0000000..98d99b9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00022_Sprite.uasset new file mode 100644 index 0000000..770c2ee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00023.uasset new file mode 100644 index 0000000..35be348 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00023_Sprite.uasset new file mode 100644 index 0000000..7dbb502 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00024.uasset new file mode 100644 index 0000000..f46aa75 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00024_Sprite.uasset new file mode 100644 index 0000000..1f42fe7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00025.uasset new file mode 100644 index 0000000..22cc3cf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00025_Sprite.uasset new file mode 100644 index 0000000..1a4b50c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00026.uasset new file mode 100644 index 0000000..c02895b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00026_Sprite.uasset new file mode 100644 index 0000000..bac49cf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00027.uasset new file mode 100644 index 0000000..0ff16fd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00027_Sprite.uasset new file mode 100644 index 0000000..e79b289 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00028.uasset new file mode 100644 index 0000000..1cbe2bd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00028_Sprite.uasset new file mode 100644 index 0000000..3c1ba71 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00029.uasset new file mode 100644 index 0000000..4ce2d8f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00029_Sprite.uasset new file mode 100644 index 0000000..0b144ae Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00030.uasset new file mode 100644 index 0000000..18beff1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00030_Sprite.uasset new file mode 100644 index 0000000..6d27b57 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00031.uasset new file mode 100644 index 0000000..b86a21f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00031_Sprite.uasset new file mode 100644 index 0000000..ed50310 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00032.uasset new file mode 100644 index 0000000..ac92817 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00032_Sprite.uasset new file mode 100644 index 0000000..e78e2e2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00033.uasset new file mode 100644 index 0000000..1314aa3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00033_Sprite.uasset new file mode 100644 index 0000000..5807ae6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00034.uasset new file mode 100644 index 0000000..0276c68 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00034_Sprite.uasset new file mode 100644 index 0000000..e572dae Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00035.uasset new file mode 100644 index 0000000..e35d27d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00035_Sprite.uasset new file mode 100644 index 0000000..de6ed6b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00036.uasset new file mode 100644 index 0000000..a8c6df9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00036_Sprite.uasset new file mode 100644 index 0000000..b67583d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00037.uasset new file mode 100644 index 0000000..4967029 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00037_Sprite.uasset new file mode 100644 index 0000000..0f70545 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00038.uasset new file mode 100644 index 0000000..3c0ec58 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00038_Sprite.uasset new file mode 100644 index 0000000..7a26562 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00039.uasset new file mode 100644 index 0000000..eb4391b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00039_Sprite.uasset new file mode 100644 index 0000000..79fe181 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00040.uasset new file mode 100644 index 0000000..52a5175 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00040_Sprite.uasset new file mode 100644 index 0000000..0a91855 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00041.uasset new file mode 100644 index 0000000..eb5497f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00041_Sprite.uasset new file mode 100644 index 0000000..a109039 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00042.uasset new file mode 100644 index 0000000..731f542 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00042_Sprite.uasset new file mode 100644 index 0000000..1a7595d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00043.uasset new file mode 100644 index 0000000..31cf3fc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00043_Sprite.uasset new file mode 100644 index 0000000..bcbccee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00044.uasset new file mode 100644 index 0000000..cce822d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00044_Sprite.uasset new file mode 100644 index 0000000..e9669c7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00045.uasset new file mode 100644 index 0000000..7fc9662 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00045_Sprite.uasset new file mode 100644 index 0000000..5ca241b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00046.uasset new file mode 100644 index 0000000..46858a7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00046_Sprite.uasset new file mode 100644 index 0000000..c87d017 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00047.uasset new file mode 100644 index 0000000..146bfd9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00047_Sprite.uasset new file mode 100644 index 0000000..c1fcdc6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00048.uasset new file mode 100644 index 0000000..4c6ea95 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00048_Sprite.uasset new file mode 100644 index 0000000..67857f2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00049.uasset new file mode 100644 index 0000000..7eaf9bb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00049_Sprite.uasset new file mode 100644 index 0000000..2b1bd60 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00050.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00050.uasset new file mode 100644 index 0000000..0240606 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00050.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00050_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00050_Sprite.uasset new file mode 100644 index 0000000..963a494 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00050_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00051.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00051.uasset new file mode 100644 index 0000000..7bb4b45 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00051.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00051_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00051_Sprite.uasset new file mode 100644 index 0000000..8ac9d15 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00051_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00052.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00052.uasset new file mode 100644 index 0000000..3a1affa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00052.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00052_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00052_Sprite.uasset new file mode 100644 index 0000000..0f5b091 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00052_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00053.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00053.uasset new file mode 100644 index 0000000..58ae8f2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00053.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00053_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00053_Sprite.uasset new file mode 100644 index 0000000..a4b0eab Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00053_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00054.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00054.uasset new file mode 100644 index 0000000..b46f921 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00054.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00054_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00054_Sprite.uasset new file mode 100644 index 0000000..a933ae9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00054_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00055.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00055.uasset new file mode 100644 index 0000000..f1426ce Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00055.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00055_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00055_Sprite.uasset new file mode 100644 index 0000000..35d411d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00055_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00056.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00056.uasset new file mode 100644 index 0000000..ed328e2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00056.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00056_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00056_Sprite.uasset new file mode 100644 index 0000000..75b1646 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00056_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00057.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00057.uasset new file mode 100644 index 0000000..12b01c7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00057.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00057_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00057_Sprite.uasset new file mode 100644 index 0000000..1551bc9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00057_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00058.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00058.uasset new file mode 100644 index 0000000..7039c38 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00058.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00058_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00058_Sprite.uasset new file mode 100644 index 0000000..f2787b4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00058_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00059.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00059.uasset new file mode 100644 index 0000000..7274ef4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00059.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00059_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00059_Sprite.uasset new file mode 100644 index 0000000..aca6b00 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00059_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00060.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00060.uasset new file mode 100644 index 0000000..383d441 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00060.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00060_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00060_Sprite.uasset new file mode 100644 index 0000000..7c0faec Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00060_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00061.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00061.uasset new file mode 100644 index 0000000..575fb14 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00061.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00061_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00061_Sprite.uasset new file mode 100644 index 0000000..27ef9f0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00061_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00062.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00062.uasset new file mode 100644 index 0000000..ec64c3f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00062.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00062_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00062_Sprite.uasset new file mode 100644 index 0000000..9da0342 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00062_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00063.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00063.uasset new file mode 100644 index 0000000..9b799c0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00063.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00063_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00063_Sprite.uasset new file mode 100644 index 0000000..328d5a7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00063_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00064.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00064.uasset new file mode 100644 index 0000000..d6811fd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00064.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00064_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00064_Sprite.uasset new file mode 100644 index 0000000..21281a1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00064_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00065.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00065.uasset new file mode 100644 index 0000000..cb20580 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00065.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00065_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00065_Sprite.uasset new file mode 100644 index 0000000..ccc11d0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00065_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00066.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00066.uasset new file mode 100644 index 0000000..0771b67 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00066.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00066_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00066_Sprite.uasset new file mode 100644 index 0000000..ddb92c0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00066_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00067.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00067.uasset new file mode 100644 index 0000000..fa06560 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00067.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00067_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00067_Sprite.uasset new file mode 100644 index 0000000..4843160 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00067_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00068.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00068.uasset new file mode 100644 index 0000000..b3d2247 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00068.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00068_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00068_Sprite.uasset new file mode 100644 index 0000000..ff95a76 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00068_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00069.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00069.uasset new file mode 100644 index 0000000..2985600 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00069.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00069_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00069_Sprite.uasset new file mode 100644 index 0000000..8ff3a1c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00069_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00070.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00070.uasset new file mode 100644 index 0000000..5710616 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00070.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00070_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00070_Sprite.uasset new file mode 100644 index 0000000..322fe30 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00070_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00071.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00071.uasset new file mode 100644 index 0000000..87189d9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00071.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00071_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00071_Sprite.uasset new file mode 100644 index 0000000..d9baabe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00071_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00072.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00072.uasset new file mode 100644 index 0000000..3ba3b05 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00072.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00072_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00072_Sprite.uasset new file mode 100644 index 0000000..8d636e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00072_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00073.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00073.uasset new file mode 100644 index 0000000..ac21161 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00073.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00073_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00073_Sprite.uasset new file mode 100644 index 0000000..b412f32 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00073_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00074.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00074.uasset new file mode 100644 index 0000000..888c5d0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00074.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00074_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00074_Sprite.uasset new file mode 100644 index 0000000..4c77037 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00074_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00075.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00075.uasset new file mode 100644 index 0000000..742f9bf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00075.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00075_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00075_Sprite.uasset new file mode 100644 index 0000000..a89a06a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00075_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00076.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00076.uasset new file mode 100644 index 0000000..52af817 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00076.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00076_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00076_Sprite.uasset new file mode 100644 index 0000000..15ee285 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00076_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00077.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00077.uasset new file mode 100644 index 0000000..c039574 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00077.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00077_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00077_Sprite.uasset new file mode 100644 index 0000000..8b95c1d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00077_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00078.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00078.uasset new file mode 100644 index 0000000..70a3827 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00078.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00078_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00078_Sprite.uasset new file mode 100644 index 0000000..6fae8ba Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00078_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00079.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00079.uasset new file mode 100644 index 0000000..58e5277 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00079.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00079_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00079_Sprite.uasset new file mode 100644 index 0000000..d9ed9ea Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00079_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00080.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00080.uasset new file mode 100644 index 0000000..0601246 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00080.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00080_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00080_Sprite.uasset new file mode 100644 index 0000000..cf58e8b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00080_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00081.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00081.uasset new file mode 100644 index 0000000..527e55d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00081.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00081_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00081_Sprite.uasset new file mode 100644 index 0000000..9113958 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00081_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00082.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00082.uasset new file mode 100644 index 0000000..019983d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00082.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00082_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00082_Sprite.uasset new file mode 100644 index 0000000..100d655 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00082_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00083.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00083.uasset new file mode 100644 index 0000000..b8f8757 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00083.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00083_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00083_Sprite.uasset new file mode 100644 index 0000000..ec879ed Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00083_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00084.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00084.uasset new file mode 100644 index 0000000..b8c5730 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00084.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00084_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00084_Sprite.uasset new file mode 100644 index 0000000..8425b07 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00084_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00085.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00085.uasset new file mode 100644 index 0000000..3c8612e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00085.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00085_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00085_Sprite.uasset new file mode 100644 index 0000000..88088ef Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00085_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00086.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00086.uasset new file mode 100644 index 0000000..837c1c8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00086.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00086_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00086_Sprite.uasset new file mode 100644 index 0000000..fa61d90 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00086_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00087.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00087.uasset new file mode 100644 index 0000000..2d0fe8e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00087.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00087_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00087_Sprite.uasset new file mode 100644 index 0000000..eb67a97 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00087_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00088.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00088.uasset new file mode 100644 index 0000000..8e5e2a4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00088.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00088_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00088_Sprite.uasset new file mode 100644 index 0000000..164c044 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00088_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00089.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00089.uasset new file mode 100644 index 0000000..d0ca263 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00089.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00089_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00089_Sprite.uasset new file mode 100644 index 0000000..faa02b2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00089_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00090.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00090.uasset new file mode 100644 index 0000000..361e33e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00090.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00090_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00090_Sprite.uasset new file mode 100644 index 0000000..b6a0895 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00090_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00091.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00091.uasset new file mode 100644 index 0000000..ed09383 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00091.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00091_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00091_Sprite.uasset new file mode 100644 index 0000000..9f32334 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00091_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00092.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00092.uasset new file mode 100644 index 0000000..5872ad9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00092.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00092_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00092_Sprite.uasset new file mode 100644 index 0000000..5378ffe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00092_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00093.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00093.uasset new file mode 100644 index 0000000..6953ed8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00093.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00093_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00093_Sprite.uasset new file mode 100644 index 0000000..015e891 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00093_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00094.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00094.uasset new file mode 100644 index 0000000..a989977 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00094.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00094_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00094_Sprite.uasset new file mode 100644 index 0000000..a5ea2d4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00094_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00095.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00095.uasset new file mode 100644 index 0000000..5e7aff2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00095.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00095_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00095_Sprite.uasset new file mode 100644 index 0000000..5298887 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00095_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00096.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00096.uasset new file mode 100644 index 0000000..ddcbff9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00096.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00096_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00096_Sprite.uasset new file mode 100644 index 0000000..4076852 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00096_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00097.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00097.uasset new file mode 100644 index 0000000..16bcb05 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00097.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00097_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00097_Sprite.uasset new file mode 100644 index 0000000..db1b2fa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00097_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00098.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00098.uasset new file mode 100644 index 0000000..d3ba7ba Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00098.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00098_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00098_Sprite.uasset new file mode 100644 index 0000000..b9b26cb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00098_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00099.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00099.uasset new file mode 100644 index 0000000..4bb771d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00099.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00099_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00099_Sprite.uasset new file mode 100644 index 0000000..654f6f6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00099_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00100.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00100.uasset new file mode 100644 index 0000000..34ded70 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00100.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00100_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00100_Sprite.uasset new file mode 100644 index 0000000..d39cf83 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/坐标测量/坐标测量_00100_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/FB_PolygonMeasure.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/FB_PolygonMeasure.uasset new file mode 100644 index 0000000..9246c07 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/FB_PolygonMeasure.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00000.uasset new file mode 100644 index 0000000..b190272 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00000_Sprite.uasset new file mode 100644 index 0000000..5e91935 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00001.uasset new file mode 100644 index 0000000..cbdbb7e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00001_Sprite.uasset new file mode 100644 index 0000000..8d77630 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00002.uasset new file mode 100644 index 0000000..cd76e6c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00002_Sprite.uasset new file mode 100644 index 0000000..47670fb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00003.uasset new file mode 100644 index 0000000..3277916 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00003_Sprite.uasset new file mode 100644 index 0000000..2963251 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00004.uasset new file mode 100644 index 0000000..b5d231b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00004_Sprite.uasset new file mode 100644 index 0000000..7037e83 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00005.uasset new file mode 100644 index 0000000..c7fb3e7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00005_Sprite.uasset new file mode 100644 index 0000000..8c0ec23 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00006.uasset new file mode 100644 index 0000000..0f5b09e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00006_Sprite.uasset new file mode 100644 index 0000000..806e45e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00007.uasset new file mode 100644 index 0000000..0a238e9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00007_Sprite.uasset new file mode 100644 index 0000000..7aea698 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00008.uasset new file mode 100644 index 0000000..e5543b6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00008_Sprite.uasset new file mode 100644 index 0000000..905cf43 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00009.uasset new file mode 100644 index 0000000..0d70f6e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00009_Sprite.uasset new file mode 100644 index 0000000..a53df56 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00010.uasset new file mode 100644 index 0000000..d128a6f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00010_Sprite.uasset new file mode 100644 index 0000000..0c0bd5f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00011.uasset new file mode 100644 index 0000000..fc07fb6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00011_Sprite.uasset new file mode 100644 index 0000000..b1c2020 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00012.uasset new file mode 100644 index 0000000..4ce82ff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00012_Sprite.uasset new file mode 100644 index 0000000..3c17e9c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00013.uasset new file mode 100644 index 0000000..f87b694 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00013_Sprite.uasset new file mode 100644 index 0000000..ec313bb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00014.uasset new file mode 100644 index 0000000..a47218e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00014_Sprite.uasset new file mode 100644 index 0000000..9f4d2f0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00015.uasset new file mode 100644 index 0000000..5ef02ce Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00015_Sprite.uasset new file mode 100644 index 0000000..88adc6c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00016.uasset new file mode 100644 index 0000000..a9b090c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00016_Sprite.uasset new file mode 100644 index 0000000..cd2a63d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00017.uasset new file mode 100644 index 0000000..b95fc17 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00017_Sprite.uasset new file mode 100644 index 0000000..f99d582 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00018.uasset new file mode 100644 index 0000000..01ae5e8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00018_Sprite.uasset new file mode 100644 index 0000000..6fc423a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00019.uasset new file mode 100644 index 0000000..df32dbf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00019_Sprite.uasset new file mode 100644 index 0000000..8539b08 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00020.uasset new file mode 100644 index 0000000..58c5d09 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00020_Sprite.uasset new file mode 100644 index 0000000..6e316b2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00021.uasset new file mode 100644 index 0000000..4fe29c0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00021_Sprite.uasset new file mode 100644 index 0000000..2faf40a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00022.uasset new file mode 100644 index 0000000..8c1ad26 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00022_Sprite.uasset new file mode 100644 index 0000000..e3be879 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00023.uasset new file mode 100644 index 0000000..2a57577 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00023_Sprite.uasset new file mode 100644 index 0000000..bc0a68e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00024.uasset new file mode 100644 index 0000000..198ac99 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00024_Sprite.uasset new file mode 100644 index 0000000..d407119 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00025.uasset new file mode 100644 index 0000000..36960e5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00025_Sprite.uasset new file mode 100644 index 0000000..e756319 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00026.uasset new file mode 100644 index 0000000..51ebb8f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00026_Sprite.uasset new file mode 100644 index 0000000..028e795 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00027.uasset new file mode 100644 index 0000000..732bfa4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00027_Sprite.uasset new file mode 100644 index 0000000..25c50b9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00028.uasset new file mode 100644 index 0000000..fb25831 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00028_Sprite.uasset new file mode 100644 index 0000000..056c079 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00029.uasset new file mode 100644 index 0000000..3f963aa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00029_Sprite.uasset new file mode 100644 index 0000000..908588f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00030.uasset new file mode 100644 index 0000000..5d1e1cd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00030_Sprite.uasset new file mode 100644 index 0000000..c22cd63 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00031.uasset new file mode 100644 index 0000000..e09010b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00031_Sprite.uasset new file mode 100644 index 0000000..90f2e77 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00032.uasset new file mode 100644 index 0000000..15ddc27 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00032_Sprite.uasset new file mode 100644 index 0000000..e480b1d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00033.uasset new file mode 100644 index 0000000..73a1774 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00033_Sprite.uasset new file mode 100644 index 0000000..6d60b90 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00034.uasset new file mode 100644 index 0000000..00f6e7b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00034_Sprite.uasset new file mode 100644 index 0000000..0ee0647 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00035.uasset new file mode 100644 index 0000000..3b22fd0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00035_Sprite.uasset new file mode 100644 index 0000000..aac7273 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00036.uasset new file mode 100644 index 0000000..b781683 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00036_Sprite.uasset new file mode 100644 index 0000000..c24cd2c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00037.uasset new file mode 100644 index 0000000..ef63d60 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00037_Sprite.uasset new file mode 100644 index 0000000..b2ce8c7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00038.uasset new file mode 100644 index 0000000..0b648ef Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00038_Sprite.uasset new file mode 100644 index 0000000..295c379 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00039.uasset new file mode 100644 index 0000000..082d973 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00039_Sprite.uasset new file mode 100644 index 0000000..a438694 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00040.uasset new file mode 100644 index 0000000..de9b584 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00040_Sprite.uasset new file mode 100644 index 0000000..8c58c97 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00041.uasset new file mode 100644 index 0000000..1459b30 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00041_Sprite.uasset new file mode 100644 index 0000000..1c36847 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00042.uasset new file mode 100644 index 0000000..f131bba Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00042_Sprite.uasset new file mode 100644 index 0000000..ad3535a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00043.uasset new file mode 100644 index 0000000..8628e84 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00043_Sprite.uasset new file mode 100644 index 0000000..6c304c7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00044.uasset new file mode 100644 index 0000000..aa6dde4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00044_Sprite.uasset new file mode 100644 index 0000000..0b80857 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00045.uasset new file mode 100644 index 0000000..917960a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00045_Sprite.uasset new file mode 100644 index 0000000..21c189e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00046.uasset new file mode 100644 index 0000000..a49ae4e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00046_Sprite.uasset new file mode 100644 index 0000000..1ffbd80 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00047.uasset new file mode 100644 index 0000000..abd8d09 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00047_Sprite.uasset new file mode 100644 index 0000000..61a6874 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00048.uasset new file mode 100644 index 0000000..0a5e553 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00048_Sprite.uasset new file mode 100644 index 0000000..1743c5b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00049.uasset new file mode 100644 index 0000000..ca1230a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00049_Sprite.uasset new file mode 100644 index 0000000..ab49410 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/投影面积/投影面积_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/FB_AngleMeasure.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/FB_AngleMeasure.uasset new file mode 100644 index 0000000..b100e96 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/FB_AngleMeasure.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00000.uasset new file mode 100644 index 0000000..3e04edf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00000_Sprite.uasset new file mode 100644 index 0000000..12ddbe6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00001.uasset new file mode 100644 index 0000000..3173afe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00001_Sprite.uasset new file mode 100644 index 0000000..0879e46 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00002.uasset new file mode 100644 index 0000000..158c458 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00002_Sprite.uasset new file mode 100644 index 0000000..f372686 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00003.uasset new file mode 100644 index 0000000..1201525 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00003_Sprite.uasset new file mode 100644 index 0000000..6f7ac70 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00004.uasset new file mode 100644 index 0000000..3f68f5a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00004_Sprite.uasset new file mode 100644 index 0000000..6a9fe5e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00005.uasset new file mode 100644 index 0000000..277db34 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00005_Sprite.uasset new file mode 100644 index 0000000..00cae8c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00006.uasset new file mode 100644 index 0000000..a03fcc0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00006_Sprite.uasset new file mode 100644 index 0000000..50018bd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00007.uasset new file mode 100644 index 0000000..3526ec9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00007_Sprite.uasset new file mode 100644 index 0000000..1860b15 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00008.uasset new file mode 100644 index 0000000..a6a1130 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00008_Sprite.uasset new file mode 100644 index 0000000..fb6ca96 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00009.uasset new file mode 100644 index 0000000..e461722 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00009_Sprite.uasset new file mode 100644 index 0000000..541c718 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00010.uasset new file mode 100644 index 0000000..c3abf63 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00010_Sprite.uasset new file mode 100644 index 0000000..9229042 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00011.uasset new file mode 100644 index 0000000..387c09e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00011_Sprite.uasset new file mode 100644 index 0000000..a729f45 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00012.uasset new file mode 100644 index 0000000..6b774cc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00012_Sprite.uasset new file mode 100644 index 0000000..10a15db Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00013.uasset new file mode 100644 index 0000000..da35684 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00013_Sprite.uasset new file mode 100644 index 0000000..1ff86f9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00014.uasset new file mode 100644 index 0000000..ffe9aee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00014_Sprite.uasset new file mode 100644 index 0000000..0140074 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00015.uasset new file mode 100644 index 0000000..94aaa30 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00015_Sprite.uasset new file mode 100644 index 0000000..261a631 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00016.uasset new file mode 100644 index 0000000..3b4d461 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00016_Sprite.uasset new file mode 100644 index 0000000..0775930 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00017.uasset new file mode 100644 index 0000000..1f120e2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00017_Sprite.uasset new file mode 100644 index 0000000..51f1c74 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00018.uasset new file mode 100644 index 0000000..a4dff0b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00018_Sprite.uasset new file mode 100644 index 0000000..80b8c87 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00019.uasset new file mode 100644 index 0000000..564f976 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00019_Sprite.uasset new file mode 100644 index 0000000..de0307d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00020.uasset new file mode 100644 index 0000000..b1105d6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00020_Sprite.uasset new file mode 100644 index 0000000..a239e59 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00021.uasset new file mode 100644 index 0000000..0a84f6b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00021_Sprite.uasset new file mode 100644 index 0000000..2627756 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00022.uasset new file mode 100644 index 0000000..0ef8a11 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00022_Sprite.uasset new file mode 100644 index 0000000..9ff3300 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00023.uasset new file mode 100644 index 0000000..bcd8b9a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00023_Sprite.uasset new file mode 100644 index 0000000..aa4ea91 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00024.uasset new file mode 100644 index 0000000..0e3eb45 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00024_Sprite.uasset new file mode 100644 index 0000000..25b4a50 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00025.uasset new file mode 100644 index 0000000..431f322 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00025_Sprite.uasset new file mode 100644 index 0000000..19b67cf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00026.uasset new file mode 100644 index 0000000..dcadc96 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00026_Sprite.uasset new file mode 100644 index 0000000..c2aeab5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00027.uasset new file mode 100644 index 0000000..dfa2c62 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00027_Sprite.uasset new file mode 100644 index 0000000..f95a8c6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00028.uasset new file mode 100644 index 0000000..01169d4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00028_Sprite.uasset new file mode 100644 index 0000000..f232dba Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00029.uasset new file mode 100644 index 0000000..4c4e49e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00029_Sprite.uasset new file mode 100644 index 0000000..fc02eb6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00030.uasset new file mode 100644 index 0000000..a7cc59a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00030_Sprite.uasset new file mode 100644 index 0000000..2b55ce5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00031.uasset new file mode 100644 index 0000000..9d467d9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00031_Sprite.uasset new file mode 100644 index 0000000..60fe925 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00032.uasset new file mode 100644 index 0000000..1cf27a3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00032_Sprite.uasset new file mode 100644 index 0000000..7993791 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00033.uasset new file mode 100644 index 0000000..36e1a13 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00033_Sprite.uasset new file mode 100644 index 0000000..5bf931e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00034.uasset new file mode 100644 index 0000000..db5a12d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00034_Sprite.uasset new file mode 100644 index 0000000..85f4f1e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00035.uasset new file mode 100644 index 0000000..788176d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00035_Sprite.uasset new file mode 100644 index 0000000..8f19658 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00036.uasset new file mode 100644 index 0000000..8118d7a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00036_Sprite.uasset new file mode 100644 index 0000000..cb9b378 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00037.uasset new file mode 100644 index 0000000..4a030c2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00037_Sprite.uasset new file mode 100644 index 0000000..435d4b2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00038.uasset new file mode 100644 index 0000000..31d441b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00038_Sprite.uasset new file mode 100644 index 0000000..70b5101 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00039.uasset new file mode 100644 index 0000000..bd61cae Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00039_Sprite.uasset new file mode 100644 index 0000000..2cd77aa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00040.uasset new file mode 100644 index 0000000..726af65 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00040_Sprite.uasset new file mode 100644 index 0000000..32d0022 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00041.uasset new file mode 100644 index 0000000..947f7b9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00041_Sprite.uasset new file mode 100644 index 0000000..cde5c2c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00042.uasset new file mode 100644 index 0000000..1e3ddc9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00042_Sprite.uasset new file mode 100644 index 0000000..a0b4c7c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00043.uasset new file mode 100644 index 0000000..0c16b9c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00043_Sprite.uasset new file mode 100644 index 0000000..6aa7db5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00044.uasset new file mode 100644 index 0000000..e6e75c4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00044_Sprite.uasset new file mode 100644 index 0000000..8ff0b39 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00045.uasset new file mode 100644 index 0000000..5679718 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00045_Sprite.uasset new file mode 100644 index 0000000..29519c6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00046.uasset new file mode 100644 index 0000000..fc1b4c8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00046_Sprite.uasset new file mode 100644 index 0000000..0b3fc3f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00047.uasset new file mode 100644 index 0000000..3c5bcc6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00047_Sprite.uasset new file mode 100644 index 0000000..c03255e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00048.uasset new file mode 100644 index 0000000..3a329b8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00048_Sprite.uasset new file mode 100644 index 0000000..16a6b9d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00049.uasset new file mode 100644 index 0000000..d8cd0b4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00049_Sprite.uasset new file mode 100644 index 0000000..28d6c61 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00050.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00050.uasset new file mode 100644 index 0000000..34d2db3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00050.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00050_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00050_Sprite.uasset new file mode 100644 index 0000000..01d1b72 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00050_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00051.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00051.uasset new file mode 100644 index 0000000..e2414ff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00051.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00051_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00051_Sprite.uasset new file mode 100644 index 0000000..353d5e1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00051_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00052.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00052.uasset new file mode 100644 index 0000000..6fa32c7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00052.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00052_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00052_Sprite.uasset new file mode 100644 index 0000000..687ae59 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00052_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00053.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00053.uasset new file mode 100644 index 0000000..4e298f1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00053.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00053_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00053_Sprite.uasset new file mode 100644 index 0000000..99c675e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00053_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00054.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00054.uasset new file mode 100644 index 0000000..dea15b5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00054.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00054_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00054_Sprite.uasset new file mode 100644 index 0000000..a364642 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00054_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00055.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00055.uasset new file mode 100644 index 0000000..b3bbd16 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00055.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00055_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00055_Sprite.uasset new file mode 100644 index 0000000..51eb351 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00055_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00056.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00056.uasset new file mode 100644 index 0000000..c271bb1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00056.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00056_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00056_Sprite.uasset new file mode 100644 index 0000000..8fea9b3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00056_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00057.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00057.uasset new file mode 100644 index 0000000..c2eb1a7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00057.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00057_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00057_Sprite.uasset new file mode 100644 index 0000000..49d1e00 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00057_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00058.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00058.uasset new file mode 100644 index 0000000..05c0b6c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00058.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00058_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00058_Sprite.uasset new file mode 100644 index 0000000..90ad5f2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00058_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00059.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00059.uasset new file mode 100644 index 0000000..7b27be9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00059.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00059_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00059_Sprite.uasset new file mode 100644 index 0000000..b862e62 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00059_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00060.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00060.uasset new file mode 100644 index 0000000..abe03b8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00060.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00060_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00060_Sprite.uasset new file mode 100644 index 0000000..960e428 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00060_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00061.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00061.uasset new file mode 100644 index 0000000..9cbc399 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00061.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00061_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00061_Sprite.uasset new file mode 100644 index 0000000..b26904b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00061_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00062.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00062.uasset new file mode 100644 index 0000000..fc99e08 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00062.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00062_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00062_Sprite.uasset new file mode 100644 index 0000000..2b78c90 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00062_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00063.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00063.uasset new file mode 100644 index 0000000..d225979 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00063.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00063_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00063_Sprite.uasset new file mode 100644 index 0000000..23eb4fe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00063_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00064.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00064.uasset new file mode 100644 index 0000000..20e0ecb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00064.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00064_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00064_Sprite.uasset new file mode 100644 index 0000000..348acb9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00064_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00065.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00065.uasset new file mode 100644 index 0000000..a501b5e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00065.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00065_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00065_Sprite.uasset new file mode 100644 index 0000000..9c3a29d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00065_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00066.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00066.uasset new file mode 100644 index 0000000..3bae231 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00066.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00066_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00066_Sprite.uasset new file mode 100644 index 0000000..070ca41 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00066_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00067.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00067.uasset new file mode 100644 index 0000000..d20d70e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00067.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00067_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00067_Sprite.uasset new file mode 100644 index 0000000..21d6cf9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00067_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00068.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00068.uasset new file mode 100644 index 0000000..9f751cf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00068.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00068_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00068_Sprite.uasset new file mode 100644 index 0000000..0a0df0d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00068_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00069.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00069.uasset new file mode 100644 index 0000000..1a51952 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00069.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00069_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00069_Sprite.uasset new file mode 100644 index 0000000..683e35f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00069_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00070.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00070.uasset new file mode 100644 index 0000000..50efad8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00070.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00070_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00070_Sprite.uasset new file mode 100644 index 0000000..ebef55e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00070_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00071.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00071.uasset new file mode 100644 index 0000000..de709cc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00071.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00071_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00071_Sprite.uasset new file mode 100644 index 0000000..0610e97 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00071_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00072.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00072.uasset new file mode 100644 index 0000000..d08c822 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00072.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00072_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00072_Sprite.uasset new file mode 100644 index 0000000..8d2fa58 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00072_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00073.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00073.uasset new file mode 100644 index 0000000..99e4c74 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00073.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00073_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00073_Sprite.uasset new file mode 100644 index 0000000..da00dad Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00073_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00074.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00074.uasset new file mode 100644 index 0000000..fa509be Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00074.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00074_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00074_Sprite.uasset new file mode 100644 index 0000000..09307a8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00074_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00075.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00075.uasset new file mode 100644 index 0000000..a767c45 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00075.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00075_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00075_Sprite.uasset new file mode 100644 index 0000000..5df5f1a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00075_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00076.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00076.uasset new file mode 100644 index 0000000..ce496a0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00076.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00076_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00076_Sprite.uasset new file mode 100644 index 0000000..319adb3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00076_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00077.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00077.uasset new file mode 100644 index 0000000..aff902c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00077.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00077_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00077_Sprite.uasset new file mode 100644 index 0000000..b1b086e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00077_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00078.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00078.uasset new file mode 100644 index 0000000..5932bfc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00078.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00078_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00078_Sprite.uasset new file mode 100644 index 0000000..57e994b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00078_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00079.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00079.uasset new file mode 100644 index 0000000..b48be2d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00079.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00079_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00079_Sprite.uasset new file mode 100644 index 0000000..5287842 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00079_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00080.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00080.uasset new file mode 100644 index 0000000..d252e14 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00080.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00080_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00080_Sprite.uasset new file mode 100644 index 0000000..5eb9817 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00080_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00081.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00081.uasset new file mode 100644 index 0000000..2e38e9d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00081.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00081_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00081_Sprite.uasset new file mode 100644 index 0000000..a637a45 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00081_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00082.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00082.uasset new file mode 100644 index 0000000..ae2ecd5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00082.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00082_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00082_Sprite.uasset new file mode 100644 index 0000000..6363640 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00082_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00083.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00083.uasset new file mode 100644 index 0000000..514ba6c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00083.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00083_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00083_Sprite.uasset new file mode 100644 index 0000000..94bf5f7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00083_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00084.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00084.uasset new file mode 100644 index 0000000..c44763c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00084.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00084_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00084_Sprite.uasset new file mode 100644 index 0000000..7346d25 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00084_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00085.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00085.uasset new file mode 100644 index 0000000..be56449 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00085.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00085_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00085_Sprite.uasset new file mode 100644 index 0000000..bdf3f42 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00085_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00086.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00086.uasset new file mode 100644 index 0000000..c56c940 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00086.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00086_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00086_Sprite.uasset new file mode 100644 index 0000000..50f400e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00086_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00087.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00087.uasset new file mode 100644 index 0000000..f82f368 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00087.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00087_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00087_Sprite.uasset new file mode 100644 index 0000000..2a1e9fc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00087_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00088.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00088.uasset new file mode 100644 index 0000000..c3b4dc0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00088.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00088_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00088_Sprite.uasset new file mode 100644 index 0000000..aa2b382 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00088_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00089.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00089.uasset new file mode 100644 index 0000000..e408226 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00089.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00089_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00089_Sprite.uasset new file mode 100644 index 0000000..db13483 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00089_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00090.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00090.uasset new file mode 100644 index 0000000..04ba543 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00090.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00090_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00090_Sprite.uasset new file mode 100644 index 0000000..96de2e2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00090_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00091.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00091.uasset new file mode 100644 index 0000000..a75a5c5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00091.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00091_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00091_Sprite.uasset new file mode 100644 index 0000000..8f954a0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00091_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00092.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00092.uasset new file mode 100644 index 0000000..0611e62 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00092.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00092_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00092_Sprite.uasset new file mode 100644 index 0000000..cd4206c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00092_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00093.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00093.uasset new file mode 100644 index 0000000..a450c08 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00093.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00093_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00093_Sprite.uasset new file mode 100644 index 0000000..a8f4fad Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00093_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00094.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00094.uasset new file mode 100644 index 0000000..618bf85 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00094.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00094_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00094_Sprite.uasset new file mode 100644 index 0000000..948bf08 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00094_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00095.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00095.uasset new file mode 100644 index 0000000..a762eb5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00095.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00095_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00095_Sprite.uasset new file mode 100644 index 0000000..37a8b0c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00095_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00096.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00096.uasset new file mode 100644 index 0000000..d73c306 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00096.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00096_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00096_Sprite.uasset new file mode 100644 index 0000000..7caa05c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00096_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00097.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00097.uasset new file mode 100644 index 0000000..3140339 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00097.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00097_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00097_Sprite.uasset new file mode 100644 index 0000000..8592f6e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00097_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00098.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00098.uasset new file mode 100644 index 0000000..07fb18d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00098.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00098_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00098_Sprite.uasset new file mode 100644 index 0000000..0c61c93 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00098_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00099.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00099.uasset new file mode 100644 index 0000000..48cf959 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00099.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00099_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00099_Sprite.uasset new file mode 100644 index 0000000..5b1e11c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/方位角/方位角_00099_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/FB_DistanceMeasure.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/FB_DistanceMeasure.uasset new file mode 100644 index 0000000..1676d53 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/FB_DistanceMeasure.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00000.uasset new file mode 100644 index 0000000..e7c9b6e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00000_Sprite.uasset new file mode 100644 index 0000000..6c52ea7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00001.uasset new file mode 100644 index 0000000..f58234b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00001_Sprite.uasset new file mode 100644 index 0000000..d850694 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00002.uasset new file mode 100644 index 0000000..99211a6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00002_Sprite.uasset new file mode 100644 index 0000000..de2cd58 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00003.uasset new file mode 100644 index 0000000..29ae002 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00003_Sprite.uasset new file mode 100644 index 0000000..284fd01 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00004.uasset new file mode 100644 index 0000000..826365d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00004_Sprite.uasset new file mode 100644 index 0000000..e3fd84d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00005.uasset new file mode 100644 index 0000000..ec25437 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00005_Sprite.uasset new file mode 100644 index 0000000..e6d0c90 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00006.uasset new file mode 100644 index 0000000..804779d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00006_Sprite.uasset new file mode 100644 index 0000000..6124164 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00007.uasset new file mode 100644 index 0000000..8dac431 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00007_Sprite.uasset new file mode 100644 index 0000000..e5adda8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00008.uasset new file mode 100644 index 0000000..98707ad Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00008_Sprite.uasset new file mode 100644 index 0000000..5ca5dfb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00009.uasset new file mode 100644 index 0000000..6b377dc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00009_Sprite.uasset new file mode 100644 index 0000000..2dba58f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00010.uasset new file mode 100644 index 0000000..d29add1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00010_Sprite.uasset new file mode 100644 index 0000000..73979c8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00011.uasset new file mode 100644 index 0000000..4d6100a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00011_Sprite.uasset new file mode 100644 index 0000000..ab042e8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00012.uasset new file mode 100644 index 0000000..28301e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00012_Sprite.uasset new file mode 100644 index 0000000..15a0d7b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00013.uasset new file mode 100644 index 0000000..807fe94 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00013_Sprite.uasset new file mode 100644 index 0000000..9e698c6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00014.uasset new file mode 100644 index 0000000..8cdd08b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00014_Sprite.uasset new file mode 100644 index 0000000..7da28ae Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00015.uasset new file mode 100644 index 0000000..d97e7cb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00015_Sprite.uasset new file mode 100644 index 0000000..01ca4e6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00016.uasset new file mode 100644 index 0000000..0c12030 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00016_Sprite.uasset new file mode 100644 index 0000000..ba0c6a9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00017.uasset new file mode 100644 index 0000000..66454ad Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00017_Sprite.uasset new file mode 100644 index 0000000..94e0a64 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00018.uasset new file mode 100644 index 0000000..d8b3640 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00018_Sprite.uasset new file mode 100644 index 0000000..a875e03 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00019.uasset new file mode 100644 index 0000000..23874c5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00019_Sprite.uasset new file mode 100644 index 0000000..8b9e3d0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00020.uasset new file mode 100644 index 0000000..bad84f1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00020_Sprite.uasset new file mode 100644 index 0000000..3ebb5d8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00021.uasset new file mode 100644 index 0000000..10a8ef6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00021_Sprite.uasset new file mode 100644 index 0000000..aa672a4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00022.uasset new file mode 100644 index 0000000..36081dc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00022_Sprite.uasset new file mode 100644 index 0000000..76e7efb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00023.uasset new file mode 100644 index 0000000..e3e51a7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00023_Sprite.uasset new file mode 100644 index 0000000..c521757 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00024.uasset new file mode 100644 index 0000000..a583615 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00024_Sprite.uasset new file mode 100644 index 0000000..458cc1a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00025.uasset new file mode 100644 index 0000000..80a2a51 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00025_Sprite.uasset new file mode 100644 index 0000000..35b80b4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00026.uasset new file mode 100644 index 0000000..75268fc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00026_Sprite.uasset new file mode 100644 index 0000000..631447b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00027.uasset new file mode 100644 index 0000000..16e05bf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00027_Sprite.uasset new file mode 100644 index 0000000..b127141 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00028.uasset new file mode 100644 index 0000000..9146b1b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00028_Sprite.uasset new file mode 100644 index 0000000..431ac7c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00029.uasset new file mode 100644 index 0000000..3ccd257 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00029_Sprite.uasset new file mode 100644 index 0000000..51a693d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00030.uasset new file mode 100644 index 0000000..d739ca6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00030_Sprite.uasset new file mode 100644 index 0000000..3e05bba Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00031.uasset new file mode 100644 index 0000000..48020da Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00031_Sprite.uasset new file mode 100644 index 0000000..435e708 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00032.uasset new file mode 100644 index 0000000..b45a27d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00032_Sprite.uasset new file mode 100644 index 0000000..55cc363 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00033.uasset new file mode 100644 index 0000000..9be188c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00033_Sprite.uasset new file mode 100644 index 0000000..17e20ea Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00034.uasset new file mode 100644 index 0000000..29a1666 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00034_Sprite.uasset new file mode 100644 index 0000000..a56adfc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00035.uasset new file mode 100644 index 0000000..fb96c78 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00035_Sprite.uasset new file mode 100644 index 0000000..df0cf83 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00036.uasset new file mode 100644 index 0000000..9d763e3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00036_Sprite.uasset new file mode 100644 index 0000000..cab6ee5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00037.uasset new file mode 100644 index 0000000..c43d745 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00037_Sprite.uasset new file mode 100644 index 0000000..9a18fee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00038.uasset new file mode 100644 index 0000000..fba1a0c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00038_Sprite.uasset new file mode 100644 index 0000000..53b2311 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00039.uasset new file mode 100644 index 0000000..aa174f1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00039_Sprite.uasset new file mode 100644 index 0000000..a810ab5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00040.uasset new file mode 100644 index 0000000..6f5a02f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00040_Sprite.uasset new file mode 100644 index 0000000..e35bad9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00041.uasset new file mode 100644 index 0000000..df6a3c9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00041_Sprite.uasset new file mode 100644 index 0000000..eacee80 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00042.uasset new file mode 100644 index 0000000..53e7184 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00042_Sprite.uasset new file mode 100644 index 0000000..8566c7f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00043.uasset new file mode 100644 index 0000000..0c3ec3d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00043_Sprite.uasset new file mode 100644 index 0000000..a1583c5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00044.uasset new file mode 100644 index 0000000..cb27d15 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00044_Sprite.uasset new file mode 100644 index 0000000..ae422dd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00045.uasset new file mode 100644 index 0000000..bb396e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00045_Sprite.uasset new file mode 100644 index 0000000..4de5d32 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00046.uasset new file mode 100644 index 0000000..f2e86fe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00046_Sprite.uasset new file mode 100644 index 0000000..27cbe9f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00047.uasset new file mode 100644 index 0000000..c92c881 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00047_Sprite.uasset new file mode 100644 index 0000000..a011aba Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00048.uasset new file mode 100644 index 0000000..e930709 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00048_Sprite.uasset new file mode 100644 index 0000000..7854388 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00049.uasset new file mode 100644 index 0000000..3f81a93 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00049_Sprite.uasset new file mode 100644 index 0000000..94fe6cc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/贴地距离/贴地距离_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/FB_HeightMeasure.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/FB_HeightMeasure.uasset new file mode 100644 index 0000000..8219f66 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/FB_HeightMeasure.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00000.uasset new file mode 100644 index 0000000..c4ff636 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00000_Sprite.uasset new file mode 100644 index 0000000..943f54c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00001.uasset new file mode 100644 index 0000000..b731347 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00001_Sprite.uasset new file mode 100644 index 0000000..aeef156 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00002.uasset new file mode 100644 index 0000000..70edf10 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00002_Sprite.uasset new file mode 100644 index 0000000..696a45b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00003.uasset new file mode 100644 index 0000000..ef2fa7a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00003_Sprite.uasset new file mode 100644 index 0000000..ec62926 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00004.uasset new file mode 100644 index 0000000..3d9aa63 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00004_Sprite.uasset new file mode 100644 index 0000000..8e0fec9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00005.uasset new file mode 100644 index 0000000..b13b5fa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00005_Sprite.uasset new file mode 100644 index 0000000..1241b24 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00006.uasset new file mode 100644 index 0000000..72ae94f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00006_Sprite.uasset new file mode 100644 index 0000000..23e3807 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00007.uasset new file mode 100644 index 0000000..fc4c0bd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00007_Sprite.uasset new file mode 100644 index 0000000..cf2d7fd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00008.uasset new file mode 100644 index 0000000..ecfa7a8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00008_Sprite.uasset new file mode 100644 index 0000000..769d508 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00009.uasset new file mode 100644 index 0000000..f823990 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00009_Sprite.uasset new file mode 100644 index 0000000..67d90bf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00010.uasset new file mode 100644 index 0000000..1c2c30e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00010_Sprite.uasset new file mode 100644 index 0000000..c21fffb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00011.uasset new file mode 100644 index 0000000..4a7d962 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00011_Sprite.uasset new file mode 100644 index 0000000..90c4871 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00012.uasset new file mode 100644 index 0000000..7a0b398 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00012_Sprite.uasset new file mode 100644 index 0000000..ab13950 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00013.uasset new file mode 100644 index 0000000..ed3a3cf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00013_Sprite.uasset new file mode 100644 index 0000000..058d224 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00014.uasset new file mode 100644 index 0000000..3778b3a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00014_Sprite.uasset new file mode 100644 index 0000000..ec5a27e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00015.uasset new file mode 100644 index 0000000..dc5adf0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00015_Sprite.uasset new file mode 100644 index 0000000..c071c03 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00016.uasset new file mode 100644 index 0000000..8f7ccb3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00016_Sprite.uasset new file mode 100644 index 0000000..fe04d7e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00017.uasset new file mode 100644 index 0000000..d0093a0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00017_Sprite.uasset new file mode 100644 index 0000000..ea992fe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00018.uasset new file mode 100644 index 0000000..bc95f11 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00018_Sprite.uasset new file mode 100644 index 0000000..2596102 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00019.uasset new file mode 100644 index 0000000..a8a19a2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00019_Sprite.uasset new file mode 100644 index 0000000..48f4d39 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00020.uasset new file mode 100644 index 0000000..a72c240 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00020_Sprite.uasset new file mode 100644 index 0000000..123f983 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00021.uasset new file mode 100644 index 0000000..a510de1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00021_Sprite.uasset new file mode 100644 index 0000000..4a5f44f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00022.uasset new file mode 100644 index 0000000..1530055 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00022_Sprite.uasset new file mode 100644 index 0000000..6b2cdf1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00023.uasset new file mode 100644 index 0000000..017569a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00023_Sprite.uasset new file mode 100644 index 0000000..b68ccf6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00024.uasset new file mode 100644 index 0000000..a725ccc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00024_Sprite.uasset new file mode 100644 index 0000000..b6133b9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00025.uasset new file mode 100644 index 0000000..9fc8f0e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00025_Sprite.uasset new file mode 100644 index 0000000..8d78bca Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00026.uasset new file mode 100644 index 0000000..ee81829 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00026_Sprite.uasset new file mode 100644 index 0000000..4efca3c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00027.uasset new file mode 100644 index 0000000..47dadf3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00027_Sprite.uasset new file mode 100644 index 0000000..217266f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00028.uasset new file mode 100644 index 0000000..88ad950 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00028_Sprite.uasset new file mode 100644 index 0000000..5c3983d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00029.uasset new file mode 100644 index 0000000..0293a3d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00029_Sprite.uasset new file mode 100644 index 0000000..b5aea48 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00030.uasset new file mode 100644 index 0000000..f94d9e6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00030_Sprite.uasset new file mode 100644 index 0000000..87aa8ae Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00031.uasset new file mode 100644 index 0000000..abf3537 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00031_Sprite.uasset new file mode 100644 index 0000000..852f74d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00032.uasset new file mode 100644 index 0000000..1bbbc74 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00032_Sprite.uasset new file mode 100644 index 0000000..bb63ddb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00033.uasset new file mode 100644 index 0000000..9de7b24 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00033_Sprite.uasset new file mode 100644 index 0000000..cf52e9b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00034.uasset new file mode 100644 index 0000000..808f8a6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00034_Sprite.uasset new file mode 100644 index 0000000..bb74742 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00035.uasset new file mode 100644 index 0000000..4961d06 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00035_Sprite.uasset new file mode 100644 index 0000000..0faca40 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00036.uasset new file mode 100644 index 0000000..db896ad Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00036_Sprite.uasset new file mode 100644 index 0000000..9e56a15 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00037.uasset new file mode 100644 index 0000000..d1bbb9c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00037_Sprite.uasset new file mode 100644 index 0000000..69fe21b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00038.uasset new file mode 100644 index 0000000..f4d2a64 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00038_Sprite.uasset new file mode 100644 index 0000000..ac338e5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00039.uasset new file mode 100644 index 0000000..2321e6f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00039_Sprite.uasset new file mode 100644 index 0000000..49e2579 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00040.uasset new file mode 100644 index 0000000..a4739ef Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00040_Sprite.uasset new file mode 100644 index 0000000..5b86900 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00041.uasset new file mode 100644 index 0000000..690eb69 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00041_Sprite.uasset new file mode 100644 index 0000000..bbbe013 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00042.uasset new file mode 100644 index 0000000..e3aa81b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00042_Sprite.uasset new file mode 100644 index 0000000..962e7bd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00043.uasset new file mode 100644 index 0000000..e73d48a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00043_Sprite.uasset new file mode 100644 index 0000000..c9b0ae1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00044.uasset new file mode 100644 index 0000000..0ba3e63 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00044_Sprite.uasset new file mode 100644 index 0000000..e403f1f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00045.uasset new file mode 100644 index 0000000..844df09 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00045_Sprite.uasset new file mode 100644 index 0000000..081d0ad Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00046.uasset new file mode 100644 index 0000000..65b69e6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00046_Sprite.uasset new file mode 100644 index 0000000..3f4de72 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00047.uasset new file mode 100644 index 0000000..9a81950 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00047_Sprite.uasset new file mode 100644 index 0000000..f9accb0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00048.uasset new file mode 100644 index 0000000..b1a5679 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00048_Sprite.uasset new file mode 100644 index 0000000..0c43b33 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00049.uasset new file mode 100644 index 0000000..ea6849a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00049_Sprite.uasset new file mode 100644 index 0000000..3ae2b14 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/测量/高度测量/高度测量_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙.uasset new file mode 100644 index 0000000..e85957c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00000.uasset new file mode 100644 index 0000000..e092ea4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00000_Sprite.uasset new file mode 100644 index 0000000..9a1aaa8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00001.uasset new file mode 100644 index 0000000..203ae6e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00001_Sprite.uasset new file mode 100644 index 0000000..290ca8f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00002.uasset new file mode 100644 index 0000000..fcec1b8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00002_Sprite.uasset new file mode 100644 index 0000000..96b00cd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00003.uasset new file mode 100644 index 0000000..b38cd00 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00003_Sprite.uasset new file mode 100644 index 0000000..57e42b2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00004.uasset new file mode 100644 index 0000000..e4907b5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00004_Sprite.uasset new file mode 100644 index 0000000..f7b7079 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00005.uasset new file mode 100644 index 0000000..8b3db73 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00005_Sprite.uasset new file mode 100644 index 0000000..af2ab57 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00006.uasset new file mode 100644 index 0000000..26a605b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00006_Sprite.uasset new file mode 100644 index 0000000..8bded89 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00007.uasset new file mode 100644 index 0000000..d8b6202 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00007_Sprite.uasset new file mode 100644 index 0000000..faab27d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00008.uasset new file mode 100644 index 0000000..6a037c8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00008_Sprite.uasset new file mode 100644 index 0000000..18c6aa0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00009.uasset new file mode 100644 index 0000000..8d79bc7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00009_Sprite.uasset new file mode 100644 index 0000000..f21e3c6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00010.uasset new file mode 100644 index 0000000..97f9411 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00010_Sprite.uasset new file mode 100644 index 0000000..6d6ce47 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00011.uasset new file mode 100644 index 0000000..0010728 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00011_Sprite.uasset new file mode 100644 index 0000000..2eef31d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00012.uasset new file mode 100644 index 0000000..5124397 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00012_Sprite.uasset new file mode 100644 index 0000000..bd20e1d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00013.uasset new file mode 100644 index 0000000..32b1b5e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00013_Sprite.uasset new file mode 100644 index 0000000..eaeee8e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00014.uasset new file mode 100644 index 0000000..9c8c48f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00014_Sprite.uasset new file mode 100644 index 0000000..d09b4cd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00015.uasset new file mode 100644 index 0000000..d54f9f6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00015_Sprite.uasset new file mode 100644 index 0000000..c2fa61b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00016.uasset new file mode 100644 index 0000000..400a1f1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00016_Sprite.uasset new file mode 100644 index 0000000..0c7a9a3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00017.uasset new file mode 100644 index 0000000..771c632 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00017_Sprite.uasset new file mode 100644 index 0000000..ec3149c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00018.uasset new file mode 100644 index 0000000..b69ec9d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00018_Sprite.uasset new file mode 100644 index 0000000..f840951 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00019.uasset new file mode 100644 index 0000000..76c75e1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00019_Sprite.uasset new file mode 100644 index 0000000..5e55272 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00020.uasset new file mode 100644 index 0000000..90ea279 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00020_Sprite.uasset new file mode 100644 index 0000000..e9fe83a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00021.uasset new file mode 100644 index 0000000..4702b1d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00021_Sprite.uasset new file mode 100644 index 0000000..be99787 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00022.uasset new file mode 100644 index 0000000..50b8549 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00022_Sprite.uasset new file mode 100644 index 0000000..62e8724 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00023.uasset new file mode 100644 index 0000000..fbb7429 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00023_Sprite.uasset new file mode 100644 index 0000000..151ef21 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00024.uasset new file mode 100644 index 0000000..8d43955 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00024_Sprite.uasset new file mode 100644 index 0000000..3a922db Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00025.uasset new file mode 100644 index 0000000..9f8b777 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00025_Sprite.uasset new file mode 100644 index 0000000..6883208 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00026.uasset new file mode 100644 index 0000000..be29f03 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00026_Sprite.uasset new file mode 100644 index 0000000..1b87ca5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00027.uasset new file mode 100644 index 0000000..aabf5a9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00027_Sprite.uasset new file mode 100644 index 0000000..99a65b0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00028.uasset new file mode 100644 index 0000000..b8e4063 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00028_Sprite.uasset new file mode 100644 index 0000000..489c772 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00029.uasset new file mode 100644 index 0000000..86fd95d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00029_Sprite.uasset new file mode 100644 index 0000000..a34fd9b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00030.uasset new file mode 100644 index 0000000..60bbe20 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00030_Sprite.uasset new file mode 100644 index 0000000..a0031a8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00031.uasset new file mode 100644 index 0000000..6adf30c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00031_Sprite.uasset new file mode 100644 index 0000000..252b79f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00032.uasset new file mode 100644 index 0000000..18e8f0d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00032_Sprite.uasset new file mode 100644 index 0000000..ad6c533 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00033.uasset new file mode 100644 index 0000000..0184347 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00033_Sprite.uasset new file mode 100644 index 0000000..5658ed7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00034.uasset new file mode 100644 index 0000000..4c8f6b1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00034_Sprite.uasset new file mode 100644 index 0000000..e20b714 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00035.uasset new file mode 100644 index 0000000..df3da4c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00035_Sprite.uasset new file mode 100644 index 0000000..67f20af Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00036.uasset new file mode 100644 index 0000000..a4fb0cb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00036_Sprite.uasset new file mode 100644 index 0000000..6ac1676 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00037.uasset new file mode 100644 index 0000000..beaeefb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00037_Sprite.uasset new file mode 100644 index 0000000..74639af Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00038.uasset new file mode 100644 index 0000000..fdd8f0a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00038_Sprite.uasset new file mode 100644 index 0000000..2c06e90 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00039.uasset new file mode 100644 index 0000000..978c370 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00039_Sprite.uasset new file mode 100644 index 0000000..a7ddfb2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00040.uasset new file mode 100644 index 0000000..ca4c8c9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00040_Sprite.uasset new file mode 100644 index 0000000..be763fd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00041.uasset new file mode 100644 index 0000000..1b2e1f6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00041_Sprite.uasset new file mode 100644 index 0000000..20be566 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00042.uasset new file mode 100644 index 0000000..c0b9974 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00042_Sprite.uasset new file mode 100644 index 0000000..9195bb1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00043.uasset new file mode 100644 index 0000000..42f5f6d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00043_Sprite.uasset new file mode 100644 index 0000000..34c19a6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00044.uasset new file mode 100644 index 0000000..21ba957 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00044_Sprite.uasset new file mode 100644 index 0000000..b583aa3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00045.uasset new file mode 100644 index 0000000..e2c45bd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00045_Sprite.uasset new file mode 100644 index 0000000..7d17d24 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00046.uasset new file mode 100644 index 0000000..d2bfb67 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00046_Sprite.uasset new file mode 100644 index 0000000..8b82ae7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00047.uasset new file mode 100644 index 0000000..df7592b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00047_Sprite.uasset new file mode 100644 index 0000000..b718986 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00048.uasset new file mode 100644 index 0000000..1993077 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00048_Sprite.uasset new file mode 100644 index 0000000..4d2e5ee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/实体墙/实体墙_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰.uasset new file mode 100644 index 0000000..106a496 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00000.uasset new file mode 100644 index 0000000..7d45d17 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00000_Sprite.uasset new file mode 100644 index 0000000..363041f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00001.uasset new file mode 100644 index 0000000..a0b3543 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00001_Sprite.uasset new file mode 100644 index 0000000..d2bcc30 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00002.uasset new file mode 100644 index 0000000..5e25b26 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00002_Sprite.uasset new file mode 100644 index 0000000..cc6351b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00003.uasset new file mode 100644 index 0000000..caf542b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00003_Sprite.uasset new file mode 100644 index 0000000..a62b1cf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00004.uasset new file mode 100644 index 0000000..15eab12 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00004_Sprite.uasset new file mode 100644 index 0000000..ac75489 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00005.uasset new file mode 100644 index 0000000..531aa72 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00005_Sprite.uasset new file mode 100644 index 0000000..bca4f23 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00006.uasset new file mode 100644 index 0000000..983667b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00006_Sprite.uasset new file mode 100644 index 0000000..5651b2f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00007.uasset new file mode 100644 index 0000000..8694a5f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00007_Sprite.uasset new file mode 100644 index 0000000..c5abd70 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00008.uasset new file mode 100644 index 0000000..01b750d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00008_Sprite.uasset new file mode 100644 index 0000000..39c39ee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00009.uasset new file mode 100644 index 0000000..913f558 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00009_Sprite.uasset new file mode 100644 index 0000000..051f531 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00010.uasset new file mode 100644 index 0000000..314e3b2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00010_Sprite.uasset new file mode 100644 index 0000000..36dd2d3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00011.uasset new file mode 100644 index 0000000..86b49eb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00011_Sprite.uasset new file mode 100644 index 0000000..f6eab23 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00012.uasset new file mode 100644 index 0000000..344ba17 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00012_Sprite.uasset new file mode 100644 index 0000000..eb39a1e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00013.uasset new file mode 100644 index 0000000..2ecc529 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00013_Sprite.uasset new file mode 100644 index 0000000..bc1420e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00014.uasset new file mode 100644 index 0000000..3f5e690 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00014_Sprite.uasset new file mode 100644 index 0000000..c8ab7bb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00015.uasset new file mode 100644 index 0000000..d9de85d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00015_Sprite.uasset new file mode 100644 index 0000000..cf2c1ac Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00016.uasset new file mode 100644 index 0000000..eb5fdc4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00016_Sprite.uasset new file mode 100644 index 0000000..e08d4d5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00017.uasset new file mode 100644 index 0000000..fe61c29 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00017_Sprite.uasset new file mode 100644 index 0000000..4aacda8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00018.uasset new file mode 100644 index 0000000..745f583 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00018_Sprite.uasset new file mode 100644 index 0000000..57c48f9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00019.uasset new file mode 100644 index 0000000..aab2f31 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00019_Sprite.uasset new file mode 100644 index 0000000..f61f960 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00020.uasset new file mode 100644 index 0000000..9191e47 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00020_Sprite.uasset new file mode 100644 index 0000000..4483b66 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00021.uasset new file mode 100644 index 0000000..2255c7a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00021_Sprite.uasset new file mode 100644 index 0000000..26f17b8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00022.uasset new file mode 100644 index 0000000..158ca7c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00022_Sprite.uasset new file mode 100644 index 0000000..664b5ff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00023.uasset new file mode 100644 index 0000000..e39c9f7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00023_Sprite.uasset new file mode 100644 index 0000000..18172a1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00024.uasset new file mode 100644 index 0000000..adb6c19 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00024_Sprite.uasset new file mode 100644 index 0000000..f2c3c31 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00025.uasset new file mode 100644 index 0000000..aab1372 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00025_Sprite.uasset new file mode 100644 index 0000000..33d9e57 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00026.uasset new file mode 100644 index 0000000..817a730 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00026_Sprite.uasset new file mode 100644 index 0000000..2780f5f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00027.uasset new file mode 100644 index 0000000..ceb871b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00027_Sprite.uasset new file mode 100644 index 0000000..7e4ad04 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00028.uasset new file mode 100644 index 0000000..1e60fc4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00028_Sprite.uasset new file mode 100644 index 0000000..f5b29b4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00029.uasset new file mode 100644 index 0000000..d8edb39 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00029_Sprite.uasset new file mode 100644 index 0000000..a17b8b0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00030.uasset new file mode 100644 index 0000000..0c6d997 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00030_Sprite.uasset new file mode 100644 index 0000000..24b802b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00031.uasset new file mode 100644 index 0000000..6aa1aae Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00031_Sprite.uasset new file mode 100644 index 0000000..4777cdc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00032.uasset new file mode 100644 index 0000000..ebae2d6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00032_Sprite.uasset new file mode 100644 index 0000000..9bc647e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00033.uasset new file mode 100644 index 0000000..4bfdbbe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00033_Sprite.uasset new file mode 100644 index 0000000..cc484d3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00034.uasset new file mode 100644 index 0000000..d456964 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00034_Sprite.uasset new file mode 100644 index 0000000..3bc818b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00035.uasset new file mode 100644 index 0000000..917efa8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00035_Sprite.uasset new file mode 100644 index 0000000..bf6bf1e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00036.uasset new file mode 100644 index 0000000..6fdabcd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00036_Sprite.uasset new file mode 100644 index 0000000..014bad9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00037.uasset new file mode 100644 index 0000000..4c5a8d5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00037_Sprite.uasset new file mode 100644 index 0000000..c0e00fa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00038.uasset new file mode 100644 index 0000000..3891578 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00038_Sprite.uasset new file mode 100644 index 0000000..2b68841 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00039.uasset new file mode 100644 index 0000000..859dc81 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00039_Sprite.uasset new file mode 100644 index 0000000..45907ed Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00040.uasset new file mode 100644 index 0000000..9a0d58c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00040_Sprite.uasset new file mode 100644 index 0000000..6076d88 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00041.uasset new file mode 100644 index 0000000..61d2459 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00041_Sprite.uasset new file mode 100644 index 0000000..b05b45d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00042.uasset new file mode 100644 index 0000000..0d36499 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00042_Sprite.uasset new file mode 100644 index 0000000..02c7a89 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00043.uasset new file mode 100644 index 0000000..b7aa7a6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00043_Sprite.uasset new file mode 100644 index 0000000..c77e7d8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00044.uasset new file mode 100644 index 0000000..0666945 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00044_Sprite.uasset new file mode 100644 index 0000000..2e7e196 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00045.uasset new file mode 100644 index 0000000..4767ed1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00045_Sprite.uasset new file mode 100644 index 0000000..8b52009 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00046.uasset new file mode 100644 index 0000000..17c0a8e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00046_Sprite.uasset new file mode 100644 index 0000000..712176e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00047.uasset new file mode 100644 index 0000000..093ece7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00047_Sprite.uasset new file mode 100644 index 0000000..8ba0634 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00048.uasset new file mode 100644 index 0000000..539119a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00048_Sprite.uasset new file mode 100644 index 0000000..94f673e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00049.uasset new file mode 100644 index 0000000..9bc854d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00049_Sprite.uasset new file mode 100644 index 0000000..dd9f11a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/扩散火焰/扩散火焰_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水.uasset new file mode 100644 index 0000000..fd1ac20 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00000.uasset new file mode 100644 index 0000000..c6912e5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00000_Sprite.uasset new file mode 100644 index 0000000..034e178 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00001.uasset new file mode 100644 index 0000000..ddae4b5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00001_Sprite.uasset new file mode 100644 index 0000000..49ff919 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00002.uasset new file mode 100644 index 0000000..c69520e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00002_Sprite.uasset new file mode 100644 index 0000000..2212657 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00003.uasset new file mode 100644 index 0000000..1719a5c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00003_Sprite.uasset new file mode 100644 index 0000000..f23e7c3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00004.uasset new file mode 100644 index 0000000..a3c20e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00004_Sprite.uasset new file mode 100644 index 0000000..efe113e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00005.uasset new file mode 100644 index 0000000..bde9d1a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00005_Sprite.uasset new file mode 100644 index 0000000..594870c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00006.uasset new file mode 100644 index 0000000..158c069 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00006_Sprite.uasset new file mode 100644 index 0000000..459f514 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00007.uasset new file mode 100644 index 0000000..0c11f4c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00007_Sprite.uasset new file mode 100644 index 0000000..5485117 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00008.uasset new file mode 100644 index 0000000..53465c7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00008_Sprite.uasset new file mode 100644 index 0000000..71ff977 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00009.uasset new file mode 100644 index 0000000..0b4fc60 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00009_Sprite.uasset new file mode 100644 index 0000000..52e0c9c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00010.uasset new file mode 100644 index 0000000..4e07d9d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00010_Sprite.uasset new file mode 100644 index 0000000..24dfc65 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00011.uasset new file mode 100644 index 0000000..da463fe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00011_Sprite.uasset new file mode 100644 index 0000000..86becb3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00012.uasset new file mode 100644 index 0000000..1c292bb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00012_Sprite.uasset new file mode 100644 index 0000000..7564606 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00013.uasset new file mode 100644 index 0000000..c314536 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00013_Sprite.uasset new file mode 100644 index 0000000..1817a12 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00014.uasset new file mode 100644 index 0000000..50fcef3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00014_Sprite.uasset new file mode 100644 index 0000000..e94e7a1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00015.uasset new file mode 100644 index 0000000..927723f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00015_Sprite.uasset new file mode 100644 index 0000000..a254c4b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00016.uasset new file mode 100644 index 0000000..6c78238 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00016_Sprite.uasset new file mode 100644 index 0000000..8d7e600 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00017.uasset new file mode 100644 index 0000000..97780f2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00017_Sprite.uasset new file mode 100644 index 0000000..c681be4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00018.uasset new file mode 100644 index 0000000..f3de202 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00018_Sprite.uasset new file mode 100644 index 0000000..7d8eceb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00019.uasset new file mode 100644 index 0000000..50aeb34 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00019_Sprite.uasset new file mode 100644 index 0000000..cf524cc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00020.uasset new file mode 100644 index 0000000..b4edc43 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00020_Sprite.uasset new file mode 100644 index 0000000..193d543 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00021.uasset new file mode 100644 index 0000000..fc7b5a2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00021_Sprite.uasset new file mode 100644 index 0000000..90945f2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00022.uasset new file mode 100644 index 0000000..fa3a57b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00022_Sprite.uasset new file mode 100644 index 0000000..f6da778 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00023.uasset new file mode 100644 index 0000000..0b194fb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00023_Sprite.uasset new file mode 100644 index 0000000..4351744 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00024.uasset new file mode 100644 index 0000000..2ab33d5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00024_Sprite.uasset new file mode 100644 index 0000000..7d8a271 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00025.uasset new file mode 100644 index 0000000..c164528 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00025_Sprite.uasset new file mode 100644 index 0000000..561d187 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00026.uasset new file mode 100644 index 0000000..eec46c5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00026_Sprite.uasset new file mode 100644 index 0000000..03e349c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00027.uasset new file mode 100644 index 0000000..7cc6224 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00027_Sprite.uasset new file mode 100644 index 0000000..2457ab9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00028.uasset new file mode 100644 index 0000000..e0a852d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00028_Sprite.uasset new file mode 100644 index 0000000..06def62 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00029.uasset new file mode 100644 index 0000000..0a351f6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00029_Sprite.uasset new file mode 100644 index 0000000..47e23b3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00030.uasset new file mode 100644 index 0000000..abd0481 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00030_Sprite.uasset new file mode 100644 index 0000000..c52c620 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00031.uasset new file mode 100644 index 0000000..b7af4c9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00031_Sprite.uasset new file mode 100644 index 0000000..00c0e97 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00032.uasset new file mode 100644 index 0000000..8b7c323 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00032_Sprite.uasset new file mode 100644 index 0000000..b510fe8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00033.uasset new file mode 100644 index 0000000..4c4f01c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00033_Sprite.uasset new file mode 100644 index 0000000..f91a0c6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00034.uasset new file mode 100644 index 0000000..baa37b9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00034_Sprite.uasset new file mode 100644 index 0000000..29d9f53 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00035.uasset new file mode 100644 index 0000000..6f7c6e7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00035_Sprite.uasset new file mode 100644 index 0000000..336cb60 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00036.uasset new file mode 100644 index 0000000..204919e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00036_Sprite.uasset new file mode 100644 index 0000000..a7d60c7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00037.uasset new file mode 100644 index 0000000..0442240 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00037_Sprite.uasset new file mode 100644 index 0000000..5073161 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00038.uasset new file mode 100644 index 0000000..b1bf534 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00038_Sprite.uasset new file mode 100644 index 0000000..2d68a4d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00039.uasset new file mode 100644 index 0000000..94dce8b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00039_Sprite.uasset new file mode 100644 index 0000000..6a67b24 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00040.uasset new file mode 100644 index 0000000..e7e1d64 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00040_Sprite.uasset new file mode 100644 index 0000000..e64fae1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00041.uasset new file mode 100644 index 0000000..47e8257 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00041_Sprite.uasset new file mode 100644 index 0000000..2e73b1e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00042.uasset new file mode 100644 index 0000000..63e8a02 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00042_Sprite.uasset new file mode 100644 index 0000000..809f289 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00043.uasset new file mode 100644 index 0000000..2643638 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00043_Sprite.uasset new file mode 100644 index 0000000..d536448 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00044.uasset new file mode 100644 index 0000000..b651ad5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00044_Sprite.uasset new file mode 100644 index 0000000..52140e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00045.uasset new file mode 100644 index 0000000..7a6d561 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00045_Sprite.uasset new file mode 100644 index 0000000..739042d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00046.uasset new file mode 100644 index 0000000..b2fed69 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00046_Sprite.uasset new file mode 100644 index 0000000..659b704 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00047.uasset new file mode 100644 index 0000000..76288a4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00047_Sprite.uasset new file mode 100644 index 0000000..bb81796 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00048.uasset new file mode 100644 index 0000000..fa1bf6b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00048_Sprite.uasset new file mode 100644 index 0000000..b50e94b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00049.uasset new file mode 100644 index 0000000..a1cf1de Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00049_Sprite.uasset new file mode 100644 index 0000000..aa98d8a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00050.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00050.uasset new file mode 100644 index 0000000..45bee35 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00050.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00050_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00050_Sprite.uasset new file mode 100644 index 0000000..497ed17 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水/水_00050_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/FB_PolygonWater.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/FB_PolygonWater.uasset new file mode 100644 index 0000000..b92cd63 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/FB_PolygonWater.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00000.uasset new file mode 100644 index 0000000..662eb08 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00000_Sprite.uasset new file mode 100644 index 0000000..260018d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00001.uasset new file mode 100644 index 0000000..2434114 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00001_Sprite.uasset new file mode 100644 index 0000000..fe81283 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00002.uasset new file mode 100644 index 0000000..19c1993 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00002_Sprite.uasset new file mode 100644 index 0000000..9c301c9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00003.uasset new file mode 100644 index 0000000..bb11951 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00003_Sprite.uasset new file mode 100644 index 0000000..1475ffb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00004.uasset new file mode 100644 index 0000000..8d9b243 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00004_Sprite.uasset new file mode 100644 index 0000000..0995fb6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00005.uasset new file mode 100644 index 0000000..97d6838 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00005_Sprite.uasset new file mode 100644 index 0000000..cdea131 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00006.uasset new file mode 100644 index 0000000..1fa3272 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00006_Sprite.uasset new file mode 100644 index 0000000..548e04b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00007.uasset new file mode 100644 index 0000000..7d81b7e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00007_Sprite.uasset new file mode 100644 index 0000000..61e4e13 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00008.uasset new file mode 100644 index 0000000..a750e8f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00008_Sprite.uasset new file mode 100644 index 0000000..7b9ee7b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00009.uasset new file mode 100644 index 0000000..f43d789 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00009_Sprite.uasset new file mode 100644 index 0000000..e476984 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00010.uasset new file mode 100644 index 0000000..0a8052e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00010_Sprite.uasset new file mode 100644 index 0000000..43f49d7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00011.uasset new file mode 100644 index 0000000..d1f8b57 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00011_Sprite.uasset new file mode 100644 index 0000000..f63d6cb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00012.uasset new file mode 100644 index 0000000..ecded2e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00012_Sprite.uasset new file mode 100644 index 0000000..29ccc2c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00013.uasset new file mode 100644 index 0000000..f75a8e9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00013_Sprite.uasset new file mode 100644 index 0000000..2e8c642 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00014.uasset new file mode 100644 index 0000000..a998b43 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00014_Sprite.uasset new file mode 100644 index 0000000..2744308 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00015.uasset new file mode 100644 index 0000000..c5c3dc9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00015_Sprite.uasset new file mode 100644 index 0000000..448d9da Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00016.uasset new file mode 100644 index 0000000..2e64cff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00016_Sprite.uasset new file mode 100644 index 0000000..a6dddbb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00017.uasset new file mode 100644 index 0000000..7cd3720 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00017_Sprite.uasset new file mode 100644 index 0000000..849c16a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00018.uasset new file mode 100644 index 0000000..a9ef720 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00018_Sprite.uasset new file mode 100644 index 0000000..f0bd8db Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00019.uasset new file mode 100644 index 0000000..a46a519 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00019_Sprite.uasset new file mode 100644 index 0000000..2bb04f2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00020.uasset new file mode 100644 index 0000000..5f19385 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00020_Sprite.uasset new file mode 100644 index 0000000..e013630 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00021.uasset new file mode 100644 index 0000000..deceba0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00021_Sprite.uasset new file mode 100644 index 0000000..72e9d51 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00022.uasset new file mode 100644 index 0000000..16426ac Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00022_Sprite.uasset new file mode 100644 index 0000000..a24a42d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00023.uasset new file mode 100644 index 0000000..5d8e9ba Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00023_Sprite.uasset new file mode 100644 index 0000000..ab124bb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00024.uasset new file mode 100644 index 0000000..b694b28 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00024_Sprite.uasset new file mode 100644 index 0000000..ec57c33 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00025.uasset new file mode 100644 index 0000000..92eb877 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00025_Sprite.uasset new file mode 100644 index 0000000..ce71eac Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00026.uasset new file mode 100644 index 0000000..e495106 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00026_Sprite.uasset new file mode 100644 index 0000000..236a8f2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00027.uasset new file mode 100644 index 0000000..baa1b13 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00027_Sprite.uasset new file mode 100644 index 0000000..d9f9afa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00028.uasset new file mode 100644 index 0000000..8692618 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00028_Sprite.uasset new file mode 100644 index 0000000..aac21a2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00029.uasset new file mode 100644 index 0000000..3f6b239 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00029_Sprite.uasset new file mode 100644 index 0000000..d8ef740 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00030.uasset new file mode 100644 index 0000000..7c8ab31 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00030_Sprite.uasset new file mode 100644 index 0000000..3655145 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00031.uasset new file mode 100644 index 0000000..4efb684 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00031_Sprite.uasset new file mode 100644 index 0000000..734ff19 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00032.uasset new file mode 100644 index 0000000..ab8a0c2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00032_Sprite.uasset new file mode 100644 index 0000000..3beccb9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00033.uasset new file mode 100644 index 0000000..2776cd6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00033_Sprite.uasset new file mode 100644 index 0000000..819ab3a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00034.uasset new file mode 100644 index 0000000..bff2f94 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00034_Sprite.uasset new file mode 100644 index 0000000..b89a652 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00035.uasset new file mode 100644 index 0000000..2a711e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00035_Sprite.uasset new file mode 100644 index 0000000..b99b681 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00036.uasset new file mode 100644 index 0000000..9f7b021 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00036_Sprite.uasset new file mode 100644 index 0000000..1659406 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00037.uasset new file mode 100644 index 0000000..2f25286 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00037_Sprite.uasset new file mode 100644 index 0000000..f5025bb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00038.uasset new file mode 100644 index 0000000..8b8b24b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00038_Sprite.uasset new file mode 100644 index 0000000..2ef1aba Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00039.uasset new file mode 100644 index 0000000..7d2a093 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00039_Sprite.uasset new file mode 100644 index 0000000..20e1eff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00040.uasset new file mode 100644 index 0000000..0343e76 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00040_Sprite.uasset new file mode 100644 index 0000000..4893553 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00041.uasset new file mode 100644 index 0000000..d275982 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00041_Sprite.uasset new file mode 100644 index 0000000..f247ea1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00042.uasset new file mode 100644 index 0000000..e2d47ac Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00042_Sprite.uasset new file mode 100644 index 0000000..8f20189 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00043.uasset new file mode 100644 index 0000000..74ec93c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00043_Sprite.uasset new file mode 100644 index 0000000..f4c0d27 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00044.uasset new file mode 100644 index 0000000..714b367 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00044_Sprite.uasset new file mode 100644 index 0000000..d1790dc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00045.uasset new file mode 100644 index 0000000..40f53cd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00045_Sprite.uasset new file mode 100644 index 0000000..2dd0001 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00046.uasset new file mode 100644 index 0000000..a4256a3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00046_Sprite.uasset new file mode 100644 index 0000000..06c7138 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00047.uasset new file mode 100644 index 0000000..35bd93d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00047_Sprite.uasset new file mode 100644 index 0000000..ab4c5a3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00048.uasset new file mode 100644 index 0000000..8b391cc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00048_Sprite.uasset new file mode 100644 index 0000000..98f6d8f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00049.uasset new file mode 100644 index 0000000..a8e50ad Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00049_Sprite.uasset new file mode 100644 index 0000000..5d7b60a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00050.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00050.uasset new file mode 100644 index 0000000..5bc2237 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00050.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00050_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00050_Sprite.uasset new file mode 100644 index 0000000..4c79998 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/水面/水面_00050_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/FB_PointFire.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/FB_PointFire.uasset new file mode 100644 index 0000000..2d5b6fa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/FB_PointFire.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00000.uasset new file mode 100644 index 0000000..6d6b9c7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00000_Sprite.uasset new file mode 100644 index 0000000..01d81c7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00001.uasset new file mode 100644 index 0000000..2d9725b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00001_Sprite.uasset new file mode 100644 index 0000000..b6eba48 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00002.uasset new file mode 100644 index 0000000..18a5354 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00002_Sprite.uasset new file mode 100644 index 0000000..3751101 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00003.uasset new file mode 100644 index 0000000..36417fa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00003_Sprite.uasset new file mode 100644 index 0000000..a544dae Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00004.uasset new file mode 100644 index 0000000..9ba4e9c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00004_Sprite.uasset new file mode 100644 index 0000000..90c04f8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00005.uasset new file mode 100644 index 0000000..7994f8e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00005_Sprite.uasset new file mode 100644 index 0000000..604680e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00006.uasset new file mode 100644 index 0000000..c5bcc7b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00006_Sprite.uasset new file mode 100644 index 0000000..cd074bc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00007.uasset new file mode 100644 index 0000000..699a066 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00007_Sprite.uasset new file mode 100644 index 0000000..5cce3f9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00008.uasset new file mode 100644 index 0000000..286c2dc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00008_Sprite.uasset new file mode 100644 index 0000000..f56d734 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00009.uasset new file mode 100644 index 0000000..fbf2e7a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00009_Sprite.uasset new file mode 100644 index 0000000..f4ef929 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00010.uasset new file mode 100644 index 0000000..d4d4726 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00010_Sprite.uasset new file mode 100644 index 0000000..3435354 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00011.uasset new file mode 100644 index 0000000..98bfc12 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00011_Sprite.uasset new file mode 100644 index 0000000..fe95cd6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00012.uasset new file mode 100644 index 0000000..e296754 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00012_Sprite.uasset new file mode 100644 index 0000000..181b993 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00013.uasset new file mode 100644 index 0000000..9c2dabc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00013_Sprite.uasset new file mode 100644 index 0000000..3d1d953 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00014.uasset new file mode 100644 index 0000000..4221aa5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00014_Sprite.uasset new file mode 100644 index 0000000..ee38586 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00015.uasset new file mode 100644 index 0000000..36ad82a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00015_Sprite.uasset new file mode 100644 index 0000000..9d04d1c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00016.uasset new file mode 100644 index 0000000..b333e97 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00016_Sprite.uasset new file mode 100644 index 0000000..0c19a8c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00017.uasset new file mode 100644 index 0000000..167e718 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00017_Sprite.uasset new file mode 100644 index 0000000..590c598 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00018.uasset new file mode 100644 index 0000000..098382c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00018_Sprite.uasset new file mode 100644 index 0000000..cabf5f8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00019.uasset new file mode 100644 index 0000000..49b2a79 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00019_Sprite.uasset new file mode 100644 index 0000000..2fb56de Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00020.uasset new file mode 100644 index 0000000..debaed9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00020_Sprite.uasset new file mode 100644 index 0000000..8074823 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00021.uasset new file mode 100644 index 0000000..e955f31 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00021_Sprite.uasset new file mode 100644 index 0000000..6b7ebce Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00022.uasset new file mode 100644 index 0000000..fa50e7b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00022_Sprite.uasset new file mode 100644 index 0000000..71c6c17 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00023.uasset new file mode 100644 index 0000000..dbfe301 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00023_Sprite.uasset new file mode 100644 index 0000000..39dd830 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00024.uasset new file mode 100644 index 0000000..c920811 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00024_Sprite.uasset new file mode 100644 index 0000000..1d711fb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00025.uasset new file mode 100644 index 0000000..9411ba4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00025_Sprite.uasset new file mode 100644 index 0000000..f05f896 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00026.uasset new file mode 100644 index 0000000..3fc526f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00026_Sprite.uasset new file mode 100644 index 0000000..5684509 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00027.uasset new file mode 100644 index 0000000..0630b1d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00027_Sprite.uasset new file mode 100644 index 0000000..d48afbd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00028.uasset new file mode 100644 index 0000000..1f20150 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00028_Sprite.uasset new file mode 100644 index 0000000..c4295c2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00029.uasset new file mode 100644 index 0000000..c9218f8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00029_Sprite.uasset new file mode 100644 index 0000000..4fcdc50 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00030.uasset new file mode 100644 index 0000000..214e375 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00030_Sprite.uasset new file mode 100644 index 0000000..faea94c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00031.uasset new file mode 100644 index 0000000..a5f2b08 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00031_Sprite.uasset new file mode 100644 index 0000000..50e3fa5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00032.uasset new file mode 100644 index 0000000..a8396ea Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00032_Sprite.uasset new file mode 100644 index 0000000..31c2e6b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00033.uasset new file mode 100644 index 0000000..3b6e675 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00033_Sprite.uasset new file mode 100644 index 0000000..0267413 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00034.uasset new file mode 100644 index 0000000..1874b75 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00034_Sprite.uasset new file mode 100644 index 0000000..7355087 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00035.uasset new file mode 100644 index 0000000..961b337 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00035_Sprite.uasset new file mode 100644 index 0000000..d81df21 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00036.uasset new file mode 100644 index 0000000..eed1a2c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00036_Sprite.uasset new file mode 100644 index 0000000..3b0c898 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00037.uasset new file mode 100644 index 0000000..09ac814 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00037_Sprite.uasset new file mode 100644 index 0000000..7f62199 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00038.uasset new file mode 100644 index 0000000..bd82f4b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00038_Sprite.uasset new file mode 100644 index 0000000..3f20e5c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00039.uasset new file mode 100644 index 0000000..23eefc7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00039_Sprite.uasset new file mode 100644 index 0000000..2730d64 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00040.uasset new file mode 100644 index 0000000..63d04e6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00040_Sprite.uasset new file mode 100644 index 0000000..11e08ef Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00041.uasset new file mode 100644 index 0000000..2b2c2dd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00041_Sprite.uasset new file mode 100644 index 0000000..a61e718 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00042.uasset new file mode 100644 index 0000000..3cd7c8e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00042_Sprite.uasset new file mode 100644 index 0000000..9a38102 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00043.uasset new file mode 100644 index 0000000..2159213 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00043_Sprite.uasset new file mode 100644 index 0000000..75b49ee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00044.uasset new file mode 100644 index 0000000..82781e8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00044_Sprite.uasset new file mode 100644 index 0000000..8488d7b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00045.uasset new file mode 100644 index 0000000..a159c45 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00045_Sprite.uasset new file mode 100644 index 0000000..7502c1d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00046.uasset new file mode 100644 index 0000000..2e1a78b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00046_Sprite.uasset new file mode 100644 index 0000000..8b675ec Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00047.uasset new file mode 100644 index 0000000..9d7cc5d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00047_Sprite.uasset new file mode 100644 index 0000000..746245c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00048.uasset new file mode 100644 index 0000000..5f55173 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00048_Sprite.uasset new file mode 100644 index 0000000..4d7eab0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00049.uasset new file mode 100644 index 0000000..3445ddc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00049_Sprite.uasset new file mode 100644 index 0000000..0037f9f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00050.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00050.uasset new file mode 100644 index 0000000..0efec0e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00050.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00050_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00050_Sprite.uasset new file mode 100644 index 0000000..1326a22 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/火焰/火焰_00050_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/FB_Explosion.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/FB_Explosion.uasset new file mode 100644 index 0000000..463653f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/FB_Explosion.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00000.uasset new file mode 100644 index 0000000..e26edde Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00000_Sprite.uasset new file mode 100644 index 0000000..00dc68c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00001.uasset new file mode 100644 index 0000000..f2c85ff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00001_Sprite.uasset new file mode 100644 index 0000000..91e535a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00002.uasset new file mode 100644 index 0000000..8a67cb5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00002_Sprite.uasset new file mode 100644 index 0000000..b3c7fa0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00003.uasset new file mode 100644 index 0000000..02d6a6b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00003_Sprite.uasset new file mode 100644 index 0000000..e3ecab8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00004.uasset new file mode 100644 index 0000000..a4eca66 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00004_Sprite.uasset new file mode 100644 index 0000000..2e72c59 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00005.uasset new file mode 100644 index 0000000..1d3b5b2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00005_Sprite.uasset new file mode 100644 index 0000000..ed03896 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00006.uasset new file mode 100644 index 0000000..c02b9df Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00006_Sprite.uasset new file mode 100644 index 0000000..2c09d5a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00007.uasset new file mode 100644 index 0000000..26cfa85 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00007_Sprite.uasset new file mode 100644 index 0000000..97a62d4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00008.uasset new file mode 100644 index 0000000..01f8ae3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00008_Sprite.uasset new file mode 100644 index 0000000..810df3a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00009.uasset new file mode 100644 index 0000000..f750367 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00009_Sprite.uasset new file mode 100644 index 0000000..6dc319f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00010.uasset new file mode 100644 index 0000000..fdbd3cc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00010_Sprite.uasset new file mode 100644 index 0000000..567f878 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00011.uasset new file mode 100644 index 0000000..f56e92b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00011_Sprite.uasset new file mode 100644 index 0000000..f504cbb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00012.uasset new file mode 100644 index 0000000..4c4ab55 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00012_Sprite.uasset new file mode 100644 index 0000000..3dba552 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00013.uasset new file mode 100644 index 0000000..8290412 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00013_Sprite.uasset new file mode 100644 index 0000000..56f5fcd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00014.uasset new file mode 100644 index 0000000..d4d592d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00014_Sprite.uasset new file mode 100644 index 0000000..e59ce5a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00015.uasset new file mode 100644 index 0000000..259d0d5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00015_Sprite.uasset new file mode 100644 index 0000000..9c2959c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00016.uasset new file mode 100644 index 0000000..4bda588 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00016_Sprite.uasset new file mode 100644 index 0000000..46515ed Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00017.uasset new file mode 100644 index 0000000..4a15b86 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00017_Sprite.uasset new file mode 100644 index 0000000..1f4c535 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00018.uasset new file mode 100644 index 0000000..d79d684 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00018_Sprite.uasset new file mode 100644 index 0000000..0ba99e8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00019.uasset new file mode 100644 index 0000000..4f16939 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00019_Sprite.uasset new file mode 100644 index 0000000..0a1c299 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00020.uasset new file mode 100644 index 0000000..dd41019 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00020_Sprite.uasset new file mode 100644 index 0000000..23df061 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00021.uasset new file mode 100644 index 0000000..3f5f733 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00021_Sprite.uasset new file mode 100644 index 0000000..4cdfa4c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00022.uasset new file mode 100644 index 0000000..70a490b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00022_Sprite.uasset new file mode 100644 index 0000000..1732d1e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00023.uasset new file mode 100644 index 0000000..2c8ff9e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00023_Sprite.uasset new file mode 100644 index 0000000..119d216 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00024.uasset new file mode 100644 index 0000000..7931d08 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00024_Sprite.uasset new file mode 100644 index 0000000..402d1dd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00025.uasset new file mode 100644 index 0000000..d8d95a0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00025_Sprite.uasset new file mode 100644 index 0000000..ca2e9e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00026.uasset new file mode 100644 index 0000000..42dbd74 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00026_Sprite.uasset new file mode 100644 index 0000000..668613d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00027.uasset new file mode 100644 index 0000000..6446fcb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00027_Sprite.uasset new file mode 100644 index 0000000..68d4869 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00028.uasset new file mode 100644 index 0000000..70df328 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00028_Sprite.uasset new file mode 100644 index 0000000..88217ee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00029.uasset new file mode 100644 index 0000000..5df74ce Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00029_Sprite.uasset new file mode 100644 index 0000000..0add4e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00030.uasset new file mode 100644 index 0000000..83ad51a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00030_Sprite.uasset new file mode 100644 index 0000000..71d1736 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00031.uasset new file mode 100644 index 0000000..2242e10 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00031_Sprite.uasset new file mode 100644 index 0000000..3dac885 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00032.uasset new file mode 100644 index 0000000..4cf1cdf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00032_Sprite.uasset new file mode 100644 index 0000000..2ccd222 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00033.uasset new file mode 100644 index 0000000..e2c4ecd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00033_Sprite.uasset new file mode 100644 index 0000000..8562cf0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00034.uasset new file mode 100644 index 0000000..1c09930 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00034_Sprite.uasset new file mode 100644 index 0000000..2bad3d6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00035.uasset new file mode 100644 index 0000000..ab6ef68 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00035_Sprite.uasset new file mode 100644 index 0000000..973b209 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00036.uasset new file mode 100644 index 0000000..f500c6a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00036_Sprite.uasset new file mode 100644 index 0000000..99543cc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00037.uasset new file mode 100644 index 0000000..b82b301 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00037_Sprite.uasset new file mode 100644 index 0000000..7d1769d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00038.uasset new file mode 100644 index 0000000..885bdfe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00038_Sprite.uasset new file mode 100644 index 0000000..932780a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00039.uasset new file mode 100644 index 0000000..8abef68 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00039_Sprite.uasset new file mode 100644 index 0000000..798ef44 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00040.uasset new file mode 100644 index 0000000..4dae60e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00040_Sprite.uasset new file mode 100644 index 0000000..0a5adcb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00041.uasset new file mode 100644 index 0000000..8ebd916 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00041_Sprite.uasset new file mode 100644 index 0000000..db478a7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00042.uasset new file mode 100644 index 0000000..080dc3f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00042_Sprite.uasset new file mode 100644 index 0000000..472ba6b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00043.uasset new file mode 100644 index 0000000..b755a7d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00043_Sprite.uasset new file mode 100644 index 0000000..94f88b5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00044.uasset new file mode 100644 index 0000000..4991114 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00044_Sprite.uasset new file mode 100644 index 0000000..024724c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00045.uasset new file mode 100644 index 0000000..fe72f18 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00045_Sprite.uasset new file mode 100644 index 0000000..7902e03 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00046.uasset new file mode 100644 index 0000000..a5db9f2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00046_Sprite.uasset new file mode 100644 index 0000000..3b3b02b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00047.uasset new file mode 100644 index 0000000..1f6e79b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00047_Sprite.uasset new file mode 100644 index 0000000..998287b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00048.uasset new file mode 100644 index 0000000..6091294 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00048_Sprite.uasset new file mode 100644 index 0000000..03c4db7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00049.uasset new file mode 100644 index 0000000..ae5eee5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00049_Sprite.uasset new file mode 100644 index 0000000..10c8e0e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00050.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00050.uasset new file mode 100644 index 0000000..bd8c1a4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00050.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00050_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00050_Sprite.uasset new file mode 100644 index 0000000..094a122 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/爆炸/爆炸_00050_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/FB_EffectWall.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/FB_EffectWall.uasset new file mode 100644 index 0000000..801adb5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/FB_EffectWall.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00000.uasset new file mode 100644 index 0000000..1d38daa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00000_Sprite.uasset new file mode 100644 index 0000000..4c4367b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00001.uasset new file mode 100644 index 0000000..9193ab0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00001_Sprite.uasset new file mode 100644 index 0000000..743242e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00002.uasset new file mode 100644 index 0000000..1ebbeb6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00002_Sprite.uasset new file mode 100644 index 0000000..79db9ef Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00003.uasset new file mode 100644 index 0000000..1c40b07 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00003_Sprite.uasset new file mode 100644 index 0000000..adfcd69 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00004.uasset new file mode 100644 index 0000000..bfaacc9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00004_Sprite.uasset new file mode 100644 index 0000000..da7c79b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00005.uasset new file mode 100644 index 0000000..75dacb4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00005_Sprite.uasset new file mode 100644 index 0000000..c830c05 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00006.uasset new file mode 100644 index 0000000..3b8d95f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00006_Sprite.uasset new file mode 100644 index 0000000..cdce2b2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00007.uasset new file mode 100644 index 0000000..1f6ffae Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00007_Sprite.uasset new file mode 100644 index 0000000..97eefe8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00008.uasset new file mode 100644 index 0000000..d70ad21 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00008_Sprite.uasset new file mode 100644 index 0000000..e7b6374 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00009.uasset new file mode 100644 index 0000000..c76ed67 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00009_Sprite.uasset new file mode 100644 index 0000000..71ad435 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00010.uasset new file mode 100644 index 0000000..3bf164b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00010_Sprite.uasset new file mode 100644 index 0000000..fa5d933 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00011.uasset new file mode 100644 index 0000000..581cd8f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00011_Sprite.uasset new file mode 100644 index 0000000..a6027b1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00012.uasset new file mode 100644 index 0000000..26b7ba3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00012_Sprite.uasset new file mode 100644 index 0000000..339924c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00013.uasset new file mode 100644 index 0000000..c7a78ff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00013_Sprite.uasset new file mode 100644 index 0000000..dd84209 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00014.uasset new file mode 100644 index 0000000..3af5214 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00014_Sprite.uasset new file mode 100644 index 0000000..55f2472 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00015.uasset new file mode 100644 index 0000000..38a56a0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00015_Sprite.uasset new file mode 100644 index 0000000..4c5bb23 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00016.uasset new file mode 100644 index 0000000..0930023 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00016_Sprite.uasset new file mode 100644 index 0000000..4a5af5d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00017.uasset new file mode 100644 index 0000000..f5d3cd2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00017_Sprite.uasset new file mode 100644 index 0000000..4347c19 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00018.uasset new file mode 100644 index 0000000..b2d0a96 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00018_Sprite.uasset new file mode 100644 index 0000000..8f561ce Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00019.uasset new file mode 100644 index 0000000..598fb17 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00019_Sprite.uasset new file mode 100644 index 0000000..177a568 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00020.uasset new file mode 100644 index 0000000..b57eaeb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00020_Sprite.uasset new file mode 100644 index 0000000..468dcce Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00021.uasset new file mode 100644 index 0000000..815f627 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00021_Sprite.uasset new file mode 100644 index 0000000..af3a477 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00022.uasset new file mode 100644 index 0000000..08ee142 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00022_Sprite.uasset new file mode 100644 index 0000000..878c805 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00023.uasset new file mode 100644 index 0000000..1986e19 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00023_Sprite.uasset new file mode 100644 index 0000000..de75388 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00024.uasset new file mode 100644 index 0000000..70ed0a2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00024_Sprite.uasset new file mode 100644 index 0000000..8c8f77a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00025.uasset new file mode 100644 index 0000000..8c923b0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00025_Sprite.uasset new file mode 100644 index 0000000..c71072d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00026.uasset new file mode 100644 index 0000000..942a080 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00026_Sprite.uasset new file mode 100644 index 0000000..9e05d3e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00027.uasset new file mode 100644 index 0000000..2f26cbf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00027_Sprite.uasset new file mode 100644 index 0000000..22d0d37 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00028.uasset new file mode 100644 index 0000000..2469ddc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00028_Sprite.uasset new file mode 100644 index 0000000..e627306 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00029.uasset new file mode 100644 index 0000000..e2c0e13 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00029_Sprite.uasset new file mode 100644 index 0000000..e1659e2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00030.uasset new file mode 100644 index 0000000..266ee28 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00030_Sprite.uasset new file mode 100644 index 0000000..a9fd145 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00031.uasset new file mode 100644 index 0000000..29d750a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00031_Sprite.uasset new file mode 100644 index 0000000..af143dc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00032.uasset new file mode 100644 index 0000000..95d504a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00032_Sprite.uasset new file mode 100644 index 0000000..f55e778 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00033.uasset new file mode 100644 index 0000000..84ce1b1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00033_Sprite.uasset new file mode 100644 index 0000000..c5129ce Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00034.uasset new file mode 100644 index 0000000..77809e6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00034_Sprite.uasset new file mode 100644 index 0000000..c6b03fc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00035.uasset new file mode 100644 index 0000000..276e68a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00035_Sprite.uasset new file mode 100644 index 0000000..9929b79 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00036.uasset new file mode 100644 index 0000000..199f7c2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00036_Sprite.uasset new file mode 100644 index 0000000..7b8dacd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00037.uasset new file mode 100644 index 0000000..37b7aed Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00037_Sprite.uasset new file mode 100644 index 0000000..37fccd9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00038.uasset new file mode 100644 index 0000000..56f8ff7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00038_Sprite.uasset new file mode 100644 index 0000000..8c24abe Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00039.uasset new file mode 100644 index 0000000..9425800 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00039_Sprite.uasset new file mode 100644 index 0000000..a2a0b3d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00040.uasset new file mode 100644 index 0000000..282aa5d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00040_Sprite.uasset new file mode 100644 index 0000000..8524343 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00041.uasset new file mode 100644 index 0000000..da17a3b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00041_Sprite.uasset new file mode 100644 index 0000000..0b7ca11 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00042.uasset new file mode 100644 index 0000000..35a83ee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00042_Sprite.uasset new file mode 100644 index 0000000..3c584cc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00043.uasset new file mode 100644 index 0000000..2c4c948 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00043_Sprite.uasset new file mode 100644 index 0000000..2882913 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00044.uasset new file mode 100644 index 0000000..bfbd6c0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00044_Sprite.uasset new file mode 100644 index 0000000..42e0bd9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00045.uasset new file mode 100644 index 0000000..fcbe283 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00045_Sprite.uasset new file mode 100644 index 0000000..03e9c9e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00046.uasset new file mode 100644 index 0000000..3ca37e5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00046_Sprite.uasset new file mode 100644 index 0000000..291834a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00047.uasset new file mode 100644 index 0000000..5cd7d12 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00047_Sprite.uasset new file mode 100644 index 0000000..a3d5545 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00048.uasset new file mode 100644 index 0000000..332fdb0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00048_Sprite.uasset new file mode 100644 index 0000000..26ca380 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00049.uasset new file mode 100644 index 0000000..1fcabbd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00049_Sprite.uasset new file mode 100644 index 0000000..e5a3692 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00050.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00050.uasset new file mode 100644 index 0000000..0438d89 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00050.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00050_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00050_Sprite.uasset new file mode 100644 index 0000000..9c8e3f1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/电子围墙/电子围墙_00050_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰2.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰2.uasset new file mode 100644 index 0000000..5371b95 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰2.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00007.uasset new file mode 100644 index 0000000..424eccd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00007_Sprite.uasset new file mode 100644 index 0000000..72bfbe7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00008.uasset new file mode 100644 index 0000000..31f5d75 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00008_Sprite.uasset new file mode 100644 index 0000000..c563da5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00009.uasset new file mode 100644 index 0000000..5d23844 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00009_Sprite.uasset new file mode 100644 index 0000000..934e9b3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00010.uasset new file mode 100644 index 0000000..8a493d1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00010_Sprite.uasset new file mode 100644 index 0000000..5fc5b36 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00011.uasset new file mode 100644 index 0000000..f684133 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00011_Sprite.uasset new file mode 100644 index 0000000..f63c5d4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00012.uasset new file mode 100644 index 0000000..a4edbae Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00012_Sprite.uasset new file mode 100644 index 0000000..2f5fd9f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00013.uasset new file mode 100644 index 0000000..77e7cda Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00013_Sprite.uasset new file mode 100644 index 0000000..dbf877b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00014.uasset new file mode 100644 index 0000000..c396bd0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00014_Sprite.uasset new file mode 100644 index 0000000..c790374 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00015.uasset new file mode 100644 index 0000000..b0c998f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00015_Sprite.uasset new file mode 100644 index 0000000..b99b3e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00016.uasset new file mode 100644 index 0000000..6561b48 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00016_Sprite.uasset new file mode 100644 index 0000000..7ab6249 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00017.uasset new file mode 100644 index 0000000..14ae49b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00017_Sprite.uasset new file mode 100644 index 0000000..f54f2c7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00018.uasset new file mode 100644 index 0000000..98a82a6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00018_Sprite.uasset new file mode 100644 index 0000000..b251385 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00019.uasset new file mode 100644 index 0000000..3a9de79 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00019_Sprite.uasset new file mode 100644 index 0000000..2f6d445 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00020.uasset new file mode 100644 index 0000000..60fa6ca Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00020_Sprite.uasset new file mode 100644 index 0000000..187c811 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00021.uasset new file mode 100644 index 0000000..046d919 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00021_Sprite.uasset new file mode 100644 index 0000000..723156d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00022.uasset new file mode 100644 index 0000000..12290cd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00022_Sprite.uasset new file mode 100644 index 0000000..0ea5d02 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00023.uasset new file mode 100644 index 0000000..a059d4c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00023_Sprite.uasset new file mode 100644 index 0000000..708e06c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00024.uasset new file mode 100644 index 0000000..b35bd5a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00024_Sprite.uasset new file mode 100644 index 0000000..512ff83 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00025.uasset new file mode 100644 index 0000000..8714993 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00025_Sprite.uasset new file mode 100644 index 0000000..765f116 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00026.uasset new file mode 100644 index 0000000..83ca9e5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00026_Sprite.uasset new file mode 100644 index 0000000..3579162 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00027.uasset new file mode 100644 index 0000000..0c1c152 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00027_Sprite.uasset new file mode 100644 index 0000000..23e9d2f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00028.uasset new file mode 100644 index 0000000..3014654 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00028_Sprite.uasset new file mode 100644 index 0000000..bdc0578 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/线性火焰/线性火焰_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑.uasset new file mode 100644 index 0000000..93666c4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00000.uasset new file mode 100644 index 0000000..6183e23 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00000_Sprite.uasset new file mode 100644 index 0000000..ae7dce8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00001.uasset new file mode 100644 index 0000000..13d6bb4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00001_Sprite.uasset new file mode 100644 index 0000000..3fe8e99 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00002.uasset new file mode 100644 index 0000000..4385ae6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00002_Sprite.uasset new file mode 100644 index 0000000..6b79fc0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00003.uasset new file mode 100644 index 0000000..3e5440f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00003_Sprite.uasset new file mode 100644 index 0000000..77f1d05 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00004.uasset new file mode 100644 index 0000000..3e82974 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00004_Sprite.uasset new file mode 100644 index 0000000..d7ec964 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00005.uasset new file mode 100644 index 0000000..3884621 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00005_Sprite.uasset new file mode 100644 index 0000000..7ad02e9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00006.uasset new file mode 100644 index 0000000..b12089b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00006_Sprite.uasset new file mode 100644 index 0000000..5b3c085 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00007.uasset new file mode 100644 index 0000000..2e04290 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00007_Sprite.uasset new file mode 100644 index 0000000..6ca3590 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00008.uasset new file mode 100644 index 0000000..c16b38e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00008_Sprite.uasset new file mode 100644 index 0000000..4fba69f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00009.uasset new file mode 100644 index 0000000..e7a5e2f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00009_Sprite.uasset new file mode 100644 index 0000000..bf4e125 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00010.uasset new file mode 100644 index 0000000..3bf02d0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00010_Sprite.uasset new file mode 100644 index 0000000..106338f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00011.uasset new file mode 100644 index 0000000..3f21c57 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00011_Sprite.uasset new file mode 100644 index 0000000..47d1add Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00012.uasset new file mode 100644 index 0000000..e932696 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00012_Sprite.uasset new file mode 100644 index 0000000..98fdc0a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00013.uasset new file mode 100644 index 0000000..7014bac Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00013_Sprite.uasset new file mode 100644 index 0000000..f79cac5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00014.uasset new file mode 100644 index 0000000..160ceb7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00014_Sprite.uasset new file mode 100644 index 0000000..0036e46 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00015.uasset new file mode 100644 index 0000000..46a0bad Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00015_Sprite.uasset new file mode 100644 index 0000000..129588a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00016.uasset new file mode 100644 index 0000000..36fc1e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00016_Sprite.uasset new file mode 100644 index 0000000..bea76bb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00017.uasset new file mode 100644 index 0000000..184d64e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00017_Sprite.uasset new file mode 100644 index 0000000..8e97571 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00018.uasset new file mode 100644 index 0000000..fa4fb18 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00018_Sprite.uasset new file mode 100644 index 0000000..9b193ee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00019.uasset new file mode 100644 index 0000000..05057e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00019_Sprite.uasset new file mode 100644 index 0000000..259e30d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00020.uasset new file mode 100644 index 0000000..fb4a7ff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00020_Sprite.uasset new file mode 100644 index 0000000..4125f57 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00021.uasset new file mode 100644 index 0000000..d1382a4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00021_Sprite.uasset new file mode 100644 index 0000000..8086f29 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00022.uasset new file mode 100644 index 0000000..711f8a5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00022_Sprite.uasset new file mode 100644 index 0000000..9c95baa Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00023.uasset new file mode 100644 index 0000000..714d2ed Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00023_Sprite.uasset new file mode 100644 index 0000000..f4d3489 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00024.uasset new file mode 100644 index 0000000..7aa3360 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00024_Sprite.uasset new file mode 100644 index 0000000..e0f7380 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00025.uasset new file mode 100644 index 0000000..a30e48d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00025_Sprite.uasset new file mode 100644 index 0000000..fcee085 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00026.uasset new file mode 100644 index 0000000..8b45623 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00026_Sprite.uasset new file mode 100644 index 0000000..978bacc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00027.uasset new file mode 100644 index 0000000..2cf65d5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00027_Sprite.uasset new file mode 100644 index 0000000..e3b3a17 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00028.uasset new file mode 100644 index 0000000..80d9ec2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00028_Sprite.uasset new file mode 100644 index 0000000..257292f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00029.uasset new file mode 100644 index 0000000..2c447d9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00029_Sprite.uasset new file mode 100644 index 0000000..466d6df Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00030.uasset new file mode 100644 index 0000000..ca423f4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00030_Sprite.uasset new file mode 100644 index 0000000..b626530 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00031.uasset new file mode 100644 index 0000000..20692ef Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00031_Sprite.uasset new file mode 100644 index 0000000..d97c4f1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00032.uasset new file mode 100644 index 0000000..bdca773 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00032_Sprite.uasset new file mode 100644 index 0000000..5a67fb8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00033.uasset new file mode 100644 index 0000000..6d9ac81 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00033_Sprite.uasset new file mode 100644 index 0000000..90caa01 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00034.uasset new file mode 100644 index 0000000..3bc6af2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00034_Sprite.uasset new file mode 100644 index 0000000..af5daba Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00035.uasset new file mode 100644 index 0000000..03c5b43 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00035_Sprite.uasset new file mode 100644 index 0000000..d206263 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00036.uasset new file mode 100644 index 0000000..d66154d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00036_Sprite.uasset new file mode 100644 index 0000000..0624380 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00037.uasset new file mode 100644 index 0000000..5dedfcd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00037_Sprite.uasset new file mode 100644 index 0000000..f9c9b63 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00038.uasset new file mode 100644 index 0000000..a055b0e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00038_Sprite.uasset new file mode 100644 index 0000000..a67f7c9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00039.uasset new file mode 100644 index 0000000..b6e1414 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00039_Sprite.uasset new file mode 100644 index 0000000..e072fb5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00040.uasset new file mode 100644 index 0000000..61080e6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00040_Sprite.uasset new file mode 100644 index 0000000..7adc6c1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00041.uasset new file mode 100644 index 0000000..4715d50 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00041_Sprite.uasset new file mode 100644 index 0000000..204b233 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00042.uasset new file mode 100644 index 0000000..14188c8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00042_Sprite.uasset new file mode 100644 index 0000000..253f3b8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00043.uasset new file mode 100644 index 0000000..7bf6588 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00043_Sprite.uasset new file mode 100644 index 0000000..30e3e2c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00044.uasset new file mode 100644 index 0000000..6d42572 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00044_Sprite.uasset new file mode 100644 index 0000000..1676736 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00045.uasset new file mode 100644 index 0000000..8030989 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00045_Sprite.uasset new file mode 100644 index 0000000..dceb085 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00046.uasset new file mode 100644 index 0000000..6aafd0b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00046_Sprite.uasset new file mode 100644 index 0000000..1d5c83e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00047.uasset new file mode 100644 index 0000000..8c69974 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00047_Sprite.uasset new file mode 100644 index 0000000..ca311ac Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/绘制建筑/绘制建筑_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/FB_ModelMover.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/FB_ModelMover.uasset new file mode 100644 index 0000000..e2c6a0e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/FB_ModelMover.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00000.uasset new file mode 100644 index 0000000..cffa51f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00000_Sprite.uasset new file mode 100644 index 0000000..fa81806 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00001.uasset new file mode 100644 index 0000000..2fca979 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00001_Sprite.uasset new file mode 100644 index 0000000..352f556 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00002.uasset new file mode 100644 index 0000000..28306a8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00002_Sprite.uasset new file mode 100644 index 0000000..c674c60 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00003.uasset new file mode 100644 index 0000000..9140845 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00003_Sprite.uasset new file mode 100644 index 0000000..9d8fbad Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00004.uasset new file mode 100644 index 0000000..6c1262e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00004_Sprite.uasset new file mode 100644 index 0000000..83c6915 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00005.uasset new file mode 100644 index 0000000..73875d0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00005_Sprite.uasset new file mode 100644 index 0000000..f4851b9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00006.uasset new file mode 100644 index 0000000..ab684a9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00006_Sprite.uasset new file mode 100644 index 0000000..ae2c2c1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00007.uasset new file mode 100644 index 0000000..08c7632 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00007_Sprite.uasset new file mode 100644 index 0000000..5a5af82 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00008.uasset new file mode 100644 index 0000000..fd2884d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00008_Sprite.uasset new file mode 100644 index 0000000..2af044f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00009.uasset new file mode 100644 index 0000000..d25d196 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00009_Sprite.uasset new file mode 100644 index 0000000..496afb2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00010.uasset new file mode 100644 index 0000000..ac36cde Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00010_Sprite.uasset new file mode 100644 index 0000000..e3e0950 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00011.uasset new file mode 100644 index 0000000..65f87ca Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00011_Sprite.uasset new file mode 100644 index 0000000..8d870bb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00012.uasset new file mode 100644 index 0000000..4f28614 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00012_Sprite.uasset new file mode 100644 index 0000000..658b20a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00013.uasset new file mode 100644 index 0000000..1d28902 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00013_Sprite.uasset new file mode 100644 index 0000000..7bff63c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00014.uasset new file mode 100644 index 0000000..ce35ccb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00014_Sprite.uasset new file mode 100644 index 0000000..2f2b9c4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00015.uasset new file mode 100644 index 0000000..0bb8bed Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00015_Sprite.uasset new file mode 100644 index 0000000..388c9e4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00016.uasset new file mode 100644 index 0000000..90a7df0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00016_Sprite.uasset new file mode 100644 index 0000000..78ad91f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00017.uasset new file mode 100644 index 0000000..8a2edb6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00017_Sprite.uasset new file mode 100644 index 0000000..2692925 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00018.uasset new file mode 100644 index 0000000..5ca7f48 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00018_Sprite.uasset new file mode 100644 index 0000000..b45e2e6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00019.uasset new file mode 100644 index 0000000..b0af714 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00019_Sprite.uasset new file mode 100644 index 0000000..afab1ed Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00020.uasset new file mode 100644 index 0000000..e2a60fd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00020_Sprite.uasset new file mode 100644 index 0000000..dd08e98 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00021.uasset new file mode 100644 index 0000000..9eb28e9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00021_Sprite.uasset new file mode 100644 index 0000000..1d8145f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00022.uasset new file mode 100644 index 0000000..61511dd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00022_Sprite.uasset new file mode 100644 index 0000000..bf592e8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00023.uasset new file mode 100644 index 0000000..7e09e16 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00023_Sprite.uasset new file mode 100644 index 0000000..d894562 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00024.uasset new file mode 100644 index 0000000..5d2672f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00024_Sprite.uasset new file mode 100644 index 0000000..4cba005 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00025.uasset new file mode 100644 index 0000000..9aebaaf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00025_Sprite.uasset new file mode 100644 index 0000000..27d9b3d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00026.uasset new file mode 100644 index 0000000..e11da16 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00026_Sprite.uasset new file mode 100644 index 0000000..365753d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00027.uasset new file mode 100644 index 0000000..b461fd8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00027_Sprite.uasset new file mode 100644 index 0000000..06f982d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00028.uasset new file mode 100644 index 0000000..c157581 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00028_Sprite.uasset new file mode 100644 index 0000000..f8f10bb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00029.uasset new file mode 100644 index 0000000..a44d079 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00029_Sprite.uasset new file mode 100644 index 0000000..52665d3 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00030.uasset new file mode 100644 index 0000000..6fc90e6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00030_Sprite.uasset new file mode 100644 index 0000000..586adff Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00031.uasset new file mode 100644 index 0000000..8b70b1e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00031_Sprite.uasset new file mode 100644 index 0000000..176e8f9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00032.uasset new file mode 100644 index 0000000..330250d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00032_Sprite.uasset new file mode 100644 index 0000000..77cb980 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00033.uasset new file mode 100644 index 0000000..8671cd5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00033_Sprite.uasset new file mode 100644 index 0000000..c2530e5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00034.uasset new file mode 100644 index 0000000..b62f98c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00034_Sprite.uasset new file mode 100644 index 0000000..6dc05bf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00035.uasset new file mode 100644 index 0000000..b44fe25 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00035_Sprite.uasset new file mode 100644 index 0000000..bd8a5d1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00036.uasset new file mode 100644 index 0000000..6316e16 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00036_Sprite.uasset new file mode 100644 index 0000000..c7c12c4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00037.uasset new file mode 100644 index 0000000..3c3317e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00037_Sprite.uasset new file mode 100644 index 0000000..c527f24 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00038.uasset new file mode 100644 index 0000000..c7ce84a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00038_Sprite.uasset new file mode 100644 index 0000000..b3e2332 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00039.uasset new file mode 100644 index 0000000..6e9d2de Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00039_Sprite.uasset new file mode 100644 index 0000000..7dc5cc4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00040.uasset new file mode 100644 index 0000000..3cfa9e0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00040_Sprite.uasset new file mode 100644 index 0000000..9e34ee6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00041.uasset new file mode 100644 index 0000000..53063f1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00041_Sprite.uasset new file mode 100644 index 0000000..21b66e8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00042.uasset new file mode 100644 index 0000000..4ea545d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00042_Sprite.uasset new file mode 100644 index 0000000..5007f1a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00043.uasset new file mode 100644 index 0000000..efcafd8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00043_Sprite.uasset new file mode 100644 index 0000000..faae142 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00044.uasset new file mode 100644 index 0000000..01e2f73 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00044_Sprite.uasset new file mode 100644 index 0000000..506e5ef Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00045.uasset new file mode 100644 index 0000000..caba335 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00045_Sprite.uasset new file mode 100644 index 0000000..a914685 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00046.uasset new file mode 100644 index 0000000..38221f5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00046_Sprite.uasset new file mode 100644 index 0000000..204b453 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00047.uasset new file mode 100644 index 0000000..9583d54 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00047_Sprite.uasset new file mode 100644 index 0000000..54fc259 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00048.uasset new file mode 100644 index 0000000..cf929a0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00048_Sprite.uasset new file mode 100644 index 0000000..b48dede Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00049.uasset new file mode 100644 index 0000000..2bb99e7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00049_Sprite.uasset new file mode 100644 index 0000000..e04f17e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00050.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00050.uasset new file mode 100644 index 0000000..cb612a0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00050.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00050_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00050_Sprite.uasset new file mode 100644 index 0000000..4855b49 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/轨迹运动/轨迹运动_00050_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰.uasset new file mode 100644 index 0000000..dd68cb9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00000.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00000.uasset new file mode 100644 index 0000000..9d083e1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00000.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00000_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00000_Sprite.uasset new file mode 100644 index 0000000..474c21e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00000_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00001.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00001.uasset new file mode 100644 index 0000000..8a092a1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00001.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00001_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00001_Sprite.uasset new file mode 100644 index 0000000..7b80a07 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00001_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00002.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00002.uasset new file mode 100644 index 0000000..7bf4fe8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00002.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00002_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00002_Sprite.uasset new file mode 100644 index 0000000..8bb667d Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00002_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00003.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00003.uasset new file mode 100644 index 0000000..8ef7281 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00003.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00003_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00003_Sprite.uasset new file mode 100644 index 0000000..22abf43 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00003_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00004.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00004.uasset new file mode 100644 index 0000000..83f5237 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00004.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00004_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00004_Sprite.uasset new file mode 100644 index 0000000..16b3e24 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00004_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00005.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00005.uasset new file mode 100644 index 0000000..31bb41c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00005.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00005_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00005_Sprite.uasset new file mode 100644 index 0000000..b6de044 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00005_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00006.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00006.uasset new file mode 100644 index 0000000..233c3d7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00006.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00006_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00006_Sprite.uasset new file mode 100644 index 0000000..9815b87 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00006_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00007.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00007.uasset new file mode 100644 index 0000000..f6c36a0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00007.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00007_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00007_Sprite.uasset new file mode 100644 index 0000000..b876677 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00007_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00008.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00008.uasset new file mode 100644 index 0000000..4dc5a7e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00008.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00008_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00008_Sprite.uasset new file mode 100644 index 0000000..21984ba Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00008_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00009.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00009.uasset new file mode 100644 index 0000000..ca6f9cc Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00009.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00009_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00009_Sprite.uasset new file mode 100644 index 0000000..27ed81e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00009_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00010.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00010.uasset new file mode 100644 index 0000000..8c06909 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00010.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00010_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00010_Sprite.uasset new file mode 100644 index 0000000..72696a9 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00010_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00011.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00011.uasset new file mode 100644 index 0000000..ecd43eb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00011.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00011_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00011_Sprite.uasset new file mode 100644 index 0000000..0a8f1ee Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00011_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00012.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00012.uasset new file mode 100644 index 0000000..e4db753 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00012.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00012_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00012_Sprite.uasset new file mode 100644 index 0000000..526f228 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00012_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00013.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00013.uasset new file mode 100644 index 0000000..7985f4a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00013.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00013_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00013_Sprite.uasset new file mode 100644 index 0000000..d291563 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00013_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00014.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00014.uasset new file mode 100644 index 0000000..b8af72b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00014.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00014_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00014_Sprite.uasset new file mode 100644 index 0000000..19faf4b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00014_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00015.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00015.uasset new file mode 100644 index 0000000..1f1c2e2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00015.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00015_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00015_Sprite.uasset new file mode 100644 index 0000000..f3106ae Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00015_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00016.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00016.uasset new file mode 100644 index 0000000..88e6e75 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00016.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00016_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00016_Sprite.uasset new file mode 100644 index 0000000..b875407 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00016_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00017.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00017.uasset new file mode 100644 index 0000000..d43e8a0 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00017.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00017_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00017_Sprite.uasset new file mode 100644 index 0000000..b55ad82 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00017_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00018.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00018.uasset new file mode 100644 index 0000000..abdc652 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00018.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00018_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00018_Sprite.uasset new file mode 100644 index 0000000..a7f772a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00018_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00019.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00019.uasset new file mode 100644 index 0000000..77736b6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00019.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00019_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00019_Sprite.uasset new file mode 100644 index 0000000..e826478 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00019_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00020.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00020.uasset new file mode 100644 index 0000000..cee758c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00020.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00020_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00020_Sprite.uasset new file mode 100644 index 0000000..fc30133 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00020_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00021.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00021.uasset new file mode 100644 index 0000000..bdcfa93 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00021.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00021_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00021_Sprite.uasset new file mode 100644 index 0000000..905e04b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00021_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00022.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00022.uasset new file mode 100644 index 0000000..fa38d21 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00022.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00022_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00022_Sprite.uasset new file mode 100644 index 0000000..6360372 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00022_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00023.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00023.uasset new file mode 100644 index 0000000..a537dc7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00023.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00023_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00023_Sprite.uasset new file mode 100644 index 0000000..3e438fb Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00023_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00024.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00024.uasset new file mode 100644 index 0000000..b1b84de Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00024.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00024_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00024_Sprite.uasset new file mode 100644 index 0000000..362a0bf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00024_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00025.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00025.uasset new file mode 100644 index 0000000..110a45a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00025.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00025_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00025_Sprite.uasset new file mode 100644 index 0000000..eba2fb5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00025_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00026.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00026.uasset new file mode 100644 index 0000000..a82b58b Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00026.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00026_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00026_Sprite.uasset new file mode 100644 index 0000000..7865e22 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00026_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00027.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00027.uasset new file mode 100644 index 0000000..cdb8201 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00027.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00027_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00027_Sprite.uasset new file mode 100644 index 0000000..17b4a52 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00027_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00028.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00028.uasset new file mode 100644 index 0000000..8731b42 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00028.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00028_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00028_Sprite.uasset new file mode 100644 index 0000000..5c26946 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00028_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00029.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00029.uasset new file mode 100644 index 0000000..e20b5e7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00029.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00029_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00029_Sprite.uasset new file mode 100644 index 0000000..2f5376a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00029_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00030.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00030.uasset new file mode 100644 index 0000000..02b142e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00030.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00030_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00030_Sprite.uasset new file mode 100644 index 0000000..cf82374 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00030_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00031.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00031.uasset new file mode 100644 index 0000000..5408811 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00031.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00031_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00031_Sprite.uasset new file mode 100644 index 0000000..7d32d49 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00031_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00032.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00032.uasset new file mode 100644 index 0000000..ca23177 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00032.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00032_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00032_Sprite.uasset new file mode 100644 index 0000000..e231e30 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00032_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00033.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00033.uasset new file mode 100644 index 0000000..b885a17 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00033.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00033_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00033_Sprite.uasset new file mode 100644 index 0000000..94a8197 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00033_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00034.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00034.uasset new file mode 100644 index 0000000..5c309bf Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00034.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00034_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00034_Sprite.uasset new file mode 100644 index 0000000..e965069 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00034_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00035.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00035.uasset new file mode 100644 index 0000000..80dbf87 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00035.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00035_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00035_Sprite.uasset new file mode 100644 index 0000000..da26f52 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00035_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00036.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00036.uasset new file mode 100644 index 0000000..7e0feb4 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00036.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00036_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00036_Sprite.uasset new file mode 100644 index 0000000..eb4a5f6 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00036_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00037.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00037.uasset new file mode 100644 index 0000000..3c1a7e5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00037.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00037_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00037_Sprite.uasset new file mode 100644 index 0000000..1534f09 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00037_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00038.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00038.uasset new file mode 100644 index 0000000..2dc1488 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00038.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00038_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00038_Sprite.uasset new file mode 100644 index 0000000..cd9da8e Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00038_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00039.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00039.uasset new file mode 100644 index 0000000..37635e1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00039.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00039_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00039_Sprite.uasset new file mode 100644 index 0000000..c63ca0c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00039_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00040.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00040.uasset new file mode 100644 index 0000000..56caa1a Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00040.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00040_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00040_Sprite.uasset new file mode 100644 index 0000000..fd242e7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00040_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00041.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00041.uasset new file mode 100644 index 0000000..483e600 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00041.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00041_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00041_Sprite.uasset new file mode 100644 index 0000000..327b6d2 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00041_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00042.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00042.uasset new file mode 100644 index 0000000..382160f Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00042.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00042_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00042_Sprite.uasset new file mode 100644 index 0000000..40a14a1 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00042_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00043.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00043.uasset new file mode 100644 index 0000000..e1d37d5 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00043.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00043_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00043_Sprite.uasset new file mode 100644 index 0000000..4930e96 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00043_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00044.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00044.uasset new file mode 100644 index 0000000..bbb10cd Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00044.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00044_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00044_Sprite.uasset new file mode 100644 index 0000000..7467cc8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00044_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00045.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00045.uasset new file mode 100644 index 0000000..7fbcf62 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00045.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00045_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00045_Sprite.uasset new file mode 100644 index 0000000..a663f69 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00045_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00046.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00046.uasset new file mode 100644 index 0000000..8cfe430 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00046.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00046_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00046_Sprite.uasset new file mode 100644 index 0000000..3a00543 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00046_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00047.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00047.uasset new file mode 100644 index 0000000..72ce983 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00047.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00047_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00047_Sprite.uasset new file mode 100644 index 0000000..ba45974 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00047_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00048.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00048.uasset new file mode 100644 index 0000000..3908269 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00048.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00048_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00048_Sprite.uasset new file mode 100644 index 0000000..c38f23c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00048_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00049.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00049.uasset new file mode 100644 index 0000000..22f27a7 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00049.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00049_Sprite.uasset b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00049_Sprite.uasset new file mode 100644 index 0000000..256dbe8 Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/LeftPanelIcon/特效/面性火焰/面性火焰_00049_Sprite.uasset differ diff --git a/Content/ToolFunction/03Textures/UI_GIF/UI_Gif1.uasset b/Content/ToolFunction/03Textures/UI_GIF/UI_Gif1.uasset new file mode 100644 index 0000000..0e0907c Binary files /dev/null and b/Content/ToolFunction/03Textures/UI_GIF/UI_Gif1.uasset differ diff --git a/Content/ToolFunction/03Textures/WallAndLine/GrowDown.uasset b/Content/ToolFunction/03Textures/WallAndLine/GrowDown.uasset new file mode 100644 index 0000000..f4e9d3a Binary files /dev/null and b/Content/ToolFunction/03Textures/WallAndLine/GrowDown.uasset differ diff --git a/Content/ToolFunction/03Textures/WallAndLine/GrowUp.uasset b/Content/ToolFunction/03Textures/WallAndLine/GrowUp.uasset new file mode 100644 index 0000000..da8d668 Binary files /dev/null and b/Content/ToolFunction/03Textures/WallAndLine/GrowUp.uasset differ diff --git a/Content/ToolFunction/03Textures/WallAndLine/Warning.uasset b/Content/ToolFunction/03Textures/WallAndLine/Warning.uasset new file mode 100644 index 0000000..215c929 Binary files /dev/null and b/Content/ToolFunction/03Textures/WallAndLine/Warning.uasset differ diff --git a/Content/ToolFunction/03Textures/WallAndLine/行动路线5.uasset b/Content/ToolFunction/03Textures/WallAndLine/行动路线5.uasset new file mode 100644 index 0000000..d41982b Binary files /dev/null and b/Content/ToolFunction/03Textures/WallAndLine/行动路线5.uasset differ diff --git a/Content/ToolFunction/03Textures/X.uasset b/Content/ToolFunction/03Textures/X.uasset new file mode 100644 index 0000000..ebb65f6 Binary files /dev/null and b/Content/ToolFunction/03Textures/X.uasset differ diff --git a/Content/ToolFunction/03Textures/全球范围线.uasset b/Content/ToolFunction/03Textures/全球范围线.uasset new file mode 100644 index 0000000..2274c5a Binary files /dev/null and b/Content/ToolFunction/03Textures/全球范围线.uasset differ diff --git a/Content/ToolFunction/03Textures/分组_3.uasset b/Content/ToolFunction/03Textures/分组_3.uasset new file mode 100644 index 0000000..f4290bb Binary files /dev/null and b/Content/ToolFunction/03Textures/分组_3.uasset differ diff --git a/Content/ToolFunction/03Textures/喇叭.uasset b/Content/ToolFunction/03Textures/喇叭.uasset new file mode 100644 index 0000000..07eed93 Binary files /dev/null and b/Content/ToolFunction/03Textures/喇叭.uasset differ diff --git a/Content/ToolFunction/03Textures/定位.uasset b/Content/ToolFunction/03Textures/定位.uasset new file mode 100644 index 0000000..c364128 Binary files /dev/null and b/Content/ToolFunction/03Textures/定位.uasset differ diff --git a/Content/ToolFunction/03Textures/定位_3x.uasset b/Content/ToolFunction/03Textures/定位_3x.uasset new file mode 100644 index 0000000..ca2619d Binary files /dev/null and b/Content/ToolFunction/03Textures/定位_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/定位(1).uasset b/Content/ToolFunction/03Textures/定位(1).uasset new file mode 100644 index 0000000..317b766 Binary files /dev/null and b/Content/ToolFunction/03Textures/定位(1).uasset differ diff --git a/Content/ToolFunction/03Textures/形状_9_3x.uasset b/Content/ToolFunction/03Textures/形状_9_3x.uasset new file mode 100644 index 0000000..a5a05b1 Binary files /dev/null and b/Content/ToolFunction/03Textures/形状_9_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/微信截图_20240704093614.uasset b/Content/ToolFunction/03Textures/微信截图_20240704093614.uasset new file mode 100644 index 0000000..d1d30de Binary files /dev/null and b/Content/ToolFunction/03Textures/微信截图_20240704093614.uasset differ diff --git a/Content/ToolFunction/03Textures/扩散波大_拷贝.uasset b/Content/ToolFunction/03Textures/扩散波大_拷贝.uasset new file mode 100644 index 0000000..9025669 Binary files /dev/null and b/Content/ToolFunction/03Textures/扩散波大_拷贝.uasset differ diff --git a/Content/ToolFunction/03Textures/测绘导航.uasset b/Content/ToolFunction/03Textures/测绘导航.uasset new file mode 100644 index 0000000..2e79b4b Binary files /dev/null and b/Content/ToolFunction/03Textures/测绘导航.uasset differ diff --git a/Content/ToolFunction/03Textures/测绘导航PNG源.uasset b/Content/ToolFunction/03Textures/测绘导航PNG源.uasset new file mode 100644 index 0000000..0b3b833 Binary files /dev/null and b/Content/ToolFunction/03Textures/测绘导航PNG源.uasset differ diff --git a/Content/ToolFunction/03Textures/测绘导航Red.uasset b/Content/ToolFunction/03Textures/测绘导航Red.uasset new file mode 100644 index 0000000..373abcf Binary files /dev/null and b/Content/ToolFunction/03Textures/测绘导航Red.uasset differ diff --git a/Content/ToolFunction/03Textures/渐变矩形.uasset b/Content/ToolFunction/03Textures/渐变矩形.uasset new file mode 100644 index 0000000..32568a7 Binary files /dev/null and b/Content/ToolFunction/03Textures/渐变矩形.uasset differ diff --git a/Content/ToolFunction/03Textures/组合_25_3x.uasset b/Content/ToolFunction/03Textures/组合_25_3x.uasset new file mode 100644 index 0000000..4ba2432 Binary files /dev/null and b/Content/ToolFunction/03Textures/组合_25_3x.uasset differ diff --git a/Content/ToolFunction/03Textures/联系表-001.uasset b/Content/ToolFunction/03Textures/联系表-001.uasset new file mode 100644 index 0000000..7dffca7 Binary files /dev/null and b/Content/ToolFunction/03Textures/联系表-001.uasset differ diff --git a/Content/ToolFunction/03Textures/链接.uasset b/Content/ToolFunction/03Textures/链接.uasset new file mode 100644 index 0000000..1bbebf0 Binary files /dev/null and b/Content/ToolFunction/03Textures/链接.uasset differ diff --git a/Content/ToolFunction/03Textures/鼠标定位.uasset b/Content/ToolFunction/03Textures/鼠标定位.uasset new file mode 100644 index 0000000..666f8b9 Binary files /dev/null and b/Content/ToolFunction/03Textures/鼠标定位.uasset differ diff --git a/Content/ToolFunction/04Materials/Brush/MI_CesiumThreeOverlaysAndClipping_Painting.uasset b/Content/ToolFunction/04Materials/Brush/MI_CesiumThreeOverlaysAndClipping_Painting.uasset new file mode 100644 index 0000000..93404e8 Binary files /dev/null and b/Content/ToolFunction/04Materials/Brush/MI_CesiumThreeOverlaysAndClipping_Painting.uasset differ diff --git a/Content/ToolFunction/04Materials/Brush/MLB_PaintingCanvas.uasset b/Content/ToolFunction/04Materials/Brush/MLB_PaintingCanvas.uasset new file mode 100644 index 0000000..1b7d6cf Binary files /dev/null and b/Content/ToolFunction/04Materials/Brush/MLB_PaintingCanvas.uasset differ diff --git a/Content/ToolFunction/04Materials/Brush/ML_PaintingCanvas.uasset b/Content/ToolFunction/04Materials/Brush/ML_PaintingCanvas.uasset new file mode 100644 index 0000000..af56c47 Binary files /dev/null and b/Content/ToolFunction/04Materials/Brush/ML_PaintingCanvas.uasset differ diff --git a/Content/ToolFunction/04Materials/Brush/M_Brush.uasset b/Content/ToolFunction/04Materials/Brush/M_Brush.uasset new file mode 100644 index 0000000..5c43e8f Binary files /dev/null and b/Content/ToolFunction/04Materials/Brush/M_Brush.uasset differ diff --git a/Content/ToolFunction/04Materials/Brush/M_Brush_Inst.uasset b/Content/ToolFunction/04Materials/Brush/M_Brush_Inst.uasset new file mode 100644 index 0000000..aad9fa4 Binary files /dev/null and b/Content/ToolFunction/04Materials/Brush/M_Brush_Inst.uasset differ diff --git a/Content/ToolFunction/04Materials/Brush/M_CanvasDecal.uasset b/Content/ToolFunction/04Materials/Brush/M_CanvasDecal.uasset new file mode 100644 index 0000000..2c71e02 Binary files /dev/null and b/Content/ToolFunction/04Materials/Brush/M_CanvasDecal.uasset differ diff --git a/Content/ToolFunction/04Materials/Color/M_DefaultMaterial.uasset b/Content/ToolFunction/04Materials/Color/M_DefaultMaterial.uasset new file mode 100644 index 0000000..c17eb14 Binary files /dev/null and b/Content/ToolFunction/04Materials/Color/M_DefaultMaterial.uasset differ diff --git a/Content/ToolFunction/04Materials/Color/M_DefaultMaterial1.uasset b/Content/ToolFunction/04Materials/Color/M_DefaultMaterial1.uasset new file mode 100644 index 0000000..c0b1b16 Binary files /dev/null and b/Content/ToolFunction/04Materials/Color/M_DefaultMaterial1.uasset differ diff --git a/Content/ToolFunction/04Materials/Color/M_DefaultMaterial2.uasset b/Content/ToolFunction/04Materials/Color/M_DefaultMaterial2.uasset new file mode 100644 index 0000000..85a5f8a Binary files /dev/null and b/Content/ToolFunction/04Materials/Color/M_DefaultMaterial2.uasset differ diff --git a/Content/ToolFunction/04Materials/Decal/DistanceFeild/M_SDF_Square.uasset b/Content/ToolFunction/04Materials/Decal/DistanceFeild/M_SDF_Square.uasset new file mode 100644 index 0000000..a637274 Binary files /dev/null and b/Content/ToolFunction/04Materials/Decal/DistanceFeild/M_SDF_Square.uasset differ diff --git a/Content/ToolFunction/04Materials/Decal/M_Border_Decal_Spline.uasset b/Content/ToolFunction/04Materials/Decal/M_Border_Decal_Spline.uasset new file mode 100644 index 0000000..53282e0 Binary files /dev/null and b/Content/ToolFunction/04Materials/Decal/M_Border_Decal_Spline.uasset differ diff --git a/Content/ToolFunction/04Materials/Decal/M_Decal_DottedCircle.uasset b/Content/ToolFunction/04Materials/Decal/M_Decal_DottedCircle.uasset new file mode 100644 index 0000000..ef4e84d Binary files /dev/null and b/Content/ToolFunction/04Materials/Decal/M_Decal_DottedCircle.uasset differ diff --git a/Content/ToolFunction/04Materials/Decal/M_Decal_LightWave.uasset b/Content/ToolFunction/04Materials/Decal/M_Decal_LightWave.uasset new file mode 100644 index 0000000..46b3d6b Binary files /dev/null and b/Content/ToolFunction/04Materials/Decal/M_Decal_LightWave.uasset differ diff --git a/Content/ToolFunction/04Materials/Decal/M_Decal_Roundness02.uasset b/Content/ToolFunction/04Materials/Decal/M_Decal_Roundness02.uasset new file mode 100644 index 0000000..e40e7d6 Binary files /dev/null and b/Content/ToolFunction/04Materials/Decal/M_Decal_Roundness02.uasset differ diff --git a/Content/ToolFunction/04Materials/Decal/M_Decal_SimpleMark.uasset b/Content/ToolFunction/04Materials/Decal/M_Decal_SimpleMark.uasset new file mode 100644 index 0000000..53acef7 Binary files /dev/null and b/Content/ToolFunction/04Materials/Decal/M_Decal_SimpleMark.uasset differ diff --git a/Content/ToolFunction/04Materials/Decal/M_ExplosionDecal.uasset b/Content/ToolFunction/04Materials/Decal/M_ExplosionDecal.uasset new file mode 100644 index 0000000..9ff1bcc Binary files /dev/null and b/Content/ToolFunction/04Materials/Decal/M_ExplosionDecal.uasset differ diff --git a/Content/ToolFunction/04Materials/Decal/M_FireDecal.uasset b/Content/ToolFunction/04Materials/Decal/M_FireDecal.uasset new file mode 100644 index 0000000..cfae01a Binary files /dev/null and b/Content/ToolFunction/04Materials/Decal/M_FireDecal.uasset differ diff --git a/Content/ToolFunction/04Materials/Decal/M_FireDecal_Inst.uasset b/Content/ToolFunction/04Materials/Decal/M_FireDecal_Inst.uasset new file mode 100644 index 0000000..b5623c7 Binary files /dev/null and b/Content/ToolFunction/04Materials/Decal/M_FireDecal_Inst.uasset differ diff --git a/Content/ToolFunction/04Materials/Decal/M_Roundness.uasset b/Content/ToolFunction/04Materials/Decal/M_Roundness.uasset new file mode 100644 index 0000000..8ffe5a7 Binary files /dev/null and b/Content/ToolFunction/04Materials/Decal/M_Roundness.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/FlowPipe/M_FlowPipe.uasset b/Content/ToolFunction/04Materials/Effect/FlowPipe/M_FlowPipe.uasset new file mode 100644 index 0000000..4b3bd66 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/FlowPipe/M_FlowPipe.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/FlowPipe/M_PT_DottedLine_Anim_ThroughWall_Masked1.uasset b/Content/ToolFunction/04Materials/Effect/FlowPipe/M_PT_DottedLine_Anim_ThroughWall_Masked1.uasset new file mode 100644 index 0000000..03093e4 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/FlowPipe/M_PT_DottedLine_Anim_ThroughWall_Masked1.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/LineOfSight/MI_Frustum_Invisible.uasset b/Content/ToolFunction/04Materials/Effect/LineOfSight/MI_Frustum_Invisible.uasset new file mode 100644 index 0000000..d7fec86 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/LineOfSight/MI_Frustum_Invisible.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/LineOfSight/MI_Frustum_Visible.uasset b/Content/ToolFunction/04Materials/Effect/LineOfSight/MI_Frustum_Visible.uasset new file mode 100644 index 0000000..f5e2c5f Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/LineOfSight/MI_Frustum_Visible.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/LineOfSight/M_EmiColor.uasset b/Content/ToolFunction/04Materials/Effect/LineOfSight/M_EmiColor.uasset new file mode 100644 index 0000000..5a64730 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/LineOfSight/M_EmiColor.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/LineOfSight/M_EmiColor_Invisible.uasset b/Content/ToolFunction/04Materials/Effect/LineOfSight/M_EmiColor_Invisible.uasset new file mode 100644 index 0000000..e0230c3 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/LineOfSight/M_EmiColor_Invisible.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/LineOfSight/M_EmiColor_Visible.uasset b/Content/ToolFunction/04Materials/Effect/LineOfSight/M_EmiColor_Visible.uasset new file mode 100644 index 0000000..faff30b Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/LineOfSight/M_EmiColor_Visible.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/LineOfSight/M_Frustum.uasset b/Content/ToolFunction/04Materials/Effect/LineOfSight/M_Frustum.uasset new file mode 100644 index 0000000..17ca65e Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/LineOfSight/M_Frustum.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/MI_DecalWater.uasset b/Content/ToolFunction/04Materials/Effect/MI_DecalWater.uasset new file mode 100644 index 0000000..e5afa4c Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/MI_DecalWater.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/M_DecalWater.uasset b/Content/ToolFunction/04Materials/Effect/M_DecalWater.uasset new file mode 100644 index 0000000..f7d50ca Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/M_DecalWater.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/M_DecalWater02.uasset b/Content/ToolFunction/04Materials/Effect/M_DecalWater02.uasset new file mode 100644 index 0000000..6028ffb Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/M_DecalWater02.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/M_PolygonWater.uasset b/Content/ToolFunction/04Materials/Effect/M_PolygonWater.uasset new file mode 100644 index 0000000..2286d19 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/M_PolygonWater.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/ModelCutter/MF_ModelCutter.uasset b/Content/ToolFunction/04Materials/Effect/ModelCutter/MF_ModelCutter.uasset new file mode 100644 index 0000000..cdd22d5 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/ModelCutter/MF_ModelCutter.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingBothShow.uasset b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingBothShow.uasset new file mode 100644 index 0000000..ac97ec9 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingBothShow.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingLeft.uasset b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingLeft.uasset new file mode 100644 index 0000000..69f61c5 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingLeft.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingNewRight.uasset b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingNewRight.uasset new file mode 100644 index 0000000..9eb458a Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingNewRight.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingRight.uasset b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingRight.uasset new file mode 100644 index 0000000..657836c Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingRight.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingTranslucentBothShow.uasset b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingTranslucentBothShow.uasset new file mode 100644 index 0000000..63d1c01 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingTranslucentBothShow.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingTranslucentLeft.uasset b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingTranslucentLeft.uasset new file mode 100644 index 0000000..80b926a Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingTranslucentLeft.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingTranslucentRight.uasset b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingTranslucentRight.uasset new file mode 100644 index 0000000..22242a2 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/ModelCutter/MI_CesiumThreeOverlaysAndClippingTranslucentRight.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/ModelCutter/MPC_ModelCutter.uasset b/Content/ToolFunction/04Materials/Effect/ModelCutter/MPC_ModelCutter.uasset new file mode 100644 index 0000000..57cc2da Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/ModelCutter/MPC_ModelCutter.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/ModelCutter/M_MarkCutterPlane.uasset b/Content/ToolFunction/04Materials/Effect/ModelCutter/M_MarkCutterPlane.uasset new file mode 100644 index 0000000..1e3454c Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/ModelCutter/M_MarkCutterPlane.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/Movies/M_MoviePlayerBase.uasset b/Content/ToolFunction/04Materials/Effect/Movies/M_MoviePlayerBase.uasset new file mode 100644 index 0000000..7a67846 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/Movies/M_MoviePlayerBase.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/Movies/M_MoviePlayerUIBase.uasset b/Content/ToolFunction/04Materials/Effect/Movies/M_MoviePlayerUIBase.uasset new file mode 100644 index 0000000..fc7ee8f Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/Movies/M_MoviePlayerUIBase.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/SkyLine/MPC_Skyline.uasset b/Content/ToolFunction/04Materials/Effect/SkyLine/MPC_Skyline.uasset new file mode 100644 index 0000000..5517e97 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/SkyLine/MPC_Skyline.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/SkyLine/M_SkylinePost.uasset b/Content/ToolFunction/04Materials/Effect/SkyLine/M_SkylinePost.uasset new file mode 100644 index 0000000..90058a2 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/SkyLine/M_SkylinePost.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/SlopAnalysis/M_Decal_SlopAnalysis.uasset b/Content/ToolFunction/04Materials/Effect/SlopAnalysis/M_Decal_SlopAnalysis.uasset new file mode 100644 index 0000000..d94b88d Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/SlopAnalysis/M_Decal_SlopAnalysis.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/Text3D/M_Text3DBase.uasset b/Content/ToolFunction/04Materials/Effect/Text3D/M_Text3DBase.uasset new file mode 100644 index 0000000..48514e6 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/Text3D/M_Text3DBase.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/Text3D/M_Text3DBody.uasset b/Content/ToolFunction/04Materials/Effect/Text3D/M_Text3DBody.uasset new file mode 100644 index 0000000..380e13b Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/Text3D/M_Text3DBody.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/Text3D/M_Text3OutLine.uasset b/Content/ToolFunction/04Materials/Effect/Text3D/M_Text3OutLine.uasset new file mode 100644 index 0000000..19bb4f6 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/Text3D/M_Text3OutLine.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/TextDecal/M_TextDecalBase.uasset b/Content/ToolFunction/04Materials/Effect/TextDecal/M_TextDecalBase.uasset new file mode 100644 index 0000000..419e067 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/TextDecal/M_TextDecalBase.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/Wall/M_MultiMarkSolidWall.uasset b/Content/ToolFunction/04Materials/Effect/Wall/M_MultiMarkSolidWall.uasset new file mode 100644 index 0000000..b252f63 Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/Wall/M_MultiMarkSolidWall.uasset differ diff --git a/Content/ToolFunction/04Materials/Effect/Wall/M_MultiMarkWall.uasset b/Content/ToolFunction/04Materials/Effect/Wall/M_MultiMarkWall.uasset new file mode 100644 index 0000000..34fcc0a Binary files /dev/null and b/Content/ToolFunction/04Materials/Effect/Wall/M_MultiMarkWall.uasset differ diff --git a/Content/ToolFunction/04Materials/HDRI/M_HRDIBase.uasset b/Content/ToolFunction/04Materials/HDRI/M_HRDIBase.uasset new file mode 100644 index 0000000..a76b85b Binary files /dev/null and b/Content/ToolFunction/04Materials/HDRI/M_HRDIBase.uasset differ diff --git a/Content/ToolFunction/04Materials/HDRI/M_HRDIBase_Inst.uasset b/Content/ToolFunction/04Materials/HDRI/M_HRDIBase_Inst.uasset new file mode 100644 index 0000000..f6a987a Binary files /dev/null and b/Content/ToolFunction/04Materials/HDRI/M_HRDIBase_Inst.uasset differ diff --git a/Content/ToolFunction/04Materials/Layer/ML_Ocean.uasset b/Content/ToolFunction/04Materials/Layer/ML_Ocean.uasset new file mode 100644 index 0000000..35710ad Binary files /dev/null and b/Content/ToolFunction/04Materials/Layer/ML_Ocean.uasset differ diff --git a/Content/ToolFunction/04Materials/Library/MF_Lerp3ColorAdvance.uasset b/Content/ToolFunction/04Materials/Library/MF_Lerp3ColorAdvance.uasset new file mode 100644 index 0000000..3d6016b Binary files /dev/null and b/Content/ToolFunction/04Materials/Library/MF_Lerp3ColorAdvance.uasset differ diff --git a/Content/ToolFunction/04Materials/Library/MF_SDF_Box.uasset b/Content/ToolFunction/04Materials/Library/MF_SDF_Box.uasset new file mode 100644 index 0000000..3d59ef9 Binary files /dev/null and b/Content/ToolFunction/04Materials/Library/MF_SDF_Box.uasset differ diff --git a/Content/ToolFunction/04Materials/M_Polygon.uasset b/Content/ToolFunction/04Materials/M_Polygon.uasset new file mode 100644 index 0000000..6760a9e Binary files /dev/null and b/Content/ToolFunction/04Materials/M_Polygon.uasset differ diff --git a/Content/ToolFunction/04Materials/MilitaryLOGO/M_MarkPointWidgetMaterial.uasset b/Content/ToolFunction/04Materials/MilitaryLOGO/M_MarkPointWidgetMaterial.uasset new file mode 100644 index 0000000..9bcc6c8 Binary files /dev/null and b/Content/ToolFunction/04Materials/MilitaryLOGO/M_MarkPointWidgetMaterial.uasset differ diff --git a/Content/ToolFunction/04Materials/MilitaryLOGO/M_MarkPointWidgetMaterial_Inst.uasset b/Content/ToolFunction/04Materials/MilitaryLOGO/M_MarkPointWidgetMaterial_Inst.uasset new file mode 100644 index 0000000..45ec75d Binary files /dev/null and b/Content/ToolFunction/04Materials/MilitaryLOGO/M_MarkPointWidgetMaterial_Inst.uasset differ diff --git a/Content/ToolFunction/04Materials/MilitaryLOGO/M_MilitaryDecal.uasset b/Content/ToolFunction/04Materials/MilitaryLOGO/M_MilitaryDecal.uasset new file mode 100644 index 0000000..c2f968e Binary files /dev/null and b/Content/ToolFunction/04Materials/MilitaryLOGO/M_MilitaryDecal.uasset differ diff --git a/Content/ToolFunction/04Materials/MilitaryLOGO/M_MilitaryDecal_Inst.uasset b/Content/ToolFunction/04Materials/MilitaryLOGO/M_MilitaryDecal_Inst.uasset new file mode 100644 index 0000000..fc30657 Binary files /dev/null and b/Content/ToolFunction/04Materials/MilitaryLOGO/M_MilitaryDecal_Inst.uasset differ diff --git a/Content/ToolFunction/04Materials/MilitaryLOGO/M_MilitaryLOGO3D.uasset b/Content/ToolFunction/04Materials/MilitaryLOGO/M_MilitaryLOGO3D.uasset new file mode 100644 index 0000000..1a4275d Binary files /dev/null and b/Content/ToolFunction/04Materials/MilitaryLOGO/M_MilitaryLOGO3D.uasset differ diff --git a/Content/ToolFunction/04Materials/MilitaryLOGO/M_MilitaryLOGO3D_Inst.uasset b/Content/ToolFunction/04Materials/MilitaryLOGO/M_MilitaryLOGO3D_Inst.uasset new file mode 100644 index 0000000..4671227 Binary files /dev/null and b/Content/ToolFunction/04Materials/MilitaryLOGO/M_MilitaryLOGO3D_Inst.uasset differ diff --git a/Content/ToolFunction/04Materials/Model/M_ModelChangeColorBase.uasset b/Content/ToolFunction/04Materials/Model/M_ModelChangeColorBase.uasset new file mode 100644 index 0000000..47f93c7 Binary files /dev/null and b/Content/ToolFunction/04Materials/Model/M_ModelChangeColorBase.uasset differ diff --git a/Content/ToolFunction/04Materials/Model/M_ModelChangeColorBase_ModelData.uasset b/Content/ToolFunction/04Materials/Model/M_ModelChangeColorBase_ModelData.uasset new file mode 100644 index 0000000..e358724 Binary files /dev/null and b/Content/ToolFunction/04Materials/Model/M_ModelChangeColorBase_ModelData.uasset differ diff --git a/Content/ToolFunction/04Materials/Model/M_ModelChangeColorTrans.uasset b/Content/ToolFunction/04Materials/Model/M_ModelChangeColorTrans.uasset new file mode 100644 index 0000000..36fdeee Binary files /dev/null and b/Content/ToolFunction/04Materials/Model/M_ModelChangeColorTrans.uasset differ diff --git a/Content/ToolFunction/04Materials/Ocean/MF_MyCesiumWaterMaskSample.uasset b/Content/ToolFunction/04Materials/Ocean/MF_MyCesiumWaterMaskSample.uasset new file mode 100644 index 0000000..945da30 Binary files /dev/null and b/Content/ToolFunction/04Materials/Ocean/MF_MyCesiumWaterMaskSample.uasset differ diff --git a/Content/ToolFunction/04Materials/Ocean/MI_MyCesiumThreeOverlaysAndClippingAndWater_Inst.uasset b/Content/ToolFunction/04Materials/Ocean/MI_MyCesiumThreeOverlaysAndClippingAndWater_Inst.uasset new file mode 100644 index 0000000..13e36a8 Binary files /dev/null and b/Content/ToolFunction/04Materials/Ocean/MI_MyCesiumThreeOverlaysAndClippingAndWater_Inst.uasset differ diff --git a/Content/ToolFunction/04Materials/Ocean/ML_MyCesiumWaterMask.uasset b/Content/ToolFunction/04Materials/Ocean/ML_MyCesiumWaterMask.uasset new file mode 100644 index 0000000..92919f3 Binary files /dev/null and b/Content/ToolFunction/04Materials/Ocean/ML_MyCesiumWaterMask.uasset differ diff --git a/Content/ToolFunction/04Materials/Ocean/ML_MyCesiumWaterMaskInst.uasset b/Content/ToolFunction/04Materials/Ocean/ML_MyCesiumWaterMaskInst.uasset new file mode 100644 index 0000000..e15b908 Binary files /dev/null and b/Content/ToolFunction/04Materials/Ocean/ML_MyCesiumWaterMaskInst.uasset differ diff --git a/Content/ToolFunction/04Materials/Thermal/M_PP_Thermal.uasset b/Content/ToolFunction/04Materials/Thermal/M_PP_Thermal.uasset new file mode 100644 index 0000000..1d70220 Binary files /dev/null and b/Content/ToolFunction/04Materials/Thermal/M_PP_Thermal.uasset differ diff --git a/Content/ToolFunction/04Materials/UI/MPC_UIBase.uasset b/Content/ToolFunction/04Materials/UI/MPC_UIBase.uasset new file mode 100644 index 0000000..bbdee1a Binary files /dev/null and b/Content/ToolFunction/04Materials/UI/MPC_UIBase.uasset differ diff --git a/Content/ToolFunction/04Materials/UI/M_UIBase.uasset b/Content/ToolFunction/04Materials/UI/M_UIBase.uasset new file mode 100644 index 0000000..5cf858e Binary files /dev/null and b/Content/ToolFunction/04Materials/UI/M_UIBase.uasset differ diff --git a/Content/ToolFunction/04Materials/UI/M_UIBase_Inst.uasset b/Content/ToolFunction/04Materials/UI/M_UIBase_Inst.uasset new file mode 100644 index 0000000..67c0d9f Binary files /dev/null and b/Content/ToolFunction/04Materials/UI/M_UIBase_Inst.uasset differ diff --git a/Content/ToolFunction/04Materials/WidgetCompnent/Widget3DPassThrough.uasset b/Content/ToolFunction/04Materials/WidgetCompnent/Widget3DPassThrough.uasset new file mode 100644 index 0000000..c4f4bc4 Binary files /dev/null and b/Content/ToolFunction/04Materials/WidgetCompnent/Widget3DPassThrough.uasset differ diff --git a/Content/ToolFunction/04Materials/WidgetCompnent/Widget3DPassThrough02.uasset b/Content/ToolFunction/04Materials/WidgetCompnent/Widget3DPassThrough02.uasset new file mode 100644 index 0000000..b61d40d Binary files /dev/null and b/Content/ToolFunction/04Materials/WidgetCompnent/Widget3DPassThrough02.uasset differ diff --git a/Content/ToolFunction/04Materials/WidgetCompnent/Widget3DPassThrough_Inst.uasset b/Content/ToolFunction/04Materials/WidgetCompnent/Widget3DPassThrough_Inst.uasset new file mode 100644 index 0000000..ed38b9c Binary files /dev/null and b/Content/ToolFunction/04Materials/WidgetCompnent/Widget3DPassThrough_Inst.uasset differ diff --git a/Content/ToolFunction/06Data/Curve/CurveA_LightWave.uasset b/Content/ToolFunction/06Data/Curve/CurveA_LightWave.uasset new file mode 100644 index 0000000..fe97941 Binary files /dev/null and b/Content/ToolFunction/06Data/Curve/CurveA_LightWave.uasset differ diff --git a/Content/ToolFunction/06Data/Curve/Curve_FollowView.uasset b/Content/ToolFunction/06Data/Curve/Curve_FollowView.uasset new file mode 100644 index 0000000..0c5a09a Binary files /dev/null and b/Content/ToolFunction/06Data/Curve/Curve_FollowView.uasset differ diff --git a/Content/ToolFunction/06Data/Curve/Curve_LightWave.uasset b/Content/ToolFunction/06Data/Curve/Curve_LightWave.uasset new file mode 100644 index 0000000..d3f8c36 Binary files /dev/null and b/Content/ToolFunction/06Data/Curve/Curve_LightWave.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/E_AddFunctionType.uasset b/Content/ToolFunction/06Data/Enum/E_AddFunctionType.uasset new file mode 100644 index 0000000..a646b19 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/E_AddFunctionType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/E_MarkType.uasset b/Content/ToolFunction/06Data/Enum/E_MarkType.uasset new file mode 100644 index 0000000..97b847e Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/E_MarkType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Effect/E_EffectType.uasset b/Content/ToolFunction/06Data/Enum/Effect/E_EffectType.uasset new file mode 100644 index 0000000..645f7e4 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Effect/E_EffectType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Effect/E_GoodsCheckType.uasset b/Content/ToolFunction/06Data/Enum/Effect/E_GoodsCheckType.uasset new file mode 100644 index 0000000..723cd88 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Effect/E_GoodsCheckType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Effect/Model/E_ModelAnimType.uasset b/Content/ToolFunction/06Data/Enum/Effect/Model/E_ModelAnimType.uasset new file mode 100644 index 0000000..6a15aa8 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Effect/Model/E_ModelAnimType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Effect/Model/E_ModelMoverControlType.uasset b/Content/ToolFunction/06Data/Enum/Effect/Model/E_ModelMoverControlType.uasset new file mode 100644 index 0000000..26ec9b5 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Effect/Model/E_ModelMoverControlType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Effect/Model/E_ModelMoverMode.uasset b/Content/ToolFunction/06Data/Enum/Effect/Model/E_ModelMoverMode.uasset new file mode 100644 index 0000000..02eba39 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Effect/Model/E_ModelMoverMode.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Effect/Model/E_MoverLineMode.uasset b/Content/ToolFunction/06Data/Enum/Effect/Model/E_MoverLineMode.uasset new file mode 100644 index 0000000..7f60e07 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Effect/Model/E_MoverLineMode.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Effect/Wall/E_MarkWallType.uasset b/Content/ToolFunction/06Data/Enum/Effect/Wall/E_MarkWallType.uasset new file mode 100644 index 0000000..6ccdf33 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Effect/Wall/E_MarkWallType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Language/E_LanguageType.uasset b/Content/ToolFunction/06Data/Enum/Language/E_LanguageType.uasset new file mode 100644 index 0000000..650524e Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Language/E_LanguageType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/MarkPoint/E_MilitaryLOGOType.uasset b/Content/ToolFunction/06Data/Enum/MarkPoint/E_MilitaryLOGOType.uasset new file mode 100644 index 0000000..9b02b61 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/MarkPoint/E_MilitaryLOGOType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/MarkPoint/E_PointStatsType.uasset b/Content/ToolFunction/06Data/Enum/MarkPoint/E_PointStatsType.uasset new file mode 100644 index 0000000..425c85a Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/MarkPoint/E_PointStatsType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/MarkPoint/E_PointWidgetType.uasset b/Content/ToolFunction/06Data/Enum/MarkPoint/E_PointWidgetType.uasset new file mode 100644 index 0000000..7c37b3b Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/MarkPoint/E_PointWidgetType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Measure/E_MeasureType.uasset b/Content/ToolFunction/06Data/Enum/Measure/E_MeasureType.uasset new file mode 100644 index 0000000..80ca8e4 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Measure/E_MeasureType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/SecondEdit/E_SecondEditType.uasset b/Content/ToolFunction/06Data/Enum/SecondEdit/E_SecondEditType.uasset new file mode 100644 index 0000000..d702315 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/SecondEdit/E_SecondEditType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Widget/E_ColorChangeType.uasset b/Content/ToolFunction/06Data/Enum/Widget/E_ColorChangeType.uasset new file mode 100644 index 0000000..8bd9e47 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Widget/E_ColorChangeType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Widget/E_CounterType.uasset b/Content/ToolFunction/06Data/Enum/Widget/E_CounterType.uasset new file mode 100644 index 0000000..4c2566a Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Widget/E_CounterType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Widget/E_SelectorPanelType.uasset b/Content/ToolFunction/06Data/Enum/Widget/E_SelectorPanelType.uasset new file mode 100644 index 0000000..24b7fa0 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Widget/E_SelectorPanelType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Widget/E_SwitchType.uasset b/Content/ToolFunction/06Data/Enum/Widget/E_SwitchType.uasset new file mode 100644 index 0000000..49e49e4 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Widget/E_SwitchType.uasset differ diff --git a/Content/ToolFunction/06Data/Enum/Widget/TopDialog/E_TopDialogType.uasset b/Content/ToolFunction/06Data/Enum/Widget/TopDialog/E_TopDialogType.uasset new file mode 100644 index 0000000..9c74f86 Binary files /dev/null and b/Content/ToolFunction/06Data/Enum/Widget/TopDialog/E_TopDialogType.uasset differ diff --git a/Content/ToolFunction/08MyFunctionLibrary/MacroLibrary/ML_MyActor.uasset b/Content/ToolFunction/08MyFunctionLibrary/MacroLibrary/ML_MyActor.uasset new file mode 100644 index 0000000..0d701ad Binary files /dev/null and b/Content/ToolFunction/08MyFunctionLibrary/MacroLibrary/ML_MyActor.uasset differ diff --git a/Content/ToolFunction/08MyFunctionLibrary/MacroLibrary/ML_UserWidget.uasset b/Content/ToolFunction/08MyFunctionLibrary/MacroLibrary/ML_UserWidget.uasset new file mode 100644 index 0000000..5511657 Binary files /dev/null and b/Content/ToolFunction/08MyFunctionLibrary/MacroLibrary/ML_UserWidget.uasset differ diff --git a/Content/ToolFunction/08MyFunctionLibrary/Materials/MyLocalMoveAlignedTexture.uasset b/Content/ToolFunction/08MyFunctionLibrary/Materials/MyLocalMoveAlignedTexture.uasset new file mode 100644 index 0000000..9664770 Binary files /dev/null and b/Content/ToolFunction/08MyFunctionLibrary/Materials/MyLocalMoveAlignedTexture.uasset differ diff --git a/Content/ToolFunction/08MyFunctionLibrary/Materials/MyLocalStaticAlignedTexture.uasset b/Content/ToolFunction/08MyFunctionLibrary/Materials/MyLocalStaticAlignedTexture.uasset new file mode 100644 index 0000000..05f48d6 Binary files /dev/null and b/Content/ToolFunction/08MyFunctionLibrary/Materials/MyLocalStaticAlignedTexture.uasset differ diff --git a/Content/ToolFunction/08MyFunctionLibrary/Materials/MyWorldMoveAlignedTexture1.uasset b/Content/ToolFunction/08MyFunctionLibrary/Materials/MyWorldMoveAlignedTexture1.uasset new file mode 100644 index 0000000..507491a Binary files /dev/null and b/Content/ToolFunction/08MyFunctionLibrary/Materials/MyWorldMoveAlignedTexture1.uasset differ diff --git a/Content/ToolFunction/09Font/ALIMAMASHUHEITI-BOLD.uasset b/Content/ToolFunction/09Font/ALIMAMASHUHEITI-BOLD.uasset new file mode 100644 index 0000000..6e37720 Binary files /dev/null and b/Content/ToolFunction/09Font/ALIMAMASHUHEITI-BOLD.uasset differ diff --git a/Content/ToolFunction/09Font/ALIMAMASHUHEITI-BOLD_Font.uasset b/Content/ToolFunction/09Font/ALIMAMASHUHEITI-BOLD_Font.uasset new file mode 100644 index 0000000..f27364d Binary files /dev/null and b/Content/ToolFunction/09Font/ALIMAMASHUHEITI-BOLD_Font.uasset differ diff --git a/Content/ToolFunction/09Font/FontLibrary/庞门正道/PangMenZhengDaoBiaoTiTi-1.uasset b/Content/ToolFunction/09Font/FontLibrary/庞门正道/PangMenZhengDaoBiaoTiTi-1.uasset new file mode 100644 index 0000000..56cf01e Binary files /dev/null and b/Content/ToolFunction/09Font/FontLibrary/庞门正道/PangMenZhengDaoBiaoTiTi-1.uasset differ diff --git a/Content/ToolFunction/09Font/FontLibrary/庞门正道/PangMenZhengDaoBiaoTiTi-1_Font.uasset b/Content/ToolFunction/09Font/FontLibrary/庞门正道/PangMenZhengDaoBiaoTiTi-1_Font.uasset new file mode 100644 index 0000000..a1e4799 Binary files /dev/null and b/Content/ToolFunction/09Font/FontLibrary/庞门正道/PangMenZhengDaoBiaoTiTi-1_Font.uasset differ diff --git a/Content/ToolFunction/09Font/FontLibrary/思源黑体/SourceHanSansCN-Bold.uasset b/Content/ToolFunction/09Font/FontLibrary/思源黑体/SourceHanSansCN-Bold.uasset new file mode 100644 index 0000000..25f5a4b Binary files /dev/null and b/Content/ToolFunction/09Font/FontLibrary/思源黑体/SourceHanSansCN-Bold.uasset differ diff --git a/Content/ToolFunction/09Font/FontLibrary/思源黑体/SourceHanSansCN-Bold_Font.uasset b/Content/ToolFunction/09Font/FontLibrary/思源黑体/SourceHanSansCN-Bold_Font.uasset new file mode 100644 index 0000000..66963a5 Binary files /dev/null and b/Content/ToolFunction/09Font/FontLibrary/思源黑体/SourceHanSansCN-Bold_Font.uasset differ diff --git a/Content/ToolFunction/09Font/FontLibrary/数黑体/AlimamaShuHeiTi-Bold.uasset b/Content/ToolFunction/09Font/FontLibrary/数黑体/AlimamaShuHeiTi-Bold.uasset new file mode 100644 index 0000000..02b4c68 Binary files /dev/null and b/Content/ToolFunction/09Font/FontLibrary/数黑体/AlimamaShuHeiTi-Bold.uasset differ diff --git a/Content/ToolFunction/09Font/FontLibrary/数黑体/AlimamaShuHeiTi-Bold_Font.uasset b/Content/ToolFunction/09Font/FontLibrary/数黑体/AlimamaShuHeiTi-Bold_Font.uasset new file mode 100644 index 0000000..f2811e2 Binary files /dev/null and b/Content/ToolFunction/09Font/FontLibrary/数黑体/AlimamaShuHeiTi-Bold_Font.uasset differ diff --git a/Content/ToolFunction/MrBlue/BP/10-Spline_PolygonDecal/Render/M_Decal_2.uasset b/Content/ToolFunction/MrBlue/BP/10-Spline_PolygonDecal/Render/M_Decal_2.uasset new file mode 100644 index 0000000..b7bb389 Binary files /dev/null and b/Content/ToolFunction/MrBlue/BP/10-Spline_PolygonDecal/Render/M_Decal_2.uasset differ diff --git a/Content/ToolFunction/MrBlue/BP/10-Spline_PolygonDecal/Render/M_Decal_2_Inst.uasset b/Content/ToolFunction/MrBlue/BP/10-Spline_PolygonDecal/Render/M_Decal_2_Inst.uasset new file mode 100644 index 0000000..db9e34b Binary files /dev/null and b/Content/ToolFunction/MrBlue/BP/10-Spline_PolygonDecal/Render/M_Decal_2_Inst.uasset differ diff --git a/Content/ToolFunction/MrBlue/BP/10-Spline_PolygonDecal/Render/TextureRenderTarget_text.uasset b/Content/ToolFunction/MrBlue/BP/10-Spline_PolygonDecal/Render/TextureRenderTarget_text.uasset new file mode 100644 index 0000000..8b76813 Binary files /dev/null and b/Content/ToolFunction/MrBlue/BP/10-Spline_PolygonDecal/Render/TextureRenderTarget_text.uasset differ diff --git a/Content/ToolFunction/PathTracer/Blueprints/E_PT_PathType.uasset b/Content/ToolFunction/PathTracer/Blueprints/E_PT_PathType.uasset new file mode 100644 index 0000000..b6a6523 Binary files /dev/null and b/Content/ToolFunction/PathTracer/Blueprints/E_PT_PathType.uasset differ diff --git a/Content/ToolFunction/PathTracer/Blueprints/Path_Marks/BP_PathMark_Master.uasset b/Content/ToolFunction/PathTracer/Blueprints/Path_Marks/BP_PathMark_Master.uasset new file mode 100644 index 0000000..23d9ade Binary files /dev/null and b/Content/ToolFunction/PathTracer/Blueprints/Path_Marks/BP_PathMark_Master.uasset differ diff --git a/Content/ToolFunction/PathTracer/Materials/MaterialFunctions/MF_DottedLine.uasset b/Content/ToolFunction/PathTracer/Materials/MaterialFunctions/MF_DottedLine.uasset new file mode 100644 index 0000000..b9ed306 Binary files /dev/null and b/Content/ToolFunction/PathTracer/Materials/MaterialFunctions/MF_DottedLine.uasset differ diff --git a/Content/ToolFunction/PathTracer/Materials/MaterialFunctions/MF_PT_StartAndEndTranslucent.uasset b/Content/ToolFunction/PathTracer/Materials/MaterialFunctions/MF_PT_StartAndEndTranslucent.uasset new file mode 100644 index 0000000..6a4e490 Binary files /dev/null and b/Content/ToolFunction/PathTracer/Materials/MaterialFunctions/MF_PT_StartAndEndTranslucent.uasset differ diff --git a/Content/ToolFunction/PathTracer/Materials/Path/M_PT_Color.uasset b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_Color.uasset new file mode 100644 index 0000000..1a6652c Binary files /dev/null and b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_Color.uasset differ diff --git a/Content/ToolFunction/PathTracer/Materials/Path/M_PT_Color_Masked.uasset b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_Color_Masked.uasset new file mode 100644 index 0000000..3e14c6f Binary files /dev/null and b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_Color_Masked.uasset differ diff --git a/Content/ToolFunction/PathTracer/Materials/Path/M_PT_DebugRandomColor.uasset b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_DebugRandomColor.uasset new file mode 100644 index 0000000..56ae359 Binary files /dev/null and b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_DebugRandomColor.uasset differ diff --git a/Content/ToolFunction/PathTracer/Materials/Path/M_PT_DottedLine_Anim.uasset b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_DottedLine_Anim.uasset new file mode 100644 index 0000000..fa1de5a Binary files /dev/null and b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_DottedLine_Anim.uasset differ diff --git a/Content/ToolFunction/PathTracer/Materials/Path/M_PT_DottedLine_Anim_ThroughWall.uasset b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_DottedLine_Anim_ThroughWall.uasset new file mode 100644 index 0000000..69c8637 Binary files /dev/null and b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_DottedLine_Anim_ThroughWall.uasset differ diff --git a/Content/ToolFunction/PathTracer/Materials/Path/M_PT_DottedLine_Anim_ThroughWall_Masked.uasset b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_DottedLine_Anim_ThroughWall_Masked.uasset new file mode 100644 index 0000000..408b6a3 Binary files /dev/null and b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_DottedLine_Anim_ThroughWall_Masked.uasset differ diff --git a/Content/ToolFunction/PathTracer/Materials/Path/M_PT_Translucent.uasset b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_Translucent.uasset new file mode 100644 index 0000000..be4aaf6 Binary files /dev/null and b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_Translucent.uasset differ diff --git a/Content/ToolFunction/PathTracer/Materials/Path/M_PT_Translucent_ThroughWall.uasset b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_Translucent_ThroughWall.uasset new file mode 100644 index 0000000..9e1a5de Binary files /dev/null and b/Content/ToolFunction/PathTracer/Materials/Path/M_PT_Translucent_ThroughWall.uasset differ diff --git a/Content/ToolFunction/PathTracer/Materials/Textures/T_PT_Mask_25.uasset b/Content/ToolFunction/PathTracer/Materials/Textures/T_PT_Mask_25.uasset new file mode 100644 index 0000000..c4a2578 Binary files /dev/null and b/Content/ToolFunction/PathTracer/Materials/Textures/T_PT_Mask_25.uasset differ diff --git a/Content/ToolFunction/PathTracer/Materials/Textures/T_PT_WhiteSquare.uasset b/Content/ToolFunction/PathTracer/Materials/Textures/T_PT_WhiteSquare.uasset new file mode 100644 index 0000000..355f35c Binary files /dev/null and b/Content/ToolFunction/PathTracer/Materials/Textures/T_PT_WhiteSquare.uasset differ diff --git a/Content/ToolFunction/PathTracer/Meshes/SM_Cylinder_Corner.uasset b/Content/ToolFunction/PathTracer/Meshes/SM_Cylinder_Corner.uasset new file mode 100644 index 0000000..d7b50b0 Binary files /dev/null and b/Content/ToolFunction/PathTracer/Meshes/SM_Cylinder_Corner.uasset differ diff --git a/Content/ToolFunction/PathTracer/Meshes/SM_Cylinder_Line.uasset b/Content/ToolFunction/PathTracer/Meshes/SM_Cylinder_Line.uasset new file mode 100644 index 0000000..9c1a523 Binary files /dev/null and b/Content/ToolFunction/PathTracer/Meshes/SM_Cylinder_Line.uasset differ diff --git a/Content/ToolFunction/PathTracer/Meshes/SM_Cylinder_Line1.uasset b/Content/ToolFunction/PathTracer/Meshes/SM_Cylinder_Line1.uasset new file mode 100644 index 0000000..e991259 Binary files /dev/null and b/Content/ToolFunction/PathTracer/Meshes/SM_Cylinder_Line1.uasset differ diff --git a/Content/ToolFunction/PathTracer/Showcase/ShowcaseBlueprints/UI/Icons/T_Path_Icon.uasset b/Content/ToolFunction/PathTracer/Showcase/ShowcaseBlueprints/UI/Icons/T_Path_Icon.uasset new file mode 100644 index 0000000..24ec74d Binary files /dev/null and b/Content/ToolFunction/PathTracer/Showcase/ShowcaseBlueprints/UI/Icons/T_Path_Icon.uasset differ diff --git a/Content/ToolFunction/PathTracer/Showcase/ShowcaseBlueprints/UI/Icons/T_Path_Icon_Mark.uasset b/Content/ToolFunction/PathTracer/Showcase/ShowcaseBlueprints/UI/Icons/T_Path_Icon_Mark.uasset new file mode 100644 index 0000000..8dda743 Binary files /dev/null and b/Content/ToolFunction/PathTracer/Showcase/ShowcaseBlueprints/UI/Icons/T_Path_Icon_Mark.uasset differ diff --git a/Content/ToolFunction/PolygonX/LineSegment.uasset b/Content/ToolFunction/PolygonX/LineSegment.uasset new file mode 100644 index 0000000..b2f3586 Binary files /dev/null and b/Content/ToolFunction/PolygonX/LineSegment.uasset differ diff --git a/Content/ToolFunction/PolygonX/PolygonX_Core.uasset b/Content/ToolFunction/PolygonX/PolygonX_Core.uasset new file mode 100644 index 0000000..6fbd9d8 Binary files /dev/null and b/Content/ToolFunction/PolygonX/PolygonX_Core.uasset differ diff --git a/Content/ToolFunction/PolygonX/VertIndex.uasset b/Content/ToolFunction/PolygonX/VertIndex.uasset new file mode 100644 index 0000000..48a0c40 Binary files /dev/null and b/Content/ToolFunction/PolygonX/VertIndex.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_HeatDist_01.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_HeatDist_01.uasset new file mode 100644 index 0000000..6d5d006 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_HeatDist_01.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_LargeScaleFire_01.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_LargeScaleFire_01.uasset new file mode 100644 index 0000000..aeeef0b Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_LargeScaleFire_01.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_LargeScaleFire_01_LOD1.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_LargeScaleFire_01_LOD1.uasset new file mode 100644 index 0000000..0f291c7 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_LargeScaleFire_01_LOD1.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_LargeScaleFire_02.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_LargeScaleFire_02.uasset new file mode 100644 index 0000000..5d1d193 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_LargeScaleFire_02.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_LargeScaleFire_02_LOD1.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_LargeScaleFire_02_LOD1.uasset new file mode 100644 index 0000000..2290337 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_LargeScaleFire_02_LOD1.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_01.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_01.uasset new file mode 100644 index 0000000..c046cc5 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_01.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_01_LOD1.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_01_LOD1.uasset new file mode 100644 index 0000000..e8bd624 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_01_LOD1.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_02.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_02.uasset new file mode 100644 index 0000000..6653e5e Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_02.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_02_LOD1.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_02_LOD1.uasset new file mode 100644 index 0000000..0f95d72 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_02_LOD1.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_03.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_03.uasset new file mode 100644 index 0000000..1644186 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_03.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_03_LOD1.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_03_LOD1.uasset new file mode 100644 index 0000000..f02d5a5 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_ThickSmoke_03_LOD1.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_spark_01.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_spark_01.uasset new file mode 100644 index 0000000..9fb4385 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/MI_spark_01.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/M_BaseHeatDist_01.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/M_BaseHeatDist_01.uasset new file mode 100644 index 0000000..17712d3 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/M_BaseHeatDist_01.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/M_BaseThickSmoke_01.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/M_BaseThickSmoke_01.uasset new file mode 100644 index 0000000..9457a6d Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/M_BaseThickSmoke_01.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/M_Base_Fire_01.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/M_Base_Fire_01.uasset new file mode 100644 index 0000000..77f98e8 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/M_Base_Fire_01.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/M_Base_Spark_01.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/M_Base_Spark_01.uasset new file mode 100644 index 0000000..37b572c Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Mats/M_Base_Spark_01.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_LargeScaleFire_01_SCALABLE.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_LargeScaleFire_01_SCALABLE.uasset new file mode 100644 index 0000000..148c0d1 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_LargeScaleFire_01_SCALABLE.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_LargeScaleFire_01_SCALABLE1.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_LargeScaleFire_01_SCALABLE1.uasset new file mode 100644 index 0000000..0f667bb Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_LargeScaleFire_01_SCALABLE1.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_LargeScaleFire_01_SCALABLE2.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_LargeScaleFire_01_SCALABLE2.uasset new file mode 100644 index 0000000..f27f8bb Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_LargeScaleFire_01_SCALABLE2.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_Smoke_Black_Dense_01_SCALABLE.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_Smoke_Black_Dense_01_SCALABLE.uasset new file mode 100644 index 0000000..fdddb26 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_Smoke_Black_Dense_01_SCALABLE.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_Smoke_Black_Dense_01_SCALABLE1.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_Smoke_Black_Dense_01_SCALABLE1.uasset new file mode 100644 index 0000000..117503f Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/PS_Smoke_Black_Dense_01_SCALABLE1.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_dist_normal_map_1K.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_dist_normal_map_1K.uasset new file mode 100644 index 0000000..bc1a440 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_dist_normal_map_1K.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_fire_loop_01_4k.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_fire_loop_01_4k.uasset new file mode 100644 index 0000000..e803fe7 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_fire_loop_01_4k.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_large_scale_fire_loop_01_1k.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_large_scale_fire_loop_01_1k.uasset new file mode 100644 index 0000000..35f7ff0 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_large_scale_fire_loop_01_1k.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_large_scale_fire_loop_01_4k.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_large_scale_fire_loop_01_4k.uasset new file mode 100644 index 0000000..fde7dee Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_large_scale_fire_loop_01_4k.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_large_scale_fire_loop_02_1k.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_large_scale_fire_loop_02_1k.uasset new file mode 100644 index 0000000..44be20c Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_large_scale_fire_loop_02_1k.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_large_scale_fire_loop_02_4k.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_large_scale_fire_loop_02_4k.uasset new file mode 100644 index 0000000..2a86368 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_large_scale_fire_loop_02_4k.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_smoke_loop_01_4k.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_smoke_loop_01_4k.uasset new file mode 100644 index 0000000..198c9a7 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_smoke_loop_01_4k.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_spark_tex_16x16_LOD1.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_spark_tex_16x16_LOD1.uasset new file mode 100644 index 0000000..11ddc6b Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_spark_tex_16x16_LOD1.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_01_1k.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_01_1k.uasset new file mode 100644 index 0000000..2652bbc Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_01_1k.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_01_4k.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_01_4k.uasset new file mode 100644 index 0000000..e0ac298 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_01_4k.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_02_1k.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_02_1k.uasset new file mode 100644 index 0000000..2e294c5 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_02_1k.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_02_4k.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_02_4k.uasset new file mode 100644 index 0000000..4492869 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_02_4k.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_03_1k.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_03_1k.uasset new file mode 100644 index 0000000..f9cf103 Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_03_1k.uasset differ diff --git a/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_03_4k.uasset b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_03_4k.uasset new file mode 100644 index 0000000..360983f Binary files /dev/null and b/Content/ToolFunction/Realistic_Fire_FX/ParticleSystems/Textures/T_thick_smoke_loop_03_4k.uasset differ diff --git a/Plugins/CesiumForUnreal/CHANGES.md b/Plugins/CesiumForUnreal/CHANGES.md new file mode 100644 index 0000000..9562d0e --- /dev/null +++ b/Plugins/CesiumForUnreal/CHANGES.md @@ -0,0 +1,1075 @@ +# Change Log + +### v2.12.0 - 2025-01-02 + +##### Breaking Changes :mega: + +- Removed support for Unreal Engine 5.2. Unreal Engine 5.3 or later is now required. +- Renamed `FCesiumFeatureIdAttribute::GetFeatureIDForVertex` to `FCesiumFeatureIdAttribute::GetFeatureID`. +- Renamed `FCesiumFeatureIdAttribute::GetVertexCount` to `FCesiumFeatureIdAttribute::GetCount`. + +##### Additions :tada: + +- Added support for metadata querying and styling on instanced models. + +##### Fixes :wrench: + +- Fixed a bug in `CesiumSubLevelSwitcherComponent` that could prevent all sub-levels from loading if a single sub-level failed to load. + +This release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.42.0 to v0.43.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.11.0 - 2024-12-02 + +This is the last release of Cesium for Unreal that will support Unreal Engine v5.2. Future versions will require Unreal Engine v5.3+. + +##### Additions :tada: + +- Added support for Unreal Engine 5.5. +- Added a "From Ellipsoid" option to `Cesium3DTileset` to generate a tileset by tessellating the surface of the ellipsoid, producing a simple globe tileset without terrain features. + +##### Fixes :wrench: + +- Fixed a crash that could occur when using `SampleHeightMostDetailed` on a `Cesium3DTileset` with a raster overlay. +- `CesiumPolygonRasterOverlay` now references `CesiumCartographicPolygon` instances using `TSoftObjectPtr`, which allows, for example, a raster overlay in the persistent level to use a polygon in a sub-level. +- Fixed an overlay artifact bug that could occur when a `Cesium3DTileset` had three or more overlays. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.41.0 to v0.42.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.10.0 - 2024-11-01 + +##### Additions :tada: + +- Added `CircumscribedGroundHeight` property to `CesiumSunSky`. It defaults to 0, which is consistent with the previous behavior. It can be set to a larger value (like 40) to avoid dark splotchy artifacts when zoomed out far from the globe in certain tilesets where geometry extends very far beyond the ellipsoid in the low-detail representation, such as Google Photorealistic 3D Tiles. +- Added a shared assets system that ensures external images referenced by different glTFs will only be loaded once per image. Previously, these images would be loaded again for each glTF that referenced them. This significantly reduces memory usage for tilesets that reuse the same textures. + +##### Fixes :wrench: + +- Fixed a bug that caused incorrect lighting for tilesets using `KHR_materials_unlit`. +- Reduced the memory used by tiles with `KHR_materials_unlit`. +- `CesiumGlobeAnchor` properties are no longer shown on the main `CesiumSunSky` Details panel, because it is almost never necessary to set these. They can still be set on the component's own Details panel if needed. +- Fixed error messages in the Unreal log about uninitialized fields in `FCesiumSampleHeightResult`. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.40.1 to v0.41.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.9.0 - 2024-10-01 + +##### Additions :tada: + +- Added `SampleHeightMostDetailed` function to `Cesium3DTileset`, which asynchronously queries the height of a tileset at a list of positions. It is callable from both C++ and Blueprints. + +##### Fixes :wrench: + +- Drastically reduced tile mesh memory usage in UE 5.3 and 5.4 by working around a bug that causes those engine versions to add more texture coordinate sets than necessary. +- Fixed a bug where the `scale`, `noData`, and `default` values of a property in `EXT_strutural_metadata` were not correctly passed to the tileset's material. + +This release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.39.0 to v0.40.1. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.8.0 - 2024-09-02 + +##### Additions :tada: + +- Added universal (Intel and Apple Silicon) binaries for Unreal Engine 5.2. Unreal Engine 5.3 and 5.4 already had universal binaries. +- Raster overlays now have `bAllowAnyoneToDestroyMe` set to true by default. This allows them to be dynamically removed and destroyed at runtime via the Blueprint `Destroy Component` function called from anywhere, including Level Blueprints. Previously, attempting to delete a raster overlay from outside the Actor would result in an error. + +##### Fixes :wrench: + +- Fixed a bug introduced in the previous release that caused instanced tilesets to render incorrectly. +- Debug sections are no longer compressed on Linux and Android, improving compatibility. +- Fixed a bug where calling `Refresh` on a `CesiumRasterOverlay` would cause the overlay to appear on the Cesium3DTileset, even if inactive. + +This release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.38.0 to v0.39.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.7.1 - 2024-08-01 + +##### Fixes :wrench: + +- Improved collision and line tracing against tilesets by working around an overly-aggressive degenerate triangle check in the Chaos physics engine. +- Fixed a bug that could cause a `bad_any_cast` exception when trying to access glTF extensions on non-Windows platforms. This commonly popped up when loading tilesets with metadata. +- Fixed a bug that caused the `GetInteger64` functions on `CesiumMetadataValue`, `CesiumPropertyArray`, and `CesiumPropertyTableProperty` to always return the default value on non-Windows platforms. +- Fixed issue with `UCesiumGlobeAnchorComponent::GetEllipsoid` that caused compilation errors on some machines. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.37.0 to v0.38.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.7.0 - 2024-07-01 + +##### Additions :tada: + +- Cesium for Unreal now supports using non-WGS84 ellipsoids. + - An `CesiumEllipsoid` asset may be specified in the `Ellipsoid` field of a `CesiumGeoreference`. + - To create a `CesiumEllipsoid` asset, right-click in the Content Drawer and select "Data Asset" under "Miscellaneous." Choose "Cesium Ellipsoid" from the menu that appears. + +##### Fixes :wrench: + +- Fixed two problems with `CesiumCartographicRasterOverlay`: + - Small tiles would never be excluded, even with "Exclude Selected Tiles" enabled. + - Pieces of tiles would sometimes not have the raster overlay correctly applied to them. When using with clipping, this would cause bits of tiles to randomly appear inside the clipping polygon. +- Removed an unnecessary alpha check when selecting translucent base materials. +- Fixed a crash caused by `CesiumSunSky` when no viewport is activated in the Editor. +- Fixed build issues in Unreal 5.4.2 relating to `UStaticMesh` and `glm::toMat4`. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.36.0 to v0.37.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.6.0 - 2024-06-03 + +##### Breaking Changes :mega: + +- Renamed the following properties on `CesiumWebMapTileServiceRasterOverlay`: + - `Url` -> `BaseUrl` + - `West` -> `RectangleWest` + - `South` -> `RectangleSouth` + - `East` -> `RectangleEast` + - `North` -> `RectangleNorth` +- `UseWebMercatorProjection` has been deprecated on `CesiumWebMapTileServiceRasterOverlay`. Instead, use the `Projection` enum property to specify between `Geographic` or `WebMercator` projection. + +##### Additions :tada: + +- Added support for Instanced 3D Meshes (I3DM) and the glTF `EXT_mesh_gpu_instancing` extension. +- Improved DynamicPawn movement by interpolating to its intended speed. This provides smoother movement over areas with large height variation, e.g., when flying over buildings in a city. +- Added `TileWidth` and `TileHeight` properties to `CesiumWebMapTileServiceRasterOverlay`. + +##### Fixes :wrench: + +- Fixed an issue with pixel dithering artifacts that could appear on tilesets. +- Fixed an issue where DynamicPawn could get stuck after interrupting a flight from `UCesiumFlyToComponent`. +- Fixed a bug where `CesiumTileMapServiceRasterOverlay`, `CesiumWebMapServiceRasterOverlay`, and `CesiumWebMapTileServiceRasterOverlay` would attempt to load empty URLs. +- Fixed a bug that caused some textures shared between multiple glTF primitives to be missing entirely. +- Fixed a bug that caused tilesets to fail to load with the "Experimental Occlusion Culling Feature" enabled. +- Fixed a problem that could cause linker errors when packaging a game using both Cesium for Unreal and the Pixel Streaming plugin in Unreal Engine 5.4. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.35.0 to v0.36.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.5.0 - 2024-05-01 + +This is the last release of Cesium for Unreal that will support Unreal Engine v5.1. Future versions will require Unreal Engine v5.2+. + +##### Additions :tada: + +- Added support for Unreal Engine 5.4. +- Added support for Cesium ion servers in single user mode. Tokens are not required to stream assets from such servers. + +##### Fixes :wrench: + +- Fixed an issue where tilesets would render completely black on Quest headsets and some iOS devices. +- Fixed a crash on Unreal Editor shutdown that would occasionally happen due to attempts to access garbage-collected static classes. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.34.0 to v0.35.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.4.1 - 2024-04-01 + +This release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.33.0 to v0.34.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.4.0 - 2024-03-01 + +##### Additions :tada: + +- Significantly reduced CPU memory used by glTF and raster overlay textures. +- Improved texture creation performance on non-D3D platforms. +- Added support for the `KHR_texture_transform` glTF extension - including rotation - for `CesiumFeatureIdTexture` and `CesiumPropertyTextureProperty`. +- `CesiumFeaturesMetadataComponent` now generates nodes for `KHR_texture_transform` if the extension is present in a feature ID texture or property texture property. + +##### Fixes :wrench: + +- Metadata-related textures are now created in `TEXTUREGROUP_8BitData` instead of `TEXTUREGROUP_World`. +- Added some defensive nullptr checks to `CesiumSunSky`. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.32.0 to v0.33.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.3.0 - 2024-02-01 + +##### Additions :tada: + +- Added support for Web Map Tile Service (WMTS) with `CesiumWebMapTileServiceRasterOverlay`. +- Significantly reduced CPU memory usage by textures on non-Windows systems. +- Added support for the `KHR_texture_transform` glTF extension - including rotation - in `baseColorTexture`, `metallicRoughnessTexture`, `emissiveTexture`, `normalTexture`, and `occlusionTexture`. The transformation is now applied on the GPU via nodes in the Material, rather than on the CPU by directly modifying texture coordinates. + +##### Fixes :wrench: + +- Fixed a bug in `MLB_DitherFade` that made glTF materials with an `alphaMode` of `MASK` incorrectly appear as fully opaque. +- Fixed a bug in `CesiumFlyToComponent` that could cause the position of the object to shift suddenly at the very end of the flight. +- Fixed a bug that caused textures created by Cesium for Unreal on D3D11 and D3D12 (only) to not be counted in the "Texture Memory Used" stat in the "Memory" stat group or in any counter in the "TextureGroup" stat group. +- Fixed a bug in `CesiumGltfComponent` that would cause a crash if the `Ignore KHR_materials_unlit` setting was enabled on a point cloud. +- Fixed a bug in `CesiumActors` that would cause the editor to crash when running in Standalone mode. +- Fixed several build warnings when packing in Unreal Engine 5.3. +- Readded backwards compatibility for feature textures from `EXT_feature_metadata`, which was mistakenly removed. +- Fixed a bug that caused nav mesh creation to be slow due to creating duplicate physics meshes. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.31.0 to v0.32.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.2.0 - 2023-12-14 + +##### Breaking Changes :mega: + +- Deprecated `IonAssetEndpointUrl` on `Cesium3DTileset` and `CesiumIonRasterOverlay`. Use the new `CesiumIonServer` property instead. + +##### Additions :tada: + +- Added support for multiple Cesium ion servers by creating `CesiumIonServer` data assets. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.30.0 to v0.31.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.1.0 - 2023-12-01 + +##### Additions :tada: + +- Added support for styling with property textures in `EXT_structural_metadata`. +- Significantly improved tile download performance by adding `HttpThreadActiveFrameTimeInSeconds=0.001` to `Engine.ini`. This results in a major performance improvement for all tilesets, particularly Google Photorealistic 3D Tiles. +- Added `HttpMaxConnectionsPerServer=40` to `Engine.ini`. By default, only 16 connections are allowed, which limits the performance when downloading tiles. + +##### Fixes :wrench: + +- Fixed a bug in the "Select New Token" dialog that caused an error when trying to create a new token without being connected. +- Fixed a bug where an `EditConditio`n was not parsed correctly and caused Output Log window errors. +- Removed query parameters from filepaths if present, as they are no longer ignored by Unreal. This fixes a bug where the URL would not load correctly in some cases. +- Fixed a Tile Excluder bug that computed incorrect tile bounds, making tiles invisible when moving the tileset in the sample scene. +- Fixed a bug where viewports could appear wider than configured in the Dynamic Pawn's Camera Field of View. Noticed in Unreal Engine v5.3 when in Play-In-Editor mode, or a packaged game. In extreme cases, tiles would be missing near the edges of the view. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.29.0 to v0.30.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v2.0.0 - 2023-11-01 + +This release no longer supports Unreal Engine v5.0. Unreal Engine v5.1, v5.2, or v5.3 is required. + +##### Breaking Changes :mega: + +- Removed `FCesiumIntegerColor`, `FCesiumFloatColor`, `UCesiumFeatureTexturePropertyBlueprintLibrary::GetIntegerColorFromTextureCoordinates` and `UCesiumFeatureTexturePropertyBlueprintLibrary::GetFloatColorFromTextureCoordinates`. Check out the [upgrade guide](Documentation/upgrade-to-2.0-guide.md) for how retrieve metadata from property textures with the new API. +- Renamed `GetTextureCoordinateIndex` to `GetUnrealUVChannel` in both `UCesiumFeatureIdTextureBlueprintLibrary` and `UCesiumPropertyTexturePropertyBlueprintLibrary`. Contrary to what the documentation claimed, this function retrieved the index of the texture coordinate set in the _Unreal static mesh_, which is not necessarily equal to the texture coordinate set index in the _glTF primitive_. For the latter value, use `GetGltfTextureCoordinateSetIndex` instead. +- Removed the old "exclusion zones" feature, which has been deprecated since v1.11.0. Use `CesiumCartographicPolygon` or `CesiumTileExcluder` instead. + +##### Additions :tada: + +- Added new functions to `UCesiumPropertyTexturePropertyBlueprintLibrary` to retrieve detailed property information and get the values of the property as a certain type. Check out the [upgrade guide](Documentation/upgrade-to-2.0-guide.md) for how retrieve metadata from property textures with the new API. +- Added `UCesiumMetadataPickingBlueprintLibrary::FindUVFromHit`, which computes the UV coordinates from a line trace hit without requiring "Support UV Hit Info" to be enabled. This can used to retrieve more accurate feature IDs or metadata values by sampling at an intermediary point on the face. +- Added `GetPropertyTableValuesFromHit` and `GetPropertyTextureValuesFromHit` to `UCesiumMetadataPickingBlueprintLibrary` to retrieve the respective metadata from a line trace hit. For both functions, the target to sample is specified by index. +- Added `UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDFromHit` to retrieve the feature ID from a line trace hit on a primitive containing the feature ID set. This returns more accurate values for feature ID textures than `GetFeatureIDForVertex`. +- Added `UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromHit` to retrieve the feature ID from a line trace hit on a primitive, where the desired feature ID set is specified by index. For feature ID textures, this returns more accurate values than `GetFeatureIDFromFace`. +- Added `UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForUV`, which samples a feature ID texture with `FVector2D` UV coordinates. +- Added `GetGltfTextureCoordinateSetIndex` to `UCesiumFeatureIdTextureBlueprintLibrary` and `UCesiumPropertyTexturePropertyBlueprintLibrary` to avoid ambiguity with `GetUnrealUVChannel`. +- Added `UCesiumMetadataValueBlueprintLibrary::GetValuesAsStrings` to convert a map of `FCesiumMetadataValues` to their string representations. +- Added support for `file:///` URLs across all platforms and Unreal Engine versions. +- Added "Create Sub Level Here" button on `CesiumGeoreference`. +- Added "Please Georeference Origin Here" button to `CesiumSubLevelComponent`. +- Added "Google Photorealistic 3D Tiles" to the Quick Add panel. + +##### Fixes :wrench: + +- Fixed a bug that could cause tiles in a `Cesium3DTileset` to have an incorrect transformation. +- Fixed a crash that occurred when a `LevelSequenceActor` in the level did not have a `LevelSequencePlayer` assigned. +- Fixed a bug that would spam Georeference-related messages to the log when editing a globe anchor component that is not embedded in a world. For example, when editing a Blueprint asset with a globe anchor. +- Fixed several problems that could cause tilesets in sub-levels to be misaligned with the rest of the globe. + +##### Deprecated :hourglass: + +- `UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForTextureCoordinates` has been deprecated. Use `UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForUV` instead. +- `UCesiumPropertyTexturePropertyBlueprintLibrary::GetSwizzle` and `UCesiumPropertyTexturePropertyBlueprintLibrary::GetComponentCount` have been deprecated, since they are no longer necessary to handle property texture property values in the plugin. Use `UCesiumPropertyTexturePropertyBlueprintLibrary::GetChannels` instead. +- `UCesiumMetadataPickingBlueprintLibrary::GetMetadataValuesForFace` has been deprecated. Use `UCesiumMetadataPickingBlueprintLibrary::GetPropertyTableValuesForHit` instead. +- `UCesiumMetadataPickingBlueprintLibrary::GetMetadataValuesForFaceAsStrings` has been deprecated. Use `UCesiumMetadataValueBlueprintLibrary::GetValuesAsStrings` to convert the output of `UCesiumMetadataPickingBlueprintLibrary::GetPropertyTableValuesForHit` instead. +- `UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeatureAsStrings` has been deprecated. Use `UCesiumMetadataValueBlueprintLibrary::GetValuesAsStrings` to convert the output of `UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeature` instead. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.28.1 to v0.29.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.31.2 - 2023-10-26 + +This is the last release of Cesium for Unreal that will support Unreal Engine v5.0. Future versions will require Unreal Engine v5.1+. + +##### Additions :tada: + +- Added "Google Photorealistic 3D Tiles" to the Quick Add panel. + +### v2.0.0 Preview 1 - 2023-10-02 + +##### Breaking Changes :mega: + +- Feature IDs and metadata are now parsed through the `EXT_mesh_features` and `EXT_structural_metadata` extensions respectively. Models with `EXT_feature_metadata` will still be parsed, but their metadata will no longer be accessible. See the [upgrade guide](Documentation/upgrade-to-2.0-guide.md) for the full changelog and for tips on upgrading to the new API. +- Removed `CesiumMetadataFeatureTable`, `UCesiumMetadataFeatureTableBlueprintLibrary`, `UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureTables`, and `UCesiumMetadataUtilityBlueprintLibrary::GetFeatureIDForFace`. These have been deprecated since Unreal Engine 4.26. +- The old sub-level system, based on Unreal's old (and now deprecated) World Composition system, has been removed. Instead, create Level Instance Actors and attach the "Cesium Sub Level Component" to them to achieve similar functionality. Old levels will automatically be converted to the new system when they are loaded in the Editor. +- `CesiumSunSky` now uses a default `TransmittanceMinLightElevationAngle` value on its `SkyAtmosphere` component of 90.0 degrees instead of -90.0 degrees. This will generally improve lighting when far from the CesiumGeoreference origin, but it is a breaking change because it may change the lighting conditions in existing levels, particularly at sunrise and sunset. +- The `Mobility` property on `ACesium3DTileset` is now obsolete. Instead, use the normal mechanism of setting the root component's mobility. +- Removed many methods from the C++ interface of `ACesiumGeoreference` and `UCesiumGlobeAnchorComponent` that used `glm` vector types. Use the versions that work with Unreal types instead. +- The `ComputeEastSouthUpToUnreal` function on `ACesiumGeoreference` has been renamed to `ComputeEastSouthUpToUnrealTransformation` and now returns a matrix that includes the translation component of the transformation. Previously it only included the rotation component. +- Numerous properties on `CesiumGlobeAnchorComponent` must now be accessed with get/set functions from C++, instead of direct field access. +- Renamed the following on `CesiumGlobeAnchorComponent`: + - `GetECEF` renamed to `GetEarthCenteredEarthFixedPosition` + - `MoveToECEF` renamed to `MoveToEarthCenteredEarthFixedPosition` +- Deprecated the `InvalidateResolvedGeoreference` function on `CesiumGlobeAnchorComponent`. +- The `SubLevelCamera` property on `CesiumGeoreference` has been deprecated, and the georeference no longer automatically handles sub-level transitions. Instead, you must add a `CesiumOriginShiftComponent` to the `Actor` to trigger sub-level loading. When loading old levels that contain sub-levels, the plugin will automatically attempt to add this component. +- Removed the old `FloatingPawn` that has been deprecated since v1.3.0. +- Deprecated the flight functionality in `GlobeAwareDefaultPawn`. This functionality is now found in `CesiumFlyToComponent` and can be used with any Pawn or Actor. Existing Blueprints should continue to work, but C++ code will likely require changes. +- Renamed the various Curve assets used with flights to have more descriptive names and moved them to the `Curves/FlyTo` folder. Redirectors should upgrade references to the old names. + - `Curve_AltitudeProfile_Float` was renamed to `Curve_CesiumFlyToDefaultHeightPercentage_Float` + - `Curve_MaxAltitude_Float` was renamed to `Curve_CesiumFlyToDefaultMaximumHeightByDistance_Float` + - `Curve_Progress_Float` was renamed to `Curve_CesiumFlyToDefaultProgress_Float` + +##### Additions :tada: + +- The "Place Georeference Origin Here" action on CesiumGeoreference is now undoable. +- Cesium Actors now have the "Is Spatially Loaded" flag disabled by default. When using World Partition, this is essential for some, such as `CesiumGeoreference`. +- The `CesiumCameraManager` instance to use with a `Cesium3DTileset` can now be specified with a property on the tileset. In addition to offering more flexibility, this avoids the work of finding the camera manager in the level every frame. +- Cesium Actors created with the Quick Add or Cesium ion panels are now created inside the active sub-level, if there is one. +- Cesium objects in sub-levels can now explicitly reference `ACesiumGeoreference`, `ACesiumCreditSystem`, and `ACesiumCameraManager` instances in the Persistent Level. +- Added support for excluding Cesium Tiles from a tileset using the new `CesiumTileExcluder` actor component. This component can be used to implement custom logic for determining whether a tile should be excluded, either in C++ or Blueprints. +- `ACesiumGeoreference` can now act as a parent Actor. By adjusting the georeference's transformation, the entire globe can be located, rotated, and scaled within the Unreal Engine world. +- Added `AtmosphereHeight`, `AerialPerspectiveViewDistanceScale`, `RayleighExponentialDistribution`, and `MieExponentialDistribution` properties to `ACesiumSunSky`. These have the same function as the properties of the same name on Unreal's built-in SkyAtmosphere component, except that they automatically respond to the scale of the globe. +- Added `UCesiumWgs84Ellipsoid` Blueprint function library class. +- Longitude / Latitude / Height properties on CesiumGeoreference and CesiumGlobeAnchorComponent are now settable using degrees-minutes-seconds in addition to decimal degrees. +- Added the ability to interactively set the orientation of a `CesiumGlobeAnchorComponent` relative to an East-South-Up coordinate system. +- Added `ComputeEastSouthUpAtEarthCenteredEarthFixedPositionToUnrealTransformation` function to `CesiumGeoreference`. +- Added `CesiumOriginShiftComponent`. In addition to triggering transitions between sub-levels, this component optionally allows the Unreal world origin to be shifted as the Actor to which it is attached moves. The shifting may be done by either changing the `CesiumGeoreference` origin or by setting Unreal's `OriginLocation` property. +- Sub-level transitions can now be triggered manually from Blueprints using functions on the `CesiumSubLevelSwitcherComponent` attached to the `CesiumGeoreference`. Be sure to disable any `CesiumOriginShiftComponent` instances in your level if you want manual control of sub-level switching. +- Added `CesiumFlyToComponent` to allow animated flights of any Actor or Pawn. +- Globe aware objects now find their associated CesiumGeoreference by using `ACesiumGeoreference::GetDefaultDefaultGeoreferenceForActor`, which checks first for an attachment parent that is a CesiumGeoreference. This way a `Cesium3DTileset` or similar object will by associated with the CesiumGeoreference it is nested inside by default. +- The Quick Add panel now creates Actors nested inside a `CesiumGeoreference`. +- The `ResolvedGeoreference` is now shown in the Editor Details UI for georeferenced objects, next to the `Georeference` property. + +##### Fixes :wrench: + +- Fixed a bug in `ACesiumSunSky` that could cause an error when it was created inside a sub-level. +- `ACesiumGeoreference`, `ACesiumCameraManager`, and `ACesiumCreditSystem` are now created in the Persistent Level, even if the object that triggered their automatic creation (such as `ACesium3DTileset`) exists in a sub-level. It is very rarely useful to have instances of these objects within a sub-level. +- An instance of `ACesiumCreditSystem` in a sub-level will no longer cause overlapping and broken-looking credits. However, we still recommend deleting credit system instances from sub-levels. +- `ACesiumCartographicPolygon` now operates on the parts of the tileset that are shown in the Editor viewport, even if it is used with a Cesium3DTileset with a non-identity transformation. +- Fixed bug where older scenes that used Cesium UI created actors could have their `RF_Public` flag set. This could cause problems when converting an existing level to World Partition, or perhaps cause other subtle issues that we haven't realized yet. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.27.3 to v0.28.1. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.31.1 - 2023-10-02 + +This is the last release of Cesium for Unreal that will support Unreal Engine v5.0. Future versions will require Unreal Engine v5.1+. + +##### Fixes :wrench: + +- Fixed a bug that could crash the editor when selecting an individual tile in the viewport, then moving the camera to look at something else. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.27.2 to v0.27.3. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.31.0 - 2023-09-20 + +##### Additions :tada: + +- Added support for Unreal Engine 5.3. There is current a known issue with `Cesium3DTileset` textures on iOS, so we recommend that you continue to use Unreal Engine 5.2 for the time being if you are deploying to iOS. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.27.1 to v0.27.2. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.30.1 - 2023-09-03 + +This release fixes an important bug by updating [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.27.0 to v0.27.1. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.30.0 - 2023-09-01 + +This release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.26.0 to v0.27.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.29.0 - 2023-08-01 + +##### Fixes :wrench: + +- Fixed a bug introduced in v1.28.0 that prevented point clouds from rendering with attenuation. +- Fixed a bug where Google Photorealistic 3D Tiles would sometimes not render in Movie Render Queue. +- Fixed a bug that caused `UnrealLightmass` to crash when attempting to build lighting containing static meshes created by a `Cesium3DTileset`. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.25.1 to v0.26.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.28.0 - 2023-07-03 + +##### Breaking Changes :mega: + +- Removed the `GetGeoreferencedToEllipsoidCenteredTransform` and `GetEllipsoidCenteredToGeoreferencedTransform` methods from `GeoTransforms`. Because these were transformations between two right-handed coordinate systems, they are not of much use with Unreal's left-handed coordinate system. +- Deprecated the `FlyToGranularityDegrees` property for `AGlobeAwareDefaultPawn`. Flight interpolation is now computed per-frame, so this property is no longer needed. Any code that refers to `FlyToGranularityDegrees` should be removed or changed to `FlyToGranularityDegrees_DEPRECATED` to still compile. + +##### Additions :tada: + +- Added the ability to set the CesiumGeoreference `Scale` via Blueprints. +- Added `ACesiumCameraManager::RemoveCamera`. It is available via both Blueprints and C++. This complements the existing `ACesiumCameraManager::AddCamera`. + +##### Fixes :wrench: + +- Added a workaround for an apparent bug in Unreal Engine 5.1 that prevented collisions from working with Cesium3DTilesets. +- Fixed a bug that could cause the `AGlobeAwareDefaultPawn` / `DynamicPawn` to suddenly move to a very high height for one render frame just as it arrives at its destination during a flight. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.25.0 to v0.25.1. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.27.1 - 2023-06-19 + +##### Fixes :wrench: + +- Fixed a shader compilation error introduced in v1.27.0 that prevented projects from opening in Unreal Engine 5.1 and 5.2. +- Fixed a debug assertion `!IsGarbageCollecting()` that could occur within `ACesiumCreditSystem` when flying to different sublevels. + +### v1.27.0 - 2023-06-1 + +##### Additions :tada: + +- Added support for Unreal Engine 5.2. +- Added support for running Cesium for Unreal in the Unreal Editor in Linux under UE 5.2. Previous versions supported Linux only as a packaging target. +- Added point cloud shading options to `Cesium3DTileset`, which allow point cloud tilesets to be rendered with attenuation based on geometric error. +- `ACesium3DTileset` now emits a warning if the "Enable World Bounds Checks" option is enabled. That option can make the camera fly toward the origin unexpectedly. +- Added new settings to the Cesium section of the Project Settings, allowing users to control how many requests to handle before pruning and also how many elements to keep in the cache after pruning. + +##### Fixes :wrench: + +- Fixed a bug introduced in v1.26.0 that caused an error when attempting to save a sub-level containing Cesium objects. +- Removed degenerate triangles from the collision mesh created for 3D Tiles. This will avoid warnings and runtime pauses with some tilesets. +- Fixed a bug in `CesiumGlTFFunction` that caused the glTF and 3D Tiles "Ambient Occlusion" value to be 0.0 (instead of the expected 1.0) when the model does not specify an explicit occlusion texture. This could cause some extremely dark shadows. +- Fixed a bug that could cause a crash when using Cesium Actors with World Partitioning. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.24.0 to v0.25.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.26.0 - 2023-05-09 + +##### Additions :tada: + +- Added a `Scale` property to `CesiumGeoreference`. This allows the entire globe to be scaled up or down within the Unreal world. +- Tileset and raster overlay credits are now shown in Editor viewports. + +##### Fixes :wrench: + +- Fixed a bug in `ACesiumCartographicPolygon` where the standard base class `BeginPlay` implementation was not called. + +### v1.25.1 - 2023-05-02 + +##### Fixes :wrench: + +- Fixed warnings about `bUseChaos` and `bCompilePhysX` being obsolete. + +### v1.25.0 - 2023-05-01 + +Starting with this release, Cesium for Unreal requires Unreal Engine v5.0 or later. + +##### Fixes :wrench: + +- On-screen credits now only show on the screen, and not in the Data Attribution panel. Additionally, the Data Attribution panel no longer appears if there are no credits to display in it. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.23.0 to v0.24.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.24.0 - 2023-04-03 + +This will be the _last_ release that supports Unreal Engine v4.27. Future versions will require Unreal Engine v5.0+. + +##### Additions :tada: + +- The `FlyToAltitudeProfileCurve`, `FlyToProgressCurve`, `FlyToMaximumAltitudeCurve`, `FlyToDuration`, and `FlyToGranularityDegrees` properties of `GlobeAwareDefaultPawn` / `DynamicPawn` may now be read and written from Blueprints. +- Added an option on `Cesium3DTileset` to ignore the `KHR_materials_unlit` extension entirely and use normal lighting and shadows. +- Added `CreateNavCollision` property to `Cesium3DTileset`. When enabled, `CreateNavCollision` is called on the static meshes created for tiles. + +##### Fixes :wrench: + +- Fixed unexpected reflection on tilesets with `KHR_materials_unlit` extension when the sun is close to the horizon. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.22.0 to v0.23.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.23.0 - 2023-03-01 + +##### Additions :tada: + +- Added support for rendering 3D Tiles point clouds (`pnts`). + +##### Fixes :wrench: + +- Fixed bug that caused a crash when changing the project default token with tilesets active in the level. +- Vertex buffers created for 3D Tiles are now set to use full-precision UV coordinates, avoiding problems in particular with feature IDs. +- Added some missing headers, to avoid compiler errors in non-unity builds. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.21.3 to v0.22.1. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.22.0 - 2023-02-01 + +##### Additions :tada: + +- Added support for the `KHR_materials_unlit` glTF extension. This is rendered in Unreal Engine by disabling shadows and making all normals point up (along the ellipsoid surface normal). + +##### Fixes :wrench: + +- Fixed a bug that caused raster overlays and other material features to not work for materials created or saved in Unreal Engine 5.1. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.21.2 to v0.21.3. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.21.0 - 2023-01-02 + +##### Fixes :wrench: + +- Fixed a bug where Cesium for Unreal depended on a number of Unreal modules _privately_, but then used them from public headers. These are now declared as public dependencies. This could lead to compile errors in previous versions when attempting to include Cesium for Unreal headers from outside the project without also explicitly declaring `UMG` and other modules as dependencies. +- Fixed a bug that caused newly-created sub-levels to have their longitude and latitude parameters flipped relative to the current location of the `CesiumGeoreference`. + +### v1.20.1 - 2022-12-09 + +##### Additions :tada: + +- Added the ability to specify the endpoint URL of the Cesium ion API on a `CesiumIonRasterOverlay`. + +##### Fixes :wrench: + +- Fixed a bug that could cause crashes, including on startup, on non-Windows platforms. +- Fixed a bug that could cause the plugin to fail to load on Android systems in UE 5.1. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.21.1 to v0.21.2. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.20.0 - 2022-12-02 + +##### Breaking Changes :mega: + +- This is the _last release_ that will support Unreal Engine v4.26. Starting in the next release, in January 2023, UE 4.26 will no longer be supported. You may continue to use old versions of Cesium for Unreal in UE 4.26, but we recommend upgrading your UE version as soon as possible in order to continue receiving the latest updates. + +##### Additions :tada: + +- Added support for Unreal Engine v5.1. + +##### Fixes :wrench: + +- Fixed a bug that caused Cesium3DTilesets to fail to disconnect from CesiumGeoreference notifications. It could cause problems when changing to a different georeference instance. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.21.0 to v0.21.1. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.19.0 - 2022-11-01 + +##### Breaking Changes :mega: + +- Removed some poorly named and unreliable functions on the `CesiumGeoreference`: `ComputeEastNorthUp`, `TransformRotatorEastNorthUpToUnreal`, and `TransformRotatorUnrealToEastNorthUp`. These functions have been replaced with reliable "EastSouthUp" counterparts. + +##### Additions :tada: + +- Added asynchronous texture creation where supported by the graphics API. This offloads a frequent render thread bottleneck to background loading threads. +- Improved synchronous texture creation by eliminating a main-thread memcpy, for cases where asynchronous texture creation is not supported. +- Added throttling of the main-thread part of loading for glTFs. +- Added throttling for tile cache unloads on the main thread. +- Added a prototype developer feature enabling Unreal Insights tracing into Cesium Native. This helps us investigate end-to-end performance in a deeper and more precise manner. + +##### Fixes :wrench: + +- Significantly reduced frame-rate dips during asynchronous tile loading by eliminating thread pool monopolization by Cesium tasks. +- Improved the tile destruction sequence by allowing it to defer being destroyed to future frames if it is waiting on asynchronous work to finish. Previously we would essentially block the main thread waiting for tiles to become ready for destruction. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.20.0 to v0.21.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.18.0 - 2022-10-03 + +##### Additions :tada: + +- Improved the dithered transition between levels-of-detail, making it faster and eliminating depth fighting. +- Added an option to `Cesium3DTileset` to change the tileset's mobility, rather than always using Static mobility. This allows users to make a tileset movable at runtime, if needed. +- `ACesiumCreditSystem` now has a Blueprint-accessible property for the `CreditsWidget`. This is useful to, for example, move the credits to an in-game billboard rather than a 2D overlay. + +##### Fixes :wrench: + +- Fixed a bug where collision settings were only applied to the first primitive in a glTF. +- Fixed a bug where the Screen Credits Decorator prevented the Rich Text Block Image Decorator from working. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.19.0 to v0.20.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.17.0 - 2022-09-01 + +##### Additions :tada: + +- The translucent parts of 3D Tiles are now correctly rendered as translucent. In addition, a new `TranslucentMaterial` property on `Cesium3DTileset` allows a custom material to be used to render these translucent portions. +- Added a `Rendering -> Use Lod Transitions` option on `Cesium3DTileset` to smoothly dither between levels-of-detail rather than switching abruptly. +- Added support for loading WebP images inside glTFs and raster overlays. WebP textures can be provided directly in a glTF texture or in the `EXT_texture_webp` extension. + +##### Fixes :wrench: + +- Fixed a bug that prevented fractional DPI scaling from being properly taken into account. Instead, it would scale by the next-smallest integer. +- Cesium for Unreal now only uses Editor viewports for tile selection if they are visible, real-time, and use a perspective projection. Previously, any viewport with a valid size was used, which could lead to tiles being loaded and rendered unnecessarily. +- Fixed a bug that caused tiles to disappear when the Editor viewport was in Orbit mode. +- Fixed a bug in the Globe Anchor Component that prevented changing/resetting the actor transform in the details panel. +- Reduced the size of physics meshes by only copying UV data if "Support UV from Hit Results" is enabled in the project settings. +- Fixed a bug - in Unreal Engine 5 only - where a LineTrace would occasionally fail to collide with tiles at certain levels-of-detail. +- Fixed a crash that could occur while running on a dedicated server, caused by attempting to add the credits widget to the viewport. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.18.1 to v0.19.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.16.2 - 2022-08-04 + +##### Fixes :wrench: + +- Fixed a bug that caused a crash in Unreal Engine 4.26 when enabling the experimental tileset occlusion culling feature. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.18.0 to v0.18.1. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.16.1 - 2022-08-01 + +##### Fixes :wrench: + +- Fixed a bug that could cause a crash when using thumbnail rendering, notably on the Project Settings panel in UE5. +- More fully disabled the occlusion culling system when the project-level feature flag is disabled. + +### v1.16.0 - 2022-08-01 + +##### Breaking Changes :mega: + +- Cesium for Unreal now automatically scales the selected 3D Tiles level-of-detail by the viewport client's `GetDPIScale`, meaning that devices with high-DPI displays will get less detail and higher performance than they did in previous versions. This can be disabled - and the previous behavior restored - by disabling the "Scale Level Of Detail By DPI" in Project Settings under Plugins -> Cesium, or by changing the "Apply Dpi Scaling" property on individual Tileset Actors. + +##### Additions :tada: + +- Added an experimental feature that uses Occlusion Culling to avoid refining tiles that are occluded by other content in the level. Currently this must be explicitly enabled from the Plugins -> Cesium section of Project Settings. We expect to enable it by default in a future release. +- Added options in `ACesium3DTileset` to control occlusion culling and turn it off if necessary. +- `UCesiumGltfPrimitiveComponent` now has static mobility, allowing it to take advantage of several rendering optimizations only available for static objects. +- Added an `OnTilesetLoaded` even that is invoked when the current tileset has finished loading. It is available from C++ and Blueprints. +- Added a `GetLoadProgress` method that returns the current load percentage of the tileset. It is available from C++ and Blueprints. +- Added Blueprint-accessible callback `OnFlightComplete` for when Dynamic Pawn completes flight. +- Added Blueprint-accessible callback `OnFlightInterrupt` for when Dynamic Pawn's flying is interrupted. + +##### Fixes :wrench: + +- When the Cesium ion access or login token is modified and stored in a config file that is under source code control, it will now be checked out before it is saved. Previously, token changes could be silently ignores with a source code control system that marks files read-only, such as Perforce. +- Fixed a bug that prevented credit images from appearing in UE5. +- Fixed a credit-related crash that occur when switching levels. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.17.0 to v0.18.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.15.0 - 2022-07-01 + +##### Additions :tada: + +- Display credits using Rich Text Block instead of the Web Browser Widget. + +##### Fixes :wrench: + +- Swapped latitude and longitude parameters on georeferenced sublevels to match with the main georeference. +- Adjusted the presentation of sublevels in the Cesium Georeference details panel. +- We now explicitly free physics mesh UVs and face remap data, reducing memory usage in the Editor and reducing pressure on the garbage collector in-game. +- Fixed a bug that could cause a crash when reporting tileset or raster overlay load errors, particularly while switching levels. +- We now Log the correct asset source when loading a new tileset from either URL or Ion. +- Disabling physics meshes of a tileset now works in Unreal Engine 5. + +### v1.14.0 - 2022-06-01 + +##### Breaking Changes :mega: + +- Renamed `ExcludeTilesInside` to `ExcludeSelectedTiles` on the `CesiumPolygonRasterOverlay`. A core redirect was added to remap the property value in existing projects. + +##### Additions :tada: + +- Added the `InvertSelection` option on `CesiumPolygonRasterOverlay` to rasterize outside the selection instead of inside. When used in conjunction with the `ExcludeSelectedTiles` option, tiles completely outside the polygon selection will be culled, instead of the tiles inside. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.15.1 to v0.16.0, fixing an important bug. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.13.2 - 2022-05-13 + +##### Additions :tada: + +- Added pre-built binaries for Unreal Engine 5 on macOS and iOS. + +##### Fixes :wrench: + +- Fixed a bug that could cause a crash after applying a non-UMaterialInstanceDynamic material to a tileset. +- Fixed a bug introduced in v1.13.0 that could lead to incorrect axis-aligned bounding boxes. +- Gave initial values to some fields in UStructs that did not have them, including two `UObject` pointers. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.15.1 to v0.15.2, fixing an important bug and updating some third-party libraries. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.13.1 - 2022-05-05 + +This release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.15.0 to v0.15.1, fixing an important bug. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.13.0 - 2022-05-02 + +##### Breaking Changes :mega: + +- Deprecated parts of the old Blueprint API for feature ID attributes from `EXT_feature_metadata`. + +##### Additions :tada: + +- Improved the Blueprint API for feature ID attributes from `EXT_feature_metadata` (and upgraded batch tables). +- Added a Blueprint API to access feature ID textures and feature textures from the `EXT_feature_metadata` extension. +- Added the `UCesiumEncodedMetadataComponent` to enable styling with the metadata from the `EXT_feature_metadata` extension. This component provides a convenient way to query for existing metadata, dictate which metadata properties to encode for styling, and generate a starter material layer to access the wanted properties. + +##### Fixes :wrench: + +- glTF normal, occlusion, and metallic/roughness textures are no longer treated as sRGB. +- Improved the computation of axis-aligned bounding boxes for Unreal Engine, producing much smaller and more accurate bounding boxes in many cases. +- Metadata-related Blueprint functions will now return the default value if asked for an out-of-range feature or array element. Previously, they would assert or read undefined memory. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.14.0 to v0.15.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.12.1 - 2022-04-06 + +##### Fixes :wrench: + +- Fixed compiler errors with the official release of Unreal Engine 5. + +### v1.12.0 - 2022-04-01 + +##### Breaking Changes :mega: + +- Removed the `KeepWorldOriginNearCamera`, `OriginRebaseInsideSublevels`, and `MaximumWorldOriginDistanceFromCamera` options from `CesiumGeoreference`. These options are not usually necessary with Unreal Engine 5's double-precision coordinates. +- Renamed the `WorldOriginCamera` property on `CesiumGeoreference` to `SubLevelCamera`, as this property is now only used for switching sub-levels. Core Redirects should automatically make this change in Blueprints. +- Removed `Inaccurate` from the name of a large number of Blueprint functions, now that Unreal Engine 5 supports double-precision in Blueprints. Core Redirects should automatically make this change in Blueprints. + +##### Additions :tada: + +- Cesium for Unreal automatically enables Unreal Engine 5's "Enable Large Worlds" setting, which is required for correct culling of Cesium tilesets. +- Raster overlays are now, by default, rendered using the default settings for the `World` texture group, which yields much higher quality on many platforms by enabling anisotrpic texture filtering. Shimmering of overlay textures in the distance should be drastically reduced. +- New options on `RasterOverlay` give the user control over the texture group, texture filtering, and mipmapping used for overlay textures. +- Improved the mapping between glTF textures and Unreal Engine texture options, which should improve texture quality in tilesets. +- Added `CesiumWebMapServiceRasterOverlay` to pull raster overlays from a WMS server. +- Added option to show `Cesium3DTileset` and `CesiumRasterOverlay` credits on screen, rather than in a separate popup. + +##### Fixes :wrench: + +- Fixed a leak of some of the memory used by tiles that were loaded but then ended up not being used because the camera had moved. +- Fixed a leak of glTF emissive textures. +- Fixed a bug introduced in v1.11.0 that used the Y-size of the right eye viewport for the left eye in tile selection for stereographic rendering. +- Fixed a bug where glTF primitives with no render data are added to the glTF render result. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.13.0 to v0.14.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.11.0 - 2022-03-01 + +##### Breaking Changes :mega: + +- Exclusion Zones have been deprecated and will be removed in a future release. Please use the Cartographic Polygon Actor instead. + +##### Additions :tada: + +- Added experimental support for Unreal Engine 5 (preview 1). +- Added collision meshes for tilesets when using the Chaos physics engine. +- Integrated GPU pixel compression formats received from Cesium Native into Unreal's texture system. +- Added support for the `CESIUM_RTC` glTF extension. +- Added the ability to set tne Georeference origin from ECEF coordinates in Blueprints and C++. +- Exposed the Cesium ion endpoint URL as a property on tilesets and raster overlays. + +##### Fixes :wrench: + +- Fixed bug where certain pitch values in "Innaccurate Fly to Location Longitude Latitude Height" cause gimbal lock. +- Fixed a bug that caused a graphical glitch by using 16-bit indices when 32-bit indices are needed. +- Fixed a bug where tileset metadata from a feature table was not decoded correctly from UTF-8. +- Improved the shadows, making shadows fade in and out less noticable. +- The Cesium ion Token Troubleshooting panel will no longer appear in game worlds, including Play-In-Editor. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.12.0 to v0.13.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.10.1 - 2022-02-01 + +##### Fixes :wrench: + +- Fixed a crash at startup on Android devices introduced in v1.10.0. + +### v1.10.0 - 2022-02-01 + +##### Breaking Changes :mega: + +- The following Blueprints and C++ functions on `CesiumSunSky` have been renamed. CoreRedirects have been provided to handle the renames automatically for Blueprints. + - `EnableMobileRendering` to `UseMobileRendering` + - `AdjustAtmosphereRadius` to `UpdateAtmosphereRadius` + +##### Additions :tada: + +- Added Cesium Cartographic Polygon to the Cesium Quick Add panel. +- Improved the Cesium ion token management. Instead of automatically creating a Cesium ion token for each project, Cesium for Unreal now prompts you to select or create a token the first time one is needed. +- Added a Cesium ion Token Troubleshooting panel that appears when there is a problem connecting to Cesium ion tilesets and raster overlays. +- The new `FCesiumCamera` and `ACesiumCameraManager` can be used to register and update custom camera views into Cesium tilesets. + +##### Fixes :wrench: + +- Fixed a crash when editing the georeference detail panel while a sublevel is active. +- Improved the organization of `CesiumSunSky` parameters in the Details Panel. +- Improved the organization of `CesiumGlobeAnchorComponent` parameters in the Details Panel. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.11.0 to v0.12.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.9.0 - 2022-01-03 + +##### Fixes :wrench: + +- Fixed a bug that could cause incorrect LOD and culling when viewing a camera in-editor and the camera's aspect ratio does not match the viewport window's aspect ratio. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.10.0 to v0.11.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.8.1 - 2021-12-02 + +In this release, the cesium-native binaries are built using Xcode 11.3 on macOS instead of Xcode 12. Other platforms are unchanged from v1.8.0. + +### v1.8.0 - 2021-12-01 + +##### Additions :tada: + +- `Cesium3DTileset` now has options for enabling custom depth and stencil buffer. +- Added `CesiumDebugColorizeTilesRasterOverlay` to visualize how a tileset is divided into tiles. +- Added `Log Selection Stats` debug option to the `Cesium3DTileset` Actor. +- Exposed raster overlay properties to Blueprints, so that overlays can be created and manipulated with Blueprints. + +##### Fixes :wrench: + +- Cesium for Unreal now does a much better job of releasing memory when the Unreal Engine garbage collector is not active, such as in the Editor. +- Fixed a bug that could cause an incorrect field-of-view angle to be used for tile selection in the Editor. +- Fixed a bug that caused `GlobeAwareDefaultPawn` (and its derived classes, notably `DynamicPawn`) to completely ignore short flights. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.9.0 to v0.10.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.7.0 - 2021-11-01 + +##### Breaking Changes :mega: + +- Removed `CesiumGlobeAnchorParent`, which was deprecated in v1.3.0. The `CesiumGlobeAnchorParent` functionality can be recreated using an empty actor with a `CesiumGlobeAnchorComponent`. +- Removed the `FixTransformOnOriginRebase` property from `CesiumGeoreferenceComponent`, and the component now always acts as if it is enabled. This should now work correctly even for objects that are moved by physics or other Unreal Engine mechanisms. +- The `SnapToEastSouthUp` function on `CesiumGeoreference` no longer resets the Scale back to 1.0. It only modifies the rotation. +- The following `CesiumGeoreferenceComponent` Blueprints and C++ functions no longer take a `MaintainRelativeOrientation` parameter. Instead, this behavior is controlled by the `AdjustOrientationForGlobeWhenMoving` property. + - `MoveToLongitudeLatitudeHeight` + - `InaccurateMoveToLongitudeLatitudeHeight` + - `MoveToECEF` + - `InaccurateMoveToECEF` +- Renamed `CesiumGeoreferenceComponent` to `CesiumGlobeAnchorComponent`. +- `CesiumSunSky` has been converted from Blueprints to C++. Backward compatibility should be preserved in most cases, but some less common scenarios may break. +- `GlobeAwareDefaultPawn`, `DynamicPawn`, and `CesiumSunSky` no longer have a `Georeference` property. Instead, they have a `CesiumGlobeAnchor` component that has a `Georeference` property. +- The `Georeference` property on most Cesium types can now be null if it has not been set explicitly in the Editor. To get the effective Georeference, including one that has been discovered in the level, use the `ResolvedGeoreference` property or call the `ResolveGeoreference` function. +- Removed the option to locate the Georeference at the "Bounding Volume Origin". It was confusing and almost never useful. +- The `CheckForNewSubLevels` and `JumpToCurrentLevel` functions in `CesiumGeoreference` have been removed. New sub-levels now automatically appear without an explicit check, and the current sub-level can be changed using the standard Unreal Engine Levels panel. +- Removed the `CurrentLevelIndex` property from `CesiumGeoreference`. The sub-level that is currently active in the Editor can be queried with the `GetCurrentLevel` function of the `World`. +- Removed the `SunSky` property from `CesiumGeoreference`. The `CesiumSunSky` now holds a reference to the `CesiumGeoreference`, rather than the other way around. +- The following Blueprints and C++ functions on `CesiumGeoreference` have been renamed. CoreRedirects have been provided to handle the renames automatically for Blueprints. + - `TransformLongitudeLatitudeHeightToUe` to `TransformLongitudeLatitudeHeightToUnreal` + - `InaccurateTransformLongitudeLatitudeHeightToUe` to `InaccurateTransformLongitudeLatitudeHeightToUnreal` + - `TransformUeToLongitudeLatitudeHeight` to `TransformLongitudeLatitudeHeightToUnreal` + - `InaccurateTransformUeToLongitudeLatitudeHeight` to `InaccurateTransformUnrealToLongitudeLatitudeHeight` + - `TransformEcefToUe` to `TransformEcefToUnreal` + - `InaccurateTransformEcefToUe` to `InaccurateTransformEcefToUnreal` + - `TransformUeToEcef` to `TransformUnrealToEcef` + - `InaccurateTransformUeToEcef` to `InaccurateTransformUnrealToEcef` + - `TransformRotatorUeToEnu` to `TransformRotatorUnrealToEastNorthUp` + - `InaccurateTransformRotatorUeToEnu` to `InaccurateTransformRotatorUnrealToEastNorthUp` + - `TransformRotatorEnuToUe` to `TransformRotatorEastNorthUpToUnreal` + - `InaccurateTransformRotatorEnuToUe` to `InaccurateTransformRotatorEastNorthUpToUnreal` +- The following C++ functions on `CesiumGeoreference` have been removed: + - `GetGeoreferencedToEllipsoidCenteredTransform` and `GetEllipsoidCenteredToGeoreferencedTransform` moved to `GeoTransforms`, which is accessible via the `getGeoTransforms` function on `CesiumGeoreference`. + - `GetUnrealWorldToEllipsoidCenteredTransform` has been replaced with `TransformUnrealToEcef` except that the latter takes standard Unreal world coordinates rather than absolute world coordinates. If you have absolute world coordinates, subtract the World's `OriginLocation` before calling the new function. + - `GetEllipsoidCenteredToUnrealWorldTransform` has been replaced with `TransformEcefToUnreal` except that the latter returns standard Unreal world coordinates rather than absolute world coordinates. If you want absolute world coordinates, add the World's `OriginLocation` to the return value. + - `AddGeoreferencedObject` should be replaced with a subscription to the new `OnGeoreferenceUpdated` event. + +##### Additions :tada: + +- Improved the workflow for managing georeferenced sub-levels. +- `CesiumSunSky` now automatically adjusts the atmosphere size based on the player Pawn's position to avoid tiled artifacts in the atmosphere when viewing the globe from far away. +- `GlobeAwareDefaultPawn` and derived classes like `DynamicPawn` now have a `CesiumGlobeAnchorComponent` attached to them. This allows more consistent movement on the globe, and allows the pawn's Longitude/Latitude/Height or ECEF coordinates to be specified directly in the Editor. +- `CesiumSunSky` now has an `EnableMobileRendering` flag that, when enabled, switches to a mobile-compatible atmosphere rendering technique. +- `CesiumCartographicPolygon`'s `GlobeAnchor` and `Polygon` are now exposed in the Editor and to Blueprints. +- Added `InaccurateGetLongitudeLatitudeHeight` and `InaccurateGetECEF` functions to `CesiumGlobeAnchorComponent`, allowing access to the current position of a globe-anchored Actor from Blueprints. +- Added support for collision object types on 'ACesium3DTileset' actors. + +##### Fixes :wrench: + +- Cesium objects in a sub-level will now successfully find and use the `CesiumGeoreference` and `CesiumCreditSystem` object in the Persistent Level when these properties are left unset. For best results, we suggest removing all instances of these objects from sub-levels. +- Fixed a bug that made the Time-of-Day widget forget the time when it was closed and re-opened. +- Undo/Redo now work more reliably for `CesiumGlobeAnchor` properties. +- We now explicitly free the `PlatformData` and renderer resources associated with `UTexture2D` instances created for raster overlays when the textures are no longer needed. By relying less on the Unreal Engine garbage collector, this helps keep memory usage lower. It also keeps memory from going up so quickly in the Editor, which by default does not run the garbage collector at all. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.8.0 to v0.9.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.6.3 - 2021-10-01 + +##### Fixes :wrench: + +- Fixed a bug that caused incorrect tangents to be generated based on uninitialized texture coordinates. +- Fixed a bug that could cause vertices to be duplicated and tangents calculated even when not needed. +- Fixed a bug that caused the Cesium ion access token to sometimes be blank when adding an asset from the "Cesium ion Assets" panel while the "Cesium" panel is not open. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.7.2 to v0.8.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.6.2 - 2021-09-14 + +This release only updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.7.1 to v0.7.2. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.6.1 - 2021-09-14 + +##### Additions :tada: + +- Added the `MaximumCachedBytes` property to `ACesium3DTileset`. + +##### Fixes :wrench: + +- Fixed incorrect behavior when two sublevels overlap each other. Now the closest sublevel is chosen in that case. +- Fixed crash when `GlobeAwareDefaultPawn::FlyToLocation` was called when the pawn was not possessed. +- Fixed a bug that caused clipping to work incorrectly for tiles that are partially water. +- Limited the length of names assigned to the ActorComponents created for 3D Tiles, to avoid a crash caused by an FName being too long with extremely long tileset URLs. +- Fixed a bug that caused 3D Tiles tile selection to take into account Editor viewports even when in Play-in-Editor mode. +- Fixed a bug in `DynamicPawn` that caused a divide-by-zero message to be printed to the Output Log. +- Fixed a mismatch on Windows between Unreal Engine's compiler options and cesium-native's compiler options that could sometimes lead to crashes and other broken behavior. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.7.0 to v0.7.1. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.6.0 - 2021-09-01 + +##### Breaking Changes :mega: + +- Removed `ACesium3DTileset::OpacityMaskMaterial`. The regular `Material` property is used instead. +- Renamed `UCesiumMetadataFeatureTableBlueprintLibrary::GetPropertiesForFeatureID` to `UCesiumMetadataFeatureTableBlueprintLibrary::GetMetadataValuesForFeatureID`. This is a breaking change for C++ code but Blueprints should be unaffected because of a CoreRedirect. +- Renamed `UCesiumMetadataFeatureTableBlueprintLibrary::GetPropertiesAsStringsForFeatureID` to `UCesiumMetadataFeatureTableBlueprintLibrary::GetMetadataValuesAsStringForFeatureID`. This is a breaking change for C++ code but it was not previously exposed to Blueprints. + +##### Additions :tada: + +- Added the ability to define a "Cesium Cartographic Polygon" and then use it to clip away part of a Cesium 3D Tileset. +- Multiple raster overlays per tileset are now supported. +- The default materials used to render Cesium 3D Tilesets are now built around Material Layers, making them easier to compose and customize. +- Added support for using `ASceneCapture2D` with `ACesium3DTileset` actors. +- Added an editor option in `ACesium3DTileset` to optionally generate smooth normals for glTFs that originally did not have normals. +- Added an editor option in `ACesium3DTileset` to disable the creation of physics meshes for its tiles. +- Added a Refresh button on the Cesium ion Assets panel. +- Made `UCesiumMetadataFeatureTableBlueprintLibrary::GetMetadataValuesAsStringForFeatureID`, `UCesiumMetadataFeatureTableBlueprintLibrary::GetProperties`, and `UCesiumMetadataPrimitiveBlueprintLibrary::GetFirstVertexIDFromFaceID` callable from Blueprints. +- Consolidated texture preparation code. Now raster overlay textures can generate mip-maps and the overlay texture preparation can happen partially on the load thread. +- The Cesium ion Assets panel now has two buttons for imagery assets, allowing the user to select whether the asset should replace the base overlay or be added on top. + +##### Fixes :wrench: + +- Fixed indexed vertices being duplicated unnecessarily in certain situations in `UCesiumGltfComponent`. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.6.0 to v0.7.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.5.2 - 2021-08-30 + +##### Additions :tada: + +- Added support for Unreal Engine v4.27. + +### v1.5.1 - 2021-08-09 + +##### Breaking :mega: + +- Changed Cesium Native Cesium3DTiles's namespace to Cesium3DTilesSelection's namespace + +##### Fixes :wrench: + +- Fixed a bug that could cause mis-registration of feature metadata to the wrong features in Draco-compressed meshes. +- Fixed a bug that could cause a crash with VR/AR devices enabled but not in use. + +### v1.5.0 - 2021-08-02 + +##### Additions :tada: + +- Added support for reading per-feature metadata from glTFs with the `EXT_feature_metadata` extension or from 3D Tiles with a B3DM batch table and accessing it from Blueprints. +- Added support for using multiple view frustums in `ACesium3DTileset` to inform the tile selection algorithm. + +##### Fixes :wrench: + +- Fixed a bug introduced in v1.4.0 that made it impossible to add a "Blank 3D Tiles Tileset" using the Cesium panel without first signing in to Cesium ion. +- Fixed a bug that caused a crash when deleting a Cesium 3D Tileset Actor and then undoing that deletion. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.5.0 to v0.6.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.4.1 - 2021-07-13 + +##### Fixes :wrench: + +- Fixed linker warnings on macOS related to "different visibility settings." +- Fixed compile errors on Android in Unreal Engine versions prior to 4.26.2 caused by missing support for C++17. + +### v1.4.0 - 2021-07-01 + +##### Breaking :mega: + +- Tangents are now only generated for models that don't have them and that do have a normal map, saving a significant amount of time. If you have a custom material that requires the tangents, or need them for any other reason, you may set the `AlwaysIncludeTangents` property on `Cesium3DTileset` to force them to be generated like they were in previous versions. + +##### Additions :tada: + +- The main Cesium panel now has buttons to easily add a `CesiumSunSky` or a `DynamicPawn`. + +##### Fixes :wrench: + +- Fixed a bug that could sometimes cause tile-sized holes to appear in a 3D Tiles model for one render frame. +- Fixed a bug that caused Cesium toolbar buttons to disappear when `Editor Preferences` -> `Use Small Tool Bar Icons` is enabled. +- Added support for other types of glTF index accessors: `BYTE`, `UNSIGNED_BYTE`, `SHORT`, and `UNSIGNED_SHORT`. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.4.0 to v0.5.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.3.1 - 2021-06-02 + +- Temporarily removed support for the Android platform because it is causing problems in Epic's build environment, and is not quite production ready in any case. + +### v1.3.0 - 2021-06-01 + +##### Breaking :mega: + +- Tileset properties that require a tileset reload (URL, Source, IonAssetID, IonAccessToken, Materials) have been moved to `private`. Setter and getter methods are now provided for modifying them in Blueprints and C++. +- Deprecated `CesiumGlobeAnchorParent` and `FloatingPawn`. The `CesiumGlobeAnchorParent` functionality can be recreated using an empty actor with a `CesiumGeoreferenceComponent`. The `FloatingPawn` is now replaced by the `DynamicPawn`. In a future release, the `DynamicPawn` will be renamed to `CesiumFloatingPawn`. + +##### Additions :tada: + +- Added support for the Android platform. +- Added support for displaying a water effect for the parts of quantized-mesh terrain tiles that are known to be water. +- Improved property change checks in `Cesium3DTileset::LoadTileset`. +- Made origin rebasing boolean properties in `CesiumGeoreference` and `CesiumGeoreferenceComponent` blueprint editable. +- Made 3D Tiles properties editable in C++ and blueprints via getter/setter functions. The tileset now reloads at runtime when these properties are changed. +- Improvements to dynamic camera, created altitude curves for FlyTo behavior. +- Constrained the values for `UPROPERTY` user inputs to be in valid ranges. +- Added `M_CesiumOverlayWater` and `M_CesiumOverlayComplexWater` materials for use with water tiles. +- Exposed all tileset materials to allow for changes in editor. +- Added `TeleportWhenUpdatingTransform` boolean property to CesiumGeoreferenceComponent. +- Added a "Year" property to `CesiumSunSky`. +- Added the ability to use an external Directional Light with `CesiumSunSky`, rather than the embedded DirectionalLight component. + +##### Fixes :wrench: + +- Fixed a bug that caused rendering and navigation problems when zooming too far away from the globe when origin rebasing is enabled. +- Fixed a bug that caused glTF node `translation`, `rotation`, and `scale` properties to be ignored even if the node had no `matrix`. +- Cleaned up, standardized, and commented material and material functions. +- Moved all materials and material functions to the `Materials` subfolder. +- Set CesiumSunSky's directional light intensity to a more physically accurate value. +- Moved Latitude before Longitude on the `CesiumGeoreference` and `CesiumGeoreferenceComponent` Details panels. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.3.1 to v0.4.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.2.1 - 2021-05-13 + +##### Fixes :wrench: + +- Fixed a regression in Cesium for Unreal v1.2.0 where `GlobeAwareDefaultPawn` lost its georeference during playmode. +- Fixed a regression in Cesium for Unreal v1.2.0 where the matrices in `CesiumGeoreference` were being initialized to zero instead of identity. +- Fixed a regression in Cesium for Unreal v1.2.0 that broke the ability to paint foliage on terrain and other tilesets. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.3.0 to v0.3.1. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.2.0 - 2021-05-03 + +##### Additions :tada: + +- Added a dynamic camera that adapts to height above terrain. +- Added Linux support. +- Added support for Tile Map Service (TMS) raster overlays. + +##### Fixes :wrench: + +- Fixed issue where displayed longitude-latitude-height in `CesiumGeoreferenceComponent` wasn't updating in certain cases. +- `FEditorDelegates::OnFocusViewportOnActors` is no longer unnecessarily subscribed to multiple times. +- `Loading tileset ...` is now only written to the output log when the tileset actually needs to be reloaded. +- Fixed a bug where collision does not update correctly when changing properties of a tileset in the editor. +- Fixed a bug that caused tiles to disappear when "Suspend Update" was enabled. + +### v1.1.1 - 2021-04-23 + +##### Fixes :wrench: + +- Fixed a bug that caused tilesets added with the "Add Blank" button to cause an error during Play-In-Editor. +- Fixed a bug that caused `ACesiumGeoreference::TransformEcefToUe` to be much less precise than expected. +- Moved the `BodyInstance` property on `Cesium3DTileset` to the `Collision` category so that it can be modified in the Editor. + +### v1.1.0 - 2021-04-19 + +##### Additions :tada: + +- Added macOS support. +- Added support for the legacy `gltfUpAxis` property in a tileset `asset` dictionary. Although this property is **not** part of the specification, there are many existing assets that use this property and had been shown with a wrong rotation otherwise. +- Changed the log level for the tile selection output from `Display` to `Verbose`. With default settings, the output will no longer be displayed in the console, but only written to the log file. +- Added more diagnostic details to error messages for invalid glTF inputs. +- Added diagnostic details to error messages for failed OAuth2 authorization with `CesiumIonClient::Connection`. +- Added a `BodyInstance` property to `Cesium3DTileset` so that collision profiles can be configured. +- Added an experimental "Exclusion Zones" property to `Cesium3DTileset`. While likely to change in the future, it already provides a way to exclude parts of a 3D Tiles tileset to make room for another. + +##### Fixes :wrench: + +- Gave glTFs created from quantized-mesh terrain tiles a more sensible material with a `metallicFactor` of 0.0 and a `roughnessFactor` of 1.0. Previously the default glTF material was used, which has a `metallicFactor` of 1.0, leading to an undesirable appearance. +- Reported zero-length images as non-errors, because `BingMapsRasterOverlay` purposely requests that the Bing servers return a zero-length image for non-existent tiles. +- 3D Tiles geometric error is now scaled by the tile's transform. +- Fixed a bug that that caused a 3D Tiles tile to fail to refine when any of its children had an unsupported type of content. +- The `Material` property of `ACesium3DTiles` is now a `UMaterialInterface` instead of a `UMaterial`, allowing more flexibility in the types of materials that can be used. +- Fixed a possible crash when a `Cesium3DTileset` does not have a `CesiumGeoreference` or it is not valid. + +In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.1.0 to v0.2.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. + +### v1.0.0 - 2021-03-30 - Initial Release + +##### Features :tada: + +- High-accuracy, global-scale WGS84 globe for visualization of real-world 3D content +- 3D Tiles runtime engine to stream massive 3D geospatial datasets, such as terrain, imagery, 3D cities, and photogrammetry + - Streaming from the cloud, a private network, or the local machine. + - Level-of-detail selection + - Caching + - Multithreaded loading + - Batched 3D Model (B3DM) content, including the B3DM content inside Composite (CMPT) tiles + - `quantized-mesh` terrain loading and rendering + - Bing Maps and Tile Map Service (TMS) raster overlays draped on terrain +- Integrated with Cesium ion for instant access to cloud based global 3D content. +- Integrated with Unreal Engine Editor, Actors and Components, Blueprints, Landscaping and Foliage, Sublevels, and Sequencer. diff --git a/Plugins/CesiumForUnreal/CesiumForUnreal.uplugin b/Plugins/CesiumForUnreal/CesiumForUnreal.uplugin new file mode 100644 index 0000000..9ba701d --- /dev/null +++ b/Plugins/CesiumForUnreal/CesiumForUnreal.uplugin @@ -0,0 +1,59 @@ +{ + "FileVersion": 3, + "Version": 67, + "VersionName": "2.12.0", + "FriendlyName": "Cesium for Unreal", + "Description": "Unlock the 3D geospatial ecosystem in Unreal Engine with real-world 3D content and a high accuracy full-scale WGS84 globe.", + "Category": "Geospatial", + "CreatedBy": "Cesium GS, Inc.", + "CreatedByURL": "https://cesium.com", + "DocsURL": "https://cesium.com/learn/unreal/", + "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/87b0d05800a545d49bf858ef3458c4f7", + "SupportURL": "https://community.cesium.com", + "EngineVersion": "5.3.0", + "CanContainContent": true, + "Installed": true, + "SupportedTargetPlatforms": [ + "Win64", + "Mac", + "Linux", + "Android", + "IOS" + ], + "Modules": [ + { + "Name": "CesiumRuntime", + "Type": "Runtime", + "LoadingPhase": "PostConfigInit", + "PlatformAllowList": [ + "Win64", + "Mac", + "Linux", + "Android", + "IOS" + ] + }, + { + "Name": "CesiumEditor", + "Type": "Editor", + "LoadingPhase": "PostEngineInit", + "PlatformAllowList": [ + "Win64", + "Mac", + "Linux", + "Android", + "IOS" + ] + } + ], + "Plugins": [ + { + "Name": "SunPosition", + "Enabled": true + }, + { + "Name": "Water", + "Enabled": true + } + ] +} \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Config/Editor.ini b/Plugins/CesiumForUnreal/Config/Editor.ini new file mode 100644 index 0000000..332ae7e --- /dev/null +++ b/Plugins/CesiumForUnreal/Config/Editor.ini @@ -0,0 +1,6 @@ +# UE 5.3+ defaults this to 11, which is not really high enough. +# 100 is probably high enough for reasonable values of Cesium3DTileset's 'MaximumSimultaneousTileLoads property, +# but if you get log messages like "Warning: Reached threaded request limit", and you're sure you want to use +# such a high value, you may need to increase this. +[HTTP.HttpThread] +RunningThreadedRequestLimitEditor=100 diff --git a/Plugins/CesiumForUnreal/Config/Engine.ini b/Plugins/CesiumForUnreal/Config/Engine.ini new file mode 100644 index 0000000..65028cd --- /dev/null +++ b/Plugins/CesiumForUnreal/Config/Engine.ini @@ -0,0 +1,165 @@ +# UE 5.3+ defaults this to 11, which is not really high enough. +# 100 is probably high enough for reasonable values of Cesium3DTileset's 'MaximumSimultaneousTileLoads property, +# but if you get log messages like "Warning: Reached threaded request limit", and you're sure you want to use +# such a high value, you may need to increase this. +[HTTP.HttpThread] +RunningThreadedRequestLimit=100 + +# Set HttpThreadActiveFrameTimeInSeconds - Network download speed is very sensitive to this value +# Maps to the sleep time (ms) between every loop of our libcurl processing thread +# The value of 0.001 (or 1 ms) has the same performance as 0, yet still reserves some time for idle +# +# Set HttpMaxConnectionsPerServer - maps to libcurl's CURLMOPT_MAX_HOST_CONNECTIONS +# Unreal defaults to 16, but this is lower than a typical value for MaximumSimultaneousTileLoads +# Use a number just past the highest reasonable value we think a user should ever pick +[HTTP] +HttpThreadActiveFrameTimeInSeconds=0.001 +HttpMaxConnectionsPerServer=40 + +[/Script/Engine.LocalPlayer] +AspectRatioAxisConstraint=AspectRatio_MaintainXFOV + +[CoreRedirects] ++FunctionRedirects=(OldName="CesiumMetadataFeatureTableBlueprintLibrary.GetPropertiesForFeatureID",NewName="GetMetadataValuesForFeatureID") + ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformLongitudeLatitudeHeightToUe",NewName="InaccurateTransformLongitudeLatitudeHeightToUnreal") + ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformUeToLongitudeLatitudeHeight",NewName="InaccurateTransformUnrealToLongitudeLatitudeHeight") ++PropertyRedirects=(OldName="CesiumGeoreference.InaccurateTransformUnrealToLongitudeLatitudeHeight.Ue", NewName="Unreal") + ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformEcefToUe",NewName="InaccurateTransformEcefToUnreal") + ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformUeToEcef",NewName="InaccurateTransformUnrealToEcef") ++PropertyRedirects=(OldName="CesiumGeoreference.InaccurateTransformUnrealToEcef.Ue", NewName="Unreal") + ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformRotatorUeToEnu",NewName="InaccurateTransformRotatorUnrealToEastNorthUp") ++PropertyRedirects=(OldName="CesiumGeoreference.InaccurateTransformRotatorUnrealToEastNorthUp.UeRotator", NewName="UnrealRotator") ++PropertyRedirects=(OldName="CesiumGeoreference.InaccurateTransformRotatorUnrealToEastNorthUp.UeLocation", NewName="UnrealLocation") + ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformRotatorEnuToUe",NewName="InaccurateTransformRotatorEastNorthUpToUnreal") ++PropertyRedirects=(OldName="CesiumGeoreference.InaccurateTransformRotatorEastNorthUpToUnreal.UeLocation", NewName="UnrealLocation") + ++PropertyRedirects=(OldName="CesiumGeoreference.InaccurateComputeEastNorthUpToUnreal.Ue", NewName="Unreal") + ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateSetGeoreferenceOrigin",NewName="SetOriginLongitudeLatitudeHeight") + ++ClassRedirects=(OldName="CesiumGeoreferenceComponent", NewName="CesiumGlobeAnchorComponent") ++ClassRedirects=(OldName="CesiumSunSky_C",NewName="/Script/CesiumRuntime.CesiumSunSky",OverrideClassName="/Script/CoreUObject.Class") + ++PropertyRedirects=(OldName="CesiumSunSky.EnableMobileRendering",NewName="UseMobileRendering") + ++FunctionRedirects=(OldName="CesiumSunSky.AdjustAtmosphereRadius",NewName="UpdateAtmosphereRadius") + ++PropertyRedirects=(OldName="CesiumGeoreference.WorldOriginCamera",NewName="SubLevelCamera") + +# Remove "Inaccurate" from all the function names. ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateGetGeoreferenceOriginLongitudeLatitudeHeight",NewName="GetOriginLongitudeLatitudeHeight") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateSetGeoreferenceOriginLongitudeLatitudeHeight",NewName="SetOriginLongitudeLatitudeHeight") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateSetGeoreferenceOriginEcef",NewName="SetOriginEarthCenteredEarthFixed") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformLongitudeLatitudeHeightToEcef",NewName="TransformLongitudeLatitudeHeightToEcef") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformEcefToLongitudeLatitudeHeight",NewName="TransformEcefToLongitudeLatitudeHeight") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformLongitudeLatitudeHeightToUnreal",NewName="TransformLongitudeLatitudeHeightPositionToUnreal") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformUnrealToLongitudeLatitudeHeight",NewName="TransformUnrealPositionToLongitudeLatitudeHeight") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformEcefToUnreal",NewName="TransformEarthCenteredEarthFixedPositionToUnreal") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformUnrealToEcef",NewName="TransformUnrealPositionToEarthCenteredEarthFixed") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformRotatorUnrealToEastNorthUp",NewName="TransformRotatorUnrealToEastNorthUp") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformRotatorEastNorthUpToUnreal",NewName="TransformRotatorEastNorthUpToUnreal") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateComputeEastNorthUpToUnreal",NewName="ComputeEastNorthUpToUnreal") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateComputeEastNorthUpToEcef",NewName="ComputeEastNorthUpToEcef") ++FunctionRedirects=(OldName="CesiumGlobeAnchorComponent.InaccurateGetECEF",NewName="GetEarthCenteredEarthFixedPosition") ++FunctionRedirects=(OldName="CesiumGlobeAnchorComponent.InaccurateMoveToECEF",NewName="MoveToEarthCenteredEarthFixedPosition") ++FunctionRedirects=(OldName="CesiumGlobeAnchorComponent.InaccurateGetLongitudeLatitudeHeight",NewName="GetLongitudeLatitudeHeight") ++FunctionRedirects=(OldName="CesiumGlobeAnchorComponent.InaccurateMoveToLongitudeLatitudeHeight",NewName="MoveToLongitudeLatitudeHeight") ++FunctionRedirects=(OldName="GlobeAwareDefaultPawn.InaccurateFlyToLocationECEF",NewName="FlyToLocationECEF") ++FunctionRedirects=(OldName="GlobeAwareDefaultPawn.InaccurateFlyToLocationLongitudeLatitudeHeight",NewName="FlyToLocationLongitudeLatitudeHeight") + ++PropertyRedirects=(OldName="CesiumPolygonRasterOverlay.ExcludeTilesInside",NewName="ExcludeSelectedTiles") + ++FunctionRedirects=(OldName="CesiumGeoreference.TransformUnrealToLongitudeLatitudeHeight",NewName="TransformUnrealPositionToLongitudeLatitudeHeight") ++PropertyRedirects=(OldName="CesiumGeoreference.TransformUnrealPositionToLongitudeLatitudeHeight.Unreal", NewName="UnrealPosition") ++FunctionRedirects=(OldName="CesiumGeoreference.TransformEcefToUnreal",NewName="TransformEarthCenteredEarthFixedPositionToUnreal") ++PropertyRedirects=(OldName="CesiumGeoreference.TransformEarthCenteredEarthFixedPositionToUnreal.Ecef", NewName="EarthCenteredEarthFixedPosition") ++FunctionRedirects=(OldName="CesiumGeoreference.TransformUnrealToEcef",NewName="TransformUnrealPositionToEarthCenteredEarthFixed") ++PropertyRedirects=(OldName="CesiumGeoreference.TransformUnrealPositionToEarthCenteredEarthFixed.Unreal", NewName="UnrealPosition") ++FunctionRedirects=(OldName="CesiumGeoreference.TransformLongitudeLatitudeHeightToUnreal",NewName="TransformLongitudeLatitudeHeightPositionToUnreal") ++FunctionRedirects=(OldName="CesiumGeoreference.TransformRotatorUnrealToEastSouthUp",NewName="TransformUnrealRotatorToEastSouthUp") ++FunctionRedirects=(OldName="CesiumGeoreference.TransformRotatorEastSouthUpToUnreal",NewName="TransformEastSouthUpRotatorToUnreal") ++PropertyRedirects=(OldName="CesiumGeoreference.TransformEastSouthUpRotatorToUnreal.EsuRotator", NewName="EastSouthUpRotator") ++FunctionRedirects=(OldName="CesiumGeoreference.ComputeEastSouthUpToUnreal",NewName="ComputeEastSouthUpToUnrealTransformation") ++PropertyRedirects=(OldName="CesiumGeoreference.ComputeEastSouthUpToUnrealTransformation.Unreal", NewName="UnrealLocation") ++FunctionRedirects=(OldName="CesiumGeoreference.SetGeoreferenceOriginLongitudeLatitudeHeight",NewName="SetOriginLongitudeLatitudeHeight") ++FunctionRedirects=(OldName="CesiumGeoreference.GetGeoreferenceOriginLongitudeLatitudeHeight",NewName="GetOriginLongitudeLatitudeHeight") ++FunctionRedirects=(OldName="CesiumGeoreference.SetGeoreferenceOriginEcef",NewName="SetOriginEarthCenteredEarthFixed") ++PropertyRedirects=(OldName="CesiumGeoreference.SetOriginEarthCenteredEarthFixed.TargetEcef", NewName="TargetEarthCenteredEarthFixed") ++FunctionRedirects=(OldName="CesiumGlobeAnchorComponent.GetECEF",NewName="GetEarthCenteredEarthFixedPosition") ++FunctionRedirects=(OldName="CesiumGlobeAnchorComponent.MoveToECEF",NewName="MoveToEarthCenteredEarthFixedPosition") ++PropertyRedirects=(OldName="CesiumGlobeAnchorComponent.GetEarthCenteredEarthFixedPosition.TargetEcef", NewName="EarthCenteredEarthFixedPosition") ++PropertyRedirects=(OldName="CesiumGlobeAnchorComponent.MoveToLongitudeLatitudeHeight.TargetLongitudeLatitudeHeight", NewName="LongitudeLatitudeHeight") + +# EXT_feature_metadata -> EXT_structural_metadata changes + +# Deprecate the old type enum. Unfortunately, there's no way to redirect it to a CesiumMetadataValueType struct. ++EnumRedirects=(OldName="ECesiumMetadataTrueType", NewName="ECesiumMetadataTrueType_DEPRECATED", ValueChanges=(("None","None_DEPRECATED"),("Int8","Int8_DEPRECATED"),("Uint8","Uint8_DEPRECATED"),("Int16","Int16_DEPRECATED"),("Uint16","Uint16_DEPRECATED"),("Int32","Int32_DEPRECATED"),("Uint32","Uint32_DEPRECATED"),("Int64","Int64_DEPRECATED"),("Uint64","Uint64_DEPRECATED"),("Float32","Float32_DEPRECATED"),("Float64","Float64_DEPRECATED"),("Boolean","Boolean_DEPRECATED"),("Enum","Enum_DEPRECATED"),("String","String_DEPRECATED"),("Array","Array_DEPRECATED"))) + ++StructRedirects=(OldName="CesiumMetadataGenericValue", NewName="CesiumMetadataValue") ++ClassRedirects=(OldName="CesiumMetadataGenericValueBlueprintLibrary", NewName="CesiumMetadataValueBlueprintLibrary") ++FunctionRedirects=(OldName="CesiumMetadataValueBlueprintLibrary.GetBlueprintComponentType",NewName="CesiumMetadataValueBlueprintLibrary.GetArrayElementBlueprintType") + ++StructRedirects=(OldName="CesiumMetadataArray", NewName="CesiumPropertyArray") ++ClassRedirects=(OldName="CesiumMetadataArrayBlueprintLibrary", NewName="CesiumPropertyArrayBlueprintLibrary") ++FunctionRedirects=(OldName="CesiumPropertyArrayBlueprintLibrary.GetBlueprintComponentType",NewName="CesiumPropertyArrayBlueprintLibrary.GetElementBlueprintType") ++FunctionRedirects=(OldName="CesiumPropertyArrayBlueprintLibrary.GetSize", NewName="CesiumPropertyArrayBlueprintLibrary.GetArraySize") + ++StructRedirects=(OldName="CesiumFeatureTable", NewName="CesiumPropertyTable") ++ClassRedirects=(OldName="CesiumFeatureTableBlueprintLibrary", NewName="CesiumPropertyTableBlueprintLibrary") + ++FunctionRedirects=(OldName="CesiumPropertyTableBlueprintLibrary.GetNumberOfFeatures", NewName="GetPropertyTableCount") ++PropertyRedirects=(OldName="CesiumPropertyTableBlueprintLibrary.GetPropertyTableCount.FeatureTable", NewName="PropertyTable") + ++FunctionRedirects=(OldName="CesiumPropertyTableBlueprintLibrary.GetMetadataValuesForFeatureID", NewName="GetMetadataValuesForFeature") ++PropertyRedirects=(OldName="CesiumPropertyTableBlueprintLibrary.GetMetadataValuesForFeature.FeatureTable", NewName="PropertyTable") + ++FunctionRedirects=(OldName="CesiumPropertyTableBlueprintLibrary.GetMetadataValuesAsStringForFeatureID", NewName="GetMetadataValuesForFeatureAsStrings") ++PropertyRedirects=(OldName="CesiumPropertyTableBlueprintLibrary.GetMetadataValuesForFeatureAsStrings.FeatureTable", NewName="PropertyTable") + ++PropertyRedirects=(OldName="CesiumPropertyTableBlueprintLibrary.GetProperties.FeatureTable", NewName="PropertyTable") + ++StructRedirects=(OldName="CesiumMetadataProperty", NewName="CesiumPropertyTableProperty") ++ClassRedirects=(OldName="CesiumMetadataPropertyBlueprintLibrary", NewName="CesiumPropertyTablePropertyBlueprintLibrary") ++FunctionRedirects=(OldName="CesiumPropertyTablePropertyBlueprintLibrary.GetBlueprintComponentType", NewName="CesiumPropertyTablePropertyBlueprintLibrary.GetArrayElementBlueprintType") ++FunctionRedirects=(OldName="CesiumPropertyTablePropertyBlueprintLibrary.GetGenericValue", NewName="CesiumPropertyTablePropertyBlueprintLibrary.GetValue") ++FunctionRedirects=(OldName="CesiumPropertyTablePropertyBlueprintLibrary.GetNumberOfFeatures", NewName="CesiumPropertyTablePropertyBlueprintLibrary.GetPropertySize") ++FunctionRedirects=(OldName="CesiumPropertyTablePropertyBlueprintLibrary.GetComponentCount", NewName="CesiumPropertyTablePropertyBlueprintLibrary.GetArraySize") + ++StructRedirects=(OldName="CesiumFeatureTexture", NewName="CesiumPropertyTexture") ++StructRedirects=(OldName="CesiumFeatureTextureProperty", NewName="CesiumPropertyTextureProperty") ++FunctionRedirects=(OldName="CesiumPropertyTexturePropertyBlueprintLibrary.GetPropertyKeys", NewName="CesiumPropertyTexturePropertyBlueprintLibrary.GetPropertyNames") ++FunctionRedirects=(OldName="CesiumPropertyTexturePropertyBlueprintLibrary.GetTextureCoordinateIndex", NewName="CesiumPropertyTexturePropertyBlueprintLibrary.GetUnrealUVChannel") + ++StructRedirects=(OldName="CesiumMetadataModel", NewName="CesiumModelMetadata") ++ClassRedirects=(OldName="CesiumMetadataModelBlueprintLibrary", NewName="CesiumModelMetadataBlueprintLibrary") ++PropertyRedirects=(OldName="CesiumModelMetadataBlueprintLibrary.GetFeatureTables.MetadataModel", NewName="ModelMetadata") ++PropertyRedirects=(OldName="CesiumModelMetadataBlueprintLibrary.GetFeatureTextures.MetadataModel", NewName="ModelMetadata") + ++FunctionRedirects=(OldName="CesiumMetadataUtilityBlueprintLibrary.GetMetadataModel", NewName="CesiumModelMetadataBlueprintLibrary.GetModelMetadata") + ++EnumRedirects=(OldName="ECesiumPropertyComponentType", NewName="ECesiumPropertyComponentType_DEPRECATED", ValueChanges=(("Uint8","Uint8_DEPRECATED"),("Float","Float_DEPRECATED"))) + ++EnumRedirects=(OldName="ECesiumPropertyType", NewName="ECesiumPropertyType_DEPRECATED", ValueChanges=(("Scalar","Scalar_DEPRECATED"),("Vec2","Vec2_DEPRECATED"),("Vec3","Vec3_DEPRECATED"),("Vec4","Vec4_DEPRECATED"))) + ++EnumRedirects=(OldName="ECesiumFeatureTableAccessType", NewName="ECesiumFeatureTableAccessType_DEPRECATED", ValueChanges=(("Unknown","Unknown_DEPRECATED"),("Texture","Texture_DEPRECATED"),("Attribute","Attribute_DEPRECATED"),("Mixed","Mixed_DEPRECATED"))) + ++EnumRedirects=(OldName="ECesiumMetadataPackedGpuType", NewName="ECesiumMetadataPackedGpuType_DEPRECATED", ValueChanges=(("None","Unknown_DEPRECATED"),("Uint8","Uint8_DEPRECATED"),("Float","Float_DEPRECATED"))) + ++FunctionRedirects=(OldName="CesiumFeatureIdTextureBlueprintLibrary.GetTextureCoordinateIndex", NewName="CesiumFeatureIdTextureBlueprintLibrary.GetUnrealUVChannel") + ++PropertyRedirects=(OldName="CesiumWebMapTileServiceRasterOverlay.Url", NewName="CesiumWebMapTileServiceRasterOverlay.BaseUrl") ++PropertyRedirects=(OldName="CesiumWebMapTileServiceRasterOverlay.West", NewName="CesiumWebMapTileServiceRasterOverlay.RectangleWest") ++PropertyRedirects=(OldName="CesiumWebMapTileServiceRasterOverlay.South", NewName="CesiumWebMapTileServiceRasterOverlay.RectangleSouth") ++PropertyRedirects=(OldName="CesiumWebMapTileServiceRasterOverlay.East", NewName="CesiumWebMapTileServiceRasterOverlay.RectangleEast") ++PropertyRedirects=(OldName="CesiumWebMapTileServiceRasterOverlay.North", NewName="CesiumWebMapTileServiceRasterOverlay.RectangleNorth") ++PropertyRedirects=(OldName="CesiumWebMapTileServiceRasterOverlay.UseWebMercatorProjection", NewName="CesiumWebMapTileServiceRasterOverlay.UseWebMercatorProjection_DEPRECATED") + ++FunctionRedirects=(OldName="CesiumFeatureIdAttributeBlueprintLibrary.GetFeatureIDForVertex", NewName="CesiumFeatureIdAttributeBlueprintLibrary.GetFeatureID") ++PropertyRedirects=(OldName="CesiumFeatureIdAttributeBlueprintLibrary.GetFeatureIDForVertex.VertexIndex", NewName="CesiumFeatureIdAttributeBlueprintLibrary.GetFeatureID.Index") ++FunctionRedirects=(OldName="CesiumFeatureIdAttributeBlueprintLibrary.GetVertexCount", NewName="CesiumFeatureIdAttributeBlueprintLibrary.GetCount") diff --git a/Plugins/CesiumForUnreal/Config/FilterPlugin.ini b/Plugins/CesiumForUnreal/Config/FilterPlugin.ini new file mode 100644 index 0000000..57d2ebd --- /dev/null +++ b/Plugins/CesiumForUnreal/Config/FilterPlugin.ini @@ -0,0 +1,9 @@ +[FilterPlugin] +/Config/FilterPlugin.ini +/Config/Engine.ini +/Config/Editor.ini +/LICENSE +/README.md +/ThirdParty.json +/CHANGES.md +/Shaders/* diff --git a/Plugins/CesiumForUnreal/Content/Cesium-128x128.png b/Plugins/CesiumForUnreal/Content/Cesium-128x128.png new file mode 100644 index 0000000..8d8eb0a Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Cesium-128x128.png differ diff --git a/Plugins/CesiumForUnreal/Content/Cesium-64x64.png b/Plugins/CesiumForUnreal/Content/Cesium-64x64.png new file mode 100644 index 0000000..d5ff7d3 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Cesium-64x64.png differ diff --git a/Plugins/CesiumForUnreal/Content/Cesium-for-Unreal-Logo-BlackH.png b/Plugins/CesiumForUnreal/Content/Cesium-for-Unreal-Logo-BlackH.png new file mode 100644 index 0000000..90d2842 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Cesium-for-Unreal-Logo-BlackH.png differ diff --git a/Plugins/CesiumForUnreal/Content/Cesium-for-Unreal-Logo-Micro-BlackV.png b/Plugins/CesiumForUnreal/Content/Cesium-for-Unreal-Logo-Micro-BlackV.png new file mode 100644 index 0000000..6149f9c Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Cesium-for-Unreal-Logo-Micro-BlackV.png differ diff --git a/Plugins/CesiumForUnreal/Content/Cesium-for-Unreal-Logo-WhiteBGH.jpg b/Plugins/CesiumForUnreal/Content/Cesium-for-Unreal-Logo-WhiteBGH.jpg new file mode 100644 index 0000000..347c289 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Cesium-for-Unreal-Logo-WhiteBGH.jpg differ diff --git a/Plugins/CesiumForUnreal/Content/Cesium-for-Unreal-Logo-WhiteH.png b/Plugins/CesiumForUnreal/Content/Cesium-for-Unreal-Logo-WhiteH.png new file mode 100644 index 0000000..b385926 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Cesium-for-Unreal-Logo-WhiteH.png differ diff --git a/Plugins/CesiumForUnreal/Content/Cesium-icon-16x16.png b/Plugins/CesiumForUnreal/Content/Cesium-icon-16x16.png new file mode 100644 index 0000000..04b85bd Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Cesium-icon-16x16.png differ diff --git a/Plugins/CesiumForUnreal/Content/CesiumButton.png b/Plugins/CesiumForUnreal/Content/CesiumButton.png new file mode 100644 index 0000000..ff98e98 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/CesiumButton.png differ diff --git a/Plugins/CesiumForUnreal/Content/CesiumCreditSystemBP.uasset b/Plugins/CesiumForUnreal/Content/CesiumCreditSystemBP.uasset new file mode 100644 index 0000000..29f8d40 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/CesiumCreditSystemBP.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Cesium_for_Unreal_light_color_vertical-height150.png b/Plugins/CesiumForUnreal/Content/Cesium_for_Unreal_light_color_vertical-height150.png new file mode 100644 index 0000000..43b519c Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Cesium_for_Unreal_light_color_vertical-height150.png differ diff --git a/Plugins/CesiumForUnreal/Content/Cesium_for_Unreal_light_color_vertical.png b/Plugins/CesiumForUnreal/Content/Cesium_for_Unreal_light_color_vertical.png new file mode 100644 index 0000000..62d4343 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Cesium_for_Unreal_light_color_vertical.png differ diff --git a/Plugins/CesiumForUnreal/Content/Curve_AltitudeProfile_Float.uasset b/Plugins/CesiumForUnreal/Content/Curve_AltitudeProfile_Float.uasset new file mode 100644 index 0000000..3d19cd2 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Curve_AltitudeProfile_Float.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Curve_MaxAltitude_Float.uasset b/Plugins/CesiumForUnreal/Content/Curve_MaxAltitude_Float.uasset new file mode 100644 index 0000000..1e6523b Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Curve_MaxAltitude_Float.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Curve_PawnMovementSpeed_Float.uasset b/Plugins/CesiumForUnreal/Content/Curve_PawnMovementSpeed_Float.uasset new file mode 100644 index 0000000..0e13b1c Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Curve_PawnMovementSpeed_Float.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Curve_Progress_Float.uasset b/Plugins/CesiumForUnreal/Content/Curve_Progress_Float.uasset new file mode 100644 index 0000000..c1dd00e Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Curve_Progress_Float.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Curves/FlyTo/Curve_CesiumFlyToDefaultHeightPercentage_Float.uasset b/Plugins/CesiumForUnreal/Content/Curves/FlyTo/Curve_CesiumFlyToDefaultHeightPercentage_Float.uasset new file mode 100644 index 0000000..12ca2e0 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Curves/FlyTo/Curve_CesiumFlyToDefaultHeightPercentage_Float.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Curves/FlyTo/Curve_CesiumFlyToDefaultMaximumHeightByDistance_Float.uasset b/Plugins/CesiumForUnreal/Content/Curves/FlyTo/Curve_CesiumFlyToDefaultMaximumHeightByDistance_Float.uasset new file mode 100644 index 0000000..6402d3c Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Curves/FlyTo/Curve_CesiumFlyToDefaultMaximumHeightByDistance_Float.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Curves/FlyTo/Curve_CesiumFlyToDefaultProgress_Float.uasset b/Plugins/CesiumForUnreal/Content/Curves/FlyTo/Curve_CesiumFlyToDefaultProgress_Float.uasset new file mode 100644 index 0000000..29e4ce8 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Curves/FlyTo/Curve_CesiumFlyToDefaultProgress_Float.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/DynamicPawn.uasset b/Plugins/CesiumForUnreal/Content/DynamicPawn.uasset new file mode 100644 index 0000000..50e0c33 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/DynamicPawn.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/FloatingGameMode.uasset b/Plugins/CesiumForUnreal/Content/FloatingGameMode.uasset new file mode 100644 index 0000000..164a654 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/FloatingGameMode.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/attribution.txt b/Plugins/CesiumForUnreal/Content/FontAwesome/attribution.txt new file mode 100644 index 0000000..6c9fdec --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/attribution.txt @@ -0,0 +1,9 @@ +The SVG icons in this directory are from the "Font Awesome" project. +They are published under the CC BY 4.0 License. See +https://fontawesome.com/license/free for further information. + +The SVG files have been edited to change the fill color from +the "currentColor" to "#cccccc". +For "sync-alt-solid.svg", it was set to #ffffff, to be used +on a Cesium-styled button. +For "times-solid.svg" and "check-solid.svg" it was set to #ff0000 and #00ff00 respectively. diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/book-reader-solid.png b/Plugins/CesiumForUnreal/Content/FontAwesome/book-reader-solid.png new file mode 100644 index 0000000..d7da05c Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/FontAwesome/book-reader-solid.png differ diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/book-reader-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/book-reader-solid.svg new file mode 100644 index 0000000..00e2d0b --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/book-reader-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/check-solid.png b/Plugins/CesiumForUnreal/Content/FontAwesome/check-solid.png new file mode 100644 index 0000000..be52e32 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/FontAwesome/check-solid.png differ diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/check-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/check-solid.svg new file mode 100644 index 0000000..218a840 --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/check-solid.svg @@ -0,0 +1 @@ + diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/cloud-upload-alt-solid.png b/Plugins/CesiumForUnreal/Content/FontAwesome/cloud-upload-alt-solid.png new file mode 100644 index 0000000..522f663 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/FontAwesome/cloud-upload-alt-solid.png differ diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/cloud-upload-alt-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/cloud-upload-alt-solid.svg new file mode 100644 index 0000000..68b748b --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/cloud-upload-alt-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/hands-helping-solid.png b/Plugins/CesiumForUnreal/Content/FontAwesome/hands-helping-solid.png new file mode 100644 index 0000000..4c6ad45 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/FontAwesome/hands-helping-solid.png differ diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/hands-helping-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/hands-helping-solid.svg new file mode 100644 index 0000000..a03a480 --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/hands-helping-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/key-solid.png b/Plugins/CesiumForUnreal/Content/FontAwesome/key-solid.png new file mode 100644 index 0000000..763775f Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/FontAwesome/key-solid.png differ diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/key-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/key-solid.svg new file mode 100644 index 0000000..9137288 --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/key-solid.svg @@ -0,0 +1 @@ + diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/plus-solid.png b/Plugins/CesiumForUnreal/Content/FontAwesome/plus-solid.png new file mode 100644 index 0000000..b4c6e0d Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/FontAwesome/plus-solid.png differ diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/plus-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/plus-solid.svg new file mode 100644 index 0000000..0a32ed8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/plus-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/sign-out-alt-solid.png b/Plugins/CesiumForUnreal/Content/FontAwesome/sign-out-alt-solid.png new file mode 100644 index 0000000..99e1471 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/FontAwesome/sign-out-alt-solid.png differ diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/sign-out-alt-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/sign-out-alt-solid.svg new file mode 100644 index 0000000..42c488e --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/sign-out-alt-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/sync-alt-solid.png b/Plugins/CesiumForUnreal/Content/FontAwesome/sync-alt-solid.png new file mode 100644 index 0000000..45a0b12 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/FontAwesome/sync-alt-solid.png differ diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/sync-alt-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/sync-alt-solid.svg new file mode 100644 index 0000000..d6eefea --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/sync-alt-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/times-solid.png b/Plugins/CesiumForUnreal/Content/FontAwesome/times-solid.png new file mode 100644 index 0000000..a85f6a6 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/FontAwesome/times-solid.png differ diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/times-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/times-solid.svg new file mode 100644 index 0000000..d6e94a3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/times-solid.svg @@ -0,0 +1 @@ + diff --git a/Plugins/CesiumForUnreal/Content/Materials/Blends/MLB_CesiumAlphaBlendBaseColor.uasset b/Plugins/CesiumForUnreal/Content/Materials/Blends/MLB_CesiumAlphaBlendBaseColor.uasset new file mode 100644 index 0000000..3fe6a13 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Blends/MLB_CesiumAlphaBlendBaseColor.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Blends/MLB_CesiumClipping.uasset b/Plugins/CesiumForUnreal/Content/Materials/Blends/MLB_CesiumClipping.uasset new file mode 100644 index 0000000..caa41bf Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Blends/MLB_CesiumClipping.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Blends/MLB_CesiumSimpleWater.uasset b/Plugins/CesiumForUnreal/Content/Materials/Blends/MLB_CesiumSimpleWater.uasset new file mode 100644 index 0000000..f4a98b6 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Blends/MLB_CesiumSimpleWater.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Blends/MLB_DitherFade.uasset b/Plugins/CesiumForUnreal/Content/Materials/Blends/MLB_DitherFade.uasset new file mode 100644 index 0000000..31322a6 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Blends/MLB_DitherFade.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/CesiumSimpleWaterSurface.uasset b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/CesiumSimpleWaterSurface.uasset new file mode 100644 index 0000000..7901fa4 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/CesiumSimpleWaterSurface.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/CesiumWaterTextureWaves.uasset b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/CesiumWaterTextureWaves.uasset new file mode 100644 index 0000000..89355c3 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/CesiumWaterTextureWaves.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterAbsorption.uasset b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterAbsorption.uasset new file mode 100644 index 0000000..4aae3f6 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterAbsorption.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterAttributes.uasset b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterAttributes.uasset new file mode 100644 index 0000000..90683ff Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterAttributes.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterColorScale.uasset b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterColorScale.uasset new file mode 100644 index 0000000..009054e Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterColorScale.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterMaskSample.uasset b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterMaskSample.uasset new file mode 100644 index 0000000..8ebe581 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterMaskSample.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterScattering.uasset b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterScattering.uasset new file mode 100644 index 0000000..55a70db Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterScattering.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterWaves.uasset b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterWaves.uasset new file mode 100644 index 0000000..15f20b0 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/MF_CesiumWaterWaves.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/ML_CesiumLandWaterBlend.uasset b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/ML_CesiumLandWaterBlend.uasset new file mode 100644 index 0000000..c7c7cba Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/CesiumWaterMaterialFunctions/ML_CesiumLandWaterBlend.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Deprecated/M_DEPRECATED_CesiumDefaultMasked.uasset b/Plugins/CesiumForUnreal/Content/Materials/Deprecated/M_DEPRECATED_CesiumDefaultMasked.uasset new file mode 100644 index 0000000..74809cf Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Deprecated/M_DEPRECATED_CesiumDefaultMasked.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Deprecated/M_DEPRECATED_CesiumOverlay.uasset b/Plugins/CesiumForUnreal/Content/Materials/Deprecated/M_DEPRECATED_CesiumOverlay.uasset new file mode 100644 index 0000000..1a4f21e Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Deprecated/M_DEPRECATED_CesiumOverlay.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Deprecated/M_DEPRECATED_CesiumOverlayComplexWater.uasset b/Plugins/CesiumForUnreal/Content/Materials/Deprecated/M_DEPRECATED_CesiumOverlayComplexWater.uasset new file mode 100644 index 0000000..b0dba15 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Deprecated/M_DEPRECATED_CesiumOverlayComplexWater.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Deprecated/M_DEPRECATED_CesiumOverlayWater.uasset b/Plugins/CesiumForUnreal/Content/Materials/Deprecated/M_DEPRECATED_CesiumOverlayWater.uasset new file mode 100644 index 0000000..0ad127a Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Deprecated/M_DEPRECATED_CesiumOverlayWater.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Instances/MI_CesiumThreeOverlaysAndClipping.uasset b/Plugins/CesiumForUnreal/Content/Materials/Instances/MI_CesiumThreeOverlaysAndClipping.uasset new file mode 100644 index 0000000..675f07c Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Instances/MI_CesiumThreeOverlaysAndClipping.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Instances/MI_CesiumThreeOverlaysAndClippingAndWater.uasset b/Plugins/CesiumForUnreal/Content/Materials/Instances/MI_CesiumThreeOverlaysAndClippingAndWater.uasset new file mode 100644 index 0000000..da0ebf1 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Instances/MI_CesiumThreeOverlaysAndClippingAndWater.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Instances/MI_CesiumThreeOverlaysAndClippingTranslucent.uasset b/Plugins/CesiumForUnreal/Content/Materials/Instances/MI_CesiumThreeOverlaysAndClippingTranslucent.uasset new file mode 100644 index 0000000..6e1e6e6 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Instances/MI_CesiumThreeOverlaysAndClippingTranslucent.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumGltf.uasset b/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumGltf.uasset new file mode 100644 index 0000000..e8b30e2 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumGltf.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumNothing.uasset b/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumNothing.uasset new file mode 100644 index 0000000..b701a8b Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumNothing.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumRasterOverlay.uasset b/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumRasterOverlay.uasset new file mode 100644 index 0000000..386a72f Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumRasterOverlay.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumSimpleWater.uasset b/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumSimpleWater.uasset new file mode 100644 index 0000000..4b63ae9 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumSimpleWater.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumWaterMask.uasset b/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumWaterMask.uasset new file mode 100644 index 0000000..dab2eaa Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_CesiumWaterMask.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_DitherFade.uasset b/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_DitherFade.uasset new file mode 100644 index 0000000..a765e0f Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/Layers/ML_DitherFade.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/M_CesiumBaseMaterial.uasset b/Plugins/CesiumForUnreal/Content/Materials/M_CesiumBaseMaterial.uasset new file mode 100644 index 0000000..feb8a36 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/M_CesiumBaseMaterial.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/M_CesiumDefaultMasked.uasset b/Plugins/CesiumForUnreal/Content/Materials/M_CesiumDefaultMasked.uasset new file mode 100644 index 0000000..b6164d6 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/M_CesiumDefaultMasked.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/M_CesiumOverlay.uasset b/Plugins/CesiumForUnreal/Content/Materials/M_CesiumOverlay.uasset new file mode 100644 index 0000000..bfe96f5 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/M_CesiumOverlay.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/M_CesiumOverlayComplexWater.uasset b/Plugins/CesiumForUnreal/Content/Materials/M_CesiumOverlayComplexWater.uasset new file mode 100644 index 0000000..bc8f8eb Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/M_CesiumOverlayComplexWater.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/M_CesiumOverlayWater.uasset b/Plugins/CesiumForUnreal/Content/Materials/M_CesiumOverlayWater.uasset new file mode 100644 index 0000000..533b360 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/M_CesiumOverlayWater.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGetFeatureIdsFromAttribute.uasset b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGetFeatureIdsFromAttribute.uasset new file mode 100644 index 0000000..87fc0e4 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGetFeatureIdsFromAttribute.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGetFeatureIdsFromInstance.uasset b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGetFeatureIdsFromInstance.uasset new file mode 100644 index 0000000..ee69ced Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGetFeatureIdsFromInstance.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGetFeatureIdsFromTexture.uasset b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGetFeatureIdsFromTexture.uasset new file mode 100644 index 0000000..b618c49 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGetFeatureIdsFromTexture.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGlTFFunction.uasset b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGlTFFunction.uasset new file mode 100644 index 0000000..941b59d Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGlTFFunction.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGltfWithOverlays.uasset b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGltfWithOverlays.uasset new file mode 100644 index 0000000..7cc1c59 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumGltfWithOverlays.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumOverlayWater.uasset b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumOverlayWater.uasset new file mode 100644 index 0000000..6e45812 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumOverlayWater.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumPointInBox.uasset b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumPointInBox.uasset new file mode 100644 index 0000000..87a526e Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumPointInBox.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumRasterOverlay.uasset b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumRasterOverlay.uasset new file mode 100644 index 0000000..6f31d24 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumRasterOverlay.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumSelectTexCoords.uasset b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumSelectTexCoords.uasset new file mode 100644 index 0000000..66e8221 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/CesiumSelectTexCoords.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/MF_CesiumSampleRasterOverlay.uasset b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/MF_CesiumSampleRasterOverlay.uasset new file mode 100644 index 0000000..8803831 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/MF_CesiumSampleRasterOverlay.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/MF_CesiumTransformTextureCoordinates.uasset b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/MF_CesiumTransformTextureCoordinates.uasset new file mode 100644 index 0000000..e285387 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Materials/MaterialFunctions/MF_CesiumTransformTextureCoordinates.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/MobileSkySphere.uasset b/Plugins/CesiumForUnreal/Content/MobileSkySphere.uasset new file mode 100644 index 0000000..6e3a909 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/MobileSkySphere.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/ScreenCredits.uasset b/Plugins/CesiumForUnreal/Content/ScreenCredits.uasset new file mode 100644 index 0000000..f717f77 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/ScreenCredits.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Tests/Maps/ConeAndCylinder.umap b/Plugins/CesiumForUnreal/Content/Tests/Maps/ConeAndCylinder.umap new file mode 100644 index 0000000..5843fe1 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Tests/Maps/ConeAndCylinder.umap differ diff --git a/Plugins/CesiumForUnreal/Content/Tests/Maps/SingleCube.umap b/Plugins/CesiumForUnreal/Content/Tests/Maps/SingleCube.umap new file mode 100644 index 0000000..e7ca2d1 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Tests/Maps/SingleCube.umap differ diff --git a/Plugins/CesiumForUnreal/Content/Textures/NoColorTexture.uasset b/Plugins/CesiumForUnreal/Content/Textures/NoColorTexture.uasset new file mode 100644 index 0000000..d0c07f8 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Textures/NoColorTexture.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Textures/NoMetallicRoughnessTexture.uasset b/Plugins/CesiumForUnreal/Content/Textures/NoMetallicRoughnessTexture.uasset new file mode 100644 index 0000000..742d74c Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Textures/NoMetallicRoughnessTexture.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Textures/NoNormalTexture.uasset b/Plugins/CesiumForUnreal/Content/Textures/NoNormalTexture.uasset new file mode 100644 index 0000000..12adb94 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Textures/NoNormalTexture.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Textures/T_Water_TilingNormal_With_Height_02_Softened.uasset b/Plugins/CesiumForUnreal/Content/Textures/T_Water_TilingNormal_With_Height_02_Softened.uasset new file mode 100644 index 0000000..0eb8984 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Textures/T_Water_TilingNormal_With_Height_02_Softened.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/Textures/transparent1x1.uasset b/Plugins/CesiumForUnreal/Content/Textures/transparent1x1.uasset new file mode 100644 index 0000000..1701f5c Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/Textures/transparent1x1.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/WBP_Profiling.uasset b/Plugins/CesiumForUnreal/Content/WBP_Profiling.uasset new file mode 100644 index 0000000..a49c394 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/WBP_Profiling.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/WBP_TimeOfDay.uasset b/Plugins/CesiumForUnreal/Content/WBP_TimeOfDay.uasset new file mode 100644 index 0000000..d995a41 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/WBP_TimeOfDay.uasset differ diff --git a/Plugins/CesiumForUnreal/Content/WGS84.uasset b/Plugins/CesiumForUnreal/Content/WGS84.uasset new file mode 100644 index 0000000..40cdf83 Binary files /dev/null and b/Plugins/CesiumForUnreal/Content/WGS84.uasset differ diff --git a/Plugins/CesiumForUnreal/LICENSE b/Plugins/CesiumForUnreal/LICENSE new file mode 100644 index 0000000..66a27ec --- /dev/null +++ b/Plugins/CesiumForUnreal/LICENSE @@ -0,0 +1,177 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/Plugins/CesiumForUnreal/README.md b/Plugins/CesiumForUnreal/README.md new file mode 100644 index 0000000..f2c95b5 --- /dev/null +++ b/Plugins/CesiumForUnreal/README.md @@ -0,0 +1,58 @@ +[![Cesium for Unreal Logo](Content/Cesium-for-Unreal-Logo-WhiteBGH.jpg)](https://cesium.com/unreal-marketplace?utm_source=cesium-unreal&utm_medium=github&utm_campaign=unreal) + +_This branch targets Unreal Engine 5. There is also a branch targeting [Unreal Engine 4](../../tree/ue4-main)_ + +Cesium for Unreal brings the 3D geospatial ecosystem to Unreal Engine. By combining a high-accuracy full-scale WGS84 globe, open APIs and open standards for spatial indexing such as 3D Tiles, and cloud-based real-world content from [Cesium ion](https://cesium.com/cesium-ion) with Unreal Engine, this project enables a new era of 3D geospatial software. + +[Cesium for Unreal Homepage](https://cesium.com/cesium-for-unreal?utm_source=github&utm_medium=github&utm_campaign=unreal) + +### 🚀 Get Started + +**[Download Cesium for Unreal from Unreal Engine Marketplace](https://cesium.com/unreal-marketplace?utm_source=cesium-unreal&utm_medium=github&utm_campaign=unreal)** + +**[Follow the Quickstart](https://cesium.com/docs/tutorials/cesium-unreal-quickstart/)** + +Have questions? Ask them on the [community forum](https://community.cesium.com). + +### 👏 Featured Demos + +

+  +  +
+
+

+ +### 🏡 Cesium for Unreal and the 3D Geospatial Ecosystem + +Cesium for Unreal streams real-world 3D content such as high-resolution photogrammetry, terrain, imagery, and 3D buildings from [Cesium ion](https://cesium.com/cesium-ion) and other sources, available as optional commercial subscriptions. The plugin includes Cesium ion integration for instant access to global high-resolution 3D content ready for runtime streaming. Cesium ion users can also leverage cloud-based 3D tiling pipelines to create end-to-end workflows to transform massive heterogenous content into semantically-rich 3D Tiles, ready for streaming to Unreal Engine. + +Cesium for Unreal supports cloud and private network content and services based on open standards and APIs. You are free to use any combination of supported content sources, standards, APIs with Cesium for Unreal. + +[![Cesium for Unreal Ecosystem Architecture](https://prismic-io.s3.amazonaws.com/cesium/b1505fbc-5769-4032-9233-364a4f52acf6_unreal-pipeline-ice-blue-background.png)](https://cesium.com/cesium-for-unreal?utm_source=cesium-unreal&utm_medium=github&utm_campaign=unreal) + +Using Cesium ion helps support Cesium for Unreal development. :heart: + +### ⛓️ Unreal Engine Integration + +Cesium for Unreal is tightly integrated with Unreal Engine making it possible to visualize and interact with real-world content in editor and at runtime. The plugin also has support for Unreal Engine physics, collisions, character interaction, and landscaping tools. Leverage decades worth of cutting-edge advancements in Unreal Engine and geospatial to create cohesive, interactive, and realistic simulations and applications with Cesium for Unreal. + +### 📗 License + +[Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). Cesium for Unreal is free for both commercial and non-commercial use. + +### 📦 Installing Cesium for Unreal + +The easiest way to install Cesium for Unreal is by downloading the officially released version from the [Unreal Engine Marketplace](https://cesium.com/unreal-marketplace?utm_source=cesium-unreal&utm_medium=github&utm_campaign=unreal). + +You can also find all releases on the [Releases](https://github.com/CesiumGS/cesium-unreal/releases) page. This is useful if you want an older version, or if you can't or don't want to use the Unreal Engine Marketplace. In particular, if you're using Linux, the Releases page is a better option. To install any of these releases: + +1. If you previously installed the Cesium for Unreal plugin via the Unreal Engine Marketplace, uninstall it. +2. Extract the release ZIP to Unreal Engine's `Engine/Plugins/Marketplace` directory. For example, on Unreal Engine 5.3 on Windows, this is typically `C:\Program Files\Epic Games\UE_5.3\Engine\Plugins\Marketplace`. You may need to create the `Marketplace` directory yourself. +3. If you've done this correctly, you'll find a `CesiumForUnreal` sub-directory inside the `Marketplace` directory, and the plugin is ready to use. + +You can also [use pre-release packages](Documentation/using-prerelease-packages.md). + +### 💻 Developing with Unreal Engine + +See the [Developer Setup Guide](Documentation/developer-setup.md) to learn how to set up a development environment for Cesium for Unreal, allowing you to compile it, customize it, and contribute to its development. diff --git a/Plugins/CesiumForUnreal/Resources/Icon128.png b/Plugins/CesiumForUnreal/Resources/Icon128.png new file mode 100644 index 0000000..8d8eb0a Binary files /dev/null and b/Plugins/CesiumForUnreal/Resources/Icon128.png differ diff --git a/Plugins/CesiumForUnreal/Shaders/Private/CesiumPointAttenuationVertexFactory.ush b/Plugins/CesiumForUnreal/Shaders/Private/CesiumPointAttenuationVertexFactory.ush new file mode 100644 index 0000000..c484068 --- /dev/null +++ b/Plugins/CesiumForUnreal/Shaders/Private/CesiumPointAttenuationVertexFactory.ush @@ -0,0 +1,507 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +/*============================================================================= + CesiumPointAttenuationVertexFactory.ush: point attenuation vertex factory shader code. +=============================================================================*/ + +#ifndef ENGINE_VERSION_5_4_OR_HIGHER +#define ENGINE_VERSION_5_4_OR_HIGHER 0 +#endif + +#ifndef ENGINE_VERSION_5_5_OR_HIGHER +#define ENGINE_VERSION_5_5_OR_HIGHER 0 +#endif + +#include "/Engine/Private/Common.ush" +#include "/Engine/Private/VertexFactoryCommon.ush" + +Buffer PositionBuffer; +Buffer PackedTangentsBuffer; +Buffer ColorBuffer; +Buffer TexCoordBuffer; +uint NumTexCoords; + +// Whether or not the point cloud has per-point colors. +uint bHasPointColors; +float3 AttenuationParameters; + +#if INSTANCED_STEREO +uint InstancedEyeIndex; +#endif + +// This function does not exist in UE 5.0, so remove the function call here +// to avoid compilation errors. +#ifndef VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK +#define VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK() +#endif + +/* + * Per-vertex input. Only a position buffer is bound. + */ +struct FVertexFactoryInput +{ + uint VertexId : SV_VertexID; +#if USE_INSTANCING + uint InstanceId : SV_InstanceID; +#else + VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK() +#endif +}; + +/** + * Per-vertex inputs. Used by passes with a trimmed down position-only shader. + */ +struct FPositionOnlyVertexFactoryInput +{ + float4 Position : ATTRIBUTE0; + uint VertexId : SV_VertexID; +#if USE_INSTANCING + uint InstanceId : SV_InstanceID; +#else + VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK() +#endif +}; + +/** + * Per-vertex inputs. Used by passes with a trimmed down position-and-normal-only shader. + */ +struct FPositionAndNormalOnlyVertexFactoryInput +{ + float4 Position : ATTRIBUTE0; + float4 Normal : ATTRIBUTE2; + uint VertexId : SV_VertexID; +#if USE_INSTANCING + uint InstanceId : SV_InstanceID; +#else + VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK() +#endif +}; + +/** Cached intermediates that would otherwise have to be computed multiple times. */ +struct FVertexFactoryIntermediates +{ + uint PointIndex; + uint CornerIndex; + + float3 Position; + float4 WorldPosition; + + half3x3 TangentToLocal; + half3x3 TangentToWorld; + half TangentToWorldSign; + + half4 Color; + + /** Cached primitive and instance data */ + FSceneDataIntermediates SceneData; +}; + +struct FVertexFactoryInterpolantsVSToPS +{ + TANGENTTOWORLD_INTERPOLATOR_BLOCK + half4 Color : COLOR0; + +#if NUM_TEX_COORD_INTERPOLATORS + float4 TexCoords[(NUM_TEX_COORD_INTERPOLATORS+1)/2] : TEXCOORD0; +#endif + +#if INSTANCED_STEREO + nointerpolation uint EyeIndex : PACKED_EYE_INDEX; +#endif +}; + +/** Helper function for position-only passes that don't require point index for other intermediates.*/ +float4 GetWorldPosition(uint VertexId) +{ + uint PointIndex = VertexId / 4; + float3 Position = float3(0, 0, 0); + Position.x = PositionBuffer[PointIndex * 3 + 0]; + Position.y = PositionBuffer[PointIndex * 3 + 1]; + Position.z = PositionBuffer[PointIndex * 3 + 2]; + + return TransformLocalToTranslatedWorld(Position); +} + +/** Computes TangentToLocal based on the Manual Vertex Fetch method in LocalVertexFactory.ush */ +half3x3 CalculateTangentToLocal(uint PointIndex, out float TangentSign) +{ + half3 TangentInputX = PackedTangentsBuffer[2 * PointIndex + 0].xyz; + half4 TangentInputZ = PackedTangentsBuffer[2 * PointIndex + 1].xyzw; + + half3 TangentX = TangentBias(TangentInputX); + half4 TangentZ = TangentBias(TangentInputZ); + + TangentSign = TangentZ.w; + + // Derive the binormal by getting the cross product of the normal and tangent + half3 TangentY = cross(TangentZ.xyz, TangentX) * TangentZ.w; + + // Recalculate TangentX off of the other two vectors + // This corrects quantization errors since TangentX was passed in as a quantized vertex input + half3x3 Result; + Result[0] = cross(TangentY, TangentZ.xyz) * TangentZ.w; + Result[1] = TangentY; + Result[2] = TangentZ.xyz; + + return Result; +} + +half3x3 CalculateTangentToWorldNoScale(half3x3 TangentToLocal) +{ + half3x3 LocalToWorld = GetLocalToWorld3x3(); + half3 InvScale = Primitive.InvNonUniformScale; + LocalToWorld[0] *= InvScale.x; + LocalToWorld[1] *= InvScale.y; + LocalToWorld[2] *= InvScale.z; + return mul(TangentToLocal, LocalToWorld); +} + +/** Helper function for position and normal-only passes that don't require point index for other intermediates.*/ +float3 GetPointNormal(uint VertexId) { + uint PointIndex = VertexId / 4; + return PackedTangentsBuffer[2 * PointIndex + 1].xyz; +} + +FVertexFactoryIntermediates GetVertexFactoryIntermediates(FVertexFactoryInput Input) +{ + FVertexFactoryIntermediates Intermediates = (FVertexFactoryIntermediates)0; + Intermediates.SceneData = VF_GPUSCENE_GET_INTERMEDIATES(Input); + + uint PointIndex = Input.VertexId / 4; + uint CornerIndex = Input.VertexId - (PointIndex * 4); + + Intermediates.PointIndex = PointIndex; + Intermediates.CornerIndex = CornerIndex; + + Intermediates.Position.x = PositionBuffer[PointIndex * 3 + 0]; + Intermediates.Position.y = PositionBuffer[PointIndex * 3 + 1]; + Intermediates.Position.z = PositionBuffer[PointIndex * 3 + 2]; + Intermediates.WorldPosition = TransformLocalToTranslatedWorld(Intermediates.Position); + + float TangentSign = 1.0; + Intermediates.TangentToLocal = CalculateTangentToLocal(Intermediates.PointIndex, TangentSign); + Intermediates.TangentToWorld = CalculateTangentToWorldNoScale(Intermediates.TangentToLocal); + Intermediates.TangentToWorldSign = Intermediates.SceneData.InstanceData.DeterminantSign; + + bool bHasColors = bHasPointColors; + float4 Color = bHasColors ? ColorBuffer[PointIndex] : float4(1, 1, 1, 1); + Intermediates.Color = Color FMANUALFETCH_COLOR_COMPONENT_SWIZZLE; + + return Intermediates; +} + + +#if NUM_TEX_COORD_INTERPOLATORS +/** Taken from LocalVertexFactoryCommon.ush. */ + +float2 GetUV(FVertexFactoryInterpolantsVSToPS Interpolants, int UVIndex) +{ + float4 UVVector = Interpolants.TexCoords[UVIndex / 2]; + return UVIndex % 2 ? UVVector.zw : UVVector.xy; +} + +void SetUV(inout FVertexFactoryInterpolantsVSToPS Interpolants, int UVIndex, float2 InValue) +{ + FLATTEN + if (UVIndex % 2) + { + Interpolants.TexCoords[UVIndex / 2].zw = InValue; + } + else + { + Interpolants.TexCoords[UVIndex / 2].xy = InValue; + } +} +#endif + +FVertexFactoryInterpolantsVSToPS VertexFactoryGetInterpolantsVSToPS( + FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, FMaterialVertexParameters VertexParameters) +{ + FVertexFactoryInterpolantsVSToPS Interpolants = (FVertexFactoryInterpolantsVSToPS)0; + Interpolants.TangentToWorld0 = float4(Intermediates.TangentToWorld[0], 0); + Interpolants.TangentToWorld2 = float4(Intermediates.TangentToWorld[2], Intermediates.TangentToWorldSign); + Interpolants.Color = Intermediates.Color; + + #if NUM_TEX_COORD_INTERPOLATORS + float2 CustomizedUVs[NUM_TEX_COORD_INTERPOLATORS]; + GetMaterialCustomizedUVs(VertexParameters, CustomizedUVs); + GetCustomInterpolators(VertexParameters, CustomizedUVs); + + UNROLL + for (int CoordinateIndex = 0; CoordinateIndex < NUM_TEX_COORD_INTERPOLATORS; CoordinateIndex++) + { + SetUV(Interpolants, CoordinateIndex, CustomizedUVs[CoordinateIndex]); + } +#endif + +#if INSTANCED_STEREO + Interpolants.EyeIndex = 0; +#endif + + return Interpolants; +} + +half3x3 VertexFactoryGetTangentToLocal(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates) +{ + return Intermediates.TangentToLocal; +} + +float4 VertexFactoryGetWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates) +{ + return Intermediates.WorldPosition; +} + +float4 VertexFactoryGetWorldPosition(FPositionOnlyVertexFactoryInput Input) +{ + return GetWorldPosition(Input.VertexId); +} + +float4 VertexFactoryGetWorldPosition(FPositionAndNormalOnlyVertexFactoryInput Input) +{ + return GetWorldPosition(Input.VertexId); +} + +// local position relative to instance +float3 VertexFactoryGetInstanceSpacePosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates) +{ + // No support for instancing, so instance == primitive + return Intermediates.Position; +} + +float3 VertexFactoryGetWorldNormal(FPositionAndNormalOnlyVertexFactoryInput Input) +{ + float3 PointNormal = GetPointNormal(Input.VertexId); + return RotateLocalToWorld(PointNormal); +} + +float3 VertexFactoryGetWorldNormal(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates) +{ + return Intermediates.TangentToWorld[2]; +} + +float4 VertexFactoryGetPreviousWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates) +{ + #ifdef DFGetX + // When double floats exist (UE 5.4), use the df tranform functions + return DFTransformLocalToTranslatedWorld(Intermediates.Position, Intermediates.SceneData.InstanceData.PrevLocalToWorld, ResolvedView.PrevPreViewTranslation); + #else + return mul(float4(Intermediates.Position, 1), + LWCMultiplyTranslation(Intermediates.SceneData.InstanceData.PrevLocalToWorld, ResolvedView.PrevPreViewTranslation)); + #endif +} + +// local position relative to instance +float3 VertexFactoryGetPreviousInstanceSpacePosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates) +{ + // No support for instancing, so instance == primitive + return Intermediates.Position; +} + +float4 ApplyAttenuation(float4 WorldPosition, uint CornerIndex) { + // These offsets generate the quad like so: + // 1 --- 2 + // | / | + // 0 --- 3 + // Unreal uses counter-clockwise winding order, but Cesium models are created + // with a y-inverting transform. To compensate, we create the quad facing the + // wrong way, such that when the transform is applied, the quad faces the right + // way. + + // Results in -0.5 for 0, 1 and 0.5 for 2, 3 + float OffsetX = CornerIndex / 2 - 0.5; + float OffsetY = -0.5f; + if (CornerIndex == 1 || CornerIndex == 2) { + OffsetY = 0.5; + } + + float4 PositionView = mul(WorldPosition, ResolvedView.TranslatedWorldToView); + float4 PositionClip = mul(WorldPosition, ResolvedView.TranslatedWorldToClip); + + float MaximumPointSize = AttenuationParameters.x; + float GeometricError = AttenuationParameters.y; + float DepthMultiplier = AttenuationParameters.z; + float Depth = PositionView.z / 100; // Get depth in meters + float PointSize = min((GeometricError / Depth) * DepthMultiplier, MaximumPointSize); + + float2 PixelOffset = PointSize * float2(OffsetX, OffsetY); + float2 ScreenOffset = PixelOffset * ResolvedView.ViewSizeAndInvSize.zw; + float2 ClipOffset = ScreenOffset * PositionClip.w; + float4 ViewOffset = mul(float4(ClipOffset, PositionClip.z, 1), ResolvedView.ClipToView); + ViewOffset /= ViewOffset.w; + + // Adjust x-component for the left-handed coordinate system. + float3 AttenuatedPosition = WorldPosition.xyz + (-ViewOffset.x * ResolvedView.ViewRight + ViewOffset.y * ResolvedView.ViewUp); + return float4(AttenuatedPosition, 1); +} + +float4 VertexFactoryGetRasterizedWorldPosition( + FVertexFactoryInput Input, + FVertexFactoryIntermediates Intermediates, + float4 InWorldPosition) +{ + return ApplyAttenuation(InWorldPosition, Intermediates.CornerIndex); +} + +float3 VertexFactoryGetPositionForVertexLighting( + FVertexFactoryInput Input, + FVertexFactoryIntermediates Intermediates, + float3 TranslatedWorldPosition) +{ + return TranslatedWorldPosition; +} + +/** Converts from vertex factory specific input to a FMaterialVertexParameters, which is used by vertex shader material inputs. */ +FMaterialVertexParameters GetMaterialVertexParameters( + FVertexFactoryInput Input, + FVertexFactoryIntermediates Intermediates, + float3 WorldPosition, + half3x3 TangentToLocal, + bool bIsPreviousFrame = false) +{ +#if ENGINE_VERSION_5_5_OR_HIGHER + FMaterialVertexParameters Result = MakeInitializedMaterialVertexParameters(); + if (bIsPreviousFrame) + { + Result.PositionInstanceSpace = VertexFactoryGetPreviousInstanceSpacePosition(Input, Intermediates); + } + else + { + Result.PositionInstanceSpace = VertexFactoryGetInstanceSpacePosition(Input, Intermediates); + } + Result.PositionPrimitiveSpace = Result.PositionInstanceSpace; // No support for instancing, so instance == primitive +#else + FMaterialVertexParameters Result = (FMaterialVertexParameters)0; +#endif + + Result.SceneData = Intermediates.SceneData; + Result.WorldPosition = WorldPosition; + Result.TangentToWorld = Intermediates.TangentToWorld; + Result.PreSkinnedNormal = TangentToLocal[2]; + Result.PreSkinnedPosition = WorldPosition; + Result.VertexColor = Intermediates.Color; + +#if NUM_MATERIAL_TEXCOORDS_VERTEX + UNROLL + for (uint CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS_VERTEX; CoordinateIndex++) + { + // Clamp coordinates to mesh's maximum as materials can request more than are available + uint ClampedCoordinateIndex = min(CoordinateIndex, NumTexCoords - 1); + Result.TexCoords[CoordinateIndex] = TexCoordBuffer[NumTexCoords * Intermediates.PointIndex + ClampedCoordinateIndex]; + } +#endif + +#if ENGINE_VERSION_5_4_OR_HIGHER + Result.LWCData = MakeMaterialLWCData(Result); +#endif + + return Result; +} + +FMaterialPixelParameters GetMaterialPixelParameters(FVertexFactoryInterpolantsVSToPS Interpolants, float4 SvPosition) +{ + FMaterialPixelParameters Result = MakeInitializedMaterialPixelParameters(); + + Result.Particle.Color = half4(1, 1, 1, 1); + Result.TwoSidedSign = 1; + Result.VertexColor = Interpolants.Color; + + half3 TangentToWorld0 = Interpolants.TangentToWorld0.xyz; + half4 TangentToWorld2 = Interpolants.TangentToWorld2; + Result.UnMirrored = TangentToWorld2.w; + Result.TangentToWorld = AssembleTangentToWorld(TangentToWorld0, TangentToWorld2); + +#if NUM_TEX_COORD_INTERPOLATORS + UNROLL + for( int CoordinateIndex = 0; CoordinateIndex < NUM_TEX_COORD_INTERPOLATORS; CoordinateIndex++ ) + { + Result.TexCoords[CoordinateIndex] = GetUV(Interpolants, CoordinateIndex); + } +#endif + + return Result; +} + +#if USE_INSTANCING +float4 VertexFactoryGetInstanceHitProxyId(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates) { return 0; } +#endif + +float4 VertexFactoryGetTranslatedPrimitiveVolumeBounds(FVertexFactoryInterpolantsVSToPS Interpolants) +{ + FPrimitiveSceneData PrimitiveData = GetPrimitiveDataFromUniformBuffer(); + return float4(LWCToFloat(LWCAdd(PrimitiveData.ObjectWorldPosition, ResolvedView.PreViewTranslation)), PrimitiveData.ObjectRadius); +} + +#if INSTANCED_STEREO +uint VertexFactoryGetEyeIndex(uint InstanceId) +{ +#if USE_INSTANCING + return InstancedEyeIndex; +#else + return InstanceId & 1; +#endif +} +#endif + +#if NEEDS_VERTEX_FACTORY_INTERPOLATION +struct FVertexFactoryRayTracingInterpolants +{ + FVertexFactoryInterpolantsVSToPS InterpolantsVSToPS; +}; + +float2 VertexFactoryGetRayTracingTextureCoordinate(FVertexFactoryRayTracingInterpolants Interpolants) +{ +#if NUM_MATERIAL_TEXCOORDS + return Interpolants.InterpolantsVSToPS.TexCoords[0].xy; +#else + return float2(0,0); +#endif +} + +FVertexFactoryInterpolantsVSToPS VertexFactoryAssignInterpolants(FVertexFactoryRayTracingInterpolants Input) +{ + return Input.InterpolantsVSToPS; +} + +FVertexFactoryRayTracingInterpolants VertexFactoryGetRayTracingInterpolants( + FVertexFactoryInput Input, + FVertexFactoryIntermediates Intermediates, + FMaterialVertexParameters VertexParameters) +{ + FVertexFactoryRayTracingInterpolants Interpolants; + Interpolants.InterpolantsVSToPS = VertexFactoryGetInterpolantsVSToPS(Input, Intermediates, VertexParameters); + return Interpolants; +} + +FVertexFactoryRayTracingInterpolants VertexFactoryInterpolate( + FVertexFactoryRayTracingInterpolants a, + float aInterp, + FVertexFactoryRayTracingInterpolants b, + float bInterp) +{ + FVertexFactoryRayTracingInterpolants O; + + INTERPOLATE_MEMBER(InterpolantsVSToPS.TangentToWorld0.xyz); + INTERPOLATE_MEMBER(InterpolantsVSToPS.TangentToWorld2); + +#if INTERPOLATE_VERTEX_COLOR + INTERPOLATE_MEMBER(InterpolantsVSToPS.Color); +#endif + +#if NUM_TEX_COORD_INTERPOLATORS + UNROLL + for(int tc = 0; tc < (NUM_TEX_COORD_INTERPOLATORS+1)/2; ++tc) + { + INTERPOLATE_MEMBER(InterpolantsVSToPS.TexCoords[tc]); + } +#endif + + return O; +} +#endif // #if NEEDS_VERTEX_FACTORY_INTERPOLATION + +uint VertexFactoryGetPrimitiveId(FVertexFactoryInterpolantsVSToPS Interpolants) +{ + return 0; +} + +#include "/Engine/Private/VertexFactoryDefaultInterface.ush" diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/CesiumEditor.Build.cs b/Plugins/CesiumForUnreal/Source/CesiumEditor/CesiumEditor.Build.cs new file mode 100644 index 0000000..4b39523 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/CesiumEditor.Build.cs @@ -0,0 +1,127 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +using UnrealBuildTool; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +public class CesiumEditor : ModuleRules +{ + public CesiumEditor(ReadOnlyTargetRules Target) : base(Target) + { + PublicIncludePaths.AddRange( + new string[] { + // ... add public include paths required here ... + } + ); + + + PrivateIncludePaths.AddRange( + new string[] { + Path.Combine(ModuleDirectory, "../ThirdParty/include") + } + ); + + string platform; + string libSearchPattern; + if (Target.Platform == UnrealTargetPlatform.Win64) + { + platform = "Windows-AMD64-"; + libSearchPattern = "*.lib"; + } + else if (Target.Platform == UnrealTargetPlatform.Mac) + { + platform = "Darwin-universal-"; + libSearchPattern = "lib*.a"; + } + else if (Target.Platform == UnrealTargetPlatform.Android) + { + platform = "Android-aarch64-"; + libSearchPattern = "lib*.a"; + } + else if (Target.Platform == UnrealTargetPlatform.Linux) + { + platform = "Linux-x86_64-"; + libSearchPattern = "lib*.a"; + } + else if (Target.Platform == UnrealTargetPlatform.IOS) + { + platform = "iOS-ARM64-"; + libSearchPattern = "lib*.a"; + } + else + { + throw new InvalidOperationException("Cesium for Unreal does not support this platform."); + } + + string libPathBase = Path.Combine(ModuleDirectory, "../ThirdParty/lib/" + platform); + string libPathDebug = libPathBase + "Debug"; + string libPathRelease = libPathBase + "Release"; + + bool useDebug = false; + if (Target.Configuration == UnrealTargetConfiguration.Debug || Target.Configuration == UnrealTargetConfiguration.DebugGame) + { + if (Directory.Exists(libPathDebug)) + { + useDebug = true; + } + } + + string libPath = useDebug ? libPathDebug : libPathRelease; + + string[] allLibs = Directory.Exists(libPath) ? Directory.GetFiles(libPath, libSearchPattern) : new string[0]; + + PublicAdditionalLibraries.AddRange(allLibs); + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "UnrealEd", + "CesiumRuntime", + "OpenSSL" + } + ); + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "ApplicationCore", + "Slate", + "SlateCore", + "MeshDescription", + "StaticMeshDescription", + "HTTP", + "MikkTSpace", + "Chaos", + "Projects", + "InputCore", + "PropertyEditor", + "DeveloperSettings", + "EditorStyle" + // ... add private dependencies that you statically link with here ... + } + ); + + PublicDefinitions.AddRange( + new string[] + { + } + ); + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + + IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_2; + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + CppStandard = CppStandardVersion.Cpp20; + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/Cesium3DTilesetCustomization.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/Cesium3DTilesetCustomization.cpp new file mode 100644 index 0000000..62bd03c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/Cesium3DTilesetCustomization.cpp @@ -0,0 +1,41 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "Cesium3DTilesetCustomization.h" +#include "Cesium3DTileset.h" +#include "CesiumCustomization.h" +#include "DetailCategoryBuilder.h" +#include "DetailLayoutBuilder.h" + +FName FCesium3DTilesetCustomization::RegisteredLayoutName; + +void FCesium3DTilesetCustomization::Register( + FPropertyEditorModule& PropertyEditorModule) { + + RegisteredLayoutName = ACesium3DTileset::StaticClass()->GetFName(); + + PropertyEditorModule.RegisterCustomClassLayout( + RegisteredLayoutName, + FOnGetDetailCustomizationInstance::CreateStatic( + &FCesium3DTilesetCustomization::MakeInstance)); +} + +void FCesium3DTilesetCustomization::Unregister( + FPropertyEditorModule& PropertyEditorModule) { + PropertyEditorModule.UnregisterCustomClassLayout(RegisteredLayoutName); +} + +TSharedRef FCesium3DTilesetCustomization::MakeInstance() { + return MakeShareable(new FCesium3DTilesetCustomization); +} + +void FCesium3DTilesetCustomization::CustomizeDetails( + IDetailLayoutBuilder& DetailBuilder) { + DetailBuilder.SortCategories(&SortCustomDetailsCategories); +} + +void FCesium3DTilesetCustomization::SortCustomDetailsCategories( + const TMap& AllCategoryMap) { + (*AllCategoryMap.Find(FName("TransformCommon")))->SetSortOrder(0); + (*AllCategoryMap.Find(FName("Cesium")))->SetSortOrder(1); + (*AllCategoryMap.Find(FName("Rendering")))->SetSortOrder(2); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/Cesium3DTilesetCustomization.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/Cesium3DTilesetCustomization.h new file mode 100644 index 0000000..95a8dca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/Cesium3DTilesetCustomization.h @@ -0,0 +1,28 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "IDetailCustomization.h" +#include "PropertyEditorModule.h" + +class IDetailCategoryBuilder; + +/** + * An implementation of the IDetailCustomization interface that customizes + * the Details View of a Cesium3DTileset. It is registered in + * FCesiumEditorModule::StartupModule. + */ +class FCesium3DTilesetCustomization : public IDetailCustomization { +public: + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override; + + static void Register(FPropertyEditorModule& PropertyEditorModule); + static void Unregister(FPropertyEditorModule& PropertyEditorModule); + + static TSharedRef MakeInstance(); + + static void SortCustomDetailsCategories( + const TMap& AllCategoryMap); + + static FName RegisteredLayoutName; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCommands.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCommands.cpp new file mode 100644 index 0000000..a340486 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCommands.cpp @@ -0,0 +1,62 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumCommands.h" +#include "CesiumEditor.h" + +#define LOCTEXT_NAMESPACE "CesiumCommands" + +FCesiumCommands::FCesiumCommands() + : TCommands( + "Cesium.Common", + LOCTEXT("Common", "Common"), + NAME_None, + FCesiumEditorModule::GetStyleSetName()) {} + +void FCesiumCommands::RegisterCommands() { + UI_COMMAND( + AddFromIon, + "Add", + "Add a tileset from Cesium ion to this level", + EUserInterfaceActionType::Button, + FInputChord()); + UI_COMMAND( + UploadToIon, + "Upload", + "Upload a tileset to Cesium ion to process it for efficient streaming to Cesium for Unreal", + EUserInterfaceActionType::Button, + FInputChord()); + UI_COMMAND( + SignOut, + "Sign Out", + "Sign out of Cesium ion", + EUserInterfaceActionType::Button, + FInputChord()); + UI_COMMAND( + OpenDocumentation, + "Learn", + "Open Cesium for Unreal tutorials and learning resources", + EUserInterfaceActionType::Button, + FInputChord()); + UI_COMMAND( + OpenSupport, + "Help", + "Search for existing questions or ask a new question on the Cesium Community Forum", + EUserInterfaceActionType::Button, + FInputChord()); + UI_COMMAND( + OpenTokenSelector, + "Token", + "Select or create a token to use to access Cesium ion assets. " + "Not used for ion servers that don't need token authentication.", + EUserInterfaceActionType::Button, + FInputChord()); + + UI_COMMAND( + OpenCesiumPanel, + "Cesium", + "Open the Cesium panel", + EUserInterfaceActionType::Button, + FInputChord()); +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCommands.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCommands.h new file mode 100644 index 0000000..79f4ea9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCommands.h @@ -0,0 +1,22 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include "Framework/Commands/Commands.h" + +class FCesiumCommands : public TCommands { +public: + FCesiumCommands(); + + TSharedPtr AddFromIon; + TSharedPtr UploadToIon; + TSharedPtr SignOut; + TSharedPtr OpenDocumentation; + TSharedPtr OpenSupport; + TSharedPtr OpenTokenSelector; + + TSharedPtr OpenCesiumPanel; + + virtual void RegisterCommands() override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCustomization.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCustomization.cpp new file mode 100644 index 0000000..5b7371a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCustomization.cpp @@ -0,0 +1,110 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumCustomization.h" +#include "DetailCategoryBuilder.h" +#include "DetailLayoutBuilder.h" +#include "DetailWidgetRow.h" +#include "IDetailGroup.h" +#include "ScopedTransaction.h" +#include "Widgets/Input/SButton.h" +#include "Widgets/Layout/SWrapBox.h" +#include "Widgets/Text/STextBlock.h" + +struct CesiumButtonGroup::Impl { + TSharedPtr Container; + TArray> SelectedObjects; + FTextBuilder ButtonSearchText; +}; + +CesiumButtonGroup::CesiumButtonGroup() : pImpl(MakeUnique()) { + this->pImpl->Container = SNew(SWrapBox).UseAllottedSize(true); +} + +void CesiumButtonGroup::AddButtonForUFunction( + UFunction* Function, + const FText& Label) { + check(Function); + if (!Function) + return; + + FText ButtonCaption = + Label.IsEmpty() + ? FText::FromString( + FName::NameToDisplayString(*Function->GetName(), false)) + : Label; + FText ButtonTooltip = Function->GetToolTipText(); + + this->pImpl->ButtonSearchText.AppendLine(ButtonCaption); + this->pImpl->ButtonSearchText.AppendLine(ButtonTooltip); + + TWeakObjectPtr WeakFunctionPtr = Function; + + pImpl->Container->AddSlot() + .VAlign(EVerticalAlignment::VAlign_Center) + .Padding( + 0.0f, + 3.0f, + 0.0f, + 3.0f)[SNew(SButton) + .Text(ButtonCaption) + .OnClicked_Lambda([WeakFunctionPtr, + ButtonCaption, + Group = this->AsShared()]() { + if (UFunction* Function = WeakFunctionPtr.Get()) { + FScopedTransaction Transaction(ButtonCaption); + FEditorScriptExecutionGuard ScriptGuard; + for (TWeakObjectPtr SelectedObjectPtr : + Group->pImpl->SelectedObjects) { + if (UObject* Object = SelectedObjectPtr.Get()) { + Object->Modify(); + Object->ProcessEvent(Function, nullptr); + } + } + } + return FReply::Handled(); + }) + .ToolTipText(ButtonTooltip)]; +} + +void CesiumButtonGroup::Finish( + IDetailLayoutBuilder& DetailBuilder, + IDetailCategoryBuilder& Category) { + DetailBuilder.GetObjectsBeingCustomized(this->pImpl->SelectedObjects); + Category.AddCustomRow(this->pImpl->ButtonSearchText.ToText()) + .RowTag("Actions")[this->pImpl->Container.ToSharedRef()]; +} + +IDetailGroup& CesiumCustomization::CreateGroup( + IDetailCategoryBuilder& Category, + FName GroupName, + const FText& LocalizedDisplayName, + bool bForAdvanced, + bool bStartExpanded) { + IDetailGroup& Group = Category.AddGroup( + GroupName, + LocalizedDisplayName, + bForAdvanced, + bStartExpanded); + Group.HeaderRow() + .WholeRowContent() + .HAlign(HAlign_Left) + .VAlign(VAlign_Center) + [SNew(SButton) + .ButtonStyle(FAppStyle::Get(), "NoBorder") + .ContentPadding(FMargin(0, 2, 0, 2)) + .OnClicked_Lambda([&Group]() { + Group.ToggleExpansion(!Group.GetExpansionState()); + return FReply::Handled(); + }) + .ForegroundColor(FSlateColor::UseForeground()) + .Content()[SNew(STextBlock) + .Font(IDetailLayoutBuilder::GetDetailFont()) + .Text(LocalizedDisplayName)] + + ]; + return Group; +} + +TSharedPtr CesiumCustomization::CreateButtonGroup() { + return MakeShared(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCustomization.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCustomization.h new file mode 100644 index 0000000..ee3ca89 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCustomization.h @@ -0,0 +1,61 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Internationalization/Text.h" +#include "UObject/NameTypes.h" + +class IDetailCategoryBuilder; +class IDetailGroup; +class IDetailLayoutBuilder; + +class CesiumButtonGroup : public TSharedFromThis { +public: + CesiumButtonGroup(); + + /// + /// Adds a button to this group. When pressed, the button will invoke the + /// provided UFunction. If a name is not specified, the label on the button is + /// derived automatically from the name of the function. + /// + /// + void AddButtonForUFunction( + UFunction* Function, + const FText& Label = FText::GetEmpty()); + + void + Finish(IDetailLayoutBuilder& DetailBuilder, IDetailCategoryBuilder& Category); + +private: + struct Impl; + TUniquePtr pImpl; +}; + +class CesiumCustomization { +public: + /// + /// Adds a new group to the given category. This is equivalent to calling + /// `Category.AddGroup` except that it allows the label to span the entire row + /// rather than confining it to the "name" column for no apparent reason. + /// + /// The category to which to add the group. + /// The name of the group. + /// The display name of the group. + /// True if the group should appear in the advanced + /// section of the category. + /// True if the group should start + /// expanded. + /// The newly-created group. + static IDetailGroup& CreateGroup( + IDetailCategoryBuilder& Category, + FName GroupName, + const FText& LocalizedDisplayName, + bool bForAdvanced = false, + bool bStartExpanded = false); + + /// + /// Creates a new group of action buttons. Be sure to call Finish on the + /// returned instance after the last button has been added. + /// + static TSharedPtr CreateButtonGroup(); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumDegreesMinutesSecondsEditor.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumDegreesMinutesSecondsEditor.cpp new file mode 100644 index 0000000..087e9c0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumDegreesMinutesSecondsEditor.cpp @@ -0,0 +1,310 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumDegreesMinutesSecondsEditor.h" +#include "CesiumEditor.h" + +#include "DetailLayoutBuilder.h" +#include "DetailWidgetRow.h" +#include "Widgets/Input/SSpinBox.h" +#include "Widgets/Input/STextComboBox.h" +#include "Widgets/Text/STextBlock.h" + +#include + +namespace { + +/** + * @brief A structure describing cartographic coordinates in + * the DMS (Degree-Minute-Second) representation. + */ +struct DMS { + + /** + * @brief The degrees. + * + * This is usually a value in [0,90] (for latitude) or + * in [0,180] (for longitude), although explicit + * clamping is not guaranteed. + */ + int32_t d; + + /** + * @brief The minutes. + * + * This is a value in [0,60). + */ + int32_t m; + + /** + * @brief The seconds. + * + * This is a value in [0,60). + */ + double s; + + /** + * @brief Whether the coordinate is negative. + * + * When the coordinate is negative, it represents a latitude south + * of the equator, or a longitude west of the prime meridian. + */ + bool negative; +}; + +/** + * @brief Converts the given decimal degrees to a DMS representation. + * + * @param decimalDegrees The decimal degrees + * @return The DMS representation. + */ +DMS decimalDegreesToDms(double decimalDegrees) { + // Roughly based on + // https://en.wikiversity.org/wiki/Geographic_coordinate_conversion + // Section "Conversion_from_Decimal_Degree_to_DMS" + bool negative = decimalDegrees < 0; + double dd = negative ? -decimalDegrees : decimalDegrees; + double d = glm::floor(dd); + double min = (dd - d) * 60; + double m = glm::floor(min); + double sec = (min - m) * 60; + double s = sec; + if (s >= 60) { + m++; + s -= 60; + } + if (m == 60) { + d++; + m = 0; + } + return DMS{static_cast(d), static_cast(m), s, negative}; +} + +/** + * @brief Converts the given DMS into decimal degrees. + * + * @param dms The DMS + * @return The decimal degrees + */ +double dmsToDecimalDegrees(const DMS& dms) { + double dd = dms.d + (dms.m / 60.0) + (dms.s / 3600.0); + if (dms.negative) { + return -dd; + } + return dd; +} + +} // namespace + +CesiumDegreesMinutesSecondsEditor::CesiumDegreesMinutesSecondsEditor( + TSharedPtr InputDecimalDegreesHandle, + bool InputIsLongitude) { + this->DecimalDegreesHandle = InputDecimalDegreesHandle; + this->IsLongitude = InputIsLongitude; +} + +void CesiumDegreesMinutesSecondsEditor::PopulateRow(IDetailPropertyRow& Row) { + FSlateFontInfo FontInfo = IDetailLayoutBuilder::GetDetailFont(); + + // The default editing component for the property: + // A SpinBox for the decimal degrees + DecimalDegreesSpinBox = + SNew(SSpinBox) + .Font(FontInfo) + .MinSliderValue(IsLongitude ? -180 : -90) + .MaxSliderValue(IsLongitude ? 180 : 90) + .OnValueChanged( + this, + &CesiumDegreesMinutesSecondsEditor::SetDecimalDegreesOnProperty) + .Value( + this, + &CesiumDegreesMinutesSecondsEditor:: + GetDecimalDegreesFromProperty); + + // Editing components for the DMS representation: + // Spin boxes for degrees, minutes and seconds + DegreesSpinBox = + SNew(SSpinBox) + .Font(FontInfo) + .ToolTipText(FText::FromString("Degrees")) + .MinSliderValue(0) + .MaxSliderValue(IsLongitude ? 179 : 89) + .OnValueChanged(this, &CesiumDegreesMinutesSecondsEditor::SetDegrees) + .Value(this, &CesiumDegreesMinutesSecondsEditor::GetDegrees); + + MinutesSpinBox = + SNew(SSpinBox) + .Font(FontInfo) + .ToolTipText(FText::FromString("Minutes")) + .MinSliderValue(0) + .MaxSliderValue(59) + .OnValueChanged(this, &CesiumDegreesMinutesSecondsEditor::SetMinutes) + .Value(this, &CesiumDegreesMinutesSecondsEditor::GetMinutes); + + SecondsSpinBox = + SNew(SSpinBox) + .Font(FontInfo) + .ToolTipText(FText::FromString("Seconds")) + .MinSliderValue(0) + .MaxSliderValue(59.999999) + .OnValueChanged(this, &CesiumDegreesMinutesSecondsEditor::SetSeconds) + .Value(this, &CesiumDegreesMinutesSecondsEditor::GetSeconds); + + // The combo box for selecting "Eeast" or "West", + // or "North" or "South", respectively. + FText signTooltip; + if (IsLongitude) { + PositiveIndicator = MakeShareable(new FString(TEXT("E"))); + NegativeIndicator = MakeShareable(new FString(TEXT("W"))); + signTooltip = FText::FromString("East or West"); + } else { + PositiveIndicator = MakeShareable(new FString(TEXT("N"))); + NegativeIndicator = MakeShareable(new FString(TEXT("S"))); + signTooltip = FText::FromString("North or South"); + } + SignComboBoxItems.Add(NegativeIndicator); + SignComboBoxItems.Emplace(PositiveIndicator); + SignComboBox = SNew(STextComboBox) + .Font(FontInfo) + .ToolTipText(signTooltip) + .OptionsSource(&SignComboBoxItems) + .OnSelectionChanged( + this, + &CesiumDegreesMinutesSecondsEditor::SignChanged); + SignComboBox->SetSelectedItem( + GetDecimalDegreesFromProperty() < 0 ? NegativeIndicator + : PositiveIndicator); + + const float hPad = 3.0; + const float vPad = 2.0; + // clang-format off + Row.CustomWidget().NameContent() + [ + DecimalDegreesHandle->CreatePropertyNameWidget() + ] + .ValueContent().HAlign(EHorizontalAlignment::HAlign_Fill) + [ + SNew( SVerticalBox ) + + SVerticalBox::Slot().Padding(0.0f, vPad) + [ + DecimalDegreesSpinBox.ToSharedRef() + ] + + SVerticalBox::Slot().Padding(0.0f, vPad) + [ + SNew( SHorizontalBox ) + + SHorizontalBox::Slot().FillWidth(1.0) + [ + DegreesSpinBox.ToSharedRef() + ] + + SHorizontalBox::Slot().AutoWidth().Padding(hPad, 0.0f) + [ + // The 'degrees' symbol + SNew(STextBlock) + .Text(FText::FromString(TEXT("\u00B0"))) + .ToolTipText(FText::FromString("Degrees")) + ] + + SHorizontalBox::Slot().FillWidth(1.0) + [ + MinutesSpinBox.ToSharedRef() + ] + + SHorizontalBox::Slot().AutoWidth().Padding(hPad, 0.0f) + [ + // The 'minutes' symbol + SNew(STextBlock) + .Text(FText::FromString(TEXT("\u2032"))) + .ToolTipText(FText::FromString("Minutes")) + ] + + SHorizontalBox::Slot().FillWidth(1.0) + [ + SecondsSpinBox.ToSharedRef() + ] + + SHorizontalBox::Slot().AutoWidth().Padding(hPad, 0.0f) + [ + // The 'seconds' symbol + SNew(STextBlock) + .Text(FText::FromString(TEXT("\u2033"))) + .ToolTipText(FText::FromString("Seconds")) + ] + + SHorizontalBox::Slot().AutoWidth() + [ + SignComboBox.ToSharedRef() + ] + ] + ]; + // clang-format on +} + +double +CesiumDegreesMinutesSecondsEditor::GetDecimalDegreesFromProperty() const { + double decimalDegrees; + FPropertyAccess::Result AccessResult = + DecimalDegreesHandle->GetValue(decimalDegrees); + if (AccessResult == FPropertyAccess::Success) { + return decimalDegrees; + } + + // In theory, this should never happen if the actual property is a double. But + // in practice it gets triggered when saving a level, for some reason. So, we + // ignore it. + return 0.0; +} + +void CesiumDegreesMinutesSecondsEditor::SetDecimalDegreesOnProperty( + double NewValue) { + DecimalDegreesHandle->SetValue(NewValue); + SignComboBox->SetSelectedItem( + NewValue < 0 ? NegativeIndicator : PositiveIndicator); +} + +int32 CesiumDegreesMinutesSecondsEditor::GetDegrees() const { + double decimalDegrees = GetDecimalDegreesFromProperty(); + DMS dms = decimalDegreesToDms(decimalDegrees); + return static_cast(dms.d); +} +void CesiumDegreesMinutesSecondsEditor::SetDegrees(int32 NewValue) { + double decimalDegrees = GetDecimalDegreesFromProperty(); + DMS dms = decimalDegreesToDms(decimalDegrees); + dms.d = NewValue; + double newDecimalDegreesValue = dmsToDecimalDegrees(dms); + SetDecimalDegreesOnProperty(newDecimalDegreesValue); +} + +int32 CesiumDegreesMinutesSecondsEditor::GetMinutes() const { + double decimalDegrees = GetDecimalDegreesFromProperty(); + DMS dms = decimalDegreesToDms(decimalDegrees); + return static_cast(dms.m); +} +void CesiumDegreesMinutesSecondsEditor::SetMinutes(int32 NewValue) { + double decimalDegrees = GetDecimalDegreesFromProperty(); + DMS dms = decimalDegreesToDms(decimalDegrees); + dms.m = NewValue; + double newDecimalDegreesValue = dmsToDecimalDegrees(dms); + SetDecimalDegreesOnProperty(newDecimalDegreesValue); +} + +double CesiumDegreesMinutesSecondsEditor::GetSeconds() const { + double decimalDegrees = GetDecimalDegreesFromProperty(); + DMS dms = decimalDegreesToDms(decimalDegrees); + return dms.s; +} +void CesiumDegreesMinutesSecondsEditor::SetSeconds(double NewValue) { + double decimalDegrees = GetDecimalDegreesFromProperty(); + DMS dms = decimalDegreesToDms(decimalDegrees); + dms.s = NewValue; + double newDecimalDegreesValue = dmsToDecimalDegrees(dms); + SetDecimalDegreesOnProperty(newDecimalDegreesValue); +} + +void CesiumDegreesMinutesSecondsEditor::SignChanged( + TSharedPtr StringItem, + ESelectInfo::Type SelectInfo) { + + bool negative = false; + if (StringItem.IsValid()) { + negative = (StringItem == NegativeIndicator); + } + double decimalDegrees = GetDecimalDegreesFromProperty(); + DMS dms = decimalDegreesToDms(decimalDegrees); + dms.negative = negative; + double newDecimalDegreesValue = dmsToDecimalDegrees(dms); + SetDecimalDegreesOnProperty(newDecimalDegreesValue); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumDegreesMinutesSecondsEditor.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumDegreesMinutesSecondsEditor.h new file mode 100644 index 0000000..2a321ea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumDegreesMinutesSecondsEditor.h @@ -0,0 +1,80 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "IDetailCustomization.h" +#include "IDetailPropertyRow.h" +#include "Types/SlateEnums.h" +#include "Widgets/Input/SSpinBox.h" +#include "Widgets/Input/STextComboBox.h" + +/** + * A class that allows configuring a Details View row for a + * latitude or longitude property. + * + * Latitude and longitude properties are often computed with doubles + * representing decimal-point degrees. This Details View row will show the + * property with an additional Degree-Minutes-Seconds (DMS) view for easier + * usability and editing. + * + * See FCesiumGeoreferenceCustomization::CustomizeDetails for + * an example of how to use this class. + */ +class CesiumDegreesMinutesSecondsEditor + : public TSharedFromThis { + +public: + /** + * Creates a new instance. + * + * The given property handle must be a handle to a 'double' + * property! + * + * @param InputDecimalDegreesHandle The property handle for the + * decimal degrees property + * @param InputIsLongitude Whether the edited property is a + * longitude (as opposed to a latitude) property + */ + CesiumDegreesMinutesSecondsEditor( + TSharedPtr InputDecimalDegreesHandle, + bool InputIsLongitude); + + /** + * Populates the given Details View row with the default + * editor (a SSpinBox for the value), as well as the + * spin boxes and dropdowns for the DMS editing. + * + * @param Row The Details View row + */ + void PopulateRow(IDetailPropertyRow& Row); + +private: + TSharedPtr DecimalDegreesHandle; + bool IsLongitude; + + TSharedPtr> DecimalDegreesSpinBox; + TSharedPtr> DegreesSpinBox; + TSharedPtr> MinutesSpinBox; + TSharedPtr> SecondsSpinBox; + + TSharedPtr NegativeIndicator; + TSharedPtr PositiveIndicator; + + TArray> SignComboBoxItems; + TSharedPtr SignComboBox; + + double GetDecimalDegreesFromProperty() const; + void SetDecimalDegreesOnProperty(double NewValue); + + int32 GetDegrees() const; + void SetDegrees(int32 NewValue); + + int32 GetMinutes() const; + void SetMinutes(int32 NewValue); + + double GetSeconds() const; + void SetSeconds(double NewValue); + + void + SignChanged(TSharedPtr StringItem, ESelectInfo::Type SelectInfo); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditor.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditor.cpp new file mode 100644 index 0000000..807e89c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditor.cpp @@ -0,0 +1,737 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumEditor.h" +#include "Cesium3DTilesSelection/Tileset.h" +#include "Cesium3DTileset.h" +#include "Cesium3DTilesetCustomization.h" +#include "CesiumCartographicPolygon.h" +#include "CesiumCommands.h" +#include "CesiumGeoreferenceCustomization.h" +#include "CesiumGlobeAnchorCustomization.h" +#include "CesiumIonPanel.h" +#include "CesiumIonRasterOverlay.h" +#include "CesiumIonServer.h" +#include "CesiumIonTokenTroubleshooting.h" +#include "CesiumPanel.h" +#include "CesiumRuntime.h" +#include "CesiumSunSky.h" +#include "Editor.h" +#include "Editor/WorkspaceMenuStructure/Public/WorkspaceMenuStructure.h" +#include "Editor/WorkspaceMenuStructure/Public/WorkspaceMenuStructureModule.h" +#include "EngineUtils.h" +#include "Framework/Docking/LayoutExtender.h" +#include "Framework/Docking/TabManager.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "Interfaces/IPluginManager.h" +#include "LevelEditor.h" +#include "PropertyEditorModule.h" +#include "Styling/SlateStyle.h" +#include "Styling/SlateStyleRegistry.h" + +constexpr int MaximumOverlaysWithDefaultMaterial = 3; + +IMPLEMENT_MODULE(FCesiumEditorModule, CesiumEditor) +DEFINE_LOG_CATEGORY(LogCesiumEditor); + +#define IMAGE_BRUSH(RelativePath, ...) \ + FSlateImageBrush( \ + FCesiumEditorModule::InContent(RelativePath, ".png"), \ + __VA_ARGS__) + +#define BOX_BRUSH(RelativePath, ...) \ + FSlateBoxBrush( \ + FCesiumEditorModule::InContent(RelativePath, ".png"), \ + __VA_ARGS__) + +FString FCesiumEditorModule::InContent( + const FString& RelativePath, + const ANSICHAR* Extension) { + static FString ContentDir = IPluginManager::Get() + .FindPlugin(TEXT("CesiumForUnreal")) + ->GetContentDir(); + return (ContentDir / RelativePath) + Extension; +} + +TSharedPtr FCesiumEditorModule::StyleSet = nullptr; +FCesiumEditorModule* FCesiumEditorModule::_pModule = nullptr; + +namespace { + +AActor* SpawnActorWithClass(UClass* actorClass); + +/** + * Register an icon in the StyleSet, using the given property + * name and relative resource path. + * + * This will register the icon once with a default size of + * 40x40, and once under the same name, extended by the + * suffix `".Small"`, with a size of 20x20, which will be + * used when the "useSmallToolbarIcons" editor preference + * was enabled. + * + * @param styleSet The style set + * @param The property name + * @param The resource path + */ +void registerIcon( + TSharedPtr& styleSet, + const FString& propertyName, + const FString& relativePath) { + const FVector2D Icon40x40(40.0f, 40.0f); + const FVector2D Icon20x20(20.0f, 20.0f); + styleSet->Set(FName(propertyName), new IMAGE_BRUSH(relativePath, Icon40x40)); + styleSet->Set( + FName(propertyName + ".Small"), + new IMAGE_BRUSH(relativePath, Icon20x20)); +} +/** + * Create a slate box brush that can be used as the + * normal-, hovered-, or pressed-brush for a button, + * based on a resource with the given name, that + * contains a slate box image with a margin of 4 pixels. + * + * @param name The name of the image (without extension, PNG is assumed) + * @param color The color used for "dyeing" the image + * @return The box brush + */ +FSlateBoxBrush +createButtonBoxBrush(const FString& name, const FLinearColor& color) { + return BOX_BRUSH(name, FMargin(4 / 16.0f), color); +} + +} // namespace + +namespace { + +/** + * Registers our details panel customizations with the property editor. + */ +void registerDetailCustomization() { + FPropertyEditorModule& PropertyEditorModule = + FModuleManager::LoadModuleChecked( + "PropertyEditor"); + + FCesiumGeoreferenceCustomization::Register(PropertyEditorModule); + FCesiumGlobeAnchorCustomization::Register(PropertyEditorModule); + FCesium3DTilesetCustomization::Register(PropertyEditorModule); + + PropertyEditorModule.NotifyCustomizationModuleChanged(); +} + +/** + * Undo the registration that was done in `registerDetailCustomization` + */ +void unregisterDetailCustomization() { + if (FModuleManager::Get().IsModuleLoaded("PropertyEditor")) { + FPropertyEditorModule& PropertyEditorModule = + FModuleManager::LoadModuleChecked( + "PropertyEditor"); + + FCesiumGeoreferenceCustomization::Unregister(PropertyEditorModule); + FCesiumGlobeAnchorCustomization::Unregister(PropertyEditorModule); + FCesium3DTilesetCustomization::Unregister(PropertyEditorModule); + } +} + +} // namespace + +namespace { + +/** + * @brief Populate the given StyleSet with the Cesium icons and fonts. + * + * @param StyleSet The StyleSet + */ +void populateCesiumStyleSet(TSharedPtr& StyleSet) { + if (!StyleSet.IsValid()) { + return; + } + const FVector2D Icon16x16(16.0f, 16.0f); + const FVector2D Icon40x40(40.0f, 40.0f); + const FVector2D Icon64x64(64.0f, 64.0f); + + StyleSet->Set( + "Cesium.MenuIcon", + new IMAGE_BRUSH(TEXT("Cesium-icon-16x16"), Icon16x16)); + + // Give Cesium Actors a Cesium icon in the editor + StyleSet->Set( + "ClassIcon.Cesium3DTileset", + new IMAGE_BRUSH(TEXT("Cesium-icon-16x16"), Icon16x16)); + StyleSet->Set( + "ClassThumbnail.Cesium3DTileset", + new IMAGE_BRUSH(TEXT("Cesium-64x64"), Icon64x64)); + StyleSet->Set( + "ClassIcon.CesiumGeoreference", + new IMAGE_BRUSH(TEXT("Cesium-icon-16x16"), Icon16x16)); + StyleSet->Set( + "ClassThumbnail.CesiumGeoreference", + new IMAGE_BRUSH(TEXT("Cesium-64x64"), Icon64x64)); + + // Icons for the toolbar. These will be registered with + // a default size, and a ".Small" suffix for the case + // that the useSmallToolbarIcons preference is enabled + registerIcon(StyleSet, "Cesium.Common.AddFromIon", "FontAwesome/plus-solid"); + registerIcon( + StyleSet, + "Cesium.Common.UploadToIon", + "FontAwesome/cloud-upload-alt-solid"); + registerIcon( + StyleSet, + "Cesium.Common.SignOut", + "FontAwesome/sign-out-alt-solid"); + registerIcon( + StyleSet, + "Cesium.Common.OpenDocumentation", + "FontAwesome/book-reader-solid"); + registerIcon( + StyleSet, + "Cesium.Common.OpenSupport", + "FontAwesome/hands-helping-solid"); + registerIcon( + StyleSet, + "Cesium.Common.OpenTokenSelector", + "FontAwesome/key-solid"); + + StyleSet->Set( + "Cesium.Common.GreenTick", + new IMAGE_BRUSH(TEXT("FontAwesome/check-solid"), Icon16x16)); + StyleSet->Set( + "Cesium.Common.RedX", + new IMAGE_BRUSH(TEXT("FontAwesome/times-solid"), Icon16x16)); + + registerIcon(StyleSet, "Cesium.Common.OpenCesiumPanel", "Cesium-64x64"); + + StyleSet->Set( + "Cesium.Common.Refresh", + new IMAGE_BRUSH(TEXT("FontAwesome/sync-alt-solid"), Icon16x16)); + + StyleSet->Set( + "Cesium.Logo", + new IMAGE_BRUSH( + "Cesium_for_Unreal_light_color_vertical-height150", + FVector2D(184.0f, 150.0f))); + + StyleSet->Set( + "WelcomeText", + FTextBlockStyle() + .SetColorAndOpacity(FSlateColor::UseForeground()) + .SetFont(FCoreStyle::GetDefaultFontStyle("Regular", 14))); + + StyleSet->Set( + "Heading", + FTextBlockStyle() + .SetColorAndOpacity(FSlateColor::UseForeground()) + .SetFont(FCoreStyle::GetDefaultFontStyle("Regular", 12))); + + StyleSet->Set( + "BodyBold", + FTextBlockStyle() + .SetColorAndOpacity(FSlateColor::UseForeground()) + .SetFont(FCoreStyle::GetDefaultFontStyle("Bold", 9))); + + StyleSet->Set( + "AssetDetailsFieldHeader", + FTextBlockStyle() + .SetColorAndOpacity(FSlateColor::UseForeground()) + .SetFont(FCoreStyle::GetDefaultFontStyle("Regular", 11))); + + StyleSet->Set( + "AssetDetailsFieldValue", + FTextBlockStyle() + .SetColorAndOpacity(FSlateColor::UseForeground()) + .SetFont(FCoreStyle::GetDefaultFontStyle("Regular", 9))); + + const FLinearColor CesiumButtonLighter(0.16863f, 0.52941f, 0.76863f, 1.0f); + const FLinearColor CesiumButton(0.07059f, 0.35686f, 0.59216f, 1.0f); + const FLinearColor CesiumButtonDarker(0.05490f, 0.29412f, 0.45882f, 1.0f); + const FButtonStyle CesiumButtonStyle = + FButtonStyle() + .SetNormalPadding(FMargin(10, 5, 10, 5)) + .SetPressedPadding(FMargin(10, 5, 10, 5)) + .SetNormal(createButtonBoxBrush("CesiumButton", CesiumButton)) + .SetHovered(createButtonBoxBrush("CesiumButton", CesiumButtonLighter)) + .SetPressed(createButtonBoxBrush("CesiumButton", CesiumButtonDarker)); + StyleSet->Set("CesiumButton", CesiumButtonStyle); + + const FTextBlockStyle CesiumButtonTextStyle = + FTextBlockStyle() + .SetColorAndOpacity(FLinearColor(1.0f, 1.0f, 1.0f, 1.0f)) + .SetFont(FCoreStyle::GetDefaultFontStyle("Bold", 12)); + StyleSet->Set("CesiumButtonText", CesiumButtonTextStyle); +} +} // namespace + +void FCesiumEditorModule::StartupModule() { + _pModule = this; + + IModuleInterface::StartupModule(); + + registerDetailCustomization(); + + this->_serverManager.Initialize(); + + // Only register style once + if (!StyleSet.IsValid()) { + + StyleSet = MakeShareable(new FSlateStyleSet("CesiumStyleSet")); + populateCesiumStyleSet(StyleSet); + FSlateStyleRegistry::RegisterSlateStyle(*StyleSet.Get()); + } + + FCesiumCommands::Register(); + + FGlobalTabmanager::Get() + ->RegisterNomadTabSpawner( + TEXT("Cesium"), + FOnSpawnTab::CreateRaw(this, &FCesiumEditorModule::SpawnCesiumTab)) + .SetGroup(WorkspaceMenu::GetMenuStructure().GetLevelEditorCategory()) + .SetDisplayName(FText::FromString(TEXT("Cesium"))) + .SetTooltipText(FText::FromString(TEXT("Cesium"))) + .SetIcon(FSlateIcon(TEXT("CesiumStyleSet"), TEXT("Cesium.MenuIcon"))); + + FGlobalTabmanager::Get() + ->RegisterNomadTabSpawner( + TEXT("CesiumIon"), + FOnSpawnTab::CreateRaw( + this, + &FCesiumEditorModule::SpawnCesiumIonAssetBrowserTab)) + .SetGroup(WorkspaceMenu::GetMenuStructure().GetLevelEditorCategory()) + .SetDisplayName(FText::FromString(TEXT("Cesium ion Assets"))) + .SetTooltipText(FText::FromString(TEXT("Cesium ion Assets"))) + .SetIcon(FSlateIcon(TEXT("CesiumStyleSet"), TEXT("Cesium.MenuIcon"))); + + FLevelEditorModule* pLevelEditorModule = + FModuleManager::GetModulePtr( + FName(TEXT("LevelEditor"))); + if (pLevelEditorModule) { + pLevelEditorModule->OnRegisterLayoutExtensions().AddLambda( + [](FLayoutExtender& extender) { + extender.ExtendLayout( + FTabId("PlacementBrowser"), + ELayoutExtensionPosition::After, + FTabManager::FTab(FName("Cesium"), ETabState::OpenedTab)); + extender.ExtendLayout( + FTabId("OutputLog"), + ELayoutExtensionPosition::Before, + FTabManager::FTab(FName("CesiumIon"), ETabState::ClosedTab)); + }); + + TSharedRef toolbarCommandList = + MakeShared(); + + toolbarCommandList->MapAction( + FCesiumCommands::Get().OpenCesiumPanel, + FExecuteAction::CreateLambda([]() { + FLevelEditorModule* pLevelEditorModule = + FModuleManager::GetModulePtr( + FName(TEXT("LevelEditor"))); + TSharedPtr pTabManager = + pLevelEditorModule + ? pLevelEditorModule->GetLevelEditorTabManager() + : FGlobalTabmanager::Get(); + pTabManager->TryInvokeTab(FTabId(TEXT("Cesium"))); + })); + + TSharedPtr pToolbarExtender = MakeShared(); + pToolbarExtender->AddToolBarExtension( + "Settings", + EExtensionHook::After, + toolbarCommandList, + FToolBarExtensionDelegate::CreateLambda([](FToolBarBuilder& builder) { + builder.BeginSection("Cesium"); + builder.AddToolBarButton(FCesiumCommands::Get().OpenCesiumPanel); + builder.EndSection(); + })); + pLevelEditorModule->GetToolBarExtensibilityManager()->AddExtender( + pToolbarExtender); + } + + this->_tilesetLoadFailureSubscription = OnCesium3DTilesetLoadFailure.AddRaw( + this, + &FCesiumEditorModule::OnTilesetLoadFailure); + this->_rasterOverlayLoadFailureSubscription = + OnCesiumRasterOverlayLoadFailure.AddRaw( + this, + &FCesiumEditorModule::OnRasterOverlayLoadFailure); + + this->_tilesetIonTroubleshootingSubscription = + OnCesium3DTilesetIonTroubleshooting.AddRaw( + this, + &FCesiumEditorModule::OnTilesetIonTroubleshooting); + this->_rasterOverlayIonTroubleshootingSubscription = + OnCesiumRasterOverlayIonTroubleshooting.AddRaw( + this, + &FCesiumEditorModule::OnRasterOverlayIonTroubleshooting); +} + +void FCesiumEditorModule::ShutdownModule() { + if (this->_tilesetLoadFailureSubscription.IsValid()) { + OnCesium3DTilesetLoadFailure.Remove(this->_tilesetLoadFailureSubscription); + this->_tilesetLoadFailureSubscription.Reset(); + } + if (this->_rasterOverlayLoadFailureSubscription.IsValid()) { + OnCesiumRasterOverlayLoadFailure.Remove( + this->_rasterOverlayLoadFailureSubscription); + this->_rasterOverlayLoadFailureSubscription.Reset(); + } + if (this->_tilesetIonTroubleshootingSubscription.IsValid()) { + OnCesium3DTilesetIonTroubleshooting.Remove( + this->_tilesetIonTroubleshootingSubscription); + this->_tilesetIonTroubleshootingSubscription.Reset(); + } + if (this->_rasterOverlayIonTroubleshootingSubscription.IsValid()) { + OnCesiumRasterOverlayIonTroubleshooting.Remove( + this->_rasterOverlayIonTroubleshootingSubscription); + this->_rasterOverlayIonTroubleshootingSubscription.Reset(); + } + FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(TEXT("Cesium")); + FCesiumCommands::Unregister(); + IModuleInterface::ShutdownModule(); + unregisterDetailCustomization(); + _pModule = nullptr; +} + +TSharedRef +FCesiumEditorModule::SpawnCesiumTab(const FSpawnTabArgs& TabSpawnArgs) { + TSharedRef SpawnedTab = + SNew(SDockTab).TabRole(ETabRole::NomadTab)[SNew(CesiumPanel)]; + + return SpawnedTab; +} + +TSharedRef FCesiumEditorModule::SpawnCesiumIonAssetBrowserTab( + const FSpawnTabArgs& TabSpawnArgs) { + TSharedRef SpawnedTab = + SNew(SDockTab).TabRole(ETabRole::NomadTab)[SNew(CesiumIonPanel)]; + + return SpawnedTab; +} + +void FCesiumEditorModule::OnTilesetLoadFailure( + const FCesium3DTilesetLoadFailureDetails& details) { + if (!details.Tileset.IsValid()) { + return; + } + + // Don't pop a troubleshooting panel over a game world (including + // Play-In-Editor). + if (details.Tileset->GetWorld()->IsGameWorld()) { + return; + } + + FLevelEditorModule* pLevelEditorModule = + FModuleManager::GetModulePtr( + FName(TEXT("LevelEditor"))); + if (pLevelEditorModule) { + pLevelEditorModule->GetLevelEditorTabManager()->TryInvokeTab( + FTabId("OutputLog")); + } + + // Check for a 401 connecting to Cesium ion, which means the token is invalid + // (or perhaps the asset ID is). Also check for a 404, because ion returns 404 + // when the token is valid but not authorized for the asset. + if (details.Type == ECesium3DTilesetLoadType::CesiumIon && + (details.HttpStatusCode == 401 || details.HttpStatusCode == 404)) { + CesiumIonTokenTroubleshooting::Open(details.Tileset.Get(), true); + } +} + +void FCesiumEditorModule::OnRasterOverlayLoadFailure( + const FCesiumRasterOverlayLoadFailureDetails& details) { + if (!details.Overlay.IsValid()) { + return; + } + + // Don't pop a troubleshooting panel over a game world (including + // Play-In-Editor). + if (details.Overlay->GetWorld()->IsGameWorld()) { + return; + } + + FLevelEditorModule* pLevelEditorModule = + FModuleManager::GetModulePtr( + FName(TEXT("LevelEditor"))); + if (pLevelEditorModule) { + pLevelEditorModule->GetLevelEditorTabManager()->TryInvokeTab( + FTabId("OutputLog")); + } + + // Check for a 401 connecting to Cesium ion, which means the token is invalid + // (or perhaps the asset ID is). Also check for a 404, because ion returns 404 + // when the token is valid but not authorized for the asset. + if (details.Type == ECesiumRasterOverlayLoadType::CesiumIon && + (details.HttpStatusCode == 401 || details.HttpStatusCode == 404)) { + CesiumIonTokenTroubleshooting::Open(details.Overlay.Get(), true); + } +} + +void FCesiumEditorModule::OnTilesetIonTroubleshooting( + ACesium3DTileset* pTileset) { + CesiumIonTokenTroubleshooting::Open(pTileset, false); +} + +void FCesiumEditorModule::OnRasterOverlayIonTroubleshooting( + UCesiumRasterOverlay* pOverlay) { + CesiumIonTokenTroubleshooting::Open(pOverlay, false); +} + +TSharedPtr FCesiumEditorModule::GetStyle() { return StyleSet; } + +const FName& FCesiumEditorModule::GetStyleSetName() { + return StyleSet->GetStyleSetName(); +} + +ACesium3DTileset* FCesiumEditorModule::FindFirstTilesetSupportingOverlays() { + UWorld* pCurrentWorld = GEditor->GetEditorWorldContext().World(); + ULevel* pCurrentLevel = pCurrentWorld->GetCurrentLevel(); + + for (TActorIterator it(pCurrentWorld); it; ++it) { + const Cesium3DTilesSelection::Tileset* pTileset = it->GetTileset(); + if (pTileset) { + return *it; + } + } + + return nullptr; +} + +ACesium3DTileset* +FCesiumEditorModule::FindFirstTilesetWithAssetID(int64_t assetID) { + UWorld* pCurrentWorld = GEditor->GetEditorWorldContext().World(); + ULevel* pCurrentLevel = pCurrentWorld->GetCurrentLevel(); + + ACesium3DTileset* pTilesetActor = nullptr; + + for (TActorIterator it(pCurrentWorld); !pTilesetActor && it; + ++it) { + ACesium3DTileset* pActor = *it; + + // The existing Actor must be in the current level. Because it's sometimes + // useful to add the same tileset to multiple sub-levels. + if (!IsValid(pActor) || pActor->GetLevel() != pCurrentLevel) + continue; + + const Cesium3DTilesSelection::Tileset* pTileset = it->GetTileset(); + if (pTileset && it->GetIonAssetID() == assetID) { + return *it; + } + } + + return nullptr; +} + +ACesium3DTileset* +FCesiumEditorModule::CreateTileset(const std::string& name, int64_t assetID) { + AActor* pNewActor = SpawnActorWithClass(ACesium3DTileset::StaticClass()); + ACesium3DTileset* pTilesetActor = Cast(pNewActor); + if (pTilesetActor) { + pTilesetActor->SetActorLabel(UTF8_TO_TCHAR(name.c_str())); + if (assetID != -1) { + pTilesetActor->SetIonAssetID(assetID); + } + } + return pTilesetActor; +} + +UCesiumIonRasterOverlay* FCesiumEditorModule::AddOverlay( + ACesium3DTileset* pTilesetActor, + const std::string& name, + int64_t assetID) { + // Remove an existing component with the same name but different types. + // This is necessary because UE will die immediately if we create two + // components with the same name. + FName newName = FName(name.c_str()); + UObject* pExisting = static_cast( + FindObjectWithOuter(pTilesetActor, nullptr, newName)); + if (pExisting) { + UCesiumRasterOverlay* pCesiumOverlay = + Cast(pExisting); + if (pCesiumOverlay) { + pCesiumOverlay->DestroyComponent(); + } else { + // There's some object using our name, but it's not ours. + // We could do complicated things here, but this should be a very uncommon + // scenario so let's just log. + UE_LOG( + LogCesiumEditor, + Warning, + TEXT( + "Cannot create raster overlay component %s because the name is already in use."), + *newName.ToString()); + } + } + + // Find the first available `OverlayN` MaterialLayerKey. + TArray rasterOverlays; + pTilesetActor->GetComponents(rasterOverlays); + + FString overlayKey = TEXT("Overlay0"); + auto materialLayerKeyMatches = [&newName, + &overlayKey](UCesiumRasterOverlay* pOverlay) { + return pOverlay->MaterialLayerKey == overlayKey; + }; + + int i = 0; + while (rasterOverlays.FindByPredicate(materialLayerKeyMatches)) { + ++i; + overlayKey = FString(TEXT("Overlay")) + FString::FromInt(i); + } + + UCesiumIonRasterOverlay* pOverlay = NewObject( + pTilesetActor, + FName(name.c_str()), + RF_Transactional); + pOverlay->MaterialLayerKey = overlayKey; + pOverlay->IonAssetID = assetID; + pOverlay->SetActive(true); + pOverlay->OnComponentCreated(); + + pTilesetActor->AddInstanceComponent(pOverlay); + + if (i >= MaximumOverlaysWithDefaultMaterial) { + UE_LOG( + LogCesiumEditor, + Warning, + TEXT( + "The default material only supports up to %d raster overlays, and your tileset is now using %d, so the extra overlays will be ignored. Consider creating a custom Material Instance with support for more overlays."), + MaximumOverlaysWithDefaultMaterial, + i + 1); + } + + return pOverlay; +} + +UCesiumIonRasterOverlay* FCesiumEditorModule::AddBaseOverlay( + ACesium3DTileset* pTilesetActor, + const std::string& name, + int64_t assetID) { + // Remove Overlay0 (if it exists) and add the new one. + TArray rasterOverlays; + pTilesetActor->GetComponents(rasterOverlays); + + for (UCesiumRasterOverlay* pOverlay : rasterOverlays) { + if (pOverlay->MaterialLayerKey == TEXT("Overlay0")) { + pOverlay->DestroyComponent(false); + } + } + + return FCesiumEditorModule::AddOverlay(pTilesetActor, name, assetID); +} + +namespace { +AActor* GetFirstCurrentLevelActorWithClass(UClass* pActorClass) { + UWorld* pCurrentWorld = GEditor->GetEditorWorldContext().World(); + ULevel* pCurrentLevel = pCurrentWorld->GetCurrentLevel(); + for (TActorIterator it(pCurrentWorld); it; ++it) { + if (it->GetClass() == pActorClass && it->GetLevel() == pCurrentLevel) { + return *it; + } + } + return nullptr; +} + +/** + * Returns whether the current level of the edited world contains + * any actor with the given class. + * + * @param actorClass The expected class + * @return Whether such an actor could be found + */ +bool CurrentLevelContainsActorWithClass(UClass* pActorClass) { + return GetFirstCurrentLevelActorWithClass(pActorClass) != nullptr; +} +/** + * Tries to spawn an actor with the given class, with all + * default parameters, in the current level of the edited world. + * + * @param actorClass The class + * @return The resulting actor, or `nullptr` if the actor + * could not be spawned. + */ +AActor* SpawnActorWithClass(UClass* actorClass) { + if (!actorClass) { + return nullptr; + } + + UWorld* pCurrentWorld = GEditor->GetEditorWorldContext().World(); + ULevel* pCurrentLevel = pCurrentWorld->GetCurrentLevel(); + + ACesiumGeoreference* Georeference = + ACesiumGeoreference::GetDefaultGeoreference(pCurrentWorld); + + // Spawn the new Actor with the same world transform as the + // CesiumGeoreference. This way it will match the existing globe. The user may + // transform it from there (e.g., to offset one tileset from another). + + // When we're spawning this Actor in a sub-level, the transform specified here + // is a world transform relative to the _persistent level_. It's not relative + // to the sub-level's origin. Strange but true! But it's helpful in this case + // because we're able to correctly spawn things like tilesets into sub-levels + // where the sub-level origin and the persistent-level origin don't coincide + // due to a LevelTransform. + + AActor* NewActor = GEditor->AddActor( + pCurrentLevel, + actorClass, + Georeference->GetActorTransform(), + false, + RF_Transactional); + + // Make the new Actor a child of the CesiumGeoreference. Unless they're in + // different levels. + if (Georeference->GetLevel() == pCurrentLevel) { + NewActor->AttachToActor( + Georeference, + FAttachmentTransformRules::KeepWorldTransform); + } + + return NewActor; +} +} // namespace + +AActor* FCesiumEditorModule::GetCurrentLevelCesiumSunSky() { + return GetFirstCurrentLevelActorWithClass(GetCesiumSunSkyClass()); +} + +AActor* FCesiumEditorModule::GetCurrentLevelDynamicPawn() { + return GetFirstCurrentLevelActorWithClass(GetDynamicPawnBlueprintClass()); +} + +AActor* FCesiumEditorModule::SpawnCesiumSunSky() { + return SpawnActorWithClass(GetCesiumSunSkyClass()); +} + +AActor* FCesiumEditorModule::SpawnDynamicPawn() { + return SpawnActorWithClass(GetDynamicPawnBlueprintClass()); +} + +UClass* FCesiumEditorModule::GetCesiumSunSkyClass() { + return ACesiumSunSky::StaticClass(); +} + +AActor* FCesiumEditorModule::SpawnBlankTileset() { + return SpawnActorWithClass(ACesium3DTileset::StaticClass()); +} + +AActor* FCesiumEditorModule::SpawnCartographicPolygon() { + return SpawnActorWithClass(ACesiumCartographicPolygon::StaticClass()); +} + +UClass* FCesiumEditorModule::GetDynamicPawnBlueprintClass() { + static UClass* pResult = nullptr; + + if (!pResult) { + pResult = LoadClass( + nullptr, + TEXT("/CesiumForUnreal/DynamicPawn.DynamicPawn_C")); + if (!pResult) { + UE_LOG( + LogCesiumEditor, + Warning, + TEXT("Could not load /CesiumForUnreal/DynamicPawn.DynamicPawn_C")); + } + } + + return pResult; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditor.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditor.h new file mode 100644 index 0000000..2eabd16 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditor.h @@ -0,0 +1,137 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumEditorReparentHandler.h" +#include "CesiumEditorSubLevelMutex.h" +#include "CesiumIonServerManager.h" +#include "CesiumIonSession.h" +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" +#include "Styling/SlateStyle.h" +#include "Widgets/Docking/SDockTab.h" +#include + +class FSpawnTabArgs; +class ACesium3DTileset; +class UCesiumRasterOverlay; +class UCesiumIonRasterOverlay; +struct FCesium3DTilesetLoadFailureDetails; +struct FCesiumRasterOverlayLoadFailureDetails; +class UCesiumIonServer; + +DECLARE_LOG_CATEGORY_EXTERN(LogCesiumEditor, Log, All); + +class FCesiumEditorModule : public IModuleInterface { +public: + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; + + static FString + InContent(const FString& RelativePath, const ANSICHAR* Extension); + + static TSharedPtr GetStyle(); + static const FName& GetStyleSetName(); + + static FCesiumEditorModule* get() { return _pModule; } + + static CesiumIonServerManager& serverManager() { + assert(_pModule); + return get()->_serverManager; + } + + static ACesium3DTileset* FindFirstTilesetSupportingOverlays(); + static ACesium3DTileset* FindFirstTilesetWithAssetID(int64_t assetID); + static ACesium3DTileset* + CreateTileset(const std::string& name, int64_t assetID); + + /** + * Adds an overlay with the the MaterialLayerKey `OverlayN` where N is the + * next unused index. + */ + static UCesiumIonRasterOverlay* AddOverlay( + ACesium3DTileset* pTilesetActor, + const std::string& name, + int64_t assetID); + + /** + * Adds a base overlay, replacing the existing overlay with MaterialLayerKey + * Overlay0, if any. + */ + static UCesiumIonRasterOverlay* AddBaseOverlay( + ACesium3DTileset* pTilesetActor, + const std::string& name, + int64_t assetID); + + /** + * Gets the first CesiumSunSky in the current level if there is one, or + * nullptr if there is not. + */ + static AActor* GetCurrentLevelCesiumSunSky(); + + /** + * Gets the first DynamicPawn in the current level if there is one, or + * nullptr if there is not. + */ + static AActor* GetCurrentLevelDynamicPawn(); + + /** + * Spawns a new actor with the _cesiumSunSkyBlueprintClass + * in the current level of the edited world. + */ + static AActor* SpawnCesiumSunSky(); + + /** + * Spawns a new actor with the _dynamicPawnBlueprintClass + * in the current level of the edited world. + */ + static AActor* SpawnDynamicPawn(); + + /** + * Spawns a new Cesium3DTileset with default values in the current level of + * the edited world. + */ + static AActor* SpawnBlankTileset(); + + /** + * Spawns a new CesiumCartographicPolygon in the current level of the edited + * world. + */ + static AActor* SpawnCartographicPolygon(); + +private: + TSharedRef SpawnCesiumTab(const FSpawnTabArgs& TabSpawnArgs); + TSharedRef + SpawnCesiumIonAssetBrowserTab(const FSpawnTabArgs& TabSpawnArgs); + + void OnTilesetLoadFailure(const FCesium3DTilesetLoadFailureDetails& details); + void OnRasterOverlayLoadFailure( + const FCesiumRasterOverlayLoadFailureDetails& details); + void OnTilesetIonTroubleshooting(ACesium3DTileset* pTileset); + void OnRasterOverlayIonTroubleshooting(UCesiumRasterOverlay* pOverlay); + + CesiumIonServerManager _serverManager; + FDelegateHandle _tilesetLoadFailureSubscription; + FDelegateHandle _rasterOverlayLoadFailureSubscription; + FDelegateHandle _tilesetIonTroubleshootingSubscription; + FDelegateHandle _rasterOverlayIonTroubleshootingSubscription; + + CesiumEditorSubLevelMutex _subLevelMutex; + CesiumEditorReparentHandler _reparentHandler; + + static TSharedPtr StyleSet; + static FCesiumEditorModule* _pModule; + + /** + * Gets the class of the "Cesium Sun Sky", loading it if necessary. + * Used for spawning the CesiumSunSky. + */ + static UClass* GetCesiumSunSkyClass(); + + /** + * Gets the class of the "Dynamic Pawn" blueprint, loading it if necessary. + * Used for spawning the DynamicPawn. + */ + static UClass* GetDynamicPawnBlueprintClass(); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorReparentHandler.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorReparentHandler.cpp new file mode 100644 index 0000000..398e53e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorReparentHandler.cpp @@ -0,0 +1,43 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumEditorReparentHandler.h" +#include "Cesium3DTileset.h" +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumSubLevelComponent.h" +#include "Engine/Engine.h" + +CesiumEditorReparentHandler::CesiumEditorReparentHandler() { + if (GEngine) { + this->_subscription = GEngine->OnLevelActorAttached().AddRaw( + this, + &CesiumEditorReparentHandler::OnLevelActorAttached); + } +} + +CesiumEditorReparentHandler::~CesiumEditorReparentHandler() { + if (GEngine) { + GEngine->OnLevelActorAttached().Remove(this->_subscription); + this->_subscription.Reset(); + } +} + +void CesiumEditorReparentHandler::OnLevelActorAttached( + AActor* Actor, + const AActor* Parent) { + ACesium3DTileset* Tileset = Cast(Actor); + if (IsValid(Tileset)) { + Tileset->InvalidateResolvedGeoreference(); + } + + UCesiumGlobeAnchorComponent* GlobeAnchor = + Actor->FindComponentByClass(); + if (IsValid(GlobeAnchor)) { + GlobeAnchor->ResolveGeoreference(true); + } + + UCesiumSubLevelComponent* SubLevel = + Actor->FindComponentByClass(); + if (IsValid(SubLevel)) { + SubLevel->ResolveGeoreference(true); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorReparentHandler.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorReparentHandler.h new file mode 100644 index 0000000..196ee3e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorReparentHandler.h @@ -0,0 +1,24 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Delegates/IDelegateInstance.h" + +class AActor; + +/** + * Detects when Actors are reparented in the Editor by subscribing to + * GEngine::OnLevelActorAttached and handling it appropriately. For example, + * when a Cesium3DTileset's parent changes, we need to re-resolve its + * CesiumGeoreference. + */ +class CesiumEditorReparentHandler { +public: + CesiumEditorReparentHandler(); + ~CesiumEditorReparentHandler(); + +private: + void OnLevelActorAttached(AActor* Actor, const AActor* Parent); + + FDelegateHandle _subscription; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSettings.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSettings.cpp new file mode 100644 index 0000000..3b4b73d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSettings.cpp @@ -0,0 +1,15 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumEditorSettings.h" +#include "CesiumSourceControl.h" + +UCesiumEditorSettings::UCesiumEditorSettings( + const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) {} + +void UCesiumEditorSettings::Save() { + CesiumSourceControl::PromptToCheckoutConfigFile( + this->GetClass()->GetConfigName()); + this->Modify(); + this->SaveConfig(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSettings.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSettings.h new file mode 100644 index 0000000..0f1ffdf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSettings.h @@ -0,0 +1,43 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumIonServer.h" +#include "CoreMinimal.h" +#include "Engine/DeveloperSettings.h" +#include "CesiumEditorSettings.generated.h" + +/** + * Stores Editor settings for the Cesium plugin. + */ +UCLASS(Config = EditorPerProjectUserSettings, meta = (DisplayName = "Cesium")) +class UCesiumEditorSettings : public UDeveloperSettings { + GENERATED_UCLASS_BODY() + +public: + UPROPERTY( + Config, + meta = + (DeprecatedProperty, + DeprecationMessage = "Set UserAccessTokenMap instead.")) + FString UserAccessToken_DEPRECATED; + + /** + * The Cesium ion server that is currently selected in the user interface. + */ + UPROPERTY( + Config, + EditAnywhere, + Category = "Cesium ion", + meta = (DisplayName = "Current Cesium ion Server")) + TSoftObjectPtr CurrentCesiumIonServer; + + UPROPERTY( + Config, + EditAnywhere, + Category = "Cesium ion", + meta = (DisplayName = "Token Map")) + TMap, FString> UserAccessTokenMap; + + void Save(); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSubLevelMutex.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSubLevelMutex.cpp new file mode 100644 index 0000000..1bc709a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSubLevelMutex.cpp @@ -0,0 +1,70 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumEditorSubLevelMutex.h" +#include "Async/Async.h" +#include "CesiumGeoreference.h" +#include "CesiumSubLevelComponent.h" +#include "CesiumSubLevelSwitcherComponent.h" +#include "Components/ActorComponent.h" +#include "Engine/World.h" +#include "LevelInstance/LevelInstanceActor.h" + +CesiumEditorSubLevelMutex::CesiumEditorSubLevelMutex() { + this->_subscription = UActorComponent::MarkRenderStateDirtyEvent.AddRaw( + this, + &CesiumEditorSubLevelMutex::OnMarkRenderStateDirty); +} + +CesiumEditorSubLevelMutex::~CesiumEditorSubLevelMutex() { + UActorComponent::MarkRenderStateDirtyEvent.Remove(this->_subscription); + this->_subscription.Reset(); +} + +void CesiumEditorSubLevelMutex::OnMarkRenderStateDirty( + UActorComponent& component) { + UCesiumSubLevelComponent* pSubLevel = + Cast(&component); + if (pSubLevel == nullptr) + return; + + ALevelInstance* pLevelInstance = Cast(pSubLevel->GetOwner()); + if (pLevelInstance == nullptr) + return; + + ACesiumGeoreference* pGeoreference = pSubLevel->GetResolvedGeoreference(); + if (pGeoreference == nullptr) + return; + + UCesiumSubLevelSwitcherComponent* pSwitcher = + pGeoreference->FindComponentByClass(); + if (pSwitcher == nullptr) + return; + + bool needsTick = false; + + if (!pLevelInstance->IsTemporarilyHiddenInEditor(true)) { + pSwitcher->SetTargetSubLevel(pLevelInstance); + needsTick = true; + } else if (pSwitcher->GetTargetSubLevel() == pLevelInstance) { + pSwitcher->SetTargetSubLevel(nullptr); + needsTick = true; + } + + UWorld* pWorld = pGeoreference->GetWorld(); + if (needsTick && pWorld && !pWorld->IsGameWorld()) { + // Other sub-levels won't be deactivated until + // UCesiumSubLevelSwitcherComponent next ticks. Normally that's no problem, + // but in some unusual cases it will never happen. For example, in UE 5.3, + // when running tests on CI with `-nullrhi`. Or if you close all your + // viewports in the Editor. So here we schedule a game thread task to ensure + // that _updateSubLevelStateEditor is called. It won't do any harm if we are + // ticking and it ends up being called multiple times. + TWeakObjectPtr pSwitcherWeak = pSwitcher; + AsyncTask(ENamedThreads::GameThread, [pSwitcherWeak]() { + UCesiumSubLevelSwitcherComponent* pSwitcher = pSwitcherWeak.Get(); + if (pSwitcher) { + pSwitcher->_updateSubLevelStateEditor(); + } + }); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSubLevelMutex.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSubLevelMutex.h new file mode 100644 index 0000000..a7a0676 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSubLevelMutex.h @@ -0,0 +1,24 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Delegates/IDelegateInstance.h" + +class UActorComponent; + +/** + * Ensures that only a single ALevelInstance with a UCesiumSubLevelComponent is + * visible in the Editor at any given time. It works by subscribing to the + * static MarkRenderStateDirtyEvent on UActorComponent, which is raised when the + * user toggles the visibility of an Actor in the Editor. + */ +class CesiumEditorSubLevelMutex { +public: + CesiumEditorSubLevelMutex(); + ~CesiumEditorSubLevelMutex(); + +private: + void OnMarkRenderStateDirty(UActorComponent& component); + + FDelegateHandle _subscription; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumGeoreferenceCustomization.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumGeoreferenceCustomization.cpp new file mode 100644 index 0000000..df7bc50 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumGeoreferenceCustomization.cpp @@ -0,0 +1,82 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGeoreferenceCustomization.h" +#include "CesiumCustomization.h" +#include "CesiumDegreesMinutesSecondsEditor.h" +#include "CesiumGeoreference.h" +#include "DetailCategoryBuilder.h" +#include "DetailLayoutBuilder.h" + +FName FCesiumGeoreferenceCustomization::RegisteredLayoutName; + +void FCesiumGeoreferenceCustomization::Register( + FPropertyEditorModule& PropertyEditorModule) { + + RegisteredLayoutName = ACesiumGeoreference::StaticClass()->GetFName(); + + PropertyEditorModule.RegisterCustomClassLayout( + RegisteredLayoutName, + FOnGetDetailCustomizationInstance::CreateStatic( + &FCesiumGeoreferenceCustomization::MakeInstance)); +} + +void FCesiumGeoreferenceCustomization::Unregister( + FPropertyEditorModule& PropertyEditorModule) { + PropertyEditorModule.UnregisterCustomClassLayout(RegisteredLayoutName); +} + +TSharedRef +FCesiumGeoreferenceCustomization::MakeInstance() { + return MakeShareable(new FCesiumGeoreferenceCustomization); +} + +void FCesiumGeoreferenceCustomization::CustomizeDetails( + IDetailLayoutBuilder& DetailBuilder) { + IDetailCategoryBuilder& CesiumCategory = DetailBuilder.EditCategory("Cesium"); + + TSharedPtr pButtons = + CesiumCustomization::CreateButtonGroup(); + + pButtons->AddButtonForUFunction( + ACesiumGeoreference::StaticClass()->FindFunctionByName( + GET_FUNCTION_NAME_CHECKED( + ACesiumGeoreference, + PlaceGeoreferenceOriginHere))); + + pButtons->AddButtonForUFunction( + ACesiumGeoreference::StaticClass()->FindFunctionByName( + GET_FUNCTION_NAME_CHECKED(ACesiumGeoreference, CreateSubLevelHere))); + + pButtons->Finish(DetailBuilder, CesiumCategory); + + CesiumCategory.AddProperty( + GET_MEMBER_NAME_CHECKED(ACesiumGeoreference, OriginPlacement)); + + TSharedPtr LatitudeDecimalDegreesHandle = + DetailBuilder.GetProperty( + GET_MEMBER_NAME_CHECKED(ACesiumGeoreference, OriginLatitude)); + IDetailPropertyRow& LatitudeRow = + CesiumCategory.AddProperty(LatitudeDecimalDegreesHandle); + LatitudeEditor = MakeShared( + LatitudeDecimalDegreesHandle, + false); + LatitudeEditor->PopulateRow(LatitudeRow); + + TSharedPtr LongitudeDecimalDegreesHandle = + DetailBuilder.GetProperty( + GET_MEMBER_NAME_CHECKED(ACesiumGeoreference, OriginLongitude)); + IDetailPropertyRow& LongitudeRow = + CesiumCategory.AddProperty(LongitudeDecimalDegreesHandle); + LongitudeEditor = MakeShared( + LongitudeDecimalDegreesHandle, + true); + LongitudeEditor->PopulateRow(LongitudeRow); + + CesiumCategory.AddProperty( + GET_MEMBER_NAME_CHECKED(ACesiumGeoreference, OriginHeight)); + + CesiumCategory.AddProperty( + GET_MEMBER_NAME_CHECKED(ACesiumGeoreference, Scale)); + CesiumCategory.AddProperty( + GET_MEMBER_NAME_CHECKED(ACesiumGeoreference, ShowLoadRadii)); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumGeoreferenceCustomization.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumGeoreferenceCustomization.h new file mode 100644 index 0000000..f3be7c4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumGeoreferenceCustomization.h @@ -0,0 +1,27 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumDegreesMinutesSecondsEditor.h" +#include "IDetailCustomization.h" + +/** + * An implementation of the IDetailCustomization interface that customizes + * the Details View of a CesiumGeoreference. It is registered in + * FCesiumEditorModule::StartupModule. + */ +class FCesiumGeoreferenceCustomization : public IDetailCustomization { +public: + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override; + + static void Register(FPropertyEditorModule& PropertyEditorModule); + static void Unregister(FPropertyEditorModule& PropertyEditorModule); + + static TSharedRef MakeInstance(); + +private: + TSharedPtr LongitudeEditor; + TSharedPtr LatitudeEditor; + + static FName RegisteredLayoutName; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumGlobeAnchorCustomization.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumGlobeAnchorCustomization.cpp new file mode 100644 index 0000000..4e0792b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumGlobeAnchorCustomization.cpp @@ -0,0 +1,298 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGlobeAnchorCustomization.h" +#include "CesiumCustomization.h" +#include "CesiumDegreesMinutesSecondsEditor.h" +#include "CesiumGeoreference.h" +#include "CesiumGlobeAnchorComponent.h" +#include "DetailCategoryBuilder.h" +#include "DetailLayoutBuilder.h" +#include "IDetailGroup.h" +#include "Widgets/SToolTip.h" + +FName FCesiumGlobeAnchorCustomization::RegisteredLayoutName; + +void FCesiumGlobeAnchorCustomization::Register( + FPropertyEditorModule& PropertyEditorModule) { + + RegisteredLayoutName = UCesiumGlobeAnchorComponent::StaticClass()->GetFName(); + + PropertyEditorModule.RegisterCustomClassLayout( + RegisteredLayoutName, + FOnGetDetailCustomizationInstance::CreateStatic( + &FCesiumGlobeAnchorCustomization::MakeInstance)); +} + +void FCesiumGlobeAnchorCustomization::Unregister( + FPropertyEditorModule& PropertyEditorModule) { + PropertyEditorModule.UnregisterCustomClassLayout(RegisteredLayoutName); +} + +TSharedRef +FCesiumGlobeAnchorCustomization::MakeInstance() { + return MakeShareable(new FCesiumGlobeAnchorCustomization); +} + +void FCesiumGlobeAnchorCustomization::CustomizeDetails( + IDetailLayoutBuilder& DetailBuilder) { + DetailBuilder.GetObjectsBeingCustomized(this->SelectedObjects); + + IDetailCategoryBuilder& CesiumCategory = DetailBuilder.EditCategory("Cesium"); + + TSharedPtr pButtons = + CesiumCustomization::CreateButtonGroup(); + pButtons->AddButtonForUFunction( + UCesiumGlobeAnchorComponent::StaticClass()->FindFunctionByName( + GET_FUNCTION_NAME_CHECKED( + UCesiumGlobeAnchorComponent, + SnapLocalUpToEllipsoidNormal))); + + pButtons->AddButtonForUFunction( + UCesiumGlobeAnchorComponent::StaticClass()->FindFunctionByName( + GET_FUNCTION_NAME_CHECKED( + UCesiumGlobeAnchorComponent, + SnapToEastSouthUp))); + + pButtons->Finish(DetailBuilder, CesiumCategory); + + CesiumCategory.AddProperty( + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorComponent, Georeference)); + CesiumCategory.AddProperty(GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorComponent, + ResolvedGeoreference)); + CesiumCategory.AddProperty(GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorComponent, + AdjustOrientationForGlobeWhenMoving)); + CesiumCategory.AddProperty(GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorComponent, + TeleportWhenUpdatingTransform)); + + this->UpdateDerivedProperties(); + + this->CreatePositionLongitudeLatitudeHeight(DetailBuilder, CesiumCategory); + this->CreatePositionEarthCenteredEarthFixed(DetailBuilder, CesiumCategory); + this->CreateRotationEastSouthUp(DetailBuilder, CesiumCategory); +} + +void FCesiumGlobeAnchorCustomization::CreatePositionEarthCenteredEarthFixed( + IDetailLayoutBuilder& DetailBuilder, + IDetailCategoryBuilder& Category) { + IDetailGroup& Group = CesiumCustomization::CreateGroup( + Category, + "PositionEarthCenteredEarthFixed", + FText::FromString("Position (Earth-Centered, Earth-Fixed)"), + false, + true); + + TArrayView View = this->DerivedPointers; + TSharedPtr XProperty = DetailBuilder.AddObjectPropertyData( + View, + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, X)); + TSharedPtr YProperty = DetailBuilder.AddObjectPropertyData( + View, + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, Y)); + TSharedPtr ZProperty = DetailBuilder.AddObjectPropertyData( + View, + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, Z)); + + Group.AddPropertyRow(XProperty.ToSharedRef()); + Group.AddPropertyRow(YProperty.ToSharedRef()); + Group.AddPropertyRow(ZProperty.ToSharedRef()); +} + +void FCesiumGlobeAnchorCustomization::CreatePositionLongitudeLatitudeHeight( + IDetailLayoutBuilder& DetailBuilder, + IDetailCategoryBuilder& Category) { + IDetailGroup& Group = CesiumCustomization::CreateGroup( + Category, + "PositionLatitudeLongitudeHeight", + FText::FromString("Position (Latitude, Longitude, Height)"), + false, + true); + + TArrayView View = this->DerivedPointers; + TSharedPtr LatitudeProperty = + DetailBuilder.AddObjectPropertyData( + View, + GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorDerivedProperties, + Latitude)); + TSharedPtr LongitudeProperty = + DetailBuilder.AddObjectPropertyData( + View, + GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorDerivedProperties, + Longitude)); + TSharedPtr HeightProperty = + DetailBuilder.AddObjectPropertyData( + View, + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, Height)); + + IDetailPropertyRow& LatitudeRow = + Group.AddPropertyRow(LatitudeProperty.ToSharedRef()); + LatitudeEditor = + MakeShared(LatitudeProperty, false); + LatitudeEditor->PopulateRow(LatitudeRow); + + IDetailPropertyRow& LongitudeRow = + Group.AddPropertyRow(LongitudeProperty.ToSharedRef()); + LongitudeEditor = + MakeShared(LongitudeProperty, true); + LongitudeEditor->PopulateRow(LongitudeRow); + + Group.AddPropertyRow(HeightProperty.ToSharedRef()); +} + +void FCesiumGlobeAnchorCustomization::CreateRotationEastSouthUp( + IDetailLayoutBuilder& DetailBuilder, + IDetailCategoryBuilder& Category) { + IDetailGroup& Group = CesiumCustomization::CreateGroup( + Category, + "RotationEastSouthUp", + FText::FromString("Rotation (East-South-Up)"), + false, + true); + + this->UpdateDerivedProperties(); + + TArrayView EastSouthUpPointerView = this->DerivedPointers; + TSharedPtr RollProperty = + DetailBuilder.AddObjectPropertyData(EastSouthUpPointerView, "Roll"); + TSharedPtr PitchProperty = + DetailBuilder.AddObjectPropertyData(EastSouthUpPointerView, "Pitch"); + TSharedPtr YawProperty = + DetailBuilder.AddObjectPropertyData(EastSouthUpPointerView, "Yaw"); + + Group.AddPropertyRow(RollProperty.ToSharedRef()); + Group.AddPropertyRow(PitchProperty.ToSharedRef()); + Group.AddPropertyRow(YawProperty.ToSharedRef()); +} + +void FCesiumGlobeAnchorCustomization::UpdateDerivedProperties() { + this->DerivedObjects.SetNum(this->SelectedObjects.Num()); + this->DerivedPointers.SetNum(DerivedObjects.Num()); + + for (int i = 0; i < this->SelectedObjects.Num(); ++i) { + if (!IsValid(this->DerivedObjects[i].Get())) { + this->DerivedObjects[i] = + NewObject(); + } + UCesiumGlobeAnchorComponent* GlobeAnchor = + Cast(this->SelectedObjects[i]); + this->DerivedObjects[i]->Initialize(GlobeAnchor); + this->DerivedPointers[i] = this->DerivedObjects[i].Get(); + } +} + +void UCesiumGlobeAnchorDerivedProperties::PostEditChangeProperty( + FPropertyChangedEvent& PropertyChangedEvent) { + Super::PostEditChangeProperty(PropertyChangedEvent); + + if (!PropertyChangedEvent.Property) { + return; + } + + FName propertyName = PropertyChangedEvent.Property->GetFName(); + + if (propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, X) || + propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, Y) || + propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, Z)) { + this->GlobeAnchor->Modify(); + this->GlobeAnchor->MoveToEarthCenteredEarthFixedPosition( + FVector(this->X, this->Y, this->Z)); + } else if (true) { + if (propertyName == GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorDerivedProperties, + Longitude) || + propertyName == GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorDerivedProperties, + Latitude) || + propertyName == GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorDerivedProperties, + Height)) { + this->GlobeAnchor->Modify(); + this->GlobeAnchor->MoveToLongitudeLatitudeHeight( + FVector(this->Longitude, this->Latitude, this->Height)); + } else if ( + propertyName == GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorDerivedProperties, + Pitch) || + propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, Yaw) || + propertyName == GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorDerivedProperties, + Roll)) { + this->GlobeAnchor->Modify(); + this->GlobeAnchor->SetEastSouthUpRotation( + FRotator(this->Pitch, this->Yaw, this->Roll).Quaternion()); + } + } +} + +bool UCesiumGlobeAnchorDerivedProperties::CanEditChange( + const FProperty* InProperty) const { + const FName Name = InProperty->GetFName(); + + // Valid georeference, nothing to disable + if (IsValid(this->GlobeAnchor->ResolveGeoreference())) { + return true; + } + + return Name != GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorDerivedProperties, + Longitude) && + Name != GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorDerivedProperties, + Latitude) && + Name != GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorDerivedProperties, + Height) && + Name != GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorDerivedProperties, + Pitch) && + Name != GET_MEMBER_NAME_CHECKED( + UCesiumGlobeAnchorDerivedProperties, + Yaw) && + Name != + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, Roll); +} + +void UCesiumGlobeAnchorDerivedProperties::Initialize( + UCesiumGlobeAnchorComponent* GlobeAnchorComponent) { + this->GlobeAnchor = GlobeAnchorComponent; + this->Tick(0.0f); +} + +void UCesiumGlobeAnchorDerivedProperties::Tick(float DeltaTime) { + if (this->GlobeAnchor) { + FVector position = this->GlobeAnchor->GetEarthCenteredEarthFixedPosition(); + this->X = position.X; + this->Y = position.Y; + this->Z = position.Z; + + // We can't transform the GlobeAnchor's ECEF coordinates back to + // cartographic & rotation without a valid georeference to know what + // ellipsoid to use. + if (IsValid(this->GlobeAnchor->ResolveGeoreference())) { + FVector llh = this->GlobeAnchor->GetLongitudeLatitudeHeight(); + this->Longitude = llh.X; + this->Latitude = llh.Y; + this->Height = llh.Z; + + FQuat rotation = this->GlobeAnchor->GetEastSouthUpRotation(); + FRotator rotator = rotation.Rotator(); + this->Roll = rotator.Roll; + this->Pitch = rotator.Pitch; + this->Yaw = rotator.Yaw; + } + } +} + +TStatId UCesiumGlobeAnchorDerivedProperties::GetStatId() const { + RETURN_QUICK_DECLARE_CYCLE_STAT( + UCesiumGlobeAnchorRotationEastSouthUp, + STATGROUP_Tickables); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumGlobeAnchorCustomization.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumGlobeAnchorCustomization.h new file mode 100644 index 0000000..13e7365 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumGlobeAnchorCustomization.h @@ -0,0 +1,147 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumDegreesMinutesSecondsEditor.h" +#include "IDetailCustomization.h" +#include "TickableEditorObject.h" +#include "CesiumGlobeAnchorCustomization.generated.h" + +class IDetailCategoryBuilder; +class UCesiumGlobeAnchorDerivedProperties; + +/** + * An implementation of the IDetailCustomization interface that customizes + * the Details View of a UCesiumGlobeAnchorComponent. It is registered in + * FCesiumEditorModule::StartupModule. + */ +class FCesiumGlobeAnchorCustomization : public IDetailCustomization { +public: + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override; + + static void Register(FPropertyEditorModule& PropertyEditorModule); + static void Unregister(FPropertyEditorModule& PropertyEditorModule); + + static TSharedRef MakeInstance(); + +private: + void CreatePositionEarthCenteredEarthFixed( + IDetailLayoutBuilder& DetailBuilder, + IDetailCategoryBuilder& Category); + void CreatePositionLongitudeLatitudeHeight( + IDetailLayoutBuilder& DetailBuilder, + IDetailCategoryBuilder& Category); + void CreateRotationEastSouthUp( + IDetailLayoutBuilder& DetailBuilder, + IDetailCategoryBuilder& Category); + void UpdateDerivedProperties(); + + TSharedPtr LongitudeEditor; + TSharedPtr LatitudeEditor; + TArray> SelectedObjects; + TArray> DerivedObjects; + TArray DerivedPointers; + + static FName RegisteredLayoutName; +}; + +UCLASS() +class UCesiumGlobeAnchorDerivedProperties : public UObject, + public FTickableEditorObject { + GENERATED_BODY() + +public: + UPROPERTY() + class UCesiumGlobeAnchorComponent* GlobeAnchor; + + /** + * The Earth-Centered Earth-Fixed (ECEF) X-coordinate of this component in + * meters. The ECEF coordinate system's origin is at the center of the Earth + * and +X points to the intersection of the Equator (zero degrees latitude) + * and Prime Meridian (zero degrees longitude). + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + double X = 0.0; + + /** + * The Earth-Centered Earth-Fixed (ECEF) Y-coordinate of this component in + * meters. The ECEF coordinate system's origin is at the center of the Earth + * and +Y points to the intersection of the Equator (zero degrees latitude) + * and +90 degrees longitude. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + double Y = 0.0; + + /** + * The Earth-Centered Earth-Fixed (ECEF) Z-coordinate of this component in + * meters. The ECEF coordinate system's origin is at the center of the Earth + * and +Z points up through the North Pole. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + double Z = 0.0; + + /** + * The latitude in degrees. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = (ClampMin = -90.0, ClampMax = 90.0)) + double Latitude = 0.0; + + /** + * The longitude in degrees. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = (ClampMin = -180.0, ClampMax = 180.0)) + double Longitude = 0.0; + + /** + * The height in meters above the ellipsoid. + * + * Do not confuse the ellipsoid height with a geoid height or height above + * mean sea level, which can be tens of meters higher or lower depending on + * where in the world the object is located. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + double Height = 0.0; + + /** + * The rotation around the right (Y) axis. Zero pitch means the look direction + * (+X) is level with the horizon. Positive pitch is looking up, negative + * pitch is looking down. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = (ClampMin = -89.9999, ClampMax = 89.9999)) + double Pitch = 0.0; + + /** + * The rotation around the up (Z) axis. Zero yaw means the look direction (+X) + * points East. Positive yaw rotates right toward South, while negative yaw + * rotates left toward North. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + double Yaw = 0.0; + + /** + * The rotation around the forward (X) axis. Zero roll is upright. Positive + * roll is like tilting your head to the right (clockwise), while negative + * roll is tilting to the left (counter-clockwise). + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + double Roll = 0.0; + + virtual void PostEditChangeProperty( + struct FPropertyChangedEvent& PropertyChangedEvent) override; + virtual bool CanEditChange(const FProperty* InProperty) const override; + + void Initialize(UCesiumGlobeAnchorComponent* GlobeAnchor); + + // Inherited via FTickableEditorObject + void Tick(float DeltaTime) override; + TStatId GetStatId() const override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonPanel.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonPanel.cpp new file mode 100644 index 0000000..6ab7b82 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonPanel.cpp @@ -0,0 +1,625 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumIonPanel.h" +#include "Cesium3DTilesSelection/Tile.h" +#include "Cesium3DTilesSelection/Tileset.h" +#include "Cesium3DTileset.h" +#include "CesiumCommands.h" +#include "CesiumEditor.h" +#include "CesiumIonRasterOverlay.h" +#include "CesiumIonServerSelector.h" +#include "CesiumRuntime.h" +#include "Editor.h" +#include "EditorModeManager.h" +#include "EngineUtils.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "IonLoginPanel.h" +#include "IonQuickAddPanel.h" +#include "SelectCesiumIonToken.h" +#include "Styling/SlateStyleRegistry.h" +#include "Widgets/Images/SImage.h" +#include "Widgets/Input/SButton.h" +#include "Widgets/Layout/SHeader.h" +#include "Widgets/Layout/SScrollBox.h" +#include "Widgets/Layout/SUniformGridPanel.h" +#include "Widgets/Views/SListView.h" + +using namespace CesiumIonClient; + +// Identifiers for the columns of the asset table view +static FName ColumnName_Name = "Name"; +static FName ColumnName_Type = "Type"; +static FName ColumnName_DateAdded = "DateAdded"; + +CesiumIonPanel::CesiumIonPanel() + : _pListView(nullptr), + _assets(), + _pSelection(nullptr), + _pLastServer(nullptr) { + this->_serverChangedDelegateHandle = + FCesiumEditorModule::serverManager().CurrentServerChanged.AddRaw( + this, + &CesiumIonPanel::OnServerChanged); + this->_sortColumnName = ColumnName_DateAdded; + this->_sortMode = EColumnSortMode::Type::Descending; + this->OnServerChanged(); +} + +CesiumIonPanel::~CesiumIonPanel() { + this->Subscribe(nullptr); + FCesiumEditorModule::serverManager().CurrentServerChanged.Remove( + this->_serverChangedDelegateHandle); +} + +void CesiumIonPanel::Construct(const FArguments& InArgs) { + this->Subscribe(FCesiumEditorModule::serverManager().GetCurrentServer()); + + // A function that returns the lambda that is used for rendering + // the sort mode indicator of the header column: If sorting is + // currently done based on the given name, then this will + // return the current _sortMode. Otherwise, it will return + // the 'None' sort mode. + auto sortModeLambda = [this](const FName& columnName) { + return [this, columnName]() { + if (_sortColumnName != columnName) { + return EColumnSortMode::None; + } + return _sortMode; + }; + }; + + this->_pListView = + SNew(SListView>) + .ListItemsSource(&this->_assets) + .OnMouseButtonDoubleClick(this, &CesiumIonPanel::AddAsset) + .OnGenerateRow(this, &CesiumIonPanel::CreateAssetRow) + .OnSelectionChanged(this, &CesiumIonPanel::AssetSelected) + .HeaderRow( + SNew(SHeaderRow) + + SHeaderRow::Column(ColumnName_Name) + .DefaultLabel(FText::FromString(TEXT("Name"))) + .SortMode_Lambda(sortModeLambda(ColumnName_Name)) + .OnSort(FOnSortModeChanged::CreateSP( + this, + &CesiumIonPanel::OnSortChange)) + + SHeaderRow::Column(ColumnName_Type) + .DefaultLabel(FText::FromString(TEXT("Type"))) + .SortMode_Lambda(sortModeLambda(ColumnName_Type)) + .OnSort(FOnSortModeChanged::CreateSP( + this, + &CesiumIonPanel::OnSortChange)) + + SHeaderRow::Column(ColumnName_DateAdded) + .DefaultLabel(FText::FromString(TEXT("Date added"))) + .SortMode_Lambda(sortModeLambda(ColumnName_DateAdded)) + .OnSort(FOnSortModeChanged::CreateSP( + this, + &CesiumIonPanel::OnSortChange))); + + TSharedPtr pDetails = this->AssetDetails(); + + // Create a splitter where the left shows the actual asset list + // (with the controls (search, refresh) on top), and the right + // shows the AssetDetails panel + + // clang-format off + ChildSlot[ + SNew(SSplitter).Orientation(EOrientation::Orient_Horizontal) + + SSplitter::Slot().Value(0.66f) + [ + SNew(SVerticalBox) + + SVerticalBox::Slot().AutoHeight() + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot().Padding(5.0f)[SNew(CesiumIonServerSelector)] + + // Add the refresh button at the upper left + SHorizontalBox::Slot().HAlign(HAlign_Left).Padding(5.0f) + [ + SNew(SButton) + .ButtonStyle(FCesiumEditorModule::GetStyle(), "CesiumButton") + .TextStyle( + FCesiumEditorModule::GetStyle(), "CesiumButtonText") + .ContentPadding(FMargin(1.0, 1.0)) + .HAlign(EHorizontalAlignment::HAlign_Center) + .Text(FText::FromString(TEXT("Refresh"))) + .ToolTipText(FText::FromString(TEXT("Refresh the asset list"))) + .OnClicked_Lambda([this]() { + FCesiumEditorModule::serverManager().GetCurrentSession()->refreshAssets(); + Refresh(); + return FReply::Handled(); + }) + [ + SNew(SImage).Image( + FCesiumEditorModule::GetStyle()->GetBrush( + TEXT("Cesium.Common.Refresh"))) + ] + ] + + // Add the search bar at the upper right + SHorizontalBox::Slot().HAlign(HAlign_Right).Padding(5.0f) + [ + SAssignNew(SearchBox, SSearchBox).OnTextChanged( + this, &CesiumIonPanel::OnSearchTextChange) + .MinDesiredWidth(200.f) + ] + ] + + SVerticalBox::Slot() + [ + this->_pListView.ToSharedRef() + ] + ] + + SSplitter::Slot().Value(0.34f) + [ + SNew(SBorder).Padding(10) + [ + pDetails.ToSharedRef() + ] + ] + ]; + // clang-format on + + FCesiumEditorModule::serverManager().GetCurrentSession()->refreshAssets(); +} + +void CesiumIonPanel::OnSortChange( + const EColumnSortPriority::Type SortPriority, + const FName& ColumnName, + const EColumnSortMode::Type Mode) { + if (_sortColumnName == ColumnName) { + if (_sortMode == EColumnSortMode::Type::None) { + _sortMode = EColumnSortMode::Type::Ascending; + } else if (_sortMode == EColumnSortMode::Type::Ascending) { + _sortMode = EColumnSortMode::Type::Descending; + } else { + _sortMode = EColumnSortMode::Type::None; + } + } else { + _sortColumnName = ColumnName; + _sortMode = EColumnSortMode::Type::Ascending; + } + Refresh(); +} + +void CesiumIonPanel::OnSearchTextChange(const FText& SearchText) { + _searchString = SearchText.ToString().TrimStartAndEnd(); + Refresh(); +} + +static bool isSupportedTileset(const TSharedPtr& pAsset) { + return pAsset && (pAsset->type == "3DTILES" || pAsset->type == "TERRAIN"); +} + +static bool isSupportedImagery(const TSharedPtr& pAsset) { + return pAsset && pAsset->type == "IMAGERY"; +} + +TSharedRef CesiumIonPanel::AssetDetails() { + return SNew(SScrollBox).Visibility_Lambda([this]() { + return this->_pSelection ? EVisibility::Visible : EVisibility::Collapsed; + }) + + SScrollBox::Slot().Padding( + 10, + 10, + 10, + 0)[SNew(STextBlock) + .AutoWrapText(true) + .TextStyle(FCesiumEditorModule::GetStyle(), "Heading") + .Text_Lambda([this]() { + return FText::FromString( + UTF8_TO_TCHAR(this->_pSelection->name.c_str())); + })] + + SScrollBox::Slot() + .Padding(10, 5, 10, 10) + .HAlign(EHorizontalAlignment::HAlign_Fill) + [SNew(STextBlock).Text_Lambda([this]() { + return FText::FromString(UTF8_TO_TCHAR( + (std::string("(ID: ") + + std::to_string(this->_pSelection->id) + ")") + .c_str())); + })] + + SScrollBox::Slot().Padding(10).HAlign( + EHorizontalAlignment::HAlign_Center) + [SNew(SButton) + .ButtonStyle(FCesiumEditorModule::GetStyle(), "CesiumButton") + .TextStyle( + FCesiumEditorModule::GetStyle(), + "CesiumButtonText") + .Visibility_Lambda([this]() { + return isSupportedTileset(this->_pSelection) + ? EVisibility::Visible + : EVisibility::Collapsed; + }) + .HAlign(EHorizontalAlignment::HAlign_Center) + .Text(FText::FromString(TEXT("Add to Level"))) + .OnClicked_Lambda([this]() { + this->AddAssetToLevel(this->_pSelection); + return FReply::Handled(); + })] + + SScrollBox::Slot().Padding(10).HAlign( + EHorizontalAlignment::HAlign_Center) + [SNew(SButton) + .ButtonStyle(FCesiumEditorModule::GetStyle(), "CesiumButton") + .TextStyle( + FCesiumEditorModule::GetStyle(), + "CesiumButtonText") + .Visibility_Lambda([this]() { + return isSupportedImagery(this->_pSelection) + ? EVisibility::Visible + : EVisibility::Collapsed; + }) + .HAlign(EHorizontalAlignment::HAlign_Center) + .Text(FText::FromString( + TEXT("Use as Terrain Tileset Base Layer"))) + .ToolTipText(FText::FromString(TEXT( + "Makes this asset the base overlay on the terrain tileset, underlying all others, by setting its MaterialLayerKey to 'Overlay0'. If the terrain tileset already has an 'Overlay0' it is removed. If no terrain tileset exists in the level, Cesium World Terrain is added."))) + .OnClicked_Lambda([this]() { + this->AddOverlayToTerrain(this->_pSelection, true); + return FReply::Handled(); + })] + + SScrollBox::Slot().Padding(10).HAlign( + EHorizontalAlignment::HAlign_Center) + [SNew(SButton) + .ButtonStyle(FCesiumEditorModule::GetStyle(), "CesiumButton") + .TextStyle( + FCesiumEditorModule::GetStyle(), + "CesiumButtonText") + .Visibility_Lambda([this]() { + return isSupportedImagery(this->_pSelection) + ? EVisibility::Visible + : EVisibility::Collapsed; + }) + .HAlign(EHorizontalAlignment::HAlign_Center) + .Text(FText::FromString(TEXT("Drape Over Terrain Tileset"))) + .ToolTipText(FText::FromString(TEXT( + "Adds this asset to any existing overlays on the terrain tileset by assigning it the first unused 'OverlayN` MaterialLayerKey. If no terrain tileset exists in the level, Cesium World Terrain is added."))) + .OnClicked_Lambda([this]() { + this->AddOverlayToTerrain(this->_pSelection, false); + return FReply::Handled(); + })] + + SScrollBox::Slot().Padding(10).HAlign( + EHorizontalAlignment::HAlign_Center) + [SNew(SButton) + .ButtonStyle(FCesiumEditorModule::GetStyle(), "CesiumButton") + .TextStyle( + FCesiumEditorModule::GetStyle(), + "CesiumButtonText") + .Visibility_Lambda([this]() { + return !isSupportedTileset(this->_pSelection) && + !isSupportedImagery(this->_pSelection) + ? EVisibility::Visible + : EVisibility::Collapsed; + }) + .HAlign(EHorizontalAlignment::HAlign_Center) + .Text(FText::FromString( + TEXT("This type of asset is not currently supported"))) + .IsEnabled(false)] + + SScrollBox::Slot().Padding(10).HAlign( + EHorizontalAlignment::HAlign_Fill) + [SNew(STextBlock) + .TextStyle( + FCesiumEditorModule::GetStyle(), + "AssetDetailsFieldHeader") + .Text(FText::FromString(TEXT("Description")))] + + SScrollBox::Slot().Padding( + 10, + 0)[SNew(STextBlock) + .AutoWrapText(true) + .TextStyle( + FCesiumEditorModule::GetStyle(), + "AssetDetailsFieldValue") + .Text_Lambda([this]() { + return FText::FromString(UTF8_TO_TCHAR( + this->_pSelection->description.c_str())); + })] + + SScrollBox::Slot().Padding(10).HAlign( + EHorizontalAlignment::HAlign_Fill) + [SNew(STextBlock) + .TextStyle( + FCesiumEditorModule::GetStyle(), + "AssetDetailsFieldHeader") + .Text(FText::FromString(TEXT("Attribution")))] + + SScrollBox::Slot().Padding( + 10, + 0)[SNew(STextBlock) + .AutoWrapText(true) + .TextStyle( + FCesiumEditorModule::GetStyle(), + "AssetDetailsFieldValue") + .Text_Lambda([this]() { + return FText::FromString(UTF8_TO_TCHAR( + this->_pSelection->attribution.c_str())); + })]; +} + +/** + * @brief Returns a comparator for the property of an Asset that is + * associated with the given column name. + * + * @param columnName The column name + * @return The comparator, comparing is ascending order (comparing by + * the asset->name by default, if the given column name was not known) + */ +static std::function&, const TSharedPtr&)> +comparatorFor(const FName& columnName) { + if (columnName == ColumnName_Type) { + return [](const TSharedPtr& a0, const TSharedPtr& a1) { + return a0->type < a1->type; + }; + } + if (columnName == ColumnName_DateAdded) { + return [](const TSharedPtr& a0, const TSharedPtr& a1) { + return a0->dateAdded < a1->dateAdded; + }; + } + return [](const TSharedPtr& a0, const TSharedPtr& a1) { + return a0->name < a1->name; + }; +} + +void CesiumIonPanel::ApplyFilter() { + + // UE_LOG(LogCesiumEditor, Warning, TEXT("ApplyFilter %s"), *_searchString); + + if (_searchString.IsEmpty()) { + return; + } + this->_assets = + this->_assets.FilterByPredicate([this](const TSharedPtr& Asset) { + // This mimics the behavior of the ion web UI, which + // searches for the given text in the name and description. + // + // Creating and using FString instances here instead of + // converting the _searchString to a std::string, because + // the 'FString::Contains' function does the desired + // case-INsensitive check by default. + FString Name = UTF8_TO_TCHAR(Asset->name.c_str()); + if (Name.Contains(_searchString)) { + return true; + } + FString Description = UTF8_TO_TCHAR(Asset->description.c_str()); + if (Description.Contains(_searchString)) { + return true; + } + return false; + }); +} + +void CesiumIonPanel::ApplySorting() { + + // UE_LOG(LogCesiumEditor, Warning, TEXT("ApplySorting %s with %d"), + // *_sortColumnName.ToString(), _sortMode); + + if (_sortMode == EColumnSortMode::Type::None) { + return; + } + auto baseComparator = comparatorFor(_sortColumnName); + if (_sortMode == EColumnSortMode::Type::Ascending) { + this->_assets.Sort(baseComparator); + } else { + this->_assets.Sort( + [&baseComparator]( + const TSharedPtr& a0, + const TSharedPtr& a1) { return baseComparator(a1, a0); }); + } +} + +void CesiumIonPanel::Refresh() { + if (!this->_pListView) + return; + + const Assets& assets = + FCesiumEditorModule::serverManager().GetCurrentSession()->getAssets(); + + this->_assets.SetNum(assets.items.size()); + + for (size_t i = 0; i < assets.items.size(); ++i) { + this->_assets[i] = MakeShared(assets.items[i]); + } + ApplyFilter(); + ApplySorting(); + this->_pListView->RequestListRefresh(); +} + +void CesiumIonPanel::Tick( + const FGeometry& AllottedGeometry, + const double InCurrentTime, + const float InDeltaTime) { + getAsyncSystem().dispatchMainThreadTasks(); + SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime); +} + +void CesiumIonPanel::AssetSelected( + TSharedPtr item, + ESelectInfo::Type selectionType) { + this->_pSelection = item; +} + +void CesiumIonPanel::Subscribe(UCesiumIonServer* pNewServer) { + if (this->_pLastServer) { + std::shared_ptr pLastSession = + FCesiumEditorModule::serverManager().GetSession(this->_pLastServer); + if (pLastSession) { + pLastSession->ConnectionUpdated.RemoveAll(this); + pLastSession->AssetsUpdated.RemoveAll(this); + } + } + + this->_pLastServer = pNewServer; + + if (pNewServer) { + std::shared_ptr pSession = + FCesiumEditorModule::serverManager().GetSession(pNewServer); + pSession->ConnectionUpdated.AddRaw(this, &CesiumIonPanel::Refresh); + pSession->AssetsUpdated.AddRaw(this, &CesiumIonPanel::Refresh); + } +} + +void CesiumIonPanel::OnServerChanged() { + UCesiumIonServer* pNewServer = + FCesiumEditorModule::serverManager().GetCurrentServer(); + this->Subscribe(pNewServer); + this->Refresh(); +} + +void CesiumIonPanel::AddAsset(TSharedPtr item) { + + if (isSupportedImagery(item)) { + // Don't add imagery on double-click, because we don't know if we should + // replace the base layer or add a new layer. + } else if (isSupportedTileset(item)) { + this->AddAssetToLevel(item); + } else { + UE_LOG( + LogCesiumEditor, + Warning, + TEXT("Cannot add asset of type %s"), + UTF8_TO_TCHAR(item->type.c_str())); + } +} + +void CesiumIonPanel::AddAssetToLevel(TSharedPtr item) { + SelectCesiumIonToken::SelectAndAuthorizeToken( + FCesiumEditorModule::serverManager().GetCurrentServer(), + {item->id}) + .thenInMainThread([item](const std::optional& /*maybeToken*/) { + // If token selection was canceled, or if an error occurred while + // selecting the token, ignore it and create the tileset anyway. It's + // already been logged if necessary, and we can let the user sort out + // the problem using the resulting Troubleshooting panel. + ACesium3DTileset* pTileset = + FCesiumEditorModule::CreateTileset(item->name, item->id); + if (pTileset) { + pTileset->RerunConstructionScripts(); + } + }); +} + +void CesiumIonPanel::AddOverlayToTerrain( + TSharedPtr item, + bool useAsBaseLayer) { + SelectCesiumIonToken::SelectAndAuthorizeToken( + FCesiumEditorModule::serverManager().GetCurrentServer(), + {item->id}) + .thenInMainThread([useAsBaseLayer, item](const std::optional&) { + UWorld* pCurrentWorld = GEditor->GetEditorWorldContext().World(); + ULevel* pCurrentLevel = pCurrentWorld->GetCurrentLevel(); + + ACesium3DTileset* pTilesetActor = + FCesiumEditorModule::FindFirstTilesetSupportingOverlays(); + if (!pTilesetActor) { + pTilesetActor = + FCesiumEditorModule::CreateTileset("Cesium World Terrain", 1); + } + + UCesiumRasterOverlay* pOverlay = + useAsBaseLayer ? FCesiumEditorModule::AddBaseOverlay( + pTilesetActor, + item->name, + item->id) + : FCesiumEditorModule::AddOverlay( + pTilesetActor, + item->name, + item->id); + + pTilesetActor->RerunConstructionScripts(); + + GEditor->SelectNone(true, false); + GEditor->SelectActor(pTilesetActor, true, true, true, true); + GEditor->SelectComponent(pOverlay, true, true, true); + }); +} + +namespace { + +/** + * @brief Returns a short string indicating the given asset type. + * + * The input must be one of the strings indicating the type of + * an asset, as of https://cesium.com/docs/rest-api/#tag/Assets. + * + * If the input is not a known type, then an unspecified error + * indicator will be returned. + * + * @param assetType The asset type. + * @return The string. + */ +std::string assetTypeToString(const std::string& assetType) { + static std::map lookup = { + {"3DTILES", "3D Tiles"}, + {"GLTF", "glTF"}, + {"IMAGERY", "Imagery"}, + {"TERRAIN", "Terrain"}, + {"CZML", "CZML"}, + {"KML", "KML"}, + {"GEOJSON", "GeoJSON"}}; + auto it = lookup.find(assetType); + if (it != lookup.end()) { + return it->second; + } + return "(Unknown)"; +} + +/** + * @brief Format the given asset date into a date string. + * + * The given string is assumed to be in ISO8601 format, as returned + * from the `asset.dateAdded`. It will be returned as a string in + * the YYYY-MM-DD format. If the string cannot be parsed, it will + * be returned as-it-is. + * + * @param assetDate The asset date + * @return The formatted string + */ +FString formatDate(const std::string& assetDate) { + FString unrealDateString = UTF8_TO_TCHAR(assetDate.c_str()); + FDateTime dateTime; + bool success = FDateTime::ParseIso8601(*unrealDateString, dateTime); + if (!success) { + UE_LOG( + LogCesiumEditor, + Warning, + TEXT("Could not parse date %s"), + UTF8_TO_TCHAR(assetDate.c_str())); + return UTF8_TO_TCHAR(assetDate.c_str()); + } + return dateTime.ToString(TEXT("%Y-%m-%d")); +} + +class AssetsTableRow : public SMultiColumnTableRow> { +public: + void Construct( + const FArguments& InArgs, + const TSharedRef& InOwnerTableView, + const TSharedPtr& pItem) { + this->_pItem = pItem; + SMultiColumnTableRow>::Construct( + InArgs, + InOwnerTableView); + } + + virtual TSharedRef + GenerateWidgetForColumn(const FName& InColumnName) override { + if (InColumnName == ColumnName_Name) { + return SNew(STextBlock) + .Text(FText::FromString(UTF8_TO_TCHAR(_pItem->name.c_str()))); + } else if (InColumnName == ColumnName_Type) { + return SNew(STextBlock) + .Text(FText::FromString( + UTF8_TO_TCHAR(assetTypeToString(_pItem->type).c_str()))); + } else if (InColumnName == ColumnName_DateAdded) { + return SNew(STextBlock) + .Text(FText::FromString(formatDate(_pItem->dateAdded))); + } else { + return SNew(STextBlock); + } + } + +private: + TSharedPtr _pItem; +}; + +} // namespace + +TSharedRef CesiumIonPanel::CreateAssetRow( + TSharedPtr item, + const TSharedRef& list) { + return SNew(AssetsTableRow, list, item); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonPanel.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonPanel.h new file mode 100644 index 0000000..3ae3500 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonPanel.h @@ -0,0 +1,107 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumIonClient/Assets.h" +#include "Widgets/DeclarativeSyntaxSupport.h" +#include "Widgets/Input/SSearchBox.h" +#include "Widgets/SCompoundWidget.h" +#include "Widgets/Views/SHeaderRow.h" + +class FArguments; +class ITableRow; +class STableViewBase; +class UCesiumIonServer; + +template class SListView; + +class CesiumIonPanel : public SCompoundWidget { + SLATE_BEGIN_ARGS(CesiumIonPanel) {} + SLATE_END_ARGS() + + CesiumIonPanel(); + virtual ~CesiumIonPanel(); + + void Construct(const FArguments& InArgs); + + void Refresh(); + + virtual void Tick( + const FGeometry& AllottedGeometry, + const double InCurrentTime, + const float InDeltaTime) override; + +private: + TSharedRef AssetDetails(); + TSharedRef CreateAssetRow( + TSharedPtr item, + const TSharedRef& list); + void AddAssetToLevel(TSharedPtr item); + void AddOverlayToTerrain( + TSharedPtr item, + bool useAsBaseLayer); + void AddAsset(TSharedPtr item); + void AssetSelected( + TSharedPtr item, + ESelectInfo::Type selectionType); + void Subscribe(UCesiumIonServer* pNewServer); + void OnServerChanged(); + + /** + * Filter the current _assets array, based on the current _searchString. + * This will replace the _assets array with one that only contains + * assets whose name or description contain the search string + */ + void ApplyFilter(); + + /** + * Sort the current _assets array, based on the current _sortColumnName + * and _sortMode, before using it to populate the list view. + */ + void ApplySorting(); + + /** + * Will be called whenever one header of the asset list view is + * clicked, and update the current _sortColumnName and _sortMode + * accordingly. + */ + void OnSortChange( + EColumnSortPriority::Type SortPriority, + const FName& ColumnName, + EColumnSortMode::Type NewSortMode); + + /** + * Will be called whenever the contents of the _SearchBox changes, + * store the corresponding _searchString, and refresh the view. + */ + void OnSearchTextChange(const FText& SearchText); + + FDelegateHandle _serverChangedDelegateHandle; + TSharedPtr>> _pListView; + TArray> _assets; + TSharedPtr _pSelection; + TObjectPtr _pLastServer; + + /** + * The column name based on which the main assets list view is currently + * sorted. + */ + FName _sortColumnName; + + /** + * The sort mode that is currently applied to the _sortColumnName. + */ + EColumnSortMode::Type _sortMode = EColumnSortMode::Type::None; + + /** + * The search box for entering the _searchString + */ + TSharedPtr SearchBox; + + /** + * The string that is currently entered in the SearchBox, + * (trimmed from whitespace), used for filtering the asset + * list in ApplyFilter. + */ + FString _searchString; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerDisplay.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerDisplay.cpp new file mode 100644 index 0000000..4c4b8a1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerDisplay.cpp @@ -0,0 +1,44 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumIonServerDisplay.h" +#include "CesiumEditor.h" +#include "CesiumIonServer.h" +#include "Editor.h" +#include "PropertyCustomizationHelpers.h" +#include "Widgets/Input/SEditableTextBox.h" +#include "Widgets/Text/STextBlock.h" + +void CesiumIonServerDisplay::Construct(const FArguments& InArgs) { + UCesiumIonServer* pServer = InArgs._Server; + + ChildSlot + [SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) + .Padding(5.0f)[SNew(STextBlock) + .Text(FText::FromString("Cesium ion Server:"))] + + SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) + .Padding(5.0f)[SNew(SEditableTextBox) + .IsEnabled(false) + .Padding(5.0f) + .Text(FText::FromString(pServer->DisplayName))] + + SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) + .Padding(5.0f)[PropertyCustomizationHelpers::MakeBrowseButton( + FSimpleDelegate:: + CreateSP(this, &CesiumIonServerDisplay::OnBrowseForServer), + FText::FromString( + "Show this Cesium ion Server in the Content Browser."), + true, + false)]]; +} + +void CesiumIonServerDisplay::OnBrowseForServer() { + TArray Objects; + Objects.Add(FCesiumEditorModule::serverManager().GetCurrentServer()); + GEditor->SyncBrowserToObjects(Objects); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerDisplay.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerDisplay.h new file mode 100644 index 0000000..b09e660 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerDisplay.h @@ -0,0 +1,19 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Widgets/SCompoundWidget.h" + +class FArguments; +class UCesiumIonServer; + +class CesiumIonServerDisplay : public SCompoundWidget { + SLATE_BEGIN_ARGS(CesiumIonServerDisplay) {} + SLATE_ARGUMENT(UCesiumIonServer*, Server) + SLATE_END_ARGS() + + void Construct(const FArguments& InArgs); + +private: + void OnBrowseForServer(); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerManager.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerManager.cpp new file mode 100644 index 0000000..6d685be --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerManager.cpp @@ -0,0 +1,245 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumIonServerManager.h" +#include "AssetRegistry/AssetRegistryModule.h" +#include "Cesium3DTileset.h" +#include "CesiumEditorSettings.h" +#include "CesiumIonRasterOverlay.h" +#include "CesiumIonServer.h" +#include "CesiumIonSession.h" +#include "CesiumRuntime.h" +#include "CesiumRuntimeSettings.h" +#include "CesiumSourceControl.h" +#include "Editor.h" +#include "EngineUtils.h" +#include "FileHelpers.h" + +CesiumIonServerManager::CesiumIonServerManager() noexcept { + FAssetRegistryModule& AssetRegistryModule = + FModuleManager::LoadModuleChecked("AssetRegistry"); + AssetRegistryModule.GetRegistry().OnAssetAdded().AddRaw( + this, + &CesiumIonServerManager::OnAssetAdded); + AssetRegistryModule.GetRegistry().OnAssetRemoved().AddRaw( + this, + &CesiumIonServerManager::OnAssetRemoved); + AssetRegistryModule.GetRegistry().OnAssetUpdated().AddRaw( + this, + &CesiumIonServerManager::OnAssetUpdated); +} + +CesiumIonServerManager::~CesiumIonServerManager() noexcept { + FAssetRegistryModule* pAssetRegistryModule = + FModuleManager::GetModulePtr("AssetRegistry"); + if (pAssetRegistryModule) { + pAssetRegistryModule->GetRegistry().OnAssetAdded().RemoveAll(this); + pAssetRegistryModule->GetRegistry().OnAssetRemoved().RemoveAll(this); + pAssetRegistryModule->GetRegistry().OnAssetUpdated().RemoveAll(this); + } +} + +void CesiumIonServerManager::Initialize() { + UCesiumRuntimeSettings* pSettings = + GetMutableDefault(); + if (pSettings) { + PRAGMA_DISABLE_DEPRECATION_WARNINGS + if (!pSettings->DefaultIonAccessTokenId_DEPRECATED.IsEmpty() || + !pSettings->DefaultIonAccessToken_DEPRECATED.IsEmpty()) { + UCesiumIonServer* pServer = UCesiumIonServer::GetDefaultServer(); + pServer->Modify(); + + pServer->DefaultIonAccessTokenId = + std::move(pSettings->DefaultIonAccessTokenId_DEPRECATED); + pSettings->DefaultIonAccessTokenId_DEPRECATED.Empty(); + + pServer->DefaultIonAccessToken = + std::move(pSettings->DefaultIonAccessToken_DEPRECATED); + pSettings->DefaultIonAccessToken_DEPRECATED.Empty(); + + UEditorLoadingAndSavingUtils::SavePackages({pServer->GetPackage()}, true); + + CesiumSourceControl::PromptToCheckoutConfigFile( + pSettings->GetDefaultConfigFilename()); + + pSettings->Modify(); + pSettings->TryUpdateDefaultConfigFile(); + } + PRAGMA_ENABLE_DEPRECATION_WARNINGS + } + + UCesiumEditorSettings* pEditorSettings = + GetMutableDefault(); + if (pEditorSettings) { + PRAGMA_DISABLE_DEPRECATION_WARNINGS + if (!pEditorSettings->UserAccessToken_DEPRECATED.IsEmpty()) { + UCesiumIonServer* pServer = UCesiumIonServer::GetDefaultServer(); + pEditorSettings->UserAccessTokenMap.Add( + pServer, + pEditorSettings->UserAccessToken_DEPRECATED); + pEditorSettings->UserAccessToken_DEPRECATED.Empty(); + pEditorSettings->Save(); + } + PRAGMA_ENABLE_DEPRECATION_WARNINGS + } + + UCesiumIonServer::SetServerForNewObjects(this->GetCurrentServer()); +} + +void CesiumIonServerManager::ResumeAll() { + const TArray>& servers = + this->GetServerList(); + for (const TWeakObjectPtr& pWeakServer : servers) { + UCesiumIonServer* pServer = pWeakServer.Get(); + if (pServer) { + std::shared_ptr pSession = this->GetSession(pServer); + pSession->resume(); + pSession->refreshProfileIfNeeded(); + } + } +} + +std::shared_ptr +CesiumIonServerManager::GetSession(UCesiumIonServer* Server) { + if (Server == nullptr) + return nullptr; + + ServerSession* Found = this->_sessions.FindByPredicate( + [Server](const ServerSession& ServerSession) { + return ServerSession.Server == Server; + }); + + if (!Found) { + std::shared_ptr pSession = + std::make_shared( + getAsyncSystem(), + getAssetAccessor(), + TWeakObjectPtr(Server)); + int32 index = this->_sessions.Add( + ServerSession{TWeakObjectPtr(Server), pSession}); + Found = &this->_sessions[index]; + } + + return Found->Session; +} + +std::shared_ptr CesiumIonServerManager::GetCurrentSession() { + return this->GetSession(this->GetCurrentServer()); +} + +const TArray>& +CesiumIonServerManager::GetServerList() { + this->RefreshServerList(); + return this->_servers; +} + +void CesiumIonServerManager::RefreshServerList() { + this->_servers.Empty(); + + TArray CesiumIonServers; + FAssetRegistryModule& AssetRegistryModule = + FModuleManager::LoadModuleChecked("AssetRegistry"); + AssetRegistryModule.Get().GetAssetsByClass( + UCesiumIonServer::StaticClass()->GetClassPathName(), + CesiumIonServers); + + for (const FAssetData& ServerAsset : CesiumIonServers) { + this->_servers.Add(Cast(ServerAsset.GetAsset())); + } + + this->ServerListChanged.Broadcast(); +} + +UCesiumIonServer* CesiumIonServerManager::GetCurrentServer() { + UCesiumEditorSettings* pSettings = GetMutableDefault(); + + if (!pSettings) { + return UCesiumIonServer::GetDefaultServer(); + } + + UCesiumIonServer* pServer = + pSettings->CurrentCesiumIonServer.LoadSynchronous(); + if (pServer == nullptr) { + pServer = UCesiumIonServer::GetDefaultServer(); + pSettings->CurrentCesiumIonServer = pServer; + pSettings->Save(); + } + + return pServer; +} + +void CesiumIonServerManager::SetCurrentServer(UCesiumIonServer* pServer) { + UCesiumEditorSettings* pSettings = GetMutableDefault(); + if (pSettings) { + pSettings->CurrentCesiumIonServer = pServer; + pSettings->Save(); + } + + if (UCesiumIonServer::GetServerForNewObjects() != pServer) { + UCesiumIonServer::SetServerForNewObjects(pServer); + CurrentServerChanged.Broadcast(); + } +} + +void CesiumIonServerManager::OnAssetAdded(const FAssetData& asset) { + if (asset.AssetClassPath != + UCesiumIonServer::StaticClass()->GetClassPathName()) + return; + + this->RefreshServerList(); +} + +void CesiumIonServerManager::OnAssetRemoved(const FAssetData& asset) { + if (asset.AssetClassPath != + UCesiumIonServer::StaticClass()->GetClassPathName()) + return; + + this->RefreshServerList(); + + UCesiumIonServer* pServer = Cast(asset.GetAsset()); + if (pServer && this->GetCurrentServer() == pServer) { + // Current server is being removed, so select a different one. + TWeakObjectPtr* ppNewServer = + this->_servers.FindByPredicate( + [pServer](const TWeakObjectPtr& pCandidate) { + return pCandidate.Get() != pServer; + }); + if (ppNewServer != nullptr) { + this->SetCurrentServer(ppNewServer->Get()); + } else { + this->SetCurrentServer(nullptr); + } + } +} + +void CesiumIonServerManager::OnAssetUpdated(const FAssetData& asset) { + if (!GEditor) + return; + + if (asset.AssetClassPath != + UCesiumIonServer::StaticClass()->GetClassPathName()) + return; + + // When a Cesium ion Server definition changes, refresh any objects that use + // it. + UCesiumIonServer* pServer = Cast(asset.GetAsset()); + if (!pServer) + return; + + UWorld* pCurrentWorld = GEditor->GetEditorWorldContext().World(); + if (!pCurrentWorld) + return; + + for (TActorIterator it(pCurrentWorld); it; ++it) { + if (it->GetCesiumIonServer() == pServer) { + it->RefreshTileset(); + } else { + TArray rasterOverlays; + it->GetComponents(rasterOverlays); + + for (UCesiumIonRasterOverlay* pOverlay : rasterOverlays) { + if (pOverlay->CesiumIonServer == pServer) + pOverlay->Refresh(); + } + } + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerManager.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerManager.h new file mode 100644 index 0000000..a620683 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerManager.h @@ -0,0 +1,45 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "UObject/WeakObjectPtrTemplates.h" +#include + +class UCesiumIonServer; +class CesiumIonSession; + +DECLARE_MULTICAST_DELEGATE(FCesiumIonServerChanged); + +class CESIUMEDITOR_API CesiumIonServerManager { +public: + CesiumIonServerManager() noexcept; + ~CesiumIonServerManager() noexcept; + + void Initialize(); + void ResumeAll(); + + std::shared_ptr GetSession(UCesiumIonServer* Server); + std::shared_ptr GetCurrentSession(); + + const TArray>& GetServerList(); + void RefreshServerList(); + + UCesiumIonServer* GetCurrentServer(); + void SetCurrentServer(UCesiumIonServer* pServer); + + FCesiumIonServerChanged ServerListChanged; + FCesiumIonServerChanged CurrentServerChanged; + +private: + void OnAssetAdded(const FAssetData& asset); + void OnAssetRemoved(const FAssetData& asset); + void OnAssetUpdated(const FAssetData& asset); + + struct ServerSession { + TWeakObjectPtr Server; + std::shared_ptr Session; + }; + + TArray _sessions; + TArray> _servers; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerSelector.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerSelector.cpp new file mode 100644 index 0000000..fd26477 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerSelector.cpp @@ -0,0 +1,117 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumIonServerSelector.h" +#include "CesiumEditor.h" +#include "CesiumIonServer.h" +#include "Editor.h" +#include "PropertyCustomizationHelpers.h" + +CesiumIonServerSelector::CesiumIonServerSelector() { + FCesiumEditorModule::serverManager().CurrentServerChanged.AddRaw( + this, + &CesiumIonServerSelector::OnCurrentServerChanged); +} + +CesiumIonServerSelector::~CesiumIonServerSelector() { + FCesiumEditorModule::serverManager().CurrentServerChanged.RemoveAll(this); +} + +void CesiumIonServerSelector::Construct(const FArguments& InArgs) { + ChildSlot + [SNew(SHorizontalBox) + + SHorizontalBox::Slot().FillWidth(1.0f).VAlign( + EVerticalAlignment::VAlign_Center) + [SAssignNew(_pCombo, SComboBox>) + .OptionsSource( + &FCesiumEditorModule::serverManager().GetServerList()) + .OnGenerateWidget( + this, + &CesiumIonServerSelector::OnGenerateServerEntry) + .OnSelectionChanged( + this, + &CesiumIonServerSelector::OnServerSelectionChanged) + .Content() + [SNew(STextBlock) + .Text( + this, + &CesiumIonServerSelector::GetServerValueAsText)]] + + SHorizontalBox::Slot().AutoWidth().VAlign( + EVerticalAlignment::VAlign_Center) + [PropertyCustomizationHelpers::MakeBrowseButton( + FSimpleDelegate:: + CreateSP(this, &CesiumIonServerSelector::OnBrowseForServer), + FText::FromString( + "Show this Cesium ion Server in the Content Browser."), + true, + false)]]; +} + +namespace { + +FText GetNameFromCesiumIonServerAsset( + const TWeakObjectPtr& pServer) { + if (!pServer.IsValid()) + return FText::FromString("Error: No Cesium ion server configured."); + + std::shared_ptr pSession = + FCesiumEditorModule::serverManager().GetSession(pServer.Get()); + + // Get the profile here, which will trigger it to load if it hasn't been + // loaded already. + const CesiumIonClient::Profile& profile = pSession->getProfile(); + + FString prefix; + FString suffix; + + if (pSession->isConnecting() || pSession->isResuming()) { + suffix = " (connecting...)"; + } else if (pSession->isLoadingProfile()) { + suffix = " (loading profile...)"; + } else if (pSession->isConnected() && pSession->isProfileLoaded()) { + prefix = FString(UTF8_TO_TCHAR(profile.username.c_str())); + prefix += " @ "; + } else { + suffix = " (not connected)"; + } + + return FText::FromString( + prefix + + (pServer->DisplayName.IsEmpty() ? pServer->GetPackage()->GetName() + : pServer->DisplayName) + + suffix); +} + +} // namespace + +FText CesiumIonServerSelector::GetServerValueAsText() const { + UCesiumIonServer* pServer = + FCesiumEditorModule::serverManager().GetCurrentServer(); + return GetNameFromCesiumIonServerAsset(pServer); +} + +TSharedRef CesiumIonServerSelector::OnGenerateServerEntry( + TWeakObjectPtr pServerAsset) { + return SNew(STextBlock).Text_Lambda([pServerAsset]() { + return GetNameFromCesiumIonServerAsset(pServerAsset); + }); +} + +void CesiumIonServerSelector::OnServerSelectionChanged( + TWeakObjectPtr InItem, + ESelectInfo::Type InSeletionInfo) { + FCesiumEditorModule::serverManager().SetCurrentServer(InItem.Get()); + FCesiumEditorModule::serverManager().GetCurrentSession()->resume(); +} + +void CesiumIonServerSelector::OnBrowseForServer() { + TArray Objects; + Objects.Add(FCesiumEditorModule::serverManager().GetCurrentServer()); + GEditor->SyncBrowserToObjects(Objects); +} + +void CesiumIonServerSelector::OnCurrentServerChanged() { + if (this->_pCombo) { + this->_pCombo->SetSelectedItem( + FCesiumEditorModule::serverManager().GetCurrentServer()); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerSelector.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerSelector.h new file mode 100644 index 0000000..9cce006 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonServerSelector.h @@ -0,0 +1,33 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Widgets/Input/SComboBox.h" +#include "Widgets/SCompoundWidget.h" + +class FArguments; +class UCesiumIonServer; + +class CesiumIonServerSelector : public SCompoundWidget { + SLATE_BEGIN_ARGS(CesiumIonServerSelector) {} + SLATE_END_ARGS() + + CesiumIonServerSelector(); + virtual ~CesiumIonServerSelector(); + + void Construct(const FArguments& InArgs); + +private: + TSharedRef + OnGenerateServerEntry(TWeakObjectPtr pServerAsset); + + FText GetServerValueAsText() const; + + void OnServerSelectionChanged( + TWeakObjectPtr InItem, + ESelectInfo::Type InSeletionInfo); + void OnBrowseForServer(); + void OnCurrentServerChanged(); + + TSharedPtr>> _pCombo; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonSession.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonSession.cpp new file mode 100644 index 0000000..2c64997 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonSession.cpp @@ -0,0 +1,629 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumIonSession.h" +#include "CesiumEditor.h" +#include "CesiumEditorSettings.h" +#include "CesiumIonServer.h" +#include "CesiumRuntimeSettings.h" +#include "CesiumSourceControl.h" +#include "CesiumUtility/Uri.h" +#include "FileHelpers.h" +#include "HAL/PlatformProcess.h" +#include "Misc/App.h" + +using namespace CesiumAsync; +using namespace CesiumIonClient; + +namespace { + +template void logResponseErrors(const Response& response) { + if (!response.errorCode.empty() && !response.errorMessage.empty()) { + UE_LOG( + LogCesiumEditor, + Error, + TEXT("%s (Code %s)"), + UTF8_TO_TCHAR(response.errorMessage.c_str()), + UTF8_TO_TCHAR(response.errorCode.c_str())); + } else if (!response.errorCode.empty()) { + UE_LOG( + LogCesiumEditor, + Error, + TEXT("Code %s"), + UTF8_TO_TCHAR(response.errorCode.c_str())); + } else if (!response.errorMessage.empty()) { + UE_LOG( + LogCesiumEditor, + Error, + TEXT("%s"), + UTF8_TO_TCHAR(response.errorMessage.c_str())); + } +} + +void logResponseErrors(const std::exception& exception) { + UE_LOG( + LogCesiumEditor, + Error, + TEXT("Exception: %s"), + UTF8_TO_TCHAR(exception.what())); +} + +} // namespace + +CesiumIonSession::CesiumIonSession( + CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + TWeakObjectPtr pServer) + : _asyncSystem(asyncSystem), + _pAssetAccessor(pAssetAccessor), + _pServer(pServer), + _connection(std::nullopt), + _profile(std::nullopt), + _assets(std::nullopt), + _tokens(std::nullopt), + _defaults(std::nullopt), + _appData(std::nullopt), + _isConnecting(false), + _isResuming(false), + _isLoadingProfile(false), + _isLoadingAssets(false), + _isLoadingTokens(false), + _isLoadingDefaults(false), + _loadProfileQueued(false), + _loadAssetsQueued(false), + _loadTokensQueued(false), + _loadDefaultsQueued(false), + _authorizeUrl() {} + +bool CesiumIonSession::isAuthenticationRequired() const { + return this->_appData.has_value() ? this->_appData->needsOauthAuthentication() + : true; +} + +void CesiumIonSession::connect() { + if (!this->_pServer.IsValid() || this->isConnecting() || + this->isConnected() || this->isResuming()) { + return; + } + + UCesiumIonServer* pServer = this->_pServer.Get(); + + this->_isConnecting = true; + + std::string ionServerUrl = TCHAR_TO_UTF8(*pServer->ServerUrl); + + Future> futureApiUrl = + !pServer->ApiUrl.IsEmpty() + ? this->_asyncSystem.createResolvedFuture>( + TCHAR_TO_UTF8(*pServer->ApiUrl)) + : Connection::getApiUrl( + this->_asyncSystem, + this->_pAssetAccessor, + ionServerUrl); + + std::shared_ptr thiz = this->shared_from_this(); + + std::move(futureApiUrl) + .thenInMainThread([ionServerUrl, thiz, pServer = this->_pServer]( + std::optional&& ionApiUrl) { + CesiumAsync::Promise promise = + thiz->_asyncSystem.createPromise(); + + if (!pServer.IsValid()) { + promise.reject( + std::runtime_error("CesiumIonServer unexpectedly nullptr")); + return promise.getFuture(); + } + + if (!ionApiUrl) { + promise.reject(std::runtime_error(fmt::format( + "Failed to retrieve API URL from the config.json file at the " + "specified Ion server URL: {}", + ionServerUrl))); + return promise.getFuture(); + } + + if (pServer->ApiUrl.IsEmpty()) { + pServer->ApiUrl = UTF8_TO_TCHAR(ionApiUrl->c_str()); + pServer->Modify(); + UEditorLoadingAndSavingUtils::SavePackages( + {pServer->GetPackage()}, + true); + } + + // Make request to /appData to learn the server's authentication mode + return thiz->ensureAppDataLoaded(); + }) + .thenInMainThread( + [ionServerUrl, thiz, pServer = this->_pServer](bool loadedAppData) { + if (!loadedAppData || !thiz->_appData.has_value()) { + Promise promise = + thiz->_asyncSystem.createPromise(); + promise.reject(std::runtime_error( + "Failed to obtain _appData, can't create connection")); + return promise.getFuture(); + } + + if (thiz->_appData->needsOauthAuthentication()) { + int64_t clientID = pServer->OAuth2ApplicationID; + return CesiumIonClient::Connection::authorize( + thiz->_asyncSystem, + thiz->_pAssetAccessor, + "Cesium for Unreal", + clientID, + "/cesium-for-unreal/oauth2/callback", + {"assets:list", + "assets:read", + "profile:read", + "tokens:read", + "tokens:write", + "geocode"}, + [thiz](const std::string& url) { + thiz->_authorizeUrl = url; + + thiz->_redirectUrl = + CesiumUtility::Uri::getQueryValue(url, "redirect_uri"); + + FPlatformProcess::LaunchURL( + UTF8_TO_TCHAR(thiz->_authorizeUrl.c_str()), + NULL, + NULL); + }, + thiz->_appData.value(), + std::string(TCHAR_TO_UTF8(*pServer->ApiUrl)), + CesiumUtility::Uri::resolve(ionServerUrl, "oauth")); + } + + return thiz->_asyncSystem + .createResolvedFuture( + CesiumIonClient::Connection( + thiz->_asyncSystem, + thiz->_pAssetAccessor, + "", + thiz->_appData.value(), + std::string(TCHAR_TO_UTF8(*pServer->ApiUrl)))); + }) + .thenInMainThread([ionServerUrl, thiz, pServer = this->_pServer]( + CesiumIonClient::Connection&& connection) { + thiz->_isConnecting = false; + thiz->_connection = std::move(connection); + + UCesiumEditorSettings* pSettings = + GetMutableDefault(); + pSettings->UserAccessTokenMap.Add( + thiz->_pServer.Get(), + UTF8_TO_TCHAR(thiz->_connection.value().getAccessToken().c_str())); + pSettings->Save(); + + thiz->ConnectionUpdated.Broadcast(); + + thiz->startQueuedLoads(); + }) + .catchInMainThread( + [ionServerUrl, thiz, pServer = this->_pServer](std::exception&& e) { + UE_LOG( + LogCesiumEditor, + Error, + TEXT("Error connecting: %s"), + UTF8_TO_TCHAR(e.what())); + thiz->_isConnecting = false; + thiz->_connection = std::nullopt; + thiz->ConnectionUpdated.Broadcast(); + }); +} + +void CesiumIonSession::resume() { + if (!this->_pServer.IsValid() || this->isConnecting() || + this->isConnected() || this->isResuming()) { + return; + } + + const UCesiumEditorSettings* pSettings = GetDefault(); + const FString* pUserAccessToken = + pSettings->UserAccessTokenMap.Find(this->_pServer.Get()); + + if (!pUserAccessToken || pUserAccessToken->IsEmpty()) { + // No existing session to resume. + return; + } + + this->_isResuming = true; + + std::shared_ptr thiz = this->shared_from_this(); + + // Verify that the connection actually works. + this->ensureAppDataLoaded() + .thenInMainThread([thiz, pUserAccessToken](bool loadedAppData) { + if (!loadedAppData || !thiz->_appData.has_value()) { + Promise promise = thiz->_asyncSystem.createPromise(); + + promise.reject(std::runtime_error( + "Failed to obtain _appData, can't resume connection")); + return promise.getFuture(); + } + + std::shared_ptr pConnection = std::make_shared( + thiz->_asyncSystem, + thiz->_pAssetAccessor, + TCHAR_TO_UTF8(**pUserAccessToken), + *thiz->_appData, + TCHAR_TO_UTF8(*thiz->_pServer->ApiUrl)); + + return pConnection->me().thenInMainThread( + [thiz, pConnection](Response&& response) { + logResponseErrors(response); + if (response.value.has_value()) { + thiz->_connection = std::move(*pConnection); + } + thiz->_isResuming = false; + thiz->ConnectionUpdated.Broadcast(); + + thiz->startQueuedLoads(); + }); + }) + .catchInMainThread([thiz](std::exception&& e) { + logResponseErrors(e); + thiz->_isResuming = false; + }); +} + +void CesiumIonSession::disconnect() { + this->_connection.reset(); + this->_profile.reset(); + this->_assets.reset(); + this->_tokens.reset(); + this->_defaults.reset(); + this->_appData.reset(); + + UCesiumEditorSettings* pSettings = GetMutableDefault(); + pSettings->UserAccessTokenMap.Remove(this->_pServer.Get()); + pSettings->Save(); + + this->ConnectionUpdated.Broadcast(); + this->ProfileUpdated.Broadcast(); + this->AssetsUpdated.Broadcast(); + this->TokensUpdated.Broadcast(); + this->DefaultsUpdated.Broadcast(); +} + +void CesiumIonSession::refreshProfile() { + if (!this->_connection || this->_isLoadingProfile) { + this->_loadProfileQueued = true; + return; + } + + this->_isLoadingProfile = true; + this->_loadProfileQueued = false; + + std::shared_ptr thiz = this->shared_from_this(); + + this->_connection->me() + .thenInMainThread([thiz](Response&& profile) { + logResponseErrors(profile); + thiz->_isLoadingProfile = false; + thiz->_profile = std::move(profile.value); + thiz->ProfileUpdated.Broadcast(); + if (thiz->_loadProfileQueued) + thiz->refreshProfile(); + }) + .catchInMainThread([thiz](std::exception&& e) { + logResponseErrors(e); + thiz->_isLoadingProfile = false; + thiz->_profile = std::nullopt; + thiz->ProfileUpdated.Broadcast(); + if (thiz->_loadProfileQueued) + thiz->refreshProfile(); + }); +} + +void CesiumIonSession::refreshAssets() { + if (!this->_connection || this->_isLoadingAssets) { + this->_loadAssetsQueued = true; + return; + } + + this->_isLoadingAssets = true; + this->_loadAssetsQueued = false; + + std::shared_ptr thiz = this->shared_from_this(); + + this->_connection->assets() + .thenInMainThread([thiz](Response&& assets) { + logResponseErrors(assets); + thiz->_isLoadingAssets = false; + thiz->_assets = std::move(assets.value); + thiz->AssetsUpdated.Broadcast(); + if (thiz->_loadAssetsQueued) + thiz->refreshAssets(); + }) + .catchInMainThread([thiz](std::exception&& e) { + logResponseErrors(e); + thiz->_isLoadingAssets = false; + thiz->_assets = std::nullopt; + thiz->AssetsUpdated.Broadcast(); + if (thiz->_loadAssetsQueued) + thiz->refreshAssets(); + }); +} + +void CesiumIonSession::refreshTokens() { + if (!this->_connection || this->_isLoadingTokens) { + this->_loadTokensQueued = true; + return; + } + + this->_isLoadingTokens = true; + this->_loadTokensQueued = false; + + std::shared_ptr thiz = this->shared_from_this(); + + this->_connection->tokens() + .thenInMainThread([thiz](Response&& tokens) { + logResponseErrors(tokens); + thiz->_isLoadingTokens = false; + thiz->_tokens = tokens.value + ? std::make_optional(std::move(tokens.value->items)) + : std::nullopt; + thiz->TokensUpdated.Broadcast(); + if (thiz->_loadTokensQueued) + thiz->refreshTokens(); + }) + .catchInMainThread([thiz](std::exception&& e) { + logResponseErrors(e); + thiz->_isLoadingTokens = false; + thiz->_tokens = std::nullopt; + thiz->TokensUpdated.Broadcast(); + if (thiz->_loadTokensQueued) + thiz->refreshTokens(); + }); +} + +void CesiumIonSession::refreshDefaults() { + if (!this->_connection || this->_isLoadingDefaults) { + this->_loadDefaultsQueued = true; + return; + } + + this->_isLoadingDefaults = true; + this->_loadDefaultsQueued = false; + + std::shared_ptr thiz = this->shared_from_this(); + + this->_connection->defaults() + .thenInMainThread([thiz](Response&& defaults) { + logResponseErrors(defaults); + thiz->_isLoadingDefaults = false; + thiz->_defaults = std::move(defaults.value); + thiz->DefaultsUpdated.Broadcast(); + if (thiz->_loadDefaultsQueued) + thiz->refreshDefaults(); + }) + .catchInMainThread([thiz](std::exception&& e) { + logResponseErrors(e); + thiz->_isLoadingDefaults = false; + thiz->_defaults = std::nullopt; + thiz->DefaultsUpdated.Broadcast(); + if (thiz->_loadDefaultsQueued) + thiz->refreshDefaults(); + }); +} + +const std::optional& +CesiumIonSession::getConnection() const { + return this->_connection; +} + +const CesiumIonClient::Profile& CesiumIonSession::getProfile() { + static const CesiumIonClient::Profile empty{}; + if (this->_profile) { + return *this->_profile; + } else { + this->refreshProfile(); + return empty; + } +} + +const CesiumIonClient::Assets& CesiumIonSession::getAssets() { + static const CesiumIonClient::Assets empty; + if (this->_assets) { + return *this->_assets; + } else { + this->refreshAssets(); + return empty; + } +} + +const std::vector& CesiumIonSession::getTokens() { + static const std::vector empty; + if (this->_tokens) { + return *this->_tokens; + } else { + this->refreshTokens(); + return empty; + } +} + +const CesiumIonClient::Defaults& CesiumIonSession::getDefaults() { + static const CesiumIonClient::Defaults empty; + if (this->_defaults) { + return *this->_defaults; + } else { + this->refreshDefaults(); + return empty; + } +} + +const CesiumIonClient::ApplicationData& CesiumIonSession::getAppData() { + static const CesiumIonClient::ApplicationData empty{}; + if (this->_appData) { + return *this->_appData; + } + return empty; +} + +bool CesiumIonSession::refreshProfileIfNeeded() { + if (this->_loadProfileQueued || !this->_profile.has_value()) { + this->refreshProfile(); + } + return this->isProfileLoaded(); +} + +bool CesiumIonSession::refreshAssetsIfNeeded() { + if (this->_loadAssetsQueued || !this->_assets.has_value()) { + this->refreshAssets(); + } + return this->isAssetListLoaded(); +} + +bool CesiumIonSession::refreshTokensIfNeeded() { + if (this->_loadTokensQueued || !this->_tokens.has_value()) { + this->refreshTokens(); + } + return this->isTokenListLoaded(); +} + +bool CesiumIonSession::refreshDefaultsIfNeeded() { + if (this->_loadDefaultsQueued || !this->_defaults.has_value()) { + this->refreshDefaults(); + } + return this->isDefaultsLoaded(); +} + +Future> +CesiumIonSession::findToken(const FString& token) const { + if (!this->_connection) { + return this->getAsyncSystem().createResolvedFuture( + Response(0, "NOTCONNECTED", "Not connected to Cesium ion.")); + } + + std::string tokenString = TCHAR_TO_UTF8(*token); + std::optional maybeTokenID = + Connection::getIdFromToken(tokenString); + + if (!maybeTokenID) { + return this->getAsyncSystem().createResolvedFuture( + Response(0, "INVALIDTOKEN", "The token is not valid.")); + } + + return this->_connection->token(*maybeTokenID); +} + +namespace { + +Token tokenFromServer(UCesiumIonServer* pServer) { + Token result; + + if (pServer) { + result.token = TCHAR_TO_UTF8(*pServer->DefaultIonAccessToken); + } + + return result; +} + +Future getTokenFuture(const CesiumIonSession& session) { + std::shared_ptr pSession = session.shared_from_this(); + TWeakObjectPtr pServer = session.getServer(); + + if (pServer.IsValid() && !pServer->DefaultIonAccessTokenId.IsEmpty()) { + return session.getConnection() + ->token(TCHAR_TO_UTF8(*pServer->DefaultIonAccessTokenId)) + .thenImmediately([pServer](Response&& tokenResponse) { + if (tokenResponse.value) { + return *tokenResponse.value; + } else { + return tokenFromServer(pServer.Get()); + } + }); + } else if (!pServer->DefaultIonAccessToken.IsEmpty()) { + return session.findToken(pServer->DefaultIonAccessToken) + .thenImmediately([pServer](Response&& response) { + if (response.value) { + return *response.value; + } else { + return tokenFromServer(pServer.Get()); + } + }); + } else { + return session.getAsyncSystem().createResolvedFuture( + tokenFromServer(pServer.Get())); + } +} + +} // namespace + +SharedFuture CesiumIonSession::getProjectDefaultTokenDetails() { + if (this->_projectDefaultTokenDetailsFuture) { + // If the future is resolved but its token doesn't match the designated + // default token, do the request again because the user probably specified a + // new token. + if (this->_projectDefaultTokenDetailsFuture->isReady() && + this->_projectDefaultTokenDetailsFuture->wait().token != + TCHAR_TO_UTF8(*this->_pServer->DefaultIonAccessToken)) { + this->_projectDefaultTokenDetailsFuture.reset(); + } else { + return *this->_projectDefaultTokenDetailsFuture; + } + } + + if (!this->isConnected()) { + return this->getAsyncSystem() + .createResolvedFuture(tokenFromServer(this->_pServer.Get())) + .share(); + } + + this->_projectDefaultTokenDetailsFuture = getTokenFuture(*this).share(); + return *this->_projectDefaultTokenDetailsFuture; +} + +void CesiumIonSession::invalidateProjectDefaultTokenDetails() { + this->_projectDefaultTokenDetailsFuture.reset(); +} + +void CesiumIonSession::startQueuedLoads() { + if (this->_loadProfileQueued) + this->refreshProfile(); + if (this->_loadAssetsQueued) + this->refreshAssets(); + if (this->_loadTokensQueued) + this->refreshTokens(); + if (this->_loadDefaultsQueued) + this->refreshDefaults(); +} + +CesiumAsync::Future CesiumIonSession::ensureAppDataLoaded() { + UCesiumIonServer* pServer = this->_pServer.Get(); + std::shared_ptr thiz = this->shared_from_this(); + + return CesiumIonClient::Connection::appData( + thiz->_asyncSystem, + thiz->_pAssetAccessor, + std::string(TCHAR_TO_UTF8(*pServer->ApiUrl))) + .thenInMainThread( + [thiz, pServer = this->_pServer]( + CesiumIonClient::Response&& + appData) { + CesiumAsync::Promise promise = + thiz->_asyncSystem.createPromise(); + + thiz->_appData = appData.value; + if (!appData.value.has_value()) { + UE_LOG( + LogCesiumEditor, + Error, + TEXT("Failed to obtain ion server application data: %s"), + UTF8_TO_TCHAR(appData.errorMessage.c_str())); + promise.resolve(false); + } else { + promise.resolve(true); + } + + return promise.getFuture(); + }) + .catchInMainThread([thiz, pServer = this->_pServer](std::exception&& e) { + UE_LOG( + LogCesiumEditor, + Error, + TEXT("Error obtaining appData: %s"), + UTF8_TO_TCHAR(e.what())); + return thiz->_asyncSystem.createResolvedFuture(false); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonSession.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonSession.h new file mode 100644 index 0000000..8259cd2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonSession.h @@ -0,0 +1,150 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumAsync/AsyncSystem.h" +#include "CesiumAsync/IAssetAccessor.h" +#include "CesiumAsync/SharedFuture.h" +#include "CesiumIonClient/Connection.h" +#include "Delegates/Delegate.h" +#include + +DECLARE_MULTICAST_DELEGATE(FIonUpdated); + +class UCesiumIonServer; + +class CesiumIonSession : public std::enable_shared_from_this { +public: + CesiumIonSession( + CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + TWeakObjectPtr pServer); + + const std::shared_ptr& getAssetAccessor() const { + return this->_pAssetAccessor; + } + const CesiumAsync::AsyncSystem& getAsyncSystem() const { + return this->_asyncSystem; + } + CesiumAsync::AsyncSystem& getAsyncSystem() { return this->_asyncSystem; } + + TWeakObjectPtr getServer() const { return this->_pServer; } + + bool isConnected() const { return this->_connection.has_value(); } + bool isConnecting() const { return this->_isConnecting; } + bool isResuming() const { return this->_isResuming; } + + bool isProfileLoaded() const { return this->_profile.has_value(); } + bool isLoadingProfile() const { return this->_isLoadingProfile; } + + bool isAssetListLoaded() const { return this->_assets.has_value(); } + bool isLoadingAssetList() const { return this->_isLoadingAssets; } + + bool isTokenListLoaded() const { return this->_tokens.has_value(); } + bool isLoadingTokenList() const { return this->_isLoadingTokens; } + + bool isDefaultsLoaded() const { return this->_defaults.has_value(); } + bool isLoadingDefaults() const { return this->_isLoadingDefaults; } + + bool isAuthenticationRequired() const; + + void connect(); + void resume(); + void disconnect(); + + void refreshProfile(); + void refreshAssets(); + void refreshTokens(); + void refreshDefaults(); + + FIonUpdated ConnectionUpdated; + FIonUpdated ProfileUpdated; + FIonUpdated AssetsUpdated; + FIonUpdated TokensUpdated; + FIonUpdated DefaultsUpdated; + + const std::optional& getConnection() const; + const CesiumIonClient::Profile& getProfile(); + const CesiumIonClient::Assets& getAssets(); + const std::vector& getTokens(); + const CesiumIonClient::Defaults& getDefaults(); + const CesiumIonClient::ApplicationData& getAppData(); + + const std::string& getAuthorizeUrl() const { return this->_authorizeUrl; } + const std::string& getRedirectUrl() const { return this->_redirectUrl; } + + bool refreshProfileIfNeeded(); + bool refreshAssetsIfNeeded(); + bool refreshTokensIfNeeded(); + bool refreshDefaultsIfNeeded(); + + /** + * Finds the details of the specified token in the user's account. + * + * If this session is not connected, returns std::nullopt. + * + * Even if the list of tokens is already loaded, this method does a new query + * in order get the most up-to-date information about the token. + * + * @param token The token. + * @return The details of the token, or an error response if the token does + * not exist in the signed-in user account. + */ + CesiumAsync::Future> + findToken(const FString& token) const; + + /** + * Gets the project default token. + * + * If the project default token exists in the signed-in user's account, full + * token details will be included. Otherwise, only the token value itself + * (i.e. the `token` property`) will be included, and it may or may not be + * valid. In the latter case, the `id` property will be an empty string. + * + * @return A future that resolves to the project default token. + */ + CesiumAsync::SharedFuture + getProjectDefaultTokenDetails(); + + void invalidateProjectDefaultTokenDetails(); + +private: + void startQueuedLoads(); + + /** + * If the {@link _appData} field has no value, this method will request the + * ion server's /appData endpoint to obtain its data. + * @returns A future that resolves to true if _appData is present or false if + * it couldn't be fetched. + */ + CesiumAsync::Future ensureAppDataLoaded(); + + CesiumAsync::AsyncSystem _asyncSystem; + std::shared_ptr _pAssetAccessor; + TWeakObjectPtr _pServer; + + std::optional _connection; + std::optional _profile; + std::optional _assets; + std::optional> _tokens; + std::optional _defaults; + std::optional _appData; + + std::optional> + _projectDefaultTokenDetailsFuture; + + bool _isConnecting; + bool _isResuming; + bool _isLoadingProfile; + bool _isLoadingAssets; + bool _isLoadingTokens; + bool _isLoadingDefaults; + + bool _loadProfileQueued; + bool _loadAssetsQueued; + bool _loadTokensQueued; + bool _loadDefaultsQueued; + + std::string _authorizeUrl; + std::string _redirectUrl; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonTokenTroubleshooting.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonTokenTroubleshooting.cpp new file mode 100644 index 0000000..74d1962 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonTokenTroubleshooting.cpp @@ -0,0 +1,853 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumIonTokenTroubleshooting.h" +#include "Cesium3DTileset.h" +#include "CesiumCommon.h" +#include "CesiumEditor.h" +#include "CesiumIonClient/Connection.h" +#include "CesiumIonRasterOverlay.h" +#include "CesiumIonServerDisplay.h" +#include "CesiumRuntimeSettings.h" +#include "CesiumUtility/Uri.h" +#include "EditorStyleSet.h" +#include "LevelEditor.h" +#include "ScopedTransaction.h" +#include "SelectCesiumIonToken.h" +#include "Widgets/Images/SImage.h" +#include "Widgets/Images/SThrobber.h" +#include "Widgets/Input/SButton.h" +#include "Widgets/Layout/SBorder.h" +#include "Widgets/Layout/SHeader.h" +#include "Widgets/Text/STextBlock.h" + +using namespace CesiumIonClient; + +/*static*/ std::vector + CesiumIonTokenTroubleshooting::_existingPanels{}; + +/*static*/ void CesiumIonTokenTroubleshooting::Open( + CesiumIonObject ionObject, + bool triggeredByError) { + auto panelMatch = [ionObject](const ExistingPanel& panel) { + return panel.pObject == ionObject; + }; + + // If a panel is already open for this object, close it. + auto it = std::find_if( + CesiumIonTokenTroubleshooting::_existingPanels.begin(), + CesiumIonTokenTroubleshooting::_existingPanels.end(), + panelMatch); + if (it != CesiumIonTokenTroubleshooting::_existingPanels.end()) { + TSharedRef pPanel = it->pPanel; + CesiumIonTokenTroubleshooting::_existingPanels.erase(it); + FSlateApplication::Get().RequestDestroyWindow(pPanel); + } + + // If this is a tileset, close any already-open panels associated with its + // overlays. Overlays won't appear until the tileset is working anyway. + TWeakObjectPtr* ppTileset = + swl::get_if>(&ionObject); + if (ppTileset && ppTileset->IsValid()) { + TArray rasterOverlays; + (*ppTileset)->GetComponents(rasterOverlays); + + for (UCesiumRasterOverlay* pOverlay : rasterOverlays) { + auto rasterIt = std::find_if( + CesiumIonTokenTroubleshooting::_existingPanels.begin(), + CesiumIonTokenTroubleshooting::_existingPanels.end(), + [pOverlay](const ExistingPanel& candidate) { + return candidate.pObject == CesiumIonObject(pOverlay); + }); + if (rasterIt != CesiumIonTokenTroubleshooting::_existingPanels.end()) { + TSharedRef pPanel = rasterIt->pPanel; + CesiumIonTokenTroubleshooting::_existingPanels.erase(rasterIt); + FSlateApplication::Get().RequestDestroyWindow(pPanel); + } + } + } + + // If this is a raster overlay and this panel is already open for its attached + // tileset, don't open the panel for the overlay for the same reason as above. + TWeakObjectPtr* ppRasterOverlay = + swl::get_if>(&ionObject); + if (ppRasterOverlay && ppRasterOverlay->IsValid()) { + ACesium3DTileset* pOwner = + Cast((*ppRasterOverlay)->GetOwner()); + if (pOwner) { + auto tilesetIt = std::find_if( + CesiumIonTokenTroubleshooting::_existingPanels.begin(), + CesiumIonTokenTroubleshooting::_existingPanels.end(), + [pOwner](const ExistingPanel& candidate) { + return candidate.pObject == CesiumIonObject(pOwner); + }); + if (tilesetIt != CesiumIonTokenTroubleshooting::_existingPanels.end()) { + return; + } + } + } + + // Open the panel + TSharedRef Troubleshooting = + SNew(CesiumIonTokenTroubleshooting) + .IonObject(ionObject) + .TriggeredByError(triggeredByError); + + Troubleshooting->GetOnWindowClosedEvent().AddLambda( + [panelMatch](const TSharedRef& pWindow) { + auto it = std::find_if( + CesiumIonTokenTroubleshooting::_existingPanels.begin(), + CesiumIonTokenTroubleshooting::_existingPanels.end(), + panelMatch); + if (it != CesiumIonTokenTroubleshooting::_existingPanels.end()) { + CesiumIonTokenTroubleshooting::_existingPanels.erase(it); + } + }); + FSlateApplication::Get().AddWindow(Troubleshooting); + + CesiumIonTokenTroubleshooting::_existingPanels.emplace_back( + ExistingPanel{ionObject, Troubleshooting}); +} + +namespace { + +TSharedRef +addTokenCheck(const FString& label, std::optional& state) { + return SNew(SHorizontalBox) + + SHorizontalBox::Slot().AutoWidth().Padding( + 3.0f, + 0.0f, + 3.0f, + 0.0f)[SNew(SThrobber) + .Visibility_Lambda([&state]() { + return state.has_value() ? EVisibility::Collapsed + : EVisibility::Visible; + }) + .NumPieces(1) + .Animate(SThrobber::All)] + + SHorizontalBox::Slot().AutoWidth().Padding( + 5.0f, + 0.0f, + 5.0f, + 3.0f)[SNew(SImage) + .Visibility_Lambda([&state]() { + return state.has_value() ? EVisibility::Visible + : EVisibility::Collapsed; + }) + .Image_Lambda([&state]() { + return state.has_value() && *state + ? FCesiumEditorModule::GetStyle()->GetBrush( + TEXT("Cesium.Common.GreenTick")) + : FCesiumEditorModule::GetStyle()->GetBrush( + TEXT("Cesium.Common.RedX")); + })] + + SHorizontalBox::Slot() + .AutoWidth()[SNew(STextBlock).Text(FText::FromString(label))]; +} + +bool isNull(const CesiumIonObject& o) { + return swl::visit([](auto p) { return p == nullptr; }, o); +} + +FString getLabel(const CesiumIonObject& o) { + struct Operation { + FString operator()(TWeakObjectPtr pTileset) { + return pTileset.IsValid() ? pTileset->GetActorLabel() : TEXT("Unknown"); + } + + FString operator()(TWeakObjectPtr pRasterOverlay) { + return pRasterOverlay.IsValid() ? pRasterOverlay->GetName() + : TEXT("Unknown"); + } + }; + + return swl::visit(Operation(), o); +} + +FString getName(const CesiumIonObject& o) { + return swl::visit([](auto p) { return p->GetName(); }, o); +} + +int64 getIonAssetID(const CesiumIonObject& o) { + struct Operation { + int64 operator()(TWeakObjectPtr pTileset) { + if (!pTileset.IsValid()) + return 0; + if (pTileset->GetTilesetSource() != ETilesetSource::FromCesiumIon) { + return 0; + } else { + return pTileset->GetIonAssetID(); + } + } + + int64 operator()(TWeakObjectPtr pRasterOverlay) { + if (!pRasterOverlay.IsValid()) + return 0; + UCesiumIonRasterOverlay* pIon = + Cast(pRasterOverlay); + if (!pIon) { + return 0; + } else { + return pIon->IonAssetID; + } + } + }; + + return swl::visit(Operation(), o); +} + +FString getIonAccessToken(const CesiumIonObject& o) { + struct Operation { + FString operator()(TWeakObjectPtr pTileset) { + if (!pTileset.IsValid()) + return FString(); + if (pTileset->GetTilesetSource() != ETilesetSource::FromCesiumIon) { + return FString(); + } else { + return pTileset->GetIonAccessToken(); + } + } + + FString operator()(TWeakObjectPtr pRasterOverlay) { + if (!pRasterOverlay.IsValid()) + return FString(); + UCesiumIonRasterOverlay* pIon = + Cast(pRasterOverlay); + if (!pIon) { + return FString(); + } else { + return pIon->IonAccessToken; + } + } + }; + + return swl::visit(Operation(), o); +} + +void setIonAccessToken(const CesiumIonObject& o, const FString& newToken) { + struct Operation { + const FString& newToken; + + void operator()(TWeakObjectPtr pTileset) { + if (!pTileset.IsValid()) + return; + if (pTileset->GetIonAccessToken() != newToken) { + pTileset->Modify(); + pTileset->SetIonAccessToken(newToken); + } else { + pTileset->RefreshTileset(); + } + } + + void operator()(TWeakObjectPtr pRasterOverlay) { + if (!pRasterOverlay.IsValid()) + return; + UCesiumIonRasterOverlay* pIon = + Cast(pRasterOverlay); + if (!pIon) { + return; + } + + if (pIon->IonAccessToken != newToken) { + pIon->Modify(); + pIon->IonAccessToken = newToken; + } + pIon->Refresh(); + } + }; + + return swl::visit(Operation{newToken}, o); +} + +FString getObjectType(const CesiumIonObject& o) { + struct Operation { + FString operator()(TWeakObjectPtr pTileset) { + return TEXT("Tileset"); + } + + FString operator()(TWeakObjectPtr pRasterOverlay) { + return TEXT("Raster Overlay"); + } + }; + + return swl::visit(Operation(), o); +} + +UObject* asUObject(const CesiumIonObject& o) { + return swl::visit( + [](auto p) -> UObject* { return p.IsValid() ? p.Get() : nullptr; }, + o); +} + +bool isUsingCesiumIon(const CesiumIonObject& o) { + struct Operation { + bool operator()(TWeakObjectPtr pTileset) { + return pTileset.IsValid() && + pTileset->GetTilesetSource() == ETilesetSource::FromCesiumIon; + } + + bool operator()(TWeakObjectPtr pRasterOverlay) { + if (!pRasterOverlay.IsValid()) + return false; + UCesiumIonRasterOverlay* pIon = + Cast(pRasterOverlay); + return pIon != nullptr; + } + }; + + return swl::visit(Operation(), o); +} + +UCesiumIonServer* getCesiumIonServer(const CesiumIonObject& o) { + struct Operation { + UCesiumIonServer* + operator()(TWeakObjectPtr pTileset) noexcept { + return pTileset.IsValid() ? pTileset->GetCesiumIonServer() : nullptr; + } + + UCesiumIonServer* + operator()(TWeakObjectPtr pRasterOverlay) noexcept { + if (!pRasterOverlay.IsValid()) + return nullptr; + const UCesiumIonRasterOverlay* pIon = + Cast(pRasterOverlay); + return pIon ? pIon->CesiumIonServer : nullptr; + } + }; + + UCesiumIonServer* pServer = swl::visit(Operation{}, o); + if (!IsValid(pServer)) { + pServer = UCesiumIonServer::GetDefaultServer(); + } + + return pServer; +} + +CesiumIonSession& getSession(const CesiumIonObject& o) { + return *FCesiumEditorModule::serverManager().GetSession( + getCesiumIonServer(o)); +} + +} // namespace + +void CesiumIonTokenTroubleshooting::Construct(const FArguments& InArgs) { + TSharedRef pMainVerticalBox = SNew(SVerticalBox); + + CesiumIonObject pIonObject = InArgs._IonObject; + if (isNull(pIonObject)) { + return; + } + + if (!isUsingCesiumIon(pIonObject)) { + SWindow::Construct( + SWindow::FArguments() + .Title(FText::FromString(FString::Format( + TEXT("{0}: Cesium ion Token Troubleshooting"), + {*getLabel(pIonObject)}))) + .AutoCenter(EAutoCenter::PreferredWorkArea) + .SizingRule(ESizingRule::UserSized) + .ClientSize(FVector2D(800, 600)) + [SNew(SBorder) + .Visibility(EVisibility::Visible) + .BorderImage(FAppStyle::GetBrush("Menu.Background")) + .Padding(FMargin(10.0f, 20.0f, 10.0f, 20.0f)) + [SNew(STextBlock) + .AutoWrapText(true) + .Text(FText::FromString(TEXT( + "This object is not configured to connect to Cesium ion.")))]]); + return; + } + + this->_pIonObject = pIonObject; + + if (InArgs._TriggeredByError) { + FString label = getLabel(pIonObject); + FString name = getName(pIonObject); + FString descriptor = + label == name ? FString::Format(TEXT("\"{0}\""), {name}) + : FString::Format(TEXT("\"{0}\" ({1})"), {label, name}); + + FString preamble = FString::Format( + TEXT( + "{0} {1} tried to access Cesium ion for asset ID {2}, but it didn't work, probably due to a problem with the access token. This panel will help you fix it!"), + {getObjectType(pIonObject), *descriptor, getIonAssetID(pIonObject)}); + + pMainVerticalBox->AddSlot().AutoHeight() + [SNew(STextBlock).AutoWrapText(true).Text(FText::FromString(preamble))]; + } + + pMainVerticalBox->AddSlot().AutoHeight().Padding( + 5.0f)[SNew(CesiumIonServerDisplay) + .Server(getCesiumIonServer(pIonObject))]; + + TSharedRef pDiagnosticColumns = SNew(SHorizontalBox); + + if (!getIonAccessToken(pIonObject).IsEmpty()) { + this->_assetTokenState.name = FString::Format( + TEXT("This {0}'s Access Token"), + {getObjectType(pIonObject)}); + this->_assetTokenState.token = getIonAccessToken(pIonObject); + pDiagnosticColumns->AddSlot() + .Padding(5.0f, 20.0f, 5.0f, 5.0f) + .VAlign(EVerticalAlignment::VAlign_Top) + .AutoWidth() + .FillWidth( + 0.5f)[this->createTokenPanel(pIonObject, this->_assetTokenState)]; + } + + this->_projectDefaultTokenState.name = TEXT("Project Default Access Token"); + this->_projectDefaultTokenState.token = + getCesiumIonServer(pIonObject)->DefaultIonAccessToken; + + pDiagnosticColumns->AddSlot() + .Padding(5.0f, 20.0f, 5.0f, 5.0f) + .VAlign(EVerticalAlignment::VAlign_Top) + .AutoWidth() + .FillWidth(0.5f) + [this->createTokenPanel(pIonObject, this->_projectDefaultTokenState)]; + + if (getSession(this->_pIonObject).isConnected()) { + // Don't let this panel be destroyed while the async operations below are in + // progress. + TSharedRef pPanel = + StaticCastSharedRef(this->AsShared()); + + getSession(this->_pIonObject) + .getConnection() + ->asset(getIonAssetID(pIonObject)) + .thenInMainThread([pPanel](Response&& asset) { + pPanel->_assetExistsInUserAccount = asset.value.has_value(); + }); + + // Start a new row if we have more than two columns. + if (pDiagnosticColumns->NumSlots() >= 2) { + pMainVerticalBox->AddSlot().AutoHeight()[pDiagnosticColumns]; + pDiagnosticColumns = SNew(SHorizontalBox); + } + + pDiagnosticColumns->AddSlot() + .Padding(5.0f, 20.0f, 5.0f, 5.0f) + .VAlign(EVerticalAlignment::VAlign_Top) + .AutoWidth() + .FillWidth(0.5f)[this->createDiagnosticPanel( + TEXT("Asset"), + {addTokenCheck( + TEXT("Asset ID exists in your user account"), + this->_assetExistsInUserAccount)})]; + } + + pMainVerticalBox->AddSlot().AutoHeight()[pDiagnosticColumns]; + + this->addRemedyButton( + pMainVerticalBox, + TEXT("Connect to Cesium ion"), + &CesiumIonTokenTroubleshooting::canConnectToCesiumIon, + &CesiumIonTokenTroubleshooting::connectToCesiumIon); + + this->addRemedyButton( + pMainVerticalBox, + FString::Format( + TEXT("Use the project default token for this {0}"), + {getObjectType(pIonObject)}), + &CesiumIonTokenTroubleshooting::canUseProjectDefaultToken, + &CesiumIonTokenTroubleshooting::useProjectDefaultToken); + + this->addRemedyButton( + pMainVerticalBox, + FString::Format( + TEXT("Authorize the {0}'s token to access this asset"), + {getObjectType(pIonObject)}), + &CesiumIonTokenTroubleshooting::canAuthorizeAssetToken, + &CesiumIonTokenTroubleshooting::authorizeAssetToken); + + this->addRemedyButton( + pMainVerticalBox, + TEXT("Authorize the project default token to access this asset"), + &CesiumIonTokenTroubleshooting::canAuthorizeProjectDefaultToken, + &CesiumIonTokenTroubleshooting::authorizeProjectDefaultToken); + + this->addRemedyButton( + pMainVerticalBox, + TEXT("Select or create a new project default token"), + &CesiumIonTokenTroubleshooting::canSelectNewProjectDefaultToken, + &CesiumIonTokenTroubleshooting::selectNewProjectDefaultToken); + + pMainVerticalBox->AddSlot().AutoHeight().Padding(0.0f, 20.0f, 0.0f, 0.0f) + [SNew(STextBlock) + .Visibility_Lambda([this]() { + return (this->_assetTokenState.token.IsEmpty() || + this->_assetTokenState.allowsAccessToAsset == false) && + (this->_projectDefaultTokenState.token.IsEmpty() || + this->_projectDefaultTokenState + .allowsAccessToAsset == false) && + this->_assetExistsInUserAccount == false + ? EVisibility::Visible + : EVisibility::Collapsed; + }) + .AutoWrapText(true) + .Text(FText::FromString(FString::Format( + TEXT( + "No automatic remedies are possible for Asset ID {0}, because:\n" + " - The current token does not authorize access to the specified asset ID, and\n" + " - The asset ID does not exist in your Cesium ion account.\n" + "\n" + "Please click the button below to open Cesium ion and check:\n" + " - The {1}'s \"Ion Asset ID\" property is correct.\n" + " - If the asset is from the \"Asset Depot\", verify that it has been added to \"My Assets\"."), + {getIonAssetID(pIonObject), getObjectType(pIonObject)})))]; + + this->addRemedyButton( + pMainVerticalBox, + TEXT("Open Cesium ion on the Web"), + &CesiumIonTokenTroubleshooting::canOpenCesiumIon, + &CesiumIonTokenTroubleshooting::openCesiumIon); + + SWindow::Construct( + SWindow::FArguments() + .Title(FText::FromString(FString::Format( + TEXT("{0}: Cesium ion Token Troubleshooting"), + {*getLabel(pIonObject)}))) + .AutoCenter(EAutoCenter::PreferredWorkArea) + .SizingRule(ESizingRule::UserSized) + .ClientSize(FVector2D(800, 600)) + [SNew(SBorder) + .Visibility(EVisibility::Visible) + .BorderImage(FAppStyle::GetBrush("Menu.Background")) + .Padding( + FMargin(10.0f, 10.0f, 10.0f, 10.0f))[pMainVerticalBox]]); +} + +TSharedRef CesiumIonTokenTroubleshooting::createDiagnosticPanel( + const FString& name, + const TArray>& diagnostics) { + TSharedRef pRows = + SNew(SVerticalBox) + + SVerticalBox::Slot().Padding( + 0.0f, + 5.0f, + 0.0f, + 5.0f)[SNew(SHeader).Content() + [SNew(STextBlock) + .TextStyle(FCesiumEditorModule::GetStyle(), "Heading") + .Text(FText::FromString(name))]]; + + for (const TSharedRef& diagnostic : diagnostics) { + pRows->AddSlot().Padding(0.0f, 5.0f, 0.0f, 5.0f)[diagnostic]; + } + + return pRows; +} + +TSharedRef CesiumIonTokenTroubleshooting::createTokenPanel( + const CesiumIonObject& pIonObject, + TokenState& state) { + CesiumIonSession& ionSession = getSession(pIonObject); + + int64 assetID = getIonAssetID(pIonObject); + + auto pConnection = std::make_shared( + ionSession.getAsyncSystem(), + ionSession.getAssetAccessor(), + TCHAR_TO_UTF8(*state.token), + ionSession.getAppData(), + TCHAR_TO_UTF8(*getCesiumIonServer(pIonObject)->ApiUrl)); + + // Don't let this panel be destroyed while the async operations below are in + // progress. + TSharedRef pPanel = + StaticCastSharedRef(this->AsShared()); + + pConnection->me() + .thenInMainThread( + [pPanel, pConnection, assetID, &state](Response&& profile) { + state.isValid = profile.value.has_value(); + if (pPanel->IsVisible()) { + return pConnection->asset(assetID); + } else { + return pConnection->getAsyncSystem().createResolvedFuture( + Response{}); + } + }) + .thenInMainThread([pPanel, pConnection, &state](Response&& asset) { + state.allowsAccessToAsset = asset.value.has_value(); + + if (pPanel->IsVisible()) { + // Query the tokens using the user's connection (_not_ the token + // connection created above). + CesiumIonSession& ionSession = getSession(pPanel->_pIonObject); + ionSession.resume(); + + const std::optional& userConnection = + ionSession.getConnection(); + if (!userConnection) { + Response result{}; + return ionSession.getAsyncSystem().createResolvedFuture( + std::move(result)); + } + return userConnection->tokens(); + } else { + return pConnection->getAsyncSystem().createResolvedFuture( + Response{}); + } + }) + .thenInMainThread( + [pPanel, pConnection, &state](Response&& tokens) { + state.associatedWithUserAccount = false; + if (tokens.value.has_value()) { + auto it = std::find_if( + tokens.value->items.begin(), + tokens.value->items.end(), + [&pConnection](const Token& token) { + return token.token == pConnection->getAccessToken(); + }); + state.associatedWithUserAccount = it != tokens.value->items.end(); + } + }); + + return this->createDiagnosticPanel( + state.name, + {addTokenCheck(TEXT("Is a valid Cesium ion token"), state.isValid), + addTokenCheck( + TEXT("Allows access to this asset"), + state.allowsAccessToAsset), + addTokenCheck( + TEXT("Is associated with your user account"), + state.associatedWithUserAccount)}); +} + +void CesiumIonTokenTroubleshooting::addRemedyButton( + const TSharedRef& pParent, + const FString& name, + bool (CesiumIonTokenTroubleshooting::*isAvailableCallback)() const, + void (CesiumIonTokenTroubleshooting::*clickCallback)()) { + pParent->AddSlot().AutoHeight().Padding( + 0.0f, + 20.0f, + 0.0f, + 5.0f)[SNew(SButton) + .ButtonStyle(FCesiumEditorModule::GetStyle(), "CesiumButton") + .TextStyle(FCesiumEditorModule::GetStyle(), "CesiumButtonText") + .OnClicked_Lambda([this, clickCallback]() { + std::invoke(clickCallback, *this); + this->RequestDestroyWindow(); + return FReply::Handled(); + }) + .Text(FText::FromString(name)) + .Visibility_Lambda([this, isAvailableCallback]() { + return std::invoke(isAvailableCallback, *this) + ? EVisibility::Visible + : EVisibility::Collapsed; + })]; +} + +bool CesiumIonTokenTroubleshooting::canConnectToCesiumIon() const { + return !getSession(this->_pIonObject).isConnected(); +} + +void CesiumIonTokenTroubleshooting::connectToCesiumIon() { + // Pop up the Cesium panel to show the status. + FLevelEditorModule* pLevelEditorModule = + FModuleManager::GetModulePtr( + FName(TEXT("LevelEditor"))); + TSharedPtr pTabManager = + pLevelEditorModule ? pLevelEditorModule->GetLevelEditorTabManager() + : FGlobalTabmanager::Get(); + pTabManager->TryInvokeTab(FTabId(TEXT("Cesium"))); + + // Pop up a browser window to sign in to ion. + getSession(this->_pIonObject).connect(); +} + +bool CesiumIonTokenTroubleshooting::canUseProjectDefaultToken() const { + const TokenState& state = this->_projectDefaultTokenState; + return !isNull(this->_pIonObject) && + !getIonAccessToken(this->_pIonObject).IsEmpty() && + state.isValid == true && state.allowsAccessToAsset == true; +} + +void CesiumIonTokenTroubleshooting::useProjectDefaultToken() { + if (isNull(this->_pIonObject)) { + return; + } + + FScopedTransaction transaction( + FText::FromString("Use Project Default Token")); + setIonAccessToken(this->_pIonObject, FString()); +} + +bool CesiumIonTokenTroubleshooting::canAuthorizeAssetToken() const { + const TokenState& state = this->_assetTokenState; + return this->_assetExistsInUserAccount == true && state.isValid == true && + state.allowsAccessToAsset == false && + state.associatedWithUserAccount == true; +} + +void CesiumIonTokenTroubleshooting::authorizeAssetToken() { + if (isNull(this->_pIonObject)) { + return; + } + this->authorizeToken(getIonAccessToken(this->_pIonObject), false); +} + +bool CesiumIonTokenTroubleshooting::canAuthorizeProjectDefaultToken() const { + const TokenState& state = this->_projectDefaultTokenState; + return this->_assetExistsInUserAccount == true && state.isValid == true && + state.allowsAccessToAsset == false && + state.associatedWithUserAccount == true; +} + +void CesiumIonTokenTroubleshooting::authorizeProjectDefaultToken() { + UCesiumIonServer* pServer = getCesiumIonServer(this->_pIonObject); + this->authorizeToken(pServer->DefaultIonAccessToken, true); +} + +bool CesiumIonTokenTroubleshooting::canSelectNewProjectDefaultToken() const { + if (this->_assetExistsInUserAccount == false) { + return false; + } + + const TokenState& state = this->_projectDefaultTokenState; + return getSession(this->_pIonObject).isConnected() && + (state.isValid == false || (state.allowsAccessToAsset == false && + state.associatedWithUserAccount == false)); +} + +void CesiumIonTokenTroubleshooting::selectNewProjectDefaultToken() { + if (isNull(this->_pIonObject)) { + return; + } + + CesiumIonSession& session = getSession(this->_pIonObject); + const std::optional& maybeConnection = session.getConnection(); + if (!session.isConnected() || !maybeConnection) { + UE_LOG( + LogCesiumEditor, + Error, + TEXT( + "Cannot create a new project default token because you are not signed in to Cesium ion.")); + return; + } + + // Don't let this panel be destroyed while the async operations below are in + // progress. + TSharedRef pPanel = + StaticCastSharedRef(this->AsShared()); + + SelectCesiumIonToken::SelectNewToken(getCesiumIonServer(this->_pIonObject)) + .thenInMainThread([pPanel](const std::optional& newToken) { + if (!newToken) { + return; + } + + pPanel->useProjectDefaultToken(); + }); +} + +bool CesiumIonTokenTroubleshooting::canOpenCesiumIon() const { + return getSession(this->_pIonObject).isConnected(); +} + +void CesiumIonTokenTroubleshooting::openCesiumIon() { + UCesiumIonServer* pServer = getCesiumIonServer(this->_pIonObject); + FPlatformProcess::LaunchURL( + UTF8_TO_TCHAR(CesiumUtility::Uri::resolve( + TCHAR_TO_UTF8(*pServer->ServerUrl), + "tokens") + .c_str()), + NULL, + NULL); +} + +void CesiumIonTokenTroubleshooting::authorizeToken( + const FString& token, + bool removeObjectToken) { + if (isNull(this->_pIonObject)) { + return; + } + + CesiumIonSession& session = getSession(this->_pIonObject); + const std::optional& maybeConnection = session.getConnection(); + if (!session.isConnected() || !maybeConnection) { + UE_LOG( + LogCesiumEditor, + Error, + TEXT( + "Cannot grant a token access to an asset because you are not signed in to Cesium ion.")); + return; + } + + TWeakObjectPtr pStillAlive = asUObject(this->_pIonObject); + + session.findToken(token).thenInMainThread([pStillAlive, + removeObjectToken, + pIonObject = this->_pIonObject, + ionAssetID = getIonAssetID( + this->_pIonObject), + connection = *maybeConnection]( + Response&& response) { + if (!pStillAlive.IsValid()) { + // UObject has been destroyed + return connection.getAsyncSystem().createResolvedFuture(); + } + + if (!response.value) { + UE_LOG( + LogCesiumEditor, + Error, + TEXT( + "Cannot grant a token access to an asset because the token was not found in the signed-in Cesium ion account.")); + return connection.getAsyncSystem().createResolvedFuture(); + } + + if (!response.value->assetIds) { + UE_LOG( + LogCesiumEditor, + Warning, + TEXT( + "Cannot grant a token access to an asset because the token appears to already have access to all assets.")); + return connection.getAsyncSystem().createResolvedFuture(); + } + + auto it = std::find( + response.value->assetIds->begin(), + response.value->assetIds->end(), + ionAssetID); + if (it != response.value->assetIds->end()) { + UE_LOG( + LogCesiumEditor, + Warning, + TEXT( + "Cannot grant a token access to an asset because the token appears to already have access to the asset.")); + return connection.getAsyncSystem().createResolvedFuture(); + } + + response.value->assetIds->emplace_back(ionAssetID); + + return connection + .modifyToken( + response.value->id, + response.value->name, + response.value->assetIds, + response.value->scopes, + response.value->allowedUrls) + .thenInMainThread([pIonObject, pStillAlive, removeObjectToken]( + Response&& result) { + if (result.value) { + // Refresh the object now that the token is valid (hopefully). + if (pStillAlive.IsValid()) { + if (removeObjectToken) { + setIonAccessToken(pIonObject, FString()); + } else { + // Set the token to the same value to force a refresh. + setIonAccessToken(pIonObject, getIonAccessToken(pIonObject)); + } + } + } else { + UE_LOG( + LogCesiumEditor, + Error, + TEXT( + "An error occurred while attempting to modify a token to grant it access to an asset. Please visit https://cesium.com/ion/tokens to modify the token manually.")); + } + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonTokenTroubleshooting.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonTokenTroubleshooting.h new file mode 100644 index 0000000..4602793 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonTokenTroubleshooting.h @@ -0,0 +1,86 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Widgets/SWindow.h" +#include +#include +#include + +class ACesium3DTileset; +class UCesiumRasterOverlay; + +using CesiumIonObject = swl::variant< + TWeakObjectPtr, + TWeakObjectPtr>; + +class CesiumIonTokenTroubleshooting : public SWindow { + SLATE_BEGIN_ARGS(CesiumIonTokenTroubleshooting) {} + /** + * The tileset being troubleshooted. + */ + SLATE_ARGUMENT(CesiumIonObject, IonObject) + + /** Whether this troubleshooting panel was opened in response to an error, + * versus opened manually by the user. */ + SLATE_ARGUMENT(bool, TriggeredByError) + SLATE_END_ARGS() + +public: + static void Open(CesiumIonObject ionObject, bool triggeredByError); + void Construct(const FArguments& InArgs); + +private: + struct ExistingPanel { + CesiumIonObject pObject; + TSharedRef pPanel; + }; + + static std::vector _existingPanels; + + struct TokenState { + FString name; + FString token; + std::optional isValid; + std::optional allowsAccessToAsset; + std::optional associatedWithUserAccount; + }; + + CesiumIonObject _pIonObject{}; + TokenState _assetTokenState{}; + TokenState _projectDefaultTokenState{}; + std::optional _assetExistsInUserAccount; + + TSharedRef createDiagnosticPanel( + const FString& name, + const TArray>& diagnostics); + + TSharedRef + createTokenPanel(const CesiumIonObject& pIonObject, TokenState& state); + + void addRemedyButton( + const TSharedRef& pParent, + const FString& name, + bool (CesiumIonTokenTroubleshooting::*isAvailableCallback)() const, + void (CesiumIonTokenTroubleshooting::*clickCallback)()); + + bool canConnectToCesiumIon() const; + void connectToCesiumIon(); + + bool canUseProjectDefaultToken() const; + void useProjectDefaultToken(); + + bool canAuthorizeAssetToken() const; + void authorizeAssetToken(); + + bool canAuthorizeProjectDefaultToken() const; + void authorizeProjectDefaultToken(); + + bool canSelectNewProjectDefaultToken() const; + void selectNewProjectDefaultToken(); + + bool canOpenCesiumIon() const; + void openCesiumIon(); + + void authorizeToken(const FString& token, bool removeObjectToken); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumPanel.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumPanel.cpp new file mode 100644 index 0000000..43fd08f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumPanel.cpp @@ -0,0 +1,328 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPanel.h" +#include "AssetRegistry/AssetRegistryModule.h" +#include "Cesium3DTileset.h" +#include "CesiumCommands.h" +#include "CesiumEditor.h" +#include "CesiumIonPanel.h" +#include "CesiumIonServer.h" +#include "CesiumIonServerSelector.h" +#include "CesiumRuntime.h" +#include "CesiumRuntimeSettings.h" +#include "CesiumUtility/Uri.h" +#include "Editor.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "Interfaces/IPluginManager.h" +#include "IonLoginPanel.h" +#include "IonQuickAddPanel.h" +#include "LevelEditor.h" +#include "SelectCesiumIonToken.h" +#include "Styling/SlateStyleRegistry.h" +#include "Widgets/Input/SComboBox.h" +#include "Widgets/Input/SHyperlink.h" +#include "Widgets/Layout/SScrollBox.h" + +CesiumPanel::CesiumPanel() : _pQuickAddPanel(nullptr), _pLastServer(nullptr) { + this->_serverChangedDelegateHandle = + FCesiumEditorModule::serverManager().CurrentServerChanged.AddRaw( + this, + &CesiumPanel::OnServerChanged); + this->OnServerChanged(); +} + +CesiumPanel::~CesiumPanel() { + this->Subscribe(nullptr); + FCesiumEditorModule::serverManager().CurrentServerChanged.Remove( + this->_serverChangedDelegateHandle); +} + +void CesiumPanel::Construct(const FArguments& InArgs) { + FCesiumEditorModule::serverManager().ResumeAll(); + + std::shared_ptr pSession = + FCesiumEditorModule::serverManager().GetCurrentSession(); + pSession->refreshDefaultsIfNeeded(); + + ChildSlot + [SNew(SVerticalBox) + + SVerticalBox::Slot().AutoHeight().Padding( + 5.0f)[SNew(CesiumIonServerSelector)] + + SVerticalBox::Slot().AutoHeight()[Toolbar()] + + SVerticalBox::Slot().VAlign(VAlign_Fill) + [SNew(SScrollBox) + SScrollBox::Slot()[BasicQuickAddPanel()] + + SScrollBox::Slot()[LoginPanel()] + + SScrollBox::Slot()[MainIonQuickAddPanel()]] + + SVerticalBox::Slot() + .AutoHeight() + .VAlign(VAlign_Bottom) + .HAlign(HAlign_Right)[Version()]]; +} + +void CesiumPanel::Tick( + const FGeometry& AllottedGeometry, + const double InCurrentTime, + const float InDeltaTime) { + getAsyncSystem().dispatchMainThreadTasks(); + SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime); +} + +void CesiumPanel::Refresh() { + if (!this->_pQuickAddPanel) + return; + + std::shared_ptr pSession = + FCesiumEditorModule::serverManager().GetCurrentSession(); + + this->_pQuickAddPanel->ClearItems(); + + if (pSession->isLoadingDefaults()) { + this->_pQuickAddPanel->SetMessage(FText::FromString("Loading...")); + } else if (!pSession->isDefaultsLoaded()) { + this->_pQuickAddPanel->SetMessage( + FText::FromString("This server does not define any Quick Add assets.")); + } else { + const CesiumIonClient::Defaults& defaults = pSession->getDefaults(); + + this->_pQuickAddPanel->SetMessage(FText()); + + for (const CesiumIonClient::QuickAddAsset& asset : + defaults.quickAddAssets) { + if (asset.type == "3DTILES" || + (asset.type == "TERRAIN" && !asset.rasterOverlays.empty())) { + this->_pQuickAddPanel->AddItem(QuickAddItem{ + QuickAddItemType::TILESET, + asset.name, + asset.description, + asset.objectName, + asset.assetId, + asset.rasterOverlays.empty() ? "" : asset.rasterOverlays[0].name, + asset.rasterOverlays.empty() ? -1 + : asset.rasterOverlays[0].assetId}); + } + } + } + + this->_pQuickAddPanel->Refresh(); +} + +void CesiumPanel::Subscribe(UCesiumIonServer* pNewServer) { + if (this->_pLastServer) { + std::shared_ptr pLastSession = + FCesiumEditorModule::serverManager().GetSession(this->_pLastServer); + if (pLastSession) { + pLastSession->ConnectionUpdated.RemoveAll(this); + pLastSession->DefaultsUpdated.RemoveAll(this); + } + } + + this->_pLastServer = pNewServer; + + if (pNewServer) { + std::shared_ptr pSession = + FCesiumEditorModule::serverManager().GetSession(pNewServer); + pSession->ConnectionUpdated.AddRaw(this, &CesiumPanel::OnConnectionUpdated); + pSession->DefaultsUpdated.AddRaw(this, &CesiumPanel::OnDefaultsUpdated); + } +} + +void CesiumPanel::OnServerChanged() { + UCesiumIonServer* pNewServer = + FCesiumEditorModule::serverManager().GetCurrentServer(); + this->Subscribe(pNewServer); + + std::shared_ptr pSession = + FCesiumEditorModule::serverManager().GetCurrentSession(); + if (pSession) { + pSession->refreshDefaultsIfNeeded(); + } + this->Refresh(); +} + +static bool isSignedIn() { + return FCesiumEditorModule::serverManager() + .GetCurrentSession() + ->isConnected(); +} + +static bool requiresTokenForServer() { + return FCesiumEditorModule::serverManager() + .GetCurrentSession() + ->getAppData() + .needsOauthAuthentication(); +} + +TSharedRef CesiumPanel::Toolbar() { + TSharedRef commandList = MakeShared(); + + commandList->MapAction( + FCesiumCommands::Get().AddFromIon, + FExecuteAction::CreateSP(this, &CesiumPanel::addFromIon), + FCanExecuteAction::CreateStatic(isSignedIn)); + commandList->MapAction( + FCesiumCommands::Get().UploadToIon, + FExecuteAction::CreateSP(this, &CesiumPanel::uploadToIon), + FCanExecuteAction::CreateStatic(isSignedIn)); + commandList->MapAction( + FCesiumCommands::Get().OpenTokenSelector, + FExecuteAction::CreateSP(this, &CesiumPanel::openTokenSelector), + FCanExecuteAction::CreateStatic(requiresTokenForServer)); + commandList->MapAction( + FCesiumCommands::Get().SignOut, + FExecuteAction::CreateSP(this, &CesiumPanel::signOut), + FCanExecuteAction::CreateStatic(isSignedIn)); + commandList->MapAction( + FCesiumCommands::Get().OpenDocumentation, + FExecuteAction::CreateSP(this, &CesiumPanel::openDocumentation)); + commandList->MapAction( + FCesiumCommands::Get().OpenSupport, + FExecuteAction::CreateSP(this, &CesiumPanel::openSupport)); + + FToolBarBuilder builder(commandList, FMultiBoxCustomization::None); + + builder.AddToolBarButton(FCesiumCommands::Get().AddFromIon); + builder.AddToolBarButton(FCesiumCommands::Get().UploadToIon); + builder.AddToolBarButton(FCesiumCommands::Get().OpenTokenSelector); + builder.AddToolBarButton(FCesiumCommands::Get().OpenDocumentation); + builder.AddToolBarButton(FCesiumCommands::Get().OpenSupport); + builder.AddToolBarButton(FCesiumCommands::Get().SignOut); + + return builder.MakeWidget(); +} + +TSharedRef CesiumPanel::LoginPanel() { + return SNew(IonLoginPanel).Visibility_Lambda([]() { + return isSignedIn() ? EVisibility::Collapsed : EVisibility::Visible; + }); +} + +TSharedRef CesiumPanel::MainIonQuickAddPanel() { + FCesiumEditorModule::serverManager() + .GetCurrentSession() + ->refreshDefaultsIfNeeded(); + + this->_pQuickAddPanel = + SNew(IonQuickAddPanel) + .Title(FText::FromString("Quick Add Cesium ion Assets")) + .Visibility_Lambda([]() { + return isSignedIn() ? EVisibility::Visible : EVisibility::Collapsed; + }); + + this->Refresh(); + + return this->_pQuickAddPanel.ToSharedRef(); +} + +TSharedRef CesiumPanel::BasicQuickAddPanel() { + TSharedPtr quickAddPanel = + SNew(IonQuickAddPanel).Title(FText::FromString("Quick Add Basic Actors")); + quickAddPanel->AddItem( + {QuickAddItemType::TILESET, + "Blank 3D Tiles Tileset", + "An empty tileset that can be configured to show Cesium ion assets or tilesets from other sources.", + "Blank Tileset", + -1, + "", + -1}); + quickAddPanel->AddItem( + {QuickAddItemType::SUNSKY, + "Cesium SunSky", + "An actor that represents a geospatially accurate sun and sky.", + "", + -1, + "", + -1}); + quickAddPanel->AddItem(QuickAddItem{ + QuickAddItemType::DYNAMIC_PAWN, + "Dynamic Pawn", + "A pawn that can be used to intuitively navigate in a geospatial environment.", + "", + -1, + "", + -1}); + quickAddPanel->AddItem(QuickAddItem{ + QuickAddItemType::CARTOGRAPHIC_POLYGON, + "Cesium Cartographic Polygon", + "An actor that can be used to draw out regions for use with clipping or other material effects.", + "", + -1, + "", + -1}); + return quickAddPanel.ToSharedRef(); +} + +TSharedRef CesiumPanel::Version() { + IPluginManager& PluginManager = IPluginManager::Get(); + TSharedPtr Plugin = + PluginManager.FindPlugin(TEXT("CesiumForUnreal")); + + FString Version = Plugin ? TEXT("v") + Plugin->GetDescriptor().VersionName + : TEXT("Unknown Version"); + + return SNew(SHyperlink) + .Text(FText::FromString(Version)) + .ToolTipText(FText::FromString( + TEXT("Open the Cesium for Unreal changelog in your web browser"))) + .OnNavigate_Lambda([]() { + FPlatformProcess::LaunchURL( + TEXT( + "https://github.com/CesiumGS/cesium-unreal/blob/main/CHANGES.md"), + NULL, + NULL); + }); +} + +void CesiumPanel::OnConnectionUpdated() { + FCesiumEditorModule::serverManager().GetCurrentSession()->refreshDefaults(); + this->Refresh(); +} + +void CesiumPanel::OnDefaultsUpdated() { this->Refresh(); } + +void CesiumPanel::addFromIon() { + FLevelEditorModule* pLevelEditorModule = + FModuleManager::GetModulePtr( + FName(TEXT("LevelEditor"))); + TSharedPtr pTabManager = + pLevelEditorModule ? pLevelEditorModule->GetLevelEditorTabManager() + : FGlobalTabmanager::Get(); + pTabManager->TryInvokeTab(FTabId(TEXT("CesiumIon"))); +} + +void CesiumPanel::uploadToIon() { + UCesiumIonServer* pServer = + FCesiumEditorModule::serverManager().GetCurrentServer(); + FPlatformProcess::LaunchURL( + UTF8_TO_TCHAR(CesiumUtility::Uri::resolve( + TCHAR_TO_UTF8(*pServer->ServerUrl), + "addasset") + .c_str()), + NULL, + NULL); +} + +void CesiumPanel::visitIon() { + UCesiumIonServer* pServer = + FCesiumEditorModule::serverManager().GetCurrentServer(); + FPlatformProcess::LaunchURL(*pServer->ServerUrl, NULL, NULL); +} + +void CesiumPanel::signOut() { + FCesiumEditorModule::serverManager().GetCurrentSession()->disconnect(); +} + +void CesiumPanel::openDocumentation() { + FPlatformProcess::LaunchURL(TEXT("https://cesium.com/docs"), NULL, NULL); +} + +void CesiumPanel::openSupport() { + FPlatformProcess::LaunchURL( + TEXT("https://community.cesium.com/"), + NULL, + NULL); +} + +void CesiumPanel::openTokenSelector() { + SelectCesiumIonToken::SelectNewToken( + FCesiumEditorModule::serverManager().GetCurrentServer()); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumPanel.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumPanel.h new file mode 100644 index 0000000..cf667b0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumPanel.h @@ -0,0 +1,50 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Widgets/SCompoundWidget.h" + +class FArguments; +class UCesiumIonServer; +class IonQuickAddPanel; + +class CesiumPanel : public SCompoundWidget { + SLATE_BEGIN_ARGS(CesiumPanel) {} + SLATE_END_ARGS() + + CesiumPanel(); + virtual ~CesiumPanel(); + void Construct(const FArguments& InArgs); + + virtual void Tick( + const FGeometry& AllottedGeometry, + const double InCurrentTime, + const float InDeltaTime) override; + + void Refresh(); + + void Subscribe(UCesiumIonServer* pNewServer); + void OnServerChanged(); + +private: + TSharedRef Toolbar(); + TSharedRef LoginPanel(); + TSharedRef MainIonQuickAddPanel(); + TSharedRef BasicQuickAddPanel(); + TSharedRef Version(); + + void OnConnectionUpdated(); + void OnDefaultsUpdated(); + + void addFromIon(); + void uploadToIon(); + void visitIon(); + void signOut(); + void openDocumentation(); + void openSupport(); + void openTokenSelector(); + + TSharedPtr _pQuickAddPanel; + TObjectPtr _pLastServer; + FDelegateHandle _serverChangedDelegateHandle; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumSourceControl.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumSourceControl.cpp new file mode 100644 index 0000000..dcd411c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumSourceControl.cpp @@ -0,0 +1,57 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumSourceControl.h" +#include "Framework/Notifications/NotificationManager.h" +#include "HAL/PlatformFileManager.h" +#include "ISourceControlModule.h" +#include "ISourceControlProvider.h" +#include "Misc/MessageDialog.h" +#include "SourceControlOperations.h" +#include "Widgets/Notifications/SNotificationList.h" + +void CesiumSourceControl::PromptToCheckoutConfigFile( + const FString& RelativeConfigFilePath) { + if (ISourceControlModule::Get().IsEnabled()) { + FString ConfigFilePath = + FPaths::ConvertRelativePathToFull(RelativeConfigFilePath); + FText ConfigFilename = + FText::FromString(FPaths::GetCleanFilename(ConfigFilePath)); + + ISourceControlProvider& SourceControlProvider = + ISourceControlModule::Get().GetProvider(); + FSourceControlStatePtr SourceControlState = + SourceControlProvider.GetState(ConfigFilePath, EStateCacheUsage::Use); + + if (SourceControlState.IsValid() && + SourceControlState->IsSourceControlled()) { + + TArray FilesToBeCheckedOut; + FilesToBeCheckedOut.Add(ConfigFilePath); + if (SourceControlState->CanCheckout() || + SourceControlState->IsCheckedOutOther() || + FPlatformFileManager::Get().GetPlatformFile().IsReadOnly( + *ConfigFilePath)) { + FString Message = FString::Format( + TEXT( + "The default access token is saved in {0} which is currently not checked out. Would you like to check it out from source control?"), + {ConfigFilename.ToString()}); + + if (FMessageDialog::Open( + EAppMsgType::YesNo, + FText::FromString(Message)) == EAppReturnType::Yes) { + ECommandResult::Type CommandResult = SourceControlProvider.Execute( + ISourceControlOperation::Create(), + FilesToBeCheckedOut); + + if (CommandResult != ECommandResult::Succeeded) { + // Show a notification that the file could not be checked out + FNotificationInfo CheckOutError(FText::FromString( + TEXT("Error: Failed to check out the configuration file."))); + CheckOutError.ExpireDuration = 3.0f; + FSlateNotificationManager::Get().AddNotification(CheckOutError); + } + } + } + } + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumSourceControl.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumSourceControl.h new file mode 100644 index 0000000..ea8fe89 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumSourceControl.h @@ -0,0 +1,10 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Containers/UnrealString.h" + +class CesiumSourceControl { +public: + static void PromptToCheckoutConfigFile(const FString& RelativeConfigFilePath); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonLoginPanel.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonLoginPanel.cpp new file mode 100644 index 0000000..7d50c7a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonLoginPanel.cpp @@ -0,0 +1,229 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "IonLoginPanel.h" +#include "CesiumEditor.h" +#include "CesiumIonClient/Connection.h" +#include "CesiumIonClient/Token.h" +#include "CesiumIonServer.h" +#include "HAL/PlatformApplicationMisc.h" +#include "HttpModule.h" +#include "Interfaces/IHttpRequest.h" +#include "Misc/App.h" +#include "Styling/SlateStyle.h" +#include "Widgets/Images/SImage.h" +#include "Widgets/Images/SThrobber.h" +#include "Widgets/Input/SButton.h" +#include "Widgets/Input/SEditableTextBox.h" +#include "Widgets/Input/SHyperlink.h" +#include "Widgets/Layout/SScaleBox.h" +#include "Widgets/Layout/SScrollBox.h" +#include "Widgets/SBoxPanel.h" +#include "Widgets/Text/STextBlock.h" + +using namespace CesiumIonClient; + +void IonLoginPanel::Construct(const FArguments& InArgs) { + + auto visibleWhenConnecting = [this]() { + return FCesiumEditorModule::serverManager() + .GetCurrentSession() + ->isConnecting() && + !FCesiumEditorModule::serverManager() + .GetCurrentServer() + ->ApiUrl.IsEmpty() + ? EVisibility::Visible + : EVisibility::Collapsed; + }; + + auto visibleWhenResuming = [this]() { + return FCesiumEditorModule::serverManager() + .GetCurrentSession() + ->isResuming() + ? EVisibility::Visible + : EVisibility::Collapsed; + }; + + auto visibleWhenNotConnectingOrResuming = []() { + return FCesiumEditorModule::serverManager() + .GetCurrentSession() + ->isConnecting() || + FCesiumEditorModule::serverManager() + .GetCurrentSession() + ->isResuming() + ? EVisibility::Collapsed + : EVisibility::Visible; + }; + + // TODO Format this, and disable clang format here + + TSharedPtr connectionStatusWidget = + SNew(SVerticalBox).Visibility_Lambda(visibleWhenConnecting) + + SVerticalBox::Slot() + .VAlign(VAlign_Top) + .Padding(5, 15, 5, 5) + .AutoHeight() + [SNew(STextBlock) + .Text(FText::FromString(TEXT( + "Waiting for you to sign into Cesium ion with your web browser..."))) + .AutoWrapText(true)] + + SVerticalBox::Slot() + .HAlign(HAlign_Center) + .Padding(5)[SNew(SThrobber).Animate(SThrobber::Horizontal)] + + SVerticalBox::Slot() + .HAlign(HAlign_Center) + .Padding(5) + .AutoHeight() + [SNew(SHyperlink) + .OnNavigate(this, &IonLoginPanel::LaunchBrowserAgain) + .Text(FText::FromString(TEXT("Open web browser again")))] + + SVerticalBox::Slot() + .VAlign(VAlign_Top) + .Padding(5) + .AutoHeight()[SNew(STextBlock) + .Text(FText::FromString(TEXT( + "Or copy the URL below into your web browser"))) + .AutoWrapText(true)] + + SVerticalBox::Slot() + .HAlign(HAlign_Center) + .AutoHeight() + [SNew(SHorizontalBox) + + SHorizontalBox::Slot().VAlign(VAlign_Center)[SNew( + SBorder)[SNew(SEditableText) + .IsReadOnly(true) + .Text_Lambda([this]() { + return FText::FromString(UTF8_TO_TCHAR( + FCesiumEditorModule::serverManager() + .GetCurrentSession() + ->getAuthorizeUrl() + .c_str())); + })]] + + SHorizontalBox::Slot() + .VAlign(VAlign_Center) + .HAlign(HAlign_Right) + .AutoWidth() + [SNew(SButton) + .OnClicked( + this, + &IonLoginPanel::CopyAuthorizeUrlToClipboard) + .Text( + FText::FromString(TEXT("Copy to clipboard")))]]; + + TSharedPtr connectionWidget = + SNew(SVerticalBox) + + SVerticalBox::Slot() + .VAlign(VAlign_Top) + .HAlign(HAlign_Center) + .Padding(5) + .AutoHeight() + [SNew(SButton) + .Visibility_Lambda(visibleWhenNotConnectingOrResuming) + .ButtonStyle(FCesiumEditorModule::GetStyle(), "CesiumButton") + .TextStyle( + FCesiumEditorModule::GetStyle(), + "CesiumButtonText") + .OnClicked(this, &IonLoginPanel::SignIn) + .Text(FText::FromString(TEXT("Connect to Cesium ion")))] + + SVerticalBox::Slot() + .VAlign(VAlign_Top) + .HAlign(HAlign_Center) + .Padding(5) + .AutoHeight() + [SNew(SButton) + .Visibility_Lambda(visibleWhenConnecting) + .ButtonStyle(FCesiumEditorModule::GetStyle(), "CesiumButton") + .TextStyle( + FCesiumEditorModule::GetStyle(), + "CesiumButtonText") + .OnClicked(this, &IonLoginPanel::CancelSignIn) + .Text(FText::FromString(TEXT("Cancel Connecting")))] + + SVerticalBox::Slot() + .VAlign(VAlign_Top) + .Padding(10, 0, 10, 5) + .AutoHeight() + [SNew(STextBlock) + .Visibility_Lambda([visibleWhenNotConnectingOrResuming]() { + // Only show this message for the SaaS server. + UCesiumIonServer* Server = + FCesiumEditorModule::serverManager() + .GetCurrentServer(); + if (Server->GetName() != TEXT("CesiumIonSaaS")) + return EVisibility::Collapsed; + + return visibleWhenNotConnectingOrResuming(); + }) + .AutoWrapText(true) + .TextStyle(FCesiumEditorModule::GetStyle(), "BodyBold") + .Text(FText::FromString(TEXT( + "You can now sign in with your Epic Games account!")))] + + SVerticalBox::Slot() + .VAlign(VAlign_Top) + .Padding(5, 15, 5, 5) + .AutoHeight()[SNew(STextBlock) + .Text(FText::FromString( + TEXT("Resuming the previous connection..."))) + .Visibility_Lambda(visibleWhenResuming) + .AutoWrapText(true)] + + SVerticalBox::Slot() + .VAlign(VAlign_Top) + .AutoHeight()[connectionStatusWidget.ToSharedRef()]; + + ChildSlot + [SNew(SScrollBox) + + SScrollBox::Slot() + .VAlign(VAlign_Top) + .HAlign(HAlign_Center) + .Padding(20, 0, 20, 5) + [SNew(SScaleBox) + .Stretch(EStretch::ScaleToFit) + .HAlign(HAlign_Center) + .VAlign(VAlign_Top)[SNew(SImage).Image( + FCesiumEditorModule::GetStyle()->GetBrush( + TEXT("Cesium.Logo")))]] + + SScrollBox::Slot() + .VAlign(VAlign_Top) + .Padding(30, 10, 30, 10) + [SNew(STextBlock) + .AutoWrapText(true) + .Text(FText::FromString(TEXT( + "Access global high-resolution 3D content, including photogrammetry, terrain, imagery, and buildings. Bring your own data for tiling, hosting, and streaming to Unreal Engine.")))] + + SScrollBox::Slot() + .VAlign(VAlign_Top) + .HAlign(HAlign_Center) + .Padding(20)[connectionWidget.ToSharedRef()]]; +} + +FReply IonLoginPanel::SignIn() { + FCesiumEditorModule::serverManager().GetCurrentSession()->connect(); + return FReply::Handled(); +} + +FReply IonLoginPanel::CopyAuthorizeUrlToClipboard() { + FText url = + FText::FromString(UTF8_TO_TCHAR(FCesiumEditorModule::serverManager() + .GetCurrentSession() + ->getAuthorizeUrl() + .c_str())); + FPlatformApplicationMisc::ClipboardCopy(*url.ToString()); + return FReply::Handled(); +} + +void IonLoginPanel::LaunchBrowserAgain() { + FPlatformProcess::LaunchURL( + UTF8_TO_TCHAR(FCesiumEditorModule::serverManager() + .GetCurrentSession() + ->getAuthorizeUrl() + .c_str()), + NULL, + NULL); +} + +FReply IonLoginPanel::CancelSignIn() { + TSharedRef pRequest = + FHttpModule::Get().CreateRequest(); + pRequest->SetURL(UTF8_TO_TCHAR(FCesiumEditorModule::serverManager() + .GetCurrentSession() + ->getRedirectUrl() + .c_str())); + pRequest->ProcessRequest(); + return FReply::Handled(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonLoginPanel.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonLoginPanel.h new file mode 100644 index 0000000..c48d413 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonLoginPanel.h @@ -0,0 +1,21 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Widgets/SCompoundWidget.h" + +class FArguments; + +class IonLoginPanel : public SCompoundWidget { + SLATE_BEGIN_ARGS(IonLoginPanel) {} + SLATE_END_ARGS() + + void Construct(const FArguments& InArgs); + +private: + void LaunchBrowserAgain(); + + FReply SignIn(); + FReply CancelSignIn(); + FReply CopyAuthorizeUrlToClipboard(); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonQuickAddPanel.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonQuickAddPanel.cpp new file mode 100644 index 0000000..4ca8000 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonQuickAddPanel.cpp @@ -0,0 +1,386 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "IonQuickAddPanel.h" +#include "Cesium3DTileset.h" +#include "CesiumCartographicPolygon.h" +#include "CesiumEditor.h" +#include "CesiumIonClient/Connection.h" +#include "CesiumIonRasterOverlay.h" +#include "CesiumIonServer.h" +#include "CesiumRuntimeSettings.h" +#include "CesiumUtility/Uri.h" +#include "Editor.h" +#include "PropertyCustomizationHelpers.h" +#include "SelectCesiumIonToken.h" +#include "Styling/SlateStyle.h" +#include "Widgets/Images/SThrobber.h" +#include "Widgets/Input/SButton.h" +#include "Widgets/Input/SEditableTextBox.h" +#include "Widgets/Input/SHyperlink.h" +#include "Widgets/Layout/SHeader.h" +#include "Widgets/Layout/SScrollBox.h" +#include "Widgets/SBoxPanel.h" +#include "Widgets/Text/STextBlock.h" +#include "Widgets/Views/SListView.h" + +using namespace CesiumIonClient; + +void IonQuickAddPanel::Construct(const FArguments& InArgs) { + ChildSlot + [SNew(SVerticalBox) + + SVerticalBox::Slot() + .VAlign(VAlign_Top) + .AutoHeight() + .Padding(FMargin(5.0f, 20.0f, 5.0f, 10.0f)) + [SNew(SHeader).Content() + [SNew(STextBlock) + .TextStyle(FCesiumEditorModule::GetStyle(), "Heading") + .Text(InArgs._Title)]] + + SVerticalBox::Slot() + .VAlign(VAlign_Top) + .AutoHeight()[SNew(STextBlock) + .Visibility_Lambda([this]() { + return this->_message.IsEmpty() + ? EVisibility::Collapsed + : EVisibility::Visible; + }) + .Text_Lambda([this]() { return this->_message; }) + .AutoWrapText(true)] + + SVerticalBox::Slot() + .VAlign(VAlign_Top) + .Padding(FMargin(5.0f, 0.0f, 5.0f, 20.0f))[this->QuickAddList()]]; +} + +void IonQuickAddPanel::AddItem(const QuickAddItem& item) { + _quickAddItems.Add(MakeShared(item)); +} + +void IonQuickAddPanel::ClearItems() { this->_quickAddItems.Empty(); } + +void IonQuickAddPanel::Refresh() { + if (!this->_pQuickAddList) + return; + + this->_pQuickAddList->RequestListRefresh(); +} + +const FText& IonQuickAddPanel::GetMessage() const { return this->_message; } + +void IonQuickAddPanel::SetMessage(const FText& message) { + this->_message = message; +} + +TSharedRef IonQuickAddPanel::QuickAddList() { + this->_pQuickAddList = + SNew(SListView>) + .SelectionMode(ESelectionMode::None) + .ListItemsSource(&_quickAddItems) + .OnMouseButtonDoubleClick(this, &IonQuickAddPanel::AddItemToLevel) + .OnGenerateRow(this, &IonQuickAddPanel::CreateQuickAddItemRow); + return this->_pQuickAddList.ToSharedRef(); +} + +TSharedRef IonQuickAddPanel::CreateQuickAddItemRow( + TSharedRef item, + const TSharedRef& list) { + // clang-format off + return SNew(STableRow>, list).Content() + [ + SNew(SBox) + .HAlign(EHorizontalAlignment::HAlign_Fill) + .HeightOverride(40.0f) + .Content() + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .FillWidth(1.0f) + .Padding(5.0f) + .VAlign(EVerticalAlignment::VAlign_Center) + [ + SNew(STextBlock) + .AutoWrapText(true) + .Text(FText::FromString(UTF8_TO_TCHAR(item->name.c_str()))) + .ToolTipText(FText::FromString(UTF8_TO_TCHAR(item->description.c_str()))) + ] + + SHorizontalBox::Slot() + .AutoWidth() + .VAlign(EVerticalAlignment::VAlign_Center) + [ + PropertyCustomizationHelpers::MakeNewBlueprintButton( + FSimpleDelegate::CreateLambda( + [this, item]() { this->AddItemToLevel(item); }), + FText::FromString( + TEXT("Add this item to the level")), + TAttribute::Create([this, item]() { + return this->_itemsBeingAdded.find(item->name) == + this->_itemsBeingAdded.end(); + }) + ) + ] + ] + ]; + // clang-format on +} + +namespace { + +void showAssetDepotConfirmWindow( + const FString& itemName, + int64_t missingAsset) { + + UCesiumIonServer* pServer = + FCesiumEditorModule::serverManager().GetCurrentServer(); + std::string url = CesiumUtility::Uri::resolve( + TCHAR_TO_UTF8(*pServer->ServerUrl), + "assetdepot/" + std::to_string(missingAsset)); + + // clang-format off + TSharedRef AssetDepotConfirmWindow = + SNew(SWindow) + .Title(FText::FromString(TEXT("Asset is not available in My Assets"))) + .ClientSize(FVector2D(400.0f, 200.0f)) + .Content() + [ + SNew(SVerticalBox) + + SVerticalBox::Slot().AutoHeight().Padding(10.0f) + [ + SNew(STextBlock) + .AutoWrapText(true) + .Text(FText::FromString(TEXT("Before " + itemName + + " can be added to your level, it must be added to \"My Assets\" in your Cesium ion account."))) + ] + + SVerticalBox::Slot() + .AutoHeight() + .HAlign(EHorizontalAlignment::HAlign_Left) + .Padding(10.0f, 5.0f) + [ + SNew(SHyperlink) + .OnNavigate_Lambda([url]() { + FPlatformProcess::LaunchURL( + UTF8_TO_TCHAR(url.c_str()), + NULL, + NULL); + }) + .Text(FText::FromString(TEXT( + "Open this asset in the Cesium ion Asset Depot"))) + ] + + SVerticalBox::Slot() + .AutoHeight() + .HAlign(EHorizontalAlignment::HAlign_Left) + .Padding(10.0f, 5.0f) + [ + SNew(STextBlock).Text(FText::FromString(TEXT( + "Click \"Add to my assets\" in the Cesium ion web page"))) + ] + + SVerticalBox::Slot() + .AutoHeight() + .HAlign(EHorizontalAlignment::HAlign_Left) + .Padding(10.0f, 5.0f) + [ + SNew(STextBlock) + .Text(FText::FromString(TEXT( + "Return to Cesium for Unreal and try adding this asset again"))) + ] + + SVerticalBox::Slot() + .AutoHeight() + .HAlign(EHorizontalAlignment::HAlign_Center) + .Padding(10.0f, 25.0f) + [ + SNew(SButton) + .OnClicked_Lambda( + [&AssetDepotConfirmWindow]() { + AssetDepotConfirmWindow + ->RequestDestroyWindow(); + return FReply::Handled(); + }) + .Text(FText::FromString(TEXT("Close"))) + ] + ]; + // clang-format on + GEditor->EditorAddModalWindow(AssetDepotConfirmWindow); +} +} // namespace + +void IonQuickAddPanel::AddIonTilesetToLevel(TSharedRef item) { + const std::optional& connection = + FCesiumEditorModule::serverManager().GetCurrentSession()->getConnection(); + if (!connection) { + UE_LOG( + LogCesiumEditor, + Warning, + TEXT("Cannot add an ion asset without an active connection")); + return; + } + + std::vector assetIDs{item->tilesetID}; + if (item->overlayID > 0) { + assetIDs.push_back(item->overlayID); + } + + SelectCesiumIonToken::SelectAndAuthorizeToken( + FCesiumEditorModule::serverManager().GetCurrentServer(), + assetIDs) + .thenInMainThread([connection, tilesetID = item->tilesetID]( + const std::optional& /*maybeToken*/) { + // If token selection was canceled, or if an error occurred while + // selecting the token, ignore it and create the tileset anyway. It's + // already been logged if necessary, and we can let the user sort out + // the problem using the resulting Troubleshooting panel. + return connection->asset(tilesetID); + }) + .thenInMainThread([item, connection](Response&& response) { + if (!response.value.has_value()) { + return connection->getAsyncSystem().createResolvedFuture( + std::move(int64_t(item->tilesetID))); + } + + if (item->overlayID >= 0) { + return connection->asset(item->overlayID) + .thenInMainThread([item](Response&& overlayResponse) { + return overlayResponse.value.has_value() + ? int64_t(-1) + : int64_t(item->overlayID); + }); + } else { + return connection->getAsyncSystem().createResolvedFuture(-1); + } + }) + .thenInMainThread([this, item](int64_t missingAsset) { + if (missingAsset != -1) { + FString itemName(UTF8_TO_TCHAR(item->name.c_str())); + showAssetDepotConfirmWindow(itemName, missingAsset); + } else { + ACesium3DTileset* pTileset = + FCesiumEditorModule::FindFirstTilesetWithAssetID(item->tilesetID); + if (!pTileset) { + pTileset = FCesiumEditorModule::CreateTileset( + item->tilesetName, + item->tilesetID); + } + + FCesiumEditorModule::serverManager().GetCurrentSession()->getAssets(); + + if (item->overlayID > 0) { + FCesiumEditorModule::AddBaseOverlay( + pTileset, + item->overlayName, + item->overlayID); + } + + pTileset->RerunConstructionScripts(); + + GEditor->SelectNone(true, false); + GEditor->SelectActor(pTileset, true, true, true, true); + } + + this->_itemsBeingAdded.erase(item->name); + }); +} + +void IonQuickAddPanel::AddCesiumSunSkyToLevel() { + AActor* pActor = FCesiumEditorModule::GetCurrentLevelCesiumSunSky(); + if (!pActor) { + pActor = FCesiumEditorModule::SpawnCesiumSunSky(); + } + + if (pActor) { + GEditor->SelectNone(true, false); + GEditor->SelectActor(pActor, true, true, true, true); + } +} + +namespace { +/** + * Set a byte property value in the given object. + * + * This will search the class of the given object for a property + * with the given name, which is assumed to be a byte property, + * and assign the given value to this property. + * + * If the object is `nullptr`, nothing will be done. + * If the class does not contain a property with the given name, + * or it is not a byte property, a warning will be printed. + * + * @param object The object to set the value in + * @param name The name of the property + * @param value The value to set for the property. + */ +void SetBytePropertyValue( + UObjectBase* object, + const std::string& name, + uint8 value) { + if (!object) { + return; + } + UClass* cls = object->GetClass(); + FString nameString(name.c_str()); + FName propName = FName(*nameString); + FProperty* property = cls->FindPropertyByName(propName); + if (!property) { + UE_LOG( + LogCesiumEditor, + Warning, + TEXT("Property with name %s not found"), + *nameString); + return; + } + FByteProperty* byteProperty = CastField(property); + if (!byteProperty) { + UE_LOG( + LogCesiumEditor, + Warning, + TEXT("Property is not an FByteProperty: %s"), + *nameString); + return; + } + byteProperty->SetPropertyValue_InContainer(object, value); +} +} // namespace + +void IonQuickAddPanel::AddDynamicPawnToLevel() { + AActor* pActor = FCesiumEditorModule::GetCurrentLevelDynamicPawn(); + if (!pActor) { + pActor = FCesiumEditorModule::SpawnDynamicPawn(); + } + + if (pActor) { + uint8 autoPossessValue = + static_cast(EAutoReceiveInput::Type::Player0); + SetBytePropertyValue(pActor, "AutoPossessPlayer", autoPossessValue); + + GEditor->SelectNone(true, false); + GEditor->SelectActor(pActor, true, true, true, true); + } +} + +void IonQuickAddPanel::AddItemToLevel(TSharedRef item) { + if (this->_itemsBeingAdded.find(item->name) != this->_itemsBeingAdded.end()) { + // Add is already in progress. + return; + } + this->_itemsBeingAdded.insert(item->name); + + if (item->type == QuickAddItemType::TILESET) { + + // The blank tileset (identified by the tileset and overlay ID being -1) + // can be added directly. All ion tilesets are added via + // AddIonTilesetToLevel, which requires an active connection. + bool isBlankTileset = item->type == QuickAddItemType::TILESET && + item->tilesetID == -1 && item->overlayID == -1; + if (isBlankTileset) { + FCesiumEditorModule::SpawnBlankTileset(); + this->_itemsBeingAdded.erase(item->name); + } else { + AddIonTilesetToLevel(item); + } + } else if (item->type == QuickAddItemType::SUNSKY) { + AddCesiumSunSkyToLevel(); + this->_itemsBeingAdded.erase(item->name); + } else if (item->type == QuickAddItemType::DYNAMIC_PAWN) { + AddDynamicPawnToLevel(); + this->_itemsBeingAdded.erase(item->name); + } else if (item->type == QuickAddItemType::CARTOGRAPHIC_POLYGON) { + FCesiumEditorModule::SpawnCartographicPolygon(); + this->_itemsBeingAdded.erase(item->name); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonQuickAddPanel.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonQuickAddPanel.h new file mode 100644 index 0000000..e248cfc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonQuickAddPanel.h @@ -0,0 +1,61 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Widgets/SCompoundWidget.h" +#include "Widgets/Views/STableRow.h" +#include +#include + +class FArguments; + +enum class QuickAddItemType { + TILESET, + SUNSKY, + DYNAMIC_PAWN, + CARTOGRAPHIC_POLYGON +}; + +struct QuickAddItem { + QuickAddItemType type; + std::string name{}; + std::string description; + std::string tilesetName{}; + int64_t tilesetID = -1; + std::string overlayName{}; + int64_t overlayID = -1; +}; + +class IonQuickAddPanel : public SCompoundWidget { + SLATE_BEGIN_ARGS(IonQuickAddPanel) {} + /** + * The tile shown over the elements of the list + */ + SLATE_ARGUMENT(FText, Title) + SLATE_END_ARGS() + + void Construct(const FArguments& InArgs); + + void AddItem(const QuickAddItem& item); + void ClearItems(); + void Refresh(); + + const FText& GetMessage() const; + void SetMessage(const FText& message); + +private: + TSharedRef QuickAddList(); + TSharedRef CreateQuickAddItemRow( + TSharedRef item, + const TSharedRef& list); + + void AddItemToLevel(TSharedRef item); + void AddIonTilesetToLevel(TSharedRef item); + void AddCesiumSunSkyToLevel(); + void AddDynamicPawnToLevel(); + + TArray> _quickAddItems; + std::unordered_set _itemsBeingAdded; + TSharedPtr>> _pQuickAddList; + FText _message; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/SelectCesiumIonToken.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/SelectCesiumIonToken.cpp new file mode 100644 index 0000000..57a3031 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/SelectCesiumIonToken.cpp @@ -0,0 +1,621 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "SelectCesiumIonToken.h" +#include "Cesium3DTileset.h" +#include "CesiumEditor.h" +#include "CesiumIonRasterOverlay.h" +#include "CesiumIonServerDisplay.h" +#include "CesiumRuntime.h" +#include "CesiumRuntimeSettings.h" +#include "CesiumSourceControl.h" +#include "CesiumUtility/joinToString.h" +#include "Editor.h" +#include "EditorStyleSet.h" +#include "EngineUtils.h" +#include "Framework/Application/SlateApplication.h" +#include "Misc/App.h" +#include "PropertyCustomizationHelpers.h" +#include "Runtime/Launch/Resources/Version.h" +#include "ScopedTransaction.h" +#include "Widgets/Images/SThrobber.h" +#include "Widgets/Input/SButton.h" +#include "Widgets/Input/SCheckBox.h" +#include "Widgets/Input/SEditableTextBox.h" +#include "Widgets/Layout/SBorder.h" +#include "Widgets/Text/STextBlock.h" + +using namespace CesiumAsync; +using namespace CesiumIonClient; +using namespace CesiumUtility; + +/*static*/ TSharedPtr + SelectCesiumIonToken::_pExistingPanel{}; + +/*static*/ SharedFuture> +SelectCesiumIonToken::SelectNewToken(UCesiumIonServer* pServer) { + std::shared_ptr pSession = + FCesiumEditorModule::serverManager().GetSession(pServer); + // If the current server doesn't require tokens, don't bother opening the + // window to create one. + if (!pSession->isAuthenticationRequired()) { + return getAsyncSystem() + .createResolvedFuture(std::optional(Token())) + .share(); + } + + if (SelectCesiumIonToken::_pExistingPanel.IsValid()) { + SelectCesiumIonToken::_pExistingPanel->BringToFront(); + } else { + TSharedRef Panel = + SNew(SelectCesiumIonToken).Server(pServer); + SelectCesiumIonToken::_pExistingPanel = Panel; + + Panel->_promise = getAsyncSystem().createPromise>(); + Panel->_future = Panel->_promise->getFuture().share(); + + Panel->GetOnWindowClosedEvent().AddLambda( + [Panel](const TSharedRef& pWindow) { + if (Panel->_promise) { + // Promise is still outstanding, so resolve it now (no token was + // selected). + Panel->_promise->resolve(std::nullopt); + } + SelectCesiumIonToken::_pExistingPanel.Reset(); + }); + FSlateApplication::Get().AddWindow(Panel); + } + + return *SelectCesiumIonToken::_pExistingPanel->_future; +} + +Future> +SelectCesiumIonToken::SelectTokenIfNecessary(UCesiumIonServer* pServer) { + return FCesiumEditorModule::serverManager() + .GetSession(pServer) + ->getProjectDefaultTokenDetails() + .thenInMainThread([pServer](const Token& token) { + if (token.token.empty()) { + return SelectCesiumIonToken::SelectNewToken(pServer).thenImmediately( + [](const std::optional& maybeToken) { + return maybeToken; + }); + } else { + return getAsyncSystem().createResolvedFuture( + std::make_optional(token)); + } + }); +} + +namespace { + +std::vector findUnauthorizedAssets( + const std::vector& authorizedAssets, + const std::vector& requiredAssets) { + std::vector missingAssets; + + for (int64_t assetID : requiredAssets) { + auto it = + std::find(authorizedAssets.begin(), authorizedAssets.end(), assetID); + if (it == authorizedAssets.end()) { + missingAssets.emplace_back(assetID); + } + } + + return missingAssets; +} + +} // namespace + +Future> SelectCesiumIonToken::SelectAndAuthorizeToken( + UCesiumIonServer* pServer, + const std::vector& assetIDs) { + std::shared_ptr pSession = + FCesiumEditorModule::serverManager().GetSession(pServer); + // If the current server doesn't require tokens, don't try to create or + // authorize one. + if (!pSession->isAuthenticationRequired()) { + return getAsyncSystem().createResolvedFuture(std::optional(Token())); + } + + return SelectTokenIfNecessary(pServer).thenInMainThread([pSession, assetIDs]( + const std::optional< + Token>& + maybeToken) { + const std::optional& maybeConnection = + pSession->getConnection(); + if (maybeConnection && maybeToken && !maybeToken->id.empty() && + maybeToken->assetIds) { + std::vector missingAssets = + findUnauthorizedAssets(*maybeToken->assetIds, assetIDs); + if (!missingAssets.empty()) { + // Refresh the token details. We don't want to update the token based + // on stale information. + return maybeConnection->token(maybeToken->id) + .thenInMainThread([pSession, maybeToken, assetIDs]( + Response&& response) { + if (response.value) { + std::vector missingAssets = + findUnauthorizedAssets(*maybeToken->assetIds, assetIDs); + if (!missingAssets.empty()) { + std::vector idStrings(missingAssets.size()); + std::transform( + missingAssets.begin(), + missingAssets.end(), + idStrings.begin(), + [](int64_t id) { return std::to_string(id); }); + UE_LOG( + LogCesiumEditor, + Warning, + TEXT( + "Authorizing the project's default Cesium ion token to access the following asset IDs: %s"), + UTF8_TO_TCHAR(joinToString(idStrings, ", ").c_str())); + + Token newToken = *maybeToken; + size_t destinationIndex = newToken.assetIds->size(); + newToken.assetIds->resize( + newToken.assetIds->size() + missingAssets.size()); + std::copy( + missingAssets.begin(), + missingAssets.end(), + newToken.assetIds->begin() + destinationIndex); + + return pSession->getConnection() + ->modifyToken( + newToken.id, + newToken.name, + newToken.assetIds, + newToken.scopes, + newToken.allowedUrls) + .thenImmediately([maybeToken](Response&&) { + return maybeToken; + }); + } + } + + return getAsyncSystem().createResolvedFuture( + std::optional(maybeToken)); + }); + } + } + + return getAsyncSystem().createResolvedFuture( + std::optional(maybeToken)); + }); +} + +void SelectCesiumIonToken::Construct(const FArguments& InArgs) { + UCesiumIonServer* pServer = InArgs._Server; + + if (this->_pServer.IsValid() && + this->_tokensUpdatedDelegateHandle.IsValid()) { + FCesiumEditorModule::serverManager() + .GetSession(this->_pServer.Get()) + ->TokensUpdated.Remove(this->_tokensUpdatedDelegateHandle); + } + + this->_pServer = pServer; + std::shared_ptr pSession = + FCesiumEditorModule::serverManager().GetSession(this->_pServer.Get()); + + this->_tokensUpdatedDelegateHandle = pSession->TokensUpdated.AddRaw( + this, + &SelectCesiumIonToken::RefreshTokens); + + TSharedRef pLoaderOrContent = + SNew(SVerticalBox).Visibility_Lambda([pSession]() { + return pSession->getAppData().needsOauthAuthentication() + ? EVisibility::Visible + : EVisibility::Collapsed; + }); + + TSharedRef pSingleUserText = + SNew(SVerticalBox).Visibility_Lambda([pSession]() { + return !pSession->getAppData().needsOauthAuthentication() + ? EVisibility::Visible + : EVisibility::Collapsed; + }); + + pSingleUserText->AddSlot().AutoHeight() + [SNew(STextBlock) + .AutoWrapText(true) + .Text(FText::FromString(TEXT( + "Cesium for Unreal is currently connected to a Cesium ion server running in single-user authentication mode. Tokens are not used in this mode.")))]; + + pLoaderOrContent->AddSlot().AutoHeight() + [SNew(STextBlock) + .AutoWrapText(true) + .Text(FText::FromString(TEXT( + "Cesium for Unreal embeds a Cesium ion token in your project in order to allow it to access the assets you add to your levels. Select the Cesium ion token to use.")))]; + + pLoaderOrContent->AddSlot().AutoHeight().Padding( + 5.0f)[SNew(CesiumIonServerDisplay).Server(pServer)]; + + pLoaderOrContent->AddSlot() + .Padding(0.0f, 10.0f, 0.0, 10.0f) + .AutoHeight() + [SNew(STextBlock) + .Visibility_Lambda([pSession]() { + return pSession->isConnected() ? EVisibility::Collapsed + : EVisibility::Visible; + }) + .AutoWrapText(true) + .Text(FText::FromString(TEXT( + "Please connect to Cesium ion to select a token from your account or to create a new token.")))]; + + pLoaderOrContent->AddSlot() + .AutoHeight()[SNew(SThrobber).Visibility_Lambda([pSession]() { + return pSession->isLoadingTokenList() ? EVisibility::Visible + : EVisibility::Collapsed; + })]; + + TSharedRef pMainVerticalBox = + SNew(SVerticalBox).Visibility_Lambda([pSession]() { + return pSession->isLoadingTokenList() ? EVisibility::Collapsed + : EVisibility::Visible; + }); + pLoaderOrContent->AddSlot().AutoHeight()[pMainVerticalBox]; + + this->_createNewToken.name = + FString(FApp::GetProjectName()) + TEXT(" (Created by Cesium for Unreal)"); + this->_useExistingToken.token.id = + TCHAR_TO_UTF8(*pServer->DefaultIonAccessTokenId); + this->_useExistingToken.token.token = + TCHAR_TO_UTF8(*pServer->DefaultIonAccessToken); + this->_specifyToken.token = pServer->DefaultIonAccessToken; + this->_tokenSource = + pServer->DefaultIonAccessToken.IsEmpty() && pSession->isConnected() + ? TokenSource::Create + : TokenSource::Specify; + + this->createRadioButton( + pSession, + pMainVerticalBox, + this->_tokenSource, + TokenSource::Create, + TEXT("Create a new token"), + true, + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .VAlign(EVerticalAlignment::VAlign_Center) + .AutoWidth() + .Padding(5.0f)[SNew(STextBlock) + .Text(FText::FromString(TEXT("Name:")))] + + SHorizontalBox::Slot() + .VAlign(EVerticalAlignment::VAlign_Center) + .AutoWidth() + .MaxWidth(500.0f) + .Padding( + 5.0f)[SNew(SEditableTextBox) + .Text(this, &SelectCesiumIonToken::GetNewTokenName) + .MinDesiredWidth(200.0f) + .OnTextChanged( + this, + &SelectCesiumIonToken::SetNewTokenName)]); + + SAssignNew(this->_pTokensCombo, SComboBox>) + .OptionsSource(&this->_tokens) + .OnGenerateWidget( + this, + &SelectCesiumIonToken::OnGenerateTokenComboBoxEntry) + .OnSelectionChanged(this, &SelectCesiumIonToken::OnSelectExistingToken) + .Content()[SNew(STextBlock).MinDesiredWidth(200.0f).Text_Lambda([this]() { + return this->_pTokensCombo.IsValid() && + this->_pTokensCombo->GetSelectedItem().IsValid() + ? FText::FromString(UTF8_TO_TCHAR( + this->_pTokensCombo->GetSelectedItem()->name.c_str())) + : FText::FromString(TEXT("")); + })]; + + this->createRadioButton( + pSession, + pMainVerticalBox, + this->_tokenSource, + TokenSource::UseExisting, + TEXT("Use an existing token"), + true, + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .VAlign(EVerticalAlignment::VAlign_Center) + .AutoWidth() + .MaxWidth(500.0f) + .Padding(5.0f)[SNew(STextBlock) + .Text(FText::FromString(TEXT("Token:")))] + + SHorizontalBox::Slot() + .VAlign(EVerticalAlignment::VAlign_Center) + .Padding(5.0f) + .AutoWidth()[this->_pTokensCombo.ToSharedRef()]); + + this->createRadioButton( + pSession, + pMainVerticalBox, + this->_tokenSource, + TokenSource::Specify, + TEXT("Specify a token"), + false, + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .VAlign(EVerticalAlignment::VAlign_Center) + .AutoWidth() + .Padding(5.0f)[SNew(STextBlock) + .Text(FText::FromString(TEXT("Token:")))] + + SHorizontalBox::Slot() + .VAlign(EVerticalAlignment::VAlign_Center) + .Padding(5.0f) + .AutoWidth() + .MaxWidth(500.0f) + [SNew(SEditableTextBox) + .Text(this, &SelectCesiumIonToken::GetSpecifiedToken) + .OnTextChanged( + this, + &SelectCesiumIonToken::SetSpecifiedToken) + .MinDesiredWidth(500.0f)]); + + pMainVerticalBox->AddSlot().AutoHeight().Padding( + 5.0f, + 20.0f, + 5.0f, + 5.0f)[SNew(SButton) + .ButtonStyle(FCesiumEditorModule::GetStyle(), "CesiumButton") + .TextStyle(FCesiumEditorModule::GetStyle(), "CesiumButtonText") + .Visibility_Lambda([this]() { + return this->_tokenSource == TokenSource ::Create + ? EVisibility::Collapsed + : EVisibility::Visible; + }) + .OnClicked(this, &SelectCesiumIonToken::UseOrCreate, pSession) + .Text(FText::FromString(TEXT("Use as Project Default Token")))]; + + pMainVerticalBox->AddSlot().AutoHeight().Padding( + 5.0f, + 20.0f, + 5.0f, + 5.0f)[SNew(SButton) + .ButtonStyle(FCesiumEditorModule::GetStyle(), "CesiumButton") + .TextStyle(FCesiumEditorModule::GetStyle(), "CesiumButtonText") + .Visibility_Lambda([this]() { + return this->_tokenSource == TokenSource ::Create + ? EVisibility::Visible + : EVisibility::Collapsed; + }) + .OnClicked(this, &SelectCesiumIonToken::UseOrCreate, pSession) + .Text(FText::FromString( + TEXT("Create New Project Default Token")))]; + + TSharedRef totalBox = SNew(SVerticalBox); + + totalBox->AddSlot().AutoHeight()[pLoaderOrContent]; + totalBox->AddSlot().AutoHeight()[pSingleUserText]; + + SWindow::Construct( + SWindow::FArguments() + .Title(FText::FromString(TEXT("Select a Cesium ion Token"))) + .AutoCenter(EAutoCenter::PreferredWorkArea) + .SizingRule(ESizingRule::UserSized) + .ClientSize(FVector2D( + 635, + 500))[SNew(SBorder) + .Visibility(EVisibility::Visible) + .Padding( + FMargin(10.0f, 10.0f, 10.0f, 10.0f))[totalBox]]); + + pSession->refreshTokens(); +} + +void SelectCesiumIonToken::createRadioButton( + const std::shared_ptr& pSession, + const TSharedRef& pVertical, + TokenSource& tokenSource, + TokenSource thisValue, + const FString& label, + bool requiresIonConnection, + const TSharedRef& pWidget) { + auto visibility = [pSession, requiresIonConnection]() { + if (!requiresIonConnection) { + return EVisibility::Visible; + } else if (pSession->isConnected()) { + return EVisibility::Visible; + } else { + return EVisibility::Collapsed; + } + }; + + pVertical->AddSlot().AutoHeight().Padding(5.0f, 10.0f, 5.0f, 10.0f) + [SNew(SCheckBox) + .Visibility_Lambda(visibility) + .Padding(5.0f) + .Style(FAppStyle::Get(), "RadioButton") + .IsChecked_Lambda([&tokenSource, thisValue]() { + return tokenSource == thisValue ? ECheckBoxState::Checked + : ECheckBoxState::Unchecked; + }) + .OnCheckStateChanged_Lambda([&tokenSource, + thisValue](ECheckBoxState newState) { + if (newState == ECheckBoxState::Checked) { + tokenSource = thisValue; + } + })[SNew(SBorder) + [SNew(SVerticalBox) + + SVerticalBox::Slot().Padding(5.0f).AutoHeight() + [SNew(STextBlock) + .TextStyle( + FCesiumEditorModule::GetStyle(), + "BodyBold") + .Text(FText::FromString(label))] + + SVerticalBox::Slot().Padding(5.0f).AutoHeight()[pWidget]]]]; +} + +FReply +SelectCesiumIonToken::UseOrCreate(std::shared_ptr pSession) { + if (!this->_promise || !this->_future) { + return FReply::Handled(); + } + + Promise> promise = std::move(*this->_promise); + this->_promise.reset(); + + TSharedRef pPanel = + StaticCastSharedRef(this->AsShared()); + + auto getToken = [pPanel, pSession]() { + const AsyncSystem& asyncSystem = getAsyncSystem(); + + if (pPanel->_tokenSource == TokenSource::Create) { + if (pPanel->_createNewToken.name.IsEmpty()) { + return asyncSystem.createResolvedFuture(Response()); + } + + // Create a new token, initially only with access to asset ID 1 (Cesium + // World Terrain). + return pSession->getConnection()->createToken( + TCHAR_TO_UTF8(*pPanel->_createNewToken.name), + {"assets:read"}, + std::vector{1}, + std::nullopt); + } else if (pPanel->_tokenSource == TokenSource::UseExisting) { + return asyncSystem.createResolvedFuture( + Response(Token(pPanel->_useExistingToken.token), 200, "", "")); + } else if (pPanel->_tokenSource == TokenSource::Specify) { + // Check if this is a known token, and use it if so. + return pSession->findToken(pPanel->_specifyToken.token) + .thenInMainThread([pPanel](Response&& response) { + if (response.value) { + return std::move(response); + } else { + Token t; + t.token = TCHAR_TO_UTF8(*pPanel->_specifyToken.token); + return Response(std::move(t), 200, "", ""); + } + }); + } else { + return asyncSystem.createResolvedFuture( + Response(0, "UNKNOWNSOURCE", "The token source is unknown.")); + } + }; + + getToken().thenInMainThread([pPanel, pSession, promise = std::move(promise)]( + Response&& response) { + if (response.value) { + pSession->invalidateProjectDefaultTokenDetails(); + + UCesiumIonServer* pServer = pPanel->_pServer.Get(); + + FScopedTransaction transaction( + FText::FromString("Set Project Default Token")); + pServer->DefaultIonAccessTokenId = + UTF8_TO_TCHAR(response.value->id.c_str()); + pServer->DefaultIonAccessToken = + UTF8_TO_TCHAR(response.value->token.c_str()); + pServer->Modify(); + + // Refresh all tilesets and overlays that are using the project + // default token. + UWorld* pWorld = GEditor->GetEditorWorldContext().World(); + for (auto it = TActorIterator(pWorld); it; ++it) { + if (it->GetTilesetSource() == ETilesetSource::FromCesiumIon && + it->GetIonAccessToken().IsEmpty() && + it->GetCesiumIonServer() == pServer) { + it->RefreshTileset(); + } else { + // Tileset itself does not need to be refreshed, but maybe some + // overlays do. + TArray rasterOverlays; + it->GetComponents(rasterOverlays); + + for (UCesiumIonRasterOverlay* pOverlay : rasterOverlays) { + if (pOverlay->IonAccessToken.IsEmpty() && + pOverlay->CesiumIonServer == pServer) { + pOverlay->Refresh(); + } + } + } + } + } else { + UE_LOG( + LogCesiumEditor, + Error, + TEXT("An error occurred while selecting a token: %s"), + UTF8_TO_TCHAR(response.errorMessage.c_str())); + } + + promise.resolve(std::move(response.value)); + + pPanel->RequestDestroyWindow(); + }); + + while (!this->_future->isReady()) { + getAssetAccessor()->tick(); + getAsyncSystem().dispatchMainThreadTasks(); + } + + return FReply::Handled(); +} + +void SelectCesiumIonToken::RefreshTokens() { + const std::vector& tokens = FCesiumEditorModule::serverManager() + .GetSession(this->_pServer.Get()) + ->getTokens(); + this->_tokens.SetNum(tokens.size()); + + std::string createName = TCHAR_TO_UTF8(*this->_createNewToken.name); + std::string specifiedToken = TCHAR_TO_UTF8(*this->_specifyToken.token); + + for (size_t i = 0; i < tokens.size(); ++i) { + if (this->_tokens[i]) { + *this->_tokens[i] = std::move(tokens[i]); + } else { + this->_tokens[i] = MakeShared(std::move(tokens[i])); + } + + if (this->_tokens[i]->id == this->_useExistingToken.token.id) { + this->_pTokensCombo->SetSelectedItem(this->_tokens[i]); + this->_tokenSource = TokenSource::UseExisting; + } + + // If there's already a token with the default name we would use to create a + // new one, default to selecting that rather than creating a new one. + if (this->_tokenSource == TokenSource::Create && + this->_tokens[i]->name == createName) { + this->_pTokensCombo->SetSelectedItem(this->_tokens[i]); + this->_tokenSource = TokenSource::UseExisting; + } + + // If this happens to be the specified token, select it. + if (this->_tokenSource == TokenSource::Specify && + this->_tokens[i]->token == specifiedToken) { + this->_pTokensCombo->SetSelectedItem(this->_tokens[i]); + this->_tokenSource = TokenSource::UseExisting; + } + } + + this->_pTokensCombo->RefreshOptions(); +} + +TSharedRef SelectCesiumIonToken::OnGenerateTokenComboBoxEntry( + TSharedPtr pToken) { + return SNew(STextBlock) + .Text(FText::FromString(UTF8_TO_TCHAR(pToken->name.c_str()))); +} + +FText SelectCesiumIonToken::GetNewTokenName() const { + return FText::FromString(this->_createNewToken.name); +} + +void SelectCesiumIonToken::SetNewTokenName(const FText& text) { + this->_createNewToken.name = text.ToString(); +} + +void SelectCesiumIonToken::OnSelectExistingToken( + TSharedPtr pToken, + ESelectInfo::Type type) { + if (pToken) { + this->_useExistingToken.token = *pToken; + } +} + +FText SelectCesiumIonToken::GetSpecifiedToken() const { + return FText::FromString(this->_specifyToken.token); +} + +void SelectCesiumIonToken::SetSpecifiedToken(const FText& text) { + this->_specifyToken.token = text.ToString(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/SelectCesiumIonToken.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/SelectCesiumIonToken.h new file mode 100644 index 0000000..3ac32ad --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/SelectCesiumIonToken.h @@ -0,0 +1,115 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumAsync/AsyncSystem.h" +#include "CesiumIonClient/Token.h" +#include "Widgets/Input/SComboBox.h" +#include "Widgets/SWindow.h" +#include +#include +#include + +class UCesiumIonServer; +class CesiumIonSession; + +class SelectCesiumIonToken : public SWindow { + SLATE_BEGIN_ARGS(SelectCesiumIonToken) {} + SLATE_ARGUMENT(UCesiumIonServer*, Server) + SLATE_END_ARGS() + +public: + /** + * Opens a panel to allow the user to select a new token. + * + * @return A future that resolves when the panel is closed. It resolves to the + * selected token if there was one, or to std::nullopt if the panel was closed + * without selecting a token. + */ + static CesiumAsync::SharedFuture> + SelectNewToken(UCesiumIonServer* pServer); + + /** + * Opens a panel to allow the user to select a new token if a project default + * token is not already set. If the project default token _is_ set, the future + * immediately resolves to the previously-set token. + * + * @return A future that resolves when the panel is closed or when it does not + * need to be opened in the first place. It resolves to the selected token if + * there was one, or to std::nullopt if the panel was closed without selecting + * a token. + */ + static CesiumAsync::Future> + SelectTokenIfNecessary(UCesiumIonServer* pServer); + + /** + * Authorizes the project default token to access a list of asset IDs. If the + * project default token is not set, a panel is opened to allow the token to + * be selected. Then, if possible, the token is modified to allow access to + * the list of asset IDs. + * + * @param assetIDs The asset IDs to be accessed. + * @return A future that resolves when the panel is closed or when it does not + * need to be opened in the first place. It resolves to the selected token if + * there was one, or to std::nullopt if the panel was closed without selecting + * a token. + */ + static CesiumAsync::Future> + SelectAndAuthorizeToken( + UCesiumIonServer* pServer, + const std::vector& assetIDs); + + void Construct(const FArguments& InArgs); + +private: + enum class TokenSource { Create, UseExisting, Specify }; + + struct CreateNewToken { + FString name; + }; + + struct UseExistingToken { + CesiumIonClient::Token token; + }; + + struct SpecifyToken { + FString token; + }; + + void createRadioButton( + const std::shared_ptr& pSession, + const TSharedRef& pVertical, + TokenSource& tokenSource, + TokenSource thisValue, + const FString& label, + bool requiresIonConnection, + const TSharedRef& pWidget); + FReply UseOrCreate(std::shared_ptr pSession); + void RefreshTokens(); + TSharedRef + OnGenerateTokenComboBoxEntry(TSharedPtr pToken); + FText GetNewTokenName() const; + void SetNewTokenName(const FText& text); + void OnSelectExistingToken( + TSharedPtr pToken, + ESelectInfo::Type type); + FText GetSpecifiedToken() const; + void SetSpecifiedToken(const FText& text); + + static TSharedPtr _pExistingPanel; + + std::optional>> + _promise; + std::optional< + CesiumAsync::SharedFuture>> + _future; + + TokenSource _tokenSource = TokenSource::Create; + CreateNewToken _createNewToken; + UseExistingToken _useExistingToken; + SpecifyToken _specifyToken; + FDelegateHandle _tokensUpdatedDelegateHandle; + TArray> _tokens; + TSharedPtr>> _pTokensCombo; + TWeakObjectPtr _pServer; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/CesiumRuntime.Build.cs b/Plugins/CesiumForUnreal/Source/CesiumRuntime/CesiumRuntime.Build.cs new file mode 100644 index 0000000..56ac39d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/CesiumRuntime.Build.cs @@ -0,0 +1,156 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +using UnrealBuildTool; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +public class CesiumRuntime : ModuleRules +{ + public CesiumRuntime(ReadOnlyTargetRules Target) : base(Target) + { + PublicIncludePaths.AddRange( + new string[] { + Path.Combine(ModuleDirectory, "../ThirdParty/include") + } + ); + + PrivateIncludePaths.AddRange( + new string[] { + Path.Combine(GetModuleDirectory("Renderer"), "Private") + } + ); + + string platform; + string libSearchPattern; + if (Target.Platform == UnrealTargetPlatform.Win64) + { + platform = "Windows-AMD64-"; + libSearchPattern = "*.lib"; + } + else if (Target.Platform == UnrealTargetPlatform.Mac) + { + platform = "Darwin-universal-"; + libSearchPattern = "lib*.a"; + } + else if (Target.Platform == UnrealTargetPlatform.Android) + { + platform = "Android-aarch64-"; + libSearchPattern = "lib*.a"; + } + else if (Target.Platform == UnrealTargetPlatform.Linux) + { + platform = "Linux-x86_64-"; + libSearchPattern = "lib*.a"; + } + else if(Target.Platform == UnrealTargetPlatform.IOS) + { + platform = "iOS-ARM64-"; + libSearchPattern = "lib*.a"; + } + else + { + throw new InvalidOperationException("Cesium for Unreal does not support this platform."); + } + + string libPathBase = Path.Combine(ModuleDirectory, "../ThirdParty/lib/" + platform); + string libPathDebug = libPathBase + "Debug"; + string libPathRelease = libPathBase + "Release"; + + bool useDebug = false; + if (Target.Configuration == UnrealTargetConfiguration.Debug || Target.Configuration == UnrealTargetConfiguration.DebugGame) + { + if (Directory.Exists(libPathDebug)) + { + useDebug = true; + } + } + + string libPath = useDebug ? libPathDebug : libPathRelease; + + string[] allLibs = Directory.Exists(libPath) ? Directory.GetFiles(libPath, libSearchPattern) : new string[0]; + + PublicAdditionalLibraries.AddRange(allLibs); + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "RHI", + "CoreUObject", + "Engine", + "MeshDescription", + "StaticMeshDescription", + "HTTP", + "LevelSequence", + "Projects", + "RenderCore", + "SunPosition", + "DeveloperSettings", + "UMG", + "Renderer", + "OpenSSL" + } + ); + + // Use UE's MikkTSpace on most platforms, except Android and iOS. + // On those platforms, UE's isn't available, so we use our own. + if (Target.Platform != UnrealTargetPlatform.Android && Target.Platform != UnrealTargetPlatform.IOS) + { + PrivateDependencyModuleNames.Add("MikkTSpace"); + } + else + { + PrivateIncludePaths.Add(Path.Combine(ModuleDirectory, "../ThirdParty/include/mikktspace")); + } + + PublicDefinitions.AddRange( + new string[] + { + "SPDLOG_COMPILED_LIB", + "LIBASYNC_STATIC", + "GLM_FORCE_XYZW_ONLY", + "GLM_FORCE_EXPLICIT_CTOR", + "GLM_FORCE_SIZE_T_LENGTH", + "TIDY_STATIC", + "URI_STATIC_BUILD", + "SWL_VARIANT_NO_CONSTEXPR_EMPLACE", + // Define to record the state of every tile, every frame, to a SQLite database. + // The database will be found in [Project Dir]/Saved/CesiumDebugTileStateDatabase. + // "CESIUM_DEBUG_TILE_STATES", + } + ); + + PrivateDependencyModuleNames.Add("Chaos"); + + if (Target.bBuildEditor == true) + { + PublicDependencyModuleNames.AddRange( + new string[] { + "UnrealEd", + "Slate", + "SlateCore", + "WorldBrowser", + "ContentBrowser", + "MaterialEditor" + } + ); + } + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + + ShadowVariableWarningLevel = WarningLevel.Off; + IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_2; + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + + CppStandard = CppStandardVersion.Cpp20; + bEnableExceptions = true; + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CalcBounds.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CalcBounds.cpp new file mode 100644 index 0000000..aa554ec --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CalcBounds.cpp @@ -0,0 +1,78 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CalcBounds.h" +#include "VecMath.h" +#include +#include + +glm::dmat4 CalcBoundsOperation::getModelToUnrealWorldMatrix() const { + const FMatrix matrix = localToWorld.ToMatrixWithScale(); + return VecMath::createMatrix4D(matrix); +} + +glm::dmat4 CalcBoundsOperation::getTilesetToUnrealWorldMatrix() const { + const glm::dmat4 modelToUnreal = getModelToUnrealWorldMatrix(); + const glm::dmat4 tilesetToModel = glm::affineInverse(highPrecisionTransform); + return modelToUnreal * tilesetToModel; +} + +FBoxSphereBounds CalcBoundsOperation::operator()( + const CesiumGeometry::BoundingSphere& sphere) const { + glm::dmat4 matrix = getTilesetToUnrealWorldMatrix(); + glm::dvec3 center = glm::dvec3(matrix * glm::dvec4(sphere.getCenter(), 1.0)); + glm::dmat3 halfAxes = glm::dmat3(matrix) * glm::dmat3(sphere.getRadius()); + + // The sphere only needs to reach the sides of the box, not the corners. + double sphereRadius = + glm::max(glm::length(halfAxes[0]), glm::length(halfAxes[1])); + sphereRadius = glm::max(sphereRadius, glm::length(halfAxes[2])); + + FBoxSphereBounds result; + result.Origin = VecMath::createVector(center); + result.SphereRadius = sphereRadius; + result.BoxExtent = FVector(sphereRadius, sphereRadius, sphereRadius); + return result; +} + +FBoxSphereBounds CalcBoundsOperation::operator()( + const CesiumGeometry::OrientedBoundingBox& box) const { + glm::dmat4 matrix = getTilesetToUnrealWorldMatrix(); + glm::dvec3 center = glm::dvec3(matrix * glm::dvec4(box.getCenter(), 1.0)); + glm::dmat3 halfAxes = glm::dmat3(matrix) * box.getHalfAxes(); + + glm::dvec3 corner1 = halfAxes[0] + halfAxes[1]; + glm::dvec3 corner2 = halfAxes[0] + halfAxes[2]; + glm::dvec3 corner3 = halfAxes[1] + halfAxes[2]; + + double sphereRadius = glm::max(glm::length(corner1), glm::length(corner2)); + sphereRadius = glm::max(sphereRadius, glm::length(corner3)); + + double maxX = glm::abs(halfAxes[0].x) + glm::abs(halfAxes[1].x) + + glm::abs(halfAxes[2].x); + double maxY = glm::abs(halfAxes[0].y) + glm::abs(halfAxes[1].y) + + glm::abs(halfAxes[2].y); + double maxZ = glm::abs(halfAxes[0].z) + glm::abs(halfAxes[1].z) + + glm::abs(halfAxes[2].z); + + FBoxSphereBounds result; + result.Origin = VecMath::createVector(center); + result.SphereRadius = sphereRadius; + result.BoxExtent = FVector(maxX, maxY, maxZ); + return result; +} + +FBoxSphereBounds CalcBoundsOperation::operator()( + const CesiumGeospatial::BoundingRegion& region) const { + return (*this)(region.getBoundingBox()); +} + +FBoxSphereBounds CalcBoundsOperation::operator()( + const CesiumGeospatial::BoundingRegionWithLooseFittingHeights& region) + const { + return (*this)(region.getBoundingRegion()); +} + +FBoxSphereBounds CalcBoundsOperation::operator()( + const CesiumGeospatial::S2CellBoundingVolume& s2) const { + return (*this)(s2.computeBoundingRegion()); +} \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CalcBounds.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CalcBounds.h new file mode 100644 index 0000000..ad93855 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CalcBounds.h @@ -0,0 +1,48 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Math/BoxSphereBounds.h" +#include "Math/TransformNonVectorized.h" +#include +#include +#include + +struct CalcBoundsOperation { + const FTransform& localToWorld; + const glm::dmat4& highPrecisionTransform; + + // Bounding volumes are expressed in tileset coordinates, which is usually + // ECEF. + // + // - `localToWorld` goes from model coordinates to Unreal world + // coordinates, where model coordinates include the tile's transform as + // well as any glTF node transforms. + // - `highPrecisionTransform` transforms from model coordinates to tileset + // coordinates. + // + // So to transform a bounding volume, we need to first transform by the + // inverse of `highPrecisionTransform` in order bring the bounding volume + // into model coordinates, and then transform by `localToWorld` to bring the + // bounding volume into Unreal world coordinates. + + glm::dmat4 getModelToUnrealWorldMatrix() const; + + glm::dmat4 getTilesetToUnrealWorldMatrix() const; + + FBoxSphereBounds + operator()(const CesiumGeometry::BoundingSphere& sphere) const; + + FBoxSphereBounds + operator()(const CesiumGeometry::OrientedBoundingBox& box) const; + + FBoxSphereBounds + operator()(const CesiumGeospatial::BoundingRegion& region) const; + + FBoxSphereBounds operator()( + const CesiumGeospatial::BoundingRegionWithLooseFittingHeights& region) + const; + + FBoxSphereBounds + operator()(const CesiumGeospatial::S2CellBoundingVolume& s2) const; +}; \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTileset.cpp new file mode 100644 index 0000000..22603b6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -0,0 +1,2477 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "Cesium3DTileset.h" +#include "Async/Async.h" +#include "Camera/CameraTypes.h" +#include "Camera/PlayerCameraManager.h" +#include "Cesium3DTilesSelection/EllipsoidTilesetLoader.h" +#include "Cesium3DTilesSelection/IPrepareRendererResources.h" +#include "Cesium3DTilesSelection/Tile.h" +#include "Cesium3DTilesSelection/TilesetLoadFailureDetails.h" +#include "Cesium3DTilesSelection/TilesetOptions.h" +#include "Cesium3DTilesSelection/TilesetSharedAssetSystem.h" +#include "Cesium3DTilesetLoadFailureDetails.h" +#include "Cesium3DTilesetRoot.h" +#include "CesiumActors.h" +#include "CesiumAsync/SharedAssetDepot.h" +#include "CesiumBoundingVolumeComponent.h" +#include "CesiumCamera.h" +#include "CesiumCameraManager.h" +#include "CesiumCommon.h" +#include "CesiumCustomVersion.h" +#include "CesiumGeospatial/GlobeTransforms.h" +#include "CesiumGltf/ImageAsset.h" +#include "CesiumGltf/Ktx2TranscodeTargets.h" +#include "CesiumGltfComponent.h" +#include "CesiumGltfPointsSceneProxyUpdater.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumIonClient/Connection.h" +#include "CesiumLifetime.h" +#include "CesiumRasterOverlay.h" +#include "CesiumRuntime.h" +#include "CesiumRuntimeSettings.h" +#include "CesiumTextureUtility.h" +#include "CesiumTileExcluder.h" +#include "CesiumViewExtension.h" +#include "Components/SceneCaptureComponent2D.h" +#include "CreateGltfOptions.h" +#include "Engine/Engine.h" +#include "Engine/LocalPlayer.h" +#include "Engine/SceneCapture2D.h" +#include "Engine/Texture.h" +#include "Engine/Texture2D.h" +#include "Engine/TextureRenderTarget2D.h" +#include "Engine/World.h" +#include "EngineUtils.h" +#include "ExtensionImageAssetUnreal.h" +#include "GameFramework/PlayerController.h" +#include "Kismet/GameplayStatics.h" +#include "LevelSequenceActor.h" +#include "LevelSequencePlayer.h" +#include "Math/UnrealMathUtility.h" +#include "PixelFormat.h" +#include "StereoRendering.h" +#include "VecMath.h" +#include +#include +#include + +#ifdef CESIUM_DEBUG_TILE_STATES +#include "HAL/PlatformFileManager.h" +#include +#endif + +FCesium3DTilesetLoadFailure OnCesium3DTilesetLoadFailure{}; + +#if WITH_EDITOR +#include "Editor.h" +#include "EditorViewportClient.h" +#include "FileHelpers.h" +#include "LevelEditorViewport.h" +#endif + +// Avoid complaining about the deprecated metadata struct +PRAGMA_DISABLE_DEPRECATION_WARNINGS + +// Sets default values +ACesium3DTileset::ACesium3DTileset() + : AActor(), + Georeference(nullptr), + ResolvedGeoreference(nullptr), + CreditSystem(nullptr), + + _pTileset(nullptr), + +#ifdef CESIUM_DEBUG_TILE_STATES + _pStateDebug(nullptr), +#endif + + _lastTilesRendered(0), + _lastWorkerThreadTileLoadQueueLength(0), + _lastMainThreadTileLoadQueueLength(0), + + _lastTilesVisited(0), + _lastTilesCulled(0), + _lastTilesOccluded(0), + _lastTilesWaitingForOcclusionResults(0), + _lastMaxDepthVisited(0), + + _captureMovieMode{false}, + _beforeMoviePreloadAncestors{PreloadAncestors}, + _beforeMoviePreloadSiblings{PreloadSiblings}, + _beforeMovieLoadingDescendantLimit{LoadingDescendantLimit}, + _beforeMovieUseLodTransitions{true}, + + _tilesetsBeingDestroyed(0) { + PrimaryActorTick.bCanEverTick = true; + PrimaryActorTick.TickGroup = ETickingGroup::TG_PostUpdateWork; + +#if WITH_EDITOR + this->SetIsSpatiallyLoaded(false); +#endif + + this->SetActorEnableCollision(true); + + this->RootComponent = + CreateDefaultSubobject(TEXT("Tileset")); + this->Root = this->RootComponent; + + PlatformName = UGameplayStatics::GetPlatformName(); + +#if WITH_EDITOR + bIsMac = PlatformName == TEXT("Mac"); +#endif +} + +ACesium3DTileset::~ACesium3DTileset() { this->DestroyTileset(); } +PRAGMA_ENABLE_DEPRECATION_WARNINGS + +TSoftObjectPtr ACesium3DTileset::GetGeoreference() const { + return this->Georeference; +} + +void ACesium3DTileset::SetMobility(EComponentMobility::Type NewMobility) { + if (NewMobility != this->RootComponent->Mobility) { + this->RootComponent->SetMobility(NewMobility); + DestroyTileset(); + } +} + +void ACesium3DTileset::SampleHeightMostDetailed( + const TArray& LongitudeLatitudeHeightArray, + FCesiumSampleHeightMostDetailedCallback OnHeightsSampled) { + // It's possible to call this function before a Tick happens, so make sure + // that the necessary variables are resolved. + this->ResolveGeoreference(); + this->ResolveCameraManager(); + this->ResolveCreditSystem(); + + if (this->_pTileset == nullptr) { + this->LoadTileset(); + } + + std::vector positions; + positions.reserve(LongitudeLatitudeHeightArray.Num()); + + for (const FVector& position : LongitudeLatitudeHeightArray) { + positions.emplace_back(CesiumGeospatial::Cartographic::fromDegrees( + position.X, + position.Y, + position.Z)); + } + + auto sampleHeights = [this, &positions]() mutable { + if (this->_pTileset) { + return this->_pTileset->sampleHeightMostDetailed(positions) + .catchImmediately([positions = std::move(positions)]( + std::exception&& exception) mutable { + std::vector sampleSuccess(positions.size(), false); + return Cesium3DTilesSelection::SampleHeightResult{ + std::move(positions), + std::move(sampleSuccess), + {exception.what()}}; + }); + } else { + std::vector sampleSuccess(positions.size(), false); + return getAsyncSystem().createResolvedFuture( + Cesium3DTilesSelection::SampleHeightResult{ + std::move(positions), + std::move(sampleSuccess), + {"Could not sample heights from tileset because it has not " + "been created."}}); + } + }; + + sampleHeights().thenImmediately( + [this, OnHeightsSampled = std::move(OnHeightsSampled)]( + Cesium3DTilesSelection::SampleHeightResult&& result) { + if (!IsValid(this)) + return; + + check(result.positions.size() == result.sampleSuccess.size()); + + // This should do nothing, but will prevent undefined behavior if + // the array sizes are unexpectedly different. + result.sampleSuccess.resize(result.positions.size(), false); + + TArray sampleHeightResults; + sampleHeightResults.Reserve(result.positions.size()); + + for (size_t i = 0; i < result.positions.size(); ++i) { + const CesiumGeospatial::Cartographic& position = result.positions[i]; + + FCesiumSampleHeightResult unrealResult; + unrealResult.LongitudeLatitudeHeight = FVector( + CesiumUtility::Math::radiansToDegrees(position.longitude), + CesiumUtility::Math::radiansToDegrees(position.latitude), + position.height); + unrealResult.SampleSuccess = result.sampleSuccess[i]; + + sampleHeightResults.Emplace(std::move(unrealResult)); + } + + TArray warnings; + warnings.Reserve(result.warnings.size()); + + for (const std::string& warning : result.warnings) { + warnings.Emplace(UTF8_TO_TCHAR(warning.c_str())); + } + + OnHeightsSampled.ExecuteIfBound(this, sampleHeightResults, warnings); + }); +} + +void ACesium3DTileset::SetGeoreference( + TSoftObjectPtr NewGeoreference) { + this->Georeference = NewGeoreference; + this->InvalidateResolvedGeoreference(); + this->ResolveGeoreference(); +} + +ACesiumGeoreference* ACesium3DTileset::ResolveGeoreference() { + if (IsValid(this->ResolvedGeoreference)) { + return this->ResolvedGeoreference; + } + + if (IsValid(this->Georeference.Get())) { + this->ResolvedGeoreference = this->Georeference.Get(); + } else { + this->ResolvedGeoreference = + ACesiumGeoreference::GetDefaultGeoreferenceForActor(this); + } + + UCesium3DTilesetRoot* pRoot = Cast(this->RootComponent); + if (pRoot) { + this->ResolvedGeoreference->OnGeoreferenceUpdated.AddUniqueDynamic( + pRoot, + &UCesium3DTilesetRoot::HandleGeoreferenceUpdated); + this->ResolvedGeoreference->OnEllipsoidChanged.AddUniqueDynamic( + this, + &ACesium3DTileset::HandleOnGeoreferenceEllipsoidChanged); + + // Update existing tile positions, if any. + pRoot->HandleGeoreferenceUpdated(); + } + + return this->ResolvedGeoreference; +} + +void ACesium3DTileset::InvalidateResolvedGeoreference() { + if (IsValid(this->ResolvedGeoreference)) { + this->ResolvedGeoreference->OnGeoreferenceUpdated.RemoveAll( + this->RootComponent); + } + this->ResolvedGeoreference = nullptr; +} + +TSoftObjectPtr ACesium3DTileset::GetCreditSystem() const { + return this->CreditSystem; +} + +void ACesium3DTileset::SetCreditSystem( + TSoftObjectPtr NewCreditSystem) { + this->CreditSystem = NewCreditSystem; + this->InvalidateResolvedCreditSystem(); + this->ResolveCreditSystem(); +} + +ACesiumCreditSystem* ACesium3DTileset::ResolveCreditSystem() { + if (IsValid(this->ResolvedCreditSystem)) { + return this->ResolvedCreditSystem; + } + + if (IsValid(this->CreditSystem.Get())) { + this->ResolvedCreditSystem = this->CreditSystem.Get(); + } else { + this->ResolvedCreditSystem = + ACesiumCreditSystem::GetDefaultCreditSystem(this); + } + + // Refresh the tileset so it uses the new credit system. + this->RefreshTileset(); + + return this->ResolvedCreditSystem; +} + +void ACesium3DTileset::InvalidateResolvedCreditSystem() { + this->ResolvedCreditSystem = nullptr; + this->RefreshTileset(); +} + +TSoftObjectPtr +ACesium3DTileset::GetCameraManager() const { + return this->CameraManager; +} + +void ACesium3DTileset::SetCameraManager( + TSoftObjectPtr NewCameraManager) { + this->CameraManager = NewCameraManager; + this->InvalidateResolvedCameraManager(); + this->ResolveCameraManager(); +} + +ACesiumCameraManager* ACesium3DTileset::ResolveCameraManager() { + if (IsValid(this->ResolvedCameraManager)) { + return this->ResolvedCameraManager; + } + + if (IsValid(this->CameraManager.Get())) { + this->ResolvedCameraManager = this->CameraManager.Get(); + } else { + this->ResolvedCameraManager = + ACesiumCameraManager::GetDefaultCameraManager(this); + } + + return this->ResolvedCameraManager; +} + +void ACesium3DTileset::InvalidateResolvedCameraManager() { + this->ResolvedCameraManager = nullptr; + this->RefreshTileset(); +} + +void ACesium3DTileset::RefreshTileset() { this->DestroyTileset(); } + +void ACesium3DTileset::TroubleshootToken() { + OnCesium3DTilesetIonTroubleshooting.Broadcast(this); +} + +void ACesium3DTileset::AddFocusViewportDelegate() { +#if WITH_EDITOR + FEditorDelegates::OnFocusViewportOnActors.AddLambda( + [this](const TArray& actors) { + if (actors.Num() == 1 && actors[0] == this) { + this->OnFocusEditorViewportOnThis(); + } + }); +#endif // WITH_EDITOR +} + +void ACesium3DTileset::PostInitProperties() { + UE_LOG( + LogCesium, + Verbose, + TEXT("Called PostInitProperties on actor %s"), + *this->GetName()); + + Super::PostInitProperties(); + + AddFocusViewportDelegate(); + + UCesiumRuntimeSettings* pSettings = + GetMutableDefault(); + if (pSettings) { + CanEnableOcclusionCulling = + pSettings->EnableExperimentalOcclusionCullingFeature; +#if WITH_EDITOR + pSettings->OnSettingChanged().AddUObject( + this, + &ACesium3DTileset::RuntimeSettingsChanged); +#endif + } +} + +void ACesium3DTileset::SetUseLodTransitions(bool InUseLodTransitions) { + if (InUseLodTransitions != this->UseLodTransitions) { + this->UseLodTransitions = InUseLodTransitions; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetTilesetSource(ETilesetSource InSource) { + if (InSource != this->TilesetSource) { + this->DestroyTileset(); + this->TilesetSource = InSource; + } +} + +void ACesium3DTileset::SetUrl(const FString& InUrl) { + if (InUrl != this->Url) { + if (this->TilesetSource == ETilesetSource::FromUrl) { + this->DestroyTileset(); + } + this->Url = InUrl; + } +} + +void ACesium3DTileset::SetIonAssetID(int64 InAssetID) { + if (InAssetID >= 0 && InAssetID != this->IonAssetID) { + if (this->TilesetSource == ETilesetSource::FromCesiumIon) { + this->DestroyTileset(); + } + this->IonAssetID = InAssetID; + } +} + +void ACesium3DTileset::SetIonAccessToken(const FString& InAccessToken) { + if (this->IonAccessToken != InAccessToken) { + if (this->TilesetSource == ETilesetSource::FromCesiumIon) { + this->DestroyTileset(); + } + this->IonAccessToken = InAccessToken; + } +} + +void ACesium3DTileset::SetCesiumIonServer(UCesiumIonServer* Server) { + if (this->CesiumIonServer != Server) { + if (this->TilesetSource == ETilesetSource::FromCesiumIon) { + this->DestroyTileset(); + } + this->CesiumIonServer = Server; + } +} + +void ACesium3DTileset::SetMaximumScreenSpaceError( + double InMaximumScreenSpaceError) { + if (MaximumScreenSpaceError != InMaximumScreenSpaceError) { + MaximumScreenSpaceError = InMaximumScreenSpaceError; + FCesiumGltfPointsSceneProxyUpdater::UpdateSettingsInProxies(this); + } +} + +bool ACesium3DTileset::GetEnableOcclusionCulling() const { + return GetDefault() + ->EnableExperimentalOcclusionCullingFeature && + EnableOcclusionCulling; +} + +void ACesium3DTileset::SetEnableOcclusionCulling(bool bEnableOcclusionCulling) { + if (this->EnableOcclusionCulling != bEnableOcclusionCulling) { + this->EnableOcclusionCulling = bEnableOcclusionCulling; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetOcclusionPoolSize(int32 newOcclusionPoolSize) { + if (this->OcclusionPoolSize != newOcclusionPoolSize) { + this->OcclusionPoolSize = newOcclusionPoolSize; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetDelayRefinementForOcclusion( + bool bDelayRefinementForOcclusion) { + if (this->DelayRefinementForOcclusion != bDelayRefinementForOcclusion) { + this->DelayRefinementForOcclusion = bDelayRefinementForOcclusion; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetCreatePhysicsMeshes(bool bCreatePhysicsMeshes) { + if (this->CreatePhysicsMeshes != bCreatePhysicsMeshes) { + this->CreatePhysicsMeshes = bCreatePhysicsMeshes; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetCreateNavCollision(bool bCreateNavCollision) { + if (this->CreateNavCollision != bCreateNavCollision) { + this->CreateNavCollision = bCreateNavCollision; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetAlwaysIncludeTangents(bool bAlwaysIncludeTangents) { + if (this->AlwaysIncludeTangents != bAlwaysIncludeTangents) { + this->AlwaysIncludeTangents = bAlwaysIncludeTangents; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetGenerateSmoothNormals(bool bGenerateSmoothNormals) { + if (this->GenerateSmoothNormals != bGenerateSmoothNormals) { + this->GenerateSmoothNormals = bGenerateSmoothNormals; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetEnableWaterMask(bool bEnableMask) { + if (this->EnableWaterMask != bEnableMask) { + this->EnableWaterMask = bEnableMask; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetIgnoreKhrMaterialsUnlit( + bool bIgnoreKhrMaterialsUnlit) { + if (this->IgnoreKhrMaterialsUnlit != bIgnoreKhrMaterialsUnlit) { + this->IgnoreKhrMaterialsUnlit = bIgnoreKhrMaterialsUnlit; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetMaterial(UMaterialInterface* InMaterial) { + if (this->Material != InMaterial) { + this->Material = InMaterial; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetTranslucentMaterial(UMaterialInterface* InMaterial) { + if (this->TranslucentMaterial != InMaterial) { + this->TranslucentMaterial = InMaterial; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetWaterMaterial(UMaterialInterface* InMaterial) { + if (this->WaterMaterial != InMaterial) { + this->WaterMaterial = InMaterial; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetCustomDepthParameters( + FCustomDepthParameters InCustomDepthParameters) { + if (this->CustomDepthParameters != InCustomDepthParameters) { + this->CustomDepthParameters = InCustomDepthParameters; + this->DestroyTileset(); + } +} + +void ACesium3DTileset::SetPointCloudShading( + FCesiumPointCloudShading InPointCloudShading) { + if (PointCloudShading != InPointCloudShading) { + PointCloudShading = InPointCloudShading; + FCesiumGltfPointsSceneProxyUpdater::UpdateSettingsInProxies(this); + } +} + +void ACesium3DTileset::PlayMovieSequencer() { + this->_beforeMoviePreloadAncestors = this->PreloadAncestors; + this->_beforeMoviePreloadSiblings = this->PreloadSiblings; + this->_beforeMovieLoadingDescendantLimit = this->LoadingDescendantLimit; + this->_beforeMovieUseLodTransitions = this->UseLodTransitions; + + this->_captureMovieMode = true; + this->PreloadAncestors = false; + this->PreloadSiblings = false; + this->LoadingDescendantLimit = 10000; + this->UseLodTransitions = false; +} + +void ACesium3DTileset::StopMovieSequencer() { + this->_captureMovieMode = false; + this->PreloadAncestors = this->_beforeMoviePreloadAncestors; + this->PreloadSiblings = this->_beforeMoviePreloadSiblings; + this->LoadingDescendantLimit = this->_beforeMovieLoadingDescendantLimit; + this->UseLodTransitions = this->_beforeMovieUseLodTransitions; +} + +void ACesium3DTileset::PauseMovieSequencer() { this->StopMovieSequencer(); } + +#if WITH_EDITOR +void ACesium3DTileset::OnFocusEditorViewportOnThis() { + UE_LOG( + LogCesium, + Verbose, + TEXT("Called OnFocusEditorViewportOnThis on actor %s"), + *this->GetName()); + + struct CalculateECEFCameraPosition { + const CesiumGeospatial::Ellipsoid& ellipsoid; + + glm::dvec3 operator()(const CesiumGeometry::BoundingSphere& sphere) { + const glm::dvec3& center = sphere.getCenter(); + glm::dmat4 ENU = + CesiumGeospatial::GlobeTransforms::eastNorthUpToFixedFrame( + center, + ellipsoid); + glm::dvec3 offset = + sphere.getRadius() * + glm::normalize( + glm::dvec3(ENU[0]) + glm::dvec3(ENU[1]) + glm::dvec3(ENU[2])); + glm::dvec3 position = center + offset; + return position; + } + + glm::dvec3 + operator()(const CesiumGeometry::OrientedBoundingBox& orientedBoundingBox) { + const glm::dvec3& center = orientedBoundingBox.getCenter(); + glm::dmat4 ENU = + CesiumGeospatial::GlobeTransforms::eastNorthUpToFixedFrame( + center, + ellipsoid); + const glm::dmat3& halfAxes = orientedBoundingBox.getHalfAxes(); + glm::dvec3 offset = + glm::length(halfAxes[0] + halfAxes[1] + halfAxes[2]) * + glm::normalize( + glm::dvec3(ENU[0]) + glm::dvec3(ENU[1]) + glm::dvec3(ENU[2])); + glm::dvec3 position = center + offset; + return position; + } + + glm::dvec3 + operator()(const CesiumGeospatial::BoundingRegion& boundingRegion) { + return (*this)(boundingRegion.getBoundingBox()); + } + + glm::dvec3 + operator()(const CesiumGeospatial::BoundingRegionWithLooseFittingHeights& + boundingRegionWithLooseFittingHeights) { + return (*this)(boundingRegionWithLooseFittingHeights.getBoundingRegion() + .getBoundingBox()); + } + + glm::dvec3 operator()(const CesiumGeospatial::S2CellBoundingVolume& s2) { + return (*this)(s2.computeBoundingRegion()); + } + }; + + const Cesium3DTilesSelection::Tile* pRootTile = + this->_pTileset->getRootTile(); + if (!pRootTile) { + return; + } + + const Cesium3DTilesSelection::BoundingVolume& boundingVolume = + pRootTile->getBoundingVolume(); + + ACesiumGeoreference* pGeoreference = this->ResolveGeoreference(); + + const CesiumGeospatial::Ellipsoid& ellipsoid = + pGeoreference->GetEllipsoid()->GetNativeEllipsoid(); + + // calculate unreal camera position + glm::dvec3 ecefCameraPosition = + std::visit(CalculateECEFCameraPosition{ellipsoid}, boundingVolume); + FVector unrealCameraPosition = + pGeoreference->TransformEarthCenteredEarthFixedPositionToUnreal( + VecMath::createVector(ecefCameraPosition)); + + // calculate unreal camera orientation + glm::dvec3 ecefCenter = + Cesium3DTilesSelection::getBoundingVolumeCenter(boundingVolume); + FVector unrealCenter = + pGeoreference->TransformEarthCenteredEarthFixedPositionToUnreal( + VecMath::createVector(ecefCenter)); + FVector unrealCameraFront = + (unrealCenter - unrealCameraPosition).GetSafeNormal(); + FVector unrealCameraRight = + FVector::CrossProduct(FVector::ZAxisVector, unrealCameraFront) + .GetSafeNormal(); + FVector unrealCameraUp = + FVector::CrossProduct(unrealCameraFront, unrealCameraRight) + .GetSafeNormal(); + FRotator cameraRotator = FMatrix( + unrealCameraFront, + unrealCameraRight, + unrealCameraUp, + FVector::ZeroVector) + .Rotator(); + + // Update all viewports. + for (FLevelEditorViewportClient* LinkedViewportClient : + GEditor->GetLevelViewportClients()) { + // Dont move camera attach to an actor + if (!LinkedViewportClient->IsAnyActorLocked()) { + FViewportCameraTransform& ViewTransform = + LinkedViewportClient->GetViewTransform(); + LinkedViewportClient->SetViewRotation(cameraRotator); + LinkedViewportClient->SetViewLocation(unrealCameraPosition); + LinkedViewportClient->Invalidate(); + } + } +} +#endif + +const glm::dmat4& +ACesium3DTileset::GetCesiumTilesetToUnrealRelativeWorldTransform() const { + return Cast(this->RootComponent) + ->GetCesiumTilesetToUnrealRelativeWorldTransform(); +} + +void ACesium3DTileset::UpdateTransformFromCesium() { + const glm::dmat4& CesiumToUnreal = + this->GetCesiumTilesetToUnrealRelativeWorldTransform(); + TArray gltfComponents; + this->GetComponents(gltfComponents); + + for (UCesiumGltfComponent* pGltf : gltfComponents) { + pGltf->UpdateTransformFromCesium(CesiumToUnreal); + } + + if (this->BoundingVolumePoolComponent) { + this->BoundingVolumePoolComponent->UpdateTransformFromCesium( + CesiumToUnreal); + } +} + +void ACesium3DTileset::HandleOnGeoreferenceEllipsoidChanged( + UCesiumEllipsoid* OldEllipsoid, + UCesiumEllipsoid* NewEllpisoid) { + UE_LOG(LogCesium, Warning, TEXT("Ellipsoid changed")); + this->RefreshTileset(); +} + +// Called when the game starts or when spawned +void ACesium3DTileset::BeginPlay() { + Super::BeginPlay(); + + this->ResolveGeoreference(); + this->ResolveCameraManager(); + this->ResolveCreditSystem(); + + this->LoadTileset(); + + // Search for level sequence. + for (auto sequenceActorIt = TActorIterator(GetWorld()); + sequenceActorIt; + ++sequenceActorIt) { + ALevelSequenceActor* sequenceActor = *sequenceActorIt; + + if (!IsValid(sequenceActor->GetSequencePlayer())) { + continue; + } + + FScriptDelegate playMovieSequencerDelegate; + playMovieSequencerDelegate.BindUFunction(this, FName("PlayMovieSequencer")); + sequenceActor->GetSequencePlayer()->OnPlay.Add(playMovieSequencerDelegate); + + FScriptDelegate stopMovieSequencerDelegate; + stopMovieSequencerDelegate.BindUFunction(this, FName("StopMovieSequencer")); + sequenceActor->GetSequencePlayer()->OnStop.Add(stopMovieSequencerDelegate); + + FScriptDelegate pauseMovieSequencerDelegate; + pauseMovieSequencerDelegate.BindUFunction( + this, + FName("PauseMovieSequencer")); + sequenceActor->GetSequencePlayer()->OnPause.Add( + pauseMovieSequencerDelegate); + } +} + +void ACesium3DTileset::OnConstruction(const FTransform& Transform) { + this->ResolveGeoreference(); + this->ResolveCameraManager(); + this->ResolveCreditSystem(); + + this->LoadTileset(); + + // Hide all existing tiles. The still-visible ones will be shown next time we + // tick. But if update is suspended, leave the components in their current + // state. + if (!this->SuspendUpdate) { + TArray gltfComponents; + this->GetComponents(gltfComponents); + + for (UCesiumGltfComponent* pGltf : gltfComponents) { + if (pGltf && IsValid(pGltf) && pGltf->IsVisible()) { + pGltf->SetVisibility(false, true); + pGltf->SetCollisionEnabled(ECollisionEnabled::NoCollision); + } + } + } +} + +void ACesium3DTileset::NotifyHit( + UPrimitiveComponent* MyComp, + AActor* Other, + UPrimitiveComponent* OtherComp, + bool bSelfMoved, + FVector HitLocation, + FVector HitNormal, + FVector NormalImpulse, + const FHitResult& Hit) { + // std::cout << "Hit face index: " << Hit.FaceIndex << std::endl; + + // FHitResult detailedHit; + // FCollisionQueryParams params; + // params.bReturnFaceIndex = true; + // params.bTraceComplex = true; + // MyComp->LineTraceComponent(detailedHit, Hit.TraceStart, Hit.TraceEnd, + // params); + + // std::cout << "Hit face index 2: " << detailedHit.FaceIndex << std::endl; +} + +class UnrealResourcePreparer + : public Cesium3DTilesSelection::IPrepareRendererResources { +public: + UnrealResourcePreparer(ACesium3DTileset* pActor) : _pActor(pActor) {} + + virtual CesiumAsync::Future< + Cesium3DTilesSelection::TileLoadResultAndRenderResources> + prepareInLoadThread( + const CesiumAsync::AsyncSystem& asyncSystem, + Cesium3DTilesSelection::TileLoadResult&& tileLoadResult, + const glm::dmat4& transform, + const std::any& rendererOptions) override { + CreateGltfOptions::CreateModelOptions options(std::move(tileLoadResult)); + if (!options.pModel) { + return asyncSystem.createResolvedFuture( + Cesium3DTilesSelection::TileLoadResultAndRenderResources{ + std::move(options.tileLoadResult), + nullptr}); + } + + options.alwaysIncludeTangents = this->_pActor->GetAlwaysIncludeTangents(); + options.createPhysicsMeshes = this->_pActor->GetCreatePhysicsMeshes(); + + options.ignoreKhrMaterialsUnlit = + this->_pActor->GetIgnoreKhrMaterialsUnlit(); + + if (this->_pActor->_featuresMetadataDescription) { + options.pFeaturesMetadataDescription = + &(*this->_pActor->_featuresMetadataDescription); + } else if (this->_pActor->_metadataDescription_DEPRECATED) { + options.pEncodedMetadataDescription_DEPRECATED = + &(*this->_pActor->_metadataDescription_DEPRECATED); + } + + const CesiumGeospatial::Ellipsoid& ellipsoid = tileLoadResult.ellipsoid; + + CesiumAsync::Future + pHalfFuture = UCesiumGltfComponent::CreateOffGameThread( + asyncSystem, + transform, + std::move(options), + ellipsoid); + + return MoveTemp(pHalfFuture) + .thenImmediately( + [](UCesiumGltfComponent::CreateOffGameThreadResult&& result) + -> Cesium3DTilesSelection::TileLoadResultAndRenderResources { + return Cesium3DTilesSelection::TileLoadResultAndRenderResources{ + std::move(result.TileLoadResult), + result.HalfConstructed.Release()}; + }); + } + + virtual void* prepareInMainThread( + Cesium3DTilesSelection::Tile& tile, + void* pLoadThreadResult) override { + Cesium3DTilesSelection::TileContent& content = tile.getContent(); + if (content.isRenderContent()) { + TUniquePtr pHalf( + reinterpret_cast( + pLoadThreadResult)); + Cesium3DTilesSelection::TileRenderContent& renderContent = + *content.getRenderContent(); + return UCesiumGltfComponent::CreateOnGameThread( + renderContent.getModel(), + this->_pActor, + std::move(pHalf), + _pActor->GetCesiumTilesetToUnrealRelativeWorldTransform(), + this->_pActor->GetMaterial(), + this->_pActor->GetTranslucentMaterial(), + this->_pActor->GetWaterMaterial(), + this->_pActor->GetCustomDepthParameters(), + tile, + this->_pActor->GetCreateNavCollision()); + } + // UE_LOG(LogCesium, VeryVerbose, TEXT("No content for tile")); + return nullptr; + } + + virtual void free( + Cesium3DTilesSelection::Tile& tile, + void* pLoadThreadResult, + void* pMainThreadResult) noexcept override { + if (pLoadThreadResult) { + UCesiumGltfComponent::HalfConstructed* pHalf = + reinterpret_cast( + pLoadThreadResult); + delete pHalf; + } else if (pMainThreadResult) { + UCesiumGltfComponent* pGltf = + reinterpret_cast(pMainThreadResult); + CesiumLifetime::destroyComponentRecursively(pGltf); + } + } + + virtual void* prepareRasterInLoadThread( + CesiumGltf::ImageAsset& image, + const std::any& rendererOptions) override { + auto ppOptions = + std::any_cast(&rendererOptions); + check(ppOptions != nullptr && *ppOptions != nullptr); + if (ppOptions == nullptr || *ppOptions == nullptr) { + return nullptr; + } + + auto pOptions = *ppOptions; + + if (pOptions->useMipmaps) { + std::optional errorMessage = + CesiumGltfReader::ImageDecoder::generateMipMaps(image); + if (errorMessage) { + UE_LOG( + LogCesium, + Warning, + TEXT("%s"), + UTF8_TO_TCHAR(errorMessage->c_str())); + } + } + + // TODO: sRGB should probably be configurable on the raster overlay. + bool sRGB = true; + + const ExtensionImageAssetUnreal& extension = + ExtensionImageAssetUnreal::getOrCreate( + CesiumAsync::AsyncSystem(nullptr), // TODO + image, + sRGB, + pOptions->useMipmaps, + std::nullopt); + + // Because raster overlay images are never shared (at least currently!), the + // future should already be resolved by the time we get here. + check(extension.getFuture().isReady()); + + auto texture = CesiumTextureUtility::loadTextureAnyThreadPart( + image, + TextureAddress::TA_Clamp, + TextureAddress::TA_Clamp, + pOptions->filter, + pOptions->useMipmaps, + pOptions->group, + sRGB, + std::nullopt); + + return texture.Release(); + } + + virtual void* prepareRasterInMainThread( + CesiumRasterOverlays::RasterOverlayTile& rasterTile, + void* pLoadThreadResult) override { + TUniquePtr pLoadedTexture{ + static_cast( + pLoadThreadResult)}; + + if (!pLoadedTexture) { + return nullptr; + } + + CesiumUtility::IntrusivePointer< + CesiumTextureUtility::ReferenceCountedUnrealTexture> + pTexture = CesiumTextureUtility::loadTextureGameThreadPart( + pLoadedTexture.Get()); + if (!pTexture) { + return nullptr; + } + + // Don't let this ReferenceCountedUnrealTexture be destroyed when the + // intrusive pointer goes out of scope. + pTexture->addReference(); + return pTexture.get(); + } + + virtual void freeRaster( + const CesiumRasterOverlays::RasterOverlayTile& rasterTile, + void* pLoadThreadResult, + void* pMainThreadResult) noexcept override { + if (pLoadThreadResult) { + CesiumTextureUtility::LoadedTextureResult* pLoadedTexture = + static_cast( + pLoadThreadResult); + delete pLoadedTexture; + } + + if (pMainThreadResult) { + CesiumTextureUtility::ReferenceCountedUnrealTexture* pTexture = + static_cast( + pMainThreadResult); + pTexture->releaseReference(); + } + } + + virtual void attachRasterInMainThread( + const Cesium3DTilesSelection::Tile& tile, + int32_t overlayTextureCoordinateID, + const CesiumRasterOverlays::RasterOverlayTile& rasterTile, + void* pMainThreadRendererResources, + const glm::dvec2& translation, + const glm::dvec2& scale) override { + const Cesium3DTilesSelection::TileContent& content = tile.getContent(); + const Cesium3DTilesSelection::TileRenderContent* pRenderContent = + content.getRenderContent(); + if (pMainThreadRendererResources != nullptr && pRenderContent != nullptr) { + UCesiumGltfComponent* pGltfContent = + reinterpret_cast( + pRenderContent->getRenderResources()); + if (pGltfContent) { + pGltfContent->AttachRasterTile( + tile, + rasterTile, + static_cast( + pMainThreadRendererResources) + ->getUnrealTexture(), + translation, + scale, + overlayTextureCoordinateID); + } + } + } + + virtual void detachRasterInMainThread( + const Cesium3DTilesSelection::Tile& tile, + int32_t overlayTextureCoordinateID, + const CesiumRasterOverlays::RasterOverlayTile& rasterTile, + void* pMainThreadRendererResources) noexcept override { + const Cesium3DTilesSelection::TileContent& content = tile.getContent(); + const Cesium3DTilesSelection::TileRenderContent* pRenderContent = + content.getRenderContent(); + if (pRenderContent) { + UCesiumGltfComponent* pGltfContent = + reinterpret_cast( + pRenderContent->getRenderResources()); + if (pMainThreadRendererResources != nullptr && pGltfContent != nullptr) { + pGltfContent->DetachRasterTile( + tile, + rasterTile, + static_cast( + pMainThreadRendererResources) + ->getUnrealTexture()); + } + } + } + +private: + ACesium3DTileset* _pActor; +}; + +void ACesium3DTileset::UpdateLoadStatus() { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateLoadStatus) + + float nativeLoadProgress = this->_pTileset->computeLoadProgress(); + + // If native tileset still loading, just copy its progress + if (nativeLoadProgress < 100) { + this->LoadProgress = nativeLoadProgress; + return; + } + + // Native tileset is 100% loaded, but there might be a few frames where + // nothing needs to be loaded as we are waiting for occlusion results to come + // back, which means we are not done with loading all the tiles in the tileset + // yet. Interpret this as 99% (almost) done + if (this->_lastTilesWaitingForOcclusionResults > 0) { + this->LoadProgress = 99; + return; + } + + // If we have tiles to hide next frame, we haven't completely finished loading + // yet. We need to tick once more. We're really close to done. + if (!this->_tilesToHideNextFrame.empty()) { + this->LoadProgress = glm::min(this->LoadProgress, 99.9999f); + return; + } + + // We can now report 100 percent loaded + float lastLoadProgress = this->LoadProgress; + this->LoadProgress = 100; + + // Only broadcast the update when we first hit 100%, not everytime + if (lastLoadProgress != LoadProgress) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::BroadcastOnTilesetLoaded) + + // Tileset just finished loading, we broadcast the update + UE_LOG(LogCesium, Verbose, TEXT("Broadcasting OnTileLoaded")); + OnTilesetLoaded.Broadcast(); + } +} + +namespace { +const TSharedRef& +getCesiumViewExtension() { + static TSharedRef + cesiumViewExtension = + GEngine->ViewExtensions->NewExtension(); + return cesiumViewExtension; +} +} // namespace + +void ACesium3DTileset::LoadTileset() { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::LoadTileset) + + if (this->_pTileset) { + // Tileset already loaded, do nothing. + return; + } + + UWorld* pWorld = this->GetWorld(); + if (!pWorld) { + return; + } + + AWorldSettings* pWorldSettings = pWorld->GetWorldSettings(); + if (pWorldSettings && pWorldSettings->bEnableWorldBoundsChecks) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "\"Enable World Bounds Checks\" in the world settings is currently enabled. Please consider disabling it to avoid potential issues."), + *this->Url); + } + + // Make sure we have a valid Cesium ion server if we need one. + if (this->TilesetSource == ETilesetSource::FromCesiumIon && + !IsValid(this->CesiumIonServer)) { + this->Modify(); + this->CesiumIonServer = UCesiumIonServer::GetServerForNewObjects(); + } + + const TSharedRef& + cesiumViewExtension = getCesiumViewExtension(); + const std::shared_ptr& pAssetAccessor = + getAssetAccessor(); + const CesiumAsync::AsyncSystem& asyncSystem = getAsyncSystem(); + + // Both the feature flag and the CesiumViewExtension are global, not owned by + // the Tileset. We're just applying one to the other here out of convenience. + cesiumViewExtension->SetEnabled( + GetDefault() + ->EnableExperimentalOcclusionCullingFeature); + + TArray rasterOverlays; + this->GetComponents(rasterOverlays); + + TArray tileExcluders; + this->GetComponents(tileExcluders); + + const UCesiumFeaturesMetadataComponent* pFeaturesMetadataComponent = + this->FindComponentByClass(); + + // Check if this component exists for backwards compatibility. + PRAGMA_DISABLE_DEPRECATION_WARNINGS + + const UDEPRECATED_CesiumEncodedMetadataComponent* pEncodedMetadataComponent = + this->FindComponentByClass(); + + this->_featuresMetadataDescription = std::nullopt; + this->_metadataDescription_DEPRECATED = std::nullopt; + + if (pFeaturesMetadataComponent) { + FCesiumFeaturesMetadataDescription& description = + this->_featuresMetadataDescription.emplace(); + description.Features = {pFeaturesMetadataComponent->FeatureIdSets}; + description.PrimitiveMetadata = { + pFeaturesMetadataComponent->PropertyTextureNames}; + description.ModelMetadata = { + pFeaturesMetadataComponent->PropertyTables, + pFeaturesMetadataComponent->PropertyTextures}; + } else if (pEncodedMetadataComponent) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "CesiumEncodedMetadataComponent is deprecated. Use CesiumFeaturesMetadataComponent instead.")); + this->_metadataDescription_DEPRECATED = { + pEncodedMetadataComponent->FeatureTables, + pEncodedMetadataComponent->FeatureTextures}; + } + + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + this->_cesiumViewExtension = cesiumViewExtension; + + if (GetDefault() + ->EnableExperimentalOcclusionCullingFeature && + this->EnableOcclusionCulling && !this->BoundingVolumePoolComponent) { + const glm::dmat4& cesiumToUnreal = + GetCesiumTilesetToUnrealRelativeWorldTransform(); + this->BoundingVolumePoolComponent = + NewObject(this); + this->BoundingVolumePoolComponent->SetFlags( + RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + this->BoundingVolumePoolComponent->RegisterComponent(); + this->BoundingVolumePoolComponent->UpdateTransformFromCesium( + cesiumToUnreal); + } + + if (this->BoundingVolumePoolComponent) { + this->BoundingVolumePoolComponent->initPool(this->OcclusionPoolSize); + } + + CesiumGeospatial::Ellipsoid pNativeEllipsoid = + this->ResolveGeoreference()->GetEllipsoid()->GetNativeEllipsoid(); + + ACesiumCreditSystem* pCreditSystem = this->ResolvedCreditSystem; + + Cesium3DTilesSelection::TilesetExternals externals{ + pAssetAccessor, + std::make_shared(this), + asyncSystem, + pCreditSystem ? pCreditSystem->GetExternalCreditSystem() : nullptr, + spdlog::default_logger(), + (GetDefault() + ->EnableExperimentalOcclusionCullingFeature && + this->EnableOcclusionCulling && this->BoundingVolumePoolComponent) + ? this->BoundingVolumePoolComponent->getPool() + : nullptr}; + + this->_startTime = std::chrono::high_resolution_clock::now(); + + this->LoadProgress = 0; + + Cesium3DTilesSelection::TilesetOptions options; + + options.ellipsoid = pNativeEllipsoid; + + options.enableOcclusionCulling = + GetDefault() + ->EnableExperimentalOcclusionCullingFeature && + this->EnableOcclusionCulling; + options.delayRefinementForOcclusion = this->DelayRefinementForOcclusion; + + options.showCreditsOnScreen = ShowCreditsOnScreen; + + options.loadErrorCallback = + [this](const Cesium3DTilesSelection::TilesetLoadFailureDetails& details) { + static_assert( + uint8_t(ECesium3DTilesetLoadType::CesiumIon) == + uint8_t(Cesium3DTilesSelection::TilesetLoadType::CesiumIon)); + static_assert( + uint8_t(ECesium3DTilesetLoadType::TilesetJson) == + uint8_t(Cesium3DTilesSelection::TilesetLoadType::TilesetJson)); + static_assert( + uint8_t(ECesium3DTilesetLoadType::Unknown) == + uint8_t(Cesium3DTilesSelection::TilesetLoadType::Unknown)); + + uint8_t typeValue = uint8_t(details.type); + assert( + uint8_t(details.type) <= + uint8_t(Cesium3DTilesSelection::TilesetLoadType::TilesetJson)); + assert(this->_pTileset == details.pTileset); + + FCesium3DTilesetLoadFailureDetails ueDetails{}; + ueDetails.Tileset = this; + ueDetails.Type = ECesium3DTilesetLoadType(typeValue); + ueDetails.HttpStatusCode = details.statusCode; + ueDetails.Message = UTF8_TO_TCHAR(details.message.c_str()); + + // Broadcast the event from the game thread. + // Even if we're already in the game thread, let the stack unwind. + // Otherwise actions that destroy the Tileset will cause a deadlock. + AsyncTask( + ENamedThreads::GameThread, + [ueDetails = std::move(ueDetails)]() { + OnCesium3DTilesetLoadFailure.Broadcast(ueDetails); + }); + }; + + // Generous per-frame time limits for loading / unloading on main thread. + options.mainThreadLoadingTimeLimit = 5.0; + options.tileCacheUnloadTimeLimit = 5.0; + + options.contentOptions.generateMissingNormalsSmooth = + this->GenerateSmoothNormals; + + // TODO: figure out why water material crashes mac +#if PLATFORM_MAC +#else + options.contentOptions.enableWaterMask = this->EnableWaterMask; +#endif + + CesiumGltf::SupportedGpuCompressedPixelFormats supportedFormats; + supportedFormats.ETC1_RGB = GPixelFormats[EPixelFormat::PF_ETC1].Supported; + supportedFormats.ETC2_RGBA = + GPixelFormats[EPixelFormat::PF_ETC2_RGBA].Supported; + supportedFormats.BC1_RGB = GPixelFormats[EPixelFormat::PF_DXT1].Supported; + supportedFormats.BC3_RGBA = GPixelFormats[EPixelFormat::PF_DXT5].Supported; + supportedFormats.BC4_R = GPixelFormats[EPixelFormat::PF_BC4].Supported; + supportedFormats.BC5_RG = GPixelFormats[EPixelFormat::PF_BC5].Supported; + supportedFormats.BC7_RGBA = GPixelFormats[EPixelFormat::PF_BC7].Supported; + supportedFormats.ASTC_4x4_RGBA = + GPixelFormats[EPixelFormat::PF_ASTC_4x4].Supported; + supportedFormats.PVRTC2_4_RGBA = + GPixelFormats[EPixelFormat::PF_PVRTC2].Supported; + supportedFormats.ETC2_EAC_R11 = + GPixelFormats[EPixelFormat::PF_ETC2_R11_EAC].Supported; + supportedFormats.ETC2_EAC_RG11 = + GPixelFormats[EPixelFormat::PF_ETC2_RG11_EAC].Supported; + + options.contentOptions.ktx2TranscodeTargets = + CesiumGltf::Ktx2TranscodeTargets(supportedFormats, false); + + options.contentOptions.applyTextureTransform = false; + + switch (this->TilesetSource) { + case ETilesetSource::FromEllipsoid: + UE_LOG(LogCesium, Log, TEXT("Loading tileset from ellipsoid")); + this->_pTileset = TUniquePtr( + Cesium3DTilesSelection::EllipsoidTilesetLoader::createTileset( + externals, + options) + .release()); + break; + case ETilesetSource::FromUrl: + UE_LOG(LogCesium, Log, TEXT("Loading tileset from URL %s"), *this->Url); + this->_pTileset = MakeUnique( + externals, + TCHAR_TO_UTF8(*this->Url), + options); + break; + case ETilesetSource::FromCesiumIon: + UE_LOG( + LogCesium, + Log, + TEXT("Loading tileset for asset ID %d"), + this->IonAssetID); + FString token = this->IonAccessToken.IsEmpty() + ? this->CesiumIonServer->DefaultIonAccessToken + : this->IonAccessToken; + +#if WITH_EDITOR + this->CesiumIonServer->ResolveApiUrl(); +#endif + + std::string ionAssetEndpointUrl = + TCHAR_TO_UTF8(*this->CesiumIonServer->ApiUrl); + + if (!ionAssetEndpointUrl.empty()) { + // Make sure the URL ends with a slash + if (!ionAssetEndpointUrl.empty() && *ionAssetEndpointUrl.rbegin() != '/') + ionAssetEndpointUrl += '/'; + + this->_pTileset = MakeUnique( + externals, + static_cast(this->IonAssetID), + TCHAR_TO_UTF8(*token), + options, + ionAssetEndpointUrl); + } + break; + } + +#ifdef CESIUM_DEBUG_TILE_STATES + FString dbDirectory = FPaths::Combine( + FPaths::ProjectSavedDir(), + TEXT("CesiumDebugTileStateDatabase")); + + IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); + if (!PlatformFile.DirectoryExists(*dbDirectory)) { + PlatformFile.CreateDirectory(*dbDirectory); + } + + FString dbFile = + FPaths::Combine(dbDirectory, this->GetName() + TEXT(".sqlite")); + this->_pStateDebug = + MakeUnique( + TCHAR_TO_UTF8(*dbFile)); +#endif + + for (UCesiumRasterOverlay* pOverlay : rasterOverlays) { + if (pOverlay->IsActive()) { + pOverlay->AddToTileset(); + } + } + + for (UCesiumTileExcluder* pTileExcluder : tileExcluders) { + if (pTileExcluder->IsActive()) { + pTileExcluder->AddToTileset(); + } + } + + switch (this->TilesetSource) { + case ETilesetSource::FromEllipsoid: + UE_LOG(LogCesium, Log, TEXT("Loading tileset from ellipsoid done")); + break; + case ETilesetSource::FromUrl: + UE_LOG( + LogCesium, + Log, + TEXT("Loading tileset from URL %s done"), + *this->Url); + break; + case ETilesetSource::FromCesiumIon: + UE_LOG( + LogCesium, + Log, + TEXT("Loading tileset for asset ID %d done"), + this->IonAssetID); + break; + } + + switch (ApplyDpiScaling) { + case (EApplyDpiScaling::UseProjectDefault): + _scaleUsingDPI = + GetDefault()->ScaleLevelOfDetailByDPI; + break; + case (EApplyDpiScaling::Yes): + _scaleUsingDPI = true; + break; + case (EApplyDpiScaling::No): + _scaleUsingDPI = false; + break; + default: + _scaleUsingDPI = true; + } +} + +void ACesium3DTileset::DestroyTileset() { + if (this->_cesiumViewExtension) { + this->_cesiumViewExtension = nullptr; + } + + switch (this->TilesetSource) { + case ETilesetSource::FromEllipsoid: + UE_LOG(LogCesium, Verbose, TEXT("Destroying tileset from ellipsoid")); + break; + case ETilesetSource::FromUrl: + UE_LOG( + LogCesium, + Verbose, + TEXT("Destroying tileset from URL %s"), + *this->Url); + break; + case ETilesetSource::FromCesiumIon: + UE_LOG( + LogCesium, + Verbose, + TEXT("Destroying tileset for asset ID %d"), + this->IonAssetID); + break; + } + + // The way CesiumRasterOverlay::add is currently implemented, destroying the + // tileset without removing overlays will make it impossible to add it again + // once a new tileset is created (e.g. when switching between terrain + // assets) + TArray rasterOverlays; + this->GetComponents(rasterOverlays); + for (UCesiumRasterOverlay* pOverlay : rasterOverlays) { + if (pOverlay->IsActive()) { + pOverlay->RemoveFromTileset(); + } + } + + TArray tileExcluders; + this->GetComponents(tileExcluders); + for (UCesiumTileExcluder* pTileExcluder : tileExcluders) { + if (pTileExcluder->IsActive()) { + pTileExcluder->RemoveFromTileset(); + } + } + + if (!this->_pTileset) { + return; + } + + // Don't allow this Cesium3DTileset to be fully destroyed until + // any cesium-native Tilesets it created have wrapped up any async + // operations in progress and have been fully destroyed. + // See IsReadyForFinishDestroy. + ++this->_tilesetsBeingDestroyed; + this->_pTileset->getAsyncDestructionCompleteEvent().thenInMainThread( + [this]() { --this->_tilesetsBeingDestroyed; }); + this->_pTileset.Reset(); + + switch (this->TilesetSource) { + case ETilesetSource::FromEllipsoid: + UE_LOG(LogCesium, Verbose, TEXT("Destroying tileset from ellipsoid done")); + break; + case ETilesetSource::FromUrl: + UE_LOG( + LogCesium, + Verbose, + TEXT("Destroying tileset from URL %s done"), + *this->Url); + break; + case ETilesetSource::FromCesiumIon: + UE_LOG( + LogCesium, + Verbose, + TEXT("Destroying tileset for asset ID %d done"), + this->IonAssetID); + break; + } +} + +std::vector ACesium3DTileset::GetCameras() const { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CollectCameras) + std::vector cameras = this->GetPlayerCameras(); + + std::vector sceneCaptures = this->GetSceneCaptures(); + cameras.insert( + cameras.end(), + std::make_move_iterator(sceneCaptures.begin()), + std::make_move_iterator(sceneCaptures.end())); + +#if WITH_EDITOR + std::vector editorCameras = this->GetEditorCameras(); + cameras.insert( + cameras.end(), + std::make_move_iterator(editorCameras.begin()), + std::make_move_iterator(editorCameras.end())); +#endif + + ACesiumCameraManager* pCameraManager = this->ResolvedCameraManager; + if (pCameraManager) { + const TMap& extraCameras = + pCameraManager->GetCameras(); + cameras.reserve(cameras.size() + extraCameras.Num()); + for (auto cameraIt : extraCameras) { + cameras.push_back(cameraIt.Value); + } + } + + return cameras; +} + +std::vector ACesium3DTileset::GetPlayerCameras() const { + UWorld* pWorld = this->GetWorld(); + if (!pWorld) { + return {}; + } + + double worldToMeters = 100.0; + AWorldSettings* pWorldSettings = pWorld->GetWorldSettings(); + if (pWorldSettings) { + worldToMeters = pWorldSettings->WorldToMeters; + } + + TSharedPtr pStereoRendering = nullptr; + if (GEngine) { + pStereoRendering = GEngine->StereoRenderingDevice; + } + + bool useStereoRendering = false; + if (pStereoRendering && pStereoRendering->IsStereoEnabled()) { + useStereoRendering = true; + } + + std::vector cameras; + cameras.reserve(pWorld->GetNumPlayerControllers()); + + for (auto playerControllerIt = pWorld->GetPlayerControllerIterator(); + playerControllerIt; + playerControllerIt++) { + const TWeakObjectPtr pPlayerController = + *playerControllerIt; + if (pPlayerController == nullptr) { + continue; + } + + const APlayerCameraManager* pPlayerCameraManager = + pPlayerController->PlayerCameraManager; + + if (!pPlayerCameraManager) { + continue; + } + + double fov = pPlayerCameraManager->GetFOVAngle(); + + FVector location; + FRotator rotation; + pPlayerController->GetPlayerViewPoint(location, rotation); + + int32 sizeX, sizeY; + pPlayerController->GetViewportSize(sizeX, sizeY); + sizeX /= 2; + if (sizeX < 1 || sizeY < 1) { + continue; + } + + float dpiScalingFactor = 1.0f; + if (this->_scaleUsingDPI) { + ULocalPlayer* LocPlayer = Cast(pPlayerController->Player); + if (LocPlayer && LocPlayer->ViewportClient) { + dpiScalingFactor = LocPlayer->ViewportClient->GetDPIScale(); + } + } + + if (useStereoRendering) { + const auto leftEye = EStereoscopicEye::eSSE_LEFT_EYE; + const auto rightEye = EStereoscopicEye::eSSE_RIGHT_EYE; + + uint32 stereoLeftSizeX = static_cast(sizeX); + uint32 stereoLeftSizeY = static_cast(sizeY); + uint32 stereoRightSizeX = static_cast(sizeX); + uint32 stereoRightSizeY = static_cast(sizeY); + if (useStereoRendering) { + int32 _x; + int32 _y; + + pStereoRendering + ->AdjustViewRect(leftEye, _x, _y, stereoLeftSizeX, stereoLeftSizeY); + + pStereoRendering->AdjustViewRect( + rightEye, + _x, + _y, + stereoRightSizeX, + stereoRightSizeY); + } + + FVector2D stereoLeftSize(stereoLeftSizeX, stereoLeftSizeY); + FVector2D stereoRightSize(stereoRightSizeX, stereoRightSizeY); + + if (stereoLeftSize.X >= 1.0 && stereoLeftSize.Y >= 1.0) { + FVector leftEyeLocation = location; + FRotator leftEyeRotation = rotation; + pStereoRendering->CalculateStereoViewOffset( + leftEye, + leftEyeRotation, + worldToMeters, + leftEyeLocation); + + FMatrix projection = + pStereoRendering->GetStereoProjectionMatrix(leftEye); + + // TODO: consider assymetric frustums using 4 fovs + double one_over_tan_half_hfov = projection.M[0][0]; + + double hfov = + glm::degrees(2.0 * glm::atan(1.0 / one_over_tan_half_hfov)); + + cameras.emplace_back( + stereoLeftSize, + leftEyeLocation, + leftEyeRotation, + hfov); + } + + if (stereoRightSize.X >= 1.0 && stereoRightSize.Y >= 1.0) { + FVector rightEyeLocation = location; + FRotator rightEyeRotation = rotation; + pStereoRendering->CalculateStereoViewOffset( + rightEye, + rightEyeRotation, + worldToMeters, + rightEyeLocation); + + FMatrix projection = + pStereoRendering->GetStereoProjectionMatrix(rightEye); + + double one_over_tan_half_hfov = projection.M[0][0]; + + double hfov = + glm::degrees(2.0f * glm::atan(1.0f / one_over_tan_half_hfov)); + + cameras.emplace_back( + stereoRightSize, + rightEyeLocation, + rightEyeRotation, + hfov); + } + } else { + cameras.emplace_back( + FVector2D(sizeX / dpiScalingFactor, sizeY / dpiScalingFactor), + location, + rotation, + fov); + } + } + + return cameras; +} + +std::vector ACesium3DTileset::GetSceneCaptures() const { + // TODO: really USceneCaptureComponent2D can be attached to any actor, is it + // worth searching every actor? Might it be better to provide an interface + // where users can volunteer cameras to be used with the tile selection as + // needed? + TArray sceneCaptures; + static TSubclassOf SceneCapture2D = + ASceneCapture2D::StaticClass(); + UGameplayStatics::GetAllActorsOfClass(this, SceneCapture2D, sceneCaptures); + + std::vector cameras; + cameras.reserve(sceneCaptures.Num()); + + for (AActor* pActor : sceneCaptures) { + ASceneCapture2D* pSceneCapture = static_cast(pActor); + if (!pSceneCapture) { + continue; + } + + USceneCaptureComponent2D* pSceneCaptureComponent = + pSceneCapture->GetCaptureComponent2D(); + if (!pSceneCaptureComponent) { + continue; + } + + if (pSceneCaptureComponent->ProjectionType != + ECameraProjectionMode::Type::Perspective) { + continue; + } + + UTextureRenderTarget2D* pRenderTarget = + pSceneCaptureComponent->TextureTarget; + if (!pRenderTarget) { + continue; + } + + FVector2D renderTargetSize(pRenderTarget->SizeX, pRenderTarget->SizeY); + if (renderTargetSize.X < 1.0 || renderTargetSize.Y < 1.0) { + continue; + } + + FVector captureLocation = pSceneCaptureComponent->GetComponentLocation(); + FRotator captureRotation = pSceneCaptureComponent->GetComponentRotation(); + double captureFov = pSceneCaptureComponent->FOVAngle; + + cameras.emplace_back( + renderTargetSize, + captureLocation, + captureRotation, + captureFov); + } + + return cameras; +} + +/*static*/ Cesium3DTilesSelection::ViewState +ACesium3DTileset::CreateViewStateFromViewParameters( + const FCesiumCamera& camera, + const glm::dmat4& unrealWorldToTileset, + UCesiumEllipsoid* ellipsoid) { + double horizontalFieldOfView = + FMath::DegreesToRadians(camera.FieldOfViewDegrees); + + double actualAspectRatio; + glm::dvec2 size(camera.ViewportSize.X, camera.ViewportSize.Y); + + if (camera.OverrideAspectRatio != 0.0f) { + // Use aspect ratio and recompute effective viewport size after black bars + // are added. + actualAspectRatio = camera.OverrideAspectRatio; + double computedX = actualAspectRatio * camera.ViewportSize.Y; + double computedY = camera.ViewportSize.Y / actualAspectRatio; + + double barWidth = camera.ViewportSize.X - computedX; + double barHeight = camera.ViewportSize.Y - computedY; + + if (barWidth > 0.0 && barWidth > barHeight) { + // Black bars on the sides + size.x = computedX; + } else if (barHeight > 0.0 && barHeight > barWidth) { + // Black bars on the top and bottom + size.y = computedY; + } + } else { + actualAspectRatio = camera.ViewportSize.X / camera.ViewportSize.Y; + } + + double verticalFieldOfView = + atan(tan(horizontalFieldOfView * 0.5) / actualAspectRatio) * 2.0; + + FVector direction = camera.Rotation.RotateVector(FVector(1.0f, 0.0f, 0.0f)); + FVector up = camera.Rotation.RotateVector(FVector(0.0f, 0.0f, 1.0f)); + + glm::dvec3 tilesetCameraLocation = glm::dvec3( + unrealWorldToTileset * + glm::dvec4(camera.Location.X, camera.Location.Y, camera.Location.Z, 1.0)); + glm::dvec3 tilesetCameraFront = glm::normalize(glm::dvec3( + unrealWorldToTileset * + glm::dvec4(direction.X, direction.Y, direction.Z, 0.0))); + glm::dvec3 tilesetCameraUp = glm::normalize( + glm::dvec3(unrealWorldToTileset * glm::dvec4(up.X, up.Y, up.Z, 0.0))); + + return Cesium3DTilesSelection::ViewState::create( + tilesetCameraLocation, + tilesetCameraFront, + tilesetCameraUp, + size, + horizontalFieldOfView, + verticalFieldOfView, + ellipsoid->GetNativeEllipsoid()); +} + +#if WITH_EDITOR +std::vector ACesium3DTileset::GetEditorCameras() const { + if (!GEditor) { + return {}; + } + + UWorld* pWorld = this->GetWorld(); + if (!IsValid(pWorld)) { + return {}; + } + + // Do not include editor cameras when running in a game world (which includes + // Play-in-Editor) + if (pWorld->IsGameWorld()) { + return {}; + } + + const TArray& viewportClients = + GEditor->GetAllViewportClients(); + + std::vector cameras; + cameras.reserve(viewportClients.Num()); + + for (FEditorViewportClient* pEditorViewportClient : viewportClients) { + if (!pEditorViewportClient) { + continue; + } + + if (!pEditorViewportClient->IsVisible() || + !pEditorViewportClient->IsRealtime() || + !pEditorViewportClient->IsPerspective()) { + continue; + } + + FRotator rotation; + if (pEditorViewportClient->bUsingOrbitCamera) { + rotation = (pEditorViewportClient->GetLookAtLocation() - + pEditorViewportClient->GetViewLocation()) + .Rotation(); + } else { + rotation = pEditorViewportClient->GetViewRotation(); + } + + const FVector& location = pEditorViewportClient->GetViewLocation(); + double fov = pEditorViewportClient->ViewFOV; + FIntPoint offset; + FIntPoint size; + pEditorViewportClient->GetViewportDimensions(offset, size); + + if (size.X < 1 || size.Y < 1) { + continue; + } + + if (this->_scaleUsingDPI) { + float dpiScalingFactor = pEditorViewportClient->GetDPIScale(); + size.X = static_cast(size.X) / dpiScalingFactor; + size.Y = static_cast(size.Y) / dpiScalingFactor; + } + + if (pEditorViewportClient->IsAspectRatioConstrained()) { + cameras.emplace_back( + size, + location, + rotation, + fov, + pEditorViewportClient->AspectRatio); + } else { + cameras.emplace_back(size, location, rotation, fov); + } + } + + return cameras; +} +#endif + +bool ACesium3DTileset::ShouldTickIfViewportsOnly() const { + return this->UpdateInEditor; +} + +namespace { +template +void forEachRenderableTile(const auto& tiles, Func&& f) { + for (Cesium3DTilesSelection::Tile* pTile : tiles) { + if (!pTile || + pTile->getState() != Cesium3DTilesSelection::TileLoadState::Done) { + continue; + } + + const Cesium3DTilesSelection::TileContent& content = pTile->getContent(); + const Cesium3DTilesSelection::TileRenderContent* pRenderContent = + content.getRenderContent(); + if (!pRenderContent) { + continue; + } + + UCesiumGltfComponent* Gltf = static_cast( + pRenderContent->getRenderResources()); + if (!Gltf) { + // When a tile does not have render resources (i.e. a glTF), then + // the resources either have not yet been loaded or prepared, + // or the tile is from an external tileset and does not directly + // own renderable content. In both cases, the tile is ignored here. + continue; + } + + f(pTile, Gltf); + } +} + +void removeVisibleTilesFromList( + std::vector& list, + const std::vector& visibleTiles) { + if (list.empty()) { + return; + } + + for (Cesium3DTilesSelection::Tile* pTile : visibleTiles) { + auto it = std::find(list.begin(), list.end(), pTile); + if (it != list.end()) { + list.erase(it); + } + } +} + +/** + * @brief Hides the visual representations of the given tiles. + * + * The visual representations (i.e. the `getRendererResources` of the + * tiles) are assumed to be `UCesiumGltfComponent` instances that + * are made invisible by this call. + * + * @param tiles The tiles to hide + */ +void hideTiles(const std::vector& tiles) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::HideTiles) + forEachRenderableTile( + tiles, + [](Cesium3DTilesSelection::Tile* /*pTile*/, UCesiumGltfComponent* pGltf) { + if (pGltf->IsVisible()) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetVisibilityFalse) + pGltf->SetVisibility(false, true); + } else { + // TODO: why is this happening? + UE_LOG( + LogCesium, + Verbose, + TEXT("Tile to no longer render does not have a visible Gltf")); + } + }); +} + +/** + * @brief Removes collision for tiles that have been removed from the render + * list. This includes tiles that are fading out. + */ +void removeCollisionForTiles( + const std::unordered_set& tiles) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::RemoveCollisionForTiles) + forEachRenderableTile( + tiles, + [](Cesium3DTilesSelection::Tile* /*pTile*/, UCesiumGltfComponent* pGltf) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetCollisionDisabled) + pGltf->SetCollisionEnabled(ECollisionEnabled::NoCollision); + }); +} + +/** + * @brief Applies the actor collision settings for a newly created glTF + * component + * + * TODO Add details here what that means + * @param BodyInstance ... + * @param Gltf ... + */ +void applyActorCollisionSettings( + const FBodyInstance& BodyInstance, + UCesiumGltfComponent* Gltf) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ApplyActorCollisionSettings) + + const TArray& ChildrenComponents = + Gltf->GetAttachChildren(); + + for (USceneComponent* ChildComponent : ChildrenComponents) { + UCesiumGltfPrimitiveComponent* PrimitiveComponent = + Cast(ChildComponent); + if (PrimitiveComponent != nullptr) { + if (PrimitiveComponent->GetCollisionObjectType() != + BodyInstance.GetObjectType()) { + PrimitiveComponent->SetCollisionObjectType( + BodyInstance.GetObjectType()); + } + const UEnum* ChannelEnum = StaticEnum(); + if (ChannelEnum) { + FCollisionResponseContainer responseContainer = + BodyInstance.GetResponseToChannels(); + PrimitiveComponent->SetCollisionResponseToChannels(responseContainer); + } + } + } +} +} // namespace + +void ACesium3DTileset::updateTilesetOptionsFromProperties() { + Cesium3DTilesSelection::TilesetOptions& options = + this->_pTileset->getOptions(); + options.maximumScreenSpaceError = + static_cast(this->MaximumScreenSpaceError); + options.maximumCachedBytes = this->MaximumCachedBytes; + options.preloadAncestors = this->PreloadAncestors; + options.preloadSiblings = this->PreloadSiblings; + options.forbidHoles = this->ForbidHoles; + options.maximumSimultaneousTileLoads = this->MaximumSimultaneousTileLoads; + options.loadingDescendantLimit = this->LoadingDescendantLimit; + options.enableFrustumCulling = this->EnableFrustumCulling; + options.enableOcclusionCulling = + GetDefault() + ->EnableExperimentalOcclusionCullingFeature && + this->EnableOcclusionCulling; + options.showCreditsOnScreen = this->ShowCreditsOnScreen; + + options.delayRefinementForOcclusion = this->DelayRefinementForOcclusion; + options.enableFogCulling = this->EnableFogCulling; + options.enforceCulledScreenSpaceError = this->EnforceCulledScreenSpaceError; + options.culledScreenSpaceError = + static_cast(this->CulledScreenSpaceError); + options.enableLodTransitionPeriod = this->UseLodTransitions; + options.lodTransitionLength = this->LodTransitionLength; + // options.kickDescendantsWhileFadingIn = false; +} + +void ACesium3DTileset::updateLastViewUpdateResultState( + const Cesium3DTilesSelection::ViewUpdateResult& result) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateLastViewUpdateResultState) + + if (this->DrawTileInfo) { + const UWorld* World = GetWorld(); + check(World); + + const TSoftObjectPtr Georeference = + ResolveGeoreference(); + check(Georeference); + + for (Cesium3DTilesSelection::Tile* tile : result.tilesToRenderThisFrame) { + CesiumGeometry::OrientedBoundingBox obb = + Cesium3DTilesSelection::getOrientedBoundingBoxFromBoundingVolume( + tile->getBoundingVolume(), + Georeference->GetEllipsoid()->GetNativeEllipsoid()); + + FVector unrealCenter = + Georeference->TransformEarthCenteredEarthFixedPositionToUnreal( + VecMath::createVector(obb.getCenter())); + + FString text = FString::Printf( + TEXT("ID %s (%p)"), + UTF8_TO_TCHAR( + Cesium3DTilesSelection::TileIdUtilities::createTileIdString( + tile->getTileID()) + .c_str()), + tile); + + DrawDebugString(World, unrealCenter, text, nullptr, FColor::Red, 0, true); + } + } + +#ifdef CESIUM_DEBUG_TILE_STATES + if (this->_pStateDebug && GetWorld()->IsPlayInEditor()) { + this->_pStateDebug->recordAllTileStates( + result.frameNumber, + *this->_pTileset); + } +#endif + + if (!this->LogSelectionStats && !this->LogSharedAssetStats) { + return; + } + + if (result.tilesToRenderThisFrame.size() != this->_lastTilesRendered || + result.workerThreadTileLoadQueueLength != + this->_lastWorkerThreadTileLoadQueueLength || + result.mainThreadTileLoadQueueLength != + this->_lastMainThreadTileLoadQueueLength || + result.tilesVisited != this->_lastTilesVisited || + result.culledTilesVisited != this->_lastCulledTilesVisited || + result.tilesCulled != this->_lastTilesCulled || + result.tilesOccluded != this->_lastTilesOccluded || + result.tilesWaitingForOcclusionResults != + this->_lastTilesWaitingForOcclusionResults || + result.maxDepthVisited != this->_lastMaxDepthVisited) { + this->_lastTilesRendered = result.tilesToRenderThisFrame.size(); + this->_lastWorkerThreadTileLoadQueueLength = + result.workerThreadTileLoadQueueLength; + this->_lastMainThreadTileLoadQueueLength = + result.mainThreadTileLoadQueueLength; + + this->_lastTilesVisited = result.tilesVisited; + this->_lastCulledTilesVisited = result.culledTilesVisited; + this->_lastTilesCulled = result.tilesCulled; + this->_lastTilesOccluded = result.tilesOccluded; + this->_lastTilesWaitingForOcclusionResults = + result.tilesWaitingForOcclusionResults; + this->_lastMaxDepthVisited = result.maxDepthVisited; + + if (this->LogSelectionStats) { + UE_LOG( + LogCesium, + Display, + TEXT( + "%s: %d ms, Unreal Frame #%d, Tileset Frame: #%d, Visited %d, Culled Visited %d, Rendered %d, Culled %d, Occluded %d, Waiting For Occlusion Results %d, Max Depth Visited: %d, Loading-Worker %d, Loading-Main %d, Loaded tiles %g%%"), + *this->GetName(), + (std::chrono::high_resolution_clock::now() - this->_startTime) + .count() / + 1000000, + GFrameCounter, + result.frameNumber, + result.tilesVisited, + result.culledTilesVisited, + result.tilesToRenderThisFrame.size(), + result.tilesCulled, + result.tilesOccluded, + result.tilesWaitingForOcclusionResults, + result.maxDepthVisited, + result.workerThreadTileLoadQueueLength, + result.mainThreadTileLoadQueueLength, + this->LoadProgress); + } + + if (this->LogSharedAssetStats && this->_pTileset) { + const Cesium3DTilesSelection::TilesetSharedAssetSystem::ImageDepot& + imageDepot = *this->_pTileset->getSharedAssetSystem().pImage; + UE_LOG( + LogCesium, + Display, + TEXT( + "Images shared asset depot: %d distinct assets, %d inactive assets pending deletion (%d bytes)"), + imageDepot.getAssetCount(), + imageDepot.getInactiveAssetCount(), + imageDepot.getInactiveAssetTotalSizeBytes()); + } + } +} + +void ACesium3DTileset::showTilesToRender( + const std::vector& tiles) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ShowTilesToRender) + forEachRenderableTile( + tiles, + [&RootComponent = this->RootComponent, + &BodyInstance = this->BodyInstance]( + Cesium3DTilesSelection::Tile* pTile, + UCesiumGltfComponent* pGltf) { + applyActorCollisionSettings(BodyInstance, pGltf); + + if (pGltf->GetAttachParent() == nullptr) { + // The AttachToComponent method is ridiculously complex, + // so print a warning if attaching fails for some reason + bool attached = pGltf->AttachToComponent( + RootComponent, + FAttachmentTransformRules::KeepRelativeTransform); + if (!attached) { + FString tileIdString( + Cesium3DTilesSelection::TileIdUtilities::createTileIdString( + pTile->getTileID()) + .c_str()); + UE_LOG( + LogCesium, + Warning, + TEXT("Tile %s could not be attached to root"), + *tileIdString); + } + } + + if (!pGltf->IsVisible()) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetVisibilityTrue) + pGltf->SetVisibility(true, true); + } + + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetCollisionEnabled) + pGltf->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); + } + }); +} + +static void updateTileFades(const auto& tiles, bool fadingIn) { + forEachRenderableTile( + tiles, + [fadingIn]( + Cesium3DTilesSelection::Tile* pTile, + UCesiumGltfComponent* pGltf) { + float percentage = pTile->getContent() + .getRenderContent() + ->getLodTransitionFadePercentage(); + pGltf->UpdateFade(percentage, fadingIn); + }); +} + +// Called every frame +void ACesium3DTileset::Tick(float DeltaTime) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::TilesetTick) + + Super::Tick(DeltaTime); + + this->ResolveGeoreference(); + this->ResolveCameraManager(); + this->ResolveCreditSystem(); + + UCesium3DTilesetRoot* pRoot = Cast(this->RootComponent); + if (!pRoot) { + return; + } + + if (this->SuspendUpdate) { + return; + } + + if (!this->_pTileset) { + LoadTileset(); + + // In the unlikely event that we _still_ don't have a tileset, stop here so + // we don't crash below. This shouldn't happen. + if (!this->_pTileset) { + assert(false); + return; + } + } + + if (this->BoundingVolumePoolComponent && this->_cesiumViewExtension) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateOcclusion) + const TArray& children = + this->BoundingVolumePoolComponent->GetAttachChildren(); + for (USceneComponent* pChild : children) { + UCesiumBoundingVolumeComponent* pBoundingVolume = + Cast(pChild); + + if (!pBoundingVolume) { + continue; + } + + pBoundingVolume->UpdateOcclusion(*this->_cesiumViewExtension.Get()); + } + } + + updateTilesetOptionsFromProperties(); + + std::vector cameras = this->GetCameras(); + + glm::dmat4 ueTilesetToUeWorld = + VecMath::createMatrix4D(this->GetActorTransform().ToMatrixWithScale()); + + const glm::dmat4& cesiumTilesetToUeTileset = + this->GetCesiumTilesetToUnrealRelativeWorldTransform(); + glm::dmat4 unrealWorldToCesiumTileset = + glm::affineInverse(ueTilesetToUeWorld * cesiumTilesetToUeTileset); + + if (glm::isnan(unrealWorldToCesiumTileset[3].x) || + glm::isnan(unrealWorldToCesiumTileset[3].y) || + glm::isnan(unrealWorldToCesiumTileset[3].z)) { + // Probably caused by a zero scale. + return; + } + + UCesiumEllipsoid* ellipsoid = this->ResolveGeoreference()->GetEllipsoid(); + + std::vector frustums; + for (const FCesiumCamera& camera : cameras) { + frustums.push_back(CreateViewStateFromViewParameters( + camera, + unrealWorldToCesiumTileset, + ellipsoid)); + } + + const Cesium3DTilesSelection::ViewUpdateResult* pResult; + if (this->_captureMovieMode) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateViewOffline) + pResult = &this->_pTileset->updateViewOffline(frustums); + } else { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateView) + pResult = &this->_pTileset->updateView(frustums, DeltaTime); + } + updateLastViewUpdateResultState(*pResult); + + removeCollisionForTiles(pResult->tilesFadingOut); + + removeVisibleTilesFromList( + _tilesToHideNextFrame, + pResult->tilesToRenderThisFrame); + hideTiles(_tilesToHideNextFrame); + + _tilesToHideNextFrame.clear(); + for (Cesium3DTilesSelection::Tile* pTile : pResult->tilesFadingOut) { + Cesium3DTilesSelection::TileRenderContent* pRenderContent = + pTile->getContent().getRenderContent(); + if (!this->UseLodTransitions || + (pRenderContent && + pRenderContent->getLodTransitionFadePercentage() >= 1.0f)) { + _tilesToHideNextFrame.push_back(pTile); + } + } + + showTilesToRender(pResult->tilesToRenderThisFrame); + + if (this->UseLodTransitions) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTileFades) + updateTileFades(pResult->tilesToRenderThisFrame, true); + updateTileFades(pResult->tilesFadingOut, false); + } + + this->UpdateLoadStatus(); +} + +void ACesium3DTileset::EndPlay(const EEndPlayReason::Type EndPlayReason) { + this->DestroyTileset(); + AActor::EndPlay(EndPlayReason); +} + +void ACesium3DTileset::PostLoad() { + BodyInstance.FixupData(this); // We need to call this one after Loading the + // actor to have correct BodyInstance values. + + Super::PostLoad(); + + if (CesiumActors::shouldValidateFlags(this)) + CesiumActors::validateActorFlags(this); + +#if WITH_EDITOR + const int32 CesiumVersion = + this->GetLinkerCustomVersion(FCesiumCustomVersion::GUID); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + if (CesiumVersion < FCesiumCustomVersion::CesiumIonServer) { + this->CesiumIonServer = UCesiumIonServer::GetBackwardCompatibleServer( + this->IonAssetEndpointUrl_DEPRECATED); + } + PRAGMA_ENABLE_DEPRECATION_WARNINGS +#endif +} + +void ACesium3DTileset::Serialize(FArchive& Ar) { + Super::Serialize(Ar); + + Ar.UsingCustomVersion(FCesiumCustomVersion::GUID); + + const int32 CesiumVersion = Ar.CustomVer(FCesiumCustomVersion::GUID); + + if (CesiumVersion < FCesiumCustomVersion::TilesetExplicitSource) { + // In previous versions, the tileset source was inferred from the presence + // of a non-empty URL property, rather than being explicitly specified. + if (this->Url.Len() > 0) { + this->TilesetSource = ETilesetSource::FromUrl; + } else { + this->TilesetSource = ETilesetSource::FromCesiumIon; + } + } + + if (CesiumVersion < FCesiumCustomVersion::TilesetMobilityRemoved) { + this->RootComponent->SetMobility(this->Mobility_DEPRECATED); + } +} + +#if WITH_EDITOR +void ACesium3DTileset::PostEditChangeProperty( + FPropertyChangedEvent& PropertyChangedEvent) { + Super::PostEditChangeProperty(PropertyChangedEvent); + + if (!PropertyChangedEvent.Property) { + return; + } + + FName PropName = PropertyChangedEvent.Property->GetFName(); + FString PropNameAsString = PropertyChangedEvent.Property->GetName(); + + if (PropName == GET_MEMBER_NAME_CHECKED(ACesium3DTileset, TilesetSource) || + PropName == GET_MEMBER_NAME_CHECKED(ACesium3DTileset, Url) || + PropName == GET_MEMBER_NAME_CHECKED(ACesium3DTileset, IonAssetID) || + PropName == GET_MEMBER_NAME_CHECKED(ACesium3DTileset, IonAccessToken) || + PropName == + GET_MEMBER_NAME_CHECKED(ACesium3DTileset, CreatePhysicsMeshes) || + PropName == + GET_MEMBER_NAME_CHECKED(ACesium3DTileset, CreateNavCollision) || + PropName == + GET_MEMBER_NAME_CHECKED(ACesium3DTileset, AlwaysIncludeTangents) || + PropName == + GET_MEMBER_NAME_CHECKED(ACesium3DTileset, GenerateSmoothNormals) || + PropName == GET_MEMBER_NAME_CHECKED(ACesium3DTileset, EnableWaterMask) || + PropName == + GET_MEMBER_NAME_CHECKED(ACesium3DTileset, IgnoreKhrMaterialsUnlit) || + PropName == GET_MEMBER_NAME_CHECKED(ACesium3DTileset, Material) || + PropName == + GET_MEMBER_NAME_CHECKED(ACesium3DTileset, TranslucentMaterial) || + PropName == GET_MEMBER_NAME_CHECKED(ACesium3DTileset, WaterMaterial) || + PropName == GET_MEMBER_NAME_CHECKED(ACesium3DTileset, ApplyDpiScaling) || + PropName == + GET_MEMBER_NAME_CHECKED(ACesium3DTileset, EnableOcclusionCulling) || + PropName == + GET_MEMBER_NAME_CHECKED(ACesium3DTileset, UseLodTransitions) || + PropName == + GET_MEMBER_NAME_CHECKED(ACesium3DTileset, ShowCreditsOnScreen) || + PropName == GET_MEMBER_NAME_CHECKED(ACesium3DTileset, Root) || + PropName == GET_MEMBER_NAME_CHECKED(ACesium3DTileset, CesiumIonServer) || + // For properties nested in structs, GET_MEMBER_NAME_CHECKED will prefix + // with the struct name, so just do a manual string comparison. + PropNameAsString == TEXT("RenderCustomDepth") || + PropNameAsString == TEXT("CustomDepthStencilValue") || + PropNameAsString == TEXT("CustomDepthStencilWriteMask")) { + this->DestroyTileset(); + } else if ( + PropName == GET_MEMBER_NAME_CHECKED(ACesium3DTileset, Georeference)) { + this->InvalidateResolvedGeoreference(); + } else if ( + PropName == GET_MEMBER_NAME_CHECKED(ACesium3DTileset, CreditSystem)) { + this->InvalidateResolvedCreditSystem(); + } else if ( + PropName == + GET_MEMBER_NAME_CHECKED(ACesium3DTileset, MaximumScreenSpaceError)) { + TArray rasterOverlays; + this->GetComponents(rasterOverlays); + + for (UCesiumRasterOverlay* pOverlay : rasterOverlays) { + pOverlay->Refresh(); + } + TArray tileExcluders; + this->GetComponents(tileExcluders); + + for (UCesiumTileExcluder* pTileExcluder : tileExcluders) { + pTileExcluder->Refresh(); + } + + // Maximum Screen Space Error can affect how attenuated points are rendered, + // so propagate the new value to the render proxies for this tileset. + FCesiumGltfPointsSceneProxyUpdater::UpdateSettingsInProxies(this); + } +} + +void ACesium3DTileset::PostEditChangeChainProperty( + FPropertyChangedChainEvent& PropertyChangedChainEvent) { + Super::PostEditChangeChainProperty(PropertyChangedChainEvent); + + if (!PropertyChangedChainEvent.Property || + PropertyChangedChainEvent.PropertyChain.IsEmpty()) { + return; + } + + FName PropName = + PropertyChangedChainEvent.PropertyChain.GetHead()->GetValue()->GetFName(); + if (PropName == + GET_MEMBER_NAME_CHECKED(ACesium3DTileset, PointCloudShading)) { + FCesiumGltfPointsSceneProxyUpdater::UpdateSettingsInProxies(this); + } +} + +void ACesium3DTileset::PostEditUndo() { + Super::PostEditUndo(); + + // It doesn't appear to be possible to get detailed information about what + // changed in the undo/redo operation, so we have to assume the worst and + // recreate the tileset. + this->DestroyTileset(); +} + +void ACesium3DTileset::PostEditImport() { + Super::PostEditImport(); + + // Recreate the tileset on Paste. + this->DestroyTileset(); +} +#endif + +void ACesium3DTileset::BeginDestroy() { + this->InvalidateResolvedGeoreference(); + this->DestroyTileset(); + + AActor::BeginDestroy(); +} + +bool ACesium3DTileset::IsReadyForFinishDestroy() { + bool ready = AActor::IsReadyForFinishDestroy(); + ready &= this->_tilesetsBeingDestroyed == 0; + + if (!ready) { + getAssetAccessor()->tick(); + getAsyncSystem().dispatchMainThreadTasks(); + } + + return ready; +} + +void ACesium3DTileset::Destroyed() { + this->DestroyTileset(); + + AActor::Destroyed(); +} + +#if WITH_EDITOR +void ACesium3DTileset::RuntimeSettingsChanged( + UObject* pObject, + struct FPropertyChangedEvent& changed) { + bool occlusionCullingAvailable = + GetDefault() + ->EnableExperimentalOcclusionCullingFeature; + if (occlusionCullingAvailable != this->CanEnableOcclusionCulling) { + this->CanEnableOcclusionCulling = occlusionCullingAvailable; + this->RefreshTileset(); + } +} +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTilesetRoot.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTilesetRoot.cpp new file mode 100644 index 0000000..89882dd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTilesetRoot.cpp @@ -0,0 +1,71 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "Cesium3DTilesetRoot.h" +#include "Cesium3DTileset.h" +#include "CesiumRuntime.h" +#include "CesiumUtility/Math.h" +#include "Engine/World.h" +#include "VecMath.h" + +UCesium3DTilesetRoot::UCesium3DTilesetRoot() + : _absoluteLocation(0.0, 0.0, 0.0), _tilesetToUnrealRelativeWorld(1.0) { + PrimaryComponentTick.bCanEverTick = false; +} + +void UCesium3DTilesetRoot::HandleGeoreferenceUpdated() { + UE_LOG( + LogCesium, + Verbose, + TEXT("Called HandleGeoreferenceUpdated for tileset root %s"), + *this->GetName()); + this->_updateTilesetToUnrealRelativeWorldTransform(); +} + +const glm::dmat4& +UCesium3DTilesetRoot::GetCesiumTilesetToUnrealRelativeWorldTransform() const { + return this->_tilesetToUnrealRelativeWorld; +} + +// Called when the game starts +void UCesium3DTilesetRoot::BeginPlay() { + Super::BeginPlay(); + + this->_updateAbsoluteLocation(); + this->_updateTilesetToUnrealRelativeWorldTransform(); +} + +bool UCesium3DTilesetRoot::MoveComponentImpl( + const FVector& Delta, + const FQuat& NewRotation, + bool bSweep, + FHitResult* OutHit, + EMoveComponentFlags MoveFlags, + ETeleportType Teleport) { + bool result = USceneComponent::MoveComponentImpl( + Delta, + NewRotation, + bSweep, + OutHit, + MoveFlags, + Teleport); + + this->_updateAbsoluteLocation(); + this->_updateTilesetToUnrealRelativeWorldTransform(); + + return result; +} + +void UCesium3DTilesetRoot::_updateAbsoluteLocation() { + const FVector& newLocation = this->GetRelativeLocation(); + this->_absoluteLocation = VecMath::createVector3D(newLocation); +} + +void UCesium3DTilesetRoot::_updateTilesetToUnrealRelativeWorldTransform() { + ACesium3DTileset* pTileset = this->GetOwner(); + + this->_tilesetToUnrealRelativeWorld = VecMath::createMatrix4D( + pTileset->ResolveGeoreference() + ->ComputeEarthCenteredEarthFixedToUnrealTransformation()); + + pTileset->UpdateTransformFromCesium(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTilesetRoot.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTilesetRoot.h new file mode 100644 index 0000000..a7307e0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTilesetRoot.h @@ -0,0 +1,56 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Components/SceneComponent.h" +#include +#include +#include "Cesium3DTilesetRoot.generated.h" + +UCLASS() +class UCesium3DTilesetRoot : public USceneComponent { + GENERATED_BODY() + +public: + UCesium3DTilesetRoot(); + + /** + * @brief Gets the transform from the "Cesium Tileset" reference frame to the + * "Unreal Relative World" reference frame. + * + * Gets a matrix that transforms coordinates from the "Cesium Tileset" + * reference frame (which is _usually_ Earth-centered, Earth-fixed) to Unreal + * Engine's relative world coordinates (i.e. relative to the world + * OriginLocation). + * + * See {@link reference-frames.md}. + * + * This transformation is a function of : + * * The location of the Tileset in "Unreal Absolute World" coordinates. + * * The rotation and scale of the tileset relative to the Unreal World. + * * `UWorld::OriginLocation` + * * The transformation from ellipsoid-centered to georeferenced + * coordinates, as provided by `CesiumGeoreference`. + */ + const glm::dmat4& GetCesiumTilesetToUnrealRelativeWorldTransform() const; + + UFUNCTION() + void HandleGeoreferenceUpdated(); + +protected: + virtual void BeginPlay() override; + virtual bool MoveComponentImpl( + const FVector& Delta, + const FQuat& NewRotation, + bool bSweep, + FHitResult* OutHit = NULL, + EMoveComponentFlags MoveFlags = MOVECOMP_NoFlags, + ETeleportType Teleport = ETeleportType::None) override; + +private: + void _updateAbsoluteLocation(); + void _updateTilesetToUnrealRelativeWorldTransform(); + + glm::dvec3 _absoluteLocation; + glm::dmat4 _tilesetToUnrealRelativeWorld; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumActors.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumActors.cpp new file mode 100644 index 0000000..a585eef --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumActors.cpp @@ -0,0 +1,79 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumActors.h" +#include "CesiumRuntime.h" +#include "Engine/World.h" + +#if WITH_EDITOR +#include "Editor.h" +#endif + +#include + +glm::dvec4 CesiumActors::getWorldOrigin4D(const AActor* actor) { + if (!IsValid(actor)) { + UE_LOG(LogCesium, Warning, TEXT("The actor is not valid")); + return glm::dvec4(); + } + const UWorld* world = actor->GetWorld(); + if (!IsValid(world)) { + UE_LOG( + LogCesium, + Warning, + TEXT("The actor %s is not spawned in a level"), + *actor->GetName()); + return glm::dvec4(); + } + const FIntVector& originLocation = world->OriginLocation; + return glm::dvec4(originLocation.X, originLocation.Y, originLocation.Z, 1.0); +} + +bool CesiumActors::shouldValidateFlags(UObject* object) { +#if WITH_EDITOR + // Only fixup flags in the editor, when not in play mode + if (!IsValid(GEditor) || GEditor->IsPlaySessionInProgress()) + return false; + + // In addition, don't fix when loading from an asset file, which sets the + // RF_ClassDefaultObject and RF_ArchetypeObject flags. + if (object->HasAnyFlags(RF_ClassDefaultObject) || + object->HasAnyFlags(RF_ArchetypeObject)) + return false; + else + return true; +#else + return false; +#endif +} + +void CesiumActors::validatePublicFlag(UObject* object, const FString& label) { + // + // From an Epic Engine Developer... + // RF_Public means that the object is an asset, so it should be only set for + // worlds, textures, meshes, etc. This flags essentially says it's ok to + // have a reference to public objects from other packages (with the + // exception of worlds). Actors are not assets since they are part of a + // level which is part of a world, etc. that's why they should not key the + // public flag. + // + // In earlier versions of cesium-unreal, this flag may have been set + // + if (object->HasAnyFlags(RF_Public)) { + UE_LOG( + LogCesium, + Display, + TEXT("Clearing invalid RF_Public flag on %s"), + *label); + object->ClearFlags(RF_Public); + } +} + +void CesiumActors::validateActorFlags(AActor* actor) { + FString label = FString("actor: ") + *actor->GetName(); + validatePublicFlag(actor, label); +} + +void CesiumActors::validateActorComponentFlags(UActorComponent* component) { + FString label = FString("actor component: ") + *component->GetName(); + validatePublicFlag(component, label); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumActors.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumActors.h new file mode 100644 index 0000000..fec2cda --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumActors.h @@ -0,0 +1,38 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "GameFramework/Actor.h" +#include + +#define CESIUM_POST_EDIT_CHANGE(changedPropertyName, ClassName, PropertyName) \ + if (changedPropertyName == \ + GET_MEMBER_NAME_CHECKED(ClassName, PropertyName)) { \ + this->Set##PropertyName(this->PropertyName); \ + return; \ + } + +/** + * @brief Utility functions related to Unreal actors + */ +class CesiumActors { +public: + /** + * @brief Returns the origin location of the world that the given + * actor is contained in. + * + * If the given actor is not valid or not contained in a world, + * then a warning is printed and (0,0,0,0) is returned. + * + * @param actor The actor + * @return The world origin + */ + static glm::dvec4 getWorldOrigin4D(const AActor* actor); + + static bool shouldValidateFlags(UObject* object); + static void validateActorFlags(AActor* actor); + static void validateActorComponentFlags(UActorComponent* component); + +private: + static void validatePublicFlag(UObject* object, const FString& label); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBingMapsRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBingMapsRasterOverlay.cpp new file mode 100644 index 0000000..bcc7c00 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBingMapsRasterOverlay.cpp @@ -0,0 +1,47 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumBingMapsRasterOverlay.h" +#include "Cesium3DTilesSelection/Tileset.h" +#include "CesiumRasterOverlays/BingMapsRasterOverlay.h" + +std::unique_ptr +UCesiumBingMapsRasterOverlay::CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options) { + std::string mapStyle; + + switch (this->MapStyle) { + case EBingMapsStyle::Aerial: + mapStyle = CesiumRasterOverlays::BingMapsStyle::AERIAL; + break; + case EBingMapsStyle::AerialWithLabelsOnDemand: + mapStyle = + CesiumRasterOverlays::BingMapsStyle::AERIAL_WITH_LABELS_ON_DEMAND; + break; + case EBingMapsStyle::RoadOnDemand: + mapStyle = CesiumRasterOverlays::BingMapsStyle::ROAD_ON_DEMAND; + break; + case EBingMapsStyle::CanvasDark: + mapStyle = CesiumRasterOverlays::BingMapsStyle::CANVAS_DARK; + break; + case EBingMapsStyle::CanvasLight: + mapStyle = CesiumRasterOverlays::BingMapsStyle::CANVAS_LIGHT; + break; + case EBingMapsStyle::CanvasGray: + mapStyle = CesiumRasterOverlays::BingMapsStyle::CANVAS_GRAY; + break; + case EBingMapsStyle::OrdnanceSurvey: + mapStyle = CesiumRasterOverlays::BingMapsStyle::ORDNANCE_SURVEY; + break; + case EBingMapsStyle::CollinsBart: + mapStyle = CesiumRasterOverlays::BingMapsStyle::COLLINS_BART; + break; + } + + return std::make_unique( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + "https://dev.virtualearth.net", + TCHAR_TO_UTF8(*this->BingMapsKey), + mapStyle, + "", + options); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBoundingVolumeComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBoundingVolumeComponent.cpp new file mode 100644 index 0000000..7f51736 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBoundingVolumeComponent.cpp @@ -0,0 +1,157 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumBoundingVolumeComponent.h" +#include "CalcBounds.h" +#include "CesiumCommon.h" +#include "CesiumGeoreference.h" +#include "CesiumLifetime.h" +#include "UObject/UObjectGlobals.h" +#include "VecMath.h" +#include +#include + +using namespace Cesium3DTilesSelection; + +UCesiumBoundingVolumePoolComponent::UCesiumBoundingVolumePoolComponent() + : _cesiumToUnreal(1.0) { + SetMobility(EComponentMobility::Movable); +} + +void UCesiumBoundingVolumePoolComponent::initPool(int32 maxPoolSize) { + this->_pPool = std::make_shared(this, maxPoolSize); +} + +TileOcclusionRendererProxy* UCesiumBoundingVolumePoolComponent::createProxy() { + UCesiumBoundingVolumeComponent* pBoundingVolume = + NewObject(this); + pBoundingVolume->SetVisibility(false); + pBoundingVolume->bUseAsOccluder = false; + + pBoundingVolume->SetMobility(EComponentMobility::Movable); + pBoundingVolume->SetFlags( + RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + pBoundingVolume->SetupAttachment(this); + pBoundingVolume->RegisterComponent(); + + pBoundingVolume->UpdateTransformFromCesium(this->_cesiumToUnreal); + + return (TileOcclusionRendererProxy*)pBoundingVolume; +} + +void UCesiumBoundingVolumePoolComponent::destroyProxy( + TileOcclusionRendererProxy* pProxy) { + UCesiumBoundingVolumeComponent* pBoundingVolumeComponent = + (UCesiumBoundingVolumeComponent*)pProxy; + if (pBoundingVolumeComponent) { + CesiumLifetime::destroyComponentRecursively(pBoundingVolumeComponent); + } +} + +UCesiumBoundingVolumePoolComponent::CesiumBoundingVolumePool:: + CesiumBoundingVolumePool( + UCesiumBoundingVolumePoolComponent* pOutter, + int32 maxPoolSize) + : TileOcclusionRendererProxyPool(maxPoolSize), _pOutter(pOutter) {} + +TileOcclusionRendererProxy* +UCesiumBoundingVolumePoolComponent::CesiumBoundingVolumePool::createProxy() { + return this->_pOutter->createProxy(); +} + +void UCesiumBoundingVolumePoolComponent::CesiumBoundingVolumePool::destroyProxy( + TileOcclusionRendererProxy* pProxy) { + this->_pOutter->destroyProxy(pProxy); +} + +void UCesiumBoundingVolumePoolComponent::UpdateTransformFromCesium( + const glm::dmat4& CesiumToUnrealTransform) { + this->_cesiumToUnreal = CesiumToUnrealTransform; + + const TArray& children = this->GetAttachChildren(); + for (USceneComponent* pChild : children) { + UCesiumBoundingVolumeComponent* pBoundingVolume = + Cast(pChild); + if (pBoundingVolume) { + pBoundingVolume->UpdateTransformFromCesium(CesiumToUnrealTransform); + } + } +} + +class FCesiumBoundingVolumeSceneProxy : public FPrimitiveSceneProxy { +public: + FCesiumBoundingVolumeSceneProxy(UCesiumBoundingVolumeComponent* pComponent) + : FPrimitiveSceneProxy(pComponent /*, name?*/) {} + SIZE_T GetTypeHash() const override { + static size_t UniquePointer; + return reinterpret_cast(&UniquePointer); + } + + uint32 GetMemoryFootprint(void) const override { + return sizeof(FCesiumBoundingVolumeSceneProxy) + GetAllocatedSize(); + } +}; + +FPrimitiveSceneProxy* UCesiumBoundingVolumeComponent::CreateSceneProxy() { + return new FCesiumBoundingVolumeSceneProxy(this); +} + +void UCesiumBoundingVolumeComponent::UpdateOcclusion( + const CesiumViewExtension& cesiumViewExtension) { + if (!_isMapped) { + return; + } + +#if ENGINE_VERSION_5_4_OR_HIGHER + FPrimitiveComponentId componentId = this->GetPrimitiveSceneId(); +#else + FPrimitiveComponentId componentId = this->ComponentId; +#endif + + TileOcclusionState occlusionState = + cesiumViewExtension.getPrimitiveOcclusionState( + componentId, + _occlusionState == TileOcclusionState::Occluded, + _mappedFrameTime); + + // If the occlusion result is unavailable, continue using the previous result. + if (occlusionState != TileOcclusionState::OcclusionUnavailable) { + _occlusionState = occlusionState; + } +} + +void UCesiumBoundingVolumeComponent::_updateTransform() { + const FTransform transform = FTransform( + VecMath::createMatrix(this->_cesiumToUnreal * this->_tileTransform)); + + this->SetRelativeTransform_Direct(transform); + this->SetComponentToWorld(transform); + this->MarkRenderTransformDirty(); +} + +void UCesiumBoundingVolumeComponent::UpdateTransformFromCesium( + const glm::dmat4& CesiumToUnrealTransform) { + this->_cesiumToUnreal = CesiumToUnrealTransform; + this->_updateTransform(); +} + +void UCesiumBoundingVolumeComponent::reset(const Tile* pTile) { + if (pTile) { + this->_tileTransform = pTile->getTransform(); + this->_tileBounds = pTile->getBoundingVolume(); + this->_isMapped = true; + this->_mappedFrameTime = GetWorld()->GetRealTimeSeconds(); + this->_updateTransform(); + this->SetVisibility(true); + } else { + this->_occlusionState = TileOcclusionState::OcclusionUnavailable; + this->_isMapped = false; + this->SetVisibility(false); + } +} + +FBoxSphereBounds UCesiumBoundingVolumeComponent::CalcBounds( + const FTransform& LocalToWorld) const { + return std::visit( + CalcBoundsOperation{LocalToWorld, this->_tileTransform}, + this->_tileBounds); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBoundingVolumeComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBoundingVolumeComponent.h new file mode 100644 index 0000000..582a4cc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBoundingVolumeComponent.h @@ -0,0 +1,137 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumViewExtension.h" +#include "Components/PrimitiveComponent.h" +#include "Components/SceneComponent.h" +#include "CoreMinimal.h" +#include "PrimitiveSceneProxy.h" +#include "SceneView.h" +#include +#include +#include +#include +#include +#include "CesiumBoundingVolumeComponent.generated.h" + +class ACesiumGeoreference; + +UCLASS() +class UCesiumBoundingVolumePoolComponent : public USceneComponent { + GENERATED_BODY() + +public: + UCesiumBoundingVolumePoolComponent(); + + /** + * Initialize the TileOcclusionRendererProxyPool implementation. + */ + void initPool(int32 maxPoolSize); + + /** + * Updates bounding volume transforms from a new double-precision + * transformation from the Cesium world to the Unreal Engine world. + * + * @param CesiumToUnrealTransform The new transformation. + */ + void UpdateTransformFromCesium(const glm::dmat4& CesiumToUnrealTransform); + + const std::shared_ptr& + getPool() { + return this->_pPool; + } + +private: + glm::dmat4 _cesiumToUnreal; + + // These are really implementations of the functions in + // TileOcclusionRendererProxyPool, but we can't use multiple inheritance with + // UObjects. Instead use the CesiumBoundingVolumePool and forward virtual + // calls to the implementations. + + Cesium3DTilesSelection::TileOcclusionRendererProxy* createProxy(); + + void destroyProxy(Cesium3DTilesSelection::TileOcclusionRendererProxy* pProxy); + + class CesiumBoundingVolumePool + : public Cesium3DTilesSelection::TileOcclusionRendererProxyPool { + public: + CesiumBoundingVolumePool( + UCesiumBoundingVolumePoolComponent* pOutter, + int32 maxPoolSize); + + protected: + Cesium3DTilesSelection::TileOcclusionRendererProxy* createProxy() override; + + void destroyProxy( + Cesium3DTilesSelection::TileOcclusionRendererProxy* pProxy) override; + + private: + UCesiumBoundingVolumePoolComponent* _pOutter; + }; + + std::shared_ptr + _pPool; +}; + +UCLASS() +class UCesiumBoundingVolumeComponent + : public UPrimitiveComponent, + public Cesium3DTilesSelection::TileOcclusionRendererProxy { + GENERATED_BODY() + +public: + // Sets default values for this component's properties + UCesiumBoundingVolumeComponent(){}; + virtual ~UCesiumBoundingVolumeComponent() = default; + + FPrimitiveSceneProxy* CreateSceneProxy() override; + + /** + * Update the occlusion state for this bounding volume from the + * CesiumViewExtension. + */ + void UpdateOcclusion(const CesiumViewExtension& cesiumViewExtension); + + /** + * Updates this component's transform from a new double-precision + * transformation from the Cesium world to the Unreal Engine world, as well as + * the current tile's transform. + * + * @param CesiumToUnrealTransform The new transformation. + */ + void UpdateTransformFromCesium(const glm::dmat4& CesiumToUnrealTransform); + + virtual FBoxSphereBounds + CalcBounds(const FTransform& LocalToWorld) const override; + + bool ShouldRecreateProxyOnUpdateTransform() const override { return true; } + + // virtual void BeginDestroy() override; + + Cesium3DTilesSelection::TileOcclusionState + getOcclusionState() const override { + return _occlusionState; + } + +protected: + void reset(const Cesium3DTilesSelection::Tile* pTile) override; + +private: + void _updateTransform(); + + Cesium3DTilesSelection::TileOcclusionState _occlusionState = + Cesium3DTilesSelection::TileOcclusionState::OcclusionUnavailable; + + // Whether this proxy is currently mapped to a tile. + bool _isMapped = false; + + // The time when this bounding volume was mapped to the tile. + float _mappedFrameTime = 0.0f; + + Cesium3DTilesSelection::BoundingVolume _tileBounds = + CesiumGeometry::OrientedBoundingBox(glm::dvec3(0.0), glm::dmat3(1.0)); + glm::dmat4 _tileTransform = glm::dmat4(1.0); + glm::dmat4 _cesiumToUnreal = glm::dmat4(1.0); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCamera.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCamera.cpp new file mode 100644 index 0000000..975183f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCamera.cpp @@ -0,0 +1,35 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumCamera.h" +#include "CesiumRuntime.h" +#include "Math/UnrealMathUtility.h" + +FCesiumCamera::FCesiumCamera() + : ViewportSize(1.0, 1.0), + Location(0.0, 0.0, 0.0), + Rotation(0.0, 0.0, 0.0), + FieldOfViewDegrees(0.0), + OverrideAspectRatio(0.0) {} + +FCesiumCamera::FCesiumCamera( + const FVector2D& ViewportSize_, + const FVector& Location_, + const FRotator& Rotation_, + double FieldOfViewDegrees_) + : ViewportSize(ViewportSize_), + Location(Location_), + Rotation(Rotation_), + FieldOfViewDegrees(FieldOfViewDegrees_), + OverrideAspectRatio(0.0) {} + +FCesiumCamera::FCesiumCamera( + const FVector2D& ViewportSize_, + const FVector& Location_, + const FRotator& Rotation_, + double FieldOfViewDegrees_, + double OverrideAspectRatio_) + : ViewportSize(ViewportSize_), + Location(Location_), + Rotation(Rotation_), + FieldOfViewDegrees(FieldOfViewDegrees_), + OverrideAspectRatio(OverrideAspectRatio_) {} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCameraManager.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCameraManager.cpp new file mode 100644 index 0000000..707885a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCameraManager.cpp @@ -0,0 +1,116 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumCameraManager.h" +#include "CesiumRuntime.h" +#include "Engine/World.h" +#include "EngineUtils.h" +#include +#include + +FName ACesiumCameraManager::DEFAULT_CAMERAMANAGER_TAG = + FName("DEFAULT_CAMERAMANAGER"); + +/*static*/ ACesiumCameraManager* ACesiumCameraManager::GetDefaultCameraManager( + const UObject* WorldContextObject) { + // A null world context means a null return value (no camera manager + // available) + if (WorldContextObject == nullptr) + return nullptr; + UWorld* world = WorldContextObject->GetWorld(); + // This method can be called by actors even when opening the content browser. + if (!IsValid(world)) { + return nullptr; + } + UE_LOG( + LogCesium, + Verbose, + TEXT("World name for GetDefaultCameraManager: %s"), + *world->GetFullName()); + + // Note: The actor iterator will be created with the + // "EActorIteratorFlags::SkipPendingKill" flag, + // meaning that we don't have to handle objects + // that have been deleted. (This is the default, + // but made explicit here) + ACesiumCameraManager* pCameraManager = nullptr; + EActorIteratorFlags flags = EActorIteratorFlags::OnlyActiveLevels | + EActorIteratorFlags::SkipPendingKill; + for (TActorIterator actorIterator( + world, + ACesiumCameraManager::StaticClass(), + flags); + actorIterator; + ++actorIterator) { + AActor* actor = *actorIterator; + if (actor->GetLevel() == world->PersistentLevel && + actor->ActorHasTag(DEFAULT_CAMERAMANAGER_TAG)) { + pCameraManager = Cast(actor); + break; + } + } + + if (!pCameraManager) { + UE_LOG( + LogCesium, + Verbose, + TEXT("Creating default ACesiumCameraManager for actor %s"), + *WorldContextObject->GetName()); + // Spawn georeference in the persistent level + FActorSpawnParameters spawnParameters; + spawnParameters.SpawnCollisionHandlingOverride = + ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + spawnParameters.OverrideLevel = world->PersistentLevel; + pCameraManager = world->SpawnActor(spawnParameters); + // Null check so the editor doesn't crash when it makes arbitrary calls to + // this function without a valid world context object. + if (pCameraManager) { + pCameraManager->Tags.Add(DEFAULT_CAMERAMANAGER_TAG); + } + } else { + UE_LOG( + LogCesium, + Verbose, + TEXT("Using existing ACesiumCameraManager %s for actor %s"), + *pCameraManager->GetName(), + *WorldContextObject->GetName()); + } + return pCameraManager; +} + +ACesiumCameraManager::ACesiumCameraManager() : AActor() { +#if WITH_EDITOR + this->SetIsSpatiallyLoaded(false); +#endif +} + +bool ACesiumCameraManager::ShouldTickIfViewportsOnly() const { return true; } + +void ACesiumCameraManager::Tick(float DeltaTime) { Super::Tick(DeltaTime); } + +int32 ACesiumCameraManager::AddCamera(UPARAM(ref) const FCesiumCamera& camera) { + int32 cameraId = this->_currentCameraId++; + this->_cameras.Emplace(cameraId, camera); + return cameraId; +} + +bool ACesiumCameraManager::RemoveCamera(int32 cameraId) { + int32 numRemovedPairs = this->_cameras.Remove(cameraId); + bool success = numRemovedPairs > 0; + return success; +} + +bool ACesiumCameraManager::UpdateCamera( + int32 cameraId, + UPARAM(ref) const FCesiumCamera& camera) { + FCesiumCamera* pCurrentCamera = this->_cameras.Find(cameraId); + if (pCurrentCamera) { + *pCurrentCamera = camera; + return true; + } + + return false; +} + +const TMap& ACesiumCameraManager::GetCameras() const { + return this->_cameras; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCartographicPolygon.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCartographicPolygon.cpp new file mode 100644 index 0000000..7f6027d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCartographicPolygon.cpp @@ -0,0 +1,89 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumCartographicPolygon.h" +#include "CesiumActors.h" +#include "CesiumUtility/Math.h" +#include "Components/SceneComponent.h" +#include "StaticMeshResources.h" +#include + +using namespace CesiumGeospatial; + +ACesiumCartographicPolygon::ACesiumCartographicPolygon() : AActor() { + PrimaryActorTick.bCanEverTick = false; + + this->Polygon = CreateDefaultSubobject(TEXT("Selection")); + this->SetRootComponent(this->Polygon); + this->Polygon->SetClosedLoop(true); + this->Polygon->SetMobility(EComponentMobility::Movable); + + this->Polygon->SetSplinePoints( + TArray{ + FVector(-10000.0f, -10000.0f, 0.0f), + FVector(10000.0f, -10000.0f, 0.0f), + FVector(10000.0f, 10000.0f, 0.0f), + FVector(-10000.0f, 10000.0f, 0.0f)}, + ESplineCoordinateSpace::Local); + + this->MakeLinear(); +#if WITH_EDITOR + this->SetIsSpatiallyLoaded(false); +#endif + this->GlobeAnchor = + CreateDefaultSubobject(TEXT("GlobeAnchor")); +} + +void ACesiumCartographicPolygon::OnConstruction(const FTransform& Transform) { + this->MakeLinear(); +} + +void ACesiumCartographicPolygon::BeginPlay() { + Super::BeginPlay(); + this->MakeLinear(); +} + +CesiumGeospatial::CartographicPolygon +ACesiumCartographicPolygon::CreateCartographicPolygon( + const FTransform& worldToTileset) const { + int32 splinePointsCount = this->Polygon->GetNumberOfSplinePoints(); + + if (splinePointsCount < 3) { + return CartographicPolygon({}); + } + + std::vector polygon(splinePointsCount); + + // The spline points should be located in the tileset _exactly where they + // appear to be_. The way we do that is by getting their world position, and + // then transforming that world position to a Cesium3DTileset local position. + // That way if the tileset is transformed relative to the globe, the polygon + // will still affect the tileset where the user thinks it should. + + for (size_t i = 0; i < splinePointsCount; ++i) { + const FVector& unrealPosition = worldToTileset.TransformPosition( + this->Polygon->GetLocationAtSplinePoint( + i, + ESplineCoordinateSpace::World)); + FVector cartographic = + this->GlobeAnchor->ResolveGeoreference() + ->TransformUnrealPositionToLongitudeLatitudeHeight(unrealPosition); + polygon[i] = + glm::dvec2(glm::radians(cartographic.X), glm::radians(cartographic.Y)); + } + + return CartographicPolygon(polygon); +} + +void ACesiumCartographicPolygon::MakeLinear() { + // set spline point types to linear for all points. + for (size_t i = 0; i < this->Polygon->GetNumberOfSplinePoints(); ++i) { + this->Polygon->SetSplinePointType(i, ESplinePointType::Linear); + } +} + +void ACesiumCartographicPolygon::PostLoad() { + Super::PostLoad(); + + if (CesiumActors::shouldValidateFlags(this)) + CesiumActors::validateActorFlags(this); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp new file mode 100644 index 0000000..9ee39ce --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp @@ -0,0 +1,467 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumCreditSystem.h" +#include "CesiumCommon.h" +#include "CesiumCreditSystemBPLoader.h" +#include "CesiumRuntime.h" +#include "CesiumUtility/CreditSystem.h" +#include "Engine/World.h" +#include "EngineUtils.h" +#include "ScreenCreditsWidget.h" +#include +#include +#include + +#if WITH_EDITOR +#include "Editor.h" +#include "EditorSupportDelegates.h" +#include "GameDelegates.h" +#include "IAssetViewport.h" +#include "LevelEditor.h" +#include "Modules/ModuleManager.h" +#endif + +/*static*/ UObject* ACesiumCreditSystem::CesiumCreditSystemBP = nullptr; +namespace { + +/** + * @brief Tries to find the default credit system in the given level. + * + * This will search all actors of the given level for a `ACesiumCreditSystem` + * whose name starts with `"CesiumCreditSystemDefault"` that is *valid* + * (i.e. not pending kill). + * + * @param Level The level + * @return The default credit system, or `nullptr` if there is none. + */ +ACesiumCreditSystem* findValidDefaultCreditSystem(ULevel* Level) { + if (!IsValid(Level)) { + UE_LOG( + LogCesium, + Warning, + TEXT("No valid level for findValidDefaultCreditSystem")); + return nullptr; + } +#if ENGINE_VERSION_5_4_OR_HIGHER + TArray>& Actors = Level->Actors; + using LevelActorPointer = TObjectPtr*; +#else + TArray& Actors = Level->Actors; + using LevelActorPointer = AActor**; +#endif + LevelActorPointer DefaultCreditSystemPtr = + Actors.FindByPredicate([](AActor* const& InItem) { + if (!IsValid(InItem)) { + return false; + } + if (!InItem->IsA(ACesiumCreditSystem::StaticClass())) { + return false; + } + if (!InItem->GetName().StartsWith("CesiumCreditSystemDefault")) { + return false; + } + return true; + }); + if (!DefaultCreditSystemPtr) { + return nullptr; + } + AActor* DefaultCreditSystem = *DefaultCreditSystemPtr; + return Cast(DefaultCreditSystem); +} + +bool checkIfInSubLevel(ACesiumCreditSystem* pCreditSystem) { + if (pCreditSystem->GetLevel() != pCreditSystem->GetWorld()->PersistentLevel) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "CesiumCreditSystem should only exist in the Persistent Level. Adding it to a sub-level may cause credits to be lost.")); + return true; + } else { + return false; + } +} + +} // namespace + +FName ACesiumCreditSystem::DEFAULT_CREDITSYSTEM_TAG = + FName("DEFAULT_CREDITSYSTEM"); + +/*static*/ ACesiumCreditSystem* +ACesiumCreditSystem::GetDefaultCreditSystem(const UObject* WorldContextObject) { + // Blueprint loading can only happen in a constructor, so we instantiate a + // loader object that retrieves the blueprint class in its constructor. We can + // destroy the loader immediately once it's done since it will have already + // set CesiumCreditSystemBP. + if (!CesiumCreditSystemBP) { + UCesiumCreditSystemBPLoader* bpLoader = + NewObject(); + CesiumCreditSystemBP = bpLoader->CesiumCreditSystemBP.LoadSynchronous(); + bpLoader->ConditionalBeginDestroy(); + } + + UWorld* world = WorldContextObject->GetWorld(); + // This method can be called by actors even when opening the content browser. + if (!IsValid(world)) { + return nullptr; + } + UE_LOG( + LogCesium, + Verbose, + TEXT("World name for GetDefaultCreditSystem: %s"), + *world->GetFullName()); + + // Note: The actor iterator will be created with the + // "EActorIteratorFlags::SkipPendingKill" flag, + // meaning that we don't have to handle objects + // that have been deleted. (This is the default, + // but made explicit here) + ACesiumCreditSystem* pCreditSystem = nullptr; + EActorIteratorFlags flags = EActorIteratorFlags::OnlyActiveLevels | + EActorIteratorFlags::SkipPendingKill; + for (TActorIterator actorIterator( + world, + ACesiumCreditSystem::StaticClass(), + flags); + actorIterator; + ++actorIterator) { + AActor* actor = *actorIterator; + if (actor->GetLevel() == world->PersistentLevel && + actor->ActorHasTag(DEFAULT_CREDITSYSTEM_TAG)) { + pCreditSystem = Cast(actor); + break; + } + } + if (!pCreditSystem) { + // Legacy method of finding Georeference, for backwards compatibility with + // existing projects + ACesiumCreditSystem* pCreditSystemCandidate = + findValidDefaultCreditSystem(world->PersistentLevel); + + // Test if PendingKill + if (IsValid(pCreditSystemCandidate)) { + pCreditSystem = pCreditSystemCandidate; + } + } + if (!pCreditSystem) { + UE_LOG( + LogCesium, + Verbose, + TEXT("Creating default Credit System for actor %s"), + *WorldContextObject->GetName()); + // Spawn georeference in the persistent level + FActorSpawnParameters spawnParameters; + spawnParameters.SpawnCollisionHandlingOverride = + ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + spawnParameters.OverrideLevel = world->PersistentLevel; + pCreditSystem = world->SpawnActor( + Cast(CesiumCreditSystemBP), + spawnParameters); + // Null check so the editor doesn't crash when it makes arbitrary calls to + // this function without a valid world context object. + if (pCreditSystem) { + pCreditSystem->Tags.Add(DEFAULT_CREDITSYSTEM_TAG); + } + } else { + UE_LOG( + LogCesium, + Verbose, + TEXT("Using existing CreditSystem %s for actor %s"), + *pCreditSystem->GetName(), + *WorldContextObject->GetName()); + } + return pCreditSystem; +} + +ACesiumCreditSystem::ACesiumCreditSystem() + : AActor(), + _pCreditSystem(std::make_shared()), + _lastCreditsCount(0) { + PrimaryActorTick.bCanEverTick = true; +#if WITH_EDITOR + this->SetIsSpatiallyLoaded(false); +#endif +} + +void ACesiumCreditSystem::BeginPlay() { + Super::BeginPlay(); + + if (checkIfInSubLevel(this)) + return; + + this->updateCreditsViewport(true); +} + +void ACesiumCreditSystem::EndPlay(const EEndPlayReason::Type EndPlayReason) { + this->removeCreditsFromViewports(); + Super::EndPlay(EndPlayReason); +} + +static const FName LevelEditorName("LevelEditor"); + +void ACesiumCreditSystem::OnConstruction(const FTransform& Transform) { + Super::OnConstruction(Transform); + + if (checkIfInSubLevel(this)) + return; + + this->updateCreditsViewport(false); + +#if WITH_EDITOR + FLevelEditorModule* pLevelEditorModule = + FModuleManager::GetModulePtr(LevelEditorName); + + if (pLevelEditorModule && !GetWorld()->IsGameWorld()) { + pLevelEditorModule->OnRedrawLevelEditingViewports().RemoveAll(this); + pLevelEditorModule->OnRedrawLevelEditingViewports().AddUObject( + this, + &ACesiumCreditSystem::OnRedrawLevelEditingViewports); + + FEditorSupportDelegates::CleanseEditor.RemoveAll(this); + FEditorSupportDelegates::CleanseEditor.AddUObject( + this, + &ACesiumCreditSystem::OnCleanseEditor); + + FEditorDelegates::PreBeginPIE.RemoveAll(this); + FEditorDelegates::PreBeginPIE.AddUObject( + this, + &ACesiumCreditSystem::OnPreBeginPIE); + + FGameDelegates::Get().GetEndPlayMapDelegate().RemoveAll(this); + FGameDelegates::Get().GetEndPlayMapDelegate().AddUObject( + this, + &ACesiumCreditSystem::OnEndPIE); + } +#endif +} + +void ACesiumCreditSystem::BeginDestroy() { +#if WITH_EDITOR + FLevelEditorModule* pLevelEditorModule = + FModuleManager::GetModulePtr(LevelEditorName); + if (pLevelEditorModule) { + pLevelEditorModule->OnRedrawLevelEditingViewports().RemoveAll(this); + } + + FEditorSupportDelegates::CleanseEditor.RemoveAll(this); + FEditorDelegates::PreBeginPIE.RemoveAll(this); + FEditorDelegates::EndPIE.RemoveAll(this); +#endif + + Super::BeginDestroy(); +} + +void ACesiumCreditSystem::updateCreditsViewport(bool recreateWidget) { + if (IsRunningDedicatedServer()) + return; + if (!IsValid(GetWorld())) + return; + + if (!IsValid(CreditsWidget) || recreateWidget) { + CreditsWidget = + CreateWidget(GetWorld(), CreditsWidgetClass); + } + +#if WITH_EDITOR + FLevelEditorModule* pLevelEditorModule = + FModuleManager::GetModulePtr(LevelEditorName); + + if (pLevelEditorModule && !GetWorld()->IsGameWorld()) { + // Add credits to the active editor viewport + TSharedPtr pActiveViewport = + pLevelEditorModule->GetFirstActiveViewport(); + if (pActiveViewport.IsValid() && + this->_pLastEditorViewport != pActiveViewport) { + this->removeCreditsFromViewports(); + + if (!pActiveViewport->HasPlayInEditorViewport()) { + auto pSlateWidget = CreditsWidget->TakeWidget(); + pActiveViewport->AddOverlayWidget(pSlateWidget); + this->_pLastEditorViewport = pActiveViewport; + } + } + return; + } + + this->removeCreditsFromViewports(); +#endif + + // Add credits to a game viewport + CreditsWidget->AddToViewport(); +} + +void ACesiumCreditSystem::removeCreditsFromViewports() { +#if WITH_EDITOR + if (this->_pLastEditorViewport.IsValid()) { + auto pPinned = this->_pLastEditorViewport.Pin(); + pPinned->RemoveOverlayWidget(CreditsWidget->TakeWidget()); + this->_pLastEditorViewport = nullptr; + } +#endif + + if (IsValid(CreditsWidget)) { + CreditsWidget->RemoveFromParent(); + } +} + +#if WITH_EDITOR +void ACesiumCreditSystem::OnRedrawLevelEditingViewports(bool) { + this->updateCreditsViewport(false); +} + +void ACesiumCreditSystem::OnPreBeginPIE(bool bIsSimulating) { + // When we start play-in-editor, remove the editor viewport credits. + // The game will often reuse the same viewport, and we don't want to show + // two sets of credits. + this->removeCreditsFromViewports(); +} + +void ACesiumCreditSystem::OnEndPIE() { this->updateCreditsViewport(false); } + +void ACesiumCreditSystem::OnCleanseEditor() { + // This is called late in the process of unloading a level. + this->removeCreditsFromViewports(); +} +#endif + +bool ACesiumCreditSystem::ShouldTickIfViewportsOnly() const { return true; } + +void ACesiumCreditSystem::Tick(float DeltaTime) { + Super::Tick(DeltaTime); + + if (!_pCreditSystem || !IsValid(CreditsWidget)) { + return; + } + + const std::vector& creditsToShowThisFrame = + _pCreditSystem->getCreditsToShowThisFrame(); + + // if the credit list has changed, we want to reformat the credits + CreditsUpdated = + creditsToShowThisFrame.size() != _lastCreditsCount || + _pCreditSystem->getCreditsToNoLongerShowThisFrame().size() > 0; + + if (CreditsUpdated) { + FString OnScreenCredits; + FString Credits; + + _lastCreditsCount = creditsToShowThisFrame.size(); + + bool firstCreditOnScreen = true; + for (int i = 0; i < creditsToShowThisFrame.size(); i++) { + const CesiumUtility::Credit& credit = creditsToShowThisFrame[i]; + + FString CreditRtf; + const std::string& html = _pCreditSystem->getHtml(credit); + + auto htmlFind = _htmlToRtf.find(html); + if (htmlFind != _htmlToRtf.end()) { + CreditRtf = htmlFind->second; + } else { + CreditRtf = ConvertHtmlToRtf(html); + _htmlToRtf.insert({html, CreditRtf}); + } + + if (_pCreditSystem->shouldBeShownOnScreen(credit)) { + if (firstCreditOnScreen) { + firstCreditOnScreen = false; + } else { + OnScreenCredits += TEXT(" \u2022 "); + } + + OnScreenCredits += CreditRtf; + } else { + if (i != 0) { + Credits += "\n"; + } + + Credits += CreditRtf; + } + } + + if (!Credits.IsEmpty()) { + OnScreenCredits += ""; + } + + CreditsWidget->SetCredits(Credits, OnScreenCredits); + } + _pCreditSystem->startNextFrame(); +} + +namespace { +void convertHtmlToRtf( + std::string& output, + std::string& parentUrl, + TidyDoc tdoc, + TidyNode tnod, + UScreenCreditsWidget* CreditsWidget) { + TidyNode child; + TidyBuffer buf; + tidyBufInit(&buf); + for (child = tidyGetChild(tnod); child; child = tidyGetNext(child)) { + if (tidyNodeIsText(child)) { + tidyNodeGetText(tdoc, child, &buf); + if (buf.bp) { + std::string text = reinterpret_cast(buf.bp); + tidyBufClear(&buf); + // could not find correct option in tidy html to not add new lines + if (text.size() != 0 && text[text.size() - 1] == '\n') { + text.pop_back(); + } + if (!parentUrl.empty()) { + output += + ""; + } else { + output += text; + } + } + } else if (tidyNodeGetId(child) == TidyTagId::TidyTag_IMG) { + auto srcAttr = tidyAttrGetById(child, TidyAttrId::TidyAttr_SRC); + if (srcAttr) { + auto srcValue = tidyAttrValue(srcAttr); + if (srcValue) { + output += "LoadImage( + std::string(reinterpret_cast(srcValue))) + + "\""; + if (!parentUrl.empty()) { + output += " url=\"" + parentUrl + "\""; + } + output += "/>"; + } + } + } + auto hrefAttr = tidyAttrGetById(child, TidyAttrId::TidyAttr_HREF); + if (hrefAttr) { + auto hrefValue = tidyAttrValue(hrefAttr); + parentUrl = std::string(reinterpret_cast(hrefValue)); + } + convertHtmlToRtf(output, parentUrl, tdoc, child, CreditsWidget); + } + tidyBufFree(&buf); +} +} // namespace + +FString ACesiumCreditSystem::ConvertHtmlToRtf(std::string html) { + TidyDoc tdoc; + TidyBuffer tidy_errbuf = {0}; + int err; + + tdoc = tidyCreate(); + tidyOptSetBool(tdoc, TidyForceOutput, yes); + tidyOptSetInt(tdoc, TidyWrapLen, 0); + tidyOptSetInt(tdoc, TidyNewline, TidyLF); + + tidySetErrorBuffer(tdoc, &tidy_errbuf); + + html = "" + html + ""; + + std::string output, url; + err = tidyParseString(tdoc, html.c_str()); + if (err < 2) { + convertHtmlToRtf(output, url, tdoc, tidyGetRoot(tdoc), CreditsWidget); + } + tidyBufFree(&tidy_errbuf); + tidyRelease(tdoc); + return UTF8_TO_TCHAR(output.c_str()); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystemBPLoader.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystemBPLoader.cpp new file mode 100644 index 0000000..a7195ab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystemBPLoader.cpp @@ -0,0 +1,6 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumCreditSystemBPLoader.h" +#include "UObject/ConstructorHelpers.h" + +UCesiumCreditSystemBPLoader::UCesiumCreditSystemBPLoader() {} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystemBPLoader.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystemBPLoader.h new file mode 100644 index 0000000..f9a7fa1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystemBPLoader.h @@ -0,0 +1,18 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumCreditSystemBPLoader.generated.h" + +UCLASS() +class UCesiumCreditSystemBPLoader : public UObject { + GENERATED_BODY() + +public: + UCesiumCreditSystemBPLoader(); + + UPROPERTY() + TSoftObjectPtr CesiumCreditSystemBP = TSoftObjectPtr< + UObject>(FSoftObjectPath(TEXT( + "Class'/CesiumForUnreal/CesiumCreditSystemBP.CesiumCreditSystemBP_C'"))); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCustomVersion.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCustomVersion.cpp new file mode 100644 index 0000000..0df3956 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCustomVersion.cpp @@ -0,0 +1,13 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumCustomVersion.h" +#include "Serialization/CustomVersion.h" + +const FGuid + FCesiumCustomVersion::GUID(0xA5DCCA38, 0xDDA34991, 0x98E7B2F2, 0x15E17470); + +// Register the custom version with core +FCustomVersionRegistration GRegisterCesiumCustomVersion( + FCesiumCustomVersion::GUID, + FCesiumCustomVersion::LatestVersion, + TEXT("CesiumVer")); diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumDebugColorizeTilesRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumDebugColorizeTilesRasterOverlay.cpp new file mode 100644 index 0000000..44693bd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumDebugColorizeTilesRasterOverlay.cpp @@ -0,0 +1,14 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumDebugColorizeTilesRasterOverlay.h" +#include "Cesium3DTilesSelection/Tileset.h" +#include "CesiumRasterOverlays/DebugColorizeTilesRasterOverlay.h" + +std::unique_ptr +UCesiumDebugColorizeTilesRasterOverlay::CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options) { + return std::make_unique< + CesiumRasterOverlays::DebugColorizeTilesRasterOverlay>( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + options); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEllipsoid.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEllipsoid.cpp new file mode 100644 index 0000000..c304940 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEllipsoid.cpp @@ -0,0 +1,140 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumEllipsoid.h" +#include "CesiumEllipsoidFunctions.h" +#include "CesiumGeoreference.h" +#include "CesiumRuntime.h" +#include "VecMath.h" + +#include "EngineUtils.h" +#include "MathUtil.h" +#include "UObject/ConstructorHelpers.h" +#include "UObject/ObjectSaveContext.h" + +#if WITH_EDITOR +#include "Editor.h" +#include "LevelEditor.h" +#endif + +#include + +using namespace CesiumGeospatial; + +UCesiumEllipsoid* UCesiumEllipsoid::Create(const FVector& Radii) { + UCesiumEllipsoid* pEllipsoid = NewObject(); + pEllipsoid->SetRadii(Radii); + return pEllipsoid; +} + +FVector UCesiumEllipsoid::GetRadii() { return this->Radii; } + +void UCesiumEllipsoid::SetRadii(const FVector& NewRadii) { + this->Radii = NewRadii; +} + +double UCesiumEllipsoid::GetMaximumRadius() { return this->Radii.X; } + +double UCesiumEllipsoid::GetMinimumRadius() { return this->Radii.Z; } + +FVector UCesiumEllipsoid::ScaleToGeodeticSurface( + const FVector& EllipsoidCenteredEllipsoidFixedPosition) { + return CesiumEllipsoidFunctions::ScaleToGeodeticSurface( + this->GetNativeEllipsoid(), + EllipsoidCenteredEllipsoidFixedPosition); +} + +FVector UCesiumEllipsoid::GeodeticSurfaceNormal( + const FVector& EllipsoidCenteredEllipsoidFixedPosition) { + return CesiumEllipsoidFunctions::GeodeticSurfaceNormal( + this->GetNativeEllipsoid(), + EllipsoidCenteredEllipsoidFixedPosition); +} + +FVector +UCesiumEllipsoid::LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + const FVector& LongitudeLatitudeHeight) { + return CesiumEllipsoidFunctions:: + LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + this->GetNativeEllipsoid(), + LongitudeLatitudeHeight); +} + +FVector +UCesiumEllipsoid::EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight( + const FVector& EllipsoidCenteredEllipsoidFixedPosition) { + return CesiumEllipsoidFunctions:: + EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight( + this->GetNativeEllipsoid(), + EllipsoidCenteredEllipsoidFixedPosition); +} + +FMatrix UCesiumEllipsoid::EastNorthUpToEllipsoidCenteredEllipsoidFixed( + const FVector& EllipsoidCenteredEllipsoidFixedPosition) { + return CesiumEllipsoidFunctions::EastNorthUpToEllipsoidCenteredEllipsoidFixed( + this->GetNativeEllipsoid(), + EllipsoidCenteredEllipsoidFixedPosition); +} + +LocalHorizontalCoordinateSystem +UCesiumEllipsoid::CreateCoordinateSystem(const FVector& Center, double Scale) { + { + return LocalHorizontalCoordinateSystem( + VecMath::createVector3D(Center), + LocalDirection::East, + LocalDirection::South, + LocalDirection::Up, + 1.0 / Scale, + this->GetNativeEllipsoid()); + } +} + +const Ellipsoid& UCesiumEllipsoid::GetNativeEllipsoid() { + const double MinRadiiValue = TMathUtilConstants::Epsilon; + + if (!this->NativeEllipsoid.IsSet()) { + // Radii of zero will throw Infs and NaNs into our calculations which will + // cause Unreal to crash when the values reach a transform. + if (this->Radii.X < MinRadiiValue || this->Radii.Y < MinRadiiValue || + this->Radii.Z < MinRadiiValue) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Radii must be greater than 0 - clamping to minimum value to avoid crashes.")); + } + + this->NativeEllipsoid.Emplace(Ellipsoid( + FMath::Max(this->Radii.X, MinRadiiValue), + FMath::Max(this->Radii.Y, MinRadiiValue), + FMath::Max(this->Radii.Z, MinRadiiValue))); + } + + return *this->NativeEllipsoid; +} + +#if WITH_EDITOR +void UCesiumEllipsoid::PostSaveRoot( + FObjectPostSaveRootContext ObjectSaveContext) { + if (!IsValid(GEditor)) { + return; + } + + GEditor->GetWorld(); + + UWorld* World = GEditor->GetEditorWorldContext().World(); + if (!IsValid(World)) { + return; + } + + // Go through every georeference and update its ellipsoid if it's this + // ellipsoid, since we might have modified values after saving. + if (ObjectSaveContext.SaveSucceeded()) { + for (TActorIterator It(World); It; ++It) { + ACesiumGeoreference* Georeference = *It; + if (Georeference->GetEllipsoid() == this) { + Georeference->SetEllipsoid(this); + } + } + } +} +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEllipsoidFunctions.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEllipsoidFunctions.cpp new file mode 100644 index 0000000..d38c23e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEllipsoidFunctions.cpp @@ -0,0 +1,66 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumEllipsoidFunctions.h" +#include "VecMath.h" +#include +#include +#include + +using namespace CesiumGeospatial; +using namespace CesiumUtility; + +FVector CesiumEllipsoidFunctions::ScaleToGeodeticSurface( + const CesiumGeospatial::Ellipsoid& Ellipsoid, + const FVector& EllipsoidCenteredEllipsoidFixedPosition) { + std::optional result = Ellipsoid.scaleToGeodeticSurface( + VecMath::createVector3D(EllipsoidCenteredEllipsoidFixedPosition)); + if (result) { + return VecMath::createVector(*result); + } else { + return FVector(0.0, 0.0, 0.0); + } +} + +FVector CesiumEllipsoidFunctions::GeodeticSurfaceNormal( + const CesiumGeospatial::Ellipsoid& Ellipsoid, + const FVector& EllipsoidCenteredEllipsoidFixedPosition) { + return VecMath::createVector(Ellipsoid.geodeticSurfaceNormal( + VecMath::createVector3D(EllipsoidCenteredEllipsoidFixedPosition))); +} + +FVector CesiumEllipsoidFunctions:: + LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + const CesiumGeospatial::Ellipsoid& Ellipsoid, + const FVector& LongitudeLatitudeHeight) { + glm::dvec3 cartesian = + Ellipsoid.cartographicToCartesian(Cartographic::fromDegrees( + LongitudeLatitudeHeight.X, + LongitudeLatitudeHeight.Y, + LongitudeLatitudeHeight.Z)); + return VecMath::createVector(cartesian); +} + +FVector CesiumEllipsoidFunctions:: + EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight( + const CesiumGeospatial::Ellipsoid& Ellipsoid, + const FVector& EllipsoidCenteredEllipsoidFixedPosition) { + std::optional result = Ellipsoid.cartesianToCartographic( + VecMath::createVector3D(EllipsoidCenteredEllipsoidFixedPosition)); + if (result) { + return FVector( + Math::radiansToDegrees(result->longitude), + Math::radiansToDegrees(result->latitude), + result->height); + } else { + return FVector(0.0, 0.0, 0.0); + } +} + +FMatrix CesiumEllipsoidFunctions::EastNorthUpToEllipsoidCenteredEllipsoidFixed( + const CesiumGeospatial::Ellipsoid& Ellipsoid, + const FVector& EllipsoidCenteredEllipsoidFixedPosition) { + return VecMath::createMatrix( + CesiumGeospatial::GlobeTransforms::eastNorthUpToFixedFrame( + VecMath::createVector3D(EllipsoidCenteredEllipsoidFixedPosition), + Ellipsoid)); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEllipsoidFunctions.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEllipsoidFunctions.h new file mode 100644 index 0000000..4029d23 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEllipsoidFunctions.h @@ -0,0 +1,63 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Math/Matrix.h" + +namespace CesiumGeospatial { +class Ellipsoid; +}; + +/** + * A collection of methods for working with {@link CesiumGeospatial::Ellipsoid} + * objects from Unreal. + */ +class CesiumEllipsoidFunctions { +public: + /** + * Scale the given Ellipsoid-Centered, Ellipsoid-Fixed position along the + * geodetic surface normal so that it is on the surface of the ellipsoid. If + * the position is near the center of the ellipsoid, the result will have the + * value (0,0,0) because the surface position is undefined. + */ + static FVector ScaleToGeodeticSurface( + const CesiumGeospatial::Ellipsoid& Ellipsoid, + const FVector& EllipsoidCenteredEllipsoidFixedPosition); + + /** + * Computes the normal of the plane tangent to the surface of the ellipsoid + * at the provided Ellipsoid-Centered, Ellipsoid-Fixed position. + */ + static FVector GeodeticSurfaceNormal( + const CesiumGeospatial::Ellipsoid& Ellipsoid, + const FVector& EarthCenteredEarthFixedPosition); + + /** + * Convert longitude in degrees (X), latitude in degrees (Y), and height above + * the ellipsoid in meters (Z) to Ellipsoid-Centered, Ellipsoid-Fixed (ECEF) + * coordinates. + */ + static FVector LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + const CesiumGeospatial::Ellipsoid& Ellipsoid, + const FVector& LongitudeLatitudeHeight); + + /** + * Convert Ellipsoid-Centered, Ellipsoid-Fixed (ECEF) coordinates to longitude + * in degrees (X), latitude in degrees (Y), and height above the ellipsoid in + * meters (Z). If the position is near the center of the Earth, the result + * will have the value (0,0,0) because the longitude, latitude, and height are + * undefined. + */ + static FVector EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight( + const CesiumGeospatial::Ellipsoid& Ellipsoid, + const FVector& EllipsoidCenteredEllipsoidFixedPosition); + + /** + * Computes the transformation matrix from the local East-North-Up (ENU) frame + * to Ellipsoid-Centered, Ellipsoid-Fixed (ECEF) at the specified ECEF + * location. + */ + static FMatrix EastNorthUpToEllipsoidCenteredEllipsoidFixed( + const CesiumGeospatial::Ellipsoid& Ellipsoid, + const FVector& EllipsoidCenteredEllipsoidFixedPosition); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.cpp new file mode 100644 index 0000000..e895a76 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.cpp @@ -0,0 +1,1254 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumEncodedFeaturesMetadata.h" +#include "CesiumEncodedMetadataConversions.h" +#include "CesiumFeatureIdSet.h" +#include "CesiumFeaturesMetadataComponent.h" +#include "CesiumLifetime.h" +#include "CesiumModelMetadata.h" +#include "CesiumPrimitiveFeatures.h" +#include "CesiumPrimitiveMetadata.h" +#include "CesiumPropertyArray.h" +#include "CesiumPropertyTable.h" +#include "CesiumPropertyTexture.h" +#include "CesiumRuntime.h" +#include "Containers/Map.h" +#include "Materials/MaterialInstanceDynamic.h" +#include "PixelFormat.h" +#include "TextureResource.h" +#include "UnrealMetadataConversions.h" + +#include +#include +#include +#include + +using namespace CesiumTextureUtility; + +namespace CesiumEncodedFeaturesMetadata { + +FString getNameForFeatureIDSet( + const FCesiumFeatureIdSet& featureIDSet, + int32& FeatureIdTextureCounter) { + FString label = UCesiumFeatureIdSetBlueprintLibrary::GetLabel(featureIDSet); + if (!label.IsEmpty()) { + return label; + } + + ECesiumFeatureIdSetType type = + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType(featureIDSet); + + if (type == ECesiumFeatureIdSetType::Attribute) { + FCesiumFeatureIdAttribute attribute = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute( + featureIDSet); + ECesiumFeatureIdAttributeStatus status = + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureIDAttributeStatus( + attribute); + if (status == ECesiumFeatureIdAttributeStatus::Valid) { + std::string generatedName = + "_FEATURE_ID_" + std::to_string(attribute.getAttributeIndex()); + return FString(generatedName.c_str()); + } + } + + if (type == ECesiumFeatureIdSetType::Instance) { + FCesiumFeatureIdAttribute attribute = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute( + featureIDSet); + ECesiumFeatureIdAttributeStatus status = + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureIDAttributeStatus( + attribute); + if (status == ECesiumFeatureIdAttributeStatus::Valid) { + std::string generatedName = "_FEATURE_INSTANCE_ID_" + + std::to_string(attribute.getAttributeIndex()); + return FString(generatedName.c_str()); + } + } + + if (type == ECesiumFeatureIdSetType::Texture) { + std::string generatedName = + "_FEATURE_ID_TEXTURE_" + std::to_string(FeatureIdTextureCounter); + FeatureIdTextureCounter++; + return FString(generatedName.c_str()); + } + + if (type == ECesiumFeatureIdSetType::Implicit) { + return FString("_IMPLICIT_FEATURE_ID"); + } + + if (type == ECesiumFeatureIdSetType::InstanceImplicit) { + return FString("_IMPLICIT_FEATURE_INSTANCE_ID"); + } + + // If for some reason an empty / invalid feature ID set was constructed, + // return an empty name. + return FString(); +} + +namespace { + +/** + * @brief Encodes a feature ID attribute for access in a Unreal Engine Material. + * The feature IDs are simply sent to the GPU as texture coordinates, so this + * just handles the variable names necessary for material access. + * + * @returns The encoded feature ID attribute, or std::nullopt if the attribute + * was somehow invalid. + */ +std::optional +encodeFeatureIdAttribute(const FCesiumFeatureIdAttribute& attribute) { + const ECesiumFeatureIdAttributeStatus status = + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureIDAttributeStatus( + attribute); + + if (status != ECesiumFeatureIdAttributeStatus::Valid) { + UE_LOG( + LogCesium, + Warning, + TEXT("Can't encode invalid feature ID attribute, skipped.")); + return std::nullopt; + } + + EncodedFeatureIdSet result; + result.attribute = attribute.getAttributeIndex(); + return result; +} + +std::optional encodeFeatureIdTexture( + const FCesiumFeatureIdTexture& texture, + TMap>& + featureIdTextureMap) { + const ECesiumFeatureIdTextureStatus status = + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + texture); + if (status != ECesiumFeatureIdTextureStatus::Valid) { + UE_LOG( + LogCesium, + Warning, + TEXT("Can't encode invalid feature ID texture, skipped.")); + return std::nullopt; + } + + const CesiumGltf::FeatureIdTextureView& featureIdTextureView = + texture.getFeatureIdTextureView(); + const CesiumGltf::ImageAsset* pFeatureIdImage = + featureIdTextureView.getImage(); + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeFeatureIdTexture) + + EncodedFeatureIdSet result; + EncodedFeatureIdTexture& encodedFeatureIdTexture = result.texture.emplace(); + + encodedFeatureIdTexture.channels = featureIdTextureView.getChannels(); + encodedFeatureIdTexture.textureCoordinateSetIndex = + featureIdTextureView.getTexCoordSetIndex(); + encodedFeatureIdTexture.textureTransform = + featureIdTextureView.getTextureTransform(); + + TWeakPtr* pMappedUnrealImageIt = + featureIdTextureMap.Find(pFeatureIdImage); + if (pMappedUnrealImageIt) { + encodedFeatureIdTexture.pTexture = pMappedUnrealImageIt->Pin(); + } else { + TextureAddress addressX = TextureAddress::TA_Wrap; + TextureAddress addressY = TextureAddress::TA_Wrap; + + const CesiumGltf::Sampler* pSampler = featureIdTextureView.getSampler(); + if (pSampler) { + addressX = convertGltfWrapSToUnreal(pSampler->wrapS); + addressY = convertGltfWrapTToUnreal(pSampler->wrapT); + } + + // Copy the image, so that we can keep a copy of it in the glTF. + CesiumUtility::IntrusivePointer pImageCopy = + new CesiumGltf::ImageAsset(*pFeatureIdImage); + encodedFeatureIdTexture.pTexture = + MakeShared(std::move(*loadTextureAnyThreadPart( + *pImageCopy, + addressX, + addressY, + TextureFilter::TF_Nearest, + false, + TEXTUREGROUP_8BitData, + false, + // TODO: currently this is always the case, but doesn't have to be + EPixelFormat::PF_R8G8B8A8_UINT))); + featureIdTextureMap.Emplace( + pFeatureIdImage, + encodedFeatureIdTexture.pTexture); + } + + return result; +} + +} // namespace + +EncodedPrimitiveFeatures encodePrimitiveFeaturesAnyThreadPart( + const FCesiumPrimitiveFeaturesDescription& featuresDescription, + const FCesiumPrimitiveFeatures& features) { + EncodedPrimitiveFeatures result; + + const TArray& featureIDSetDescriptions = + featuresDescription.FeatureIdSets; + result.featureIdSets.Reserve(featureIDSetDescriptions.Num()); + + // Not all feature ID sets are necessarily textures, but reserve the max + // amount just in case. + TMap> + featureIdTextureMap; + featureIdTextureMap.Reserve(featureIDSetDescriptions.Num()); + + const TArray& featureIdSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets(features); + int32_t featureIdTextureCounter = 0; + + for (int32 i = 0; i < featureIdSets.Num(); i++) { + const FCesiumFeatureIdSet& set = featureIdSets[i]; + FString name = getNameForFeatureIDSet(set, featureIdTextureCounter); + const FCesiumFeatureIdSetDescription* pDescription = + featureIDSetDescriptions.FindByPredicate( + [&name]( + const FCesiumFeatureIdSetDescription& existingFeatureIDSet) { + return existingFeatureIDSet.Name == name; + }); + + if (!pDescription) { + // The description doesn't need this feature ID set, skip. + continue; + } + + std::optional encodedSet; + ECesiumFeatureIdSetType type = + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType(set); + + if (type == ECesiumFeatureIdSetType::Attribute) { + const FCesiumFeatureIdAttribute& attribute = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute(set); + encodedSet = encodeFeatureIdAttribute(attribute); + } else if (type == ECesiumFeatureIdSetType::Texture) { + const FCesiumFeatureIdTexture& texture = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDTexture(set); + encodedSet = encodeFeatureIdTexture(texture, featureIdTextureMap); + } else if (type == ECesiumFeatureIdSetType::Implicit) { + encodedSet = EncodedFeatureIdSet(); + } + + if (!encodedSet) + continue; + + encodedSet->name = name; + encodedSet->index = i; + encodedSet->propertyTableName = pDescription->PropertyTableName; + encodedSet->nullFeatureId = + UCesiumFeatureIdSetBlueprintLibrary::GetNullFeatureID(set); + + result.featureIdSets.Add(*encodedSet); + } + + return result; +} + +bool encodePrimitiveFeaturesGameThreadPart( + EncodedPrimitiveFeatures& encodedFeatures) { + bool success = true; + + // Not all feature ID sets are necessarily textures, but reserve the max + // amount just in case. + TArray uniqueFeatureIdImages; + uniqueFeatureIdImages.Reserve(encodedFeatures.featureIdSets.Num()); + + for (EncodedFeatureIdSet& encodedFeatureIdSet : + encodedFeatures.featureIdSets) { + if (!encodedFeatureIdSet.texture) { + continue; + } + + auto& encodedFeatureIdTexture = *encodedFeatureIdSet.texture; + if (uniqueFeatureIdImages.Find(encodedFeatureIdTexture.pTexture.Get()) == + INDEX_NONE) { + success &= loadTextureGameThreadPart( + encodedFeatureIdTexture.pTexture.Get()) != nullptr; + uniqueFeatureIdImages.Emplace(encodedFeatureIdTexture.pTexture.Get()); + } + } + + return success; +} + +void destroyEncodedPrimitiveFeatures( + EncodedPrimitiveFeatures& encodedFeatures) { + for (EncodedFeatureIdSet& encodedFeatureIdSet : + encodedFeatures.featureIdSets) { + if (!encodedFeatureIdSet.texture) { + continue; + } + + auto& encodedFeatureIdTexture = *encodedFeatureIdSet.texture; + if (encodedFeatureIdTexture.pTexture) { + encodedFeatureIdTexture.pTexture->pTexture = nullptr; + } + } +} + +FString getNameForPropertyTable(const FCesiumPropertyTable& PropertyTable) { + FString propertyTableName = + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableName(PropertyTable); + + if (propertyTableName.IsEmpty()) { + // Substitute the name with the property table's class. + propertyTableName = PropertyTable.getClassName(); + } + + return propertyTableName; +} + +FString +getNameForPropertyTexture(const FCesiumPropertyTexture& PropertyTexture) { + FString propertyTextureName = + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureName( + PropertyTexture); + + if (propertyTextureName.IsEmpty()) { + // Substitute the name with the property texture's class. + propertyTextureName = PropertyTexture.getClassName(); + } + + return propertyTextureName; +} + +FString getMaterialNameForPropertyTableProperty( + const FString& propertyTableName, + const FString& propertyName) { + // Example: "PTABLE_houses_roofColor" + return createHlslSafeName( + MaterialPropertyTablePrefix + propertyTableName + "_" + propertyName); +} + +FString getMaterialNameForPropertyTextureProperty( + const FString& propertyTextureName, + const FString& propertyName) { + // Example: "PTEXTURE_house_temperature" + return createHlslSafeName( + MaterialPropertyTexturePrefix + propertyTextureName + "_" + propertyName); +} + +namespace { + +bool isValidPropertyTablePropertyDescription( + const FCesiumPropertyTablePropertyDescription& propertyDescription, + const FCesiumPropertyTableProperty& property) { + if (propertyDescription.EncodingDetails.Type == + ECesiumEncodedMetadataType::None) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "No encoded metadata type was specified for this property table property; skip encoding.")); + return false; + } + + if (propertyDescription.EncodingDetails.ComponentType == + ECesiumEncodedMetadataComponentType::None) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "No encoded metadata component type was specified for this property table property; skip encoding.")); + return false; + } + + const FCesiumMetadataValueType expectedType = + propertyDescription.PropertyDetails.GetValueType(); + const FCesiumMetadataValueType valueType = + UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType(property); + if (valueType != expectedType) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "The value type of the metadata property %s does not match the type specified by the metadata description. It will still attempt to be encoded, but may result in empty or unexpected values."), + *propertyDescription.Name); + } + + bool isNormalized = + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property); + if (propertyDescription.PropertyDetails.bIsNormalized != isNormalized) { + FString error = + propertyDescription.PropertyDetails.bIsNormalized + ? "Description incorrectly marked a property table property as normalized; skip encoding." + : "Description incorrectly marked a property table property as not normalized; skip encoding."; + UE_LOG(LogCesium, Warning, TEXT("%s"), *error); + return false; + } + + // Only uint8 normalization is currently supported. + if (isNormalized && + valueType.ComponentType != ECesiumMetadataComponentType::Uint8) { + UE_LOG( + LogCesium, + Warning, + TEXT("Only normalization of uint8 properties is currently supported.")); + return false; + } + + return true; +} + +bool isValidPropertyTexturePropertyDescription( + const FCesiumPropertyTexturePropertyDescription& propertyDescription, + const FCesiumPropertyTextureProperty& property) { + const FCesiumMetadataValueType expectedType = + propertyDescription.PropertyDetails.GetValueType(); + const FCesiumMetadataValueType valueType = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValueType(property); + if (valueType != expectedType) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "The value type of the metadata property %s does not match the type specified by the metadata description. It will still attempt to be encoded, but may result in empty or unexpected values."), + *propertyDescription.Name); + } + + bool isNormalized = + UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized(property); + if (propertyDescription.PropertyDetails.bIsNormalized != isNormalized) { + FString error = + propertyDescription.PropertyDetails.bIsNormalized + ? "Description incorrectly marked a property texture property as normalized; skip encoding." + : "Description incorrectly marked a property texture property as not normalized; skip encoding."; + UE_LOG(LogCesium, Warning, TEXT("%s"), *error); + return false; + } + + // Only uint8 normalization is currently supported. + if (isNormalized && + valueType.ComponentType != ECesiumMetadataComponentType::Uint8) { + UE_LOG( + LogCesium, + Warning, + TEXT("Only normalization of uint8 properties is currently supported.")); + return false; + } + + return true; +} + +} // namespace + +EncodedPropertyTable encodePropertyTableAnyThreadPart( + const FCesiumPropertyTableDescription& propertyTableDescription, + const FCesiumPropertyTable& propertyTable) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodePropertyTable) + + EncodedPropertyTable encodedPropertyTable; + + int64 propertyTableCount = + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable); + + const TMap& properties = + UCesiumPropertyTableBlueprintLibrary::GetProperties(propertyTable); + + encodedPropertyTable.properties.Reserve(properties.Num()); + for (const auto& pair : properties) { + const FCesiumPropertyTableProperty& property = pair.Value; + + const FCesiumPropertyTablePropertyDescription* pDescription = + propertyTableDescription.Properties.FindByPredicate( + [&key = pair.Key](const FCesiumPropertyTablePropertyDescription& + expectedProperty) { + return key == expectedProperty.Name; + }); + + if (!pDescription) { + continue; + } + + const FCesiumMetadataEncodingDetails& encodingDetails = + pDescription->EncodingDetails; + if (encodingDetails.Conversion == ECesiumEncodedMetadataConversion::None) { + // No encoding to be done; skip. + continue; + } + + if (!isValidPropertyTablePropertyDescription(*pDescription, property)) { + continue; + } + + if (encodingDetails.Conversion == + ECesiumEncodedMetadataConversion::Coerce && + !CesiumEncodedMetadataCoerce::canEncode(*pDescription)) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "Cannot use 'Coerce' with the specified property info; skipped.")); + continue; + } + + if (encodingDetails.Conversion == + ECesiumEncodedMetadataConversion::ParseColorFromString && + !CesiumEncodedMetadataParseColorFromString::canEncode(*pDescription)) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "Cannot use `Parse Color From String` with the specified property info; skipped.")); + continue; + } + + EncodedPixelFormat encodedFormat = + getPixelFormat(encodingDetails.Type, encodingDetails.ComponentType); + if (encodedFormat.format == EPixelFormat::PF_Unknown) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "Unable to determine a suitable GPU format for this property table property; skipped.")); + continue; + } + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodePropertyTableProperty) + + EncodedPropertyTableProperty& encodedProperty = + encodedPropertyTable.properties.Emplace_GetRef(); + encodedProperty.name = createHlslSafeName(pDescription->Name); + encodedProperty.type = pDescription->EncodingDetails.Type; + + if (UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property) == + ECesiumPropertyTablePropertyStatus::Valid) { + + int64 floorSqrtFeatureCount = glm::sqrt(propertyTableCount); + int64 textureDimension = + (floorSqrtFeatureCount * floorSqrtFeatureCount == propertyTableCount) + ? floorSqrtFeatureCount + : (floorSqrtFeatureCount + 1); + + CesiumUtility::IntrusivePointer pImage = + new CesiumGltf::ImageAsset(); + pImage->width = pImage->height = textureDimension; + pImage->bytesPerChannel = encodedFormat.bytesPerChannel; + pImage->channels = encodedFormat.channels; + pImage->pixelData.resize( + textureDimension * textureDimension * encodedFormat.bytesPerChannel * + encodedFormat.channels); + + if (encodingDetails.Conversion == + ECesiumEncodedMetadataConversion::ParseColorFromString) { + CesiumEncodedMetadataParseColorFromString::encode( + *pDescription, + property, + std::span(pImage->pixelData), + encodedFormat.bytesPerChannel * encodedFormat.channels); + } else /* info.Conversion == ECesiumEncodedMetadataConversion::Coerce */ { + CesiumEncodedMetadataCoerce::encode( + *pDescription, + property, + std::span(pImage->pixelData), + encodedFormat.bytesPerChannel * encodedFormat.channels); + } + + encodedProperty.pTexture = loadTextureAnyThreadPart( + *pImage, + TextureAddress::TA_Clamp, + TextureAddress::TA_Clamp, + TextureFilter::TF_Nearest, + false, + TEXTUREGROUP_8BitData, + false, + encodedFormat.format); + } + + if (pDescription->PropertyDetails.bHasOffset) { + // If no offset is provided, default to 0, as specified by the spec. + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetOffset(property); + encodedProperty.offset = + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(value) + ? value + : FCesiumMetadataValue(0); + } + + if (pDescription->PropertyDetails.bHasScale) { + // If no scale is provided, default to 1, as specified by the spec. + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetScale(property); + encodedProperty.scale = + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(value) + ? value + : FCesiumMetadataValue(1); + } + + if (pDescription->PropertyDetails.bHasNoDataValue) { + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetNoDataValue( + property); + encodedProperty.noData = + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(value) + ? value + : FCesiumMetadataValue(0); + } + + if (pDescription->PropertyDetails.bHasDefaultValue) { + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetDefaultValue( + property); + encodedProperty.defaultValue = + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(value) + ? value + : FCesiumMetadataValue(0); + } + } + + return encodedPropertyTable; +} + +EncodedPropertyTexture encodePropertyTextureAnyThreadPart( + const FCesiumPropertyTextureDescription& propertyTextureDescription, + const FCesiumPropertyTexture& propertyTexture, + TMap>& + propertyTexturePropertyMap) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodePropertyTexture) + + EncodedPropertyTexture encodedPropertyTexture; + + const TMap& properties = + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture); + + encodedPropertyTexture.properties.Reserve(properties.Num()); + + for (const auto& pair : properties) { + const FCesiumPropertyTextureProperty& property = pair.Value; + + const FCesiumPropertyTexturePropertyDescription* pDescription = + propertyTextureDescription.Properties.FindByPredicate( + [&key = pair.Key](const FCesiumPropertyTexturePropertyDescription& + expectedProperty) { + return key == expectedProperty.Name; + }); + + if (!pDescription) { + continue; + } + + if (!isValidPropertyTexturePropertyDescription(*pDescription, property)) { + continue; + } + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodePropertyTextureProperty) + + EncodedPropertyTextureProperty& encodedProperty = + encodedPropertyTexture.properties.Emplace_GetRef(); + encodedProperty.name = createHlslSafeName(pDescription->Name); + encodedProperty.type = + CesiumMetadataTypeToEncodingType(pDescription->PropertyDetails.Type); + encodedProperty.textureCoordinateSetIndex = property.getTexCoordSetIndex(); + + if (UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property) == + ECesiumPropertyTexturePropertyStatus::Valid) { + + const TArray& channels = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetChannels(property); + const int32 channelCount = channels.Num(); + for (int32 i = 0; i < channelCount; i++) { + encodedProperty.channels[i] = channels[i]; + } + + const CesiumGltf::ImageAsset* pImage = property.getImage(); + + TWeakPtr* pMappedUnrealImageIt = + propertyTexturePropertyMap.Find(pImage); + if (pMappedUnrealImageIt) { + encodedProperty.pTexture = pMappedUnrealImageIt->Pin(); + } else { + TextureAddress addressX = TextureAddress::TA_Wrap; + TextureAddress addressY = TextureAddress::TA_Wrap; + + const CesiumGltf::Sampler* pSampler = property.getSampler(); + if (pSampler) { + addressX = convertGltfWrapSToUnreal(pSampler->wrapS); + addressY = convertGltfWrapTToUnreal(pSampler->wrapT); + } + + // Copy the image, so that we can keep a copy of it in the glTF. + CesiumUtility::IntrusivePointer pImageCopy = + new CesiumGltf::ImageAsset(*pImage); + encodedProperty.pTexture = + MakeShared(std::move(*loadTextureAnyThreadPart( + *pImageCopy, + addressX, + addressY, + // TODO: account for texture filter + TextureFilter::TF_Nearest, + false, + TEXTUREGROUP_8BitData, + false, + // This assumes that the texture's image only contains one byte + // per channel. + EPixelFormat::PF_R8G8B8A8_UINT))); + propertyTexturePropertyMap.Emplace(pImage, encodedProperty.pTexture); + } + }; + + if (pDescription->PropertyDetails.bHasOffset) { + encodedProperty.offset = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetOffset(property); + } + + if (pDescription->PropertyDetails.bHasScale) { + encodedProperty.scale = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetScale(property); + } + + if (pDescription->PropertyDetails.bHasNoDataValue) { + encodedProperty.noData = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetNoDataValue( + property); + } + + if (pDescription->PropertyDetails.bHasDefaultValue) { + encodedProperty.defaultValue = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetDefaultValue( + property); + } + + if (pDescription->bHasKhrTextureTransform) { + encodedProperty.textureTransform = property.getTextureTransform(); + } + } + + return encodedPropertyTexture; +} + +EncodedPrimitiveMetadata encodePrimitiveMetadataAnyThreadPart( + const FCesiumPrimitiveMetadataDescription& metadataDescription, + const FCesiumPrimitiveMetadata& primitiveMetadata, + const FCesiumModelMetadata& modelMetadata) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeMetadataPrimitive) + + EncodedPrimitiveMetadata result; + + const TArray& propertyTextures = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTextures(modelMetadata); + result.propertyTextureIndices.Reserve( + metadataDescription.PropertyTextureNames.Num()); + + for (int32 i = 0; i < propertyTextures.Num(); i++) { + const FCesiumPropertyTexture& propertyTexture = propertyTextures[i]; + FString propertyTextureName = getNameForPropertyTexture(propertyTexture); + const FString* pName = + metadataDescription.PropertyTextureNames.Find(propertyTextureName); + // Confirm that the named property texture is actually present. This + // indicates that it is acceptable to pass the texture coordinate index to + // the material layer. + if (pName) { + result.propertyTextureIndices.Add(i); + } + } + + return result; +} + +EncodedModelMetadata encodeModelMetadataAnyThreadPart( + const FCesiumModelMetadataDescription& metadataDescription, + const FCesiumModelMetadata& metadata) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeModelMetadata) + + EncodedModelMetadata result; + + const TArray& propertyTables = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTables(metadata); + result.propertyTables.Reserve(propertyTables.Num()); + for (const FCesiumPropertyTable& propertyTable : propertyTables) { + const FString propertyTableName = getNameForPropertyTable(propertyTable); + + const FCesiumPropertyTableDescription* pExpectedPropertyTable = + metadataDescription.PropertyTables.FindByPredicate( + [&propertyTableName]( + const FCesiumPropertyTableDescription& expectedPropertyTable) { + return propertyTableName == expectedPropertyTable.Name; + }); + + if (pExpectedPropertyTable) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodePropertyTable) + + auto& encodedPropertyTable = + result.propertyTables.Emplace_GetRef(encodePropertyTableAnyThreadPart( + *pExpectedPropertyTable, + propertyTable)); + encodedPropertyTable.name = propertyTableName; + } + } + + const TArray& propertyTextures = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTextures(metadata); + result.propertyTextures.Reserve(propertyTextures.Num()); + + TMap> + propertyTexturePropertyMap; + propertyTexturePropertyMap.Reserve(propertyTextures.Num()); + + for (const FCesiumPropertyTexture& propertyTexture : propertyTextures) { + FString propertyTextureName = getNameForPropertyTexture(propertyTexture); + + const FCesiumPropertyTextureDescription* pExpectedPropertyTexture = + metadataDescription.PropertyTextures.FindByPredicate( + [&propertyTextureName](const FCesiumPropertyTextureDescription& + expectedPropertyTexture) { + return propertyTextureName == expectedPropertyTexture.Name; + }); + + if (pExpectedPropertyTexture) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodePropertyTexture) + + auto& encodedPropertyTexture = result.propertyTextures.Emplace_GetRef( + encodePropertyTextureAnyThreadPart( + *pExpectedPropertyTexture, + propertyTexture, + propertyTexturePropertyMap)); + encodedPropertyTexture.name = propertyTextureName; + } + } + + return result; +} + +bool encodePropertyTableGameThreadPart( + EncodedPropertyTable& encodedPropertyTable) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodePropertyTable) + + bool success = true; + + for (EncodedPropertyTableProperty& encodedProperty : + encodedPropertyTable.properties) { + if (encodedProperty.pTexture) { + success &= + loadTextureGameThreadPart(encodedProperty.pTexture.Get()) != nullptr; + } + } + + return success; +} + +bool encodePropertyTextureGameThreadPart( + TArray& uniqueTextures, + EncodedPropertyTexture& encodedPropertyTexture) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodePropertyTexture) + + bool success = true; + + for (EncodedPropertyTextureProperty& property : + encodedPropertyTexture.properties) { + if (uniqueTextures.Find(property.pTexture.Get()) == INDEX_NONE) { + success &= loadTextureGameThreadPart(property.pTexture.Get()) != nullptr; + uniqueTextures.Emplace(property.pTexture.Get()); + } + } + + return success; +} + +bool encodeModelMetadataGameThreadPart(EncodedModelMetadata& encodedMetadata) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeMetadata) + + bool success = true; + + TArray uniqueTextures; + uniqueTextures.Reserve(encodedMetadata.propertyTextures.Num()); + for (auto& encodedPropertyTextureIt : encodedMetadata.propertyTextures) { + success &= encodePropertyTextureGameThreadPart( + uniqueTextures, + encodedPropertyTextureIt); + } + + for (auto& encodedPropertyTable : encodedMetadata.propertyTables) { + success &= encodePropertyTableGameThreadPart(encodedPropertyTable); + } + + return success; +} + +void destroyEncodedModelMetadata(EncodedModelMetadata& encodedMetadata) { + for (auto& propertyTable : encodedMetadata.propertyTables) { + for (EncodedPropertyTableProperty& encodedProperty : + propertyTable.properties) { + if (encodedProperty.pTexture) { + encodedProperty.pTexture->pTexture = nullptr; + } + } + } + + for (auto& encodedPropertyTextureIt : encodedMetadata.propertyTextures) { + for (EncodedPropertyTextureProperty& encodedPropertyTextureProperty : + encodedPropertyTextureIt.properties) { + if (encodedPropertyTextureProperty.pTexture) { + encodedPropertyTextureProperty.pTexture->pTexture = nullptr; + } + } + } +} + +// The result should be a safe hlsl identifier, but any name clashes +// after fixing safety will not be automatically handled. +FString createHlslSafeName(const FString& rawName) { + static const FString identifierHeadChar = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; + static const FString identifierTailChar = identifierHeadChar + "0123456789"; + + FString safeName = rawName; + int32 _; + if (safeName.Len() == 0) { + return "_"; + } else { + if (!identifierHeadChar.FindChar(safeName[0], _)) { + safeName = "_" + safeName; + } + } + + for (size_t i = 1; i < safeName.Len(); ++i) { + if (!identifierTailChar.FindChar(safeName[i], _)) { + safeName[i] = '_'; + } + } + + return safeName; +} + +// TODO: consider picking better pixel formats when they are available for the +// current platform. +EncodedPixelFormat getPixelFormat( + ECesiumEncodedMetadataType Type, + ECesiumEncodedMetadataComponentType ComponentType) { + switch (ComponentType) { + case ECesiumEncodedMetadataComponentType::Uint8: + switch (Type) { + case ECesiumEncodedMetadataType::Scalar: + return {EPixelFormat::PF_R8_UINT, 1, 1}; + case ECesiumEncodedMetadataType::Vec2: + case ECesiumEncodedMetadataType::Vec3: + case ECesiumEncodedMetadataType::Vec4: + return {EPixelFormat::PF_R8G8B8A8_UINT, 1, 4}; + default: + return {EPixelFormat::PF_Unknown, 0, 0}; + } + case ECesiumEncodedMetadataComponentType::Float: + switch (Type) { + case ECesiumEncodedMetadataType::Scalar: + return {EPixelFormat::PF_R32_FLOAT, 4, 1}; + case ECesiumEncodedMetadataType::Vec2: + case ECesiumEncodedMetadataType::Vec3: + case ECesiumEncodedMetadataType::Vec4: + // Note this is ABGR + return {EPixelFormat::PF_A32B32G32R32F, 4, 4}; + } + default: + return {EPixelFormat::PF_Unknown, 0, 0}; + } +} + +bool isSupportedPropertyTextureProperty( + const FCesiumMetadataPropertyDetails& PropertyDetails) { + if (PropertyDetails.bIsArray && + PropertyDetails.Type != ECesiumMetadataType::Scalar) { + // Only scalar arrays are supported. + return false; + } + + uint32 byteSize = GetMetadataTypeByteSize( + PropertyDetails.Type, + PropertyDetails.ComponentType); + if (PropertyDetails.bIsArray) { + byteSize *= PropertyDetails.ArraySize; + } + + return byteSize > 0 && byteSize <= 4; +} + +void SetPropertyParameterValue( + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index, + const FString& name, + ECesiumEncodedMetadataType type, + const FCesiumMetadataValue& value, + float defaultValue) { + if (type == ECesiumEncodedMetadataType::Scalar) { + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo(FName(name), association, index), + UCesiumMetadataValueBlueprintLibrary::GetFloat(value, defaultValue)); + } else if ( + type == ECesiumEncodedMetadataType::Vec2 || + type == ECesiumEncodedMetadataType::Vec3 || + type == ECesiumEncodedMetadataType::Vec4) { + FVector4 vector4Value = UCesiumMetadataValueBlueprintLibrary::GetVector4( + value, + FVector4(defaultValue, defaultValue, defaultValue, defaultValue)); + + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo(FName(name), association, index), + FLinearColor( + static_cast(vector4Value.X), + static_cast(vector4Value.Y), + static_cast(vector4Value.Z), + static_cast(vector4Value.W))); + } +} + +void SetFeatureIdTextureParameterValues( + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index, + const FString& name, + const EncodedFeatureIdTexture& encodedFeatureIdTexture) { + pMaterial->SetTextureParameterValueByInfo( + FMaterialParameterInfo( + FName(name + MaterialTextureSuffix), + association, + index), + encodedFeatureIdTexture.pTexture->pTexture->getUnrealTexture()); + + size_t numChannels = encodedFeatureIdTexture.channels.size(); + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo( + FName(name + MaterialNumChannelsSuffix), + association, + index), + static_cast(numChannels)); + + std::vector channelsAsFloats{0.0f, 0.0f, 0.0f, 0.0f}; + for (size_t i = 0; i < numChannels; i++) { + channelsAsFloats[i] = + static_cast(encodedFeatureIdTexture.channels[i]); + } + + FLinearColor channels{ + channelsAsFloats[0], + channelsAsFloats[1], + channelsAsFloats[2], + channelsAsFloats[3], + }; + + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo( + FName(name + MaterialChannelsSuffix), + association, + index), + channels); + + if (!encodedFeatureIdTexture.textureTransform) { + return; + } + + glm::dvec2 scale = encodedFeatureIdTexture.textureTransform->scale(); + glm::dvec2 offset = encodedFeatureIdTexture.textureTransform->offset(); + + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo( + FName(name + MaterialTextureScaleOffsetSuffix), + association, + index), + FLinearColor(scale[0], scale[1], offset[0], offset[1])); + + glm::dvec2 rotation = + encodedFeatureIdTexture.textureTransform->rotationSineCosine(); + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo( + FName(name + MaterialTextureRotationSuffix), + association, + index), + FLinearColor(rotation[0], rotation[1], 0.0f, 1.0f)); +} + +void SetPropertyTableParameterValues( + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index, + const EncodedPropertyTable& encodedPropertyTable) { + for (const EncodedPropertyTableProperty& encodedProperty : + encodedPropertyTable.properties) { + FString fullPropertyName = getMaterialNameForPropertyTableProperty( + encodedPropertyTable.name, + encodedProperty.name); + + if (encodedProperty.pTexture) { + pMaterial->SetTextureParameterValueByInfo( + FMaterialParameterInfo(FName(fullPropertyName), association, index), + encodedProperty.pTexture->pTexture->getUnrealTexture()); + } + + if (!UCesiumMetadataValueBlueprintLibrary::IsEmpty( + encodedProperty.offset)) { + FString parameterName = fullPropertyName + MaterialPropertyOffsetSuffix; + SetPropertyParameterValue( + pMaterial, + association, + index, + parameterName, + encodedProperty.type, + encodedProperty.offset, + 0.0f); + } + + if (!UCesiumMetadataValueBlueprintLibrary::IsEmpty(encodedProperty.scale)) { + FString parameterName = fullPropertyName + MaterialPropertyScaleSuffix; + SetPropertyParameterValue( + pMaterial, + association, + index, + parameterName, + encodedProperty.type, + encodedProperty.scale, + 1.0f); + } + + if (!UCesiumMetadataValueBlueprintLibrary::IsEmpty( + encodedProperty.noData)) { + FString parameterName = fullPropertyName + MaterialPropertyNoDataSuffix; + SetPropertyParameterValue( + pMaterial, + association, + index, + parameterName, + encodedProperty.type, + encodedProperty.noData, + 0.0f); + } + + if (!UCesiumMetadataValueBlueprintLibrary::IsEmpty( + encodedProperty.defaultValue)) { + FString parameterName = + fullPropertyName + MaterialPropertyDefaultValueSuffix; + SetPropertyParameterValue( + pMaterial, + association, + index, + parameterName, + encodedProperty.type, + encodedProperty.defaultValue, + 0.0f); + + FString hasValueName = fullPropertyName + MaterialPropertyHasValueSuffix; + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo(FName(hasValueName), association, index), + encodedProperty.pTexture ? 1.0 : 0.0); + } + } +} + +void SetPropertyTextureParameterValues( + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index, + const EncodedPropertyTexture& encodedPropertyTexture) { + for (const EncodedPropertyTextureProperty& encodedProperty : + encodedPropertyTexture.properties) { + FString fullPropertyName = getMaterialNameForPropertyTextureProperty( + encodedPropertyTexture.name, + encodedProperty.name); + + if (encodedProperty.pTexture) { + pMaterial->SetTextureParameterValueByInfo( + FMaterialParameterInfo(FName(fullPropertyName), association, index), + encodedProperty.pTexture->pTexture->getUnrealTexture()); + } + + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo( + FName(fullPropertyName + MaterialChannelsSuffix), + association, + index), + FLinearColor( + encodedProperty.channels[0], + encodedProperty.channels[1], + encodedProperty.channels[2], + encodedProperty.channels[3])); + + if (!UCesiumMetadataValueBlueprintLibrary::IsEmpty( + encodedProperty.offset)) { + FString parameterName = fullPropertyName + MaterialPropertyOffsetSuffix; + SetPropertyParameterValue( + pMaterial, + association, + index, + parameterName, + encodedProperty.type, + encodedProperty.offset, + 0.0f); + } + + if (!UCesiumMetadataValueBlueprintLibrary::IsEmpty(encodedProperty.scale)) { + FString parameterName = fullPropertyName + MaterialPropertyScaleSuffix; + SetPropertyParameterValue( + pMaterial, + association, + index, + parameterName, + encodedProperty.type, + encodedProperty.scale, + 1.0f); + } + + if (!UCesiumMetadataValueBlueprintLibrary::IsEmpty( + encodedProperty.noData)) { + FString parameterName = fullPropertyName + MaterialPropertyNoDataSuffix; + SetPropertyParameterValue( + pMaterial, + association, + index, + parameterName, + encodedProperty.type, + encodedProperty.noData, + 0.0f); + } + + if (!UCesiumMetadataValueBlueprintLibrary::IsEmpty( + encodedProperty.defaultValue)) { + FString parameterName = + fullPropertyName + MaterialPropertyDefaultValueSuffix; + SetPropertyParameterValue( + pMaterial, + association, + index, + parameterName, + encodedProperty.type, + encodedProperty.defaultValue, + 0.0f); + + FString hasValueName = fullPropertyName + MaterialPropertyHasValueSuffix; + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo(FName(hasValueName), association, index), + encodedProperty.pTexture ? 1.0 : 0.0); + } + + if (!encodedProperty.textureTransform) { + continue; + } + + glm::dvec2 scale = encodedProperty.textureTransform->scale(); + glm::dvec2 offset = encodedProperty.textureTransform->offset(); + + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo( + FName(fullPropertyName + MaterialTextureScaleOffsetSuffix), + association, + index), + FLinearColor(scale[0], scale[1], offset[0], offset[1])); + + glm::dvec2 rotation = + encodedProperty.textureTransform->rotationSineCosine(); + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo( + FName(fullPropertyName + MaterialTextureRotationSuffix), + association, + index), + FLinearColor(rotation[0], rotation[1], 0.0f, 1.0f)); + } +} + +} // namespace CesiumEncodedFeaturesMetadata diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.h new file mode 100644 index 0000000..45f3ece --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.h @@ -0,0 +1,556 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumMetadataEncodingDetails.h" +#include "CesiumMetadataValue.h" +#include "CesiumTextureUtility.h" +#include "Containers/Array.h" +#include "Containers/Map.h" +#include "Containers/UnrealString.h" +#include "Templates/SharedPointer.h" +#include "Templates/UniquePtr.h" +#include +#include +#include + +struct FCesiumFeatureIdSet; +struct FCesiumPrimitiveFeatures; +struct FCesiumModelMetadata; +struct FCesiumPrimitiveMetadata; +struct FCesiumPropertyTable; +struct FCesiumPropertyTableProperty; +struct FCesiumPropertyTexture; +struct FCesiumPropertyTableDescription; +struct FCesiumPropertyTextureDescription; +struct FFeatureTextureDescription; +struct FCesiumModelMetadataDescription; +struct FCesiumPrimitiveFeaturesDescription; +struct FCesiumPrimitiveMetadataDescription; + +struct FCesiumMetadataPropertyDetails; +class UMaterialInstanceDynamic; +enum EMaterialParameterAssociation : int; + +/** + * @brief Provides utility for encoding feature IDs from EXT_mesh_features and + * metadata from EXT_structural_metadata. "Encoding" refers broadly to the + * process of converting data to accessible formats on the GPU. This process + * also gives them names for use in Unreal materials. + * + * First, the desired feature ID sets / metadata properties must be filled out + * on a tileset's CesiumFeaturesMetadataComponent. Then, encoding will occur on + * a model-by-model basis. Not all models in a tileset may necessarily contain + * the feature IDs / metadata specified in the description. + */ +namespace CesiumEncodedFeaturesMetadata { + +/** + * Naming convention for feature ID texture parameters nodes: + * - Texture: FeatureIDTextureName + "_TX" + * - Texture Coordinate Index: FeatureIDTextureName + "_UV_INDEX" + * - Channels: FeatureIDTextureName + "_CHANNELS" + * - NumChannels: FeatureIDTextureName + "_NUM_CHANNELS" + */ +static const FString MaterialTextureSuffix = "_TX"; +static const FString MaterialTexCoordIndexSuffix = "_UV_INDEX"; +static const FString MaterialChannelsSuffix = "_CHANNELS"; +static const FString MaterialNumChannelsSuffix = "_NUM_CHANNELS"; + +/** + * - Null Feature ID node: FeatureIDSetName + "_NULL_ID" + */ +static const FString MaterialNullFeatureIdSuffix = "_NULL_ID"; + +/** + * Naming convention for metadata parameter nodes + * - Property Table Property: "PTABLE_" + PropertyTableName + PropertyName + */ +static const FString MaterialPropertyTablePrefix = "PTABLE_"; + +/** + * - Property Texture Property: "PTEXTURE_" + PropertyTextureName + PropertyName + * - Property Texture Property UV Index: "PTEXTURE_" + PropertyTextureName + + * PropertyName + "_UV_INDEX" + * - Property Texture Property Channels: "PTEXTURE_" + PropertyTextureName + + * PropertyName + "_CHANNELS" + */ +static const FString MaterialPropertyTexturePrefix = "PTEXTURE_"; + +/** + * Below, "PropertyEntityName" represents the name of either a property table or + * property texture. + * + * - Property Offset: Prefix + PropertyEntityName + PropertyName + "_OFFSET" + * - Property Scale: Prefix + PropertyEntityName + PropertyName + "_SCALE" + * - Property NoData: Prefix + PropertyEntityName + PropertyName + "_NO_DATA" + * - Property Default Value: Prefix + PropertyEntityName + PropertyName + + * "_DEFAULT" + * - Property Has Value Qualifier: Prefix + PropertyEntityName + PropertyName + * + "_HAS_VALUE" + */ +static const FString MaterialPropertyOffsetSuffix = "_OFFSET"; +static const FString MaterialPropertyScaleSuffix = "_SCALE"; +static const FString MaterialPropertyNoDataSuffix = "_NO_DATA"; +static const FString MaterialPropertyDefaultValueSuffix = "_DEFAULT"; +static const FString MaterialPropertyHasValueSuffix = "_HAS_VALUE"; + +/** + * Naming convention for material inputs (for use in custom functions): + * - Property Data: PropertyName + "_DATA" + * - Property Raw Value: PropertyName + "_RAW" + * - Property Transform Value: TransformName + + * "_VALUE" + * - Property UV Value: PropertyName = "_UV" + */ +static const FString MaterialPropertyDataSuffix = "_DATA"; +static const FString MaterialPropertyRawSuffix = "_RAW"; +static const FString MaterialPropertyValueSuffix = "_VALUE"; +static const FString MaterialPropertyUVSuffix = "_UV"; + +/** + * Naming convention for KHR_texture_transform inputs: + * - Texture Scale + Offset: TextureName + "_TX_SCALE_OFFSET" + * - Texture Rotation: TextureName + "_TX_ROTATION" + */ +static const FString MaterialTextureScaleOffsetSuffix = "_TX_SCALE_OFFSET"; +static const FString MaterialTextureRotationSuffix = "_TX_ROTATION"; + +#pragma region Encoded Primitive Features + +/** + * @brief Generates a name for a feature ID set in a glTF primitive's + * EXT_mesh_features. If the feature ID set already has a label, this will + * return the label. Otherwise, if the feature ID set is unlabeled, a name + * will be generated like so: + * + * - If the feature ID set is an attribute, this will appear as + * "_FEATURE_ID_", where is the set index specified in + * the attribute. + * - If the feature ID set is a texture, this will appear as + * "_FEATURE_ID_TEXTURE_", where increments with the number + * of feature ID textures seen in an individual primitive. + * - If the feature ID set is an implicit set, this will appear as + * "_IMPLICIT_FEATURE_ID". Implicit feature ID sets don't vary in + * definition, so any additional implicit feature ID sets across the + * primitives are counted by this one. + * + * This is used by FCesiumFeatureIdSetDescription to display the names of + * the feature ID sets across a tileset. + * + * @param FeatureIDSet The feature ID set + * @param FeatureIDTextureCounter The counter representing how many feature + * ID textures have been seen in the primitive thus far. Will be incremented + * by this function if the given feature ID set is a texture. + */ +FString getNameForFeatureIDSet( + const FCesiumFeatureIdSet& FeatureIDSet, + int32& FeatureIDTextureCounter); +/** + * @brief Generates a HLSL-safe name for a feature ID set. This is used by the + * material for parameter nodes. + * + * @param FeatureIDSet The feature ID set + * @param FeatureIDTextureCounter The counter representing how many feature ID + * textures have been seen in the primitive thus far. Will be incremented by + * this function if the given feature ID set is a texture. + */ +FString getMaterialNameForFeatureIDSet(); + +/** + * @brief A feature ID texture that has been encoded for access on the GPU. + */ +struct EncodedFeatureIdTexture { + /** + * @brief The actual feature ID texture. + */ + TSharedPtr pTexture; + + /** + * @brief The channels that this feature ID texture uses within the image. + */ + std::vector channels; + + /** + * @brief The set index of the texture coordinates used to sample this feature + * ID texture. + */ + int64 textureCoordinateSetIndex; + + /** + * @brief The KHR_texture_transform extension on this feature ID texture, if + * it exists. + */ + std::optional textureTransform; +}; + +/** + * @brief A feature ID set that has been encoded for access on the GPU. + */ +struct EncodedFeatureIdSet { + /** + * @brief The name assigned to this feature ID set. This will be used as a + * variable name in the generated Unreal material. + */ + FString name; + + /** + * @brief The index of this feature ID set in the FCesiumPrimitiveFeatures on + * the glTF primitive. + */ + int32 index; + + /** + * @brief The set index of the feature ID attribute. This is an integer value + * used to construct a string in the format "_FEATURE_ID_", + * corresponding to a glTF primitive attribute of the same name. Only + * applicable if the feature ID set represents a feature ID attribute. + */ + std::optional attribute; + + /** + * @brief The encoded feature ID texture. Only applicable if the feature ID + * set represents a feature ID texture. + */ + std::optional texture; + + /** + * @brief The name of the property table that this feature ID set corresponds + * to. Only applicable if the model contains the `EXT_structural_metadata` + * extension. + */ + FString propertyTableName; + + /** + * A value that indicates that no feature is associated with the vertices or + * texels that have this value. + */ + std::optional nullFeatureId; +}; + +/** + * @brief The encoded representation of the EXT_mesh_features of a glTF + * primitive. + */ +struct EncodedPrimitiveFeatures { + TArray featureIdSets; +}; + +/** + * @brief Prepares the EXT_mesh_features of a glTF primitive to be encoded, for + * use with Unreal Engine materials. This only encodes the feature ID sets + * specified by the FCesiumPrimitiveFeaturesDescription. + */ +EncodedPrimitiveFeatures encodePrimitiveFeaturesAnyThreadPart( + const FCesiumPrimitiveFeaturesDescription& featuresDescription, + const FCesiumPrimitiveFeatures& features); + +/** + * @brief Encodes the EXT_mesh_features of a glTF primitive for use with Unreal + * Engine materials. + * + * @returns True if the encoding of all feature ID sets was successful, false + * otherwise. + */ +bool encodePrimitiveFeaturesGameThreadPart( + EncodedPrimitiveFeatures& encodedFeatures); + +void destroyEncodedPrimitiveFeatures(EncodedPrimitiveFeatures& encodedFeatures); + +#pragma endregion + +#pragma region Encoded Metadata + +/** + * @brief Generates a name for a property table in a glTF model's + * EXT_structural_metadata. If the property table already has a name, this will + * return the name. Otherwise, if the property table is unlabeled, its + * corresponding class will be substituted. + * + * This is used by FCesiumPropertyTableDescription to display the names of + * the property tables across a tileset. + * + * @param PropertyTable The property table + */ +FString getNameForPropertyTable(const FCesiumPropertyTable& PropertyTable); + +/** + * @brief Generates a name for a property texture in a glTF model's + * EXT_structural_metadata. If the property texture already has a name, this + * will return the name. Otherwise, if the property texture is unlabeled, its + * corresponding class will be substituted. + * + * This is used by FCesiumPropertyTextureDescription to display the names of + * the property textures across a tileset. + * + * @param PropertyTexture The property texture + */ +FString +getNameForPropertyTexture(const FCesiumPropertyTexture& PropertyTexture); + +/** + * @brief Generates an HLSL-safe name for a property table property in a glTF + * model's EXT_structural_metadata. This is formatted like so: + * + * "PTABLE__" + * + * This is used to name the texture parameter corresponding to this property in + * the generated Unreal material. + */ +FString getMaterialNameForPropertyTableProperty( + const FString& propertyTableName, + const FString& propertyName); + +/** + * @brief Generates an HLSL-safe name for a property texture property in a glTF + * model's EXT_structural_metadata. This is formatted like so: + * + * "PTEXTURE__" + * + * This is used to name the texture parameter corresponding to this property in + * the generated Unreal material. + */ +FString getMaterialNameForPropertyTextureProperty( + const FString& propertyTableName, + const FString& propertyName); + +/** + * A property table property that has been encoded for access on the GPU. + */ +struct EncodedPropertyTableProperty { + /** + * @brief The name of the property table property. + */ + FString name; + + /** + * @brief The property table property values, encoded into a texture. + */ + TUniquePtr pTexture; + + /** + * @brief The type that the metadata will be encoded as. + */ + ECesiumEncodedMetadataType type; + + /** + * @brief The property table property's offset. + */ + FCesiumMetadataValue offset; + + /** + * @brief The property table property's scale. + */ + FCesiumMetadataValue scale; + + /** + * @brief The property table property's "no data" value. + */ + FCesiumMetadataValue noData; + + /** + * @brief The property table property's default value. + */ + FCesiumMetadataValue defaultValue; +}; + +/** + * A property table whose properties have been encoded for access on the GPU. + */ +struct EncodedPropertyTable { + /** + * @brief The name assigned to this property table. This will be used to + * construct variable names in the generated Unreal material. + */ + FString name; + + /** + * @brief The encoded properties in this property table. + */ + TArray properties; +}; + +/** + * A property texture property that has been made accessible to Unreal materials + * through the GPU. + */ +struct EncodedPropertyTextureProperty { + /** + * @brief The name of the property texture property. + */ + FString name; + + /** + * @brief The texture used by the property texture property. + */ + TSharedPtr pTexture; + + /** + * @brief The type that of the metadata encoded in the texture. + */ + ECesiumEncodedMetadataType type; + + /** + * @brief The set index of the texture coordinates from the glTF primitive + * that are used to sample this property texture. If this is -1, this texture + * will not be sampled by texture coordinates in the primitive, but may be + * sampled by other means in the Unreal material. + */ + int64 textureCoordinateSetIndex; + + /** + * @brief The channels to use when constructing a value from texture data. The + * number of channels used is specified in the material itself, and derives + * from the type of the property. + */ + std::array channels; + + /** + * @brief The property table property's offset. + */ + FCesiumMetadataValue offset; + + /** + * @brief The property table property's scale. + */ + FCesiumMetadataValue scale; + + /** + * @brief The property table property's "no data" value. + */ + FCesiumMetadataValue noData; + + /** + * @brief The property table property's default value. + */ + FCesiumMetadataValue defaultValue; + + /** + * @brief The KHR_texture_transform extension on this feature ID texture, if + * it exists. + */ + std::optional textureTransform; +}; + +/** + * A property texture whose properties have been made accessible to Unreal + * materials. + */ +struct EncodedPropertyTexture { + /** + * @brief The name assigned to this property texture. This will be used to + * construct variable names in the generated Unreal material. + */ + FString name; + + /** + * @brief The encoded properties in this property texture. + */ + TArray properties; +}; + +/** + * @brief The encoded representation of the EXT_structural_metadata of a glTF + * primitive. + */ +struct EncodedPrimitiveMetadata { + /** + * @brief The indices of the property textures used by the primitive. + */ + TArray propertyTextureIndices; +}; + +/** + * @brief The encoded representation of the EXT_structural_metadata of a glTF + * model. + */ +struct EncodedModelMetadata { + TArray propertyTables; + TArray propertyTextures; +}; + +EncodedPropertyTable encodePropertyTableAnyThreadPart( + const FCesiumPropertyTableDescription& propertyTableDescription, + const FCesiumPropertyTable& propertyTable); + +EncodedPropertyTexture encodePropertyTextureAnyThreadPart( + const FCesiumPropertyTextureDescription& propertyTextureDescription, + const FCesiumPropertyTexture& propertyTexture, + TMap< + const CesiumGltf::ImageAsset*, + TWeakPtr>& + propertyTexturePropertyMap); + +EncodedPrimitiveMetadata encodePrimitiveMetadataAnyThreadPart( + const FCesiumPrimitiveMetadataDescription& metadataDescription, + const FCesiumPrimitiveMetadata& primitive, + const FCesiumModelMetadata& modelMetadata); + +EncodedModelMetadata encodeModelMetadataAnyThreadPart( + const FCesiumModelMetadataDescription& metadataDescription, + const FCesiumModelMetadata& modelMetadata); + +bool encodePropertyTableGameThreadPart( + EncodedPropertyTable& encodedFeatureTable); + +bool encodePropertyTextureGameThreadPart( + TArray>& + uniqueTextures, + EncodedPropertyTexture& encodedFeatureTexture); + +bool encodeModelMetadataGameThreadPart(EncodedModelMetadata& encodedMetadata); + +void destroyEncodedModelMetadata(EncodedModelMetadata& encodedMetadata); + +#pragma endregion + +#pragma region Utility + +struct EncodedPixelFormat { + EPixelFormat format; + int32_t bytesPerChannel; + int32_t channels; +}; + +// TODO: consider picking better pixel formats when they are available for the +// current platform. +EncodedPixelFormat getPixelFormat( + ECesiumEncodedMetadataType Type, + ECesiumEncodedMetadataComponentType ComponentType); + +FString createHlslSafeName(const FString& rawName); + +bool isSupportedPropertyTextureProperty( + const FCesiumMetadataPropertyDetails& PropertyDetails); + +void SetPropertyParameterValue( + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index, + const FString& name, + ECesiumEncodedMetadataType type, + const FCesiumMetadataValue& value, + float defaultValue); + +void SetFeatureIdTextureParameterValues( + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index, + const FString& name, + const EncodedFeatureIdTexture& encodedFeatureIdTexture); + +void SetPropertyTableParameterValues( + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index, + const EncodedPropertyTable& encodedPropertyTable); + +void SetPropertyTextureParameterValues( + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index, + const EncodedPropertyTexture& encodedPropertyTexture); + +#pragma endregion + +} // namespace CesiumEncodedFeaturesMetadata diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataConversions.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataConversions.cpp new file mode 100644 index 0000000..7ac5a7b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataConversions.cpp @@ -0,0 +1,568 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumEncodedMetadataConversions.h" +#include "CesiumFeaturesMetadataComponent.h" +#include "CesiumMetadataEncodingDetails.h" +#include "CesiumMetadataPropertyDetails.h" +#include "CesiumPropertyArrayBlueprintLibrary.h" +#include "CesiumPropertyTableProperty.h" +#include + +#include +#include + +namespace { +ECesiumEncodedMetadataType +GetBestFittingEncodedType(FCesiumMetadataPropertyDetails PropertyDetails) { + ECesiumMetadataType type = PropertyDetails.Type; + if (PropertyDetails.bIsArray) { + if (PropertyDetails.ArraySize <= 0) { + // Variable-length array properties are unsupported. + return ECesiumEncodedMetadataType::None; + } + + if (type != ECesiumMetadataType::Boolean && + type != ECesiumMetadataType::Scalar) { + // Only boolean and scalar array properties are supported. + return ECesiumEncodedMetadataType::None; + } + + int64 componentCount = + std::min(PropertyDetails.ArraySize, static_cast(4)); + switch (componentCount) { + case 1: + return ECesiumEncodedMetadataType::Scalar; + case 2: + return ECesiumEncodedMetadataType::Vec2; + case 3: + return ECesiumEncodedMetadataType::Vec3; + case 4: + return ECesiumEncodedMetadataType::Vec4; + default: + return ECesiumEncodedMetadataType::None; + } + } + + switch (type) { + case ECesiumMetadataType::Boolean: + case ECesiumMetadataType::Scalar: + return ECesiumEncodedMetadataType::Scalar; + case ECesiumMetadataType::Vec2: + return ECesiumEncodedMetadataType::Vec2; + case ECesiumMetadataType::Vec3: + return ECesiumEncodedMetadataType::Vec3; + case ECesiumMetadataType::Vec4: + return ECesiumEncodedMetadataType::Vec4; + default: + return ECesiumEncodedMetadataType::None; + } +} + +ECesiumEncodedMetadataComponentType +GetBestFittingEncodedComponentType(ECesiumMetadataComponentType ComponentType) { + switch (ComponentType) { + case ECesiumMetadataComponentType::Int8: // lossy or reinterpreted + case ECesiumMetadataComponentType::Uint8: + return ECesiumEncodedMetadataComponentType::Uint8; + case ECesiumMetadataComponentType::Int16: + case ECesiumMetadataComponentType::Uint16: + case ECesiumMetadataComponentType::Int32: // lossy or reinterpreted + case ECesiumMetadataComponentType::Uint32: // lossy or reinterpreted + case ECesiumMetadataComponentType::Int64: // lossy + case ECesiumMetadataComponentType::Uint64: // lossy + case ECesiumMetadataComponentType::Float32: + case ECesiumMetadataComponentType::Float64: // lossy + return ECesiumEncodedMetadataComponentType::Float; + default: + return ECesiumEncodedMetadataComponentType::None; + } +} +} // namespace + +ECesiumEncodedMetadataType + +CesiumMetadataTypeToEncodingType(ECesiumMetadataType Type) { + switch (Type) { + case ECesiumMetadataType::Scalar: + return ECesiumEncodedMetadataType::Scalar; + case ECesiumMetadataType::Vec2: + return ECesiumEncodedMetadataType::Vec2; + case ECesiumMetadataType::Vec3: + return ECesiumEncodedMetadataType::Vec3; + case ECesiumMetadataType::Vec4: + return ECesiumEncodedMetadataType::Vec4; + default: + return ECesiumEncodedMetadataType::None; + } +} + +FCesiumMetadataEncodingDetails CesiumMetadataPropertyDetailsToEncodingDetails( + FCesiumMetadataPropertyDetails PropertyDetails) { + ECesiumEncodedMetadataType type = GetBestFittingEncodedType(PropertyDetails); + + if (type == ECesiumEncodedMetadataType::None) { + // The type cannot be encoded at all; return. + return FCesiumMetadataEncodingDetails(); + } + + ECesiumEncodedMetadataComponentType componentType = + GetBestFittingEncodedComponentType(PropertyDetails.ComponentType); + + return FCesiumMetadataEncodingDetails( + type, + componentType, + ECesiumEncodedMetadataConversion::Coerce); +} + +size_t +CesiumGetEncodedMetadataTypeComponentCount(ECesiumEncodedMetadataType Type) { + switch (Type) { + case ECesiumEncodedMetadataType::Scalar: + return 1; + case ECesiumEncodedMetadataType::Vec2: + return 2; + case ECesiumEncodedMetadataType::Vec3: + return 3; + case ECesiumEncodedMetadataType::Vec4: + return 4; + default: + return 0; + } +} + +namespace { +template +void coerceAndEncodeArrays( + const FCesiumPropertyTablePropertyDescription& propertyDescription, + const FCesiumPropertyTableProperty& property, + const std::span& textureData, + size_t pixelSize) { + int64 propertySize = + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize(property); + int64 arraySize = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property); + size_t componentCount = CesiumGetEncodedMetadataTypeComponentCount( + propertyDescription.EncodingDetails.Type); + // Encode up to four array elements. + int64 elementCount = std::min(static_cast(componentCount), arraySize); + + if (textureData.size() < propertySize * elementCount * sizeof(T)) { + throw std::runtime_error( + "Buffer is too small to store the data of this property."); + } + + uint8* pWritePos = reinterpret_cast(textureData.data()); + for (int64 i = 0; i < propertySize; ++i) { + FCesiumPropertyArray array = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, i); + if constexpr (std::is_same_v) { + for (int64 j = 0; j < elementCount; ++j) { + const FCesiumMetadataValue& value = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, j); + *(pWritePos + j) = + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 0); + } + } else if constexpr (std::is_same_v) { + // Floats are encoded backwards (e.g., ABGR) + float* pWritePosF = reinterpret_cast(pWritePos + pixelSize) - 1; + for (int64 j = 0; j < elementCount; ++j) { + const FCesiumMetadataValue& value = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, j); + *pWritePosF = + UCesiumMetadataValueBlueprintLibrary::GetFloat(value, 0.0f); + --pWritePosF; + } + } + pWritePos += pixelSize; + } +} + +template +void coerceAndEncodeScalars( + const FCesiumPropertyTableProperty& property, + const std::span& textureData) { + int64 propertySize = + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize(property); + if (textureData.size() < propertySize * sizeof(T)) { + throw std::runtime_error( + "Buffer is too small to store the data of this property."); + } + + T* pWritePos = reinterpret_cast(textureData.data()); + + for (int64 i = 0; i < propertySize; ++i) { + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetRawValue(property, i); + + if constexpr (std::is_same_v) { + *pWritePos = UCesiumMetadataValueBlueprintLibrary::GetByte(value, 0); + } else if constexpr (std::is_same_v) { + *pWritePos = UCesiumMetadataValueBlueprintLibrary::GetFloat(value, 0.0f); + } + + ++pWritePos; + } + return; +} + +template +void coerceAndEncodeVec2s( + const FCesiumPropertyTableProperty& property, + const std::span& textureData, + size_t pixelSize) { + int64 propertySize = + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize(property); + if (textureData.size() < propertySize * 2 * sizeof(T)) { + throw std::runtime_error( + "Buffer is too small to store the data of this property."); + } + + uint8* pWritePos = reinterpret_cast(textureData.data()); + + for (int64 i = 0; i < propertySize; ++i) { + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetRawValue(property, i); + + if constexpr (std::is_same_v) { + FIntPoint vec2 = UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + value, + FIntPoint(0)); + for (int64 j = 0; j < 2; ++j) { + *(pWritePos + j) = + CesiumGltf::MetadataConversions::convert(vec2[j]) + .value_or(0); + } + } else if constexpr (std::is_same_v) { + FVector2D vec2 = UCesiumMetadataValueBlueprintLibrary::GetVector2D( + value, + FVector2D::Zero()); + + // Floats are encoded backwards (e.g., ABGR) + float* pWritePosF = reinterpret_cast(pWritePos + pixelSize) - 1; + for (int64 j = 0; j < 2; ++j) { + *pWritePosF = + CesiumGltf::MetadataConversions::convert(vec2[j]) + .value_or(0.0f); + --pWritePosF; + } + } + + pWritePos += pixelSize; + } +} + +template +void coerceAndEncodeVec3s( + const FCesiumPropertyTableProperty& property, + const std::span& textureData, + size_t pixelSize) { + int64 propertySize = + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize(property); + if (textureData.size() < propertySize * 3 * sizeof(T)) { + throw std::runtime_error( + "Buffer is too small to store the data of this property."); + } + + uint8* pWritePos = reinterpret_cast(textureData.data()); + + for (int64 i = 0; i < propertySize; ++i) { + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetRawValue(property, i); + + if constexpr (std::is_same_v) { + FIntVector vec3 = UCesiumMetadataValueBlueprintLibrary::GetIntVector( + value, + FIntVector(0)); + for (int64 j = 0; j < 3; ++j) { + *(pWritePos + j) = + CesiumGltf::MetadataConversions::convert(vec3[j]) + .value_or(0); + } + } else if constexpr (std::is_same_v) { + FVector3f vec3 = UCesiumMetadataValueBlueprintLibrary::GetVector3f( + value, + FVector3f::Zero()); + + // Floats are encoded backwards (e.g., ABGR) + float* pWritePosF = reinterpret_cast(pWritePos + pixelSize) - 1; + for (int64 j = 0; j < 3; ++j) { + *pWritePosF = vec3[j]; + --pWritePosF; + } + } + + pWritePos += pixelSize; + } +} + +template +void coerceAndEncodeVec4s( + const FCesiumPropertyTableProperty& property, + const std::span& textureData, + size_t pixelSize) { + int64 propertySize = + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize(property); + if (textureData.size() < propertySize * 4 * sizeof(T)) { + throw std::runtime_error( + "Buffer is too small to store the data of this property."); + } + + uint8* pWritePos = reinterpret_cast(textureData.data()); + + for (int64 i = 0; i < propertySize; ++i) { + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetRawValue(property, i); + FVector4 vec4 = UCesiumMetadataValueBlueprintLibrary::GetVector4( + value, + FVector4::Zero()); + + if constexpr (std::is_same_v) { + for (int64 j = 0; j < 4; ++j) { + *(pWritePos + j) = + CesiumGltf::MetadataConversions::convert(vec4[j]) + .value_or(0); + } + } else if constexpr (std::is_same_v) { + // Floats are encoded backwards (e.g., ABGR) + float* pWritePosF = reinterpret_cast(pWritePos + pixelSize) - 1; + for (int64 j = 0; j < 4; ++j) { + *pWritePosF = + CesiumGltf::MetadataConversions::convert(vec4[j]) + .value_or(0.0f); + --pWritePosF; + } + } + + pWritePos += pixelSize; + } +} +} // namespace + +bool CesiumEncodedMetadataCoerce::canEncode( + const FCesiumPropertyTablePropertyDescription& description) { + const ECesiumMetadataType type = description.PropertyDetails.Type; + + if (type == ECesiumMetadataType::Boolean || + type == ECesiumMetadataType::String) { + // Booleans and boolean arrays are supported. + // Strings and string arrays are technically supported for all encoded + // types. This will attempt to coerce a string by parsing it as the + // specified encoded type. If coercion fails, they default to zero values. + return true; + } + + const ECesiumMetadataComponentType componentType = + description.PropertyDetails.ComponentType; + if (componentType == ECesiumMetadataComponentType::None) { + // Can't coerce a numeric property that doesn't know its component type. + return false; + } + + if (description.PropertyDetails.bIsArray) { + // Only scalar and boolean types are supported. (Booleans will have been + // verified earlier in this function). + return type == ECesiumMetadataType::Scalar; + } + + switch (type) { + case ECesiumMetadataType::Scalar: + // Scalars can be converted to vecNs. + return true; + case ECesiumMetadataType::Vec2: + case ECesiumMetadataType::Vec3: + case ECesiumMetadataType::Vec4: + // VecNs can be converted to other vecNs of different dimensions, but not to + // scalars. + return description.EncodingDetails.Type != + ECesiumEncodedMetadataType::Scalar; + default: + return false; + } +} + +void CesiumEncodedMetadataCoerce::encode( + const FCesiumPropertyTablePropertyDescription& propertyDescription, + const FCesiumPropertyTableProperty& property, + const std::span& textureData, + size_t pixelSize) { + if (propertyDescription.PropertyDetails.bIsArray) { + if (propertyDescription.EncodingDetails.ComponentType == + ECesiumEncodedMetadataComponentType::Uint8) { + coerceAndEncodeArrays( + propertyDescription, + property, + textureData, + pixelSize); + } else if ( + propertyDescription.EncodingDetails.ComponentType == + ECesiumEncodedMetadataComponentType::Float) { + coerceAndEncodeArrays( + propertyDescription, + property, + textureData, + pixelSize); + } + return; + } + + if (propertyDescription.EncodingDetails.ComponentType == + ECesiumEncodedMetadataComponentType::Uint8) { + switch (propertyDescription.EncodingDetails.Type) { + case ECesiumEncodedMetadataType::Scalar: + coerceAndEncodeScalars(property, textureData); + break; + case ECesiumEncodedMetadataType::Vec2: + coerceAndEncodeVec2s(property, textureData, pixelSize); + break; + case ECesiumEncodedMetadataType::Vec3: + coerceAndEncodeVec3s(property, textureData, pixelSize); + break; + case ECesiumEncodedMetadataType::Vec4: + coerceAndEncodeVec4s(property, textureData, pixelSize); + break; + default: + break; + } + } else if ( + propertyDescription.EncodingDetails.ComponentType == + ECesiumEncodedMetadataComponentType::Float) { + switch (propertyDescription.EncodingDetails.Type) { + case ECesiumEncodedMetadataType::Scalar: + coerceAndEncodeScalars(property, textureData); + break; + case ECesiumEncodedMetadataType::Vec2: + coerceAndEncodeVec2s(property, textureData, pixelSize); + break; + case ECesiumEncodedMetadataType::Vec3: + coerceAndEncodeVec3s(property, textureData, pixelSize); + break; + case ECesiumEncodedMetadataType::Vec4: + coerceAndEncodeVec4s(property, textureData, pixelSize); + break; + default: + break; + } + } +} + +namespace { +/** + * @param hexString The string containing the hex code color, including the # + * prefix. + */ +glm::u8vec3 getHexColorFromString(const FString& hexString) { + glm::u8vec3 result(0); + + // Get the code without the # sign + FString hexSubstr = hexString.Mid(1); + std::string hexStr = TCHAR_TO_UTF8(*hexSubstr); + size_t length = hexStr.length(); + if (length != 3 && length != 6) { + return result; + } + + size_t substringLength = length / 3; + for (int32 i = 0; i < 3; i++) { + std::string substr = hexStr.substr(i * substringLength, substringLength); + int32_t component = std::stoi(substr, 0, 16); + result[i] = + CesiumGltf::MetadataConversions::convert(component) + .value_or(0); + } + + return result; +} + +/** + * @param rgbString The string containing the rgb color in its original rgb(R, + * G, B) format. + */ +glm::u8vec3 getRgbColorFromString(const FString& rgbString) { + glm::u8vec3 result(0); + + TArray parts; + parts.Reserve(3); + + int partCount = rgbString.Mid(4, rgbString.Len() - 5) + .ParseIntoArray(parts, TEXT(","), false); + if (partCount == 3) { + result[0] = FCString::Atoi(*parts[0]); + result[1] = FCString::Atoi(*parts[1]); + result[2] = FCString::Atoi(*parts[2]); + } + + return result; +} + +template +void parseAndEncodeColors( + const FCesiumPropertyTableProperty& property, + const std::span& textureData, + size_t pixelSize) { + int64 propertySize = + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize(property); + if (textureData.size() < propertySize * 3 * sizeof(T)) { + throw std::runtime_error( + "Buffer is too small to store the data of this property."); + } + + uint8* pWritePos = reinterpret_cast(textureData.data()); + + for (int64 i = 0; i < propertySize; i++) { + FString str = + UCesiumPropertyTablePropertyBlueprintLibrary::GetString(property, i); + + // This could be expanded to handle float or vec4 color representations. + glm::u8vec3 color(0); + + if (str.StartsWith(TEXT("#"))) { + // Handle hex case + color = getHexColorFromString(str); + } else if (str.StartsWith(TEXT("rgb(")) && str.EndsWith(TEXT(")"))) { + // Handle rgb(R,G,B) case + color = getRgbColorFromString(str); + } + + if constexpr (std::is_same_v) { + for (int64 j = 0; j < 3; j++) { + *(pWritePos + j) = color[j]; + } + } else if constexpr (std::is_same_v) { + // Floats are encoded backwards (e.g., ABGR) + float* pWritePosF = reinterpret_cast(pWritePos + pixelSize) - 1; + for (int64 j = 0; j < 3; j++) { + *pWritePosF = + CesiumGltf::MetadataConversions::convert(color[j]) + .value_or(0.0f); + --pWritePosF; + } + } + + pWritePos += pixelSize; + } +} +} // namespace + +bool CesiumEncodedMetadataParseColorFromString::canEncode( + const FCesiumPropertyTablePropertyDescription& description) { + return description.PropertyDetails.Type == ECesiumMetadataType::String && + !description.PropertyDetails.bIsArray && + (description.EncodingDetails.Type == + ECesiumEncodedMetadataType::Vec3 || + description.EncodingDetails.Type == ECesiumEncodedMetadataType::Vec4); +} + +void CesiumEncodedMetadataParseColorFromString::encode( + const FCesiumPropertyTablePropertyDescription& propertyDescription, + const FCesiumPropertyTableProperty& property, + const std::span& textureData, + size_t pixelSize) { + if (propertyDescription.EncodingDetails.ComponentType == + ECesiumEncodedMetadataComponentType::Uint8) { + parseAndEncodeColors(property, textureData, pixelSize); + } else if ( + propertyDescription.EncodingDetails.ComponentType == + ECesiumEncodedMetadataComponentType::Float) { + parseAndEncodeColors(property, textureData, pixelSize); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataConversions.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataConversions.h new file mode 100644 index 0000000..d3ed133 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataConversions.h @@ -0,0 +1,118 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "HAL/Platform.h" +#include + +enum class ECesiumMetadataType : uint8; +enum class ECesiumEncodedMetadataType : uint8; +struct FCesiumPropertyTablePropertyDescription; +struct FCesiumPropertyTableProperty; +struct FCesiumMetadataPropertyDetails; +struct FCesiumMetadataEncodingDetails; + +/** + * @brief Gets the best-fitting encoded type for the given metadata type. + */ +ECesiumEncodedMetadataType +CesiumMetadataTypeToEncodingType(ECesiumMetadataType Type); + +/** + * @brief Gets the best-fitting encoded types and conversion method for a given + * metadata type. This determines the best way (if one is possible) to transfer + * values of the given type to the GPU, for access in Unreal materials. + * + * An array size can also be supplied if bIsArray is true on the given value + * type. If bIsArray is true, but the given array size is zero, this indicates + * the arrays of the property vary in length. Variable-length array properties + * are unsupported. + * + * @param PropertyDetails The metadata property details + */ +FCesiumMetadataEncodingDetails CesiumMetadataPropertyDetailsToEncodingDetails( + FCesiumMetadataPropertyDetails PropertyDetails); + +/** + * @brief Gets the number of components associated with the given encoded type. + * @param type The encoded metadata type. + */ +size_t +CesiumGetEncodedMetadataTypeComponentCount(ECesiumEncodedMetadataType Type); + +/** + * Any custom encoding behavior, e.g., special encoding of unsupported + * properties, can go here. Use the below methods as examples. + */ + +/** + * @brief Coerces property values to the type specified by the property + * description. The following property types are supported: + * - scalars + * - vecNs + * - booleans + * - scalar and boolean arrays (up to the first four elements) + * + * Additionally, if the property contains strings or string arrays, it will + * attempt to parse numbers from each string, then coerce those numbers to the + * desired format. + */ +struct CesiumEncodedMetadataCoerce { + /** + * Whether it is possible to apply the encoding method based on the property + * description. + * + * @param description The property table property description. + */ + static bool + canEncode(const FCesiumPropertyTablePropertyDescription& description); + + /** + * Encodes the data of the property table property into the given texture data + * pointer, as the type specified in the property description. + * + * @param propertyDescription The property table property description. + * @param property The property table property itself. + * @param pTextureData A pointer to the texture data, which will be filled + * during encoding. + * @param pixelSize The size of a pixel from the given texture, in bytes. + */ + static void encode( + const FCesiumPropertyTablePropertyDescription& propertyDescription, + const FCesiumPropertyTableProperty& property, + const std::span& pTextureData, + size_t pixelSize); +}; + +/** + * @brief Attempts to parse colors from string property values and encode them + * for access in Unreal materials. This supports the following formats: + * - rgb(R,G,B), where R, G, and B are values in the range [0, 255] + * - hexcode colors, e.g. #AF012B and #fff + */ +struct CesiumEncodedMetadataParseColorFromString { + /** + * Whether it is possible to apply the encoding method based on the property + * description. + * + * @param description The property table property description. + */ + static bool + canEncode(const FCesiumPropertyTablePropertyDescription& description); + + /** + * Encodes the data of the property table property into the given texture data + * pointer, as the type specified in the property description. + * + * @param propertyDescription The property table property description. + * @param property The property table property itself. + * @param pTextureData A pointer to the texture data, which will be filled + * during encoding. + * @param pixelSize The size of a pixel from the given texture, in bytes. + */ + static void encode( + const FCesiumPropertyTablePropertyDescription& propertyDescription, + const FCesiumPropertyTableProperty& property, + const std::span& textureData, + size_t pixelSize); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.cpp new file mode 100644 index 0000000..28f6fa3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.cpp @@ -0,0 +1,766 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumEncodedMetadataUtility.h" +#include "CesiumEncodedMetadataComponent.h" +#include "CesiumFeatureIdAttribute.h" +#include "CesiumFeatureIdTexture.h" +#include "CesiumLifetime.h" +#include "CesiumMetadataPrimitive.h" +#include "CesiumModelMetadata.h" +#include "CesiumPropertyArray.h" +#include "CesiumPropertyArrayBlueprintLibrary.h" +#include "CesiumPropertyTable.h" +#include "CesiumPropertyTableProperty.h" +#include "CesiumPropertyTexture.h" +#include "CesiumRuntime.h" +#include "Containers/Map.h" +#include "PixelFormat.h" +#include "TextureResource.h" +#include "UnrealMetadataConversions.h" +#include +#include +#include +#include +#include + +using namespace CesiumTextureUtility; + +PRAGMA_DISABLE_DEPRECATION_WARNINGS + +namespace CesiumEncodedMetadataUtility { + +namespace { + +struct EncodedPixelFormat { + EPixelFormat format; + int32_t bytesPerChannel; + int32_t channels; +}; + +// TODO: consider picking better pixel formats when they are available for the +// current platform. +EncodedPixelFormat getPixelFormat( + ECesiumMetadataPackedGpuType_DEPRECATED type, + int64 componentCount, + bool isNormalized) { + + switch (type) { + case ECesiumMetadataPackedGpuType_DEPRECATED::Uint8_DEPRECATED: + switch (componentCount) { + case 1: + return { + isNormalized ? EPixelFormat::PF_R8 : EPixelFormat::PF_R8_UINT, + 1, + 1}; + case 2: + case 3: + case 4: + return { + isNormalized ? EPixelFormat::PF_R8G8B8A8 + : EPixelFormat::PF_R8G8B8A8_UINT, + 1, + 4}; + default: + return {EPixelFormat::PF_Unknown, 0}; + } + case ECesiumMetadataPackedGpuType_DEPRECATED::Float_DEPRECATED: + switch (componentCount) { + case 1: + return {EPixelFormat::PF_R32_FLOAT, 4, 1}; + case 2: + case 3: + case 4: + // Note this is ABGR + return {EPixelFormat::PF_A32B32G32R32F, 4, 4}; + } + default: + return {EPixelFormat::PF_Unknown, 0, 0}; + } +} +} // namespace + +EncodedMetadataFeatureTable encodeMetadataFeatureTableAnyThreadPart( + const FFeatureTableDescription& featureTableDescription, + const FCesiumPropertyTable& featureTable) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeFeatureTable) + + EncodedMetadataFeatureTable encodedFeatureTable; + + int64 featureCount = + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount(featureTable); + + const TMap& properties = + UCesiumPropertyTableBlueprintLibrary::GetProperties(featureTable); + + encodedFeatureTable.encodedProperties.Reserve(properties.Num()); + for (const auto& pair : properties) { + const FCesiumPropertyTableProperty& property = pair.Value; + + const FPropertyDescription* pExpectedProperty = + featureTableDescription.Properties.FindByPredicate( + [&key = pair.Key](const FPropertyDescription& expectedProperty) { + return key == expectedProperty.Name; + }); + + if (!pExpectedProperty) { + continue; + } + + FCesiumMetadataValueType trueType = + UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType(property); + bool isArray = trueType.bIsArray; + bool isNormalized = + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property); + + int64 componentCount; + if (isArray) { + componentCount = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property); + } else { + componentCount = 1; + } + + int32 expectedComponentCount = 1; + switch (pExpectedProperty->Type) { + // case ECesiumPropertyType::Scalar: + // expectedComponentCount = 1; + // break; + case ECesiumPropertyType_DEPRECATED::Vec2_DEPRECATED: + expectedComponentCount = 2; + break; + case ECesiumPropertyType_DEPRECATED::Vec3_DEPRECATED: + expectedComponentCount = 3; + break; + case ECesiumPropertyType_DEPRECATED::Vec4_DEPRECATED: + expectedComponentCount = 4; + }; + + if (expectedComponentCount != componentCount) { + UE_LOG( + LogCesium, + Warning, + TEXT("Unexpected component count in feature table property.")); + continue; + } + + // Coerce the true type into the expected gpu component type. + ECesiumMetadataPackedGpuType_DEPRECATED gpuType = + ECesiumMetadataPackedGpuType_DEPRECATED::None_DEPRECATED; + if (pExpectedProperty->ComponentType == + ECesiumPropertyComponentType_DEPRECATED::Uint8_DEPRECATED) { + gpuType = ECesiumMetadataPackedGpuType_DEPRECATED::Uint8_DEPRECATED; + } else /*if (expected type is float)*/ { + gpuType = ECesiumMetadataPackedGpuType_DEPRECATED::Float_DEPRECATED; + } + + if (pExpectedProperty->Normalized != isNormalized) { + if (isNormalized) { + UE_LOG( + LogCesium, + Warning, + TEXT("Unexpected normalization in feature table property.")); + } else { + UE_LOG( + LogCesium, + Warning, + TEXT("Feature table property not normalized as expected")); + } + continue; + } + + // Only support normalization of uint8 for now + if (isNormalized && + trueType.ComponentType != ECesiumMetadataComponentType::Uint8) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "Feature table property has unexpected type for normalization, only normalization of Uint8 is supported.")); + continue; + } + + EncodedPixelFormat encodedFormat = + getPixelFormat(gpuType, componentCount, isNormalized); + + if (encodedFormat.format == EPixelFormat::PF_Unknown) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "Unable to determine a suitable GPU format for this feature table property.")); + continue; + } + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodePropertyArray) + + EncodedMetadataProperty& encodedProperty = + encodedFeatureTable.encodedProperties.Emplace_GetRef(); + encodedProperty.name = + "FTB_" + featureTableDescription.Name + "_" + pair.Key; + + int64 floorSqrtFeatureCount = glm::sqrt(featureCount); + int64 ceilSqrtFeatureCount = + (floorSqrtFeatureCount * floorSqrtFeatureCount == featureCount) + ? floorSqrtFeatureCount + : (floorSqrtFeatureCount + 1); + + CesiumUtility::IntrusivePointer pImage = + new CesiumGltf::ImageAsset(); + pImage->bytesPerChannel = encodedFormat.bytesPerChannel; + pImage->channels = encodedFormat.channels; + pImage->compressedPixelFormat = CesiumGltf::GpuCompressedPixelFormat::NONE; + pImage->height = pImage->width = ceilSqrtFeatureCount; + pImage->pixelData.resize(size_t( + pImage->width * pImage->height * pImage->channels * + pImage->bytesPerChannel)); + + if (isArray) { + switch (gpuType) { + case ECesiumMetadataPackedGpuType_DEPRECATED::Uint8_DEPRECATED: { + uint8* pWritePos = reinterpret_cast(pImage->pixelData.data()); + int64_t pixelSize = + encodedFormat.channels * encodedFormat.bytesPerChannel; + for (int64 i = 0; i < featureCount; ++i) { + FCesiumPropertyArray arrayProperty = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArray( + property, + i); + for (int64 j = 0; j < componentCount; ++j) { + *(pWritePos + j) = + UCesiumPropertyArrayBlueprintLibrary::GetByte(arrayProperty, j); + } + pWritePos += pixelSize; + } + } break; + case ECesiumMetadataPackedGpuType_DEPRECATED::Float_DEPRECATED: { + uint8* pWritePos = reinterpret_cast(pImage->pixelData.data()); + int64_t pixelSize = + encodedFormat.channels * encodedFormat.bytesPerChannel; + for (int64 i = 0; i < featureCount; ++i) { + FCesiumPropertyArray arrayProperty = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArray( + property, + i); + // Floats are encoded backwards (e.g., ABGR) + float* pWritePosF = + reinterpret_cast(pWritePos + pixelSize) - 1; + for (int64 j = 0; j < componentCount; ++j) { + *pWritePosF = UCesiumPropertyArrayBlueprintLibrary::GetFloat( + arrayProperty, + j); + --pWritePosF; + } + pWritePos += pixelSize; + } + } break; + } + } else { + switch (gpuType) { + case ECesiumMetadataPackedGpuType_DEPRECATED::Uint8_DEPRECATED: { + uint8* pWritePos = reinterpret_cast(pImage->pixelData.data()); + for (int64 i = 0; i < featureCount; ++i) { + *pWritePos = UCesiumPropertyTablePropertyBlueprintLibrary::GetByte( + property, + i); + ++pWritePos; + } + } break; + case ECesiumMetadataPackedGpuType_DEPRECATED::Float_DEPRECATED: { + float* pWritePosF = reinterpret_cast(pImage->pixelData.data()); + for (int64 i = 0; i < featureCount; ++i) { + *pWritePosF = UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat( + property, + i); + ++pWritePosF; + } + } break; + } + } + + encodedProperty.pTexture = loadTextureAnyThreadPart( + *pImage, + TextureAddress::TA_Clamp, + TextureAddress::TA_Clamp, + TextureFilter::TF_Nearest, + false, + TEXTUREGROUP_8BitData, + false, + encodedFormat.format); + } + + return encodedFeatureTable; +} + +EncodedFeatureTexture encodeFeatureTextureAnyThreadPart( + TMap>& + featureTexturePropertyMap, + const FFeatureTextureDescription& featureTextureDescription, + const FString& featureTextureName, + const FCesiumPropertyTexture& featureTexture) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeFeatureTexture) + + EncodedFeatureTexture encodedFeatureTexture; + + const auto& properties = + UCesiumPropertyTextureBlueprintLibrary::GetProperties(featureTexture); + encodedFeatureTexture.properties.Reserve(properties.Num()); + + for (const auto& propertyIt : properties) { + const FFeatureTexturePropertyDescription* pPropertyDescription = + featureTextureDescription.Properties.FindByPredicate( + [propertyName = propertyIt.Key]( + const FFeatureTexturePropertyDescription& expectedProperty) { + return propertyName == expectedProperty.Name; + }); + + if (!pPropertyDescription) { + continue; + } + + const FCesiumPropertyTextureProperty& featureTextureProperty = + propertyIt.Value; + + const CesiumGltf::ImageAsset* pImage = featureTextureProperty.getImage(); + + if (!pImage) { + UE_LOG( + LogCesium, + Warning, + TEXT("This feature texture property does not have a valid image.")); + continue; + } + + int32 expectedComponentCount = 0; + switch (pPropertyDescription->Type) { + case ECesiumPropertyType_DEPRECATED::Scalar_DEPRECATED: + expectedComponentCount = 1; + break; + case ECesiumPropertyType_DEPRECATED::Vec2_DEPRECATED: + expectedComponentCount = 2; + break; + case ECesiumPropertyType_DEPRECATED::Vec3_DEPRECATED: + expectedComponentCount = 3; + break; + case ECesiumPropertyType_DEPRECATED::Vec4_DEPRECATED: + expectedComponentCount = 4; + break; + }; + + int32 actualComponentCount = 0; + FCesiumMetadataValueType valueType = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValueType( + featureTextureProperty); + switch (valueType.Type) { + case ECesiumMetadataType::Scalar: + actualComponentCount = 1; + break; + case ECesiumMetadataType::Vec2: + actualComponentCount = 2; + break; + case ECesiumMetadataType::Vec3: + actualComponentCount = 3; + break; + case ECesiumMetadataType::Vec4: + actualComponentCount = 4; + break; + } + + if (expectedComponentCount != actualComponentCount) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "This feature texture property does not have the expected component count")); + continue; + } + + bool isNormalized = + UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized( + featureTextureProperty); + if (pPropertyDescription->Normalized != isNormalized) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "This feature texture property does not have the expected normalization.")); + continue; + } + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeFeatureTextureProperty) + + EncodedFeatureTextureProperty& encodedFeatureTextureProperty = + encodedFeatureTexture.properties.Emplace_GetRef(); + + encodedFeatureTextureProperty.baseName = + "FTX_" + featureTextureName + "_" + pPropertyDescription->Name + "_"; + encodedFeatureTextureProperty.textureCoordinateAttributeId = + featureTextureProperty.getTexCoordSetIndex(); + + const auto& channels = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetChannels( + featureTextureProperty); + encodedFeatureTextureProperty.channelOffsets[0] = channels[0]; + encodedFeatureTextureProperty.channelOffsets[1] = channels[1]; + encodedFeatureTextureProperty.channelOffsets[2] = channels[2]; + encodedFeatureTextureProperty.channelOffsets[3] = channels[3]; + + TWeakPtr* pMappedUnrealImageIt = + featureTexturePropertyMap.Find(pImage); + if (pMappedUnrealImageIt) { + encodedFeatureTextureProperty.pTexture = pMappedUnrealImageIt->Pin(); + } else { + CesiumUtility::IntrusivePointer pImageCopy = + new CesiumGltf::ImageAsset(*pImage); + encodedFeatureTextureProperty.pTexture = + MakeShared(std::move(*loadTextureAnyThreadPart( + *pImageCopy, + TextureAddress::TA_Clamp, + TextureAddress::TA_Clamp, + TextureFilter::TF_Nearest, + false, + TEXTUREGROUP_8BitData, + false, + // TODO : currently the unnormalized pixels are always in unsigned + // R8G8B8A8 form, but this does not necessarily need to be the + // case in the future. + isNormalized ? EPixelFormat::PF_R8G8B8A8 + : EPixelFormat::PF_R8G8B8A8_UINT))); + featureTexturePropertyMap.Emplace( + pImage, + encodedFeatureTextureProperty.pTexture); + } + } + + return encodedFeatureTexture; +} + +EncodedMetadataPrimitive encodeMetadataPrimitiveAnyThreadPart( + const FMetadataDescription& metadataDescription, + const FCesiumMetadataPrimitive& primitive) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeMetadataPrimitive) + + EncodedMetadataPrimitive result; + + const TArray& featureIdTextures = + UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdTextures(primitive); + const TArray& featureIdAttributes = + UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdAttributes( + primitive); + + const TArray& featureTextureNames = + UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureTextureNames( + primitive); + result.featureTextureNames.Reserve(featureTextureNames.Num()); + + for (const FFeatureTextureDescription& expectedFeatureTexture : + metadataDescription.FeatureTextures) { + if (featureTextureNames.Find(expectedFeatureTexture.Name) != INDEX_NONE) { + result.featureTextureNames.Add(expectedFeatureTexture.Name); + } + } + + TMap> + featureIdTextureMap; + featureIdTextureMap.Reserve(featureIdTextures.Num()); + + result.encodedFeatureIdTextures.Reserve(featureIdTextures.Num()); + result.encodedFeatureIdAttributes.Reserve(featureIdAttributes.Num()); + + // Imposed implementation limitation: Assume only upto one feature id texture + // or attribute corresponds to each feature table. + for (const FFeatureTableDescription& expectedFeatureTable : + metadataDescription.FeatureTables) { + const FString& featureTableName = expectedFeatureTable.Name; + + if (expectedFeatureTable.AccessType == + ECesiumFeatureTableAccessType_DEPRECATED::Texture_DEPRECATED) { + + const FCesiumFeatureIdTexture* pFeatureIdTexture = + featureIdTextures.FindByPredicate([&featureTableName]( + const FCesiumFeatureIdTexture& + featureIdTexture) { + return featureTableName == + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureTableName( + featureIdTexture); + }); + + if (pFeatureIdTexture) { + const CesiumGltf::FeatureIdTextureView& featureIdTextureView = + pFeatureIdTexture->getFeatureIdTextureView(); + const CesiumGltf::ImageAsset* pFeatureIdImage = + featureIdTextureView.getImage(); + + if (!pFeatureIdImage) { + UE_LOG( + LogCesium, + Warning, + TEXT("Feature id texture missing valid image.")); + continue; + } + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeFeatureIdTexture) + + EncodedFeatureIdTexture& encodedFeatureIdTexture = + result.encodedFeatureIdTextures.Emplace_GetRef(); + + const auto channels = featureIdTextureView.getChannels(); + encodedFeatureIdTexture.baseName = "FIT_" + featureTableName + "_"; + encodedFeatureIdTexture.channel = channels.size() ? channels[0] : 0; + encodedFeatureIdTexture.textureCoordinateAttributeId = + featureIdTextureView.getTexCoordSetIndex(); + + TWeakPtr* pMappedUnrealImageIt = + featureIdTextureMap.Find(pFeatureIdImage); + if (pMappedUnrealImageIt) { + encodedFeatureIdTexture.pTexture = pMappedUnrealImageIt->Pin(); + } else { + CesiumUtility::IntrusivePointer pImageCopy = + new CesiumGltf::ImageAsset(*pFeatureIdImage); + encodedFeatureIdTexture.pTexture = MakeShared( + std::move(*loadTextureAnyThreadPart( + *pImageCopy, + TextureAddress::TA_Clamp, + TextureAddress::TA_Clamp, + TextureFilter::TF_Nearest, + false, + TEXTUREGROUP_8BitData, + false, + // TODO: currently this is always the case, but doesn't have + // to be + EPixelFormat::PF_R8G8B8A8_UINT))); + featureIdTextureMap.Emplace( + pFeatureIdImage, + encodedFeatureIdTexture.pTexture); + } + + encodedFeatureIdTexture.featureTableName = featureTableName; + } + } else if ( + expectedFeatureTable.AccessType == + ECesiumFeatureTableAccessType_DEPRECATED::Attribute_DEPRECATED) { + for (size_t i = 0; i < featureIdAttributes.Num(); ++i) { + const FCesiumFeatureIdAttribute& featureIdAttribute = + featureIdAttributes[i]; + + if (featureTableName == + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureTableName( + featureIdAttribute)) { + EncodedFeatureIdAttribute& encodedFeatureIdAttribute = + result.encodedFeatureIdAttributes.Emplace_GetRef(); + + encodedFeatureIdAttribute.name = "FA_" + featureTableName; + encodedFeatureIdAttribute.featureTableName = featureTableName; + encodedFeatureIdAttribute.index = static_cast(i); + + break; + } + } + } + } + + return result; +} + +EncodedMetadata encodeMetadataAnyThreadPart( + const FMetadataDescription& metadataDescription, + const FCesiumModelMetadata& metadata) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeMetadataModel) + + EncodedMetadata result; + + const TMap& featureTables = + UCesiumModelMetadataBlueprintLibrary::GetFeatureTables(metadata); + result.encodedFeatureTables.Reserve(featureTables.Num()); + for (const auto& featureTableIt : featureTables) { + const FString& featureTableName = featureTableIt.Key; + + const FFeatureTableDescription* pExpectedFeatureTable = + metadataDescription.FeatureTables.FindByPredicate( + [&featureTableName]( + const FFeatureTableDescription& expectedFeatureTable) { + return featureTableName == expectedFeatureTable.Name; + }); + + if (pExpectedFeatureTable) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeFeatureTable) + + result.encodedFeatureTables.Emplace( + featureTableName, + encodeMetadataFeatureTableAnyThreadPart( + *pExpectedFeatureTable, + featureTableIt.Value)); + } + } + + const TMap& featureTextures = + UCesiumModelMetadataBlueprintLibrary::GetFeatureTextures(metadata); + result.encodedFeatureTextures.Reserve(featureTextures.Num()); + TMap> + featureTexturePropertyMap; + featureTexturePropertyMap.Reserve(featureTextures.Num()); + for (const auto& featureTextureIt : featureTextures) { + const FString& featureTextureName = featureTextureIt.Key; + + const FFeatureTextureDescription* pExpectedFeatureTexture = + metadataDescription.FeatureTextures.FindByPredicate( + [&featureTextureName]( + const FFeatureTextureDescription& expectedFeatureTexture) { + return featureTextureName == expectedFeatureTexture.Name; + }); + + if (pExpectedFeatureTexture) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeFeatureTexture) + + result.encodedFeatureTextures.Emplace( + featureTextureName, + encodeFeatureTextureAnyThreadPart( + featureTexturePropertyMap, + *pExpectedFeatureTexture, + featureTextureName, + featureTextureIt.Value)); + } + } + + return result; +} + +bool encodeMetadataFeatureTableGameThreadPart( + EncodedMetadataFeatureTable& encodedFeatureTable) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeFeatureTable) + + bool success = true; + + for (EncodedMetadataProperty& encodedProperty : + encodedFeatureTable.encodedProperties) { + success &= + loadTextureGameThreadPart(encodedProperty.pTexture.Get()) != nullptr; + } + + return success; +} + +bool encodeFeatureTextureGameThreadPart( + TArray& uniqueTextures, + EncodedFeatureTexture& encodedFeatureTexture) { + bool success = true; + + for (EncodedFeatureTextureProperty& property : + encodedFeatureTexture.properties) { + if (uniqueTextures.Find(property.pTexture.Get()) == INDEX_NONE) { + success &= loadTextureGameThreadPart(property.pTexture.Get()) != nullptr; + uniqueTextures.Emplace(property.pTexture.Get()); + } + } + + return success; +} + +bool encodeMetadataPrimitiveGameThreadPart( + EncodedMetadataPrimitive& encodedPrimitive) { + bool success = true; + + TArray uniqueFeatureIdImages; + uniqueFeatureIdImages.Reserve( + encodedPrimitive.encodedFeatureIdTextures.Num()); + + for (EncodedFeatureIdTexture& encodedFeatureIdTexture : + encodedPrimitive.encodedFeatureIdTextures) { + if (uniqueFeatureIdImages.Find(encodedFeatureIdTexture.pTexture.Get()) == + INDEX_NONE) { + success &= loadTextureGameThreadPart( + encodedFeatureIdTexture.pTexture.Get()) != nullptr; + uniqueFeatureIdImages.Emplace(encodedFeatureIdTexture.pTexture.Get()); + } + } + + return success; +} + +bool encodeMetadataGameThreadPart(EncodedMetadata& encodedMetadata) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeMetadata) + + bool success = true; + + TArray uniqueTextures; + uniqueTextures.Reserve(encodedMetadata.encodedFeatureTextures.Num()); + for (auto& encodedFeatureTextureIt : encodedMetadata.encodedFeatureTextures) { + success &= encodeFeatureTextureGameThreadPart( + uniqueTextures, + encodedFeatureTextureIt.Value); + } + + for (auto& encodedFeatureTableIt : encodedMetadata.encodedFeatureTables) { + success &= + encodeMetadataFeatureTableGameThreadPart(encodedFeatureTableIt.Value); + } + + return success; +} + +void destroyEncodedMetadataPrimitive( + EncodedMetadataPrimitive& encodedPrimitive) { + for (EncodedFeatureIdTexture& encodedFeatureIdTexture : + encodedPrimitive.encodedFeatureIdTextures) { + + if (encodedFeatureIdTexture.pTexture) { + encodedFeatureIdTexture.pTexture->pTexture = nullptr; + } + } +} + +void destroyEncodedMetadata(EncodedMetadata& encodedMetadata) { + + // Destroy encoded feature tables. + for (auto& encodedFeatureTableIt : encodedMetadata.encodedFeatureTables) { + for (EncodedMetadataProperty& encodedProperty : + encodedFeatureTableIt.Value.encodedProperties) { + if (encodedProperty.pTexture) { + encodedProperty.pTexture->pTexture = nullptr; + } + } + } + + // Destroy encoded feature textures. + for (auto& encodedFeatureTextureIt : encodedMetadata.encodedFeatureTextures) { + for (EncodedFeatureTextureProperty& encodedFeatureTextureProperty : + encodedFeatureTextureIt.Value.properties) { + if (encodedFeatureTextureProperty.pTexture) { + encodedFeatureTextureProperty.pTexture->pTexture = nullptr; + } + } + } +} + +// The result should be a safe hlsl identifier, but any name clashes after +// fixing safety will not be automatically handled. +FString createHlslSafeName(const FString& rawName) { + static const FString identifierHeadChar = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; + static const FString identifierTailChar = identifierHeadChar + "0123456789"; + + FString safeName = rawName; + int32 _; + if (safeName.Len() == 0) { + return "_"; + } else { + if (!identifierHeadChar.FindChar(safeName[0], _)) { + safeName = "_" + safeName; + } + } + + for (size_t i = 1; i < safeName.Len(); ++i) { + if (!identifierTailChar.FindChar(safeName[i], _)) { + safeName[i] = '_'; + } + } + + return safeName; +} + +} // namespace CesiumEncodedMetadataUtility + +PRAGMA_ENABLE_DEPRECATION_WARNINGS diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.h new file mode 100644 index 0000000..84c4b3d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.h @@ -0,0 +1,146 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumMetadataValueType.h" +#include "CesiumTextureUtility.h" +#include "Containers/Array.h" +#include "Containers/Map.h" +#include "Containers/UnrealString.h" +#include "Templates/SharedPointer.h" +#include "Templates/UniquePtr.h" + +PRAGMA_DISABLE_DEPRECATION_WARNINGS + +struct FCesiumModelMetadata; +struct FCesiumMetadataPrimitive; +struct FCesiumPropertyTable; +struct FCesiumPropertyTexture; +struct FFeatureTableDescription; +struct FFeatureTextureDescription; +struct FMetadataDescription; +struct FCesiumPrimitiveFeaturesDescription; + +/** + * DEPRECATED. Use CesiumEncodedFeaturesMetadata instead. + */ +namespace CesiumEncodedMetadataUtility { +struct EncodedMetadataProperty { + /** + * @brief The name of this property. + */ + FString name; + + /** + * @brief The encoded property array. + */ + TUniquePtr pTexture; +}; + +struct EncodedMetadataFeatureTable { + /** + * @brief The encoded properties in this feature table. + */ + TArray encodedProperties; +}; + +struct EncodedFeatureIdTexture { + /** + * @brief The name to use for this feature id texture in the shader. + */ + FString baseName; + + /** + * @brief The encoded feature table corresponding to this feature id + * texture. + */ + FString featureTableName; + + /** + * @brief The actual feature id texture. + */ + TSharedPtr pTexture; + + /** + * @brief The channel that this feature id texture uses within the image. + */ + int32 channel; + + /** + * @brief The texture coordinate accessor index for the feature id texture. + */ + int64 textureCoordinateAttributeId; +}; + +struct EncodedFeatureIdAttribute { + FString name; + FString featureTableName; + int32 index; +}; + +struct EncodedFeatureTextureProperty { + FString baseName; + TSharedPtr pTexture; + int64 textureCoordinateAttributeId; + int32 channelOffsets[4]; +}; + +struct EncodedFeatureTexture { + TArray properties; +}; + +struct EncodedMetadataPrimitive { + TArray encodedFeatureIdTextures; + TArray encodedFeatureIdAttributes; + TArray featureTextureNames; +}; + +struct EncodedMetadata { + TMap encodedFeatureTables; + TMap encodedFeatureTextures; +}; + +EncodedMetadataFeatureTable encodeMetadataFeatureTableAnyThreadPart( + const FFeatureTableDescription& featureTableDescription, + const FCesiumPropertyTable& featureTable); + +EncodedFeatureTexture encodeFeatureTextureAnyThreadPart( + TMap< + const CesiumGltf::ImageAsset*, + TWeakPtr>& + featureTexturePropertyMap, + const FFeatureTextureDescription& featureTextureDescription, + const FString& featureTextureName, + const FCesiumPropertyTexture& featureTexture); + +EncodedMetadataPrimitive encodeMetadataPrimitiveAnyThreadPart( + const FMetadataDescription& metadataDescription, + const FCesiumMetadataPrimitive& primitive); + +EncodedMetadata encodeMetadataAnyThreadPart( + const FMetadataDescription& metadataDescription, + const FCesiumModelMetadata& metadata); + +bool encodeMetadataFeatureTableGameThreadPart( + EncodedMetadataFeatureTable& encodedFeatureTable); + +bool encodeFeatureTextureGameThreadPart( + TArray>& + uniqueTextures, + EncodedFeatureTexture& encodedFeatureTexture); + +bool encodeMetadataPrimitiveGameThreadPart( + EncodedMetadataPrimitive& encodedPrimitive); + +bool encodeMetadataGameThreadPart(EncodedMetadata& encodedMetadata); + +void destroyEncodedMetadataPrimitive( + EncodedMetadataPrimitive& encodedPrimitive); + +void destroyEncodedMetadata(EncodedMetadata& encodedMetadata); + +FString createHlslSafeName(const FString& rawName); + +} // namespace CesiumEncodedMetadataUtility + +PRAGMA_ENABLE_DEPRECATION_WARNINGS diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdAttribute.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdAttribute.cpp new file mode 100644 index 0000000..60936b3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdAttribute.cpp @@ -0,0 +1,89 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumFeatureIdAttribute.h" +#include +#include + +FCesiumFeatureIdAttribute::FCesiumFeatureIdAttribute( + const CesiumGltf::Model& Model, + const CesiumGltf::MeshPrimitive& Primitive, + const int64 FeatureIDAttribute, + const FString& PropertyTableName) + : _status(ECesiumFeatureIdAttributeStatus::ErrorInvalidAttribute), + _featureIdAccessor(), + _attributeIndex(FeatureIDAttribute), + _propertyTableName(PropertyTableName) { + const std::string attributeName = + "_FEATURE_ID_" + std::to_string(FeatureIDAttribute); + + auto featureID = Primitive.attributes.find(attributeName); + if (featureID == Primitive.attributes.end()) { + return; + } + + this->_featureIdAccessor = CesiumGltf::getFeatureIdAccessorView( + Model, + Primitive, + this->_attributeIndex); + + this->_status = std::visit( + [](auto view) { + if (view.status() != CesiumGltf::AccessorViewStatus::Valid) { + return ECesiumFeatureIdAttributeStatus::ErrorInvalidAccessor; + } + + return ECesiumFeatureIdAttributeStatus::Valid; + }, + this->_featureIdAccessor); +} + +FCesiumFeatureIdAttribute::FCesiumFeatureIdAttribute( + const CesiumGltf::Model& Model, + const CesiumGltf::Node& Node, + const int64 FeatureIDAttribute, + const FString& PropertyTableName) + : _status(ECesiumFeatureIdAttributeStatus::ErrorInvalidAttribute), + _featureIdAccessor(), + _attributeIndex(FeatureIDAttribute), + _propertyTableName(PropertyTableName) { + this->_featureIdAccessor = CesiumGltf::getFeatureIdAccessorView( + Model, + Node, + static_cast(this->_attributeIndex)); + + this->_status = std::visit( + [](auto&& view) { + if (view.status() != CesiumGltf::AccessorViewStatus::Valid) { + return ECesiumFeatureIdAttributeStatus::ErrorInvalidAccessor; + } + + return ECesiumFeatureIdAttributeStatus::Valid; + }, + this->_featureIdAccessor); +} + +const FString& UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureTableName( + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIDAttribute) { + return FeatureIDAttribute._propertyTableName; +} + +ECesiumFeatureIdAttributeStatus +UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureIDAttributeStatus( + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIDAttribute) { + return FeatureIDAttribute._status; +} + +int64 UCesiumFeatureIdAttributeBlueprintLibrary::GetCount( + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIDAttribute) { + return std::visit( + CesiumGltf::CountFromAccessor{}, + FeatureIDAttribute._featureIdAccessor); +} + +int64 UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIDAttribute, + int64 Index) { + return std::visit( + CesiumGltf::FeatureIdFromAccessor{Index}, + FeatureIDAttribute._featureIdAccessor); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdSet.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdSet.cpp new file mode 100644 index 0000000..50d475b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdSet.cpp @@ -0,0 +1,254 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumFeatureIdSet.h" +#include "CesiumGltf/Accessor.h" +#include "CesiumGltf/ExtensionExtInstanceFeaturesFeatureId.h" +#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" +#include "CesiumGltf/FeatureId.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltfPrimitiveComponent.h" + +static FCesiumFeatureIdAttribute EmptyFeatureIDAttribute; +static FCesiumFeatureIdTexture EmptyFeatureIDTexture; + +FCesiumFeatureIdSet::FCesiumFeatureIdSet( + const CesiumGltf::Model& InModel, + const CesiumGltf::MeshPrimitive& Primitive, + const CesiumGltf::FeatureId& FeatureID) + : _featureID(), + _featureIDSetType(ECesiumFeatureIdSetType::None), + _featureCount(FeatureID.featureCount), + _nullFeatureID(FeatureID.nullFeatureId.value_or(-1)), + _propertyTableIndex(FeatureID.propertyTable), + _label(FString(FeatureID.label.value_or("").c_str())) { + FString propertyTableName; + + // For backwards compatibility with GetFeatureTableName. + const CesiumGltf::ExtensionModelExtStructuralMetadata* pMetadata = + InModel.getExtension(); + if (pMetadata && _propertyTableIndex >= 0) { + size_t index = static_cast(_propertyTableIndex); + if (index < pMetadata->propertyTables.size()) { + const CesiumGltf::PropertyTable& propertyTable = + pMetadata->propertyTables[index]; + std::string name = propertyTable.name.value_or(""); + propertyTableName = FString(name.c_str()); + } + } + + if (FeatureID.attribute) { + _featureID = FCesiumFeatureIdAttribute( + InModel, + Primitive, + *FeatureID.attribute, + propertyTableName); + _featureIDSetType = ECesiumFeatureIdSetType::Attribute; + + return; + } + + if (FeatureID.texture) { + _featureID = FCesiumFeatureIdTexture( + InModel, + Primitive, + *FeatureID.texture, + propertyTableName); + _featureIDSetType = ECesiumFeatureIdSetType::Texture; + + return; + } + + if (_featureCount > 0) { + _featureIDSetType = ECesiumFeatureIdSetType::Implicit; + } +} + +FCesiumFeatureIdSet::FCesiumFeatureIdSet( + const CesiumGltf::Model& InModel, + const CesiumGltf::Node& Node, + const CesiumGltf::ExtensionExtInstanceFeaturesFeatureId& InstanceFeatureID) + : _featureID(), + _featureIDSetType(ECesiumFeatureIdSetType::Instance), + _featureCount(InstanceFeatureID.featureCount), + _nullFeatureID(InstanceFeatureID.nullFeatureId.value_or(-1)), + _propertyTableIndex(InstanceFeatureID.propertyTable.value_or(-1)), + _label(FString(InstanceFeatureID.label.value_or("").c_str())) { + FString propertyTableName; + + // For backwards compatibility with GetFeatureTableName. + const CesiumGltf::ExtensionModelExtStructuralMetadata* pMetadata = + InModel.getExtension(); + if (pMetadata && this->_propertyTableIndex >= 0) { + size_t index = static_cast(_propertyTableIndex); + if (index < pMetadata->propertyTables.size()) { + const CesiumGltf::PropertyTable& propertyTable = + pMetadata->propertyTables[index]; + std::string name = propertyTable.name.value_or(""); + propertyTableName = FString(name.c_str()); + } + } + + if (InstanceFeatureID.attribute) { + _featureID = FCesiumFeatureIdAttribute( + InModel, + Node, + *InstanceFeatureID.attribute, + propertyTableName); + } else if (_featureCount > 0) { + _featureIDSetType = ECesiumFeatureIdSetType::InstanceImplicit; + } +} + +const ECesiumFeatureIdSetType +UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) { + return FeatureIDSet._featureIDSetType; +} + +const FCesiumFeatureIdAttribute& +UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) { + if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Attribute || + FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Instance) { + return std::get(FeatureIDSet._featureID); + } + + return EmptyFeatureIDAttribute; +} + +const FCesiumFeatureIdTexture& +UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDTexture( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) { + if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Texture) { + return std::get(FeatureIDSet._featureID); + } + + return EmptyFeatureIDTexture; +} + +const int64 UCesiumFeatureIdSetBlueprintLibrary::GetPropertyTableIndex( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) { + return FeatureIDSet._propertyTableIndex; +} + +int64 UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) { + return FeatureIDSet._featureCount; +} + +const int64 UCesiumFeatureIdSetBlueprintLibrary::GetNullFeatureID( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) { + return FeatureIDSet._nullFeatureID; +} + +const FString UCesiumFeatureIdSetBlueprintLibrary::GetLabel( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) { + return FeatureIDSet._label; +} + +int64 UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForVertex( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet, + int64 VertexIndex) { + if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Attribute) { + FCesiumFeatureIdAttribute attribute = + std::get(FeatureIDSet._featureID); + return UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + attribute, + VertexIndex); + } + + if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Texture) { + FCesiumFeatureIdTexture texture = + std::get(FeatureIDSet._featureID); + return UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex( + texture, + VertexIndex); + } + + if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Implicit) { + return (VertexIndex >= 0 && VertexIndex < FeatureIDSet._featureCount) + ? VertexIndex + : -1; + } + + return -1; +} + +int64 UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForInstance( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet, + int64 InstanceIndex) { + ECesiumFeatureIdSetType type = FeatureIDSet._featureIDSetType; + if (type == ECesiumFeatureIdSetType::InstanceImplicit) { + return InstanceIndex; + } else if ( + type != ECesiumFeatureIdSetType::Instance || + !std::holds_alternative( + FeatureIDSet._featureID) || + InstanceIndex < 0) { + return -1; + } + const auto& featureIdAttribute = + std::get(FeatureIDSet._featureID); + return UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + featureIdAttribute, + InstanceIndex); +} + +int64 UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDFromHit( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet, + const FHitResult& Hit) { + // FeatureIDs from instanced geometry take precedence. + const auto* pInstancedComponent = + Cast(Hit.Component); + if (IsValid(pInstancedComponent)) { + const FCesiumPrimitiveFeatures& instanceFeatures = + *pInstancedComponent->pInstanceFeatures; + return UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromInstance( + instanceFeatures, + Hit.Item); + } + + if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Texture) { + FCesiumFeatureIdTexture texture = + std::get(FeatureIDSet._featureID); + return UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit( + texture, + Hit); + } + + // Find the first vertex of the face. + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast(Hit.Component); + if (!IsValid(pGltfComponent)) { + return -1; + } + + const CesiumPrimitiveData& primData = pGltfComponent->getPrimitiveData(); + if (!primData.pMeshPrimitive) { + return -1; + } + auto VertexIndices = std::visit( + CesiumGltf::IndicesForFaceFromAccessor{ + Hit.FaceIndex, + primData.PositionAccessor.size(), + primData.pMeshPrimitive->mode}, + primData.IndexAccessor); + + int64 VertexIndex = VertexIndices[0]; + + if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Attribute) { + FCesiumFeatureIdAttribute attribute = + std::get(FeatureIDSet._featureID); + return UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + attribute, + VertexIndex); + } + + if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Implicit) { + return (VertexIndex >= 0 && VertexIndex < FeatureIDSet._featureCount) + ? VertexIndex + : -1; + } + + return -1; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdTexture.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdTexture.cpp new file mode 100644 index 0000000..8ee2edb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdTexture.cpp @@ -0,0 +1,137 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumFeatureIdTexture.h" +#include "CesiumGltf/FeatureIdTexture.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumMetadataPickingBlueprintLibrary.h" + +#include + +FCesiumFeatureIdTexture::FCesiumFeatureIdTexture( + const CesiumGltf::Model& Model, + const CesiumGltf::MeshPrimitive& Primitive, + const CesiumGltf::FeatureIdTexture& FeatureIdTexture, + const FString& PropertyTableName) + : _status(ECesiumFeatureIdTextureStatus::ErrorInvalidTexture), + _featureIdTextureView(), + _texCoordAccessor(), + _textureCoordinateSetIndex(FeatureIdTexture.texCoord), + _propertyTableName(PropertyTableName) { + CesiumGltf::TextureViewOptions options; + options.applyKhrTextureTransformExtension = true; + + if (FeatureIdTexture.extras.find("makeImageCopy") != + FeatureIdTexture.extras.end()) { + options.makeImageCopy = + FeatureIdTexture.extras.at("makeImageCopy").getBoolOrDefault(false); + } + + this->_featureIdTextureView = + CesiumGltf::FeatureIdTextureView(Model, FeatureIdTexture, options); + + switch (_featureIdTextureView.status()) { + case CesiumGltf::FeatureIdTextureViewStatus::Valid: + this->_status = ECesiumFeatureIdTextureStatus::Valid; + break; + case CesiumGltf::FeatureIdTextureViewStatus::ErrorInvalidChannels: + this->_status = ECesiumFeatureIdTextureStatus::ErrorInvalidTextureAccess; + return; + default: + // Error with the texture or image. The status is already set by the + // initializer list. + return; + } + + // The EXT_feature_metadata version of FCesiumFeatureIdTexture was not + // constructed with an "owner" primitive. It was possible to access the + // texture data with technically arbitrary coordinates. + // + // To maintain this functionality in EXT_mesh_features, the texture view will + // still be valid if the intended texcoords don't exist. However, feature IDs + // won't be retrievable by vertex index. + this->_texCoordAccessor = CesiumGltf::getTexCoordAccessorView( + Model, + Primitive, + this->_textureCoordinateSetIndex); +} + +const FString& UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureTableName( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture) { + return FeatureIDTexture._propertyTableName; +} + +ECesiumFeatureIdTextureStatus +UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture) { + return FeatureIDTexture._status; +} + +int64 UCesiumFeatureIdTextureBlueprintLibrary::GetGltfTextureCoordinateSetIndex( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture) { + return FeatureIDTexture._featureIdTextureView.getTexCoordSetIndex(); +} + +int64 UCesiumFeatureIdTextureBlueprintLibrary::GetUnrealUVChannel( + const UPrimitiveComponent* PrimitiveComponent, + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture) { + const auto* pCesiumPrimitive = Cast(PrimitiveComponent); + if (!pCesiumPrimitive || + FeatureIDTexture._status != ECesiumFeatureIdTextureStatus::Valid) { + return -1; + } + const CesiumPrimitiveData& primData = pCesiumPrimitive->getPrimitiveData(); + auto textureCoordinateIndexIt = primData.GltfToUnrealTexCoordMap.find( + UCesiumFeatureIdTextureBlueprintLibrary::GetGltfTextureCoordinateSetIndex( + FeatureIDTexture)); + if (textureCoordinateIndexIt == primData.GltfToUnrealTexCoordMap.end()) { + return -1; + } + + return textureCoordinateIndexIt->second; +} + +PRAGMA_DISABLE_DEPRECATION_WARNINGS +int64 UCesiumFeatureIdTextureBlueprintLibrary:: + GetFeatureIDForTextureCoordinates( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture, + float U, + float V) { + return FeatureIDTexture._featureIdTextureView.getFeatureID(U, V); +} +PRAGMA_ENABLE_DEPRECATION_WARNINGS + +int64 UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForUV( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture, + const FVector2D& UV) { + return FeatureIDTexture._featureIdTextureView.getFeatureID(UV[0], UV[1]); +} + +int64 UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture, + int64 VertexIndex) { + const std::optional texCoords = std::visit( + CesiumGltf::TexCoordFromAccessor{VertexIndex}, + FeatureIDTexture._texCoordAccessor); + if (!texCoords) { + return -1; + } + + return FeatureIDTexture._featureIdTextureView.getFeatureID( + (*texCoords)[0], + (*texCoords)[1]); +} + +int64 UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture, + const FHitResult& Hit) { + FVector2D UV; + if (UCesiumMetadataPickingBlueprintLibrary::FindUVFromHit( + Hit, + FeatureIDTexture._featureIdTextureView.getTexCoordSetIndex(), + UV)) { + return FeatureIDTexture._featureIdTextureView.getFeatureID(UV[0], UV[1]); + } + + return -1; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeaturesMetadataComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeaturesMetadataComponent.cpp new file mode 100644 index 0000000..ac2d9bc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeaturesMetadataComponent.cpp @@ -0,0 +1,2755 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumFeaturesMetadataComponent.h" +#include "Cesium3DTileset.h" +#include "CesiumEncodedFeaturesMetadata.h" +#include "CesiumEncodedMetadataConversions.h" +#include "CesiumGltfComponent.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumModelMetadata.h" +#include "CesiumRuntime.h" +#include "UnrealMetadataConversions.h" + +#if WITH_EDITOR +#include "AssetRegistry/AssetData.h" +#include "AssetRegistry/AssetRegistryModule.h" +#include "ComponentReregisterContext.h" +#include "Containers/Map.h" +#include "ContentBrowserModule.h" +#include "Factories/MaterialFunctionMaterialLayerFactory.h" +#include "IContentBrowserSingleton.h" +#include "IMaterialEditor.h" +#include "Materials/Material.h" +#include "Materials/MaterialExpressionAppendVector.h" +#include "Materials/MaterialExpressionCustom.h" +#include "Materials/MaterialExpressionFunctionInput.h" +#include "Materials/MaterialExpressionFunctionOutput.h" +#include "Materials/MaterialExpressionIf.h" +#include "Materials/MaterialExpressionMaterialFunctionCall.h" +#include "Materials/MaterialExpressionPerInstanceCustomData.h" +#include "Materials/MaterialExpressionRound.h" +#include "Materials/MaterialExpressionScalarParameter.h" +#include "Materials/MaterialExpressionSetMaterialAttributes.h" +#include "Materials/MaterialExpressionTextureCoordinate.h" +#include "Materials/MaterialExpressionTextureObjectParameter.h" +#include "Materials/MaterialExpressionTextureProperty.h" +#include "Materials/MaterialExpressionVectorParameter.h" +#include "Misc/PackageName.h" +#include "Modules/ModuleManager.h" +#include "Subsystems/AssetEditorSubsystem.h" +#include "UObject/Package.h" + +extern UNREALED_API class UEditorEngine* GEditor; + +using namespace CesiumEncodedFeaturesMetadata; + +static const FString AutogeneratedMessage = "AUTOGENERATED DO NOT EDIT"; + +namespace { +void AutoFillPropertyTableDescriptions( + TArray& Descriptions, + const FCesiumModelMetadata& ModelMetadata) { + const TArray& propertyTables = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTables(ModelMetadata); + + for (const auto& propertyTable : propertyTables) { + FString propertyTableName = getNameForPropertyTable(propertyTable); + + FCesiumPropertyTableDescription* pDescription = + Descriptions.FindByPredicate( + [&name = propertyTableName]( + const FCesiumPropertyTableDescription& existingPropertyTable) { + return existingPropertyTable.Name == name; + }); + + if (!pDescription) { + pDescription = &Descriptions.Emplace_GetRef(); + pDescription->Name = propertyTableName; + } + + const TMap& properties = + UCesiumPropertyTableBlueprintLibrary::GetProperties(propertyTable); + for (const auto& propertyIt : properties) { + auto pExistingProperty = pDescription->Properties.FindByPredicate( + [&propertyName = propertyIt.Key]( + const FCesiumPropertyTablePropertyDescription& existingProperty) { + return existingProperty.Name == propertyName; + }); + + if (pExistingProperty) { + // We have already accounted for this property, but we may need to check + // for its offset / scale, since they can differ from the class + // property's definition. + ECesiumMetadataType type = pExistingProperty->PropertyDetails.Type; + switch (type) { + case ECesiumMetadataType::Scalar: + case ECesiumMetadataType::Vec2: + case ECesiumMetadataType::Vec3: + case ECesiumMetadataType::Vec4: + case ECesiumMetadataType::Mat2: + case ECesiumMetadataType::Mat3: + case ECesiumMetadataType::Mat4: + break; + default: + continue; + } + + FCesiumMetadataValue offset = + UCesiumPropertyTablePropertyBlueprintLibrary::GetOffset( + propertyIt.Value); + pExistingProperty->PropertyDetails.bHasOffset |= + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(offset); + + FCesiumMetadataValue scale = + UCesiumPropertyTablePropertyBlueprintLibrary::GetOffset( + propertyIt.Value); + pExistingProperty->PropertyDetails.bHasScale |= + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(scale); + + continue; + } + + FCesiumPropertyTablePropertyDescription& property = + pDescription->Properties.Emplace_GetRef(); + property.Name = propertyIt.Key; + + const FCesiumMetadataValueType ValueType = + UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType( + propertyIt.Value); + property.PropertyDetails.SetValueType(ValueType); + property.PropertyDetails.ArraySize = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize( + propertyIt.Value); + property.PropertyDetails.bIsNormalized = + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized( + propertyIt.Value); + + FCesiumMetadataValue offset = + UCesiumPropertyTablePropertyBlueprintLibrary::GetOffset( + propertyIt.Value); + property.PropertyDetails.bHasOffset = + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(offset); + + FCesiumMetadataValue scale = + UCesiumPropertyTablePropertyBlueprintLibrary::GetOffset( + propertyIt.Value); + property.PropertyDetails.bHasScale = + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(scale); + + FCesiumMetadataValue noData = + UCesiumPropertyTablePropertyBlueprintLibrary::GetNoDataValue( + propertyIt.Value); + property.PropertyDetails.bHasNoDataValue = + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(noData); + + FCesiumMetadataValue defaultValue = + UCesiumPropertyTablePropertyBlueprintLibrary::GetDefaultValue( + propertyIt.Value); + property.PropertyDetails.bHasDefaultValue = + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(defaultValue); + + property.EncodingDetails = CesiumMetadataPropertyDetailsToEncodingDetails( + property.PropertyDetails); + } + } +} + +void AutoFillPropertyTextureDescriptions( + TArray& Descriptions, + const FCesiumModelMetadata& ModelMetadata) { + const TArray& propertyTextures = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTextures(ModelMetadata); + + for (const auto& propertyTexture : propertyTextures) { + FString propertyTextureName = getNameForPropertyTexture(propertyTexture); + FCesiumPropertyTextureDescription* pDescription = + Descriptions.FindByPredicate( + [&propertyTextureName = + propertyTextureName](const FCesiumPropertyTextureDescription& + existingPropertyTexture) { + return existingPropertyTexture.Name == propertyTextureName; + }); + + if (!pDescription) { + pDescription = &Descriptions.Emplace_GetRef(); + pDescription->Name = propertyTextureName; + } + + const TMap& properties = + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture); + for (const auto& propertyIt : properties) { + auto pExistingProperty = pDescription->Properties.FindByPredicate( + [&propertyName = + propertyIt.Key](const FCesiumPropertyTexturePropertyDescription& + existingProperty) { + return propertyName == existingProperty.Name; + }); + + if (pExistingProperty) { + // We have already accounted for this property, but we may need to check + // for its offset / scale, since they can differ from the class + // property's definition. + ECesiumMetadataType type = pExistingProperty->PropertyDetails.Type; + switch (type) { + case ECesiumMetadataType::Scalar: + case ECesiumMetadataType::Vec2: + case ECesiumMetadataType::Vec3: + case ECesiumMetadataType::Vec4: + case ECesiumMetadataType::Mat2: + case ECesiumMetadataType::Mat3: + case ECesiumMetadataType::Mat4: + break; + default: + continue; + } + + FCesiumMetadataValue offset = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetOffset( + propertyIt.Value); + pExistingProperty->PropertyDetails.bHasOffset |= + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(offset); + + FCesiumMetadataValue scale = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetOffset( + propertyIt.Value); + pExistingProperty->PropertyDetails.bHasScale |= + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(scale); + + continue; + } + + FCesiumPropertyTexturePropertyDescription& property = + pDescription->Properties.Emplace_GetRef(); + property.Name = propertyIt.Key; + + const FCesiumMetadataValueType ValueType = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValueType( + propertyIt.Value); + property.PropertyDetails.SetValueType(ValueType); + property.PropertyDetails.ArraySize = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( + propertyIt.Value); + property.PropertyDetails.bIsNormalized = + UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized( + propertyIt.Value); + + FCesiumMetadataValue offset = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetOffset( + propertyIt.Value); + property.PropertyDetails.bHasOffset = + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(offset); + + FCesiumMetadataValue scale = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetOffset( + propertyIt.Value); + property.PropertyDetails.bHasScale = + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(scale); + + FCesiumMetadataValue noData = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetNoDataValue( + propertyIt.Value); + property.PropertyDetails.bHasNoDataValue = + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(noData); + + FCesiumMetadataValue defaultValue = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetDefaultValue( + propertyIt.Value); + property.PropertyDetails.bHasDefaultValue = + !UCesiumMetadataValueBlueprintLibrary::IsEmpty(defaultValue); + + auto maybeTextureTransform = propertyIt.Value.getTextureTransform(); + if (maybeTextureTransform) { + property.bHasKhrTextureTransform = + (maybeTextureTransform->status() == + CesiumGltf::KhrTextureTransformStatus::Valid); + } + } + } +} + +void AutoFillFeatureIdSetDescriptions( + TArray& Descriptions, + const FCesiumPrimitiveFeatures& Features, + const FCesiumPrimitiveFeatures* InstanceFeatures, + const TArray& PropertyTables) { + TArray featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets(Features); + if (InstanceFeatures) { + featureIDSets.Append( + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets( + *InstanceFeatures)); + } + int32 featureIDTextureCounter = 0; + + for (const FCesiumFeatureIdSet& featureIDSet : featureIDSets) { + ECesiumFeatureIdSetType type = + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType(featureIDSet); + int64 count = + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(featureIDSet); + if (type == ECesiumFeatureIdSetType::None || count == 0) { + // Empty or invalid feature ID set. Skip. + continue; + } + + FString featureIDSetName = + getNameForFeatureIDSet(featureIDSet, featureIDTextureCounter); + FCesiumFeatureIdSetDescription* pDescription = Descriptions.FindByPredicate( + [&name = featureIDSetName]( + const FCesiumFeatureIdSetDescription& existingFeatureIDSet) { + return existingFeatureIDSet.Name == name; + }); + + if (pDescription) { + // We have already accounted for a feature ID set of this name; skip. + continue; + } + + pDescription = &Descriptions.Emplace_GetRef(); + pDescription->Name = featureIDSetName; + pDescription->Type = type; + + const int64 propertyTableIndex = + UCesiumFeatureIdSetBlueprintLibrary::GetPropertyTableIndex( + featureIDSet); + if (propertyTableIndex >= 0 && propertyTableIndex < PropertyTables.Num()) { + const FCesiumPropertyTable& propertyTable = + PropertyTables[propertyTableIndex]; + pDescription->PropertyTableName = getNameForPropertyTable(propertyTable); + } + + pDescription->bHasNullFeatureId = + UCesiumFeatureIdSetBlueprintLibrary::GetNullFeatureID(featureIDSet) > + -1; + + if (type == ECesiumFeatureIdSetType::Texture) { + FCesiumFeatureIdTexture featureIdTexture = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDTexture( + featureIDSet); + auto maybeTextureTransform = + featureIdTexture.getFeatureIdTextureView().getTextureTransform(); + if (maybeTextureTransform) { + pDescription->bHasKhrTextureTransform = + (maybeTextureTransform->status() == + CesiumGltf::KhrTextureTransformStatus::Valid); + } + } + } +} + +void AutoFillPropertyTextureNames( + TSet& Names, + const FCesiumPrimitiveMetadata& PrimitiveMetadata, + const TArray& PropertyTextures) { + const TArray propertyTextureIndices = + UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyTextureIndices( + PrimitiveMetadata); + + for (const int64& propertyTextureIndex : propertyTextureIndices) { + if (propertyTextureIndex < 0 || + propertyTextureIndex >= PropertyTextures.Num()) { + continue; + } + + const FCesiumPropertyTexture& propertyTexture = + PropertyTextures[propertyTextureIndex]; + FString propertyTextureName = getNameForPropertyTexture(propertyTexture); + Names.Emplace(propertyTextureName); + } +} + +} // namespace + +void UCesiumFeaturesMetadataComponent::AutoFill() { + const ACesium3DTileset* pOwner = this->GetOwner(); + if (!pOwner) { + return; + } + + Super::PreEditChange(NULL); + + // This assumes that the property tables are the same across all models in the + // tileset, and that they all have the same schema. + for (const UActorComponent* pComponent : pOwner->GetComponents()) { + const UCesiumGltfComponent* pGltf = Cast(pComponent); + if (!pGltf) { + continue; + } + + const FCesiumModelMetadata& modelMetadata = pGltf->Metadata; + AutoFillPropertyTableDescriptions(this->PropertyTables, modelMetadata); + AutoFillPropertyTextureDescriptions(this->PropertyTextures, modelMetadata); + + TArray childComponents; + pGltf->GetChildrenComponents(false, childComponents); + + for (const USceneComponent* pChildComponent : childComponents) { + const auto* pCesiumPrimitive = Cast(pChildComponent); + if (!pCesiumPrimitive) { + continue; + } + const CesiumPrimitiveData& primData = + pCesiumPrimitive->getPrimitiveData(); + const FCesiumPrimitiveFeatures& primitiveFeatures = primData.Features; + const TArray& propertyTables = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTables( + modelMetadata); + const FCesiumPrimitiveFeatures* pInstanceFeatures = nullptr; + const auto* pInstancedComponent = + Cast(pChildComponent); + if (pInstancedComponent) { + pInstanceFeatures = pInstancedComponent->pInstanceFeatures.Get(); + } + AutoFillFeatureIdSetDescriptions( + this->FeatureIdSets, + primitiveFeatures, + pInstanceFeatures, + propertyTables); + + const FCesiumPrimitiveMetadata& primitiveMetadata = primData.Metadata; + const TArray& propertyTextures = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTextures( + modelMetadata); + AutoFillPropertyTextureNames( + this->PropertyTextureNames, + primitiveMetadata, + propertyTextures); + } + } + + Super::PostEditChange(); +} + +template +static FORCEINLINE ObjClass* LoadObjFromPath(const FName& Path) { + if (Path == NAME_None) + return nullptr; + + return Cast( + StaticLoadObject(ObjClass::StaticClass(), nullptr, *Path.ToString())); +} + +static FORCEINLINE UMaterialFunction* LoadMaterialFunction(const FName& Path) { + if (Path == NAME_None) + return nullptr; + + return LoadObjFromPath(Path); +} + +static const FString GetPropertyValuesPrefix = "Get Property Values From "; +static const FString ApplyValueTransformsPrefix = "Apply Value Transforms To "; + +namespace { +struct MaterialNodeClassification { + TArray AutoGeneratedNodes; + TArray GetFeatureIdNodes; + TArray GetPropertyValueNodes; + TArray ApplyValueTransformNodes; + TArray IfNodes; + TArray UserAddedNodes; +}; + +struct MaterialFunctionLibrary { + UMaterialFunction* SelectTexCoords = nullptr; + UMaterialFunction* TransformTexCoords = nullptr; + UMaterialFunction* GetFeatureIdsFromAttribute = nullptr; + UMaterialFunction* GetFeatureIdsFromTexture = nullptr; + UMaterialFunction* GetFeatureIdsFromInstance = nullptr; + + MaterialFunctionLibrary() + : SelectTexCoords(LoadMaterialFunction( + "/CesiumForUnreal/Materials/MaterialFunctions/CesiumSelectTexCoords.CesiumSelectTexCoords")), + TransformTexCoords(LoadMaterialFunction( + "/CesiumForUnreal/Materials/MaterialFunctions/MF_CesiumTransformTextureCoordinates.MF_CesiumTransformTextureCoordinates")), + GetFeatureIdsFromAttribute(LoadMaterialFunction( + "/CesiumForUnreal/Materials/MaterialFunctions/CesiumGetFeatureIdsFromAttribute.CesiumGetFeatureIdsFromAttribute")), + GetFeatureIdsFromTexture(LoadMaterialFunction( + "/CesiumForUnreal/Materials/MaterialFunctions/CesiumGetFeatureIdsFromTexture.CesiumGetFeatureIdsFromTexture")), + GetFeatureIdsFromInstance(LoadMaterialFunction( + "/CesiumForUnreal/Materials/MaterialFunctions/CesiumGetFeatureIdsFromInstance.CesiumGetFeatureIdsFromInstance")) { + } + + bool isValid() { + return SelectTexCoords != nullptr && + GetFeatureIdsFromAttribute != nullptr && + GetFeatureIdsFromTexture != nullptr && + GetFeatureIdsFromInstance != nullptr; + } +}; +} // namespace + +// Separate nodes into auto-generated and user-added. Collect the property +// result nodes. +static void ClassifyNodes( + UMaterialFunctionMaterialLayer* Layer, + MaterialNodeClassification& Classification, + const MaterialFunctionLibrary& FunctionLibrary) { + const UMaterialFunction* GetFeatureIdsFromAttributeFunction = + FunctionLibrary.GetFeatureIdsFromAttribute; + const UMaterialFunction* GetFeatureIdsFromTextureFunction = + FunctionLibrary.GetFeatureIdsFromTexture; + const UMaterialFunction* GetFeatureIdsFromInstanceFunction = + FunctionLibrary.GetFeatureIdsFromInstance; + for (const TObjectPtr& Node : + Layer->GetExpressionCollection().Expressions) { + // Check if this node is marked as autogenerated. + if (Node->Desc.StartsWith( + AutogeneratedMessage, + ESearchCase::Type::CaseSensitive)) { + Classification.AutoGeneratedNodes.Add(Node); + + UMaterialExpressionCustom* CustomNode = + Cast(Node); + if (CustomNode && + CustomNode->Description.Contains(GetPropertyValuesPrefix)) { + Classification.GetPropertyValueNodes.Add(CustomNode); + continue; + } + + if (CustomNode && + CustomNode->Description.Contains(ApplyValueTransformsPrefix)) { + Classification.ApplyValueTransformNodes.Add(CustomNode); + continue; + } + + // If nodes are added in when feature ID sets specify a null feature ID + // value, when properties specify a "no data" value, and when properties + // specify a default value. + UMaterialExpressionIf* IfNode = Cast(Node); + if (IfNode) { + Classification.IfNodes.Add(IfNode); + continue; + } + + UMaterialExpressionMaterialFunctionCall* FunctionCallNode = + Cast(Node); + if (!FunctionCallNode) + continue; + + const FName& name = FunctionCallNode->MaterialFunction->GetFName(); + if (name == GetFeatureIdsFromAttributeFunction->GetFName() || + name == GetFeatureIdsFromTextureFunction->GetFName() || + name == GetFeatureIdsFromInstanceFunction->GetFName()) { + Classification.GetFeatureIdNodes.Add(FunctionCallNode); + } + } else { + Classification.UserAddedNodes.Add(Node); + } + } +} + +static void ClearAutoGeneratedNodes( + UMaterialFunctionMaterialLayer* Layer, + TMap>& ConnectionInputRemap, + TMap>& ConnectionOutputRemap, + const MaterialFunctionLibrary& FunctionLibrary) { + + MaterialNodeClassification Classification; + ClassifyNodes(Layer, Classification, FunctionLibrary); + + // Determine which user-added connections to remap when regenerating the + // feature ID retrieval nodes. + for (const UMaterialExpressionMaterialFunctionCall* GetFeatureIdNode : + Classification.GetFeatureIdNodes) { + if (!GetFeatureIdNode->Outputs.Num()) { + continue; + } + + const auto Inputs = GetFeatureIdNode->FunctionInputs; + + if (!Inputs.Num()) { + // Should not happen, but just in case, this node would be invalid. Break + // any user-made connections to this node and don't attempt to remap it. + for (UMaterialExpression* UserNode : Classification.UserAddedNodes) { + for (FExpressionInput* Input : UserNode->GetInputsView()) { + if (Input->Expression == GetFeatureIdNode && + Input->OutputIndex == 0) { + Input->Expression = nullptr; + } + } + } + continue; + } + + // It's not as easy to distinguish the material function calls from each + // other. Try using the name of the first valid input (the texture + // coordinate index name), which should be different for each feature ID + // set. + const auto Parameter = + Cast(Inputs[0].Input.Expression); + FString ParameterName; + if (Parameter) { + ParameterName = Parameter->ParameterName.ToString(); + } + + if (ParameterName.IsEmpty()) { + // In case, treat the node as invalid. Break any user-made connections to + // this node and don't attempt to remap it. + for (UMaterialExpression* UserNode : Classification.UserAddedNodes) { + for (FExpressionInput* Input : UserNode->GetInputsView()) { + if (Input->Expression == GetFeatureIdNode && + Input->OutputIndex == 0) { + Input->Expression = nullptr; + } + } + } + continue; + } + + FString Key = GetFeatureIdNode->GetDescription() + ParameterName; + TArray Connections; + for (UMaterialExpression* UserNode : Classification.UserAddedNodes) { + for (FExpressionInput* Input : UserNode->GetInputsView()) { + // Look for user-made connections to this node. + if (Input->Expression == GetFeatureIdNode && Input->OutputIndex == 0) { + Connections.Add(Input); + Input->Expression = nullptr; + } + } + } + ConnectionOutputRemap.Emplace(MoveTemp(Key), MoveTemp(Connections)); + } + + // Determine which user-added connections to remap when regenerating the + // property value retrieval nodes. + for (const UMaterialExpressionCustom* GetPropertyValueNode : + Classification.GetPropertyValueNodes) { + int32 OutputIndex = 0; + for (const FExpressionOutput& PropertyOutput : + GetPropertyValueNode->Outputs) { + FString Key = GetPropertyValueNode->GetDescription() + + PropertyOutput.OutputName.ToString(); + + // Look for user-made connections to this property. + TArray Connections; + for (UMaterialExpression* UserNode : Classification.UserAddedNodes) { + for (FExpressionInput* Input : UserNode->GetInputsView()) { + if (Input->Expression == GetPropertyValueNode && + Input->OutputIndex == OutputIndex) { + Connections.Add(Input); + Input->Expression = nullptr; + } + } + } + + ConnectionOutputRemap.Emplace(MoveTemp(Key), MoveTemp(Connections)); + ++OutputIndex; + } + } + + // Determine which user-added connections to remap when regenerating the + // value transform nodes. + for (const UMaterialExpressionCustom* ApplyValueTransformNode : + Classification.ApplyValueTransformNodes) { + int32 OutputIndex = 0; + for (const FExpressionOutput& PropertyOutput : + ApplyValueTransformNode->Outputs) { + FString Key = ApplyValueTransformNode->GetDescription() + + PropertyOutput.OutputName.ToString(); + + // Look for user-made connections to this property. + TArray Connections; + for (UMaterialExpression* UserNode : Classification.UserAddedNodes) { + for (FExpressionInput* Input : UserNode->GetInputsView()) { + if (Input->Expression == ApplyValueTransformNode && + Input->OutputIndex == OutputIndex) { + Connections.Add(Input); + Input->Expression = nullptr; + } + } + } + + ConnectionOutputRemap.Emplace(MoveTemp(Key), MoveTemp(Connections)); + ++OutputIndex; + } + } + + // Determine which user-added connections to remap when regenerating the if + // statements for null feature IDs. + for (const UMaterialExpressionIf* IfNode : Classification.IfNodes) { + // Distinguish the if statements from each other using A and B. If both of + // these nodes have been disconnected, then treat this node as invalid. + FString IfNodeName; + + UMaterialExpressionParameter* Parameter = + Cast(IfNode->A.Expression); + if (Parameter) { + IfNodeName += Parameter->GetParameterName().ToString(); + } else if (IfNode->A.Expression) { + TArray& Outputs = IfNode->A.Expression->GetOutputs(); + if (Outputs.Num() > 0) { + IfNodeName += Outputs[IfNode->A.OutputIndex].OutputName.ToString(); + } + } + + Parameter = Cast(IfNode->B.Expression); + if (Parameter) { + IfNodeName += Parameter->GetParameterName().ToString(); + } else if (IfNode->B.Expression) { + TArray& Outputs = IfNode->B.Expression->GetOutputs(); + if (Outputs.Num() > 0) { + IfNodeName += Outputs[IfNode->B.OutputIndex].OutputName.ToString(); + } + } + + if (IfNodeName.IsEmpty()) { + // In case, treat the node as invalid. Break any user-made connections to + // this node and don't attempt to remap it. + for (UMaterialExpression* UserNode : Classification.UserAddedNodes) { + for (FExpressionInput* Input : UserNode->GetInputsView()) { + if (Input->Expression == IfNode && Input->OutputIndex == 0) { + Input->Expression = nullptr; + } + } + } + continue; + } + + FString Key = IfNode->GetDescription() + IfNodeName; + TArray Connections; + for (UMaterialExpression* UserNode : Classification.UserAddedNodes) { + for (FExpressionInput* Input : UserNode->GetInputsView()) { + // Look for user-made connections to this node. + if (Input->Expression == IfNode && Input->OutputIndex == 0) { + Connections.Add(Input); + Input->Expression = nullptr; + } + } + } + ConnectionOutputRemap.Emplace(Key, MoveTemp(Connections)); + + // Also save any user inputs to the if statement. Be sure to ignore + // connections to autogenerated nodes. + TMap InputConnections; + if (IfNode->AGreaterThanB.Expression && + !IfNode->AGreaterThanB.Expression->Desc.StartsWith( + AutogeneratedMessage, + ESearchCase::Type::CaseSensitive)) { + InputConnections.Emplace(TEXT("AGreaterThanB"), &IfNode->AGreaterThanB); + } + + if (IfNode->ALessThanB.Expression && + !IfNode->ALessThanB.Expression->Desc.StartsWith( + AutogeneratedMessage, + ESearchCase::Type::CaseSensitive)) { + InputConnections.Emplace(TEXT("ALessThanB"), &IfNode->ALessThanB); + } + + if (IfNode->AEqualsB.Expression && + !IfNode->AEqualsB.Expression->Desc.StartsWith( + AutogeneratedMessage, + ESearchCase::Type::CaseSensitive)) { + InputConnections.Emplace(TEXT("AEqualsB"), &IfNode->AEqualsB); + } + + ConnectionInputRemap.Emplace(MoveTemp(Key), MoveTemp(InputConnections)); + } + + // Remove auto-generated nodes. + for (UMaterialExpression* AutoGeneratedNode : + Classification.AutoGeneratedNodes) { + Layer->GetExpressionCollection().RemoveExpression(AutoGeneratedNode); + } +} + +static void RemapUserConnections( + UMaterialFunctionMaterialLayer* Layer, + TMap>& ConnectionInputRemap, + TMap>& ConnectionOutputRemap, + const MaterialFunctionLibrary& FunctionLibrary) { + + MaterialNodeClassification Classification; + ClassifyNodes(Layer, Classification, FunctionLibrary); + + for (UMaterialExpressionMaterialFunctionCall* GetFeatureIdNode : + Classification.GetFeatureIdNodes) { + const auto Inputs = GetFeatureIdNode->FunctionInputs; + if (!Inputs.IsEmpty()) { + const auto Parameter = + Cast(Inputs[0].Input.Expression); + FString ParameterName = Parameter->ParameterName.ToString(); + + FString Key = GetFeatureIdNode->GetDescription() + ParameterName; + TArray* pConnections = ConnectionOutputRemap.Find(Key); + if (pConnections) { + for (FExpressionInput* pConnection : *pConnections) { + pConnection->Connect(0, GetFeatureIdNode); + } + } + } + } + + for (UMaterialExpressionCustom* GetPropertyValueNode : + Classification.GetPropertyValueNodes) { + int32 OutputIndex = 0; + for (const FExpressionOutput& PropertyOutput : + GetPropertyValueNode->Outputs) { + FString Key = GetPropertyValueNode->Description + + PropertyOutput.OutputName.ToString(); + + TArray* pConnections = ConnectionOutputRemap.Find(Key); + if (pConnections) { + for (FExpressionInput* pConnection : *pConnections) { + pConnection->Connect(OutputIndex, GetPropertyValueNode); + } + } + + ++OutputIndex; + } + } + + for (UMaterialExpressionCustom* ApplyValueTransformNode : + Classification.ApplyValueTransformNodes) { + int32 OutputIndex = 0; + for (const FExpressionOutput& PropertyOutput : + ApplyValueTransformNode->Outputs) { + FString Key = ApplyValueTransformNode->Description + + PropertyOutput.OutputName.ToString(); + + TArray* pConnections = ConnectionOutputRemap.Find(Key); + if (pConnections) { + for (FExpressionInput* pConnection : *pConnections) { + pConnection->Connect(OutputIndex, ApplyValueTransformNode); + } + } + + ++OutputIndex; + } + } + + for (UMaterialExpressionIf* IfNode : Classification.IfNodes) { + FString IfNodeName; + + FString AName; + UMaterialExpressionParameter* Parameter = + Cast(IfNode->A.Expression); + if (Parameter) { + AName = Parameter->GetParameterName().ToString(); + } else if (IfNode->A.Expression) { + TArray& Outputs = IfNode->A.Expression->GetOutputs(); + if (Outputs.Num() > 0) { + AName = Outputs[IfNode->A.OutputIndex].OutputName.ToString(); + } + } + + FString BName; + Parameter = Cast(IfNode->B.Expression); + if (Parameter) { + BName = Parameter->GetParameterName().ToString(); + } else if (IfNode->B.Expression) { + TArray& Outputs = IfNode->B.Expression->GetOutputs(); + if (Outputs.Num() > 0) { + BName = Outputs[IfNode->B.OutputIndex].OutputName.ToString(); + } + } + IfNodeName = AName + BName; + + FString Key = IfNode->GetDescription() + IfNodeName; + TArray* pConnections = ConnectionOutputRemap.Find(Key); + if (pConnections) { + for (FExpressionInput* pConnection : *pConnections) { + pConnection->Connect(0, IfNode); + } + } + + if (AName.Contains(MaterialPropertyHasValueSuffix)) { + // Skip the if statement that handles omitted properties. All connections + // to this node are meant to be autogenerated. + continue; + } + + bool isNoDataIfStatement = BName.Contains("NoData"); + + TMap* pInputConnections = + ConnectionInputRemap.Find(Key); + if (pInputConnections) { + const FExpressionInput** ppAGreaterThanB = + pInputConnections->Find(TEXT("AGreaterThanB")); + if (ppAGreaterThanB && *ppAGreaterThanB) { + IfNode->AGreaterThanB = **ppAGreaterThanB; + } + + const FExpressionInput** ppALessThanB = + pInputConnections->Find(TEXT("ALessThanB")); + if (ppALessThanB && *ppALessThanB) { + IfNode->ALessThanB = **ppALessThanB; + } + + if (isNoDataIfStatement && IfNode->AEqualsB.Expression) { + // If this node is comparing the "no data" value, the property may also + // have a default value. If it does, it will have already been connected + // to this expression; don't overwrite it. + continue; + } + + const FExpressionInput** ppAEqualsB = + pInputConnections->Find(TEXT("AEqualsB")); + if (ppAEqualsB && *ppAEqualsB) { + IfNode->AEqualsB = **ppAEqualsB; + } + } + } +} + +// Increment constant that is used to space out the autogenerated nodes. +static const int32 Incr = 200; + +namespace { +/** + * Computes a scalar for spacing out material nodes. The actual computation is + * rather arbitrary, but this prevents clumping when properties have extremely + * long names. + */ +float GetNameLengthScalar(const FName& Name) { + return FMath::Max(static_cast(Name.GetStringLength()) / 24, 1.0f); +} + +float GetNameLengthScalar(const FString& Name) { + return FMath::Max(static_cast(Name.Len()) / 24, 1.0f); +} + +ECustomMaterialOutputType +GetOutputTypeForEncodedType(ECesiumEncodedMetadataType Type) { + switch (Type) { + case ECesiumEncodedMetadataType::Vec2: + return ECustomMaterialOutputType::CMOT_Float2; + case ECesiumEncodedMetadataType::Vec3: + return ECustomMaterialOutputType::CMOT_Float3; + case ECesiumEncodedMetadataType::Vec4: + return ECustomMaterialOutputType::CMOT_Float4; + case ECesiumEncodedMetadataType::Scalar: + default: + return ECustomMaterialOutputType::CMOT_Float1; + }; +} + +FString GetSwizzleForEncodedType(ECesiumEncodedMetadataType Type) { + switch (Type) { + case ECesiumEncodedMetadataType::Scalar: + return ".r"; + case ECesiumEncodedMetadataType::Vec2: + return ".rg"; + case ECesiumEncodedMetadataType::Vec3: + return ".rgb"; + case ECesiumEncodedMetadataType::Vec4: + return ".rgba"; + default: + return FString(); + }; +} + +/** + * @brief Generates code for assembling metadata values from a scalar property + * texture property. + */ +FString GenerateCodeForScalarPropertyTextureProperty( + const FString& PropertyName, + const FString& PropertyChannelsName, + const FCesiumMetadataPropertyDetails& PropertyDetails) { + // Example: "heightResult" + FString PropertyResultName = PropertyName + "Result"; + // clang-format off + // Example: "uint heightResult = 0;" + FString code = "uint " + PropertyResultName + " = 0;\n"; + // clang-format on + FString SampleString = "sample = asuint(f.Get(sampleColor, channel));\n"; + + uint32 byteSize = GetMetadataTypeByteSize( + PropertyDetails.Type, + PropertyDetails.ComponentType); + if (byteSize == 1) { + // clang-format off + code += "channel = uint(f.Get(" + PropertyChannelsName + ", 0));\n" + + SampleString + + PropertyResultName + " = sample;\n"; + // clang-format on + } else { + // clang-format off + FString byteSizeString = std::to_string(byteSize).c_str(); + code += "byteOffset = 0;\n" + "for (uint i = 0; i < " + byteSizeString + "; i++) {\n" + " channel = uint(f.Get(" + PropertyChannelsName + ", i));\n" + + " " + SampleString + + " " + PropertyResultName + " = " + + PropertyResultName + " | (sample << byteOffset);\n" + " byteOffset += 8;\n" + "}\n"; + // clang-format on + } + + FString OutputName = PropertyName; + if (PropertyDetails.bIsNormalized || PropertyDetails.bHasOffset || + PropertyDetails.bHasScale) { + OutputName += MaterialPropertyRawSuffix; + } + + switch (PropertyDetails.ComponentType) { + case ECesiumMetadataComponentType::Float32: + code += OutputName + " = asfloat(" + PropertyResultName + ");\n"; + break; + case ECesiumMetadataComponentType::Int8: + case ECesiumMetadataComponentType::Int16: + case ECesiumMetadataComponentType::Int32: + code += OutputName + " = asint(" + PropertyResultName + ");\n"; + default: + code += OutputName + " = " + PropertyResultName + ";\n"; + break; + } + + return code; +} + +/** + * @brief Generates code for assembling metadata values from a vec2 property + * texture property. + */ +FString GenerateCodeForVec2PropertyTextureProperty( + const FString& PropertyName, + const FString& PropertyChannelsName, + const FCesiumMetadataPropertyDetails& PropertyDetails) { + FString ComponentString; + switch (PropertyDetails.ComponentType) { + case ECesiumMetadataComponentType::Uint8: + case ECesiumMetadataComponentType::Uint16: + ComponentString = "uint"; + break; + case ECesiumMetadataComponentType::Int8: + case ECesiumMetadataComponentType::Int16: + ComponentString = "int"; + break; + default: + // Only 1 or 2-byte components are supported. + return FString(); + } + + // Example: "sample = asuint(f.Get(sampleColor, channel));" + FString SampleString = + "sample = as" + ComponentString + "(f.Get(sampleColor, channel));\n"; + // Example: "uint2" + FString TypeString = ComponentString + "2"; + // Example: "dimensionsResult" + FString PropertyResultName = PropertyName + "Result"; + // Example: "uint2 dimensionsResult = uint2(0,0);" + FString code = + TypeString + " " + PropertyResultName + " = " + TypeString + "(0, 0);\n"; + + if (GetMetadataTypeByteSize( + PropertyDetails.Type, + PropertyDetails.ComponentType) == 1) { + // clang-format off + code += "channel = uint(f.Get(" + PropertyChannelsName + ", 0));\n" + + SampleString + + PropertyResultName + ".x = sample;\n" + "channel = uint(f.Get(" + PropertyChannelsName + ", 1));\n" + + SampleString + + PropertyResultName + ".y = sample;\n"; + // clang-format on + } else { + // clang-format off + code += "channel = uint(f.Get(" + PropertyChannelsName + ", 0));\n" + + SampleString + + PropertyResultName + ".x = sample;\n" + "channel = uint(f.Get(" + PropertyChannelsName + ", 1));\n" + + SampleString + + PropertyResultName + ".x = " + PropertyResultName + + ".x | (sample << 8);\n " + "channel = uint(f.Get(" + PropertyChannelsName + ", 2));\n" + + SampleString + + PropertyResultName + ".y = sample;\n" + "channel = uint(f.Get(" + PropertyChannelsName + ", 3));\n" + + SampleString + + PropertyResultName + ".y = " + PropertyResultName + + ".y | (sample << 8);\n "; + // clang-format on + } + + return code; +} + +/** + * @brief Generates code for assembling metadata values from a vecN property + * texture property, assuming it contains single-byte components. + */ +FString GenerateCodeForVecNPropertyTextureProperty( + const FString& PropertyName, + const FString& PropertyChannelsName, + ECesiumMetadataComponentType ComponentType, + uint32 Count) { + FString ComponentString; + // Only single-byte components are supported. + switch (ComponentType) { + case ECesiumMetadataComponentType::Uint8: + ComponentString = "uint"; + break; + case ECesiumMetadataComponentType::Int8: + ComponentString = "int"; + break; + default: + return FString(); + } + + FString CountString; + FString ZeroString; + switch (Count) { + case 2: + CountString = "2"; + ZeroString = "(0, 0)"; + break; + case 3: + CountString = "3"; + ZeroString = "(0, 0, 0)"; + break; + case 4: + CountString = "4"; + ZeroString = "(0, 0, 0, 0)"; + break; + default: + return FString(); + } + + // Example: "uint4" + FString TypeString = ComponentString + CountString; + // Example: "colorResult" + FString PropertyResultName = PropertyName + "Result"; + // Example: "sample = asuint(f.Get(sampleColor, channel));" + FString SampleString = + "sample = as" + ComponentString + "(f.Get(sampleColor, channel));\n "; + + // Example: "uint4 colorResult = uint4(0, 0, 0, 0);" + // clang-format off + FString code = + TypeString + " " + PropertyResultName + " = " + TypeString + ZeroString + + ";\n" + "channel = uint(f.Get(" + PropertyChannelsName + ", 0));\n" + + SampleString + + PropertyResultName + ".x = sample;\n" + "channel = uint(f.Get(" + PropertyChannelsName + ", 1));\n" + + SampleString + + PropertyResultName + ".y = sample;\n"; + // clang-format on + + if (Count >= 3) { + // clang-format off + code += "channel = uint(f.Get(" + PropertyChannelsName + ", 2));\n" + + SampleString + + PropertyResultName + ".z = sample;\n"; + // clang-format on + } + + if (Count == 4) { + // clang-format off + code += "channel = uint(f.Get(" + PropertyChannelsName + ", 3));\n" + + SampleString + + PropertyResultName + ".w = sample;\n"; + // clang-format on + } + + return code; +} + +/** + * @brief Generates code for assembling metadata values from a property texture + * property, depending on its type. + */ +FString GenerateCodeForPropertyTextureProperty( + const FString& PropertyName, + const FString& PropertyUVName, + const FString& PropertyDataName, + const FString& PropertyChannelsName, + const FCesiumMetadataPropertyDetails& PropertyDetails) { + // Example: sampleColor = Height_DATA.Sample(Height_DATASampler, Height_UV); + // clang-format off + FString code = + "sampleColor = " + + PropertyDataName + ".Sample(" + PropertyDataName + "Sampler, " + PropertyUVName + ");\n"; + + // clang-format on + if (PropertyDetails.bIsArray) { + if (GetMetadataTypeByteSize( + PropertyDetails.Type, + PropertyDetails.ComponentType) > 1) { + // Only single-byte array values are supported. + return FString(); + } + + return code + GenerateCodeForVecNPropertyTextureProperty( + PropertyName, + PropertyChannelsName, + PropertyDetails.ComponentType, + PropertyDetails.ArraySize); + } + + switch (PropertyDetails.Type) { + case ECesiumMetadataType::Scalar: + return code + GenerateCodeForScalarPropertyTextureProperty( + PropertyName, + PropertyChannelsName, + PropertyDetails); + case ECesiumMetadataType::Vec2: + // Vec2s must be handled differently because they can consist of either + // single-byte or double-byte components + return code + GenerateCodeForVec2PropertyTextureProperty( + PropertyName, + PropertyChannelsName, + PropertyDetails); + case ECesiumMetadataType::Vec3: + return code + GenerateCodeForVecNPropertyTextureProperty( + PropertyName, + PropertyChannelsName, + PropertyDetails.ComponentType, + 3); + case ECesiumMetadataType::Vec4: + return code + GenerateCodeForVecNPropertyTextureProperty( + PropertyName, + PropertyChannelsName, + PropertyDetails.ComponentType, + 4); + default: + return FString(); + } +} + +/** + * @brief Generates the nodes necessary to sample feature IDs from a feature ID + * texture. + */ +UMaterialExpressionMaterialFunctionCall* GenerateNodesForFeatureIdTexture( + const FCesiumFeatureIdSetDescription& Description, + TArray& AutoGeneratedNodes, + UMaterialFunctionMaterialLayer* TargetMaterialLayer, + const MaterialFunctionLibrary& FunctionLibrary, + int32& NodeX, + int32& NodeY) { + int32 MaximumParameterSectionX = 0; + FString SafeName = createHlslSafeName(Description.Name); + + UMaterialExpressionScalarParameter* TexCoordsIndex = + NewObject(TargetMaterialLayer); + TexCoordsIndex->ParameterName = FName(SafeName + MaterialTexCoordIndexSuffix); + TexCoordsIndex->DefaultValue = 0.0f; + TexCoordsIndex->MaterialExpressionEditorX = NodeX; + TexCoordsIndex->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(TexCoordsIndex); + + MaximumParameterSectionX = FMath::Max( + MaximumParameterSectionX, + Incr * GetNameLengthScalar(TexCoordsIndex->ParameterName)); + NodeY += 0.75 * Incr; + + UMaterialExpressionTextureObjectParameter* FeatureIdTexture = + NewObject(TargetMaterialLayer); + FeatureIdTexture->ParameterName = FName(SafeName + MaterialTextureSuffix); + FeatureIdTexture->MaterialExpressionEditorX = NodeX; + FeatureIdTexture->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(FeatureIdTexture); + + MaximumParameterSectionX = FMath::Max( + MaximumParameterSectionX, + Incr * GetNameLengthScalar(FeatureIdTexture->ParameterName)); + NodeY += Incr; + + UMaterialExpressionScalarParameter* NumChannels = + NewObject(TargetMaterialLayer); + NumChannels->ParameterName = FName(SafeName + MaterialNumChannelsSuffix); + NumChannels->DefaultValue = 0.0f; + NumChannels->MaterialExpressionEditorX = NodeX; + NumChannels->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(NumChannels); + + MaximumParameterSectionX = FMath::Max( + MaximumParameterSectionX, + Incr * GetNameLengthScalar(NumChannels->ParameterName)); + NodeY += 0.75 * Incr; + + UMaterialExpressionVectorParameter* Channels = + NewObject(TargetMaterialLayer); + Channels->ParameterName = FName(SafeName + MaterialChannelsSuffix); + Channels->DefaultValue = FLinearColor(0, 0, 0, 0); + Channels->MaterialExpressionEditorX = NodeX; + Channels->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(Channels); + + // KHR_texture_transform parameters + UMaterialExpressionVectorParameter* TransformScaleOffset = nullptr; + UMaterialExpressionVectorParameter* TransformRotation = nullptr; + + if (Description.bHasKhrTextureTransform) { + TransformScaleOffset = + NewObject(TargetMaterialLayer); + TransformScaleOffset->ParameterName = + FName(SafeName + MaterialTextureScaleOffsetSuffix); + TransformScaleOffset->DefaultValue = {1, 1, 0, 0}; + TransformScaleOffset->MaterialExpressionEditorX = NodeX; + TransformScaleOffset->MaterialExpressionEditorY = NodeY + 1.25 * Incr; + AutoGeneratedNodes.Add(TransformScaleOffset); + + MaximumParameterSectionX = FMath::Max( + MaximumParameterSectionX, + Incr * GetNameLengthScalar(TransformScaleOffset->ParameterName)); + + TransformRotation = + NewObject(TargetMaterialLayer); + TransformRotation->ParameterName = + FName(SafeName + MaterialTextureRotationSuffix); + TransformRotation->DefaultValue = {0, 1, 0, 1}; + TransformRotation->MaterialExpressionEditorX = NodeX; + TransformRotation->MaterialExpressionEditorY = NodeY + 2.5 * Incr; + AutoGeneratedNodes.Add(TransformRotation); + } + + NodeX += MaximumParameterSectionX + Incr; + + UMaterialExpressionAppendVector* AppendChannels = + NewObject(TargetMaterialLayer); + AppendChannels->MaterialExpressionEditorX = NodeX; + AppendChannels->MaterialExpressionEditorY = NodeY; + AppendChannels->A.Connect(0, Channels); + AppendChannels->B.Connect(4, Channels); + + AutoGeneratedNodes.Add(AppendChannels); + + UMaterialExpressionAppendVector* AppendScaleOffset = nullptr; + + if (Description.bHasKhrTextureTransform) { + AppendScaleOffset = + NewObject(TargetMaterialLayer); + AppendScaleOffset->MaterialExpressionEditorX = NodeX; + AppendScaleOffset->MaterialExpressionEditorY = + TransformScaleOffset->MaterialExpressionEditorY; + AppendScaleOffset->A.Connect(0, TransformScaleOffset); + AppendScaleOffset->B.Connect(4, TransformScaleOffset); + AutoGeneratedNodes.Add(AppendScaleOffset); + } + + NodeY -= 1.75 * Incr; + NodeX += 1.25 * Incr; + + UMaterialExpressionMaterialFunctionCall* GetFeatureIdsFromTexture = + NewObject(TargetMaterialLayer); + GetFeatureIdsFromTexture->MaterialFunction = + FunctionLibrary.GetFeatureIdsFromTexture; + GetFeatureIdsFromTexture->MaterialExpressionEditorX = NodeX; + GetFeatureIdsFromTexture->MaterialExpressionEditorY = NodeY; + + FunctionLibrary.GetFeatureIdsFromTexture->GetInputsAndOutputs( + GetFeatureIdsFromTexture->FunctionInputs, + GetFeatureIdsFromTexture->FunctionOutputs); + + GetFeatureIdsFromTexture->FunctionInputs[0].Input.Expression = TexCoordsIndex; + GetFeatureIdsFromTexture->FunctionInputs[1].Input.Expression = + FeatureIdTexture; + GetFeatureIdsFromTexture->FunctionInputs[2].Input.Expression = NumChannels; + GetFeatureIdsFromTexture->FunctionInputs[3].Input.Expression = AppendChannels; + + if (Description.bHasKhrTextureTransform) { + GetFeatureIdsFromTexture->FunctionInputs[4].Input.Connect( + 0, + AppendScaleOffset); + GetFeatureIdsFromTexture->FunctionInputs[5].Input.Connect( + 0, + TransformRotation); + } + + AutoGeneratedNodes.Add(GetFeatureIdsFromTexture); + + NodeX += 2 * Incr; + + return GetFeatureIdsFromTexture; +} + +/** + * @brief Generates the nodes necessary to sample feature IDs from a feature ID + * attribute. + */ +UMaterialExpressionMaterialFunctionCall* GenerateNodesForFeatureIdAttribute( + const FCesiumFeatureIdSetDescription& Description, + TArray& AutoGeneratedNodes, + UMaterialFunctionMaterialLayer* TargetMaterialLayer, + UMaterialFunction* GetFeatureIdsFromAttributeFunction, + int32& NodeX, + int32& NodeY) { + FString SafeName = createHlslSafeName(Description.Name); + UMaterialExpressionScalarParameter* TextureCoordinateIndex = + NewObject(TargetMaterialLayer); + TextureCoordinateIndex->ParameterName = FName(SafeName); + TextureCoordinateIndex->DefaultValue = 0.0f; + TextureCoordinateIndex->MaterialExpressionEditorX = NodeX; + TextureCoordinateIndex->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(TextureCoordinateIndex); + + NodeX += Incr * + (0.2f + GetNameLengthScalar(TextureCoordinateIndex->ParameterName)); + + UMaterialExpressionMaterialFunctionCall* GetFeatureIdsFromAttribute = + NewObject(TargetMaterialLayer); + GetFeatureIdsFromAttribute->MaterialFunction = + GetFeatureIdsFromAttributeFunction; + GetFeatureIdsFromAttribute->MaterialExpressionEditorX = NodeX; + GetFeatureIdsFromAttribute->MaterialExpressionEditorY = NodeY; + + GetFeatureIdsFromAttributeFunction->GetInputsAndOutputs( + GetFeatureIdsFromAttribute->FunctionInputs, + GetFeatureIdsFromAttribute->FunctionOutputs); + GetFeatureIdsFromAttribute->FunctionInputs[0].Input.Expression = + TextureCoordinateIndex; + AutoGeneratedNodes.Add(GetFeatureIdsFromAttribute); + + NodeX += 2 * Incr; + + return GetFeatureIdsFromAttribute; +} + +/** + * @brief Generates the nodes necessary to account for the null feature ID value + * from a feature ID set. + */ +void GenerateNodesForNullFeatureId( + const FCesiumFeatureIdSetDescription& Description, + TArray& AutoGeneratedNodes, + UMaterialFunctionMaterialLayer* TargetMaterialLayer, + int32& NodeX, + int32& NodeY, + UMaterialExpression* LastNode) { + int32 SectionTop = NodeY; + NodeY += 0.5 * Incr; + + FString SafeName = createHlslSafeName(Description.Name); + UMaterialExpressionScalarParameter* NullFeatureId = + NewObject(TargetMaterialLayer); + NullFeatureId->ParameterName = FName(SafeName + MaterialNullFeatureIdSuffix); + NullFeatureId->DefaultValue = 0; + NullFeatureId->MaterialExpressionEditorX = NodeX; + NullFeatureId->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(NullFeatureId); + + NodeY = SectionTop; + NodeX += Incr * (0.75 + GetNameLengthScalar(NullFeatureId->ParameterName)); + + UMaterialExpressionIf* IfStatement = + NewObject(TargetMaterialLayer); + + IfStatement->A.Expression = LastNode; + IfStatement->B.Expression = NullFeatureId; + + IfStatement->MaterialExpressionEditorX = NodeX; + IfStatement->MaterialExpressionEditorY = NodeY; + + AutoGeneratedNodes.Add(IfStatement); +} + +/** + * @brief Generates a parameter node corresponding to the given encoded metadata + * type. + */ +UMaterialExpressionParameter* GenerateParameterNodeWithGivenType( + const ECesiumEncodedMetadataType Type, + const FString& Name, + TArray& AutoGeneratedNodes, + UMaterialFunctionMaterialLayer* TargetMaterialLayer, + int32 NodeX, + int32 NodeY) { + UMaterialExpressionParameter* Parameter = nullptr; + int32 NodeHeight = 0; + + if (Type == ECesiumEncodedMetadataType::Scalar) { + UMaterialExpressionScalarParameter* ScalarParameter = + NewObject(TargetMaterialLayer); + ScalarParameter->DefaultValue = 0.0f; + Parameter = ScalarParameter; + } + + if (Type == ECesiumEncodedMetadataType::Vec2 || + Type == ECesiumEncodedMetadataType::Vec3 || + Type == ECesiumEncodedMetadataType::Vec4) { + UMaterialExpressionVectorParameter* VectorParameter = + NewObject(TargetMaterialLayer); + VectorParameter->DefaultValue = FLinearColor(0.0f, 0.0f, 0.0f, 0.0f); + Parameter = VectorParameter; + } + + if (!Parameter) { + return nullptr; + } + + Parameter->ParameterName = FName(Name); + Parameter->MaterialExpressionEditorX = NodeX; + Parameter->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(Parameter); + + return Parameter; +} + +/** + * @brief Generates the nodes necessary to apply property transforms to a + * metadata property. + */ +void GenerateNodesForMetadataPropertyTransforms( + const FCesiumMetadataPropertyDetails& PropertyDetails, + ECesiumEncodedMetadataType Type, + const FString& PropertyName, + const FString& FullPropertyName, + TArray& AutoGeneratedNodes, + UMaterialFunctionMaterialLayer* TargetMaterialLayer, + int32& NodeX, + int32& NodeY, + UMaterialExpressionCustom* GetPropertyValuesFunction, + int32 GetPropertyValuesOutputIndex) { + int32 BeginSectionX = NodeX; + int32 BeginSectionY = NodeY; + + UMaterialExpressionCustom* ApplyTransformsFunction = nullptr; + UMaterialExpression* GetNoDataValueNode = nullptr; + UMaterialExpression* GetDefaultValueNode = nullptr; + UMaterialExpressionIf* NoDataIfNode = nullptr; + + // This section corresponds to the parameter nodes on the left that actually + // supply the transform values for a property. + int32 MaximumParameterSectionX = 0; + + TArray NodesToMove; + ECustomMaterialOutputType OutputType = GetOutputTypeForEncodedType(Type); + + if (PropertyDetails.bIsNormalized || PropertyDetails.bHasScale || + PropertyDetails.bHasOffset) { + ApplyTransformsFunction = + NewObject(TargetMaterialLayer); + ApplyTransformsFunction->Code = ""; + ApplyTransformsFunction->Description = + ApplyValueTransformsPrefix + PropertyName; + ApplyTransformsFunction->MaterialExpressionEditorX = + BeginSectionX + 0.5 * Incr; + ApplyTransformsFunction->MaterialExpressionEditorY = NodeY; + + ApplyTransformsFunction->Inputs.Reserve(3); + ApplyTransformsFunction->Outputs.Reset(2); + ApplyTransformsFunction->AdditionalOutputs.Reserve(1); + ApplyTransformsFunction->Outputs.Add(FExpressionOutput(FName("Raw Value"))); + ApplyTransformsFunction->bShowOutputNameOnPin = true; + AutoGeneratedNodes.Add(ApplyTransformsFunction); + NodesToMove.Add(ApplyTransformsFunction); + + FCustomInput& RawValueInput = ApplyTransformsFunction->Inputs[0]; + RawValueInput.InputName = FName("RawValue"); + RawValueInput.Input.Expression = GetPropertyValuesFunction; + RawValueInput.Input.OutputIndex = GetPropertyValuesOutputIndex; + + FCustomOutput& TransformedOutput = + ApplyTransformsFunction->AdditionalOutputs.Emplace_GetRef(); + TransformedOutput.OutputName = FName("TransformedValue"); + ApplyTransformsFunction->Outputs.Add( + FExpressionOutput(TransformedOutput.OutputName)); + + TransformedOutput.OutputType = OutputType; + + FString TransformCode = "TransformedValue = "; + + if (PropertyDetails.bIsNormalized) { + // Normalization can be hardcoded because only normalized uint8s are + // supported. + TransformCode += "(RawValue / 255.0f)"; + } else { + TransformCode += "RawValue"; + } + + if (PropertyDetails.bHasScale) { + NodeY += Incr; + UMaterialExpressionParameter* Parameter = + GenerateParameterNodeWithGivenType( + Type, + FullPropertyName + MaterialPropertyScaleSuffix, + AutoGeneratedNodes, + TargetMaterialLayer, + BeginSectionX, + NodeY); + + FString ScaleName = "Scale"; + + FCustomInput& DefaultInput = + ApplyTransformsFunction->Inputs.Emplace_GetRef(); + DefaultInput.InputName = FName(ScaleName); + DefaultInput.Input.Expression = Parameter; + + TransformCode += " * " + ScaleName; + + MaximumParameterSectionX = FMath::Max( + MaximumParameterSectionX, + Incr * GetNameLengthScalar(Parameter->ParameterName)); + } + + if (PropertyDetails.bHasOffset) { + NodeY += Incr; + UMaterialExpressionParameter* Parameter = + GenerateParameterNodeWithGivenType( + Type, + FullPropertyName + MaterialPropertyOffsetSuffix, + AutoGeneratedNodes, + TargetMaterialLayer, + BeginSectionX, + NodeY); + + FString OffsetName = "Offset"; + + FCustomInput& DefaultInput = + ApplyTransformsFunction->Inputs.Emplace_GetRef(); + DefaultInput.InputName = FName(OffsetName); + DefaultInput.Input.Expression = Parameter; + + TransformCode += " + " + OffsetName; + + MaximumParameterSectionX = FMath::Max( + MaximumParameterSectionX, + Incr * GetNameLengthScalar(Parameter->ParameterName)); + } + + // Example: TransformedValue = (RawValue / 255.0f) * Scale_VALUE + + // Offset_VALUE; + ApplyTransformsFunction->Code += TransformCode + ";\n"; + + // Return the raw value. + ApplyTransformsFunction->OutputType = OutputType; + ApplyTransformsFunction->Code += "return RawValue;"; + + NodeX += + Incr * (1 + GetNameLengthScalar(ApplyTransformsFunction->Description)); + } + + FString swizzle = GetSwizzleForEncodedType(Type); + + if (PropertyDetails.bHasNoDataValue) { + NodeY += Incr; + UMaterialExpressionParameter* Parameter = + GenerateParameterNodeWithGivenType( + Type, + FullPropertyName + MaterialPropertyNoDataSuffix, + AutoGeneratedNodes, + TargetMaterialLayer, + BeginSectionX, + NodeY); + + int32 NameLength = Incr * GetNameLengthScalar(Parameter->ParameterName); + + if (Type == ECesiumEncodedMetadataType::Scalar) { + // No additional work needs to be done to retrieve the scalar, so don't + // an extra unnecessary node. + GetNoDataValueNode = Parameter; + } else { + // This is equivalent to a "MakeFloatN" function. + UMaterialExpressionCustom* CustomFunction = + NewObject(TargetMaterialLayer); + CustomFunction->Description = "Get No Data Value For " + PropertyName; + CustomFunction->MaterialExpressionEditorX = BeginSectionX + 0.5 * Incr; + CustomFunction->MaterialExpressionEditorY = NodeY; + + CustomFunction->Outputs.Reset(1); + CustomFunction->bShowOutputNameOnPin = true; + NodesToMove.Add(CustomFunction); + AutoGeneratedNodes.Add(CustomFunction); + + FString NoDataName = "NoData"; + FString InputName = NoDataName + MaterialPropertyValueSuffix; + + FCustomInput& NoDataInput = CustomFunction->Inputs[0]; + NoDataInput.InputName = FName(InputName); + NoDataInput.Input.Expression = Parameter; + + CustomFunction->Outputs.Add(FExpressionOutput(FName(NoDataName))); + CustomFunction->OutputType = OutputType; + + CustomFunction->Code = "return " + InputName + swizzle + ";\n"; + GetNoDataValueNode = CustomFunction; + + NameLength += GetNameLengthScalar(CustomFunction->Description) * Incr; + } + + MaximumParameterSectionX = + FMath::Max(MaximumParameterSectionX, 0.25 * Incr); + } + + if (PropertyDetails.bHasDefaultValue) { + NodeY += 0.75 * Incr; + UMaterialExpressionParameter* Parameter = + GenerateParameterNodeWithGivenType( + Type, + FullPropertyName + MaterialPropertyDefaultValueSuffix, + AutoGeneratedNodes, + TargetMaterialLayer, + BeginSectionX, + NodeY); + + int32 NameLength = Incr * GetNameLengthScalar(Parameter->ParameterName); + + if (Type == ECesiumEncodedMetadataType::Scalar) { + // No additional work needs to be done to retrieve the scalar, so don't + // an extra unnecessary node. + GetDefaultValueNode = Parameter; + } else { + // This is equivalent to a "MakeFloatN" function. + UMaterialExpressionCustom* CustomFunction = + NewObject(TargetMaterialLayer); + CustomFunction->Description = "Get Default Value For " + PropertyName; + CustomFunction->MaterialExpressionEditorX = BeginSectionX + 0.5 * Incr; + CustomFunction->MaterialExpressionEditorY = NodeY; + + CustomFunction->Outputs.Reset(1); + CustomFunction->bShowOutputNameOnPin = true; + NodesToMove.Add(CustomFunction); + AutoGeneratedNodes.Add(CustomFunction); + + FString DefaultName = "Default"; + FString InputName = DefaultName + MaterialPropertyValueSuffix; + + FCustomInput& DefaultInput = CustomFunction->Inputs[0]; + DefaultInput.InputName = FName(InputName); + DefaultInput.Input.Expression = Parameter; + + CustomFunction->Outputs.Add(FExpressionOutput(FName("Default Value"))); + CustomFunction->OutputType = OutputType; + + // Example: Default = Default_VALUE.xyz; + CustomFunction->Code = "return " + InputName + swizzle + ";\n"; + + GetDefaultValueNode = CustomFunction; + NameLength += GetNameLengthScalar(CustomFunction->Description) * Incr; + } + + MaximumParameterSectionX = FMath::Max( + MaximumParameterSectionX, + Incr * GetNameLengthScalar(Parameter->ParameterName)); + } + + for (UMaterialExpression* Node : NodesToMove) { + Node->MaterialExpressionEditorX += MaximumParameterSectionX; + } + NodesToMove.Empty(); + + NodeX += FMath::Max(2 * Incr, MaximumParameterSectionX + Incr); + + // We want to return to the top of the section and work down again, without + // overwriting NodeY. At the end, we use the maximum value to determine the + // vertical extent of the entire section. + int32 SectionNodeY = BeginSectionY; + + // Add if statement for resolving the no data / default values + if (GetNoDataValueNode) { + NodeX += Incr; + + NoDataIfNode = NewObject(TargetMaterialLayer); + NoDataIfNode->MaterialExpressionEditorX = NodeX; + NoDataIfNode->MaterialExpressionEditorY = SectionNodeY; + + NoDataIfNode->B.Expression = GetNoDataValueNode; + NoDataIfNode->AEqualsB.Expression = GetDefaultValueNode; + + if (ApplyTransformsFunction) { + NoDataIfNode->A.Expression = ApplyTransformsFunction; + NoDataIfNode->A.OutputIndex = 0; + + NoDataIfNode->AGreaterThanB.Expression = ApplyTransformsFunction; + NoDataIfNode->AGreaterThanB.OutputIndex = 1; + + NoDataIfNode->ALessThanB.Expression = ApplyTransformsFunction; + NoDataIfNode->ALessThanB.OutputIndex = 1; + } else { + NoDataIfNode->A.Expression = GetPropertyValuesFunction; + NoDataIfNode->A.OutputIndex = GetPropertyValuesOutputIndex; + + NoDataIfNode->AGreaterThanB.Expression = GetPropertyValuesFunction; + NoDataIfNode->AGreaterThanB.OutputIndex = GetPropertyValuesOutputIndex; + + NoDataIfNode->ALessThanB.Expression = GetPropertyValuesFunction; + NoDataIfNode->ALessThanB.OutputIndex = GetPropertyValuesOutputIndex; + } + + AutoGeneratedNodes.Add(NoDataIfNode); + NodeX += 2 * Incr; + } + + // If the property has a default value defined, it may be omitted from an + // instance of a property table, texture, or attribute. In this case, the + // default value should be used without needing to execute the + // GetPropertyValues function. We check this with a scalar parameter that + // acts as a boolean. + if (GetDefaultValueNode) { + UMaterialExpressionScalarParameter* HasValueParameter = + NewObject(TargetMaterialLayer); + HasValueParameter->DefaultValue = 0.0f; + HasValueParameter->ParameterName = + FName(FullPropertyName + MaterialPropertyHasValueSuffix); + HasValueParameter->MaterialExpressionEditorX = NodeX; + HasValueParameter->MaterialExpressionEditorY = SectionNodeY; + AutoGeneratedNodes.Add(HasValueParameter); + + NodeX += Incr * (1 + GetNameLengthScalar(HasValueParameter->ParameterName)); + UMaterialExpressionIf* IfStatement = + NewObject(TargetMaterialLayer); + IfStatement->MaterialExpressionEditorX = NodeX; + IfStatement->MaterialExpressionEditorY = SectionNodeY; + + IfStatement->A.Expression = HasValueParameter; + IfStatement->ConstB = 1.0f; + + IfStatement->ALessThanB.Expression = GetDefaultValueNode; + + if (NoDataIfNode) { + IfStatement->AGreaterThanB.Expression = NoDataIfNode; + IfStatement->AEqualsB.Expression = NoDataIfNode; + } else if (ApplyTransformsFunction) { + IfStatement->AGreaterThanB.Expression = ApplyTransformsFunction; + IfStatement->AGreaterThanB.OutputIndex = 1; + + IfStatement->AEqualsB.Expression = ApplyTransformsFunction; + IfStatement->AEqualsB.OutputIndex = 1; + } else { + IfStatement->AGreaterThanB.Expression = GetPropertyValuesFunction; + IfStatement->AGreaterThanB.OutputIndex = GetPropertyValuesOutputIndex; + + IfStatement->AEqualsB.Expression = GetPropertyValuesFunction; + IfStatement->AEqualsB.OutputIndex = GetPropertyValuesOutputIndex; + } + + AutoGeneratedNodes.Add(IfStatement); + } + + if (SectionNodeY > NodeY) { + NodeY = SectionNodeY; + } + + NodeY += Incr; +} + +/** + * @brief Generates the nodes necessary to retrieve values from a property + * table. + */ +void GenerateNodesForPropertyTable( + const FCesiumPropertyTableDescription& PropertyTable, + TArray& AutoGeneratedNodes, + UMaterialFunctionMaterialLayer* TargetMaterialLayer, + int32& NodeX, + int32& NodeY, + UMaterialExpression* GetFeatureExpression) { + int32 BeginSectionX = NodeX; + // This value is used by parameters on the left side of the + // "GetPropertyValues" function... + int32 PropertyDataSectionY = NodeY - 0.5 * Incr; + // ...whereas this value is used for parameters on the right side of the + // function. + int32 PropertyTransformsSectionY = NodeY + 20; + + UMaterialExpressionCustom* GetPropertyValuesFunction = + NewObject(TargetMaterialLayer); + GetPropertyValuesFunction->Inputs.Reserve(PropertyTable.Properties.Num() + 2); + GetPropertyValuesFunction->Outputs.Reset(PropertyTable.Properties.Num() + 1); + GetPropertyValuesFunction->Outputs.Add(FExpressionOutput(TEXT("Feature ID"))); + GetPropertyValuesFunction->bShowOutputNameOnPin = true; + GetPropertyValuesFunction->Code = ""; + GetPropertyValuesFunction->Description = + GetPropertyValuesPrefix + PropertyTable.Name; + GetPropertyValuesFunction->MaterialExpressionEditorX = NodeX; + GetPropertyValuesFunction->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(GetPropertyValuesFunction); + + int32 GetPropertyValuesFunctionWidth = + Incr * GetNameLengthScalar(GetPropertyValuesFunction->Description); + + // To prevent nodes from overlapping -- especially if they have really long + // names -- the GetPropertyValuesFunction node will be shifted to the right + // depending on the longest name among the parameters on the left. + int32 MaximumPropertyDataSectionX = 0; + // In a similar vein, this tracks the overall width of the property transforms + // section. This will be added to NodeX at the end so that nodes can continue + // to spawn horizontally. + int32 MaximumPropertyTransformsSectionX = 0; + + // The nodes to the right of GetPropertyValuesFunction will also need to be + // shifted, hence this array to keep track of them. + TArray PropertyTransformNodes; + + FCustomInput& FeatureIDInput = GetPropertyValuesFunction->Inputs[0]; + FeatureIDInput.InputName = FName("FeatureID"); + FeatureIDInput.Input.Expression = GetFeatureExpression; + + GetPropertyValuesFunction->AdditionalOutputs.Reserve( + PropertyTable.Properties.Num()); + + FString PropertyTableName = createHlslSafeName(PropertyTable.Name); + bool foundFirstProperty = false; + for (const FCesiumPropertyTablePropertyDescription& Property : + PropertyTable.Properties) { + if (Property.EncodingDetails.Conversion == + ECesiumEncodedMetadataConversion::None || + !Property.EncodingDetails.HasValidType()) { + continue; + } + + PropertyDataSectionY += Incr; + + FString PropertyName = createHlslSafeName(Property.Name); + // Example: "roofColor_DATA" + FString PropertyDataName = PropertyName + MaterialPropertyDataSuffix; + + if (!foundFirstProperty) { + // Get the dimensions of the first valid property. All the properties + // will have the same pixel dimensions since it is based on the feature + // count. + GetPropertyValuesFunction->Code += + "uint _czm_width;\nuint _czm_height;\n"; + GetPropertyValuesFunction->Code += + PropertyDataName + ".GetDimensions(_czm_width, _czm_height);\n"; + GetPropertyValuesFunction->Code += + "uint _czm_featureIndex = round(FeatureID);\n"; + GetPropertyValuesFunction->Code += + "uint _czm_pixelX = _czm_featureIndex % _czm_width;\n"; + GetPropertyValuesFunction->Code += + "uint _czm_pixelY = _czm_featureIndex / _czm_width;\n"; + + foundFirstProperty = true; + } + + UMaterialExpressionTextureObjectParameter* PropertyData = + NewObject( + TargetMaterialLayer); + FString FullPropertyName = getMaterialNameForPropertyTableProperty( + PropertyTableName, + PropertyName); + PropertyData->ParameterName = FName(FullPropertyName); + PropertyData->MaterialExpressionEditorX = BeginSectionX; + PropertyData->MaterialExpressionEditorY = PropertyDataSectionY; + AutoGeneratedNodes.Add(PropertyData); + + MaximumPropertyDataSectionX = FMath::Max( + MaximumPropertyDataSectionX, + Incr * GetNameLengthScalar(PropertyData->ParameterName)); + + FCustomInput& PropertyInput = + GetPropertyValuesFunction->Inputs.Emplace_GetRef(); + PropertyInput.InputName = FName(PropertyDataName); + PropertyInput.Input.Expression = PropertyData; + + FCustomOutput& PropertyOutput = + GetPropertyValuesFunction->AdditionalOutputs.Emplace_GetRef(); + + FString OutputName = PropertyName; + if (Property.PropertyDetails.bIsNormalized || + Property.PropertyDetails.bHasOffset || + Property.PropertyDetails.bHasScale) { + OutputName += MaterialPropertyRawSuffix; + } + + PropertyOutput.OutputName = FName(OutputName); + GetPropertyValuesFunction->Outputs.Add( + FExpressionOutput(PropertyOutput.OutputName)); + + FString swizzle = GetSwizzleForEncodedType(Property.EncodingDetails.Type); + PropertyOutput.OutputType = + GetOutputTypeForEncodedType(Property.EncodingDetails.Type); + + FString asComponentString = + Property.EncodingDetails.ComponentType == + ECesiumEncodedMetadataComponentType::Float + ? "asfloat" + : "asuint"; + + // Example: + // "color = asfloat(color_DATA.Load(int3(_czm_pixelX, _czm_pixelY, + // 0)).rgb);" + GetPropertyValuesFunction->Code += + OutputName + " = " + asComponentString + "(" + PropertyDataName + + ".Load(int3(_czm_pixelX, _czm_pixelY, 0))" + swizzle + ");\n"; + + if (Property.PropertyDetails.HasValueTransforms()) { + int32 PropertyTransformsSectionX = + 0.25 * Incr + GetPropertyValuesFunctionWidth; + GenerateNodesForMetadataPropertyTransforms( + Property.PropertyDetails, + Property.EncodingDetails.Type, + PropertyName, + FullPropertyName, + PropertyTransformNodes, + TargetMaterialLayer, + PropertyTransformsSectionX, + PropertyTransformsSectionY, + GetPropertyValuesFunction, + GetPropertyValuesFunction->Outputs.Num() - 1); + + MaximumPropertyTransformsSectionX = FMath::Max( + MaximumPropertyTransformsSectionX, + PropertyTransformsSectionX); + } + } + + // Shift the X of GetPropertyValues depending on the width of the data + // parameters. + GetPropertyValuesFunction->MaterialExpressionEditorX += + MaximumPropertyDataSectionX + Incr; + NodeX = GetPropertyValuesFunction->MaterialExpressionEditorX + + GetPropertyValuesFunctionWidth; + + // Reposition all of the nodes related to property transforms. + for (UMaterialExpression* Node : PropertyTransformNodes) { + Node->MaterialExpressionEditorX += + GetPropertyValuesFunction->MaterialExpressionEditorX; + AutoGeneratedNodes.Add(Node); + } + + // Return the feature ID. + GetPropertyValuesFunction->OutputType = + ECustomMaterialOutputType::CMOT_Float1; + GetPropertyValuesFunction->Code += "return FeatureID;"; + + NodeX = GetPropertyValuesFunction->MaterialExpressionEditorX + + GetPropertyValuesFunctionWidth + MaximumPropertyTransformsSectionX + + Incr; + NodeY = FMath::Max(PropertyDataSectionY, PropertyTransformsSectionY) + Incr; +} + +/** + * @brief Generates the nodes necessary to retrieve values from a property + * texture. In summary: + * - Gets UVs from primitive with SelectTexCoords (if applicable) + * - Creates GetPropertyValuesFrom function for property texture + * - Adds parameter nodes for each property's UV index, data, and channels array + * - Creates nodes to handle property transforms (if applicable) + */ +void GenerateNodesForPropertyTexture( + const FCesiumPropertyTextureDescription& PropertyTexture, + TArray& AutoGeneratedNodes, + UMaterialFunctionMaterialLayer* TargetMaterialLayer, + const MaterialFunctionLibrary& FunctionLibrary, + int32& NodeX, + int32& NodeY, + bool bHasTexCoords) { + int32 BeginSectionX = NodeX; + // This value is used by parameters on the left side of the + // "GetPropertyValues" function... + int32 PropertyDataSectionY = NodeY; + // ...whereas this value is used for parameters on the right side of the + // function. + int32 PropertyTransformsSectionY = NodeY + 20; + + UMaterialExpressionCustom* GetPropertyValuesFunction = + NewObject(TargetMaterialLayer); + GetPropertyValuesFunction->Inputs.Reset(3 * PropertyTexture.Properties.Num()); + GetPropertyValuesFunction->Outputs.Reset( + PropertyTexture.Properties.Num() + 1); + GetPropertyValuesFunction->Outputs.Add(FExpressionOutput(TEXT("return"))); + GetPropertyValuesFunction->bShowOutputNameOnPin = true; + GetPropertyValuesFunction->Code = ""; + GetPropertyValuesFunction->Description = + GetPropertyValuesPrefix + PropertyTexture.Name; + GetPropertyValuesFunction->MaterialExpressionEditorX = NodeX; + GetPropertyValuesFunction->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(GetPropertyValuesFunction); + + int32 GetPropertyValuesFunctionWidth = + Incr * GetNameLengthScalar(GetPropertyValuesFunction->Description); + + // To prevent nodes from overlapping -- especially if they have really long + // names -- the GetPropertyValuesFunction node will be shifted to the right + // depending on the longest name among the parameters on the left. + int32 MaximumPropertyDataSectionX = 0; + // In a similar vein, this tracks the overall width of the property transforms + // section. This will be added to NodeX at the end so that nodes can continue + // to spawn horizontally. + int32 MaximumPropertyTransformsSectionX = 0; + + // The nodes to the right of GetPropertyValuesFunction will also need to be + // shifted, hence this array to keep track of them. + TArray PropertyTransformNodes; + + FString PropertyTextureName = createHlslSafeName(PropertyTexture.Name); + bool foundFirstProperty = false; + + for (const FCesiumPropertyTexturePropertyDescription& Property : + PropertyTexture.Properties) { + if (!isSupportedPropertyTextureProperty(Property.PropertyDetails)) { + // Ignore properties that are unsupported, i.e., properties that require + // more than four bytes to parse values from. This limitation is imposed + // by cesium-native because only single-byte channels are supported. + UE_LOG( + LogCesium, + Warning, + TEXT( + "Skipping material node generation for unsupported property texture property %s in %s."), + *Property.Name, + *PropertyTexture.Name); + continue; + } + + FString PropertyName = createHlslSafeName(Property.Name); + FString FullPropertyName = getMaterialNameForPropertyTextureProperty( + PropertyTextureName, + PropertyName); + ECesiumEncodedMetadataType Type = + CesiumMetadataPropertyDetailsToEncodingDetails(Property.PropertyDetails) + .Type; + + if (!foundFirstProperty) { + // Define this helper function at the beginning of the code. This extracts + // the correct value from a float4 based on the given channel index. + // This is needed because the code input[index] doesn't seem to work with + // a dynamic index. + FString StructName = + MaterialPropertyTexturePrefix + PropertyTextureName + "Functions"; + // clang-format off + GetPropertyValuesFunction->Code += + "struct " + StructName + " {\n " + " float Get(float4 input, uint index) {\n" + " switch (index) {\n" + " case 0:\n return input.r;\n" + " case 1:\n return input.g;\n" + " case 2:\n return input.b;\n" + " case 3:\n return input.a;\n" + " default:\n return 0.0f;\n" + " }\n" + " }\n" + "};\n" + + StructName + " f;\n"; + // clang-format on + + // Also declare some temporary variables for later use. + GetPropertyValuesFunction->Code += + "float4 sampleColor = float4(0, 0, 0, 0);\n" + "uint byteOffset = 0;\n" + "uint sample = 0;\n" + "uint channel = 0;\n\n"; + + foundFirstProperty = true; + } + + UMaterialExpressionMaterialFunctionCall* TexCoordsInputFunction = nullptr; + + if (bHasTexCoords) { + UMaterialExpressionScalarParameter* TexCoordsIndex = + NewObject(TargetMaterialLayer); + TexCoordsIndex->ParameterName = + FName(FullPropertyName + MaterialTexCoordIndexSuffix); + TexCoordsIndex->DefaultValue = 0.0f; + TexCoordsIndex->MaterialExpressionEditorY = NodeX; + TexCoordsIndex->MaterialExpressionEditorY = PropertyDataSectionY; + AutoGeneratedNodes.Add(TexCoordsIndex); + + NodeX += + Incr * (GetNameLengthScalar(TexCoordsIndex->ParameterName) + 0.2f); + + UMaterialExpressionMaterialFunctionCall* SelectTexCoords = + NewObject( + TargetMaterialLayer); + SelectTexCoords->MaterialFunction = FunctionLibrary.SelectTexCoords; + SelectTexCoords->MaterialExpressionEditorX = NodeX; + SelectTexCoords->MaterialExpressionEditorY = PropertyDataSectionY; + + FunctionLibrary.SelectTexCoords->GetInputsAndOutputs( + SelectTexCoords->FunctionInputs, + SelectTexCoords->FunctionOutputs); + SelectTexCoords->FunctionInputs[0].Input.Expression = TexCoordsIndex; + AutoGeneratedNodes.Add(SelectTexCoords); + TexCoordsInputFunction = SelectTexCoords; + + MaximumPropertyDataSectionX = NodeX + 2 * Incr; + NodeX = BeginSectionX; + + if (Property.bHasKhrTextureTransform) { + PropertyDataSectionY += 1.25 * Incr; + + UMaterialExpressionVectorParameter* TransformRotation = + NewObject(TargetMaterialLayer); + TransformRotation->ParameterName = + FName(FullPropertyName + MaterialTextureRotationSuffix); + TransformRotation->DefaultValue = {0, 1, 0, 1}; + TransformRotation->MaterialExpressionEditorX = NodeX; + TransformRotation->MaterialExpressionEditorY = PropertyDataSectionY; + AutoGeneratedNodes.Add(TransformRotation); + + UMaterialExpressionVectorParameter* TransformScaleOffset = + NewObject(TargetMaterialLayer); + TransformScaleOffset->ParameterName = + FName(FullPropertyName + MaterialTextureScaleOffsetSuffix); + TransformScaleOffset->DefaultValue = {1, 1, 0, 0}; + TransformScaleOffset->MaterialExpressionEditorX = NodeX; + TransformScaleOffset->MaterialExpressionEditorY = + PropertyDataSectionY + Incr; + AutoGeneratedNodes.Add(TransformScaleOffset); + + UMaterialExpressionAppendVector* AppendScale = + NewObject(TargetMaterialLayer); + AppendScale->MaterialExpressionEditorX = + NodeX + Incr * (0.5 + GetNameLengthScalar( + TransformScaleOffset->ParameterName)); + AppendScale->MaterialExpressionEditorY = + TransformRotation->MaterialExpressionEditorY; + AppendScale->A.Connect(1, TransformScaleOffset); + AppendScale->B.Connect(2, TransformScaleOffset); + AutoGeneratedNodes.Add(AppendScale); + + UMaterialExpressionAppendVector* AppendOffset = + NewObject(TargetMaterialLayer); + AppendOffset->MaterialExpressionEditorX = + AppendScale->MaterialExpressionEditorX; + AppendOffset->MaterialExpressionEditorY = + TransformScaleOffset->MaterialExpressionEditorY; + AppendOffset->A.Connect(3, TransformScaleOffset); + AppendOffset->B.Connect(4, TransformScaleOffset); + AutoGeneratedNodes.Add(AppendOffset); + + MaximumPropertyDataSectionX = FMath::Max( + MaximumPropertyDataSectionX, + AppendOffset->MaterialExpressionEditorX + Incr - NodeX); + PropertyDataSectionY += 1.25 * Incr; + + UMaterialExpressionMaterialFunctionCall* TransformTexCoords = + NewObject( + TargetMaterialLayer); + TransformTexCoords->MaterialFunction = + FunctionLibrary.TransformTexCoords; + TransformTexCoords->MaterialExpressionEditorX = + SelectTexCoords->MaterialExpressionEditorX + Incr * 1.5; + TransformTexCoords->MaterialExpressionEditorY = + SelectTexCoords->MaterialExpressionEditorY; + + FunctionLibrary.TransformTexCoords->GetInputsAndOutputs( + TransformTexCoords->FunctionInputs, + TransformTexCoords->FunctionOutputs); + // For some reason, Connect() doesn't work with this input... + TransformTexCoords->FunctionInputs[0].Input.Expression = + SelectTexCoords; + TransformTexCoords->FunctionInputs[0].Input.OutputIndex = 0; + TransformTexCoords->FunctionInputs[1].Input.Connect( + 0, + TransformRotation); + TransformTexCoords->FunctionInputs[2].Input.Connect(0, AppendScale); + TransformTexCoords->FunctionInputs[3].Input.Connect(0, AppendOffset); + AutoGeneratedNodes.Add(TransformTexCoords); + + TexCoordsInputFunction = TransformTexCoords; + + MaximumPropertyDataSectionX = FMath::Max( + MaximumPropertyDataSectionX, + TransformTexCoords->MaterialExpressionEditorX + Incr * 1.5); + } + + PropertyDataSectionY += 0.8 * Incr; + } + + UMaterialExpressionTextureObjectParameter* PropertyData = + NewObject( + TargetMaterialLayer); + PropertyData->ParameterName = FName(FullPropertyName); + PropertyData->MaterialExpressionEditorX = NodeX; + PropertyData->MaterialExpressionEditorY = PropertyDataSectionY; + AutoGeneratedNodes.Add(PropertyData); + + MaximumPropertyDataSectionX = FMath::Max( + MaximumPropertyDataSectionX, + Incr * GetNameLengthScalar(PropertyData->ParameterName)); + PropertyDataSectionY += Incr; + + UMaterialExpressionVectorParameter* Channels = + NewObject(TargetMaterialLayer); + Channels->ParameterName = FName(FullPropertyName + MaterialChannelsSuffix); + Channels->DefaultValue = FLinearColor(0, 0, 0, 0); + Channels->MaterialExpressionEditorX = NodeX; + Channels->MaterialExpressionEditorY = PropertyDataSectionY; + AutoGeneratedNodes.Add(Channels); + + UMaterialExpressionAppendVector* AppendChannels = + NewObject(TargetMaterialLayer); + AppendChannels->MaterialExpressionEditorX = + NodeX + Incr * (1 + GetNameLengthScalar(Channels->ParameterName)); + AppendChannels->MaterialExpressionEditorY = PropertyDataSectionY; + AppendChannels->A.Connect(0, Channels); + AppendChannels->B.Connect(4, Channels); + AutoGeneratedNodes.Add(AppendChannels); + + MaximumPropertyDataSectionX = FMath::Max( + MaximumPropertyDataSectionX, + Incr * GetNameLengthScalar(Channels->ParameterName)); + + FCustomInput& TexCoordsInput = + GetPropertyValuesFunction->Inputs.Emplace_GetRef(); + FString PropertyTextureUVName = PropertyName + MaterialPropertyUVSuffix; + TexCoordsInput.InputName = FName(PropertyTextureUVName); + TexCoordsInput.Input.Expression = TexCoordsInputFunction; + + FCustomInput& PropertyTextureInput = + GetPropertyValuesFunction->Inputs.Emplace_GetRef(); + FString PropertyTextureDataName = PropertyName + MaterialPropertyDataSuffix; + PropertyTextureInput.InputName = FName(PropertyTextureDataName); + PropertyTextureInput.Input.Expression = PropertyData; + + FCustomInput& ChannelsInput = + GetPropertyValuesFunction->Inputs.Emplace_GetRef(); + FString PropertyTextureChannelsName = PropertyName + MaterialChannelsSuffix; + ChannelsInput.InputName = FName(PropertyTextureChannelsName); + ChannelsInput.Input.Expression = AppendChannels; + + FCustomOutput& PropertyOutput = + GetPropertyValuesFunction->AdditionalOutputs.Emplace_GetRef(); + + FString OutputName = PropertyName; + if (Property.PropertyDetails.bIsNormalized || + Property.PropertyDetails.bHasOffset || + Property.PropertyDetails.bHasScale) { + OutputName += MaterialPropertyRawSuffix; + } + + PropertyOutput.OutputName = FName(OutputName); + GetPropertyValuesFunction->Outputs.Add( + FExpressionOutput(PropertyOutput.OutputName)); + + PropertyOutput.OutputType = GetOutputTypeForEncodedType(Type); + + GetPropertyValuesFunction->Code += GenerateCodeForPropertyTextureProperty( + PropertyName, + PropertyTextureUVName, + PropertyTextureDataName, + PropertyTextureChannelsName, + Property.PropertyDetails); + + if (Property.PropertyDetails.HasValueTransforms()) { + int32 PropertyTransformsSectionX = + 0.2f * Incr + GetPropertyValuesFunctionWidth; + GenerateNodesForMetadataPropertyTransforms( + Property.PropertyDetails, + Type, + PropertyName, + FullPropertyName, + PropertyTransformNodes, + TargetMaterialLayer, + PropertyTransformsSectionX, + PropertyTransformsSectionY, + GetPropertyValuesFunction, + GetPropertyValuesFunction->Outputs.Num() - 1); + + MaximumPropertyTransformsSectionX = FMath::Max( + MaximumPropertyTransformsSectionX, + PropertyTransformsSectionX); + } + + PropertyDataSectionY += Incr; + } + + // Set the X of GetPropertyValues. + GetPropertyValuesFunction->MaterialExpressionEditorX += + MaximumPropertyDataSectionX + Incr; + + // Reposition all of the nodes related to property transforms. + for (UMaterialExpression* Node : PropertyTransformNodes) { + Node->MaterialExpressionEditorX += + GetPropertyValuesFunction->MaterialExpressionEditorX; + AutoGeneratedNodes.Add(Node); + } + + // Obligatory return code. + GetPropertyValuesFunction->OutputType = + ECustomMaterialOutputType::CMOT_Float1; + GetPropertyValuesFunction->Code += "return 0.0f;"; + + NodeX = GetPropertyValuesFunction->MaterialExpressionEditorX + + GetPropertyValuesFunctionWidth + MaximumPropertyTransformsSectionX + + Incr; + NodeY = FMath::Max(PropertyDataSectionY, PropertyTransformsSectionY) + Incr; +} + +UMaterialExpression* GenerateInstanceNodes( + TArray& AutoGeneratedNodes, + UMaterialFunctionMaterialLayer* TargetMaterialLayer, + UMaterialFunction* GetFeatureIdsFromInstanceFunction, + int32& NodeX, + int32& NodeY) { + UMaterialExpressionMaterialFunctionCall* GetFeatureIds = + NewObject(TargetMaterialLayer); + GetFeatureIds->MaterialFunction = GetFeatureIdsFromInstanceFunction; + GetFeatureIds->MaterialExpressionEditorX = NodeX; + GetFeatureIds->MaterialExpressionEditorY = NodeY; + + GetFeatureIdsFromInstanceFunction->GetInputsAndOutputs( + GetFeatureIds->FunctionInputs, + GetFeatureIds->FunctionOutputs); + + NodeX += 2 * Incr; + AutoGeneratedNodes.Add(GetFeatureIds); + return GetFeatureIds; +} + +void GenerateMaterialNodes( + UCesiumFeaturesMetadataComponent* pComponent, + TArray& AutoGeneratedNodes, + TArray& OneTimeGeneratedNodes, + const MaterialFunctionLibrary& FunctionLibrary) { + int32 NodeX = 0; + int32 NodeY = 0; + + int32 BeginSectionX = NodeX; + int32 MaximumSectionX = BeginSectionX; + + TSet GeneratedPropertyTableNames; + GeneratedPropertyTableNames.Reserve(pComponent->PropertyTables.Num()); + + for (const FCesiumFeatureIdSetDescription& featureIdSet : + pComponent->FeatureIdSets) { + if (featureIdSet.Type == ECesiumFeatureIdSetType::None) { + continue; + } + + UMaterialExpressionMaterialFunctionCall* GetFeatureIdCall = nullptr; + UMaterialExpression* LastNode = nullptr; + if (featureIdSet.Type == ECesiumFeatureIdSetType::Texture) { + LastNode = GenerateNodesForFeatureIdTexture( + featureIdSet, + AutoGeneratedNodes, + pComponent->TargetMaterialLayer, + FunctionLibrary, + NodeX, + NodeY); + } else if (featureIdSet.Type == ECesiumFeatureIdSetType::Instance) { + LastNode = GenerateInstanceNodes( + AutoGeneratedNodes, + pComponent->TargetMaterialLayer, + FunctionLibrary.GetFeatureIdsFromInstance, + NodeX, + NodeY); + } else { + // Handle implicit feature IDs the same as feature ID attributes + LastNode = GenerateNodesForFeatureIdAttribute( + featureIdSet, + AutoGeneratedNodes, + pComponent->TargetMaterialLayer, + FunctionLibrary.GetFeatureIdsFromAttribute, + NodeX, + NodeY); + } + + int32 BeginSectionY = NodeY; + + if (!featureIdSet.PropertyTableName.IsEmpty()) { + const FCesiumPropertyTableDescription* pPropertyTable = + pComponent->PropertyTables.FindByPredicate( + [&name = featureIdSet.PropertyTableName]( + const FCesiumPropertyTableDescription& + existingPropertyTable) { + return existingPropertyTable.Name == name; + }); + + if (pPropertyTable) { + GenerateNodesForPropertyTable( + *pPropertyTable, + AutoGeneratedNodes, + pComponent->TargetMaterialLayer, + NodeX, + NodeY, + LastNode); + GeneratedPropertyTableNames.Add(pPropertyTable->Name); + } + } + + if (featureIdSet.bHasNullFeatureId) { + // Spatial nitpicking; this aligns the if statement to the same Y as the + // PropertyTableFunction node then resets the Y so that the next section + // appears below all of the just-generated nodes. + int32 OriginalY = NodeY; + NodeY = BeginSectionY; + + GenerateNodesForNullFeatureId( + featureIdSet, + AutoGeneratedNodes, + pComponent->TargetMaterialLayer, + NodeX, + NodeY, + LastNode); + + NodeY = OriginalY; + } + MaximumSectionX = FMath::Max(MaximumSectionX, NodeX); + + NodeX = BeginSectionX; + NodeY += 1.75 * Incr; + } + + // Generate nodes for any property tables that aren't linked to a feature ID + // set. + for (const FCesiumPropertyTableDescription& propertyTable : + pComponent->PropertyTables) { + if (!GeneratedPropertyTableNames.Find(propertyTable.Name)) { + GenerateNodesForPropertyTable( + propertyTable, + AutoGeneratedNodes, + pComponent->TargetMaterialLayer, + NodeX, + NodeY, + nullptr); + MaximumSectionX = FMath::Max(MaximumSectionX, NodeX); + + NodeX = BeginSectionX; + NodeY += 1.75 * Incr; + } + } + + NodeY += Incr; + NodeX = BeginSectionX; + + TSet GeneratedPropertyTextureNames; + GeneratedPropertyTextureNames.Reserve(pComponent->PropertyTextures.Num()); + + for (const FString& propertyTextureName : pComponent->PropertyTextureNames) { + const FCesiumPropertyTextureDescription* pPropertyTexture = + pComponent->PropertyTextures.FindByPredicate( + [&propertyTextureName](const FCesiumPropertyTextureDescription& + existingPropertyTexture) { + return existingPropertyTexture.Name == propertyTextureName; + }); + if (!pPropertyTexture) { + continue; + } + + GenerateNodesForPropertyTexture( + *pPropertyTexture, + AutoGeneratedNodes, + pComponent->TargetMaterialLayer, + FunctionLibrary, + NodeX, + NodeY, + true); + GeneratedPropertyTextureNames.Add(propertyTextureName); + + MaximumSectionX = FMath::Max(MaximumSectionX, NodeX); + + NodeY += 1.75 * Incr; + NodeX = BeginSectionX; + } + + // Generate nodes for any property textures that aren't linked to a + // primitive / texture coordinate set. + for (const FCesiumPropertyTextureDescription& propertyTexture : + pComponent->PropertyTextures) { + if (!GeneratedPropertyTextureNames.Find(propertyTexture.Name)) { + GenerateNodesForPropertyTexture( + propertyTexture, + AutoGeneratedNodes, + pComponent->TargetMaterialLayer, + FunctionLibrary, + NodeX, + NodeY, + false); + + MaximumSectionX = FMath::Max(MaximumSectionX, NodeX); + + NodeY += 2 * Incr; + NodeX = BeginSectionX; + } + } + + NodeY = -2 * Incr; + + UMaterialExpressionFunctionInput* InputMaterial = nullptr; + for (const TObjectPtr& ExistingNode : + pComponent->TargetMaterialLayer->GetExpressionCollection().Expressions) { + UMaterialExpressionFunctionInput* ExistingInputMaterial = + Cast(ExistingNode); + if (ExistingInputMaterial) { + InputMaterial = ExistingInputMaterial; + break; + } + } + + if (!InputMaterial) { + InputMaterial = NewObject( + pComponent->TargetMaterialLayer); + InputMaterial->InputType = + EFunctionInputType::FunctionInput_MaterialAttributes; + InputMaterial->bUsePreviewValueAsDefault = true; + InputMaterial->MaterialExpressionEditorX = NodeX; + InputMaterial->MaterialExpressionEditorY = NodeY; + OneTimeGeneratedNodes.Add(InputMaterial); + } + + NodeX += BeginSectionX + MaximumSectionX; + + UMaterialExpressionSetMaterialAttributes* SetMaterialAttributes = nullptr; + for (const TObjectPtr& ExistingNode : + pComponent->TargetMaterialLayer->GetExpressionCollection().Expressions) { + UMaterialExpressionSetMaterialAttributes* ExistingSetAttributes = + Cast(ExistingNode); + if (ExistingSetAttributes) { + SetMaterialAttributes = ExistingSetAttributes; + break; + } + } + + if (!SetMaterialAttributes) { + SetMaterialAttributes = NewObject( + pComponent->TargetMaterialLayer); + OneTimeGeneratedNodes.Add(SetMaterialAttributes); + } + + SetMaterialAttributes->Inputs[0].Expression = InputMaterial; + SetMaterialAttributes->MaterialExpressionEditorX = NodeX; + SetMaterialAttributes->MaterialExpressionEditorY = NodeY; + + NodeX += 2 * Incr; + + UMaterialExpressionFunctionOutput* OutputMaterial = nullptr; + for (const TObjectPtr& ExistingNode : + pComponent->TargetMaterialLayer->GetExpressionCollection().Expressions) { + UMaterialExpressionFunctionOutput* ExistingOutputMaterial = + Cast(ExistingNode); + if (ExistingOutputMaterial) { + OutputMaterial = ExistingOutputMaterial; + break; + } + } + + if (!OutputMaterial) { + OutputMaterial = NewObject( + pComponent->TargetMaterialLayer); + OneTimeGeneratedNodes.Add(OutputMaterial); + } + + OutputMaterial->MaterialExpressionEditorX = NodeX; + OutputMaterial->MaterialExpressionEditorY = NodeY; + OutputMaterial->A = FMaterialAttributesInput(); + OutputMaterial->A.Expression = SetMaterialAttributes; +} + +} // namespace + +void UCesiumFeaturesMetadataComponent::GenerateMaterial() { + ACesium3DTileset* pTileset = Cast(this->GetOwner()); + if (!pTileset) { + return; + } + + FString MaterialName = + "ML_" + pTileset->GetFName().ToString() + "_FeaturesMetadata"; + FString PackageBaseName = "/Game/"; + FString PackageName = PackageBaseName + MaterialName; + + MaterialFunctionLibrary FunctionLibrary = MaterialFunctionLibrary(); + if (!FunctionLibrary.isValid()) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Can't find the material functions necessary to generate material. Aborting.")); + return; + } + + if (this->TargetMaterialLayer && + this->TargetMaterialLayer->GetPackage()->IsDirty()) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Can't regenerate a material layer that has unsaved changes. Please save your changes and try again.")); + return; + } + + bool Overwriting = false; + if (this->TargetMaterialLayer) { + // Overwriting an existing material layer. + Overwriting = true; + GEditor->GetEditorSubsystem() + ->CloseAllEditorsForAsset(this->TargetMaterialLayer); + } else { + UPackage* Package = CreatePackage(*PackageName); + + // Create an Unreal material layer + UMaterialFunctionMaterialLayerFactory* MaterialFactory = + NewObject(); + this->TargetMaterialLayer = + (UMaterialFunctionMaterialLayer*)MaterialFactory->FactoryCreateNew( + UMaterialFunctionMaterialLayer::StaticClass(), + Package, + *MaterialName, + RF_Public | RF_Standalone | RF_Transactional, + NULL, + GWarn); + FAssetRegistryModule::AssetCreated(this->TargetMaterialLayer); + Package->FullyLoad(); + Package->SetDirtyFlag(true); + } + + this->TargetMaterialLayer->PreEditChange(NULL); + + // Maps autogenerated nodes to the FExpressionInputs that it previously sent + // its outputs to. + TMap> ConnectionOutputRemap; + // Maps autogenerated nodes to the FExpressionInputs that it previously took + // inputs from. + TMap> ConnectionInputRemap; + + ClearAutoGeneratedNodes( + this->TargetMaterialLayer, + ConnectionInputRemap, + ConnectionOutputRemap, + FunctionLibrary); + + TArray AutoGeneratedNodes; + TArray OneTimeGeneratedNodes; + + GenerateMaterialNodes( + this, + AutoGeneratedNodes, + OneTimeGeneratedNodes, + FunctionLibrary); + + // Add the generated nodes to the material. + + for (UMaterialExpression* AutoGeneratedNode : AutoGeneratedNodes) { + // Mark as auto-generated. If the material is regenerated, we will look + // for this exact description to determine whether it was autogenerated. + + AutoGeneratedNode->Desc = AutogeneratedMessage; + + this->TargetMaterialLayer->GetExpressionCollection().AddExpression( + AutoGeneratedNode); + } + + for (UMaterialExpression* OneTimeGeneratedNode : OneTimeGeneratedNodes) { + this->TargetMaterialLayer->GetExpressionCollection().AddExpression( + OneTimeGeneratedNode); + } + + RemapUserConnections( + this->TargetMaterialLayer, + ConnectionInputRemap, + ConnectionOutputRemap, + FunctionLibrary); + + // Let the material update itself if necessary + this->TargetMaterialLayer->PostEditChange(); + + // Make sure that any static meshes, etc using this material will stop + // using the FMaterialResource of the original material, and will use the + // new FMaterialResource created when we make a new UMaterial in place + FGlobalComponentReregisterContext RecreateComponents; + + // If this is a new material, open the content browser to the auto-generated + // material. + if (!Overwriting) { + FContentBrowserModule* pContentBrowserModule = + FModuleManager::Get().GetModulePtr( + "ContentBrowser"); + if (pContentBrowserModule) { + TArray AssetsToHighlight; + AssetsToHighlight.Add(this->TargetMaterialLayer); + pContentBrowserModule->Get().SyncBrowserToAssets(AssetsToHighlight); + } + } + + // Open the updated material in editor. + if (GEditor) { + UAssetEditorSubsystem* pAssetEditor = + GEditor->GetEditorSubsystem(); + if (pAssetEditor) { + GEngine->EndTransaction(); + pAssetEditor->OpenEditorForAsset(this->TargetMaterialLayer); + IMaterialEditor* pMaterialEditor = static_cast( + pAssetEditor->FindEditorForAsset(this->TargetMaterialLayer, true)); + if (pMaterialEditor) { + pMaterialEditor->UpdateMaterialAfterGraphChange(); + } + } + } +} + +#endif // WITH_EDITOR diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFlyToComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFlyToComponent.cpp new file mode 100644 index 0000000..7c4bff2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFlyToComponent.cpp @@ -0,0 +1,327 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumFlyToComponent.h" +#include "CesiumGeoreference.h" +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumWgs84Ellipsoid.h" +#include "Curves/CurveFloat.h" +#include "GameFramework/Controller.h" +#include "GameFramework/Pawn.h" +#include "UObject/ConstructorHelpers.h" +#include "VecMath.h" + +#include + +UCesiumFlyToComponent::UCesiumFlyToComponent() { + // Structure to hold one-time initialization + struct FConstructorStatics { + ConstructorHelpers::FObjectFinder ProgressCurve; + ConstructorHelpers::FObjectFinder HeightPercentageCurve; + ConstructorHelpers::FObjectFinder MaximumHeightByDistanceCurve; + FConstructorStatics() + : ProgressCurve(TEXT( + "/CesiumForUnreal/Curves/FlyTo/Curve_CesiumFlyToDefaultProgress_Float.Curve_CesiumFlyToDefaultProgress_Float")), + HeightPercentageCurve(TEXT( + "/CesiumForUnreal/Curves/FlyTo/Curve_CesiumFlyToDefaultHeightPercentage_Float.Curve_CesiumFlyToDefaultHeightPercentage_Float")), + MaximumHeightByDistanceCurve(TEXT( + "/CesiumForUnreal/Curves/FlyTo/Curve_CesiumFlyToDefaultMaximumHeightByDistance_Float.Curve_CesiumFlyToDefaultMaximumHeightByDistance_Float")) { + } + }; + static FConstructorStatics ConstructorStatics; + + this->ProgressCurve = ConstructorStatics.ProgressCurve.Object; + this->HeightPercentageCurve = ConstructorStatics.HeightPercentageCurve.Object; + this->MaximumHeightByDistanceCurve = + ConstructorStatics.MaximumHeightByDistanceCurve.Object; + + this->PrimaryComponentTick.bCanEverTick = true; +} + +void UCesiumFlyToComponent::FlyToLocationEarthCenteredEarthFixed( + const FVector& EarthCenteredEarthFixedDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving) { + if (this->_flightInProgress) { + UE_LOG( + LogCesium, + Error, + TEXT("Cannot start a flight because one is already in progress.")); + return; + } + + UCesiumGlobeAnchorComponent* GlobeAnchor = this->GetGlobeAnchor(); + if (!IsValid(GlobeAnchor)) { + return; + } + + PitchAtDestination = glm::clamp(PitchAtDestination, -89.99, 89.99); + + // Compute source location in ECEF + FVector ecefSource = GlobeAnchor->GetEarthCenteredEarthFixedPosition(); + + // Obtain Ellipsoid + UCesiumEllipsoid* ellipsoid = + GlobeAnchor->ResolveGeoreference()->GetEllipsoid(); + + check(IsValid(ellipsoid)); + + // Create curve + std::optional curve = + CesiumGeospatial::SimplePlanarEllipsoidCurve:: + fromEarthCenteredEarthFixedCoordinates( + ellipsoid->GetNativeEllipsoid(), + glm::dvec3(ecefSource.X, ecefSource.Y, ecefSource.Z), + glm::dvec3( + EarthCenteredEarthFixedDestination.X, + EarthCenteredEarthFixedDestination.Y, + EarthCenteredEarthFixedDestination.Z)); + + if (!curve.has_value()) { + return; + } + + this->_currentCurve = + MakeUnique(curve.value()); + + this->_length = (EarthCenteredEarthFixedDestination - ecefSource).Length(); + + // The source and destination rotations are expressed in East-South-Up + // coordinates. + this->_sourceRotation = this->GetCurrentRotationEastSouthUp(); + this->_destinationRotation = + FRotator(PitchAtDestination, YawAtDestination, 0.0).Quaternion(); + + this->_currentFlyTime = 0.0f; + + // Compute a wanted height from curve + this->_maxHeight = 0.0; + if (this->HeightPercentageCurve != NULL) { + this->_maxHeight = 30000.0; + if (this->MaximumHeightByDistanceCurve != NULL) { + this->_maxHeight = + this->MaximumHeightByDistanceCurve->GetFloatValue(this->_length); + } + } + + // Tell the tick we will be flying from now + this->_canInterruptByMoving = CanInterruptByMoving; + this->_previousPositionEcef = ecefSource; + this->_flightInProgress = true; + this->_destinationEcef = EarthCenteredEarthFixedDestination; +} + +void UCesiumFlyToComponent::FlyToLocationLongitudeLatitudeHeight( + const FVector& LongitudeLatitudeHeightDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving) { + UCesiumEllipsoid* ellipsoid = + this->GetGlobeAnchor()->ResolveGeoreference()->GetEllipsoid(); + + FVector Ecef = + ellipsoid->LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + LongitudeLatitudeHeightDestination); + this->FlyToLocationEarthCenteredEarthFixed( + Ecef, + YawAtDestination, + PitchAtDestination, + CanInterruptByMoving); +} + +void UCesiumFlyToComponent::FlyToLocationUnreal( + const FVector& UnrealDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving) { + UCesiumGlobeAnchorComponent* GlobeAnchor = this->GetGlobeAnchor(); + if (!IsValid(GlobeAnchor)) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "CesiumFlyToComponent cannot FlyToLocationUnreal because the Actor has no CesiumGlobeAnchorComponent.")); + return; + } + + ACesiumGeoreference* Georeference = GlobeAnchor->ResolveGeoreference(); + if (!IsValid(Georeference)) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "CesiumFlyToComponent cannot FlyToLocationUnreal because the globe anchor has no associated CesiumGeoreference.")); + return; + } + + this->FlyToLocationEarthCenteredEarthFixed( + Georeference->TransformUnrealPositionToEarthCenteredEarthFixed( + UnrealDestination), + YawAtDestination, + PitchAtDestination, + CanInterruptByMoving); +} + +void UCesiumFlyToComponent::InterruptFlight() { + this->_flightInProgress = false; + + UCesiumGlobeAnchorComponent* GlobeAnchor = this->GetGlobeAnchor(); + if (IsValid(GlobeAnchor)) { + // fix Actor roll to 0.0 + FRotator currentRotator = this->GetCurrentRotationEastSouthUp().Rotator(); + currentRotator.Roll = 0.0; + FQuat eastSouthUpRotation = currentRotator.Quaternion(); + this->SetCurrentRotationEastSouthUp(eastSouthUpRotation); + } + + // Trigger callback accessible from BP + UE_LOG(LogCesium, Verbose, TEXT("Broadcasting OnFlightInterrupt")); + OnFlightInterrupted.Broadcast(); +} + +void UCesiumFlyToComponent::TickComponent( + float DeltaTime, + ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) { + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + if (!this->_flightInProgress) { + return; + } + + check(this->_currentCurve); + + UCesiumGlobeAnchorComponent* GlobeAnchor = this->GetGlobeAnchor(); + if (!IsValid(GlobeAnchor)) { + return; + } + + if (this->_canInterruptByMoving && + this->_previousPositionEcef != + GlobeAnchor->GetEarthCenteredEarthFixedPosition()) { + this->InterruptFlight(); + return; + } + + this->_currentFlyTime += DeltaTime; + + // In order to accelerate at start and slow down at end, we use a progress + // profile curve + float flyPercentage; + if (this->_currentFlyTime >= this->Duration) { + flyPercentage = 1.0f; + } else if (this->ProgressCurve) { + flyPercentage = glm::clamp( + this->ProgressCurve->GetFloatValue( + this->_currentFlyTime / this->Duration), + 0.0f, + 1.0f); + } else { + flyPercentage = this->_currentFlyTime / this->Duration; + } + + // If we reached the end, set actual destination location and + // orientation + if (flyPercentage >= 1.0f || + (this->_length == 0.0 && + this->_sourceRotation == this->_destinationRotation)) { + GlobeAnchor->MoveToEarthCenteredEarthFixedPosition(this->_destinationEcef); + this->SetCurrentRotationEastSouthUp(this->_destinationRotation); + this->_flightInProgress = false; + this->_currentFlyTime = 0.0f; + + // Trigger callback accessible from BP + UE_LOG(LogCesium, Verbose, TEXT("Broadcasting OnFlightComplete")); + OnFlightComplete.Broadcast(); + + return; + } + + // Get altitude offset from profile curve if one is specified + double altitudeOffset = 0.0; + if (this->_maxHeight != 0.0 && this->HeightPercentageCurve) { + double curveOffset = + this->_maxHeight * + this->HeightPercentageCurve->GetFloatValue(flyPercentage); + altitudeOffset = curveOffset; + } + + glm::dvec3 currentPositionEcef = + _currentCurve->getPosition(flyPercentage, altitudeOffset); + + FVector currentPositionVector( + currentPositionEcef.x, + currentPositionEcef.y, + currentPositionEcef.z); + + // Set Location + GlobeAnchor->MoveToEarthCenteredEarthFixedPosition(currentPositionVector); + + // Interpolate rotation in the ESU frame. The local ESU ControlRotation will + // be transformed to the appropriate world rotation as we fly. + FQuat currentQuat = FQuat::Slerp( + this->_sourceRotation, + this->_destinationRotation, + flyPercentage); + this->SetCurrentRotationEastSouthUp(currentQuat); + + this->_previousPositionEcef = + GlobeAnchor->GetEarthCenteredEarthFixedPosition(); +} + +FQuat UCesiumFlyToComponent::GetCurrentRotationEastSouthUp() { + if (this->RotationToUse != ECesiumFlyToRotation::Actor) { + APawn* Pawn = Cast(this->GetOwner()); + const TObjectPtr Controller = + IsValid(Pawn) ? Pawn->Controller : nullptr; + if (Controller) { + FRotator rotator = Controller->GetControlRotation(); + if (this->RotationToUse == + ECesiumFlyToRotation::ControlRotationInUnreal) { + USceneComponent* PawnRoot = Pawn->GetRootComponent(); + if (IsValid(PawnRoot)) { + rotator = GetGlobeAnchor() + ->ResolveGeoreference() + ->TransformUnrealRotatorToEastSouthUp( + Controller->GetControlRotation(), + PawnRoot->GetRelativeLocation()); + } + } + return rotator.Quaternion(); + } + } + + return this->GetGlobeAnchor()->GetEastSouthUpRotation(); +} + +void UCesiumFlyToComponent::SetCurrentRotationEastSouthUp( + const FQuat& EastSouthUpRotation) { + bool controlRotationSet = false; + + if (this->RotationToUse != ECesiumFlyToRotation::Actor) { + APawn* Pawn = Cast(this->GetOwner()); + const TObjectPtr Controller = + IsValid(Pawn) ? Pawn->Controller : nullptr; + if (Controller) { + FRotator rotator = EastSouthUpRotation.Rotator(); + if (this->RotationToUse == + ECesiumFlyToRotation::ControlRotationInUnreal) { + USceneComponent* PawnRoot = Pawn->GetRootComponent(); + if (IsValid(PawnRoot)) { + rotator = GetGlobeAnchor() + ->ResolveGeoreference() + ->TransformEastSouthUpRotatorToUnreal( + EastSouthUpRotation.Rotator(), + PawnRoot->GetRelativeLocation()); + } + } + + Controller->SetControlRotation(EastSouthUpRotation.Rotator()); + controlRotationSet = true; + } + } + + if (!controlRotationSet) { + this->GetGlobeAnchor()->SetEastSouthUpRotation(EastSouthUpRotation); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGeoreference.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGeoreference.cpp new file mode 100644 index 0000000..19e0f9e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGeoreference.cpp @@ -0,0 +1,930 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGeoreference.h" +#include "Camera/PlayerCameraManager.h" +#include "Cesium3DTileset.h" +#include "CesiumActors.h" +#include "CesiumCommon.h" +#include "CesiumCustomVersion.h" +#include "CesiumGeospatial/Cartographic.h" +#include "CesiumOriginShiftComponent.h" +#include "CesiumRuntime.h" +#include "CesiumSubLevelComponent.h" +#include "CesiumSubLevelSwitcherComponent.h" +#include "CesiumTransforms.h" +#include "CesiumUtility/Math.h" +#include "Engine/LevelStreaming.h" +#include "Engine/World.h" +#include "Engine/WorldComposition.h" +#include "EngineUtils.h" +#include "GameFramework/PlayerController.h" +#include "GeoTransforms.h" +#include "Kismet/GameplayStatics.h" +#include "LevelInstance/LevelInstanceActor.h" +#include "Math/Matrix.h" +#include "Math/RotationTranslationMatrix.h" +#include "Math/Rotator.h" +#include "Math/Vector.h" +#include "Misc/PackageName.h" +#include "UObject/Class.h" +#include "UObject/UnrealType.h" +#include "VecMath.h" +#include +#include +#include +#include +#include + +#if WITH_EDITOR +#include "DrawDebugHelpers.h" +#include "Editor.h" +#include "EditorLevelUtils.h" +#include "EditorViewportClient.h" +#include "GameFramework/Pawn.h" +#include "LevelInstance/LevelInstanceEditorLevelStreaming.h" +#include "Slate/SceneViewport.h" +#endif + +using namespace CesiumGeospatial; + +namespace { + +ACesiumGeoreference* FindGeoreferenceAncestor(AActor* Actor) { + AActor* Current = Actor; + + while (IsValid(Current)) { + ACesiumGeoreference* Georeference = Cast(Current); + if (IsValid(Georeference)) { + return Georeference; + } + Current = Current->GetAttachParentActor(); + } + + return nullptr; +} + +ACesiumGeoreference* +FindGeoreferenceWithTag(const UObject* WorldContextObject, const FName& Tag) { + UWorld* World = WorldContextObject->GetWorld(); + if (!IsValid(World)) + return nullptr; + + // Note: The actor iterator will be created with the + // "EActorIteratorFlags::SkipPendingKill" flag, + // meaning that we don't have to handle objects + // that have been deleted. (This is the default, + // but made explicit here) + ACesiumGeoreference* Georeference = nullptr; + EActorIteratorFlags flags = EActorIteratorFlags::OnlyActiveLevels | + EActorIteratorFlags::SkipPendingKill; + for (TActorIterator actorIterator( + World, + ACesiumGeoreference::StaticClass(), + flags); + actorIterator; + ++actorIterator) { + AActor* actor = *actorIterator; + if (actor->GetLevel() == World->PersistentLevel && + actor->ActorHasTag(Tag)) { + Georeference = Cast(actor); + break; + } + } + + return Georeference; +} + +ACesiumGeoreference* +FindGeoreferenceWithDefaultName(const UObject* WorldContextObject) { + UWorld* World = WorldContextObject->GetWorld(); + if (!IsValid(World)) + return nullptr; + + ACesiumGeoreference* Candidate = FindObject( + World->PersistentLevel, + TEXT("CesiumGeoreferenceDefault")); + + // Test if PendingKill + if (IsValid(Candidate)) { + return Candidate; + } + + return nullptr; +} + +ACesiumGeoreference* +CreateDefaultGeoreference(const UObject* WorldContextObject, const FName& Tag) { + UWorld* World = WorldContextObject->GetWorld(); + if (!IsValid(World)) + return nullptr; + + // Spawn georeference in the persistent level + FActorSpawnParameters spawnParameters; + spawnParameters.SpawnCollisionHandlingOverride = + ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + spawnParameters.OverrideLevel = World->PersistentLevel; + + ACesiumGeoreference* Georeference = + World->SpawnActor(spawnParameters); + if (Georeference) { + Georeference->Tags.Add(Tag); + } + + return Georeference; +} + +} // namespace + +/*static*/ const double ACesiumGeoreference::kMinimumScale = 1.0e-6; + +/*static*/ ACesiumGeoreference* +ACesiumGeoreference::GetDefaultGeoreference(const UObject* WorldContextObject) { + if (!IsValid(WorldContextObject)) + return nullptr; + + ACesiumGeoreference* Georeference = + FindGeoreferenceWithTag(WorldContextObject, DEFAULT_GEOREFERENCE_TAG); + if (IsValid(Georeference)) + return Georeference; + + Georeference = FindGeoreferenceWithDefaultName(WorldContextObject); + if (IsValid(Georeference)) + return Georeference; + + Georeference = + CreateDefaultGeoreference(WorldContextObject, DEFAULT_GEOREFERENCE_TAG); + + return Georeference; +} + +/*static*/ ACesiumGeoreference* +ACesiumGeoreference::GetDefaultGeoreferenceForActor(AActor* Actor) { + if (!IsValid(Actor)) + return nullptr; + + ACesiumGeoreference* Georeference = FindGeoreferenceAncestor(Actor); + if (IsValid(Georeference)) + return Georeference; + + return ACesiumGeoreference::GetDefaultGeoreference(Actor); +} + +UCesiumEllipsoid* ACesiumGeoreference::GetEllipsoid() const { + if (!IsValid(this->Ellipsoid)) { + UE_LOG( + LogCesium, + Error, + TEXT( + "ACesiumGeoreference needs a valid Ellipsoid asset. Calculations will use a unit ellipsoid as a placeholder.")); + return UCesiumEllipsoid::Create(FVector::OneVector); + } + return this->Ellipsoid; +} + +FVector ACesiumGeoreference::GetOriginLongitudeLatitudeHeight() const { + return FVector(OriginLongitude, OriginLatitude, OriginHeight); +} + +void ACesiumGeoreference::SetOriginLongitudeLatitudeHeight( + const FVector& targetLongitudeLatitudeHeight) { + this->OriginLongitude = targetLongitudeLatitudeHeight.X; + this->OriginLatitude = targetLongitudeLatitudeHeight.Y; + this->OriginHeight = targetLongitudeLatitudeHeight.Z; + this->UpdateGeoreference(); +} + +FVector ACesiumGeoreference::GetOriginEarthCenteredEarthFixed() const { + return this->GetEllipsoid() + ->LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + this->GetOriginLongitudeLatitudeHeight()); +} + +void ACesiumGeoreference::SetOriginEarthCenteredEarthFixed( + const FVector& TargetEarthCenteredEarthFixed) { + this->SetOriginLongitudeLatitudeHeight( + this->GetEllipsoid() + ->EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight( + TargetEarthCenteredEarthFixed)); +} + +EOriginPlacement ACesiumGeoreference::GetOriginPlacement() const { + return this->OriginPlacement; +} + +void ACesiumGeoreference::SetOriginPlacement(EOriginPlacement NewValue) { + this->OriginPlacement = NewValue; + this->UpdateGeoreference(); +} + +double ACesiumGeoreference::GetOriginLatitude() const { + return this->OriginLatitude; +} + +void ACesiumGeoreference::SetOriginLatitude(double NewValue) { + this->OriginLatitude = NewValue; + this->UpdateGeoreference(); +} + +double ACesiumGeoreference::GetOriginLongitude() const { + return this->OriginLongitude; +} + +void ACesiumGeoreference::SetOriginLongitude(double NewValue) { + this->OriginLongitude = NewValue; + this->UpdateGeoreference(); +} + +double ACesiumGeoreference::GetOriginHeight() const { + return this->OriginHeight; +} + +void ACesiumGeoreference::SetOriginHeight(double NewValue) { + this->OriginHeight = NewValue; + this->UpdateGeoreference(); +} + +double ACesiumGeoreference::GetScale() const { return this->Scale; } + +void ACesiumGeoreference::SetScale(double NewValue) { + if (NewValue < ACesiumGeoreference::kMinimumScale) { + this->Scale = ACesiumGeoreference::kMinimumScale; + } else { + this->Scale = NewValue; + } + this->UpdateGeoreference(); +} + +APlayerCameraManager* ACesiumGeoreference::GetSubLevelCamera() const { + return this->SubLevelCamera_DEPRECATED; +} + +void ACesiumGeoreference::SetSubLevelCamera(APlayerCameraManager* NewValue) { + this->SubLevelCamera_DEPRECATED = NewValue; +} + +void ACesiumGeoreference::SetEllipsoid(UCesiumEllipsoid* NewEllipsoid) { + UCesiumEllipsoid* OldEllipsoid = this->Ellipsoid; + this->Ellipsoid = NewEllipsoid; + this->OnEllipsoidChanged.Broadcast(OldEllipsoid, NewEllipsoid); + this->UpdateGeoreference(); +} + +#if WITH_EDITOR +bool ACesiumGeoreference::GetShowLoadRadii() const { + return this->ShowLoadRadii; +} + +void ACesiumGeoreference::SetShowLoadRadii(bool NewValue) { + this->ShowLoadRadii = NewValue; +} +#endif // WITH_EDITOR + +FVector ACesiumGeoreference::TransformLongitudeLatitudeHeightPositionToUnreal( + const FVector& LongitudeLatitudeHeight) const { + return this->TransformEarthCenteredEarthFixedPositionToUnreal( + this->GetEllipsoid() + ->LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + LongitudeLatitudeHeight)); +} + +FVector ACesiumGeoreference::TransformUnrealPositionToLongitudeLatitudeHeight( + const FVector& UnrealPosition) const { + return this->GetEllipsoid() + ->EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight( + this->TransformUnrealPositionToEarthCenteredEarthFixed( + UnrealPosition)); +} + +FVector ACesiumGeoreference::TransformEarthCenteredEarthFixedPositionToUnreal( + const FVector& EarthCenteredEarthFixedPosition) const { + return VecMath::createVector(this->_coordinateSystem.ecefPositionToLocal( + VecMath::createVector3D(EarthCenteredEarthFixedPosition))); +} + +FVector ACesiumGeoreference::TransformUnrealPositionToEarthCenteredEarthFixed( + const FVector& UnrealPosition) const { + return VecMath::createVector(this->_coordinateSystem.localPositionToEcef( + VecMath::createVector3D(UnrealPosition))); +} + +FVector ACesiumGeoreference::TransformEarthCenteredEarthFixedDirectionToUnreal( + const FVector& EarthCenteredEarthFixedDirection) const { + return VecMath::createVector(this->_coordinateSystem.ecefDirectionToLocal( + VecMath::createVector3D(EarthCenteredEarthFixedDirection))); +} + +FVector ACesiumGeoreference::TransformUnrealDirectionToEarthCenteredEarthFixed( + const FVector& UnrealDirection) const { + return VecMath::createVector(this->_coordinateSystem.localDirectionToEcef( + VecMath::createVector3D(UnrealDirection))); +} + +FRotator ACesiumGeoreference::TransformUnrealRotatorToEastSouthUp( + const FRotator& UnrealRotator, + const FVector& UnrealLocation) const { + FMatrix unrealToEsu = + this->ComputeEastSouthUpToUnrealTransformation(UnrealLocation).Inverse(); + return FRotator(unrealToEsu.ToQuat() * UnrealRotator.Quaternion()); +} + +FRotator ACesiumGeoreference::TransformEastSouthUpRotatorToUnreal( + const FRotator& EastSouthUpRotator, + const FVector& UnrealLocation) const { + FMatrix esuToUnreal = + this->ComputeEastSouthUpToUnrealTransformation(UnrealLocation); + return FRotator(esuToUnreal.ToQuat() * EastSouthUpRotator.Quaternion()); +} + +FMatrix +ACesiumGeoreference::ComputeUnrealToEarthCenteredEarthFixedTransformation() + const { + return VecMath::createMatrix( + this->_coordinateSystem.getLocalToEcefTransformation()); +} + +FMatrix +ACesiumGeoreference::ComputeEarthCenteredEarthFixedToUnrealTransformation() + const { + return VecMath::createMatrix( + this->_coordinateSystem.getEcefToLocalTransformation()); +} + +FMatrix ACesiumGeoreference::ComputeEastSouthUpToUnrealTransformation( + const FVector& UnrealLocation) const { + FVector ecef = + this->TransformUnrealPositionToEarthCenteredEarthFixed(UnrealLocation); + return this + ->ComputeEastSouthUpAtEarthCenteredEarthFixedPositionToUnrealTransformation( + ecef); +} + +FMatrix ACesiumGeoreference:: + ComputeEastSouthUpAtEarthCenteredEarthFixedPositionToUnrealTransformation( + const FVector& EarthCenteredEarthFixedPosition) const { + LocalHorizontalCoordinateSystem newLocal = + this->GetEllipsoid()->CreateCoordinateSystem( + EarthCenteredEarthFixedPosition, + this->GetScale()); + return VecMath::createMatrix( + newLocal.computeTransformationToAnotherLocal(this->_coordinateSystem)); +} + +FMatrix ACesiumGeoreference::ComputeUnrealToEastSouthUpTransformation( + const FVector& UnrealLocation) const { + return this->ComputeEastSouthUpToUnrealTransformation(UnrealLocation) + .Inverse(); +} + +#if WITH_EDITOR +void ACesiumGeoreference::PlaceGeoreferenceOriginHere() { + // If this is PIE mode, ignore + UWorld* pWorld = this->GetWorld(); + if (!pWorld || !GEditor || pWorld->IsGameWorld()) { + return; + } + + this->Modify(); + + FViewport* pViewport = GEditor->GetActiveViewport(); + FViewportClient* pViewportClient = pViewport->GetClient(); + FEditorViewportClient* pEditorViewportClient = + static_cast(pViewportClient); + + // The viewport location / rotation is Unreal world coordinates. Transform + // into the georeference's reference frame. This way we'll compute the correct + // globe position even if the globe is transformed into the Unreal world. + FVector ViewLocation = pEditorViewportClient->GetViewLocation(); + FQuat ViewRotation = pEditorViewportClient->GetViewRotation().Quaternion(); + + ViewLocation = + this->GetActorTransform().InverseTransformPosition(ViewLocation); + ViewRotation = + this->GetActorTransform().InverseTransformRotation(ViewRotation); + + FRotator NewViewRotation = this->TransformUnrealRotatorToEastSouthUp( + ViewRotation.Rotator(), + ViewLocation); + + // camera local space to ECEF + FVector CameraEcefPosition = + this->TransformUnrealPositionToEarthCenteredEarthFixed(ViewLocation); + + // Long/Lat/Height camera location, in degrees/meters (also our new target + // georeference origin) When the location is too close to the center of the + // earth, the result will be (0,0,0) + this->SetOriginEarthCenteredEarthFixed(CameraEcefPosition); + + // TODO: check for degeneracy ? + FVector cameraFront = NewViewRotation.RotateVector(FVector::XAxisVector); + FVector cameraRight = + FVector::CrossProduct(FVector::ZAxisVector, cameraFront).GetSafeNormal(); + FVector cameraUp = + FVector::CrossProduct(cameraFront, cameraRight).GetSafeNormal(); + + pEditorViewportClient->SetViewRotation( + FMatrix(cameraFront, cameraRight, cameraUp, FVector::ZeroVector) + .Rotator()); + pEditorViewportClient->SetViewLocation( + this->GetActorTransform().TransformPosition(FVector::ZeroVector)); +} + +void ACesiumGeoreference::CreateSubLevelHere() { + UWorld* World = GetWorld(); + if (!World || !GEditor || World->IsGameWorld()) { + return; + } + + // Deactivate any previous sub-levels, so that setting the georeference origin + // doesn't change their origin, too. + this->SubLevelSwitcher->SetTargetSubLevel(nullptr); + + // Update the georeference origin so that the new sub-level inherits it. + this->PlaceGeoreferenceOriginHere(); + + // Create a dummy Actor to add to the new sub-level, because + // CreateLevelInstanceFrom forbids an empty array for some reason. + TArray SubLevelActors; + + FActorSpawnParameters SpawnParameters{}; + SpawnParameters.NameMode = + FActorSpawnParameters::ESpawnActorNameMode::Requested; + SpawnParameters.Name = TEXT("Placeholder"); + SpawnParameters.ObjectFlags = RF_Transactional; + + AActor* PlaceholderActor = World->SpawnActor( + FVector::ZeroVector, + FRotator::ZeroRotator, + SpawnParameters); + PlaceholderActor->SetActorLabel(TEXT("Placeholder")); + + SubLevelActors.Add(PlaceholderActor); + + // Create the new Level Instance Actor and corresponding streaming level. + FNewLevelInstanceParams LevelInstanceParams{}; + LevelInstanceParams.PivotType = ELevelInstancePivotType::WorldOrigin; + LevelInstanceParams.Type = ELevelInstanceCreationType::LevelInstance; + LevelInstanceParams.SetExternalActors(false); + + ULevelInstanceSubsystem* LevelInstanceSubsystem = + World->GetSubsystem(); + AActor* LevelInstance = + Cast(LevelInstanceSubsystem->CreateLevelInstanceFrom( + SubLevelActors, + LevelInstanceParams)); + if (!IsValid(LevelInstance)) { + // User canceled creation of the sub-level, so delete the placeholder we + // created. + PlaceholderActor->Destroy(); + return; + } + + UCesiumSubLevelComponent* LevelComponent = + Cast(LevelInstance->AddComponentByClass( + UCesiumSubLevelComponent::StaticClass(), + false, + FTransform::Identity, + false)); + LevelComponent->SetFlags(RF_Transactional); + LevelInstance->AddInstanceComponent(LevelComponent); + + // Move the new level instance under the CesiumGeoreference. + LevelInstance->GetRootComponent()->SetMobility( + this->GetRootComponent()->Mobility); + LevelInstance->AttachToActor( + this, + FAttachmentTransformRules::KeepRelativeTransform); +} + +void ACesiumGeoreference::_showSubLevelLoadRadii() const { + UWorld* world = this->GetWorld(); + if (world->IsGameWorld()) { + return; + } + if (!this->ShowLoadRadii) { + return; + } + + for (const auto& pLevelWeak : + this->SubLevelSwitcher->GetRegisteredSubLevelsWeak()) { + ALevelInstance* pLevel = pLevelWeak.Get(); + if (!IsValid(pLevel)) + continue; + + UCesiumSubLevelComponent* pComponent = + pLevel->FindComponentByClass(); + + FVector center = + this->TransformLongitudeLatitudeHeightPositionToUnreal(FVector( + pComponent->GetOriginLongitude(), + pComponent->GetOriginLatitude(), + pComponent->GetOriginHeight())); + center = GetActorTransform().TransformPosition(center); + + DrawDebugSphere( + world, + center, + 100.0 * pComponent->GetLoadRadius() * GetActorScale3D().GetMax(), + 100, + FColor::Blue); + } +} +#endif // WITH_EDITOR + +bool ACesiumGeoreference::ShouldTickIfViewportsOnly() const { return true; } + +void ACesiumGeoreference::Tick(float DeltaTime) { + Super::Tick(DeltaTime); + +#if WITH_EDITOR + _showSubLevelLoadRadii(); +#endif +} + +void ACesiumGeoreference::Serialize(FArchive& Ar) { + Super::Serialize(Ar); + + Ar.UsingCustomVersion(FCesiumCustomVersion::GUID); + + // Recompute derived values on load. + if (Ar.IsLoading()) { + this->_updateCoordinateSystem(); + } +} + +void ACesiumGeoreference::BeginPlay() { + Super::BeginPlay(); + + PrimaryActorTick.TickGroup = TG_PrePhysics; + + UWorld* pWorld = this->GetWorld(); + if (!pWorld) { + UE_LOG( + LogCesium, + Warning, + TEXT("CesiumGeoreference does not have a World in BeginPlay.")); + return; + } + + UpdateGeoreference(); +} + +/** In case the CesiumGeoreference gets spawned at run time, instead of design + * time, ensure that frames are updated */ +void ACesiumGeoreference::OnConstruction(const FTransform& Transform) { + Super::OnConstruction(Transform); + + UE_LOG( + LogCesium, + Verbose, + TEXT("Called OnConstruction on actor %s"), + *this->GetName()); + + this->UpdateGeoreference(); +} + +void ACesiumGeoreference::PostLoad() { + Super::PostLoad(); + +#if WITH_EDITOR + if (GEditor && IsValid(this->GetWorld()) && + IsValid(this->GetWorld()->WorldComposition) && + !this->GetWorld()->IsGameWorld()) { + this->_createSubLevelsFromWorldComposition(); + } + + const int32 CesiumVersion = + this->GetLinkerCustomVersion(FCesiumCustomVersion::GUID); + + if (CesiumVersion < FCesiumCustomVersion::OriginShiftComponent && + !this->SubLevelSwitcher->GetRegisteredSubLevelsWeak().IsEmpty()) { + // In previous versions, the CesiumGeoreference managed origin shifting + // based on a SubLevelCamera, which defaulted to the PlayerCameraManager of + // the World's `GetFirstPlayerController()`. + + // Backward compatibility for this is tricky, but we can make a decent + // attempt that will work in a lot of cases. And this is just an unfortunate + // v2.0 breakage for any remaining cases. + + AActor* SubLevelActor = nullptr; + + if (this->SubLevelCamera_DEPRECATED) { + // An explicit SubLevelCamera_DEPRECATED is specified. If it has a target + // Actor, attach a CesiumOriginShiftComponent to that Actor. + SubLevelActor = this->SubLevelCamera_DEPRECATED->ViewTarget.Target.Get(); + + if (!SubLevelActor) { + UE_LOG( + LogCesium, + Warning, + TEXT("An explicit SubLevelCamera was specified on this " + "CesiumGeoreference, but its ViewTarget is not a valid " + "Actor, so a CesiumOriginShiftComponent could not be added " + "automatically. You must manually add a " + "CesiumOriginShiftComponent to the Actor whose position " + "should be used to control sub-level switching.")); + } + } else { + // No explicit SubLevelCamera_DEPRECATED, so try to find a Pawn set to + // auto-possess player 0. + for (TActorIterator it( + GetWorld(), + APawn::StaticClass(), + EActorIteratorFlags::SkipPendingKill); + it; + ++it) { + if (it->AutoPossessPlayer == EAutoReceiveInput::Player0) { + SubLevelActor = *it; + break; + } + } + + if (!SubLevelActor) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "Could not find a Pawn in the level set to auto-possess player " + "0, so a CesiumOriginShiftComponent could not be added " + "automatically. You must manually add a " + "CesiumOriginShiftComponent to the Actor whose position " + "should be used to control sub-level switching.")); + } + } + + if (SubLevelActor) { + // If this is a Blueprint object, like DynamicPawn, its construction + // scripts may not have been run yet at this point. Doing so might cause + // an origin shift component to be added. So we force it to happen here so + // that we don't end up adding a duplicate CesiumOriginShiftComponent. + SubLevelActor->RerunConstructionScripts(); + if (SubLevelActor->FindComponentByClass() == + nullptr) { + + UCesiumOriginShiftComponent* OriginShift = + Cast( + SubLevelActor->AddComponentByClass( + UCesiumOriginShiftComponent::StaticClass(), + false, + FTransform::Identity, + false)); + OriginShift->SetFlags(RF_Transactional); + SubLevelActor->AddInstanceComponent(OriginShift); + + UE_LOG( + LogCesium, + Warning, + TEXT("Added CesiumOriginShiftComponent to %s in order to preserve " + "backward compatibility for sub-level switching."), + *SubLevelActor->GetName()); + } + } + } +#endif // WITH_EDITOR +} + +#if WITH_EDITOR +void ACesiumGeoreference::PostEditChangeProperty(FPropertyChangedEvent& event) { + Super::PostEditChangeProperty(event); + + if (!event.Property) { + return; + } + + FName propertyName = event.Property->GetFName(); + + CESIUM_POST_EDIT_CHANGE(propertyName, ACesiumGeoreference, OriginPlacement); + CESIUM_POST_EDIT_CHANGE(propertyName, ACesiumGeoreference, OriginLongitude); + CESIUM_POST_EDIT_CHANGE(propertyName, ACesiumGeoreference, OriginLatitude); + CESIUM_POST_EDIT_CHANGE(propertyName, ACesiumGeoreference, OriginHeight); + CESIUM_POST_EDIT_CHANGE(propertyName, ACesiumGeoreference, Scale); + CESIUM_POST_EDIT_CHANGE(propertyName, ACesiumGeoreference, Ellipsoid); +} + +namespace { + +template +FString longPackageNameToCesiumName(UWorld* pWorld, const TStringish& name) { + FString levelName = FPackageName::GetShortName(name); + levelName.RemoveFromStart(pWorld->StreamingLevelsPrefix); + return levelName; +} + +} // namespace + +PRAGMA_DISABLE_DEPRECATION_WARNINGS +void ACesiumGeoreference::_createSubLevelsFromWorldComposition() { + UWorld* pWorld = this->GetWorld(); + if (!IsValid(pWorld)) { + // This happens for the georeference that is shown in the + // content browser. Might omit this message. + UE_LOG( + LogCesium, + Verbose, + TEXT( + "Georeference is not spawned in world: %s, skipping _updateCesiumSubLevels"), + *this->GetFullName()); + return; + } + + if (this->CesiumSubLevels_DEPRECATED.IsEmpty() || + !this->GetLevel()->IsPersistentLevel()) + return; + + this->Modify(); + + // Convert old-style sub-levels (using World Composition) to new style + // sub-levels (level instances) + UWorldComposition::FTilesList& allLevels = + pWorld->WorldComposition->GetTilesList(); + + ALevelInstance* pActiveSubLevel = nullptr; + + for (const FWorldCompositionTile& level : allLevels) { + FString levelName = longPackageNameToCesiumName(pWorld, level.PackageName); + + // Check if the level is already known + FCesiumSubLevel* pFound = this->CesiumSubLevels_DEPRECATED.FindByPredicate( + [&levelName](FCesiumSubLevel& subLevel) { + return levelName.Equals(subLevel.LevelName); + }); + + // A sub-level that can't be enabled is being controlled by Unreal Engine, + // based on its own distance-based system. Ignore it. + if (pFound == nullptr || !pFound->CanBeEnabled) + continue; + + FActorSpawnParameters spawnParameters{}; + spawnParameters.Name = FName(pFound->LevelName); + spawnParameters.NameMode = + FActorSpawnParameters::ESpawnActorNameMode::Requested; + spawnParameters.ObjectFlags = RF_Transactional; + + ALevelInstance* pLevelInstance = pWorld->SpawnActor( + FVector::ZeroVector, + FRotator::ZeroRotator, + spawnParameters); + pLevelInstance->SetIsSpatiallyLoaded(false); + pLevelInstance->DesiredRuntimeBehavior = + ELevelInstanceRuntimeBehavior::LevelStreaming; + pLevelInstance->SetActorLabel(pFound->LevelName); + + FString levelPath = level.PackageName.ToString() + "." + + FPackageName::GetShortName(level.PackageName); + TSoftObjectPtr asset{FSoftObjectPath(levelPath)}; + pLevelInstance->SetWorldAsset(asset); + + // Initially mark all sub-levels hidden in the Editor. + pLevelInstance->SetIsTemporarilyHiddenInEditor(true); + + UCesiumSubLevelComponent* pLevelComponent = + Cast(pLevelInstance->AddComponentByClass( + UCesiumSubLevelComponent::StaticClass(), + false, + FTransform::Identity, + false)); + pLevelComponent->SetFlags(RF_Transactional); + pLevelInstance->AddInstanceComponent(pLevelComponent); + + pLevelComponent->SetOriginLongitudeLatitudeHeight(FVector( + pFound->LevelLongitude, + pFound->LevelLatitude, + pFound->LevelHeight)); + pLevelComponent->SetEnabled(pFound->Enabled); + pLevelComponent->SetLoadRadius(pFound->LoadRadius); + + // But if the georeference origin is close to this sub-level's origin, + // make this the active sub-level. + if (FMath::IsNearlyEqual( + this->OriginLongitude, + pFound->LevelLongitude, + 1e-8) && + FMath::IsNearlyEqual( + this->OriginLatitude, + pFound->LevelLatitude, + 1e-8) && + FMath::IsNearlyEqual(this->OriginHeight, pFound->LevelHeight, 1e-3)) { + pActiveSubLevel = pLevelInstance; + } + + pLevelInstance->LoadLevelInstance(); + } + + this->SubLevelSwitcher->SetTargetSubLevel(pActiveSubLevel); + + this->CesiumSubLevels_DEPRECATED.Empty(); + + UE_LOG( + LogCesium, + Warning, + TEXT( + "Cesium sub-levels based on World Composition have been converted to Level Instances. Save the level to keep these changes. We recommend disabling World Composition in the World Settings, as it is now obsolete.")); +} +PRAGMA_ENABLE_DEPRECATION_WARNINGS +#endif // WITH_EDITOR + +FVector ACesiumGeoreference::TransformLongitudeLatitudeHeightToEcef( + const FVector& longitudeLatitudeHeight) const { + return this->GetEllipsoid() + ->LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + longitudeLatitudeHeight); +} + +FVector ACesiumGeoreference::TransformEcefToLongitudeLatitudeHeight( + const FVector& ecef) const { + return this->GetEllipsoid() + ->EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight(ecef); +} + +FMatrix +ACesiumGeoreference::ComputeEastNorthUpToEcef(const FVector& ecef) const { + return this->GetEllipsoid()->EastNorthUpToEllipsoidCenteredEllipsoidFixed( + ecef); +} + +ACesiumGeoreference::ACesiumGeoreference() : AActor() { + struct FConstructorStatics { + ConstructorHelpers::FObjectFinder DefaultEllipsoid; + + FConstructorStatics() + : DefaultEllipsoid(TEXT( + "/Script/CesiumRuntime.CesiumEllipsoid'/CesiumForUnreal/WGS84.WGS84'")) { + + } + }; + + static FConstructorStatics ConstructorStatics; + this->Ellipsoid = ConstructorStatics.DefaultEllipsoid.Object; + + PrimaryActorTick.bCanEverTick = true; + + this->Root = CreateDefaultSubobject(TEXT("Root")); + this->RootComponent = this->Root; + +#if WITH_EDITOR + this->SetIsSpatiallyLoaded(false); +#endif + this->SubLevelSwitcher = + CreateDefaultSubobject( + "SubLevelSwitcher"); +} + +void ACesiumGeoreference::UpdateGeoreference() { + this->_updateCoordinateSystem(); + + // If we're in a sub-level, update its origin as well. + UCesiumSubLevelSwitcherComponent* pSwitcher = this->SubLevelSwitcher; + if (IsValid(pSwitcher) && pSwitcher->GetTargetSubLevel() != nullptr) { + if (pSwitcher->GetTargetSubLevel() == pSwitcher->GetCurrentSubLevel() || + pSwitcher->GetCurrentSubLevel() == nullptr) { + ALevelInstance* pTarget = pSwitcher->GetTargetSubLevel(); + UCesiumSubLevelComponent* pComponent = + pTarget->FindComponentByClass(); + if (IsValid(pComponent)) { + pComponent->SetOriginLongitudeLatitudeHeight(FVector( + this->OriginLongitude, + this->OriginLatitude, + this->OriginHeight)); + } + } + } + + UE_LOG( + LogCesium, + Verbose, + TEXT("Broadcasting OnGeoreferenceUpdated for Georeference %s"), + *this->GetFullName()); + + OnGeoreferenceUpdated.Broadcast(); +} + +GeoTransforms ACesiumGeoreference::GetGeoTransforms() const noexcept { + // Because GeoTransforms is deprecated, we only lazily update it. + return GeoTransforms( + this->GetEllipsoid()->GetNativeEllipsoid(), + glm::dvec3(this->_coordinateSystem.getLocalToEcefTransformation()[3]), + this->GetScale() / 100.0); +} + +FName ACesiumGeoreference::DEFAULT_GEOREFERENCE_TAG = + FName("DEFAULT_GEOREFERENCE"); + +void ACesiumGeoreference::_updateCoordinateSystem() { + if (this->OriginPlacement == EOriginPlacement::CartographicOrigin) { + FVector origin = this->GetOriginLongitudeLatitudeHeight(); + this->_coordinateSystem = this->GetEllipsoid()->CreateCoordinateSystem( + this->GetOriginEarthCenteredEarthFixed(), + this->GetScale()); + } else { + // In True Origin mode, we want a coordinate system that: + // 1. Is at the origin, + // 2. Inverts Y to create a left-handed coordinate system, and + // 3. Uses the georeference's scale + double scale = 1.0 / this->GetScale(); + glm::dmat4 localToEcef( + glm::dvec4(scale, 0.0, 0.0, 0.0), + glm::dvec4(0.0, -scale, 0.0, 0.0), + glm::dvec4(0.0, 0.0, scale, 0.0), + glm::dvec4(0.0, 0.0, 0.0, 1.0)); + this->_coordinateSystem = LocalHorizontalCoordinateSystem(localToEcef); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGlobeAnchorComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGlobeAnchorComponent.cpp new file mode 100644 index 0000000..055d656 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGlobeAnchorComponent.cpp @@ -0,0 +1,793 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumCustomVersion.h" +#include "CesiumGeometry/Transforms.h" +#include "CesiumGeoreference.h" +#include "CesiumRuntime.h" +#include "CesiumWgs84Ellipsoid.h" +#include "Components/SceneComponent.h" +#include "GameFramework/Actor.h" +#include "VecMath.h" +#include + +// quick macro for ellipsoid existence check +#define ELLIPSOID_CHECK(thiz, ret) \ + if (!IsValid(thiz->GetEllipsoid())) { \ + UE_LOG(LogCesium, Error, TEXT("Expected ellipsoid but got nullptr")); \ + return ret; \ + } + +// These are the "changes" that can happen to this component, how it detects +// them, and what it does about them: +// +// ## Actor Transform Changed +// +// * Detected by subscribing to the `TransformUpdated` event of the root +// component of the Actor to which this component is attached. The subscription +// is added in `OnRegister` and removed in `OnUnregister`. +// * Updates the ECEF transform from the new Actor transform. +// * If `AdjustOrientationForGlobeWhenMoving` is enabled, also applies a +// rotation based on the change in surface normal. +// +// ## Globe (ECEF) Position Changed +// +// * Happens when MoveToECEF (or similar) is called explicitly, or position +// properties are changed in the Editor. +// * Updates the Actor transform from the new ECEF transform. +// * If `AdjustOrientationForGlobeWhenMoving` is enabled, also applies a +// rotation based on the change in surface normal. +// +// ## Georeference Changed +// +// * Detected by subscribing to the `GeoreferenceUpdated` event. The +// subscription is added when a new Georeference is resolved in +// `ResolveGeoreference` (in `OnRegister` at the latest) and removed in +// `InvalidateResolvedGeoreference` (in `OnUnregister` and when the +// Georeference property is changed). +// * Updates the Actor transform from the existing ECEF transform. +// * Ignores `AdjustOrientationForGlobeWhenMoving` because the globe position is +// not changing. +// +// ## OriginLocation Changed +// +// * Handled by Unreal's normal `ApplyWorldOffset` mechanism. + +namespace { + +CesiumGeospatial::GlobeAnchor +createNativeGlobeAnchor(const FMatrix& actorToECEF) { + return CesiumGeospatial::GlobeAnchor(VecMath::createMatrix4D(actorToECEF)); +} + +} // namespace + +TSoftObjectPtr +UCesiumGlobeAnchorComponent::GetGeoreference() const { + return this->Georeference; +} + +void UCesiumGlobeAnchorComponent::SetGeoreference( + TSoftObjectPtr NewGeoreference) { + ACesiumGeoreference* pOriginal = this->ResolvedGeoreference; + + if (IsValid(pOriginal)) { + pOriginal->OnGeoreferenceUpdated.RemoveAll(this); + } + + this->ResolvedGeoreference = nullptr; + this->Georeference = NewGeoreference; + + // If this component is currently registered, we need to re-resolve the + // georeference. If it's not, this will happen when it becomes registered. + if (this->IsRegistered()) { + this->ResolveGeoreference(); + } +} + +ACesiumGeoreference* +UCesiumGlobeAnchorComponent::GetResolvedGeoreference() const { + return this->ResolvedGeoreference; +} + +FVector +UCesiumGlobeAnchorComponent::GetEarthCenteredEarthFixedPosition() const { + if (!this->_actorToECEFIsValid) { + // Only log a warning if we're actually in a world. Otherwise we'll spam the + // log when editing a CDO. + if (this->GetWorld()) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "CesiumGlobeAnchorComponent %s globe position is invalid because the component is not yet registered."), + *this->GetName()); + } + return FVector(0.0); + } + + return this->ActorToEarthCenteredEarthFixedMatrix.GetOrigin(); +} + +FMatrix +UCesiumGlobeAnchorComponent::GetActorToEarthCenteredEarthFixedMatrix() const { + if (!this->_actorToECEFIsValid) { + const_cast(this) + ->_setNewActorToECEFFromRelativeTransform(); + } + + return this->ActorToEarthCenteredEarthFixedMatrix; +} + +void UCesiumGlobeAnchorComponent::SetActorToEarthCenteredEarthFixedMatrix( + const FMatrix& Value) { + // This method is equivalent to + // CesiumGlobeAnchorImpl::SetNewLocalToGlobeFixedMatrix in Cesium for Unity. + USceneComponent* pOwnerRoot = this->_getRootComponent(/*warnIfNull*/ true); + if (!IsValid(pOwnerRoot)) { + return; + } + + // Update with the new ECEF transform, also rotating based on the new position + // if desired. + CesiumGeospatial::GlobeAnchor nativeAnchor = + this->_createOrUpdateNativeGlobeAnchorFromECEF(Value); + this->_updateFromNativeGlobeAnchor(nativeAnchor); + +#if WITH_EDITOR + // In the Editor, mark this component and the root component modified so Undo + // works properly. + this->Modify(); + pOwnerRoot->Modify(); +#endif +} + +bool UCesiumGlobeAnchorComponent::GetTeleportWhenUpdatingTransform() const { + return this->TeleportWhenUpdatingTransform; +} + +void UCesiumGlobeAnchorComponent::SetTeleportWhenUpdatingTransform(bool Value) { + this->TeleportWhenUpdatingTransform = Value; +} + +bool UCesiumGlobeAnchorComponent::GetAdjustOrientationForGlobeWhenMoving() + const { + return this->AdjustOrientationForGlobeWhenMoving; +} + +void UCesiumGlobeAnchorComponent::SetAdjustOrientationForGlobeWhenMoving( + bool Value) { + this->AdjustOrientationForGlobeWhenMoving = Value; +} + +void UCesiumGlobeAnchorComponent::MoveToEarthCenteredEarthFixedPosition( + const FVector& TargetEcef) { + if (!this->_actorToECEFIsValid) + this->_setNewActorToECEFFromRelativeTransform(); + FMatrix newMatrix = this->ActorToEarthCenteredEarthFixedMatrix; + newMatrix.SetOrigin(TargetEcef); + this->SetActorToEarthCenteredEarthFixedMatrix(newMatrix); +} + +void UCesiumGlobeAnchorComponent::SnapLocalUpToEllipsoidNormal() { + if (!this->_actorToECEFIsValid || !IsValid(this->ResolvedGeoreference)) { + UE_LOG( + LogCesium, + Error, + TEXT( + "CesiumGlobeAnchorComponent %s globe orientation cannot be changed because the component is not yet registered."), + *this->GetName()); + return; + } + + ELLIPSOID_CHECK(this->ResolveGeoreference(), ); + + UCesiumEllipsoid* ellipsoid = this->ResolveGeoreference()->GetEllipsoid(); + + // Compute the current local up axis of the actor (the +Z axis) in ECEF + FVector up = this->ActorToEarthCenteredEarthFixedMatrix.GetUnitAxis(EAxis::Z); + + // Compute the surface normal of the ellipsoid + FVector ellipsoidNormal = ellipsoid->GeodeticSurfaceNormal( + this->GetEarthCenteredEarthFixedPosition()); + + // Find the shortest rotation to align local up with the ellipsoid normal + FMatrix alignmentRotation = + FQuat::FindBetween(up, ellipsoidNormal).ToMatrix(); + + // Apply the new rotation to the Actor->ECEF transform. + // Note that FMatrix multiplication order is opposite glm::dmat4 + // multiplication order! + FMatrix newActorToECEF = + this->ActorToEarthCenteredEarthFixedMatrix * alignmentRotation; + + // We don't want to rotate the origin, though, so re-set it. + newActorToECEF.SetOrigin( + this->ActorToEarthCenteredEarthFixedMatrix.GetOrigin()); + + this->_updateFromNativeGlobeAnchor(createNativeGlobeAnchor(newActorToECEF)); + +#if WITH_EDITOR + // In the Editor, mark this component modified so Undo works properly. + this->Modify(); +#endif +} + +void UCesiumGlobeAnchorComponent::SnapToEastSouthUp() { + this->SetEastSouthUpRotation(FQuat::Identity); + +#if WITH_EDITOR + // In the Editor, mark this component modified so Undo works properly. + this->Modify(); +#endif +} + +void UCesiumGlobeAnchorComponent::Sync() { + // If we don't have a actor -> ECEF matrix yet, we must update from the + // actor's root transform. + bool updateFromTransform = !this->_actorToECEFIsValid; + if (!updateFromTransform && this->_lastRelativeTransformIsValid) { + // We may also need to update from the Transform if it has changed + // since the last time we computed the local -> globe fixed matrix. + updateFromTransform = !this->_lastRelativeTransform.Equals( + this->_getCurrentRelativeTransform(), + 0.0); + } + + if (updateFromTransform) { + this->_setNewActorToECEFFromRelativeTransform(); + } else { + this->SetActorToEarthCenteredEarthFixedMatrix( + this->ActorToEarthCenteredEarthFixedMatrix); + } +} + +ACesiumGeoreference* +UCesiumGlobeAnchorComponent::ResolveGeoreference(bool bForceReresolve) { + if (IsValid(this->ResolvedGeoreference) && !bForceReresolve) { + return this->ResolvedGeoreference; + } + + ACesiumGeoreference* Previous = this->ResolvedGeoreference; + ACesiumGeoreference* Next = + IsValid(this->Georeference.Get()) + ? this->ResolvedGeoreference = this->Georeference.Get() + : ACesiumGeoreference::GetDefaultGeoreferenceForActor( + this->GetOwner()); + + if (Previous != Next) { + if (IsValid(Previous)) { + // If we previously had a valid georeference, first synchronize using the + // old one so that the ECEF and Actor transforms are both up-to-date. + this->Sync(); + + Previous->OnGeoreferenceUpdated.RemoveAll(this); + } + + this->ResolvedGeoreference = Next; + + if (this->ResolvedGeoreference) { + this->ResolvedGeoreference->OnGeoreferenceUpdated.AddUniqueDynamic( + this, + &UCesiumGlobeAnchorComponent::_onGeoreferenceChanged); + + // Now synchronize based on the new georeference. + this->Sync(); + } + } + + return this->ResolvedGeoreference; +} + +UCesiumEllipsoid* UCesiumGlobeAnchorComponent::GetEllipsoid() const { + ACesiumGeoreference* Georeference = this->GetResolvedGeoreference(); + if (!IsValid(Georeference)) { + Georeference = + ACesiumGeoreference::GetDefaultGeoreferenceForActor(this->GetOwner()); + } + + if (!IsValid(Georeference)) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Unable to find UCesiumGeoreference for UCesiumGlobeAnchorComponent - returning unit ellipsoid.")); + return UCesiumEllipsoid::Create(FVector::OneVector); + } + + return Georeference->GetEllipsoid(); +} + +void UCesiumGlobeAnchorComponent::InvalidateResolvedGeoreference() { + // This method is deprecated and no longer does anything. +} + +FVector UCesiumGlobeAnchorComponent::GetLongitudeLatitudeHeight() const { + ELLIPSOID_CHECK(this, FVector::ZeroVector); + return this->GetEllipsoid() + ->EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight( + this->GetEarthCenteredEarthFixedPosition()); +} + +void UCesiumGlobeAnchorComponent::MoveToLongitudeLatitudeHeight( + const FVector& TargetLongitudeLatitudeHeight) { + ELLIPSOID_CHECK(this, ); + this->MoveToEarthCenteredEarthFixedPosition( + this->GetEllipsoid() + ->LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + TargetLongitudeLatitudeHeight)); +} + +namespace { + +CesiumGeospatial::LocalHorizontalCoordinateSystem createEastSouthUp( + const CesiumGeospatial::GlobeAnchor& anchor, + const CesiumGeospatial::Ellipsoid& ellipsoid) { + glm::dvec3 ecefPosition; + CesiumGeometry::Transforms::computeTranslationRotationScaleFromMatrix( + anchor.getAnchorToFixedTransform(), + &ecefPosition, + nullptr, + nullptr); + + return CesiumGeospatial::LocalHorizontalCoordinateSystem( + ecefPosition, + CesiumGeospatial::LocalDirection::East, + CesiumGeospatial::LocalDirection::South, + CesiumGeospatial::LocalDirection::Up, + 1.0, + ellipsoid); +} + +} // namespace + +FQuat UCesiumGlobeAnchorComponent::GetEastSouthUpRotation() const { + if (!this->_actorToECEFIsValid) { + // Only log a warning if we're actually in a world. Otherwise we'll spam the + // log when editing a CDO. + if (this->GetWorld()) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Cannot get the rotation from CesiumGlobeAnchorComponent %s because the component is not yet registered or does not have a valid CesiumGeoreference."), + *this->GetName()); + } + return FQuat::Identity; + } + + ELLIPSOID_CHECK(this, FQuat::Identity); + + CesiumGeospatial::GlobeAnchor anchor( + VecMath::createMatrix4D(this->ActorToEarthCenteredEarthFixedMatrix)); + + CesiumGeospatial::LocalHorizontalCoordinateSystem eastSouthUp = + createEastSouthUp(anchor, this->GetEllipsoid()->GetNativeEllipsoid()); + + glm::dmat4 modelToEastSouthUp = anchor.getAnchorToLocalTransform(eastSouthUp); + + glm::dquat rotationToEastSouthUp; + CesiumGeometry::Transforms::computeTranslationRotationScaleFromMatrix( + modelToEastSouthUp, + nullptr, + &rotationToEastSouthUp, + nullptr); + return VecMath::createQuaternion(rotationToEastSouthUp); +} + +void UCesiumGlobeAnchorComponent::SetEastSouthUpRotation( + const FQuat& EastSouthUpRotation) { + if (!this->_actorToECEFIsValid) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Cannot set the rotation on CesiumGlobeAnchorComponent %s because the component is not yet registered or does not have a valid CesiumGeoreference."), + *this->GetName()); + return; + } + + ELLIPSOID_CHECK(this, ); + + CesiumGeospatial::GlobeAnchor anchor( + VecMath::createMatrix4D(this->ActorToEarthCenteredEarthFixedMatrix)); + + CesiumGeospatial::LocalHorizontalCoordinateSystem eastSouthUp = + createEastSouthUp(anchor, this->GetEllipsoid()->GetNativeEllipsoid()); + + glm::dmat4 modelToEastSouthUp = anchor.getAnchorToLocalTransform(eastSouthUp); + + glm::dvec3 translation; + glm::dvec3 scale; + CesiumGeometry::Transforms::computeTranslationRotationScaleFromMatrix( + modelToEastSouthUp, + &translation, + nullptr, + &scale); + + glm::dmat4 newModelToEastSouthUp = + CesiumGeometry::Transforms::createTranslationRotationScaleMatrix( + translation, + VecMath::createQuaternion(EastSouthUpRotation), + scale); + + const CesiumGeospatial::Ellipsoid& ellipsoid = + this->ResolveGeoreference()->GetEllipsoid()->GetNativeEllipsoid(); + + anchor.setAnchorToLocalTransform( + eastSouthUp, + newModelToEastSouthUp, + false, + ellipsoid); + this->_updateFromNativeGlobeAnchor(anchor); +} + +FQuat UCesiumGlobeAnchorComponent::GetEarthCenteredEarthFixedRotation() const { + if (!this->_actorToECEFIsValid) { + // Only log a warning if we're actually in a world. Otherwise we'll spam the + // log when editing a CDO. + if (this->GetWorld()) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Cannot get the rotation from CesiumGlobeAnchorComponent %s because the component is not yet registered or does not have a valid CesiumGeoreference."), + *this->GetName()); + } + return FQuat::Identity; + } + + glm::dquat rotationToEarthCenteredEarthFixed; + CesiumGeometry::Transforms::computeTranslationRotationScaleFromMatrix( + VecMath::createMatrix4D(this->ActorToEarthCenteredEarthFixedMatrix), + nullptr, + &rotationToEarthCenteredEarthFixed, + nullptr); + return VecMath::createQuaternion(rotationToEarthCenteredEarthFixed); +} + +void UCesiumGlobeAnchorComponent::SetEarthCenteredEarthFixedRotation( + const FQuat& EarthCenteredEarthFixedRotation) { + if (!this->_actorToECEFIsValid) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Cannot set the rotation on CesiumGlobeAnchorComponent %s because the component is not yet registered or does not have a valid CesiumGeoreference."), + *this->GetName()); + return; + } + + glm::dvec3 translation; + glm::dvec3 scale; + CesiumGeometry::Transforms::computeTranslationRotationScaleFromMatrix( + VecMath::createMatrix4D(this->ActorToEarthCenteredEarthFixedMatrix), + &translation, + nullptr, + &scale); + + glm::dmat4 newModelToEarthCenteredEarthFixed = + CesiumGeometry::Transforms::createTranslationRotationScaleMatrix( + translation, + VecMath::createQuaternion(EarthCenteredEarthFixedRotation), + scale); + + this->ActorToEarthCenteredEarthFixedMatrix = + VecMath::createMatrix(newModelToEarthCenteredEarthFixed); +} + +void UCesiumGlobeAnchorComponent::Serialize(FArchive& Ar) { + Super::Serialize(Ar); + + Ar.UsingCustomVersion(FCesiumCustomVersion::GUID); + + const int32 CesiumVersion = Ar.CustomVer(FCesiumCustomVersion::GUID); + + if (CesiumVersion < FCesiumCustomVersion::GeoreferenceRefactoring) { + // In previous versions, there was no _actorToECEFIsValid flag. But we can + // assume that the previously-stored ECEF transform was valid. + this->_actorToECEFIsValid = true; + } + +#if WITH_EDITORONLY_DATA + if (CesiumVersion < + FCesiumCustomVersion::GlobeAnchorTransformationAsFMatrix) { + memcpy( + this->ActorToEarthCenteredEarthFixedMatrix.M, + this->_actorToECEF_Array_DEPRECATED, + sizeof(double) * 16); + } +#endif +} + +void UCesiumGlobeAnchorComponent::OnComponentCreated() { + Super::OnComponentCreated(); + this->_actorToECEFIsValid = false; +} + +#if WITH_EDITOR +void UCesiumGlobeAnchorComponent::PostEditChangeProperty( + FPropertyChangedEvent& PropertyChangedEvent) { + if (PropertyChangedEvent.Property) { + FName propertyName = PropertyChangedEvent.Property->GetFName(); + + if (propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorComponent, Georeference)) { + this->SetGeoreference(this->Georeference); + } + } + + // Call the base class implementation last, because it will call OnRegister, + // which will call Sync. So we need to apply the updated values first. + Super::PostEditChangeProperty(PropertyChangedEvent); + + // Calling the Super implementation above shouldn't change the current + // relative transform without also changing _lastRelativeTransform. Except it + // can, because in some cases (e.g., on undo/redo), Unreal reruns the Actor's + // construction scripts, which can cause the relative transform to be + // recomputed from the world transform. That's a problem because later we'll + // think the relative transform has changed and will recompute the globe + // transform from it. So we set (again) the _lastRelativeTransform here. + // + // One possible danger is that the construction script _intentionally_ changes + // the transform. But we can't reliably distinguish that case from a phantom + // transform "change" caused by converting to a world transform and back. And + // surely something dodgy would be happening if something _other_ than the + // globe anchor were intentionally moving the Actor in the globe anchor's + // PostEditChangeProperty, right? + if (this->_lastRelativeTransformIsValid) { + this->_lastRelativeTransform = this->_getCurrentRelativeTransform(); + } +} +#endif + +void UCesiumGlobeAnchorComponent::OnRegister() { + Super::OnRegister(); + + const AActor* pOwner = this->GetOwner(); + if (!IsValid(pOwner)) { + UE_LOG( + LogCesium, + Warning, + TEXT("CesiumGlobeAnchorComponent %s does not have a valid owner"), + *this->GetName()); + return; + } + + USceneComponent* pOwnerRoot = pOwner->GetRootComponent(); + if (pOwnerRoot) { + pOwnerRoot->TransformUpdated.AddUObject( + this, + &UCesiumGlobeAnchorComponent::_onActorTransformChanged); + } + + this->ResolveGeoreference(); +} + +void UCesiumGlobeAnchorComponent::OnUnregister() { + Super::OnUnregister(); + + // Unsubscribe from the ResolvedGeoreference. + if (IsValid(this->ResolvedGeoreference)) { + this->ResolvedGeoreference->OnGeoreferenceUpdated.RemoveAll(this); + } + this->ResolvedGeoreference = nullptr; + + // Unsubscribe from the TransformUpdated event. + const AActor* pOwner = this->GetOwner(); + if (!IsValid(pOwner)) { + UE_LOG( + LogCesium, + Warning, + TEXT("CesiumGlobeAnchorComponent %s does not have a valid owner"), + *this->GetName()); + return; + } + + USceneComponent* pOwnerRoot = pOwner->GetRootComponent(); + if (pOwnerRoot) { + pOwnerRoot->TransformUpdated.RemoveAll(this); + } +} + +CesiumGeospatial::GlobeAnchor +UCesiumGlobeAnchorComponent::_createNativeGlobeAnchor() const { + return createNativeGlobeAnchor(this->ActorToEarthCenteredEarthFixedMatrix); +} + +USceneComponent* +UCesiumGlobeAnchorComponent::_getRootComponent(bool warnIfNull) const { + const AActor* pOwner = this->GetOwner(); + if (!IsValid(pOwner)) { + if (warnIfNull) { + UE_LOG( + LogCesium, + Warning, + TEXT("UCesiumGlobeAnchorComponent %s does not have a valid owner."), + *this->GetName()); + } + return nullptr; + } + + USceneComponent* pOwnerRoot = pOwner->GetRootComponent(); + if (!IsValid(pOwnerRoot)) { + if (warnIfNull) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "The owner of UCesiumGlobeAnchorComponent %s does not have a valid root component."), + *this->GetName()); + } + return nullptr; + } + + return pOwnerRoot; +} + +FTransform UCesiumGlobeAnchorComponent::_getCurrentRelativeTransform() const { + const USceneComponent* pOwnerRoot = this->_getRootComponent(true); + return pOwnerRoot->GetRelativeTransform(); +} + +void UCesiumGlobeAnchorComponent::_setCurrentRelativeTransform( + const FTransform& relativeTransform) { + AActor* pOwner = this->GetOwner(); + if (!IsValid(pOwner)) { + UE_LOG( + LogCesium, + Warning, + TEXT("UCesiumGlobeAnchorComponent %s does not have a valid owner"), + *this->GetName()); + return; + } + + USceneComponent* pOwnerRoot = pOwner->GetRootComponent(); + if (!IsValid(pOwnerRoot)) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "The owner of UCesiumGlobeAnchorComponent %s does not have a valid root component"), + *this->GetName()); + return; + } + + // Set the new Actor relative transform, taking care not to do this + // recursively. + this->_updatingActorTransform = true; + pOwnerRoot->SetRelativeTransform( + relativeTransform, + false, + nullptr, + this->TeleportWhenUpdatingTransform ? ETeleportType::TeleportPhysics + : ETeleportType::None); + this->_updatingActorTransform = false; + + this->_lastRelativeTransform = this->_getCurrentRelativeTransform(); + this->_lastRelativeTransformIsValid = true; +} + +CesiumGeospatial::GlobeAnchor UCesiumGlobeAnchorComponent:: + _createOrUpdateNativeGlobeAnchorFromRelativeTransform( + const FTransform& newRelativeTransform) { + ACesiumGeoreference* pGeoreference = this->ResolvedGeoreference; + assert(pGeoreference != nullptr); + + const CesiumGeospatial::LocalHorizontalCoordinateSystem& local = + pGeoreference->GetCoordinateSystem(); + + glm::dmat4 newModelToLocal = + VecMath::createMatrix4D(newRelativeTransform.ToMatrixWithScale()); + + if (!this->_actorToECEFIsValid) { + // Create a new anchor initialized at the new position, because there is no + // old one. + return CesiumGeospatial::GlobeAnchor::fromAnchorToLocalTransform( + local, + newModelToLocal); + } else { + assert(this->GetEllipsoid() != nullptr); + // Create an anchor at the old position and move it to the new one. + CesiumGeospatial::GlobeAnchor cppAnchor = this->_createNativeGlobeAnchor(); + cppAnchor.setAnchorToLocalTransform( + local, + newModelToLocal, + this->AdjustOrientationForGlobeWhenMoving, + this->GetEllipsoid()->GetNativeEllipsoid()); + return cppAnchor; + } +} + +CesiumGeospatial::GlobeAnchor +UCesiumGlobeAnchorComponent::_createOrUpdateNativeGlobeAnchorFromECEF( + const FMatrix& newActorToECEFMatrix) { + if (!this->_actorToECEFIsValid) { + // Create a new anchor initialized at the new position, because there is no + // old one. + return CesiumGeospatial::GlobeAnchor( + VecMath::createMatrix4D(newActorToECEFMatrix)); + } else { + assert(this->GetEllipsoid() != nullptr); + // Create an anchor at the old position and move it to the new one. + CesiumGeospatial::GlobeAnchor cppAnchor( + VecMath::createMatrix4D(this->ActorToEarthCenteredEarthFixedMatrix)); + cppAnchor.setAnchorToFixedTransform( + VecMath::createMatrix4D(newActorToECEFMatrix), + this->AdjustOrientationForGlobeWhenMoving, + this->GetEllipsoid()->GetNativeEllipsoid()); + return cppAnchor; + } +} + +void UCesiumGlobeAnchorComponent::_updateFromNativeGlobeAnchor( + const CesiumGeospatial::GlobeAnchor& nativeAnchor) { + this->ActorToEarthCenteredEarthFixedMatrix = + VecMath::createMatrix(nativeAnchor.getAnchorToFixedTransform()); + this->_actorToECEFIsValid = true; + + // Update the Unreal relative transform + ACesiumGeoreference* pGeoreference = this->ResolveGeoreference(); + if (IsValid(pGeoreference)) { + glm::dmat4 anchorToLocal = nativeAnchor.getAnchorToLocalTransform( + pGeoreference->GetCoordinateSystem()); + + this->_setCurrentRelativeTransform( + FTransform(VecMath::createMatrix(anchorToLocal))); + } else { + this->_lastRelativeTransformIsValid = false; + } +} + +void UCesiumGlobeAnchorComponent::_onActorTransformChanged( + USceneComponent* InRootComponent, + EUpdateTransformFlags UpdateTransformFlags, + ETeleportType Teleport) { + if (this->_updatingActorTransform) { + return; + } + + this->_setNewActorToECEFFromRelativeTransform(); +} + +void UCesiumGlobeAnchorComponent::_setNewActorToECEFFromRelativeTransform() { + // This method is equivalent to + // CesiumGlobeAnchorImpl::SetNewLocalToGlobeFixedMatrixFromTransform in Cesium + // for Unity. + ACesiumGeoreference* pGeoreference = this->ResolveGeoreference(); + if (!IsValid(pGeoreference)) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "CesiumGlobeAnchorComponent %s cannot update globe transform from actor transform because there is no valid Georeference."), + *this->GetName()); + return; + } + + USceneComponent* pOwnerRoot = this->_getRootComponent(/*warnIfNull*/ true); + if (!IsValid(pOwnerRoot)) { + return; + } + + // Update with the new local transform, also rotating based on the new + // position if desired. + FTransform modelToLocal = this->_getCurrentRelativeTransform(); + CesiumGeospatial::GlobeAnchor cppAnchor = + this->_createOrUpdateNativeGlobeAnchorFromRelativeTransform(modelToLocal); + this->_updateFromNativeGlobeAnchor(cppAnchor); + +#if WITH_EDITOR + // In the Editor, mark this component and the root component modified so Undo + // works properly. + this->Modify(); + pOwnerRoot->Modify(); +#endif +} + +void UCesiumGlobeAnchorComponent::_onGeoreferenceChanged() { + if (this->_actorToECEFIsValid) { + this->SetActorToEarthCenteredEarthFixedMatrix( + this->ActorToEarthCenteredEarthFixedMatrix); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGlobeAnchoredActorComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGlobeAnchoredActorComponent.cpp new file mode 100644 index 0000000..43609a3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGlobeAnchoredActorComponent.cpp @@ -0,0 +1,52 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGlobeAnchoredActorComponent.h" +#include "CesiumGlobeAnchorComponent.h" + +#if WITH_EDITOR +#include "Editor.h" +#endif + +UCesiumGlobeAnchorComponent* +UCesiumGlobeAnchoredActorComponent::GetGlobeAnchor() { + return this->GlobeAnchor; +} + +void UCesiumGlobeAnchoredActorComponent::OnRegister() { + Super::OnRegister(); + this->ResolveGlobeAnchor(); +} + +void UCesiumGlobeAnchoredActorComponent::BeginPlay() { + Super::BeginPlay(); + this->ResolveGlobeAnchor(); +} + +void UCesiumGlobeAnchoredActorComponent::ResolveGlobeAnchor() { + this->GlobeAnchor = nullptr; + + AActor* Owner = this->GetOwner(); + if (!IsValid(Owner)) + return; + + this->GlobeAnchor = + Owner->FindComponentByClass(); + if (!IsValid(this->GlobeAnchor)) { + // A globe anchor is missing and required, so add one. + this->GlobeAnchor = + Cast(Owner->AddComponentByClass( + UCesiumGlobeAnchorComponent::StaticClass(), + false, + FTransform::Identity, + false)); + Owner->AddInstanceComponent(this->GlobeAnchor); + + // Force the Editor to refresh to show the newly-added component +#if WITH_EDITOR + Owner->Modify(); + if (Owner->IsSelectedInEditor()) { + GEditor->SelectActor(Owner, true, true, true, true); + } +#endif + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp new file mode 100644 index 0000000..d82ae89 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp @@ -0,0 +1,3678 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGltfComponent.h" +#include "Async/Async.h" +#include "CesiumCommon.h" +#include "CesiumEncodedFeaturesMetadata.h" +#include "CesiumEncodedMetadataUtility.h" +#include "CesiumFeatureIdSet.h" +#include "CesiumGltfPointsComponent.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumGltfTextures.h" +#include "CesiumMaterialUserData.h" +#include "CesiumRasterOverlays.h" +#include "CesiumRuntime.h" +#include "CesiumTextureUtility.h" +#include "CesiumTransforms.h" +#include "Chaos/AABBTree.h" +#include "Chaos/CollisionConvexMesh.h" +#include "Chaos/TriangleMeshImplicitObject.h" +#include "CreateGltfOptions.h" +#include "Engine/CollisionProfile.h" +#include "Engine/StaticMesh.h" +#include "HttpModule.h" +#include "Interfaces/IHttpResponse.h" +#include "LoadGltfResult.h" +#include "Materials/Material.h" +#include "Materials/MaterialInstanceDynamic.h" +#include "MeshTypes.h" +#include "PhysicsEngine/BodySetup.h" +#include "PhysicsEngine/PhysicsSettings.h" +#include "PixelFormat.h" +#include "Runtime/Launch/Resources/Version.h" +#include "StaticMeshOperations.h" +#include "StaticMeshResources.h" +#include "UObject/ConstructorHelpers.h" +#include "VecMath.h" +#include "mikktspace.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if WITH_EDITOR +#include "ScopedTransaction.h" +#endif + +using namespace CesiumTextureUtility; +using namespace CreateGltfOptions; +using namespace LoadGltfResult; + +// To debug which urls correspond to which gltf components you see in the view, +// - Set this define to 1 +// - Click on a piece of terrain in the editor viewport to select it +// - Press delete to try to delete it +// Note that the console gives an error, but also tells you the url associated +// with it +#define DEBUG_GLTF_ASSET_NAMES 0 + +namespace { +using TMeshVector2 = FVector2f; +using TMeshVector3 = FVector3f; +using TMeshVector4 = FVector4f; +} // namespace + +static uint32_t nextMaterialId = 0; + +namespace { +class HalfConstructedReal : public UCesiumGltfComponent::HalfConstructed { +public: + LoadModelResult loadModelResult{}; +}; +} // namespace + +template struct IsAccessorView; + +template struct IsAccessorView : std::false_type {}; + +template +struct IsAccessorView> : std::true_type {}; + +template +static uint32_t updateTextureCoordinates( + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + bool duplicateVertices, + TArray& vertices, + const TArray& indices, + const std::optional& texture, + std::unordered_map& gltfToUnrealTexCoordMap) { + if (!texture) { + return 0; + } + + return updateTextureCoordinates( + model, + primitive, + duplicateVertices, + vertices, + indices, + "TEXCOORD_" + std::to_string(texture.value().texCoord), + gltfToUnrealTexCoordMap); +} + +uint32_t updateTextureCoordinates( + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + bool duplicateVertices, + TArray& vertices, + const TArray& indices, + const std::string& attributeName, + std::unordered_map& gltfToUnrealTexCoordMap) { + auto uvAccessorIt = primitive.attributes.find(attributeName); + if (uvAccessorIt == primitive.attributes.end()) { + // Texture not used, texture coordinates don't matter. + return 0; + } + + int32_t uvAccessorID = uvAccessorIt->second; + auto mapIt = gltfToUnrealTexCoordMap.find(uvAccessorID); + if (mapIt != gltfToUnrealTexCoordMap.end()) { + // Texture coordinates for this accessor are already populated. + return mapIt->second; + } + + size_t textureCoordinateIndex = gltfToUnrealTexCoordMap.size(); + gltfToUnrealTexCoordMap[uvAccessorID] = textureCoordinateIndex; + + CesiumGltf::AccessorView uvAccessor(model, uvAccessorID); + if (uvAccessor.status() != CesiumGltf::AccessorViewStatus::Valid) { + return 0; + } + + if (duplicateVertices) { + for (int i = 0; i < indices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = vertices[i]; + uint32 vertexIndex = indices[i]; + if (vertexIndex >= 0 && vertexIndex < uvAccessor.size()) { + vertex.UVs[textureCoordinateIndex] = uvAccessor[vertexIndex]; + } else { + vertex.UVs[textureCoordinateIndex] = TMeshVector2(0.0f, 0.0f); + } + } + } else { + for (int i = 0; i < vertices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = vertices[i]; + if (i >= 0 && i < uvAccessor.size()) { + vertex.UVs[textureCoordinateIndex] = uvAccessor[i]; + } else { + vertex.UVs[textureCoordinateIndex] = TMeshVector2(0.0f, 0.0f); + } + } + } + + return textureCoordinateIndex; +} + +static int mikkGetNumFaces(const SMikkTSpaceContext* Context) { + TArray& vertices = + *reinterpret_cast*>(Context->m_pUserData); + return vertices.Num() / 3; +} + +static int +mikkGetNumVertsOfFace(const SMikkTSpaceContext* Context, const int FaceIdx) { + TArray& vertices = + *reinterpret_cast*>(Context->m_pUserData); + return FaceIdx < (vertices.Num() / 3) ? 3 : 0; +} + +static void mikkGetPosition( + const SMikkTSpaceContext* Context, + float Position[3], + const int FaceIdx, + const int VertIdx) { + TArray& vertices = + *reinterpret_cast*>(Context->m_pUserData); + const TMeshVector3& position = vertices[FaceIdx * 3 + VertIdx].Position; + Position[0] = position.X; + Position[1] = -position.Y; + Position[2] = position.Z; +} + +static void mikkGetNormal( + const SMikkTSpaceContext* Context, + float Normal[3], + const int FaceIdx, + const int VertIdx) { + TArray& vertices = + *reinterpret_cast*>(Context->m_pUserData); + const TMeshVector3& normal = vertices[FaceIdx * 3 + VertIdx].TangentZ; + Normal[0] = normal.X; + Normal[1] = -normal.Y; + Normal[2] = normal.Z; +} + +static void mikkGetTexCoord( + const SMikkTSpaceContext* Context, + float UV[2], + const int FaceIdx, + const int VertIdx) { + TArray& vertices = + *reinterpret_cast*>(Context->m_pUserData); + const TMeshVector2& uv = vertices[FaceIdx * 3 + VertIdx].UVs[0]; + UV[0] = uv.X; + UV[1] = uv.Y; +} + +static void mikkSetTSpaceBasic( + const SMikkTSpaceContext* Context, + const float Tangent[3], + const float BitangentSign, + const int FaceIdx, + const int VertIdx) { + TArray& vertices = + *reinterpret_cast*>(Context->m_pUserData); + FStaticMeshBuildVertex& vertex = vertices[FaceIdx * 3 + VertIdx]; + + FVector3f TangentZ = vertex.TangentZ; + TangentZ.Y = -TangentZ.Y; + + FVector3f TangentX = TMeshVector3(Tangent[0], Tangent[1], Tangent[2]); + FVector3f TangentY = + BitangentSign * TMeshVector3::CrossProduct(TangentZ, TangentX); + + TangentX.Y = -TangentX.Y; + TangentY.Y = -TangentY.Y; + + vertex.TangentX = TangentX; + vertex.TangentY = TangentY; +} + +static void computeTangentSpace(TArray& vertices) { + SMikkTSpaceInterface MikkTInterface{}; + MikkTInterface.m_getNormal = mikkGetNormal; + MikkTInterface.m_getNumFaces = mikkGetNumFaces; + MikkTInterface.m_getNumVerticesOfFace = mikkGetNumVertsOfFace; + MikkTInterface.m_getPosition = mikkGetPosition; + MikkTInterface.m_getTexCoord = mikkGetTexCoord; + MikkTInterface.m_setTSpaceBasic = mikkSetTSpaceBasic; + MikkTInterface.m_setTSpace = nullptr; + + SMikkTSpaceContext MikkTContext{}; + MikkTContext.m_pInterface = &MikkTInterface; + MikkTContext.m_pUserData = (void*)(&vertices); + // MikkTContext.m_bIgnoreDegenerates = false; + genTangSpaceDefault(&MikkTContext); +} + +static void setUnlitNormals( + TArray& vertices, + const CesiumGeospatial::Ellipsoid& ellipsoid, + const glm::dmat4& vertexToEllipsoidFixed) { + glm::dmat4 ellipsoidFixedToVertex = + glm::affineInverse(vertexToEllipsoidFixed); + + for (int i = 0; i < vertices.Num(); i++) { + FStaticMeshBuildVertex& v = vertices[i]; + v.TangentX = v.TangentY = TMeshVector3(0.0f); + + glm::dvec3 positionFixed = glm::dvec3( + vertexToEllipsoidFixed * + glm::dvec4(VecMath::createVector3D(FVector(v.Position)), 1.0)); + glm::dvec3 normal = ellipsoid.geodeticSurfaceNormal(positionFixed); + v.TangentZ = FVector3f(VecMath::createVector( + glm::normalize(ellipsoidFixedToVertex * glm::dvec4(normal, 0.0)))); + } +} + +static void computeFlatNormals(TArray& vertices) { + // Compute flat normals + for (int i = 0; i < vertices.Num(); i += 3) { + FStaticMeshBuildVertex& v0 = vertices[i]; + FStaticMeshBuildVertex& v1 = vertices[i + 1]; + FStaticMeshBuildVertex& v2 = vertices[i + 2]; + + // The Y axis has previously been inverted, so undo that before + // computing the normal direction. Then invert the Y coordinate of the + // normal, too. + + TMeshVector3 v01 = v1.Position - v0.Position; + v01.Y = -v01.Y; + TMeshVector3 v02 = v2.Position - v0.Position; + v02.Y = -v02.Y; + TMeshVector3 normal = TMeshVector3::CrossProduct(v01, v02); + + normal.Y = -normal.Y; + + v0.TangentX = v1.TangentX = v2.TangentX = TMeshVector3(0.0f); + v0.TangentY = v1.TangentY = v2.TangentY = TMeshVector3(0.0f); + v0.TangentZ = v1.TangentZ = v2.TangentZ = normal.GetSafeNormal(); + } +} + +template +#if ENGINE_VERSION_5_4_OR_HIGHER +static Chaos::FTriangleMeshImplicitObjectPtr +#else +static TSharedPtr +#endif +BuildChaosTriangleMeshes( + const TArray& vertexData, + const TArray& indices); + +static const CesiumGltf::Material defaultMaterial; +static const CesiumGltf::MaterialPBRMetallicRoughness + defaultPbrMetallicRoughness; + +struct ColorVisitor { + bool duplicateVertices; + TArray& StaticMeshBuildVertices; + const TArray& indices; + + bool operator()(CesiumGltf::AccessorView&& invalidView) { + return false; + } + + template bool operator()(TColorView&& colorView) { + if (colorView.status() != CesiumGltf::AccessorViewStatus::Valid) { + return false; + } + + bool success = true; + if (duplicateVertices) { + for (int i = 0; success && i < this->indices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = this->StaticMeshBuildVertices[i]; + uint32 vertexIndex = this->indices[i]; + if (vertexIndex >= colorView.size()) { + success = false; + } else { + success = + ColorVisitor::convertColor(colorView[vertexIndex], vertex.Color); + } + } + } else { + for (int i = 0; success && i < this->StaticMeshBuildVertices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = this->StaticMeshBuildVertices[i]; + if (i >= colorView.size()) { + success = false; + } else { + success = ColorVisitor::convertColor(colorView[i], vertex.Color); + } + } + } + + return success; + } + + template + static bool convertColor( + const CesiumGltf::AccessorTypes::VEC3& color, + FColor& out) { + out.A = 255; + return convertElement(color.value[0], out.R) && + convertElement(color.value[1], out.G) && + convertElement(color.value[2], out.B); + } + + template + static bool convertColor( + const CesiumGltf::AccessorTypes::VEC4& color, + FColor& out) { + return convertElement(color.value[0], out.R) && + convertElement(color.value[1], out.G) && + convertElement(color.value[2], out.B) && + convertElement(color.value[3], out.A); + } + + static bool convertElement(float value, uint8_t& out) { + out = uint8_t(value * 255.0f); + return true; + } + + static bool convertElement(uint8_t value, uint8_t& out) { + out = value; + return true; + } + + static bool convertElement(uint16_t value, uint8_t& out) { + out = uint8_t(value / 256); + return true; + } + + template static bool convertColor(const T& color, FColor& out) { + return false; + } + + template + static bool convertElement(const T& color, uint8_t& out) { + return false; + } +}; + +template +static TUniquePtr loadTexture( + CesiumGltf::Model& model, + const std::optional& gltfTextureInfo, + bool sRGB) { + if (!gltfTextureInfo || gltfTextureInfo.value().index < 0 || + gltfTextureInfo.value().index >= model.textures.size()) { + if (gltfTextureInfo && gltfTextureInfo.value().index >= 0) { + UE_LOG( + LogCesium, + Warning, + TEXT("Texture index must be less than %d, but is %d"), + model.textures.size(), + gltfTextureInfo.value().index); + } + return nullptr; + } + + int32_t textureIndex = gltfTextureInfo.value().index; + CesiumGltf::Texture& texture = model.textures[textureIndex]; + return loadTextureFromModelAnyThreadPart(model, texture, sRGB); +} + +static void applyWaterMask( + CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + LoadPrimitiveResult& primitiveResult) { + // Initialize water mask if needed. + auto onlyWaterIt = primitive.extras.find("OnlyWater"); + auto onlyLandIt = primitive.extras.find("OnlyLand"); + if (onlyWaterIt != primitive.extras.end() && onlyWaterIt->second.isBool() && + onlyLandIt != primitive.extras.end() && onlyLandIt->second.isBool()) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ApplyWaterMask) + bool onlyWater = onlyWaterIt->second.getBoolOrDefault(false); + bool onlyLand = onlyLandIt->second.getBoolOrDefault(true); + primitiveResult.onlyWater = onlyWater; + primitiveResult.onlyLand = onlyLand; + if (!onlyWater && !onlyLand) { + // We have to use the water mask + auto waterMaskTextureIdIt = primitive.extras.find("WaterMaskTex"); + if (waterMaskTextureIdIt != primitive.extras.end() && + waterMaskTextureIdIt->second.isInt64()) { + int32_t waterMaskTextureId = static_cast( + waterMaskTextureIdIt->second.getInt64OrDefault(-1)); + CesiumGltf::TextureInfo waterMaskInfo; + waterMaskInfo.index = waterMaskTextureId; + if (waterMaskTextureId >= 0 && + waterMaskTextureId < model.textures.size()) { + primitiveResult.waterMaskTexture = + loadTexture(model, std::make_optional(waterMaskInfo), false); + } + } + } + } else { + primitiveResult.onlyWater = false; + primitiveResult.onlyLand = true; + } + + auto waterMaskTranslationXIt = primitive.extras.find("WaterMaskTranslationX"); + auto waterMaskTranslationYIt = primitive.extras.find("WaterMaskTranslationY"); + auto waterMaskScaleIt = primitive.extras.find("WaterMaskScale"); + + if (waterMaskTranslationXIt != primitive.extras.end() && + waterMaskTranslationXIt->second.isDouble() && + waterMaskTranslationYIt != primitive.extras.end() && + waterMaskTranslationYIt->second.isDouble() && + waterMaskScaleIt != primitive.extras.end() && + waterMaskScaleIt->second.isDouble()) { + primitiveResult.waterMaskTranslationX = + waterMaskTranslationXIt->second.getDoubleOrDefault(0.0); + primitiveResult.waterMaskTranslationY = + waterMaskTranslationYIt->second.getDoubleOrDefault(0.0); + primitiveResult.waterMaskScale = + waterMaskScaleIt->second.getDoubleOrDefault(1.0); + } +} + +#pragma region Features Metadata helper functions(load thread) + +static bool textureUsesSpecifiedImage( + const CesiumGltf::Model& model, + int32_t textureIndex, + int32_t imageIndex) { + if (textureIndex < 0 || textureIndex >= model.textures.size()) { + return false; + } + + const CesiumGltf::Texture& texture = model.textures[textureIndex]; + return texture.source == imageIndex; +} + +static bool hasMaterialTextureConflicts( + const CesiumGltf::Model& model, + const CesiumGltf::Material& material, + int32_t imageIndex) { + if (material.pbrMetallicRoughness) { + const std::optional& maybeBaseColorTexture = + material.pbrMetallicRoughness->baseColorTexture; + if (maybeBaseColorTexture && textureUsesSpecifiedImage( + model, + maybeBaseColorTexture->index, + imageIndex)) { + return true; + } + + const std::optional& + maybeMetallicRoughnessTexture = + material.pbrMetallicRoughness->metallicRoughnessTexture; + if (maybeMetallicRoughnessTexture && + textureUsesSpecifiedImage( + model, + maybeMetallicRoughnessTexture->index, + imageIndex)) { + return true; + } + } + + if (material.normalTexture && textureUsesSpecifiedImage( + model, + material.normalTexture->index, + imageIndex)) { + return true; + } + + if (material.emissiveTexture && textureUsesSpecifiedImage( + model, + material.emissiveTexture->index, + imageIndex)) { + return true; + } + + if (material.occlusionTexture && textureUsesSpecifiedImage( + model, + material.occlusionTexture->index, + imageIndex)) { + return true; + } + + return false; +} + +/** + * Creates texture coordinate accessors for the feature ID sets and metadata in + * the primitive. This enables feature ID texture / property texture picking + * without requiring UVs in the physics bodies. + */ +static void createTexCoordAccessorsForFeaturesMetadata( + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + const FCesiumPrimitiveFeatures& primitiveFeatures, + const FCesiumPrimitiveMetadata& primitiveMetadata, + const FCesiumModelMetadata& modelMetadata, + std::unordered_map& + texCoordAccessorsMap) { + auto featureIdTextures = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSetsOfType( + primitiveFeatures, + ECesiumFeatureIdSetType::Texture); + + for (const FCesiumFeatureIdSet& featureIdSet : featureIdTextures) { + FCesiumFeatureIdTexture featureIdTexture = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDTexture( + featureIdSet); + + int64 gltfTexCoordSetIndex = UCesiumFeatureIdTextureBlueprintLibrary:: + GetGltfTextureCoordinateSetIndex(featureIdTexture); + if (gltfTexCoordSetIndex < 0 || + texCoordAccessorsMap.find(gltfTexCoordSetIndex) != + texCoordAccessorsMap.end()) { + // Skip if the index is invalid or if it has already been accounted for. + continue; + } + texCoordAccessorsMap.emplace( + gltfTexCoordSetIndex, + CesiumGltf::getTexCoordAccessorView( + model, + primitive, + gltfTexCoordSetIndex)); + } + + auto propertyTextureIndices = + UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyTextureIndices( + primitiveMetadata); + auto propertyTextures = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTexturesAtIndices( + modelMetadata, + propertyTextureIndices); + + for (const FCesiumPropertyTexture& propertyTexture : propertyTextures) { + auto properties = + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture); + + for (const auto& propertyIt : properties) { + int64 gltfTexCoordSetIndex = + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetGltfTextureCoordinateSetIndex(propertyIt.Value); + if (gltfTexCoordSetIndex < 0 || + texCoordAccessorsMap.find(gltfTexCoordSetIndex) != + texCoordAccessorsMap.end()) { + // Skip if the index is invalid or if it has already been accounted for. + continue; + } + texCoordAccessorsMap.emplace( + gltfTexCoordSetIndex, + CesiumGltf::getTexCoordAccessorView( + model, + primitive, + gltfTexCoordSetIndex)); + } + } +} + +/** + * Updates the primitive's information for the texture coordinates required for + * features and metadata styling. This processes existing texture coordinate + * sets for feature ID textures and property textures, and generates new texture + * coordinates for attribute and implicit feature ID sets. + */ +static void updateTextureCoordinatesForFeaturesMetadata( + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + bool duplicateVertices, + TArray& vertices, + const TArray& indices, + const FCesiumPrimitiveFeatures& primitiveFeatures, + const CesiumEncodedFeaturesMetadata::EncodedPrimitiveFeatures& + encodedPrimitiveFeatures, + const CesiumEncodedFeaturesMetadata::EncodedPrimitiveMetadata& + encodedPrimitiveMetadata, + const CesiumEncodedFeaturesMetadata::EncodedModelMetadata& + encodedModelMetadata, + TMap& featuresMetadataTexcoordParameters, + std::unordered_map& gltfToUnrealTexCoordMap) { + + TRACE_CPUPROFILER_EVENT_SCOPE( + Cesium::UpdateTextureCoordinatesForFeaturesMetadata) + + for (const int64 propertyTextureIndex : + encodedPrimitiveMetadata.propertyTextureIndices) { + // Property textures can be made accessible in Unreal materials without + // requiring a texture coordinate set on the primitive. If it is not present + // in primitive metadata, then do not set the parameter. + const CesiumEncodedFeaturesMetadata::EncodedPropertyTexture& + encodedPropertyTexture = + encodedModelMetadata.propertyTextures[propertyTextureIndex]; + + for (const CesiumEncodedFeaturesMetadata::EncodedPropertyTextureProperty& + encodedProperty : encodedPropertyTexture.properties) { + + FString fullPropertyName = CesiumEncodedFeaturesMetadata:: + getMaterialNameForPropertyTextureProperty( + encodedPropertyTexture.name, + encodedProperty.name); + + featuresMetadataTexcoordParameters.Emplace( + fullPropertyName + + CesiumEncodedFeaturesMetadata::MaterialTexCoordIndexSuffix, + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + vertices, + indices, + "TEXCOORD_" + + std::to_string(encodedProperty.textureCoordinateSetIndex), + gltfToUnrealTexCoordMap)); + } + } + + // These are necessary for retrieving feature ID attributes, since we'll be + // taking feature IDs from the attribute itself and putting them into + // texcoords. We could technically just make an AccessorView on the attribute, + // but there are multiple feature ID component types, and + // FCesiumFeatureIdAttribute already creates the accessor view for us. + const TArray& featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets( + primitiveFeatures); + + for (const CesiumEncodedFeaturesMetadata::EncodedFeatureIdSet& + encodedFeatureIDSet : encodedPrimitiveFeatures.featureIdSets) { + FString SafeName = CesiumEncodedFeaturesMetadata::createHlslSafeName( + encodedFeatureIDSet.name); + if (encodedFeatureIDSet.attribute) { + int32_t attribute = *encodedFeatureIDSet.attribute; + std::string attributeName = "_FEATURE_ID_" + std::to_string(attribute); + if (primitive.attributes.find(attributeName) == + primitive.attributes.end()) { + continue; + } + + // This was already validated when creating the EncodedFeatureIdSet. + int32_t accessor = primitive.attributes.at(attributeName); + + uint32_t textureCoordinateIndex = gltfToUnrealTexCoordMap.size(); + gltfToUnrealTexCoordMap[accessor] = textureCoordinateIndex; + featuresMetadataTexcoordParameters.Emplace( + SafeName, + textureCoordinateIndex); + + const FCesiumFeatureIdSet& featureIDSet = + featureIDSets[encodedFeatureIDSet.index]; + const FCesiumFeatureIdAttribute& featureIDAttribute = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute( + featureIDSet); + + // Each feature ID corresponds to a vertex, so the vertex count is just + // the length of the attribute. + int64 vertexCount = UCesiumFeatureIdAttributeBlueprintLibrary::GetCount( + featureIDAttribute); + + // We encode unsigned integer feature ids as floats in the u-channel of + // a texture coordinate slot. + if (duplicateVertices) { + for (int64_t i = 0; i < indices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = vertices[i]; + uint32 vertexIndex = indices[i]; + if (vertexIndex >= 0 && vertexIndex < vertexCount) { + float featureId = static_cast( + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + featureIDAttribute, + vertexIndex)); + vertex.UVs[textureCoordinateIndex] = TMeshVector2(featureId, 0.0f); + } else { + vertex.UVs[textureCoordinateIndex] = TMeshVector2(0.0f, 0.0f); + } + } + } else { + for (int64_t i = 0; i < vertices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = vertices[i]; + if (i < vertexCount) { + float featureId = static_cast( + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + featureIDAttribute, + i)); + vertex.UVs[textureCoordinateIndex] = TMeshVector2(featureId, 0.0f); + } else { + vertex.UVs[textureCoordinateIndex] = TMeshVector2(0.0f, 0.0f); + } + } + } + } else if (encodedFeatureIDSet.texture) { + const CesiumEncodedFeaturesMetadata::EncodedFeatureIdTexture& + encodedFeatureIDTexture = *encodedFeatureIDSet.texture; + featuresMetadataTexcoordParameters.Emplace( + SafeName + CesiumEncodedFeaturesMetadata::MaterialTexCoordIndexSuffix, + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + vertices, + indices, + "TEXCOORD_" + + std::to_string( + encodedFeatureIDTexture.textureCoordinateSetIndex), + gltfToUnrealTexCoordMap)); + } else { + // Similar to feature ID attributes, we encode the unsigned integer vertex + // ids as floats in the u-channel of a texture coordinate slot. If it ever + // becomes possible to access the vertex ID through an Unreal material + // node, this can be removed. + uint32_t textureCoordinateIndex = gltfToUnrealTexCoordMap.size(); + gltfToUnrealTexCoordMap[-1] = textureCoordinateIndex; + featuresMetadataTexcoordParameters.Emplace( + SafeName, + textureCoordinateIndex); + if (duplicateVertices) { + for (int64_t i = 0; i < indices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = vertices[i]; + uint32 vertexIndex = indices[i]; + vertex.UVs[textureCoordinateIndex] = + TMeshVector2(static_cast(vertexIndex), 0.0f); + } + } else { + for (int64_t i = 0; i < vertices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = vertices[i]; + vertex.UVs[textureCoordinateIndex] = + TMeshVector2(static_cast(i), 0.0f); + } + } + } + } +} + +PRAGMA_DISABLE_DEPRECATION_WARNINGS +static void updateTextureCoordinatesForMetadata_DEPRECATED( + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + bool duplicateVertices, + TArray& vertices, + const TArray& indices, + const CesiumEncodedMetadataUtility::EncodedMetadata& encodedMetadata, + const CesiumEncodedMetadataUtility::EncodedMetadataPrimitive& + encodedPrimitiveMetadata, + const TArray& featureIdAttributes, + TMap& metadataTextureCoordinateParameters, + std::unordered_map& gltfToUnrealTexCoordMap) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTextureCoordinatesForMetadata) + + for (const CesiumEncodedMetadataUtility::EncodedFeatureIdTexture& + encodedFeatureIdTexture : + encodedPrimitiveMetadata.encodedFeatureIdTextures) { + metadataTextureCoordinateParameters.Emplace( + encodedFeatureIdTexture.baseName + "UV", + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + vertices, + indices, + "TEXCOORD_" + + std::to_string( + encodedFeatureIdTexture.textureCoordinateAttributeId), + gltfToUnrealTexCoordMap)); + } + + for (const FString& featureTextureName : + encodedPrimitiveMetadata.featureTextureNames) { + const CesiumEncodedMetadataUtility::EncodedFeatureTexture* + pEncodedFeatureTexture = + encodedMetadata.encodedFeatureTextures.Find(featureTextureName); + if (pEncodedFeatureTexture) { + for (const CesiumEncodedMetadataUtility::EncodedFeatureTextureProperty& + encodedProperty : pEncodedFeatureTexture->properties) { + metadataTextureCoordinateParameters.Emplace( + encodedProperty.baseName + "UV", + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + vertices, + indices, + "TEXCOORD_" + std::to_string( + encodedProperty.textureCoordinateAttributeId), + gltfToUnrealTexCoordMap)); + } + } + } + + const CesiumGltf::ExtensionExtMeshFeatures* pFeatures = + primitive.getExtension(); + + if (pFeatures) { + for (const CesiumEncodedMetadataUtility::EncodedFeatureIdAttribute& + encodedFeatureIdAttribute : + encodedPrimitiveMetadata.encodedFeatureIdAttributes) { + const FCesiumFeatureIdAttribute& featureIdAttribute = + featureIdAttributes[encodedFeatureIdAttribute.index]; + + int32_t attribute = featureIdAttribute.getAttributeIndex(); + std::string attributeName = "_FEATURE_ID_" + std::to_string(attribute); + if (primitive.attributes.find(attributeName) == + primitive.attributes.end()) { + continue; + } + + // This was already validated when creating the EncodedFeatureIdSet. + int32_t accessor = primitive.attributes.at(attributeName); + + uint32_t textureCoordinateIndex = gltfToUnrealTexCoordMap.size(); + gltfToUnrealTexCoordMap[accessor] = textureCoordinateIndex; + metadataTextureCoordinateParameters.Emplace( + encodedFeatureIdAttribute.name, + textureCoordinateIndex); + + // Each feature ID corresponds to a vertex, so the vertex count is just + // the length of the attribute. + int64 vertexCount = UCesiumFeatureIdAttributeBlueprintLibrary::GetCount( + featureIdAttribute); + + // We encode unsigned integer feature ids as floats in the u-channel of + // a texture coordinate slot. + if (duplicateVertices) { + for (int64_t i = 0; i < indices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = vertices[i]; + uint32 vertexIndex = indices[i]; + if (vertexIndex >= 0 && vertexIndex < vertexCount) { + float featureId = static_cast( + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + featureIdAttribute, + vertexIndex)); + vertex.UVs[textureCoordinateIndex] = TMeshVector2(featureId, 0.0f); + } else { + vertex.UVs[textureCoordinateIndex] = TMeshVector2(0.0f, 0.0f); + } + } + } else { + for (int64_t i = 0; i < vertices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = vertices[i]; + if (i < vertexCount) { + float featureId = static_cast( + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + featureIdAttribute, + i)); + vertex.UVs[textureCoordinateIndex] = TMeshVector2(featureId, 0.0f); + } else { + vertex.UVs[textureCoordinateIndex] = TMeshVector2(0.0f, 0.0f); + } + } + } + } + } +} +PRAGMA_ENABLE_DEPRECATION_WARNINGS + +static void loadPrimitiveFeaturesMetadata( + LoadPrimitiveResult& primitiveResult, + const CreatePrimitiveOptions& options, + CesiumGltf::Model& model, + CesiumGltf::MeshPrimitive& primitive, + bool duplicateVertices, + TArray& vertices, + const TArray& indices) { + + CesiumGltf::ExtensionExtMeshFeatures* pFeatures = + primitive.getExtension(); + + if (pFeatures) { + int32_t materialIndex = primitive.material; + if (materialIndex >= 0 && materialIndex < model.materials.size()) { + const CesiumGltf::Material& material = + model.materials[primitive.material]; + + for (CesiumGltf::FeatureId& featureId : pFeatures->featureIds) { + if (!featureId.texture) { + continue; + } + + if (featureId.texture->extras.find("makeImageCopy") != + featureId.texture->extras.end()) { + continue; + } + + int32_t textureIndex = featureId.texture->index; + if (textureIndex < 0 || textureIndex >= model.textures.size()) { + continue; + } + + const CesiumGltf::Texture& texture = model.textures[textureIndex]; + if (texture.source < 0 || texture.source >= model.images.size()) { + continue; + } + + int32_t imageIndex = model.textures[textureIndex].source; + if (hasMaterialTextureConflicts(model, material, imageIndex)) { + // Add a flag in the extras to indicate a copy should be made. + // This is checked for in FCesiumFeatureIdTexture. + featureId.texture->extras.insert({"makeImageCopy", true}); + } + } + } + } + + const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata* pMetadata = + primitive.getExtension< + CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata>(); + + const CreateGltfOptions::CreateModelOptions* pModelOptions = + options.pMeshOptions->pNodeOptions->pModelOptions; + const LoadGltfResult::LoadModelResult* pModelResult = + options.pMeshOptions->pNodeOptions->pHalfConstructedModelResult; + + primitiveResult.Features = + pFeatures ? FCesiumPrimitiveFeatures(model, primitive, *pFeatures) + : FCesiumPrimitiveFeatures(); + primitiveResult.Metadata = + pMetadata ? FCesiumPrimitiveMetadata(primitive, *pMetadata) + : FCesiumPrimitiveMetadata(); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + primitiveResult.Metadata_DEPRECATED = FCesiumMetadataPrimitive{ + primitiveResult.Features, + primitiveResult.Metadata, + pModelResult->Metadata}; + + createTexCoordAccessorsForFeaturesMetadata( + model, + primitive, + primitiveResult.Features, + primitiveResult.Metadata, + pModelResult->Metadata, + primitiveResult.TexCoordAccessorMap); + + const FCesiumFeaturesMetadataDescription* pFeaturesMetadataDescription = + pModelOptions->pFeaturesMetadataDescription; + + // Check for deprecated metadata description + const FMetadataDescription* pMetadataDescription_DEPRECATED = + pModelOptions->pEncodedMetadataDescription_DEPRECATED; + + std::unordered_map& gltfToUnrealTexCoordMap = + primitiveResult.GltfToUnrealTexCoordMap; + + if (pFeaturesMetadataDescription) { + primitiveResult.EncodedFeatures = + CesiumEncodedFeaturesMetadata::encodePrimitiveFeaturesAnyThreadPart( + pFeaturesMetadataDescription->Features, + primitiveResult.Features); + + primitiveResult.EncodedMetadata = + CesiumEncodedFeaturesMetadata::encodePrimitiveMetadataAnyThreadPart( + pFeaturesMetadataDescription->PrimitiveMetadata, + primitiveResult.Metadata, + pModelResult->Metadata); + + updateTextureCoordinatesForFeaturesMetadata( + model, + primitive, + duplicateVertices, + vertices, + indices, + primitiveResult.Features, + primitiveResult.EncodedFeatures, + primitiveResult.EncodedMetadata, + pModelResult->EncodedMetadata, + primitiveResult.FeaturesMetadataTexCoordParameters, + gltfToUnrealTexCoordMap); + } else if (pMetadataDescription_DEPRECATED) { + primitiveResult.EncodedMetadata_DEPRECATED = + CesiumEncodedMetadataUtility::encodeMetadataPrimitiveAnyThreadPart( + *pMetadataDescription_DEPRECATED, + primitiveResult.Metadata_DEPRECATED); + + updateTextureCoordinatesForMetadata_DEPRECATED( + model, + primitive, + duplicateVertices, + vertices, + indices, + *pModelResult->EncodedMetadata_DEPRECATED, + *primitiveResult.EncodedMetadata_DEPRECATED, + UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdAttributes( + primitiveResult.Metadata_DEPRECATED), + primitiveResult.FeaturesMetadataTexCoordParameters, + gltfToUnrealTexCoordMap); + } + PRAGMA_ENABLE_DEPRECATION_WARNINGS +} +#pragma endregion + +namespace { + +/** + * @brief Constrain the length of the given string. + * + * If the string is shorter than the maximum length, it is returned. + * If it is not longer than 3 characters, the first maxLength + * characters will be returned. + * Otherwise, the result will be of the form `prefix + "..." + suffix`, + * with the prefix and suffix chosen so that the length of the result + * is maxLength + * + * @param s The input string + * @param maxLength The maximum length. + * @return The constrained string + */ +std::string constrainLength(const std::string& s, const size_t maxLength) { + if (s.length() <= maxLength) { + return s; + } + if (maxLength <= 3) { + return s.substr(0, maxLength); + } + const std::string ellipsis("..."); + const size_t prefixLength = ((maxLength - ellipsis.length()) + 1) / 2; + const size_t suffixLength = (maxLength - ellipsis.length()) / 2; + const std::string prefix = s.substr(0, prefixLength); + const std::string suffix = s.substr(s.length() - suffixLength, suffixLength); + return prefix + ellipsis + suffix; +} + +/** + * @brief Create an FName from the given strings. + * + * This will combine the prefix and the suffix and create an FName. + * If the string would be longer than the given length, then + * the prefix will be shortened (in an unspecified way), to + * constrain the result to a length of maxLength. + * + * The default maximum length is 256, because Unreal may in turn + * add a prefix like the `/Internal/Path/Name` to this name. + * + * @param prefix The prefix input string + * @param suffix The suffix input string + * @param maxLength The maximum length + * @return The FName + */ +FName createSafeName( + const std::string& prefix, + const std::string& suffix, + const size_t maxLength = 256) { + std::string constrainedPrefix = + constrainLength(prefix, maxLength - suffix.length()); + std::string combined = constrainedPrefix + suffix; + return FName(combined.c_str()); +} + +// This matrix converts from right-handed Z-up to Unreal +// left-handed Z-up by flipping the Y axis. It effectively undoes the Y-axis +// flipping that we did when creating the mesh in the first place. This is +// necessary to work around a problem in UE 5.1 where negatively-scaled meshes +// don't work correctly for collision. +// See https://github.com/CesiumGS/cesium-unreal/pull/1126 +// Note that this matrix is its own inverse. + +constexpr glm::dmat4 yInvertMatrix = { + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0}; +} // namespace + +template +static void loadPrimitive( + LoadPrimitiveResult& primitiveResult, + const glm::dmat4x4& transform, + const CreatePrimitiveOptions& options, + const CesiumGltf::Accessor& positionAccessor, + const CesiumGltf::AccessorView& positionView, + const TIndexAccessor& indicesView, + const CesiumGeospatial::Ellipsoid& ellipsoid) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadPrimitive) + + CesiumGltf::Model& model = + *options.pMeshOptions->pNodeOptions->pModelOptions->pModel; + CesiumGltf::Mesh& mesh = model.meshes[options.pMeshOptions->meshIndex]; + CesiumGltf::MeshPrimitive& primitive = + mesh.primitives[options.primitiveIndex]; + + if (primitive.mode != CesiumGltf::MeshPrimitive::Mode::TRIANGLES && + primitive.mode != CesiumGltf::MeshPrimitive::Mode::TRIANGLE_STRIP && + primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS) { + // TODO: add support for other primitive types. + UE_LOG( + LogCesium, + Warning, + TEXT("Primitive mode %d is not supported"), + primitive.mode); + return; + } + + std::string name = "glTF"; + + auto urlIt = model.extras.find("Cesium3DTiles_TileUrl"); + if (urlIt != model.extras.end()) { + name = urlIt->second.getStringOrDefault("glTF"); + name = constrainLength(name, 256); + } + + auto meshIt = std::find_if( + model.meshes.begin(), + model.meshes.end(), + [&mesh](const CesiumGltf::Mesh& candidate) { + return &candidate == &mesh; + }); + if (meshIt != model.meshes.end()) { + int64_t meshIndex = meshIt - model.meshes.begin(); + name += " mesh " + std::to_string(meshIndex); + } + + auto primitiveIt = std::find_if( + mesh.primitives.begin(), + mesh.primitives.end(), + [&primitive](const CesiumGltf::MeshPrimitive& candidate) { + return &candidate == &primitive; + }); + if (primitiveIt != mesh.primitives.end()) { + int64_t primitiveIndex = primitiveIt - mesh.primitives.begin(); + name += " primitive " + std::to_string(primitiveIndex); + } + + primitiveResult.name = name; + + if (positionView.status() != CesiumGltf::AccessorViewStatus::Valid) { + UE_LOG( + LogCesium, + Warning, + TEXT("%s: Invalid position buffer"), + UTF8_TO_TCHAR(name.c_str())); + return; + } + + if constexpr (IsAccessorView::value) { + if (indicesView.status() != CesiumGltf::AccessorViewStatus::Valid) { + UE_LOG( + LogCesium, + Warning, + TEXT("%s: Invalid indices buffer"), + UTF8_TO_TCHAR(name.c_str())); + return; + } + } + + auto normalAccessorIt = primitive.attributes.find("NORMAL"); + CesiumGltf::AccessorView normalAccessor; + bool hasNormals = false; + if (normalAccessorIt != primitive.attributes.end()) { + int normalAccessorID = normalAccessorIt->second; + normalAccessor = + CesiumGltf::AccessorView(model, normalAccessorID); + hasNormals = + normalAccessor.status() == CesiumGltf::AccessorViewStatus::Valid; + if (!hasNormals) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "%s: Invalid normal buffer. Flat normals will be auto-generated instead."), + UTF8_TO_TCHAR(name.c_str())); + } + } + + int materialID = primitive.material; + const CesiumGltf::Material& material = + materialID >= 0 && materialID < model.materials.size() + ? model.materials[materialID] + : defaultMaterial; + + primitiveResult.materialIndex = materialID; + + primitiveResult.isUnlit = + material.hasExtension() && + !options.pMeshOptions->pNodeOptions->pModelOptions + ->ignoreKhrMaterialsUnlit; + + // We can't calculate flat normals for points or lines, so we have to force + // them to be unlit if no normals are specified. Otherwise this causes a + // crash when attempting to calculate flat normals. + bool isTriangles = + primitive.mode == CesiumGltf::MeshPrimitive::Mode::TRIANGLES || + primitive.mode == CesiumGltf::MeshPrimitive::Mode::TRIANGLE_FAN || + primitive.mode == CesiumGltf::MeshPrimitive::Mode::TRIANGLE_STRIP; + + if (!isTriangles && !hasNormals) { + primitiveResult.isUnlit = true; + } + + const CesiumGltf::MaterialPBRMetallicRoughness& pbrMetallicRoughness = + material.pbrMetallicRoughness ? material.pbrMetallicRoughness.value() + : defaultPbrMetallicRoughness; + + bool hasNormalMap = material.normalTexture.has_value(); + if (hasNormalMap) { + const CesiumGltf::Texture* pTexture = CesiumGltf::Model::getSafe( + &model.textures, + material.normalTexture->index); + hasNormalMap = + pTexture != nullptr && + CesiumGltf::Model::getSafe(&model.images, pTexture->source) != nullptr; + } + + bool needsTangents = + hasNormalMap || + options.pMeshOptions->pNodeOptions->pModelOptions->alwaysIncludeTangents; + + bool hasTangents = false; + auto tangentAccessorIt = primitive.attributes.find("TANGENT"); + CesiumGltf::AccessorView tangentAccessor; + if (tangentAccessorIt != primitive.attributes.end()) { + int tangentAccessorID = tangentAccessorIt->second; + tangentAccessor = + CesiumGltf::AccessorView(model, tangentAccessorID); + hasTangents = + tangentAccessor.status() == CesiumGltf::AccessorViewStatus::Valid; + if (!hasTangents) { + UE_LOG( + LogCesium, + Warning, + TEXT("%s: Invalid tangent buffer."), + UTF8_TO_TCHAR(name.c_str())); + } + } + + applyWaterMask(model, primitive, primitiveResult); + + // The water effect works by animating the normal, and the normal is + // expressed in tangent space. So if we have water, we need tangents. + if (primitiveResult.onlyWater || primitiveResult.waterMaskTexture) { + needsTangents = true; + } + + TUniquePtr RenderData = + MakeUnique(); + RenderData->AllocateLODResources(1); + + FStaticMeshLODResources& LODResources = RenderData->LODResources[0]; + + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ComputeAABB) + + const std::vector& min = positionAccessor.min; + const std::vector& max = positionAccessor.max; + glm::dvec3 minPosition{std::numeric_limits::max()}; + glm::dvec3 maxPosition{std::numeric_limits::lowest()}; + if (min.size() != 3 || max.size() != 3) { + for (int64_t i = 0; i < positionView.size(); ++i) { + minPosition.x = glm::min(minPosition.x, positionView[i].X); + minPosition.y = glm::min(minPosition.y, positionView[i].Y); + minPosition.z = glm::min(minPosition.z, positionView[i].Z); + + maxPosition.x = glm::max(maxPosition.x, positionView[i].X); + maxPosition.y = glm::max(maxPosition.y, positionView[i].Y); + maxPosition.z = glm::max(maxPosition.z, positionView[i].Z); + } + } else { + minPosition = glm::dvec3(min[0], min[1], min[2]); + maxPosition = glm::dvec3(max[0], max[1], max[2]); + } + + minPosition *= CesiumPrimitiveData::positionScaleFactor; + maxPosition *= CesiumPrimitiveData::positionScaleFactor; + + primitiveResult.dimensions = + glm::vec3(transform * glm::dvec4(maxPosition - minPosition, 0)); + + FBox aaBox( + FVector3d(minPosition.x, -minPosition.y, minPosition.z), + FVector3d(maxPosition.x, -maxPosition.y, maxPosition.z)); + + aaBox.GetCenterAndExtents( + RenderData->Bounds.Origin, + RenderData->Bounds.BoxExtent); + RenderData->Bounds.SphereRadius = 0.0f; + } + + TArray indices; + if (primitive.mode == CesiumGltf::MeshPrimitive::Mode::TRIANGLES || + primitive.mode == CesiumGltf::MeshPrimitive::Mode::POINTS) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CopyIndices) + indices.SetNum(static_cast::SizeType>(indicesView.size())); + + for (int32 i = 0; i < indicesView.size(); ++i) { + indices[i] = indicesView[i]; + } + } else { + // assume TRIANGLE_STRIP because all others are rejected earlier. + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CopyIndices) + indices.SetNum( + static_cast::SizeType>(3 * (indicesView.size() - 2))); + for (int32 i = 0; i < indicesView.size() - 2; ++i) { + if (i % 2) { + indices[3 * i] = indicesView[i]; + indices[3 * i + 1] = indicesView[i + 2]; + indices[3 * i + 2] = indicesView[i + 1]; + } else { + indices[3 * i] = indicesView[i]; + indices[3 * i + 1] = indicesView[i + 1]; + indices[3 * i + 2] = indicesView[i + 2]; + } + } + } + + // If we don't have normals, the gltf spec prescribes that the client + // implementation must generate flat normals, which requires duplicating + // vertices shared by multiple triangles. If we don't have tangents, but + // need them, we need to use a tangent space generation algorithm which + // requires duplicated vertices. + bool normalsAreRequired = !primitiveResult.isUnlit; + bool needToGenerateFlatNormals = normalsAreRequired && !hasNormals; + bool needToGenerateTangents = needsTangents && !hasTangents; + bool duplicateVertices = needToGenerateFlatNormals || needToGenerateTangents; + duplicateVertices = duplicateVertices && + primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS; + + TArray StaticMeshBuildVertices; + StaticMeshBuildVertices.SetNum( + duplicateVertices ? indices.Num() + : static_cast(positionView.size())); + + { + if (duplicateVertices) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CopyDuplicatedPositions) + for (int i = 0; i < indices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = StaticMeshBuildVertices[i]; + uint32 vertexIndex = indices[i]; + const TMeshVector3& pos = positionView[vertexIndex]; + vertex.Position.X = pos.X * CesiumPrimitiveData::positionScaleFactor; + vertex.Position.Y = -pos.Y * CesiumPrimitiveData::positionScaleFactor; + vertex.Position.Z = pos.Z * CesiumPrimitiveData::positionScaleFactor; + vertex.UVs[0] = TMeshVector2(0.0f, 0.0f); + vertex.UVs[2] = TMeshVector2(0.0f, 0.0f); + RenderData->Bounds.SphereRadius = FMath::Max( + (FVector(vertex.Position) - RenderData->Bounds.Origin).Size(), + RenderData->Bounds.SphereRadius); + } + } else { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CopyPositions) + for (int i = 0; i < StaticMeshBuildVertices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = StaticMeshBuildVertices[i]; + const TMeshVector3& pos = positionView[i]; + vertex.Position.X = pos.X * CesiumPrimitiveData::positionScaleFactor; + vertex.Position.Y = -pos.Y * CesiumPrimitiveData::positionScaleFactor; + vertex.Position.Z = pos.Z * CesiumPrimitiveData::positionScaleFactor; + vertex.UVs[0] = TMeshVector2(0.0f, 0.0f); + vertex.UVs[2] = TMeshVector2(0.0f, 0.0f); + RenderData->Bounds.SphereRadius = FMath::Max( + (FVector(vertex.Position) - RenderData->Bounds.Origin).Size(), + RenderData->Bounds.SphereRadius); + } + } + } + + bool hasVertexColors = false; + + auto colorAccessorIt = primitive.attributes.find("COLOR_0"); + if (colorAccessorIt != primitive.attributes.end()) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CopyVertexColors) + int colorAccessorID = colorAccessorIt->second; + hasVertexColors = createAccessorView( + model, + colorAccessorID, + ColorVisitor{duplicateVertices, StaticMeshBuildVertices, indices}); + } + + LODResources.bHasColorVertexData = hasVertexColors; + + // We need to copy the texture coordinates associated with each texture (if + // any) into the the appropriate UVs slot in FStaticMeshBuildVertex. + + std::unordered_map& gltfToUnrealTexCoordMap = + primitiveResult.GltfToUnrealTexCoordMap; + + // This must be done before material textures are loaded, in case any of the + // material textures are also used for features + metadata. + loadPrimitiveFeaturesMetadata( + primitiveResult, + options, + model, + primitive, + duplicateVertices, + StaticMeshBuildVertices, + indices); + + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadTextures) + primitiveResult.baseColorTexture = + loadTexture(model, pbrMetallicRoughness.baseColorTexture, true); + primitiveResult.metallicRoughnessTexture = loadTexture( + model, + pbrMetallicRoughness.metallicRoughnessTexture, + false); + primitiveResult.normalTexture = + loadTexture(model, material.normalTexture, false); + primitiveResult.occlusionTexture = + loadTexture(model, material.occlusionTexture, false); + primitiveResult.emissiveTexture = + loadTexture(model, material.emissiveTexture, true); + } + + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTextureCoordinates) + + primitiveResult + .textureCoordinateParameters["baseColorTextureCoordinateIndex"] = + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + StaticMeshBuildVertices, + indices, + pbrMetallicRoughness.baseColorTexture, + gltfToUnrealTexCoordMap); + primitiveResult.textureCoordinateParameters + ["metallicRoughnessTextureCoordinateIndex"] = updateTextureCoordinates( + model, + primitive, + duplicateVertices, + StaticMeshBuildVertices, + indices, + pbrMetallicRoughness.metallicRoughnessTexture, + gltfToUnrealTexCoordMap); + primitiveResult + .textureCoordinateParameters["normalTextureCoordinateIndex"] = + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + StaticMeshBuildVertices, + indices, + material.normalTexture, + gltfToUnrealTexCoordMap); + primitiveResult + .textureCoordinateParameters["occlusionTextureCoordinateIndex"] = + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + StaticMeshBuildVertices, + indices, + material.occlusionTexture, + gltfToUnrealTexCoordMap); + primitiveResult + .textureCoordinateParameters["emissiveTextureCoordinateIndex"] = + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + StaticMeshBuildVertices, + indices, + material.emissiveTexture, + gltfToUnrealTexCoordMap); + + for (size_t i = 0; + i < primitiveResult.overlayTextureCoordinateIDToUVIndex.size(); + ++i) { + std::string attributeName = "_CESIUMOVERLAY_" + std::to_string(i); + auto overlayIt = primitive.attributes.find(attributeName); + if (overlayIt != primitive.attributes.end()) { + primitiveResult.overlayTextureCoordinateIDToUVIndex[i] = + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + StaticMeshBuildVertices, + indices, + attributeName, + gltfToUnrealTexCoordMap); + } else { + primitiveResult.overlayTextureCoordinateIDToUVIndex[i] = 0; + } + } + } + + double scale = 1.0 / CesiumPrimitiveData::positionScaleFactor; + glm::dmat4 scaleMatrix = glm::dmat4( + glm::dvec4(scale, 0.0, 0.0, 0.0), + glm::dvec4(0.0, scale, 0.0, 0.0), + glm::dvec4(0.0, 0.0, scale, 0.0), + glm::dvec4(0.0, 0.0, 0.0, 1.0)); + + // TangentX: Tangent + // TangentY: Bi-tangent + // TangentZ: Normal + + if (hasNormals) { + if (duplicateVertices) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CopyNormalsForDuplicatedVertices) + for (int i = 0; i < indices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = StaticMeshBuildVertices[i]; + uint32 vertexIndex = indices[i]; + vertex.TangentX = TMeshVector3(0.0f, 0.0f, 0.0f); + vertex.TangentY = TMeshVector3(0.0f, 0.0f, 0.0f); + const TMeshVector3& normal = normalAccessor[vertexIndex]; + vertex.TangentZ.X = normal.X; + vertex.TangentZ.Y = -normal.Y; + vertex.TangentZ.Z = normal.Z; + } + } else { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CopyNormals) + for (int i = 0; i < StaticMeshBuildVertices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = StaticMeshBuildVertices[i]; + vertex.TangentX = TMeshVector3(0.0f, 0.0f, 0.0f); + vertex.TangentY = TMeshVector3(0.0f, 0.0f, 0.0f); + const TMeshVector3& normal = normalAccessor[i]; + vertex.TangentZ.X = normal.X; + vertex.TangentZ.Y = -normal.Y; + vertex.TangentZ.Z = normal.Z; + } + } + } else { + if (primitiveResult.isUnlit) { + setUnlitNormals( + StaticMeshBuildVertices, + ellipsoid, + transform * yInvertMatrix * scaleMatrix); + } else { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ComputeFlatNormals) + computeFlatNormals(StaticMeshBuildVertices); + } + } + + if (hasTangents) { + if (duplicateVertices) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CopyTangentsForDuplicatedVertices) + for (int i = 0; i < indices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = StaticMeshBuildVertices[i]; + uint32 vertexIndex = indices[i]; + const TMeshVector4& tangent = tangentAccessor[vertexIndex]; + vertex.TangentX.X = tangent.X; + vertex.TangentX.Y = -tangent.Y; + vertex.TangentX.Z = tangent.Z; + vertex.TangentY = + TMeshVector3::CrossProduct(vertex.TangentZ, vertex.TangentX) * + tangent.W; + } + } else { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CopyTangents) + for (int i = 0; i < StaticMeshBuildVertices.Num(); ++i) { + FStaticMeshBuildVertex& vertex = StaticMeshBuildVertices[i]; + const TMeshVector4& tangent = tangentAccessor[i]; + vertex.TangentX = tangent; + vertex.TangentX.X = tangent.X; + vertex.TangentX.Y = -tangent.Y; + vertex.TangentX.Z = tangent.Z; + vertex.TangentY = + TMeshVector3::CrossProduct(vertex.TangentZ, vertex.TangentX) * + tangent.W; + } + } + } + + if (needsTangents && !hasTangents) { + // Use mikktspace to calculate the tangents. + // Note that this assumes normals and UVs are already populated. + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ComputeTangents) + computeTangentSpace(StaticMeshBuildVertices); + } + + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::InitBuffers) + + // Set to full precision (32-bit) UVs. This is especially important for + // metadata because integer feature IDs can and will lose meaningful + // precision when using 16-bit floats. + LODResources.VertexBuffers.StaticMeshVertexBuffer.SetUseFullPrecisionUVs( + true); + + LODResources.VertexBuffers.PositionVertexBuffer.Init( + StaticMeshBuildVertices, + false); + + FColorVertexBuffer& ColorVertexBuffer = + LODResources.VertexBuffers.ColorVertexBuffer; + if (hasVertexColors) { + ColorVertexBuffer.Init(StaticMeshBuildVertices, false); + } + + uint32 numberOfTextureCoordinates = + gltfToUnrealTexCoordMap.size() == 0 + ? 1 + : uint32(gltfToUnrealTexCoordMap.size()); + + FStaticMeshVertexBuffer& vertexBuffer = + LODResources.VertexBuffers.StaticMeshVertexBuffer; + vertexBuffer.Init( + StaticMeshBuildVertices.Num(), + numberOfTextureCoordinates, + false); + + // Manually copy the vertices into the buffer. We do this because UE 5.3 + // and 5.4 have a bug where the overload of `FStaticMeshVertexBuffer::Init` + // taking an array of `FStaticMeshBuildVertex` will create a mesh with all 8 + // sets of texture coordinates, even when we usually only need one or two. + // See https://github.com/CesiumGS/cesium-unreal/issues/1513 + for (uint32 vertexIndex = 0; + vertexIndex < uint32(StaticMeshBuildVertices.Num()); + ++vertexIndex) { + const FStaticMeshBuildVertex& source = + StaticMeshBuildVertices[vertexIndex]; + + vertexBuffer.SetVertexTangents( + vertexIndex, + source.TangentX, + source.TangentY, + source.TangentZ); + for (uint32 uvIndex = 0; uvIndex < numberOfTextureCoordinates; + uvIndex++) { + vertexBuffer + .SetVertexUV(vertexIndex, uvIndex, source.UVs[uvIndex], false); + } + } + } + + FStaticMeshSectionArray& Sections = LODResources.Sections; + FStaticMeshSection& section = Sections.AddDefaulted_GetRef(); + // This will be ignored if the primitive contains points. + section.NumTriangles = indices.Num() / 3; + section.FirstIndex = 0; + section.MinVertexIndex = 0; + section.MaxVertexIndex = StaticMeshBuildVertices.Num() - 1; + section.bEnableCollision = + primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS; + section.bCastShadow = true; + section.MaterialIndex = 0; + + if (duplicateVertices) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ReverseWindingOrder) + for (int32 i = 0; i < indices.Num(); i++) { + indices[i] = i; + } + } + + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetIndices) + LODResources.IndexBuffer.SetIndices( + indices, + StaticMeshBuildVertices.Num() >= std::numeric_limits::max() + ? EIndexBufferStride::Type::Force32Bit + : EIndexBufferStride::Type::Force16Bit); + } + + LODResources.bHasDepthOnlyIndices = false; + LODResources.bHasReversedIndices = false; + LODResources.bHasReversedDepthOnlyIndices = false; + +#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. + RenderData->InitializeRayTracingRepresentationFromRenderingLODs(); +#endif + + primitiveResult.meshIndex = options.pMeshOptions->meshIndex; + primitiveResult.primitiveIndex = options.primitiveIndex; + primitiveResult.RenderData = std::move(RenderData); + primitiveResult.pCollisionMesh = nullptr; + + primitiveResult.transform = transform * yInvertMatrix * scaleMatrix; + + if (primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS && + options.pMeshOptions->pNodeOptions->pModelOptions->createPhysicsMeshes) { + if (StaticMeshBuildVertices.Num() != 0 && indices.Num() != 0) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ChaosCook) + primitiveResult.pCollisionMesh = + StaticMeshBuildVertices.Num() < TNumericLimits::Max() + ? BuildChaosTriangleMeshes( + StaticMeshBuildVertices, + indices) + : BuildChaosTriangleMeshes( + StaticMeshBuildVertices, + indices); + } + } +} + +static void loadIndexedPrimitive( + LoadPrimitiveResult& primitiveResult, + const glm::dmat4x4& transform, + const CreatePrimitiveOptions& options, + const CesiumGltf::Accessor& positionAccessor, + const CesiumGltf::AccessorView& positionView, + const CesiumGeospatial::Ellipsoid& ellipsoid) { + const CesiumGltf::Model& model = + *options.pMeshOptions->pNodeOptions->pModelOptions->pModel; + const CesiumGltf::MeshPrimitive& primitive = + model.meshes[options.pMeshOptions->meshIndex] + .primitives[options.primitiveIndex]; + + const CesiumGltf::Accessor& indexAccessorGltf = + model.accessors[primitive.indices]; + if (indexAccessorGltf.componentType == + CesiumGltf::Accessor::ComponentType::UNSIGNED_BYTE) { + CesiumGltf::AccessorView indexAccessor(model, primitive.indices); + loadPrimitive( + primitiveResult, + transform, + options, + positionAccessor, + positionView, + indexAccessor, + ellipsoid); + primitiveResult.IndexAccessor = indexAccessor; + } else if ( + indexAccessorGltf.componentType == + CesiumGltf::Accessor::ComponentType::UNSIGNED_SHORT) { + CesiumGltf::AccessorView indexAccessor(model, primitive.indices); + loadPrimitive( + primitiveResult, + transform, + options, + positionAccessor, + positionView, + indexAccessor, + ellipsoid); + primitiveResult.IndexAccessor = indexAccessor; + } else if ( + indexAccessorGltf.componentType == + CesiumGltf::Accessor::ComponentType::UNSIGNED_INT) { + CesiumGltf::AccessorView indexAccessor(model, primitive.indices); + loadPrimitive( + primitiveResult, + transform, + options, + positionAccessor, + positionView, + indexAccessor, + ellipsoid); + primitiveResult.IndexAccessor = indexAccessor; + } else { + UE_LOG( + LogCesium, + Warning, + TEXT( + "Ignoring a glTF primitive because the componentType (%d) of its indices is not supported."), + indexAccessorGltf.componentType); + } +} + +static void loadPrimitive( + LoadPrimitiveResult& result, + const glm::dmat4x4& transform, + const CreatePrimitiveOptions& options, + const CesiumGeospatial::Ellipsoid& ellipsoid) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadPrimitive) + + const CesiumGltf::Model& model = + *options.pMeshOptions->pNodeOptions->pModelOptions->pModel; + const CesiumGltf::MeshPrimitive& primitive = + model.meshes[options.pMeshOptions->meshIndex] + .primitives[options.primitiveIndex]; + + auto positionAccessorIt = primitive.attributes.find("POSITION"); + if (positionAccessorIt == primitive.attributes.end()) { + // This primitive doesn't have a POSITION semantic, ignore it. + return; + } + + int positionAccessorID = positionAccessorIt->second; + const CesiumGltf::Accessor* pPositionAccessor = + CesiumGltf::Model::getSafe(&model.accessors, positionAccessorID); + if (!pPositionAccessor) { + // Position accessor does not exist, so ignore this primitive. + return; + } + + CesiumGltf::AccessorView positionView( + model, + *pPositionAccessor); + + if (primitive.indices < 0 || primitive.indices >= model.accessors.size()) { + std::vector syntheticIndexBuffer(positionView.size()); + syntheticIndexBuffer.resize(positionView.size()); + for (uint32_t i = 0; i < positionView.size(); ++i) { + syntheticIndexBuffer[i] = i; + } + loadPrimitive( + result, + transform, + options, + *pPositionAccessor, + positionView, + syntheticIndexBuffer, + ellipsoid); + } else { + loadIndexedPrimitive( + result, + transform, + options, + *pPositionAccessor, + positionView, + ellipsoid); + } + result.PositionAccessor = std::move(positionView); +} + +static void loadMesh( + std::optional& result, + const glm::dmat4x4& transform, + CreateMeshOptions& options, + const CesiumGeospatial::Ellipsoid& ellipsoid) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadMesh) + + CesiumGltf::Model& model = *options.pNodeOptions->pModelOptions->pModel; + CesiumGltf::Mesh& mesh = model.meshes[options.meshIndex]; + + result = LoadMeshResult(); + result->primitiveResults.reserve(mesh.primitives.size()); + for (size_t i = 0; i < mesh.primitives.size(); i++) { + CreatePrimitiveOptions primitiveOptions = {&options, &*result, i}; + auto& primitiveResult = result->primitiveResults.emplace_back(); + loadPrimitive(primitiveResult, transform, primitiveOptions, ellipsoid); + + // if it doesn't have render data, then it can't be loaded + if (!primitiveResult.RenderData) { + result->primitiveResults.pop_back(); + } + } +} + +// Helpers for different instancing rotation formats + +namespace { +template struct is_float_quat : std::false_type {}; + +template <> +struct is_float_quat> : std::true_type { +}; + +template struct is_int_quat : std::false_type {}; + +template +struct is_int_quat> + : std::conjunction, std::is_signed> {}; + +template +inline constexpr bool is_float_quat_v = is_float_quat::value; + +template +inline constexpr bool is_int_quat_v = is_int_quat::value; +} // namespace + +static void loadInstancingData( + const CesiumGltf::Model& model, + const CesiumGltf::Node& node, + LoadNodeResult& result, + const CesiumGltf::ExtensionExtMeshGpuInstancing* pGpuInstancing, + const CesiumGltf::ExtensionExtInstanceFeatures* pInstanceFeatures) { + auto getInstanceAccessor = + [&](const char* name) -> const CesiumGltf::Accessor* { + if (auto accessorItr = pGpuInstancing->attributes.find(name); + accessorItr != pGpuInstancing->attributes.end()) { + return CesiumGltf::Model::getSafe(&model.accessors, accessorItr->second); + } + return nullptr; + }; + const CesiumGltf::Accessor* translations = getInstanceAccessor("TRANSLATION"); + const CesiumGltf::Accessor* rotations = getInstanceAccessor("ROTATION"); + const CesiumGltf::Accessor* scales = getInstanceAccessor("SCALE"); + + int64_t count = 0; + if (translations) { + count = translations->count; + } + if (rotations) { + if (count == 0) { + count = rotations->count; + } else if (count != rotations->count) { + UE_LOG( + LogCesium, + Warning, + TEXT("instance rotation count %d not consistent with %d"), + rotations->count, + count); + return; + } + } + if (scales) { + if (count == 0) { + count = scales->count; + } else if (count != scales->count) { + UE_LOG( + LogCesium, + Warning, + TEXT("instance scale count %d not consistent with %d"), + scales->count, + count); + return; + } + } + if (count == 0) { + UE_LOG(LogCesium, Warning, TEXT("No valid instance data")); + return; + } + // The glTF instance transforms need to be transformed into the local + // coordinate system of the Unreal static mesh i.e., Unreals' left-handed + // system. Another way to think about it is that the geometry, which is stored + // in the Unreal system, must be transformed to glTF, have the instance + // transform applied, and then be transformed back to Unreal. It's tempting to + // do this by trying some manipulation of the individual glTF instance + // operations, but that general approach has always ended in tears for me. + // Better to formally multiply out the matrices and be assured that the + // operation is correct. + std::vector instanceTransforms(count, glm::dmat4(1.0)); + + // Note: the glm functions translate() and scale() post-multiply the matrix + // argument by the new transform. E.g., translate() does *not* translate the + // matrix. + if (translations) { + CesiumGltf::AccessorView translationAccessor( + model, + *translations); + if (translationAccessor.status() == CesiumGltf::AccessorViewStatus::Valid) { + for (int64_t i = 0; i < count; ++i) { + glm::dvec3 translation(translationAccessor[i]); + instanceTransforms[i] = glm::translate( + instanceTransforms[i], + translation * CesiumPrimitiveData::positionScaleFactor); + } + } + } else { + UE_LOG( + LogCesium, + Warning, + TEXT("Invalid accessor for instance translations")); + } + if (rotations) { + createAccessorView(model, *rotations, [&](auto&& quatView) -> void { + using QuatType = decltype(quatView[0]); + using ValueType = std::decay_t; + if constexpr (is_float_quat_v) { + for (int i = 0; i < count; ++i) { + glm::dquat quat( + quatView[i].value[3], + quatView[i].value[0], + quatView[i].value[1], + quatView[i].value[2]); + instanceTransforms[i] = instanceTransforms[i] * glm::mat4_cast(quat); + } + } else if constexpr (is_int_quat_v) { + for (int64_t i = 0; i < count; ++i) { + float val[4]; + for (int j = 0; j < 4; ++j) { + val[j] = GltfNormalized(quatView[i].value[j]); + } + glm::dquat quat(val[3], val[0], val[1], val[2]); + instanceTransforms[i] = instanceTransforms[i] * glm::mat4_cast(quat); + } + } + }); + } + if (scales) { + CesiumGltf::AccessorView scaleAccessor(model, *scales); + for (int64_t i = 0; i < count; ++i) { + glm::dvec3 scaleFactors(scaleAccessor[i]); + instanceTransforms[i] = glm::scale(instanceTransforms[i], scaleFactors); + } + } else { + UE_LOG(LogCesium, Warning, TEXT("Invalid accessor for instance scales")); + } + result.InstanceTransforms.resize(count); + for (int64_t i = 0; i < count; ++i) { + glm::dmat4 unrealMat = + yInvertMatrix * instanceTransforms[i] * yInvertMatrix; + auto unrealFMatrix = VecMath::createMatrix(unrealMat); + result.InstanceTransforms[i].SetFromMatrix(unrealFMatrix); + } + if (pInstanceFeatures) { + result.pInstanceFeatures = + MakeShared(model, node, *pInstanceFeatures); + } +} + +static void loadNode( + std::vector& loadNodeResults, + const glm::dmat4x4& transform, + CreateNodeOptions& options, + const CesiumGeospatial::Ellipsoid& ellipsoid) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadNode) + + static constexpr std::array identityMatrix = { + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0}; + + CesiumGltf::Model& model = *options.pModelOptions->pModel; + const CesiumGltf::Node& node = *options.pNode; + + LoadNodeResult& result = loadNodeResults.emplace_back(); + + glm::dmat4x4 nodeTransform = transform; + + const std::vector& matrix = node.matrix; + bool isIdentityMatrix = false; + if (matrix.size() == 16) { + isIdentityMatrix = + std::equal(matrix.begin(), matrix.end(), identityMatrix.begin()); + } + + if (matrix.size() == 16 && !isIdentityMatrix) { + glm::dmat4x4 nodeTransformGltf( + glm::dvec4(matrix[0], matrix[1], matrix[2], matrix[3]), + glm::dvec4(matrix[4], matrix[5], matrix[6], matrix[7]), + glm::dvec4(matrix[8], matrix[9], matrix[10], matrix[11]), + glm::dvec4(matrix[12], matrix[13], matrix[14], matrix[15])); + + nodeTransform = nodeTransform * nodeTransformGltf; + } else { + glm::dmat4 translation(1.0); + if (node.translation.size() == 3) { + translation[3] = glm::dvec4( + node.translation[0], + node.translation[1], + node.translation[2], + 1.0); + } + + glm::dquat rotationQuat(1.0, 0.0, 0.0, 0.0); + if (node.rotation.size() == 4) { + rotationQuat[0] = node.rotation[0]; + rotationQuat[1] = node.rotation[1]; + rotationQuat[2] = node.rotation[2]; + rotationQuat[3] = node.rotation[3]; + } + + glm::dmat4 scale(1.0); + if (node.scale.size() == 3) { + scale[0].x = node.scale[0]; + scale[1].y = node.scale[1]; + scale[2].z = node.scale[2]; + } + + nodeTransform = + nodeTransform * translation * glm::dmat4(rotationQuat) * scale; + } + + int meshId = node.mesh; + if (meshId >= 0 && meshId < model.meshes.size()) { + if (const auto* pGpuInstancingExtension = + node.getExtension()) { + loadInstancingData( + model, + node, + result, + pGpuInstancingExtension, + node.getExtension()); + } + CreateMeshOptions meshOptions = {&options, &result, meshId}; + loadMesh(result.meshResult, nodeTransform, meshOptions, ellipsoid); + } + + for (int childNodeId : node.children) { + if (childNodeId >= 0 && childNodeId < model.nodes.size()) { + CreateNodeOptions childNodeOptions = { + options.pModelOptions, + options.pHalfConstructedModelResult, + &model.nodes[childNodeId]}; + loadNode(loadNodeResults, nodeTransform, childNodeOptions, ellipsoid); + } + } +} + +namespace { +/** + * @brief Apply the transform so that the up-axis of the given model is the + * Z-axis. + * + * By default, the up-axis of a glTF model will the the Y-axis. + * + * If the tileset that contained the model had the `asset.gltfUpAxis` string + * property, then the information about the up-axis has been stored in as a + * number property called `gltfUpAxis` in the `extras` of the given model. + * + * Depending on whether this value is CesiumGeometry::Axis::X, Y, or Z, + * the given matrix will be multiplied with a matrix that converts the + * respective axis to be the Z-axis, as required by the 3D Tiles standard. + * + * @param model The glTF model + * @param rootTransform The matrix that will be multiplied with the transform + */ +void applyGltfUpAxisTransform( + const CesiumGltf::Model& model, + glm::dmat4x4& rootTransform) { + + auto gltfUpAxisIt = model.extras.find("gltfUpAxis"); + if (gltfUpAxisIt == model.extras.end()) { + // The default up-axis of glTF is the Y-axis, and no other + // up-axis was specified. Transform the Y-axis to the Z-axis, + // to match the 3D Tiles specification + rootTransform *= CesiumGeometry::Transforms::Y_UP_TO_Z_UP; + return; + } + const CesiumUtility::JsonValue& gltfUpAxis = gltfUpAxisIt->second; + int gltfUpAxisValue = static_cast(gltfUpAxis.getSafeNumberOrDefault(1)); + if (gltfUpAxisValue == static_cast(CesiumGeometry::Axis::X)) { + rootTransform *= CesiumGeometry::Transforms::X_UP_TO_Z_UP; + } else if (gltfUpAxisValue == static_cast(CesiumGeometry::Axis::Y)) { + rootTransform *= CesiumGeometry::Transforms::Y_UP_TO_Z_UP; + } else if (gltfUpAxisValue == static_cast(CesiumGeometry::Axis::Z)) { + // No transform required + } else { + UE_LOG( + LogCesium, + Warning, + TEXT("Ignoring unknown gltfUpAxis value: {}"), + gltfUpAxisValue); + } +} + +} // namespace + +static void +loadModelMetadata(LoadModelResult& result, const CreateModelOptions& options) { + CesiumGltf::Model& model = *options.pModel; + + CesiumGltf::ExtensionModelExtStructuralMetadata* pModelMetadata = + model.getExtension(); + if (!pModelMetadata) { + return; + } + + model.forEachPrimitiveInScene( + model.scene, + [pModelMetadata]( + CesiumGltf::Model& gltf, + CesiumGltf::Node& /*node*/, + CesiumGltf::Mesh& /*mesh*/, + CesiumGltf::MeshPrimitive& primitive, + const glm::dmat4& /*nodeTransform*/) { + const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata* + pPrimitiveMetadata = primitive.getExtension< + CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata>(); + if (!pPrimitiveMetadata) { + return; + } + + int32_t materialIndex = primitive.material; + if (materialIndex < 0 || materialIndex >= gltf.materials.size()) { + return; + } + + const CesiumGltf::Material& material = + gltf.materials[primitive.material]; + + for (const auto& propertyTextureIndex : + pPrimitiveMetadata->propertyTextures) { + if (propertyTextureIndex < 0 || + static_cast(propertyTextureIndex) >= + pModelMetadata->propertyTextures.size()) { + continue; + } + + CesiumGltf::PropertyTexture& propertyTexture = + pModelMetadata->propertyTextures[propertyTextureIndex]; + + for (auto& propertyIt : propertyTexture.properties) { + if (propertyIt.second.extras.find("makeImageCopy") != + propertyIt.second.extras.end()) { + continue; + } + + int32_t textureIndex = propertyIt.second.index; + if (textureIndex < 0 || textureIndex > gltf.textures.size()) { + continue; + } + + const CesiumGltf::Texture& texture = gltf.textures[textureIndex]; + if (texture.source < 0 || texture.source >= gltf.images.size()) { + continue; + } + + if (hasMaterialTextureConflicts(gltf, material, texture.source)) { + // Add a flag in the extras to indicate a copy should be made. + // This is checked for in FCesiumPropertyTexture. + propertyIt.second.extras.insert({"makeImageCopy", true}); + } + } + } + }); + + result.Metadata = FCesiumModelMetadata(model, *pModelMetadata); + + const FCesiumFeaturesMetadataDescription* pFeaturesMetadataDescription = + options.pFeaturesMetadataDescription; + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + const FMetadataDescription* pMetadataDescription_DEPRECATED = + options.pEncodedMetadataDescription_DEPRECATED; + if (pFeaturesMetadataDescription) { + result.EncodedMetadata = + CesiumEncodedFeaturesMetadata::encodeModelMetadataAnyThreadPart( + pFeaturesMetadataDescription->ModelMetadata, + result.Metadata); + } else if (pMetadataDescription_DEPRECATED) { + result.EncodedMetadata_DEPRECATED = + CesiumEncodedMetadataUtility::encodeMetadataAnyThreadPart( + *pMetadataDescription_DEPRECATED, + result.Metadata); + } + PRAGMA_ENABLE_DEPRECATION_WARNINGS +} + +static CesiumAsync::Future +loadModelAnyThreadPart( + const CesiumAsync::AsyncSystem& asyncSystem, + const glm::dmat4x4& transform, + CreateModelOptions&& options, + const CesiumGeospatial::Ellipsoid& ellipsoid) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadModelAnyThreadPart) + + return CesiumGltfTextures::createInWorkerThread(asyncSystem, *options.pModel) + .thenInWorkerThread( + [transform, ellipsoid, options = std::move(options)]() mutable + -> UCesiumGltfComponent::CreateOffGameThreadResult { + auto pHalf = MakeUnique(); + + loadModelMetadata(pHalf->loadModelResult, options); + + glm::dmat4x4 rootTransform = transform; + + CesiumGltf::Model& model = *options.pModel; + + { + rootTransform = CesiumGltfContent::GltfUtilities::applyRtcCenter( + model, + rootTransform); + applyGltfUpAxisTransform(model, rootTransform); + } + + if (model.scene >= 0 && model.scene < model.scenes.size()) { + // Show the default scene + const CesiumGltf::Scene& defaultScene = model.scenes[model.scene]; + for (int nodeId : defaultScene.nodes) { + CreateNodeOptions nodeOptions = { + &options, + &pHalf->loadModelResult, + &model.nodes[nodeId]}; + loadNode( + pHalf->loadModelResult.nodeResults, + rootTransform, + nodeOptions, + ellipsoid); + } + } else if (model.scenes.size() > 0) { + // There's no default, so show the first scene + const CesiumGltf::Scene& defaultScene = model.scenes[0]; + for (int nodeId : defaultScene.nodes) { + CreateNodeOptions nodeOptions = { + &options, + &pHalf->loadModelResult, + &model.nodes[nodeId]}; + loadNode( + pHalf->loadModelResult.nodeResults, + rootTransform, + nodeOptions, + ellipsoid); + } + } else if (model.nodes.size() > 0) { + // No scenes at all, use the first node as the root node. + CreateNodeOptions nodeOptions = { + &options, + &pHalf->loadModelResult, + &model.nodes[0]}; + loadNode( + pHalf->loadModelResult.nodeResults, + rootTransform, + nodeOptions, + ellipsoid); + } else if (model.meshes.size() > 0) { + // No nodes either, show all the meshes. + for (size_t i = 0; i < model.meshes.size(); i++) { + CreateNodeOptions dummyNodeOptions = { + &options, + &pHalf->loadModelResult, + nullptr}; + LoadNodeResult& dummyNodeResult = + pHalf->loadModelResult.nodeResults.emplace_back(); + CreateMeshOptions meshOptions = { + &dummyNodeOptions, + &dummyNodeResult, + i}; + loadMesh( + dummyNodeResult.meshResult, + rootTransform, + meshOptions, + ellipsoid); + } + } + + UCesiumGltfComponent::CreateOffGameThreadResult result; + result.HalfConstructed = std::move(pHalf); + result.TileLoadResult = std::move(options.tileLoadResult); + + return result; + }); +} + +bool applyTexture( + CesiumGltf::Model& model, + UMaterialInstanceDynamic* pMaterial, + const FMaterialParameterInfo& info, + CesiumTextureUtility::LoadedTextureResult* pLoadedTexture) { + CesiumUtility::IntrusivePointer< + CesiumTextureUtility::ReferenceCountedUnrealTexture> + pTexture = CesiumTextureUtility::loadTextureGameThreadPart( + model, + pLoadedTexture); + if (!pTexture) { + return false; + } + + pMaterial->SetTextureParameterValueByInfo(info, pTexture->getUnrealTexture()); + + return true; +} + +#pragma region Material Parameter setters + +static void SetGltfParameterValues( + CesiumGltf::Model& model, + LoadPrimitiveResult& loadResult, + const CesiumGltf::Material& material, + const CesiumGltf::MaterialPBRMetallicRoughness& pbr, + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index) { + for (auto& textureCoordinateSet : loadResult.textureCoordinateParameters) { + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo( + UTF8_TO_TCHAR(textureCoordinateSet.first.c_str()), + association, + index), + static_cast(textureCoordinateSet.second)); + } + + if (pbr.baseColorFactor.size() > 3) { + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo("baseColorFactor", association, index), + FLinearColor( + pbr.baseColorFactor[0], + pbr.baseColorFactor[1], + pbr.baseColorFactor[2], + pbr.baseColorFactor[3])); + } else if (pbr.baseColorFactor.size() == 3) { + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo("baseColorFactor", association, index), + FLinearColor( + pbr.baseColorFactor[0], + pbr.baseColorFactor[1], + pbr.baseColorFactor[2], + 1.)); + } else { + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo("baseColorFactor", association, index), + FLinearColor(1., 1., 1., 1.)); + } + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo("metallicFactor", association, index), + static_cast(loadResult.isUnlit ? 0.0f : pbr.metallicFactor)); + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo("roughnessFactor", association, index), + static_cast(loadResult.isUnlit ? 1.0f : pbr.roughnessFactor)); + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo("opacityMask", association, index), + 1.0f); + + applyTexture( + model, + pMaterial, + FMaterialParameterInfo("baseColorTexture", association, index), + loadResult.baseColorTexture.Get()); + applyTexture( + model, + pMaterial, + FMaterialParameterInfo("metallicRoughnessTexture", association, index), + loadResult.metallicRoughnessTexture.Get()); + applyTexture( + model, + pMaterial, + FMaterialParameterInfo("normalTexture", association, index), + loadResult.normalTexture.Get()); + bool hasEmissiveTexture = applyTexture( + model, + pMaterial, + FMaterialParameterInfo("emissiveTexture", association, index), + loadResult.emissiveTexture.Get()); + applyTexture( + model, + pMaterial, + FMaterialParameterInfo("occlusionTexture", association, index), + loadResult.occlusionTexture.Get()); + + CesiumGltf::KhrTextureTransform textureTransform; + FLinearColor baseColorMetallicRoughnessRotation(0.0f, 1.0f, 0.0f, 1.0f); + const CesiumGltf::ExtensionKhrTextureTransform* pBaseColorTextureTransform = + pbr.baseColorTexture + ? pbr.baseColorTexture + ->getExtension() + : nullptr; + + if (pBaseColorTextureTransform) { + textureTransform = + CesiumGltf::KhrTextureTransform(*pBaseColorTextureTransform); + if (textureTransform.status() == + CesiumGltf::KhrTextureTransformStatus::Valid) { + const glm::dvec2& scale = textureTransform.scale(); + const glm::dvec2& offset = textureTransform.offset(); + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo("baseColorScaleOffset", association, index), + FLinearColor(scale[0], scale[1], offset[0], offset[1])); + + const glm::dvec2& rotationSineCosine = + textureTransform.rotationSineCosine(); + baseColorMetallicRoughnessRotation.R = rotationSineCosine[0]; + baseColorMetallicRoughnessRotation.G = rotationSineCosine[1]; + } + } + + const CesiumGltf::ExtensionKhrTextureTransform* + pMetallicRoughnessTextureTransform = + pbr.metallicRoughnessTexture + ? pbr.metallicRoughnessTexture + ->getExtension() + : nullptr; + + if (pMetallicRoughnessTextureTransform) { + textureTransform = + CesiumGltf::KhrTextureTransform(*pMetallicRoughnessTextureTransform); + if (textureTransform.status() == + CesiumGltf::KhrTextureTransformStatus::Valid) { + const glm::dvec2& scale = textureTransform.scale(); + const glm::dvec2& offset = textureTransform.offset(); + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo( + "metallicRoughnessScaleOffset", + association, + index), + FLinearColor(scale[0], scale[1], offset[0], offset[1])); + + const glm::dvec2& rotationSineCosine = + textureTransform.rotationSineCosine(); + baseColorMetallicRoughnessRotation.B = rotationSineCosine[0]; + baseColorMetallicRoughnessRotation.A = rotationSineCosine[1]; + } + } + + if (pBaseColorTextureTransform || pMetallicRoughnessTextureTransform) { + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo( + "baseColorMetallicRoughnessRotation", + association, + index), + baseColorMetallicRoughnessRotation); + } + + FLinearColor emissiveNormalRotation(0.0f, 1.0f, 0.0f, 1.0f); + + const CesiumGltf::ExtensionKhrTextureTransform* pEmissiveTextureTransform = + material.emissiveTexture + ? material.emissiveTexture + ->getExtension() + : nullptr; + + if (pEmissiveTextureTransform) { + textureTransform = + CesiumGltf::KhrTextureTransform(*pEmissiveTextureTransform); + const glm::dvec2& scale = textureTransform.scale(); + const glm::dvec2& offset = textureTransform.offset(); + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo("emissiveScaleOffset", association, index), + FLinearColor(scale[0], scale[1], offset[0], offset[1])); + + const glm::dvec2& rotationSineCosine = + textureTransform.rotationSineCosine(); + emissiveNormalRotation.R = rotationSineCosine[0]; + emissiveNormalRotation.G = rotationSineCosine[1]; + } + + const CesiumGltf::ExtensionKhrTextureTransform* pNormalTextureTransform = + material.normalTexture + ? material.normalTexture + ->getExtension() + : nullptr; + + if (pNormalTextureTransform) { + textureTransform = + CesiumGltf::KhrTextureTransform(*pNormalTextureTransform); + const glm::dvec2& scale = textureTransform.scale(); + const glm::dvec2& offset = textureTransform.offset(); + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo("normalScaleOffset", association, index), + FLinearColor(scale[0], scale[1], offset[0], offset[1])); + const glm::dvec2& rotationSineCosine = + textureTransform.rotationSineCosine(); + emissiveNormalRotation.B = rotationSineCosine[0]; + emissiveNormalRotation.A = rotationSineCosine[1]; + } + + if (pEmissiveTextureTransform || pNormalTextureTransform) { + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo("emissiveNormalRotation", association, index), + emissiveNormalRotation); + } + + const CesiumGltf::ExtensionKhrTextureTransform* pOcclusionTransform = + material.occlusionTexture + ? material.occlusionTexture + ->getExtension() + : nullptr; + + if (pOcclusionTransform) { + textureTransform = CesiumGltf::KhrTextureTransform(*pOcclusionTransform); + const glm::dvec2& scale = textureTransform.scale(); + const glm::dvec2& offset = textureTransform.offset(); + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo("occlusionScaleOffset", association, index), + FLinearColor(scale[0], scale[1], offset[0], offset[1])); + + const glm::dvec2& rotationSineCosine = + textureTransform.rotationSineCosine(); + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo("occlusionRotation", association, index), + FLinearColor( + float(rotationSineCosine[0]), + float(rotationSineCosine[1]), + 0.0f, + 1.0f)); + } + + if (material.emissiveFactor.size() >= 3) { + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo("emissiveFactor", association, index), + FVector( + material.emissiveFactor[0], + material.emissiveFactor[1], + material.emissiveFactor[2])); + } else if (hasEmissiveTexture) { + // When we have an emissive texture but not a factor, we need to use a + // factor of vec3(1.0). The default, vec3(0.0), would disable the emission + // from the texture. + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo("emissiveFactor", association, index), + FVector(1.0f, 1.0f, 1.0f)); + } +} + +void SetWaterParameterValues( + CesiumGltf::Model& model, + LoadPrimitiveResult& loadResult, + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index) { + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo("OnlyLand", association, index), + static_cast(loadResult.onlyLand)); + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo("OnlyWater", association, index), + static_cast(loadResult.onlyWater)); + + if (!loadResult.onlyLand && !loadResult.onlyWater) { + applyTexture( + model, + pMaterial, + FMaterialParameterInfo("WaterMask", association, index), + loadResult.waterMaskTexture.Get()); + } + + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo("WaterMaskTranslationScale", association, index), + FVector( + loadResult.waterMaskTranslationX, + loadResult.waterMaskTranslationY, + loadResult.waterMaskScale)); +} + +static void SetFeaturesMetadataParameterValues( + const CesiumGltf::Model& model, + UCesiumGltfComponent& gltfComponent, + LoadPrimitiveResult& loadResult, + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index) { + // This handles texture coordinate indices for both attribute feature ID + // sets and property textures. + for (const auto& textureCoordinateSet : + loadResult.FeaturesMetadataTexCoordParameters) { + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo( + FName(textureCoordinateSet.Key), + association, + index), + textureCoordinateSet.Value); + } + + if (encodePrimitiveFeaturesGameThreadPart(loadResult.EncodedFeatures)) { + for (CesiumEncodedFeaturesMetadata::EncodedFeatureIdSet& + encodedFeatureIdSet : loadResult.EncodedFeatures.featureIdSets) { + FString SafeName = CesiumEncodedFeaturesMetadata::createHlslSafeName( + encodedFeatureIdSet.name); + if (encodedFeatureIdSet.nullFeatureId) { + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo( + FName( + SafeName + + CesiumEncodedFeaturesMetadata::MaterialNullFeatureIdSuffix), + association, + index), + static_cast(*encodedFeatureIdSet.nullFeatureId)); + } + + if (encodedFeatureIdSet.texture) { + CesiumEncodedFeaturesMetadata::SetFeatureIdTextureParameterValues( + pMaterial, + association, + index, + SafeName, + *encodedFeatureIdSet.texture); + } + } + + for (const CesiumEncodedFeaturesMetadata::EncodedPropertyTexture& + propertyTexture : gltfComponent.EncodedMetadata.propertyTextures) { + CesiumEncodedFeaturesMetadata::SetPropertyTextureParameterValues( + pMaterial, + association, + index, + propertyTexture); + } + + for (const CesiumEncodedFeaturesMetadata::EncodedPropertyTable& + propertyTable : gltfComponent.EncodedMetadata.propertyTables) { + CesiumEncodedFeaturesMetadata::SetPropertyTableParameterValues( + pMaterial, + association, + index, + propertyTable); + } + } +} + +static void SetMetadataFeatureTableParameterValues_DEPRECATED( + const CesiumEncodedMetadataUtility::EncodedMetadataFeatureTable& + encodedFeatureTable, + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index) { + for (const CesiumEncodedMetadataUtility::EncodedMetadataProperty& + encodedProperty : encodedFeatureTable.encodedProperties) { + + pMaterial->SetTextureParameterValueByInfo( + FMaterialParameterInfo(FName(encodedProperty.name), association, index), + encodedProperty.pTexture->pTexture->getUnrealTexture()); + } +} + +PRAGMA_DISABLE_DEPRECATION_WARNINGS +static void SetMetadataParameterValues_DEPRECATED( + const CesiumGltf::Model& model, + UCesiumGltfComponent& gltfComponent, + LoadPrimitiveResult& loadResult, + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index) { + /** + * The following is the naming convention for deprecated encoded metadata: + * + * Feature Id Textures: + * - Base: "FIT__"... + * - Texture: ..."TX" + * - Texture Coordinate Index: ..."UV" + * - Channel Mask: ..."CM" + * + * Feature Id Attributes: + * - Texture Coordinate Index (feature ids are encoded into UVs): + * "FA_" + * + * Feature Texture Properties: + * - Base: "FTX___"... + * - Texture: ..."TX" + * - Texture Coordinate Index: ..."UV" + * - Swizzle: ..."SW" + * + * Encoded Feature Table Properties: + * - Encoded Property Table: + * "FTB__" + */ + + if (!loadResult.EncodedMetadata_DEPRECATED || + !encodeMetadataPrimitiveGameThreadPart( + *loadResult.EncodedMetadata_DEPRECATED)) { + return; + } + + for (const auto& textureCoordinateSet : + loadResult.FeaturesMetadataTexCoordParameters) { + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo( + FName(textureCoordinateSet.Key), + association, + index), + textureCoordinateSet.Value); + } + + for (const FString& featureTextureName : + loadResult.EncodedMetadata_DEPRECATED->featureTextureNames) { + CesiumEncodedMetadataUtility::EncodedFeatureTexture* + pEncodedFeatureTexture = + gltfComponent.EncodedMetadata_DEPRECATED->encodedFeatureTextures + .Find(featureTextureName); + + if (pEncodedFeatureTexture) { + for (CesiumEncodedMetadataUtility::EncodedFeatureTextureProperty& + encodedProperty : pEncodedFeatureTexture->properties) { + + pMaterial->SetTextureParameterValueByInfo( + FMaterialParameterInfo( + FName(encodedProperty.baseName + "TX"), + association, + index), + encodedProperty.pTexture->pTexture->getUnrealTexture()); + + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo( + FName(encodedProperty.baseName + "SW"), + association, + index), + FLinearColor( + encodedProperty.channelOffsets[0], + encodedProperty.channelOffsets[1], + encodedProperty.channelOffsets[2], + encodedProperty.channelOffsets[3])); + } + } + } + + for (CesiumEncodedMetadataUtility::EncodedFeatureIdTexture& + encodedFeatureIdTexture : + loadResult.EncodedMetadata_DEPRECATED->encodedFeatureIdTextures) { + + pMaterial->SetTextureParameterValueByInfo( + FMaterialParameterInfo( + FName(encodedFeatureIdTexture.baseName + "TX"), + association, + index), + encodedFeatureIdTexture.pTexture->pTexture->getUnrealTexture()); + + FLinearColor channelMask; + switch (encodedFeatureIdTexture.channel) { + case 1: + channelMask = FLinearColor::Green; + break; + case 2: + channelMask = FLinearColor::Blue; + break; + default: + channelMask = FLinearColor::Red; + } + + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo( + FName(encodedFeatureIdTexture.baseName + "CM"), + association, + index), + channelMask); + + const CesiumEncodedMetadataUtility::EncodedMetadataFeatureTable* + pEncodedFeatureTable = + gltfComponent.EncodedMetadata_DEPRECATED->encodedFeatureTables.Find( + encodedFeatureIdTexture.featureTableName); + + if (pEncodedFeatureTable) { + SetMetadataFeatureTableParameterValues_DEPRECATED( + *pEncodedFeatureTable, + pMaterial, + association, + index); + } + } + + for (const CesiumEncodedMetadataUtility::EncodedFeatureIdAttribute& + encodedFeatureIdAttribute : + loadResult.EncodedMetadata_DEPRECATED->encodedFeatureIdAttributes) { + const CesiumEncodedMetadataUtility::EncodedMetadataFeatureTable* + pEncodedFeatureTable = + gltfComponent.EncodedMetadata_DEPRECATED->encodedFeatureTables.Find( + encodedFeatureIdAttribute.featureTableName); + + if (pEncodedFeatureTable) { + SetMetadataFeatureTableParameterValues_DEPRECATED( + *pEncodedFeatureTable, + pMaterial, + association, + index); + } + } +} +PRAGMA_ENABLE_DEPRECATION_WARNINGS +#pragma endregion + +namespace { +void addInstanceFeatureIds( + UCesiumGltfInstancedComponent* pInstancedComponent, + const FCesiumFeaturesMetadataDescription& featuresDescription) { + const TSharedPtr& pInstanceFeatures = + pInstancedComponent->pInstanceFeatures; + if (!pInstanceFeatures) { + return; + } + const TArray& allFeatureIdSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets( + *pInstanceFeatures); + + const TArray& featureIDSetDescriptions = + featuresDescription.Features.FeatureIdSets; + + int32_t featureIdTextureCounter = 0; + + TArray activeFeatureIdSets; + + for (int32 i = 0; i < allFeatureIdSets.Num(); ++i) { + FString name = CesiumEncodedFeaturesMetadata::getNameForFeatureIDSet( + allFeatureIdSets[i], + featureIdTextureCounter); + + const FCesiumFeatureIdSetDescription* pDescription = + featureIDSetDescriptions.FindByPredicate( + [&name]( + const FCesiumFeatureIdSetDescription& existingFeatureIDSet) { + return existingFeatureIDSet.Name == name; + }); + + if (pDescription) { + activeFeatureIdSets.Emplace(i); + } + } + + int32 featureSetCount = activeFeatureIdSets.Num(); + if (featureSetCount == 0) { + return; + } + pInstancedComponent->SetNumCustomDataFloats(featureSetCount); + int32 numInstances = pInstancedComponent->GetInstanceCount(); + pInstancedComponent->PerInstanceSMCustomData.SetNum( + featureSetCount * numInstances); + for (int32 j = 0; j < featureSetCount; ++j) { + int64_t setIndex = activeFeatureIdSets[j]; + + for (int32 i = 0; i < numInstances; ++i) { + int64 featureId = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromInstance( + *pInstanceFeatures, + i, + setIndex); + pInstancedComponent + ->SetCustomDataValue(i, j, static_cast(featureId), true); + } + } +} +} // namespace + +static void loadPrimitiveGameThreadPart( + CesiumGltf::Model& model, + UCesiumGltfComponent* pGltf, + LoadPrimitiveResult& loadResult, + const glm::dmat4x4& cesiumToUnrealTransform, + const Cesium3DTilesSelection::Tile& tile, + bool createNavCollision, + ACesium3DTileset* pTilesetActor, + const std::vector& instanceTransforms, + const TSharedPtr& pInstanceFeatures) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::LoadPrimitive) + +#if DEBUG_GLTF_ASSET_NAMES + FName componentName = createSafeName(loadResult.name, ""); +#else + FName componentName = ""; +#endif + + const Cesium3DTilesSelection::BoundingVolume& boundingVolume = + tile.getContentBoundingVolume().value_or(tile.getBoundingVolume()); + + CesiumGltf::MeshPrimitive& meshPrimitive = + model.meshes[loadResult.meshIndex].primitives[loadResult.primitiveIndex]; + + UStaticMeshComponent* pMesh = nullptr; + ICesiumPrimitive* pCesiumPrimitive = nullptr; + if (meshPrimitive.mode == CesiumGltf::MeshPrimitive::Mode::POINTS) { + UCesiumGltfPointsComponent* pPointMesh = + NewObject(pGltf, componentName); + pPointMesh->UsesAdditiveRefinement = + tile.getRefine() == Cesium3DTilesSelection::TileRefine::Add; + pPointMesh->GeometricError = static_cast(tile.getGeometricError()); + pPointMesh->Dimensions = loadResult.dimensions; + pMesh = pPointMesh; + pCesiumPrimitive = pPointMesh; + } else if (!instanceTransforms.empty()) { + auto* pInstancedComponent = + NewObject(pGltf, componentName); + pMesh = pInstancedComponent; + for (const FTransform& transform : instanceTransforms) { + pInstancedComponent->AddInstance(transform, false); + } + pInstancedComponent->pInstanceFeatures = pInstanceFeatures; + + const std::optional& + maybeFeaturesDescription = + pTilesetActor->getFeaturesMetadataDescription(); + if (maybeFeaturesDescription) { + addInstanceFeatureIds(pInstancedComponent, *maybeFeaturesDescription); + } + + pCesiumPrimitive = pInstancedComponent; + } else { + auto* pComponent = + NewObject(pGltf, componentName); + pMesh = pComponent; + pCesiumPrimitive = pComponent; + } + CesiumPrimitiveData& primData = pCesiumPrimitive->getPrimitiveData(); + + UStaticMesh* pStaticMesh; + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetupMesh) + primData.pTilesetActor = pTilesetActor; + primData.overlayTextureCoordinateIDToUVIndex = + loadResult.overlayTextureCoordinateIDToUVIndex; + primData.GltfToUnrealTexCoordMap = + std::move(loadResult.GltfToUnrealTexCoordMap); + primData.TexCoordAccessorMap = std::move(loadResult.TexCoordAccessorMap); + primData.PositionAccessor = std::move(loadResult.PositionAccessor); + primData.IndexAccessor = std::move(loadResult.IndexAccessor); + primData.HighPrecisionNodeTransform = loadResult.transform; + pCesiumPrimitive->UpdateTransformFromCesium(cesiumToUnrealTransform); + pMesh->bUseDefaultCollision = false; + pMesh->SetCollisionObjectType(ECollisionChannel::ECC_WorldStatic); + pMesh->SetFlags( + RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + primData.pModel = &model; + primData.pMeshPrimitive = &meshPrimitive; + primData.boundingVolume = boundingVolume; + pMesh->SetRenderCustomDepth(pGltf->CustomDepthParameters.RenderCustomDepth); + pMesh->SetCustomDepthStencilWriteMask( + pGltf->CustomDepthParameters.CustomDepthStencilWriteMask); + pMesh->SetCustomDepthStencilValue( + pGltf->CustomDepthParameters.CustomDepthStencilValue); + if (loadResult.isUnlit) { + pMesh->bCastDynamicShadow = false; + } + + pStaticMesh = NewObject(pMesh, componentName); + pMesh->SetStaticMesh(pStaticMesh); + + pStaticMesh->SetFlags( + RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + pStaticMesh->NeverStream = true; + + pStaticMesh->SetRenderData(std::move(loadResult.RenderData)); + } + + const CesiumGltf::Material& material = + loadResult.materialIndex != -1 ? model.materials[loadResult.materialIndex] + : defaultMaterial; + + const CesiumGltf::MaterialPBRMetallicRoughness& pbr = + material.pbrMetallicRoughness ? material.pbrMetallicRoughness.value() + : defaultPbrMetallicRoughness; + + const FName ImportedSlotName( + *(TEXT("CesiumMaterial") + FString::FromInt(nextMaterialId++))); + + const auto is_in_blend_mode = [&model](auto& result) { + return result.materialIndex != -1 && + model.materials[result.materialIndex].alphaMode == + CesiumGltf::Material::AlphaMode::BLEND; + }; + +#if PLATFORM_MAC + // TODO: figure out why water material crashes mac + UMaterialInterface* pBaseMaterial = + (is_in_blend_mode(loadResult) && pbr.baseColorFactor.size() > 3) + ? pGltf->BaseMaterialWithTranslucency + : pGltf->BaseMaterial; +#else + UMaterialInterface* pBaseMaterial; + if (loadResult.onlyWater || !loadResult.onlyLand) { + pBaseMaterial = pGltf->BaseMaterialWithWater; + } else { + pBaseMaterial = + (is_in_blend_mode(loadResult) && pbr.baseColorFactor.size() > 3) + ? pGltf->BaseMaterialWithTranslucency + : pGltf->BaseMaterial; + } +#endif + + UMaterialInstanceDynamic* pMaterial; + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetupMaterial) + + pMaterial = UMaterialInstanceDynamic::Create( + pBaseMaterial, + nullptr, + ImportedSlotName); + + pMaterial->SetFlags( + RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + SetGltfParameterValues( + model, + loadResult, + material, + pbr, + pMaterial, + EMaterialParameterAssociation::GlobalParameter, + INDEX_NONE); + SetWaterParameterValues( + model, + loadResult, + pMaterial, + EMaterialParameterAssociation::GlobalParameter, + INDEX_NONE); + + UMaterialInstance* pBaseAsMaterialInstance = + Cast(pBaseMaterial); + UCesiumMaterialUserData* pCesiumData = + pBaseAsMaterialInstance + ? pBaseAsMaterialInstance + ->GetAssetUserData() + : nullptr; + + // If possible and necessary, attach the CesiumMaterialUserData now. +#if WITH_EDITORONLY_DATA + if (pBaseAsMaterialInstance && !pCesiumData) { + const FStaticParameterSet& parameters = + pBaseAsMaterialInstance->GetStaticParameters(); + + bool hasLayers = parameters.bHasMaterialLayers; + if (hasLayers) { +#if WITH_EDITOR + FScopedTransaction transaction( + FText::FromString("Add Cesium User Data to Material")); + pBaseAsMaterialInstance->Modify(); +#endif + pCesiumData = NewObject( + pBaseAsMaterialInstance, + NAME_None, + RF_Transactional); + pBaseAsMaterialInstance->AddAssetUserData(pCesiumData); + pCesiumData->PostEditChangeOwner(); + } + } +#endif + + if (pCesiumData) { + SetGltfParameterValues( + model, + loadResult, + material, + pbr, + pMaterial, + EMaterialParameterAssociation::LayerParameter, + 0); + + // Initialize fade uniform to fully visible, in case LOD transitions + // are off. + int fadeLayerIndex = pCesiumData->LayerNames.Find("DitherFade"); + if (fadeLayerIndex >= 0) { + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo( + "FadePercentage", + EMaterialParameterAssociation::LayerParameter, + fadeLayerIndex), + 1.0f); + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo( + "FadingType", + EMaterialParameterAssociation::LayerParameter, + fadeLayerIndex), + 0.0f); + } + + // If there's a "Water" layer, set its parameters + int32 waterIndex = pCesiumData->LayerNames.Find("Water"); + if (waterIndex >= 0) { + SetWaterParameterValues( + model, + loadResult, + pMaterial, + EMaterialParameterAssociation::LayerParameter, + waterIndex); + } + + int32 featuresMetadataIndex = + pCesiumData->LayerNames.Find("FeaturesMetadata"); + int32 metadataIndex = pCesiumData->LayerNames.Find("Metadata"); + if (featuresMetadataIndex >= 0) { + SetFeaturesMetadataParameterValues( + model, + *pGltf, + loadResult, + pMaterial, + EMaterialParameterAssociation::LayerParameter, + featuresMetadataIndex); + } else if (metadataIndex >= 0) { + // Set parameters for materials generated by the old implementation + SetMetadataParameterValues_DEPRECATED( + model, + *pGltf, + loadResult, + pMaterial, + EMaterialParameterAssociation::LayerParameter, + metadataIndex); + } + } + } + + primData.Features = std::move(loadResult.Features); + primData.Metadata = std::move(loadResult.Metadata); + + primData.EncodedFeatures = std::move(loadResult.EncodedFeatures); + primData.EncodedMetadata = std::move(loadResult.EncodedMetadata); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + + // Doing the above std::move operations invalidates the pointers in the + // FCesiumMetadataPrimitive constructed on the loadResult. It's a bit + // awkward, but we have to reconstruct the metadata primitive here. + primData.Metadata_DEPRECATED = FCesiumMetadataPrimitive{ + primData.Features, + primData.Metadata, + pGltf->Metadata}; + + if (loadResult.EncodedMetadata_DEPRECATED) { + primData.EncodedMetadata_DEPRECATED = + std::move(loadResult.EncodedMetadata_DEPRECATED); + } + + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + pMaterial->TwoSided = true; + + pStaticMesh->AddMaterial(pMaterial); + + pStaticMesh->SetLightingGuid(); + + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::InitResources) + pStaticMesh->InitResources(); + } + + // Set up RenderData bounds and LOD data + pStaticMesh->CalculateExtendedBounds(); + pStaticMesh->GetRenderData()->ScreenSize[0].Default = 1.0f; + + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::BodySetup) + + pStaticMesh->CreateBodySetup(); + + UBodySetup* pBodySetup = pMesh->GetBodySetup(); + + // pMesh->UpdateCollisionFromStaticMesh(); + pBodySetup->CollisionTraceFlag = + ECollisionTraceFlag::CTF_UseComplexAsSimple; + + if (loadResult.pCollisionMesh) { +#if ENGINE_VERSION_5_4_OR_HIGHER + pBodySetup->TriMeshGeometries.Add(loadResult.pCollisionMesh); +#else + pBodySetup->ChaosTriMeshes.Add(loadResult.pCollisionMesh); +#endif + } + + // Mark physics meshes created, no matter if we actually have a collision + // mesh or not. We don't want the editor creating collision meshes itself in + // the game thread, because that would be slow. + pBodySetup->bCreatedPhysicsMeshes = true; + pBodySetup->bSupportUVsAndFaceRemap = + UPhysicsSettings::Get()->bSupportUVFromHitResults; + } + + if (createNavCollision) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CreateNavCollision) + pStaticMesh->CreateNavCollision(true); + } + + pMesh->SetMobility(pGltf->Mobility); + + pMesh->SetupAttachment(pGltf); + + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::RegisterComponent) + pMesh->RegisterComponent(); + } +} + +/*static*/ CesiumAsync::Future +UCesiumGltfComponent::CreateOffGameThread( + const CesiumAsync::AsyncSystem& AsyncSystem, + const glm::dmat4x4& Transform, + CreateModelOptions&& Options, + const CesiumGeospatial::Ellipsoid& Ellipsoid) { + return loadModelAnyThreadPart( + AsyncSystem, + Transform, + std::move(Options), + Ellipsoid); +} + +/*static*/ UCesiumGltfComponent* UCesiumGltfComponent::CreateOnGameThread( + CesiumGltf::Model& model, + ACesium3DTileset* pTilesetActor, + TUniquePtr pHalfConstructed, + const glm::dmat4x4& cesiumToUnrealTransform, + UMaterialInterface* pBaseMaterial, + UMaterialInterface* pBaseTranslucentMaterial, + UMaterialInterface* pBaseWaterMaterial, + FCustomDepthParameters CustomDepthParameters, + const Cesium3DTilesSelection::Tile& tile, + bool createNavCollision) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::LoadModel) + + HalfConstructedReal* pReal = + static_cast(pHalfConstructed.Get()); + + // TODO: was this a common case before? + // (This code checked if there were no loaded primitives in the model) + // if (result.size() == 0) { + // return nullptr; + // } + + UCesiumGltfComponent* Gltf = NewObject(pTilesetActor); + Gltf->SetMobility(pTilesetActor->GetRootComponent()->Mobility); + Gltf->SetFlags(RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + + Gltf->Metadata = std::move(pReal->loadModelResult.Metadata); + Gltf->EncodedMetadata = std::move(pReal->loadModelResult.EncodedMetadata); + Gltf->EncodedMetadata_DEPRECATED = + std::move(pReal->loadModelResult.EncodedMetadata_DEPRECATED); + + if (pBaseMaterial) { + Gltf->BaseMaterial = pBaseMaterial; + } + + if (pBaseTranslucentMaterial) { + Gltf->BaseMaterialWithTranslucency = pBaseTranslucentMaterial; + } + + if (pBaseWaterMaterial) { + Gltf->BaseMaterialWithWater = pBaseWaterMaterial; + } + + Gltf->CustomDepthParameters = CustomDepthParameters; + + encodeModelMetadataGameThreadPart(Gltf->EncodedMetadata); + + if (Gltf->EncodedMetadata_DEPRECATED) { + encodeMetadataGameThreadPart(*Gltf->EncodedMetadata_DEPRECATED); + } + + for (LoadNodeResult& node : pReal->loadModelResult.nodeResults) { + if (node.meshResult) { + for (LoadPrimitiveResult& primitive : node.meshResult->primitiveResults) { + loadPrimitiveGameThreadPart( + model, + Gltf, + primitive, + cesiumToUnrealTransform, + tile, + createNavCollision, + pTilesetActor, + node.InstanceTransforms, + node.pInstanceFeatures); + } + } + } + + Gltf->SetVisibility(false, true); + Gltf->SetCollisionEnabled(ECollisionEnabled::NoCollision); + return Gltf; +} + +UCesiumGltfComponent::UCesiumGltfComponent() : USceneComponent() { + // Structure to hold one-time initialization + struct FConstructorStatics { + ConstructorHelpers::FObjectFinder BaseMaterial; + ConstructorHelpers::FObjectFinder + BaseMaterialWithTranslucency; + ConstructorHelpers::FObjectFinder BaseMaterialWithWater; + ConstructorHelpers::FObjectFinder Transparent1x1; + FConstructorStatics() + : BaseMaterial(TEXT( + "/CesiumForUnreal/Materials/Instances/MI_CesiumThreeOverlaysAndClipping.MI_CesiumThreeOverlaysAndClipping")), + BaseMaterialWithTranslucency(TEXT( + "/CesiumForUnreal/Materials/Instances/MI_CesiumThreeOverlaysAndClippingTranslucent.MI_CesiumThreeOverlaysAndClippingTranslucent")), + BaseMaterialWithWater(TEXT( + "/CesiumForUnreal/Materials/Instances/MI_CesiumThreeOverlaysAndClippingAndWater.MI_CesiumThreeOverlaysAndClippingAndWater")), + Transparent1x1( + TEXT("/CesiumForUnreal/Textures/transparent1x1.transparent1x1")) { + } + }; + static FConstructorStatics ConstructorStatics; + + this->BaseMaterial = ConstructorStatics.BaseMaterial.Object; + this->BaseMaterialWithTranslucency = + ConstructorStatics.BaseMaterialWithTranslucency.Object; + this->BaseMaterialWithWater = ConstructorStatics.BaseMaterialWithWater.Object; + this->Transparent1x1 = ConstructorStatics.Transparent1x1.Object; + + PrimaryComponentTick.bCanEverTick = false; +} + +void UCesiumGltfComponent::UpdateTransformFromCesium( + const glm::dmat4& cesiumToUnrealTransform) { + for (USceneComponent* pSceneComponent : this->GetAttachChildren()) { + if (auto* pCesiumPrimitive = Cast(pSceneComponent)) { + pCesiumPrimitive->UpdateTransformFromCesium(cesiumToUnrealTransform); + } + } +} + +namespace { +template +void forEachPrimitiveComponent(UCesiumGltfComponent* pGltf, Func&& f) { + for (USceneComponent* pSceneComponent : pGltf->GetAttachChildren()) { + UCesiumGltfPrimitiveComponent* pPrimitive = + Cast(pSceneComponent); + if (pPrimitive) { + UMaterialInstanceDynamic* pMaterial = + Cast(pPrimitive->GetMaterial(0)); + + if (!IsValid(pMaterial) || pMaterial->IsUnreachable()) { + // Don't try to update the material while it's in the process of + // being destroyed. This can lead to the render thread freaking out + // when it's asked to update a parameter for a material that has + // been marked for garbage collection. + continue; + } + + UMaterialInterface* pBaseMaterial = pMaterial->Parent; + UMaterialInstance* pBaseAsMaterialInstance = + Cast(pBaseMaterial); + UCesiumMaterialUserData* pCesiumData = + pBaseAsMaterialInstance + ? pBaseAsMaterialInstance + ->GetAssetUserData() + : nullptr; + + f(pPrimitive, pMaterial, pCesiumData); + } + } +} // namespace + +} // namespace + +void UCesiumGltfComponent::AttachRasterTile( + const Cesium3DTilesSelection::Tile& tile, + const CesiumRasterOverlays::RasterOverlayTile& rasterTile, + UTexture2D* pTexture, + const glm::dvec2& translation, + const glm::dvec2& scale, + int32 textureCoordinateID) { + FVector4 translationAndScale(translation.x, translation.y, scale.x, scale.y); + + forEachPrimitiveComponent( + this, + [&rasterTile, pTexture, &translationAndScale, textureCoordinateID]( + UCesiumGltfPrimitiveComponent* pPrimitive, + UMaterialInstanceDynamic* pMaterial, + UCesiumMaterialUserData* pCesiumData) { + CesiumPrimitiveData& primData = pPrimitive->getPrimitiveData(); + // If this material uses material layers and has the Cesium user data, + // set the parameters on each material layer that maps to this overlay + // tile. + if (pCesiumData) { + FString name( + UTF8_TO_TCHAR(rasterTile.getOverlay().getName().c_str())); + + for (int32 i = 0; i < pCesiumData->LayerNames.Num(); ++i) { + if (pCesiumData->LayerNames[i] != name) { + continue; + } + + pMaterial->SetTextureParameterValueByInfo( + FMaterialParameterInfo( + "Texture", + EMaterialParameterAssociation::LayerParameter, + i), + pTexture); + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo( + "TranslationScale", + EMaterialParameterAssociation::LayerParameter, + i), + translationAndScale); + check( + textureCoordinateID >= 0 && + textureCoordinateID < + primData.overlayTextureCoordinateIDToUVIndex.size()); + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo( + "TextureCoordinateIndex", + EMaterialParameterAssociation::LayerParameter, + i), + static_cast(primData.overlayTextureCoordinateIDToUVIndex + [textureCoordinateID])); + } + } else { + pMaterial->SetTextureParameterValue( + createSafeName(rasterTile.getOverlay().getName(), "_Texture"), + pTexture); + pMaterial->SetVectorParameterValue( + createSafeName( + rasterTile.getOverlay().getName(), + "_TranslationScale"), + translationAndScale); + pMaterial->SetScalarParameterValue( + createSafeName( + rasterTile.getOverlay().getName(), + "_TextureCoordinateIndex"), + static_cast(primData.overlayTextureCoordinateIDToUVIndex + [textureCoordinateID])); + } + }); +} + +void UCesiumGltfComponent::DetachRasterTile( + const Cesium3DTilesSelection::Tile& tile, + const CesiumRasterOverlays::RasterOverlayTile& rasterTile, + UTexture2D* pTexture) { + forEachPrimitiveComponent( + this, + [this, &rasterTile, pTexture]( + UCesiumGltfPrimitiveComponent* pPrimitive, + UMaterialInstanceDynamic* pMaterial, + UCesiumMaterialUserData* pCesiumData) { + // If this material uses material layers and has the Cesium user data, + // clear the parameters on each material layer that maps to this + // overlay tile. + if (pCesiumData) { + FString name( + UTF8_TO_TCHAR(rasterTile.getOverlay().getName().c_str())); + for (int32 i = 0; i < pCesiumData->LayerNames.Num(); ++i) { + if (pCesiumData->LayerNames[i] != name) { + continue; + } + + pMaterial->SetTextureParameterValueByInfo( + FMaterialParameterInfo( + "Texture", + EMaterialParameterAssociation::LayerParameter, + i), + this->Transparent1x1); + } + } else { + pMaterial->SetTextureParameterValue( + createSafeName(rasterTile.getOverlay().getName(), "_Texture"), + this->Transparent1x1); + } + }); +} + +void UCesiumGltfComponent::SetCollisionEnabled( + ECollisionEnabled::Type NewType) { + for (USceneComponent* pSceneComponent : this->GetAttachChildren()) { + UCesiumGltfPrimitiveComponent* pPrimitive = + Cast(pSceneComponent); + if (pPrimitive) { + pPrimitive->SetCollisionEnabled(NewType); + } + } +} + +void UCesiumGltfComponent::BeginDestroy() { + // Clear everything we can in order to reduce memory usage, because this + // UObject might not actually get deleted by the garbage collector until + // much later. + this->Metadata = FCesiumModelMetadata(); + this->EncodedMetadata = CesiumEncodedFeaturesMetadata::EncodedModelMetadata(); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + this->EncodedMetadata_DEPRECATED.reset(); + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + Super::BeginDestroy(); +} + +void UCesiumGltfComponent::UpdateFade(float fadePercentage, bool fadingIn) { + if (!this->IsVisible()) { + return; + } + + UCesiumMaterialUserData* pCesiumData = + BaseMaterial->GetAssetUserData(); + + if (!pCesiumData) { + return; + } + + int fadeLayerIndex = pCesiumData->LayerNames.Find("DitherFade"); + if (fadeLayerIndex < 0) { + return; + } + + fadePercentage = glm::clamp(fadePercentage, 0.0f, 1.0f); + + for (USceneComponent* pChild : this->GetAttachChildren()) { + UCesiumGltfPrimitiveComponent* pPrimitive = + Cast(pChild); + if (!pPrimitive || pPrimitive->GetMaterials().IsEmpty()) { + continue; + } + + UMaterialInstanceDynamic* pMaterial = + Cast(pPrimitive->GetMaterials()[0]); + if (!pMaterial) { + continue; + } + + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo( + "FadePercentage", + EMaterialParameterAssociation::LayerParameter, + fadeLayerIndex), + fadePercentage); + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo( + "FadingType", + EMaterialParameterAssociation::LayerParameter, + fadeLayerIndex), + fadingIn ? 0.0f : 1.0f); + } +} + +template +#if ENGINE_VERSION_5_4_OR_HIGHER +static Chaos::FTriangleMeshImplicitObjectPtr +#else +static TSharedPtr +#endif +BuildChaosTriangleMeshes( + const TArray& vertexData, + const TArray& indices) { + int32 vertexCount = vertexData.Num(); + Chaos::TParticles vertices; + vertices.AddParticles(vertexCount); + for (int32 i = 0; i < vertexCount; ++i) { + vertices.X(i) = vertexData[i].Position; + } + + int32 triangleCount = indices.Num() / 3; + TArray> triangles; + triangles.Reserve(triangleCount); + TArray faceRemap; + faceRemap.Reserve(triangleCount); + + for (int32 i = 0; i < triangleCount; ++i) { + const int32 index0 = 3 * i; + int32 vIndex0 = indices[index0 + 1]; + int32 vIndex1 = indices[index0]; + int32 vIndex2 = indices[index0 + 2]; + + triangles.Add(Chaos::TVector(vIndex0, vIndex1, vIndex2)); + faceRemap.Add(i); + } + + TUniquePtr> pFaceRemap = MakeUnique>(faceRemap); + TArray materials; + materials.SetNum(triangles.Num()); + +#if ENGINE_VERSION_5_4_OR_HIGHER + return new Chaos::FTriangleMeshImplicitObject( + MoveTemp(vertices), + MoveTemp(triangles), + MoveTemp(materials), + MoveTemp(pFaceRemap), + nullptr, + false); +#else + return MakeShared( + MoveTemp(vertices), + MoveTemp(triangles), + MoveTemp(materials), + MoveTemp(pFaceRemap), + nullptr, + false); +#endif +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfComponent.h new file mode 100644 index 0000000..e78b2d2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfComponent.h @@ -0,0 +1,140 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Cesium3DTilesSelection/Tile.h" +#include "Cesium3DTileset.h" +#include "CesiumEncodedFeaturesMetadata.h" +#include "CesiumEncodedMetadataUtility.h" +#include "CesiumModelMetadata.h" +#include "Components/PrimitiveComponent.h" +#include "Components/SceneComponent.h" +#include "CoreMinimal.h" +#include "CustomDepthParameters.h" +#include "Interfaces/IHttpRequest.h" +#include +#include +#include +#include "CesiumGltfComponent.generated.h" + +class UMaterialInterface; +class UTexture2D; +class UStaticMeshComponent; + +namespace CreateGltfOptions { +struct CreateModelOptions; +} + +namespace CesiumGltf { +struct Model; +} + +namespace Cesium3DTilesSelection { +class Tile; +} + +namespace CesiumRasterOverlays { +class RasterOverlayTile; +} + +namespace CesiumGeometry { +struct Rectangle; +} + +USTRUCT() +struct FRasterOverlayTile { + GENERATED_BODY() + + UPROPERTY() + FString OverlayName{}; + + UPROPERTY() + UTexture2D* Texture = nullptr; + + FLinearColor TranslationAndScale{}; + int32 TextureCoordinateID = -1; +}; + +UCLASS() +class UCesiumGltfComponent : public USceneComponent { + GENERATED_BODY() + +public: + class HalfConstructed { + public: + virtual ~HalfConstructed() = default; + }; + + class CreateOffGameThreadResult { + public: + TUniquePtr HalfConstructed; + Cesium3DTilesSelection::TileLoadResult TileLoadResult; + }; + + static CesiumAsync::Future CreateOffGameThread( + const CesiumAsync::AsyncSystem& AsyncSystem, + const glm::dmat4x4& Transform, + CreateGltfOptions::CreateModelOptions&& Options, + const CesiumGeospatial::Ellipsoid& Ellipsoid = + CesiumGeospatial::Ellipsoid::WGS84); + + static UCesiumGltfComponent* CreateOnGameThread( + CesiumGltf::Model& model, + ACesium3DTileset* ParentActor, + TUniquePtr HalfConstructed, + const glm::dmat4x4& CesiumToUnrealTransform, + UMaterialInterface* BaseMaterial, + UMaterialInterface* BaseTranslucentMaterial, + UMaterialInterface* BaseWaterMaterial, + FCustomDepthParameters CustomDepthParameters, + const Cesium3DTilesSelection::Tile& tile, + bool createNavCollision); + + UCesiumGltfComponent(); + + UPROPERTY(EditAnywhere, Category = "Cesium") + UMaterialInterface* BaseMaterial = nullptr; + + UPROPERTY(EditAnywhere, Category = "Cesium") + UMaterialInterface* BaseMaterialWithTranslucency = nullptr; + + UPROPERTY(EditAnywhere, Category = "Cesium") + UMaterialInterface* BaseMaterialWithWater = nullptr; + + UPROPERTY(EditAnywhere, Category = "Rendering") + FCustomDepthParameters CustomDepthParameters{}; + + FCesiumModelMetadata Metadata{}; + CesiumEncodedFeaturesMetadata::EncodedModelMetadata EncodedMetadata{}; + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + std::optional + EncodedMetadata_DEPRECATED = std::nullopt; + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + void UpdateTransformFromCesium(const glm::dmat4& CesiumToUnrealTransform); + + void AttachRasterTile( + const Cesium3DTilesSelection::Tile& Tile, + const CesiumRasterOverlays::RasterOverlayTile& RasterTile, + UTexture2D* Texture, + const glm::dvec2& Translation, + const glm::dvec2& Scale, + int32_t TextureCoordinateID); + + void DetachRasterTile( + const Cesium3DTilesSelection::Tile& Tile, + const CesiumRasterOverlays::RasterOverlayTile& RasterTile, + UTexture2D* Texture); + + UFUNCTION(BlueprintCallable, Category = "Collision") + virtual void SetCollisionEnabled(ECollisionEnabled::Type NewType); + + virtual void BeginDestroy() override; + + void UpdateFade(float fadePercentage, bool fadingIn); + +private: + UPROPERTY() + UTexture2D* Transparent1x1 = nullptr; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.cpp new file mode 100644 index 0000000..a7e9fec --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.cpp @@ -0,0 +1,28 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGltfPointsComponent.h" +#include "CesiumGltfPointsSceneProxy.h" +#include "SceneInterface.h" + +// Sets default values for this component's properties +UCesiumGltfPointsComponent::UCesiumGltfPointsComponent() + : UsesAdditiveRefinement(false), + GeometricError(0), + Dimensions(glm::vec3(0)) {} + +UCesiumGltfPointsComponent::~UCesiumGltfPointsComponent() {} + +FPrimitiveSceneProxy* UCesiumGltfPointsComponent::CreateSceneProxy() { + if (!IsValid(this)) { + return nullptr; + } + + FCesiumGltfPointsSceneProxy* Proxy = + new FCesiumGltfPointsSceneProxy(this, GetScene()->GetFeatureLevel()); + + FCesiumGltfPointsSceneProxyTilesetData TilesetData; + TilesetData.UpdateFromComponent(this); + Proxy->UpdateTilesetData(TilesetData); + + return Proxy; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.h new file mode 100644 index 0000000..9c38d67 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.h @@ -0,0 +1,30 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumGltfPointsComponent.generated.h" + +UCLASS() +class UCesiumGltfPointsComponent : public UCesiumGltfPrimitiveComponent { + GENERATED_BODY() + +public: + // Sets default values for this component's properties + UCesiumGltfPointsComponent(); + virtual ~UCesiumGltfPointsComponent(); + + // Whether the tile that contains this point component uses additive + // refinement. + bool UsesAdditiveRefinement; + + // The geometric error of the tile containing this point component. + float GeometricError; + + // The dimensions of the point component. Used to estimate the geometric + // error. + glm::vec3 Dimensions; + + // Override UPrimitiveComponent interface. + virtual FPrimitiveSceneProxy* CreateSceneProxy() override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.cpp new file mode 100644 index 0000000..e4cc050 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.cpp @@ -0,0 +1,231 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGltfPointsSceneProxy.h" +#include "CesiumGltfPointsComponent.h" +#include "DataDrivenShaderPlatformInfo.h" +#include "Engine/StaticMesh.h" +#include "RHIResources.h" +#include "Runtime/Launch/Resources/Version.h" +#include "SceneInterface.h" +#include "StaticMeshResources.h" + +FCesiumGltfPointsSceneProxyTilesetData::FCesiumGltfPointsSceneProxyTilesetData() + : PointCloudShading(), + MaximumScreenSpaceError(0.0), + UsesAdditiveRefinement(false), + GeometricError(0.0f), + Dimensions() {} + +void FCesiumGltfPointsSceneProxyTilesetData::UpdateFromComponent( + UCesiumGltfPointsComponent* Component) { + CesiumPrimitiveData& primData = Component->getPrimitiveData(); + ACesium3DTileset* Tileset = primData.pTilesetActor; + PointCloudShading = Tileset->GetPointCloudShading(); + MaximumScreenSpaceError = Tileset->MaximumScreenSpaceError; + UsesAdditiveRefinement = Component->UsesAdditiveRefinement; + GeometricError = Component->GeometricError; + Dimensions = Component->Dimensions; +} + +SIZE_T FCesiumGltfPointsSceneProxy::GetTypeHash() const { + static size_t UniquePointer; + return reinterpret_cast(&UniquePointer); +} + +FCesiumGltfPointsSceneProxy::FCesiumGltfPointsSceneProxy( + UCesiumGltfPointsComponent* InComponent, + ERHIFeatureLevel::Type InFeatureLevel) + : FPrimitiveSceneProxy(InComponent), + RenderData(InComponent->GetStaticMesh()->GetRenderData()), + NumPoints(RenderData->LODResources[0].IndexBuffer.GetNumIndices()), + bAttenuationSupported( + RHISupportsManualVertexFetch(GetScene().GetShaderPlatform())), + TilesetData(), + AttenuationVertexFactory( + InFeatureLevel, + &RenderData->LODResources[0].VertexBuffers.PositionVertexBuffer), + AttenuationIndexBuffer(NumPoints, bAttenuationSupported), + Material(InComponent->GetMaterial(0)), + MaterialRelevance(InComponent->GetMaterialRelevance(InFeatureLevel)) {} + +FCesiumGltfPointsSceneProxy::~FCesiumGltfPointsSceneProxy() {} + +#if ENGINE_VERSION_5_4_OR_HIGHER +void FCesiumGltfPointsSceneProxy::CreateRenderThreadResources( + FRHICommandListBase& RHICmdList) { + AttenuationVertexFactory.InitResource(RHICmdList); + AttenuationIndexBuffer.InitResource(RHICmdList); +} +#else +void FCesiumGltfPointsSceneProxy::CreateRenderThreadResources() { + FRHICommandListBase& RHICmdList = FRHICommandListImmediate::Get(); + AttenuationVertexFactory.InitResource(RHICmdList); + AttenuationIndexBuffer.InitResource(RHICmdList); +} +#endif + +void FCesiumGltfPointsSceneProxy::DestroyRenderThreadResources() { + AttenuationVertexFactory.ReleaseResource(); + AttenuationIndexBuffer.ReleaseResource(); +} + +void FCesiumGltfPointsSceneProxy::GetDynamicMeshElements( + const TArray& Views, + const FSceneViewFamily& ViewFamily, + uint32 VisibilityMap, + FMeshElementCollector& Collector) const { + QUICK_SCOPE_CYCLE_COUNTER(STAT_GltfPointsSceneProxy_GetDynamicMeshElements); + + const bool useAttenuation = + bAttenuationSupported && TilesetData.PointCloudShading.Attenuation; + + for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { + if (VisibilityMap & (1 << ViewIndex)) { + const FSceneView* View = Views[ViewIndex]; + FMeshBatch& Mesh = Collector.AllocateMesh(); + if (useAttenuation) { + CreateMeshWithAttenuation(Mesh, View, Collector); + } else { + CreateMesh(Mesh); + } + Collector.AddMesh(ViewIndex, Mesh); + } + } +} + +FPrimitiveViewRelevance +FCesiumGltfPointsSceneProxy::GetViewRelevance(const FSceneView* View) const { + FPrimitiveViewRelevance Result; + Result.bDrawRelevance = IsShown(View); + // Always render dynamically; the appearance of the points can change + // via point cloud shading. + Result.bDynamicRelevance = true; + Result.bStaticRelevance = false; + + Result.bRenderCustomDepth = ShouldRenderCustomDepth(); + Result.bRenderInMainPass = ShouldRenderInMainPass(); + Result.bRenderInDepthPass = ShouldRenderInDepthPass(); + Result.bUsesLightingChannels = + GetLightingChannelMask() != GetDefaultLightingChannelMask(); + Result.bShadowRelevance = IsShadowCast(View); + Result.bVelocityRelevance = + IsMovable() & Result.bOpaque & Result.bRenderInMainPass; + + MaterialRelevance.SetPrimitiveViewRelevance(Result); + + return Result; +} + +uint32 FCesiumGltfPointsSceneProxy::GetMemoryFootprint(void) const { + return (sizeof(*this) + GetAllocatedSize()); +} + +void FCesiumGltfPointsSceneProxy::UpdateTilesetData( + const FCesiumGltfPointsSceneProxyTilesetData& InTilesetData) { + TilesetData = InTilesetData; +} + +float FCesiumGltfPointsSceneProxy::GetGeometricError() const { + FCesiumPointCloudShading PointCloudShading = TilesetData.PointCloudShading; + float GeometricError = TilesetData.GeometricError; + if (GeometricError > 0.0f) { + return GeometricError; + } + + if (PointCloudShading.BaseResolution > 0.0f) { + return PointCloudShading.BaseResolution; + } + + // Estimate the geometric error. + glm::vec3 Dimensions = TilesetData.Dimensions; + float Volume = Dimensions.x * Dimensions.y * Dimensions.z; + return FMath::Pow(Volume / NumPoints, 1.0f / 3.0f); +} + +void FCesiumGltfPointsSceneProxy::CreatePointAttenuationUserData( + FMeshBatchElement& BatchElement, + const FSceneView* View, + FMeshElementCollector& Collector) const { + FCesiumPointAttenuationBatchElementUserDataWrapper* UserDataWrapper = + &Collector.AllocateOneFrameResource< + FCesiumPointAttenuationBatchElementUserDataWrapper>(); + + FCesiumPointAttenuationBatchElementUserData& UserData = UserDataWrapper->Data; + const FLocalVertexFactory& OriginalVertexFactory = + RenderData->LODVertexFactories[0].VertexFactory; + + UserData.PositionBuffer = OriginalVertexFactory.GetPositionsSRV(); + UserData.PackedTangentsBuffer = OriginalVertexFactory.GetTangentsSRV(); + UserData.ColorBuffer = OriginalVertexFactory.GetColorComponentsSRV(); + UserData.TexCoordBuffer = OriginalVertexFactory.GetTextureCoordinatesSRV(); + UserData.NumTexCoords = OriginalVertexFactory.GetNumTexcoords(); + UserData.bHasPointColors = RenderData->LODResources[0].bHasColorVertexData; + + FCesiumPointCloudShading PointCloudShading = TilesetData.PointCloudShading; + + float MaximumPointSize = TilesetData.UsesAdditiveRefinement + ? 5.0f + : TilesetData.MaximumScreenSpaceError; + + if (PointCloudShading.MaximumAttenuation > 0.0f) { + // Don't multiply by DPI scale; let Unreal handle scaling. + MaximumPointSize = PointCloudShading.MaximumAttenuation; + } + + float GeometricError = GetGeometricError(); + GeometricError *= PointCloudShading.GeometricErrorScale; + + // Depth Multiplier + float SSEDenominator = 2.0f * tanf(0.5f * FMath::DegreesToRadians(View->FOV)); + float DepthMultiplier = + static_cast(View->UnconstrainedViewRect.Height()) / SSEDenominator; + + UserData.AttenuationParameters = + FVector3f(MaximumPointSize, GeometricError, DepthMultiplier); + + BatchElement.UserData = &UserDataWrapper->Data; +} + +void FCesiumGltfPointsSceneProxy::CreateMeshWithAttenuation( + FMeshBatch& Mesh, + const FSceneView* View, + FMeshElementCollector& Collector) const { + Mesh.VertexFactory = &AttenuationVertexFactory; + Mesh.MaterialRenderProxy = Material->GetRenderProxy(); + Mesh.ReverseCulling = IsLocalToWorldDeterminantNegative(); + Mesh.Type = PT_TriangleList; + Mesh.DepthPriorityGroup = SDPG_World; + Mesh.LODIndex = 0; + Mesh.bCanApplyViewModeOverrides = false; + Mesh.bUseAsOccluder = false; + Mesh.bWireframe = false; + + FMeshBatchElement& BatchElement = Mesh.Elements[0]; + BatchElement.IndexBuffer = &AttenuationIndexBuffer; + BatchElement.NumPrimitives = NumPoints * 2; + BatchElement.FirstIndex = 0; + BatchElement.MinVertexIndex = 0; + BatchElement.MaxVertexIndex = NumPoints * 4 - 1; + BatchElement.PrimitiveUniformBuffer = GetUniformBuffer(); + + CreatePointAttenuationUserData(BatchElement, View, Collector); +} + +void FCesiumGltfPointsSceneProxy::CreateMesh(FMeshBatch& Mesh) const { + Mesh.VertexFactory = &RenderData->LODVertexFactories[0].VertexFactory; + Mesh.MaterialRenderProxy = Material->GetRenderProxy(); + Mesh.ReverseCulling = IsLocalToWorldDeterminantNegative(); + Mesh.Type = PT_PointList; + Mesh.DepthPriorityGroup = SDPG_World; + Mesh.LODIndex = 0; + Mesh.bCanApplyViewModeOverrides = false; + Mesh.bUseAsOccluder = false; + Mesh.bWireframe = false; + + 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; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.h new file mode 100644 index 0000000..19fc68d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.h @@ -0,0 +1,94 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumPointAttenuationVertexFactory.h" +#include "CesiumPointCloudShading.h" +#include "PrimitiveSceneProxy.h" +#include + +class UCesiumGltfPointsComponent; + +/** + * Used to pass tile data and Cesium3DTileset settings to a SceneProxy, usually + * via render thread. + */ +struct FCesiumGltfPointsSceneProxyTilesetData { + FCesiumPointCloudShading PointCloudShading; + double MaximumScreenSpaceError; + bool UsesAdditiveRefinement; + float GeometricError; + glm::vec3 Dimensions; + + FCesiumGltfPointsSceneProxyTilesetData(); + + void UpdateFromComponent(UCesiumGltfPointsComponent* Component); +}; + +class FCesiumGltfPointsSceneProxy final : public FPrimitiveSceneProxy { +private: + // The original render data of the static mesh. + const FStaticMeshRenderData* RenderData; + int32_t NumPoints; + +public: + SIZE_T GetTypeHash() const override; + + FCesiumGltfPointsSceneProxy( + UCesiumGltfPointsComponent* InComponent, + ERHIFeatureLevel::Type InFeatureLevel); + + virtual ~FCesiumGltfPointsSceneProxy(); + +protected: +#if ENGINE_VERSION_5_4_OR_HIGHER + virtual void + CreateRenderThreadResources(FRHICommandListBase& RHICmdList) override; +#else + virtual void CreateRenderThreadResources() override; +#endif + virtual void DestroyRenderThreadResources() override; + + virtual void GetDynamicMeshElements( + const TArray& Views, + const FSceneViewFamily& ViewFamily, + uint32 VisibilityMap, + FMeshElementCollector& Collector) const override; + + virtual FPrimitiveViewRelevance + GetViewRelevance(const FSceneView* View) const override; + + virtual uint32 GetMemoryFootprint(void) const override; + +public: + void UpdateTilesetData( + const FCesiumGltfPointsSceneProxyTilesetData& InTilesetData); + +private: + // Whether or not the shader platform supports attenuation. + bool bAttenuationSupported; + + // Data from the UCesiumGltfComponent that owns this scene proxy, as well as + // its ACesium3DTileset. + FCesiumGltfPointsSceneProxyTilesetData TilesetData; + + // The vertex factory and index buffer for point attenuation. + FCesiumPointAttenuationVertexFactory AttenuationVertexFactory; + FCesiumPointAttenuationIndexBuffer AttenuationIndexBuffer; + + UMaterialInterface* Material; + FMaterialRelevance MaterialRelevance; + + float GetGeometricError() const; + + void CreatePointAttenuationUserData( + FMeshBatchElement& BatchElement, + const FSceneView* View, + FMeshElementCollector& Collector) const; + + void CreateMeshWithAttenuation( + FMeshBatch& Mesh, + const FSceneView* View, + FMeshElementCollector& Collector) const; + void CreateMesh(FMeshBatch& Mesh) const; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxyUpdater.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxyUpdater.h new file mode 100644 index 0000000..9c47e73 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxyUpdater.h @@ -0,0 +1,52 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Cesium3DTileset.h" +#include "CesiumGltfPointsComponent.h" +#include "CesiumGltfPointsSceneProxy.h" + +/** + * This is used by Cesium3DTilesets to propagate their settings to any glTF + * points components it parents. + */ +class FCesiumGltfPointsSceneProxyUpdater { +public: + /** Updates proxies with new tileset settings. Must be called from a game + * thread. */ + static void UpdateSettingsInProxies(ACesium3DTileset* Tileset) { + if (!IsValid(Tileset) || !IsInGameThread()) { + return; + } + + TInlineComponentArray ComponentArray; + Tileset->GetComponents(ComponentArray); + + // Used to pass tileset data updates to render thread + TArray SceneProxies; + TArray ProxyTilesetData; + + for (UCesiumGltfPointsComponent* PointsComponent : ComponentArray) { + FCesiumGltfPointsSceneProxy* PointsProxy = + static_cast( + PointsComponent->SceneProxy); + if (PointsProxy) { + SceneProxies.Add(PointsProxy); + } + + FCesiumGltfPointsSceneProxyTilesetData TilesetData; + TilesetData.UpdateFromComponent(PointsComponent); + ProxyTilesetData.Add(TilesetData); + } + + // Update tileset data + ENQUEUE_RENDER_COMMAND(TransferCesium3DTilesetSettingsToPointsProxies) + ([SceneProxies, + ProxyTilesetData](FRHICommandListImmediate& RHICmdList) mutable { + // Iterate over proxies and update their data + for (int32 i = 0; i < SceneProxies.Num(); i++) { + SceneProxies[i]->UpdateTilesetData(ProxyTilesetData[i]); + } + }); + } +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp new file mode 100644 index 0000000..ddcd89c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp @@ -0,0 +1,169 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGltfPrimitiveComponent.h" +#include "CalcBounds.h" +#include "CesiumLifetime.h" +#include "CesiumMaterialUserData.h" +#include "Engine/Texture.h" +#include "Materials/MaterialInstanceDynamic.h" +#include "PhysicsEngine/BodySetup.h" +#include "VecMath.h" + +#include +#include +#include + +// Prevent deprecation warnings while initializing deprecated metadata structs. +PRAGMA_DISABLE_DEPRECATION_WARNINGS + +// Sets default values for this component's properties +UCesiumGltfPrimitiveComponent::UCesiumGltfPrimitiveComponent() { + PrimaryComponentTick.bCanEverTick = false; +} + +UCesiumGltfInstancedComponent::UCesiumGltfInstancedComponent() { + PrimaryComponentTick.bCanEverTick = false; +} + +PRAGMA_ENABLE_DEPRECATION_WARNINGS + +UCesiumGltfPrimitiveComponent::~UCesiumGltfPrimitiveComponent() {} + +UCesiumGltfInstancedComponent::~UCesiumGltfInstancedComponent() {} + +namespace { +void destroyCesiumPrimitive(UStaticMeshComponent* pComponent) { + // Clear everything we can in order to reduce memory usage, because this + // UObject might not actually get deleted by the garbage collector until + // much later. + auto* cesiumPrimitive = Cast(pComponent); + cesiumPrimitive->getPrimitiveData().destroy(); + UMaterialInstanceDynamic* pMaterial = + Cast(pComponent->GetMaterial(0)); + if (pMaterial) { + CesiumLifetime::destroy(pMaterial); + } + + UStaticMesh* pMesh = pComponent->GetStaticMesh(); + if (pMesh) { + UBodySetup* pBodySetup = pMesh->GetBodySetup(); + + if (pBodySetup) { + CesiumLifetime::destroy(pBodySetup); + } + + CesiumLifetime::destroy(pMesh); + } +} +} // namespace +void UCesiumGltfPrimitiveComponent::BeginDestroy() { + destroyCesiumPrimitive(this); + Super::BeginDestroy(); +} + +void UCesiumGltfInstancedComponent::BeginDestroy() { + destroyCesiumPrimitive(this); + Super::BeginDestroy(); +} + +namespace { + +std::optional +calcBounds(const ICesiumPrimitive& primitive, const FTransform& LocalToWorld) { + const CesiumPrimitiveData& primData = primitive.getPrimitiveData(); + if (!primData.boundingVolume) { + return std::nullopt; + } + + return std::visit( + CalcBoundsOperation{LocalToWorld, primData.HighPrecisionNodeTransform}, + *primData.boundingVolume); +} + +} // namespace + +FBoxSphereBounds UCesiumGltfPrimitiveComponent::CalcBounds( + const FTransform& LocalToWorld) const { + if (auto bounds = calcBounds(*this, LocalToWorld)) { + return *bounds; + } + return Super::CalcBounds(LocalToWorld); +} + +FBoxSphereBounds UCesiumGltfInstancedComponent::CalcBounds( + const FTransform& LocalToWorld) const { + if (auto bounds = calcBounds(*this, LocalToWorld)) { + return *bounds; + } + return Super::CalcBounds(LocalToWorld); +} + +namespace { +// Returns true if the component is moveable, so caller can "Do The Right +// Thing." This avoids making the protected member function SendPhysicsTransform +// public. +template +bool UpdateTransformFromCesiumAux( + const glm::dmat4& CesiumToUnrealTransform, + CesiumComponent* cesiumComponent) { + const CesiumPrimitiveData& primData = cesiumComponent->getPrimitiveData(); + const FTransform transform = FTransform(VecMath::createMatrix( + CesiumToUnrealTransform * primData.HighPrecisionNodeTransform)); + + if (cesiumComponent->Mobility == EComponentMobility::Movable) { + // For movable objects, move the component in the normal way, but don't + // generate collisions along the way. Teleporting physics is imperfect, + // but it's the best available option. + cesiumComponent->SetRelativeTransform( + transform, + false, + nullptr, + ETeleportType::TeleportPhysics); + return true; + } + // Unreal will yell at us for calling SetRelativeTransform on a static + // object, but we still need to adjust (accurately!) for origin rebasing + // and georeference changes. It's "ok" to move a static object in this way + // because, we assume, the globe and globe-oriented lights, etc. are + // moving too, so in a relative sense the object isn't actually moving. + // This isn't a perfect assumption, of course. + cesiumComponent->SetRelativeTransform_Direct(transform); + cesiumComponent->UpdateComponentToWorld(); + cesiumComponent->MarkRenderTransformDirty(); + return false; +} +} // namespace + +void UCesiumGltfPrimitiveComponent::UpdateTransformFromCesium( + const glm::dmat4& CesiumToUnrealTransform) { + bool moveable = UpdateTransformFromCesiumAux(CesiumToUnrealTransform, this); + if (!moveable) { + SendPhysicsTransform(ETeleportType::ResetPhysics); + } +} + +void UCesiumGltfInstancedComponent::UpdateTransformFromCesium( + const glm::dmat4& CesiumToUnrealTransform) { + bool moveable = UpdateTransformFromCesiumAux(CesiumToUnrealTransform, this); + if (!moveable) { + SendPhysicsTransform(ETeleportType::ResetPhysics); + } +} + +CesiumPrimitiveData& UCesiumGltfPrimitiveComponent::getPrimitiveData() { + return _cesiumData; +} + +const CesiumPrimitiveData& +UCesiumGltfPrimitiveComponent::getPrimitiveData() const { + return _cesiumData; +} + +CesiumPrimitiveData& UCesiumGltfInstancedComponent::getPrimitiveData() { + return _cesiumData; +} + +const CesiumPrimitiveData& +UCesiumGltfInstancedComponent::getPrimitiveData() const { + return _cesiumData; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h new file mode 100644 index 0000000..081fe68 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h @@ -0,0 +1,70 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Cesium3DTilesSelection/BoundingVolume.h" +#include "CesiumPrimitive.h" +#include "CesiumPrimitiveFeatures.h" +#include "Components/InstancedStaticMeshComponent.h" +#include "Components/StaticMeshComponent.h" +#include "CoreMinimal.h" +#include "Engine/StaticMesh.h" +#include "Materials/MaterialInstanceDynamic.h" +#include "PhysicsEngine/BodySetup.h" +#include "VecMath.h" + +#include "CesiumGltfPrimitiveComponent.generated.h" + +namespace CesiumGltf { +struct Model; +struct MeshPrimitive; +} // namespace CesiumGltf + +UCLASS() +class UCesiumGltfPrimitiveComponent : public UStaticMeshComponent, + public ICesiumPrimitive { + GENERATED_BODY() + +public: + // Sets default values for this component's properties + UCesiumGltfPrimitiveComponent(); + virtual ~UCesiumGltfPrimitiveComponent(); + + void BeginDestroy() override; + + FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override; + + void + UpdateTransformFromCesium(const glm::dmat4& CesiumToUnrealTransform) override; + + CesiumPrimitiveData& getPrimitiveData() override; + const CesiumPrimitiveData& getPrimitiveData() const override; + +private: + CesiumPrimitiveData _cesiumData; +}; + +UCLASS() +class UCesiumGltfInstancedComponent : public UInstancedStaticMeshComponent, + public ICesiumPrimitive { + GENERATED_BODY() + +public: + // Sets default values for this component's properties + UCesiumGltfInstancedComponent(); + virtual ~UCesiumGltfInstancedComponent(); + + void BeginDestroy() override; + + FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override; + void + UpdateTransformFromCesium(const glm::dmat4& CesiumToUnrealTransform) override; + + CesiumPrimitiveData& getPrimitiveData() override; + const CesiumPrimitiveData& getPrimitiveData() const override; + + TSharedPtr pInstanceFeatures; + +private: + CesiumPrimitiveData _cesiumData; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfTextures.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfTextures.cpp new file mode 100644 index 0000000..2e563a9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfTextures.cpp @@ -0,0 +1,258 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGltfTextures.h" +#include "CesiumRuntime.h" +#include "CesiumTextureResource.h" +#include "CesiumTextureUtility.h" +#include "ExtensionImageAssetUnreal.h" +#include +#include +#include +#include + +using namespace CesiumAsync; + +namespace { + +// Determines if a glTF primitive is usable for our purposes. +bool isValidPrimitive( + const CesiumGltf::Model& gltf, + const CesiumGltf::MeshPrimitive& primitive); + +// Determines if an Accessor's componentType is valid for an index buffer. +bool isSupportedIndexComponentType(int32_t componentType); + +// Determines if the given Primitive mode is one that we support. +bool isSupportedPrimitiveMode(int32_t primitiveMode); + +// Determines if the given texture uses mipmaps. +bool doesTextureUseMipmaps( + const CesiumGltf::Model& gltf, + const CesiumGltf::Texture& texture); + +// Creates a single texture in the load thread. +SharedFuture createTextureInLoadThread( + const AsyncSystem& asyncSystem, + CesiumGltf::Model& gltf, + CesiumGltf::TextureInfo& textureInfo, + bool sRGB, + const std::vector& imageNeedsMipmaps); + +} // namespace + +/*static*/ CesiumAsync::Future CesiumGltfTextures::createInWorkerThread( + const CesiumAsync::AsyncSystem& asyncSystem, + CesiumGltf::Model& model) { + // This array is parallel to model.images and indicates whether each image + // requires mipmaps. An image requires mipmaps if any of its textures have a + // sampler that will use them. + std::vector imageNeedsMipmaps(model.images.size(), false); + for (const CesiumGltf::Texture& texture : model.textures) { + int32_t imageIndex = texture.source; + if (imageIndex < 0 || imageIndex >= model.images.size()) { + continue; + } + + if (!imageNeedsMipmaps[imageIndex]) { + imageNeedsMipmaps[imageIndex] = doesTextureUseMipmaps(model, texture); + } + } + + std::vector> futures; + + model.forEachPrimitiveInScene( + -1, + [&imageNeedsMipmaps, &asyncSystem, &futures]( + CesiumGltf::Model& gltf, + CesiumGltf::Node& node, + CesiumGltf::Mesh& mesh, + CesiumGltf::MeshPrimitive& primitive, + const glm::dmat4& transform) { + if (!isValidPrimitive(gltf, primitive)) { + return; + } + + CesiumGltf::Material* pMaterial = + CesiumGltf::Model::getSafe(&gltf.materials, primitive.material); + if (!pMaterial) { + // A primitive using the default material will not have any textures. + return; + } + + if (pMaterial->pbrMetallicRoughness) { + if (pMaterial->pbrMetallicRoughness->baseColorTexture) { + futures.emplace_back(createTextureInLoadThread( + asyncSystem, + gltf, + *pMaterial->pbrMetallicRoughness->baseColorTexture, + true, + imageNeedsMipmaps)); + } + if (pMaterial->pbrMetallicRoughness->metallicRoughnessTexture) { + futures.emplace_back(createTextureInLoadThread( + asyncSystem, + gltf, + *pMaterial->pbrMetallicRoughness->metallicRoughnessTexture, + false, + imageNeedsMipmaps)); + } + } + + if (pMaterial->emissiveTexture) + futures.emplace_back(createTextureInLoadThread( + asyncSystem, + gltf, + *pMaterial->emissiveTexture, + true, + imageNeedsMipmaps)); + if (pMaterial->normalTexture) + futures.emplace_back(createTextureInLoadThread( + asyncSystem, + gltf, + *pMaterial->normalTexture, + false, + imageNeedsMipmaps)); + if (pMaterial->occlusionTexture) + futures.emplace_back(createTextureInLoadThread( + asyncSystem, + gltf, + *pMaterial->occlusionTexture, + false, + imageNeedsMipmaps)); + + // Initialize water mask if needed. + auto onlyWaterIt = primitive.extras.find("OnlyWater"); + auto onlyLandIt = primitive.extras.find("OnlyLand"); + if (onlyWaterIt != primitive.extras.end() && + onlyWaterIt->second.isBool() && + onlyLandIt != primitive.extras.end() && + onlyLandIt->second.isBool()) { + bool onlyWater = onlyWaterIt->second.getBoolOrDefault(false); + bool onlyLand = onlyLandIt->second.getBoolOrDefault(true); + + if (!onlyWater && !onlyLand) { + // We have to use the water mask + auto waterMaskTextureIdIt = primitive.extras.find("WaterMaskTex"); + if (waterMaskTextureIdIt != primitive.extras.end() && + waterMaskTextureIdIt->second.isInt64()) { + int32_t waterMaskTextureId = static_cast( + waterMaskTextureIdIt->second.getInt64OrDefault(-1)); + CesiumGltf::TextureInfo waterMaskInfo; + waterMaskInfo.index = waterMaskTextureId; + if (waterMaskTextureId >= 0 && + waterMaskTextureId < gltf.textures.size()) { + futures.emplace_back(createTextureInLoadThread( + asyncSystem, + gltf, + waterMaskInfo, + false, + imageNeedsMipmaps)); + } + } + } + } + }); + + return asyncSystem.all(std::move(futures)); +} + +namespace { + +bool isSupportedIndexComponentType(int32_t componentType) { + return componentType == CesiumGltf::Accessor::ComponentType::UNSIGNED_BYTE || + componentType == CesiumGltf::Accessor::ComponentType::UNSIGNED_SHORT || + componentType == CesiumGltf::Accessor::ComponentType::UNSIGNED_INT; +} + +bool isSupportedPrimitiveMode(int32_t primitiveMode) { + return primitiveMode == CesiumGltf::MeshPrimitive::Mode::TRIANGLES || + primitiveMode == CesiumGltf::MeshPrimitive::Mode::TRIANGLE_STRIP || + primitiveMode == CesiumGltf::MeshPrimitive::Mode::POINTS; +} + +// Determines if a glTF primitive is usable for our purposes. +bool isValidPrimitive( + const CesiumGltf::Model& gltf, + const CesiumGltf::MeshPrimitive& primitive) { + if (!isSupportedPrimitiveMode(primitive.mode)) { + // This primitive's mode is not supported. + return false; + } + + auto positionAccessorIt = + primitive.attributes.find(CesiumGltf::VertexAttributeSemantics::POSITION); + if (positionAccessorIt == primitive.attributes.end()) { + // This primitive doesn't have a POSITION semantic, so it's not valid. + return false; + } + + CesiumGltf::AccessorView positionView( + gltf, + positionAccessorIt->second); + if (positionView.status() != CesiumGltf::AccessorViewStatus::Valid) { + // This primitive's POSITION accessor is invalid, so the primitive is not + // valid. + return false; + } + + const CesiumGltf::Accessor* pIndexAccessor = + CesiumGltf::Model::getSafe(&gltf.accessors, primitive.indices); + if (pIndexAccessor && + !isSupportedIndexComponentType(pIndexAccessor->componentType)) { + // This primitive's indices are not a supported type, so the primitive is + // not valid. + return false; + } + + return true; +} + +bool doesTextureUseMipmaps( + const CesiumGltf::Model& gltf, + const CesiumGltf::Texture& texture) { + const CesiumGltf::Sampler& sampler = + CesiumGltf::Model::getSafe(gltf.samplers, texture.sampler); + + switch (sampler.minFilter.value_or( + CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR)) { + case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR: + case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_NEAREST: + case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_LINEAR: + case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_NEAREST: + return true; + default: // LINEAR and NEAREST + return false; + } +} + +SharedFuture createTextureInLoadThread( + const AsyncSystem& asyncSystem, + CesiumGltf::Model& gltf, + CesiumGltf::TextureInfo& textureInfo, + bool sRGB, + const std::vector& imageNeedsMipmaps) { + CesiumGltf::Texture* pTexture = + CesiumGltf::Model::getSafe(&gltf.textures, textureInfo.index); + if (pTexture == nullptr) + return asyncSystem.createResolvedFuture().share(); + + CesiumGltf::Image* pImage = + CesiumGltf::Model::getSafe(&gltf.images, pTexture->source); + if (pImage == nullptr || pImage->pAsset == nullptr) + return asyncSystem.createResolvedFuture().share(); + + check(pTexture->source >= 0 && pTexture->source < imageNeedsMipmaps.size()); + bool needsMips = imageNeedsMipmaps[pTexture->source]; + + const ExtensionImageAssetUnreal& extension = + ExtensionImageAssetUnreal::getOrCreate( + asyncSystem, + *pImage->pAsset, + sRGB, + needsMips, + std::nullopt); + + return extension.getFuture(); +} + +} // namespace diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfTextures.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfTextures.h new file mode 100644 index 0000000..64540f7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfTextures.h @@ -0,0 +1,25 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include + +namespace CesiumAsync { +class AsyncSystem; +} + +namespace CesiumGltf { +struct Model; +} + +class CesiumGltfTextures { +public: + /** + * Creates all of the texture resources that are required by the given glTF, + * and adds `ExtensionImageCesiumUnreal` to each. This is intended to be + * called from a worker thread. + */ + static CesiumAsync::Future createInWorkerThread( + const CesiumAsync::AsyncSystem& asyncSystem, + CesiumGltf::Model& model); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumIonRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumIonRasterOverlay.cpp new file mode 100644 index 0000000..9f32294 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumIonRasterOverlay.cpp @@ -0,0 +1,74 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumIonRasterOverlay.h" +#include "Cesium3DTilesSelection/Tileset.h" +#include "CesiumActors.h" +#include "CesiumCustomVersion.h" +#include "CesiumIonServer.h" +#include "CesiumRasterOverlays/IonRasterOverlay.h" +#include "CesiumRuntime.h" +#include "CesiumRuntimeSettings.h" + +#if WITH_EDITOR +#include "FileHelpers.h" +#endif + +void UCesiumIonRasterOverlay::TroubleshootToken() { + OnCesiumRasterOverlayIonTroubleshooting.Broadcast(this); +} + +std::unique_ptr +UCesiumIonRasterOverlay::CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options) { + if (this->IonAssetID <= 0) { + // Don't create an overlay for an invalid asset ID. + return nullptr; + } + + // Make sure we have a valid Cesium ion server. + if (!IsValid(this->CesiumIonServer)) { + this->CesiumIonServer = UCesiumIonServer::GetServerForNewObjects(); + } + + FString token = this->IonAccessToken.IsEmpty() + ? this->CesiumIonServer->DefaultIonAccessToken + : this->IonAccessToken; + +#if WITH_EDITOR + this->CesiumIonServer->ResolveApiUrl(); +#endif + + // Make sure the URL ends with a slash + std::string apiUrl = TCHAR_TO_UTF8(*this->CesiumIonServer->ApiUrl); + if (apiUrl.empty()) + return nullptr; + + if (*apiUrl.rbegin() != '/') + apiUrl += '/'; + + return std::make_unique( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + this->IonAssetID, + TCHAR_TO_UTF8(*token), + options, + apiUrl); +} + +void UCesiumIonRasterOverlay::PostLoad() { + Super::PostLoad(); + + if (CesiumActors::shouldValidateFlags(this)) + CesiumActors::validateActorComponentFlags(this); + +#if WITH_EDITOR + const int32 CesiumVersion = + this->GetLinkerCustomVersion(FCesiumCustomVersion::GUID); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + if (CesiumVersion < FCesiumCustomVersion::CesiumIonServer) { + this->CesiumIonServer = UCesiumIonServer::GetBackwardCompatibleServer( + this->IonAssetEndpointUrl_DEPRECATED); + } + PRAGMA_ENABLE_DEPRECATION_WARNINGS +#endif +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumIonServer.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumIonServer.cpp new file mode 100644 index 0000000..2cb67f2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumIonServer.cpp @@ -0,0 +1,179 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumIonServer.h" +#include "CesiumAsync/AsyncSystem.h" +#include "CesiumIonClient/Connection.h" +#include "CesiumRuntime.h" +#include "CesiumRuntimeSettings.h" +#include "UObject/Package.h" +#include "UObject/UObjectGlobals.h" + +#if WITH_EDITOR +#include "AssetRegistry/AssetRegistryModule.h" +#include "CesiumIonClient/Connection.h" +#include "Factories/DataAssetFactory.h" +#include "FileHelpers.h" +#endif + +/*static*/ UCesiumIonServer* UCesiumIonServer::_pDefaultForNewObjects = nullptr; + +/*static*/ UCesiumIonServer* UCesiumIonServer::GetDefaultServer() { + UPackage* Package = CreatePackage( + TEXT("/Game/CesiumSettings/CesiumIonServers/CesiumIonSaaS")); + Package->FullyLoad(); + UCesiumIonServer* Server = + Cast(Package->FindAssetInPackage()); + +#if WITH_EDITOR + if (!IsValid(Server)) { + UDataAssetFactory* Factory = NewObject(); + Server = Cast(Factory->FactoryCreateNew( + UCesiumIonServer::StaticClass(), + Package, + "CesiumIonSaaS", + RF_Public | RF_Standalone | RF_Transactional, + nullptr, + GWarn)); + + Server->DisplayName = TEXT("ion.cesium.com"); + Server->ServerUrl = TEXT("https://ion.cesium.com"); + Server->ApiUrl = TEXT("https://api.cesium.com"); + Server->OAuth2ApplicationID = 190; + + FAssetRegistryModule::AssetCreated(Server); + + Package->FullyLoad(); + Package->SetDirtyFlag(true); + UEditorLoadingAndSavingUtils::SavePackages({Package}, true); + } +#endif + + return Server; +} + +/*static*/ UCesiumIonServer* UCesiumIonServer::GetServerForNewObjects() { + if (IsValid(_pDefaultForNewObjects)) { + return _pDefaultForNewObjects; + } else { + return GetDefaultServer(); + } +} + +/*static*/ void +UCesiumIonServer::SetServerForNewObjects(UCesiumIonServer* Server) { + _pDefaultForNewObjects = Server; +} + +#if WITH_EDITOR +UCesiumIonServer* +UCesiumIonServer::GetBackwardCompatibleServer(const FString& apiUrl) { + // Return the default server if the API URL is unspecified or if it's the + // standard SaaS API URL. + if (apiUrl.IsEmpty() || + apiUrl.StartsWith(TEXT("https://api.ion.cesium.com")) || + apiUrl.StartsWith(TEXT("https://api.cesium.com"))) { + return UCesiumIonServer::GetDefaultServer(); + } + + // Find a server with this API URL. + TArray CesiumIonServers; + FAssetRegistryModule& AssetRegistryModule = + FModuleManager::LoadModuleChecked("AssetRegistry"); + AssetRegistryModule.Get().GetAssetsByClass( + UCesiumIonServer::StaticClass()->GetClassPathName(), + CesiumIonServers); + + FAssetData* pFound = + CesiumIonServers.FindByPredicate([&apiUrl](const FAssetData& asset) { + UCesiumIonServer* pServer = Cast(asset.GetAsset()); + return pServer && pServer->ApiUrl == apiUrl; + }); + + if (pFound) { + return Cast(pFound->GetAsset()); + } + + // Not found - create a new server asset. + UDataAssetFactory* Factory = NewObject(); + + UPackage* Package = nullptr; + + FString PackageBasePath = TEXT("/Game/CesiumSettings/CesiumIonServers/"); + FString PackageName; + FString PackagePath; + + const int ArbitraryPackageIndexLimit = 10000; + + for (int i = 0; i < ArbitraryPackageIndexLimit; ++i) { + PackageName = TEXT("FromApiUrl") + FString::FromInt(i); + PackagePath = PackageBasePath + PackageName; + Package = FindPackage(nullptr, *PackagePath); + if (Package == nullptr) { + Package = CreatePackage(*PackagePath); + break; + } + } + + if (Package == nullptr) + return nullptr; + + Package->FullyLoad(); + + UCesiumIonServer* Server = Cast(Factory->FactoryCreateNew( + UCesiumIonServer::StaticClass(), + Package, + FName(PackageName), + RF_Public | RF_Standalone | RF_Transactional, + nullptr, + GWarn)); + + Server->DisplayName = apiUrl; + Server->ServerUrl = apiUrl; + Server->ApiUrl = apiUrl; + Server->OAuth2ApplicationID = 190; + + // Adopt the token from the default server, consistent with the behavior in + // old versions of Cesium for Unreal. + UCesiumIonServer* pDefault = UCesiumIonServer::GetDefaultServer(); + Server->DefaultIonAccessTokenId = pDefault->DefaultIonAccessTokenId; + Server->DefaultIonAccessToken = pDefault->DefaultIonAccessToken; + + FAssetRegistryModule::AssetCreated(Server); + + Package->FullyLoad(); + Package->SetDirtyFlag(true); + UEditorLoadingAndSavingUtils::SavePackages({Package}, true); + + return Server; +} + +CesiumAsync::Future UCesiumIonServer::ResolveApiUrl() { + if (!this->ApiUrl.IsEmpty()) + return getAsyncSystem().createResolvedFuture(); + + if (this->ServerUrl.IsEmpty()) { + // We don't even have a server URL, so use the SaaS defaults. + this->ServerUrl = TEXT("https://ion.cesium.com/"); + this->ApiUrl = TEXT("https://api.cesium.com/"); + this->Modify(); + UEditorLoadingAndSavingUtils::SavePackages({this->GetPackage()}, true); + return getAsyncSystem().createResolvedFuture(); + } + + TObjectPtr pServer = this; + + return CesiumIonClient::Connection::getApiUrl( + getAsyncSystem(), + getAssetAccessor(), + TCHAR_TO_UTF8(*this->ServerUrl)) + .thenInMainThread([pServer](std::optional&& apiUrl) { + if (pServer && pServer->ApiUrl.IsEmpty()) { + pServer->ApiUrl = UTF8_TO_TCHAR(apiUrl->c_str()); + pServer->Modify(); + UEditorLoadingAndSavingUtils::SavePackages( + {pServer->GetPackage()}, + true); + } + }); +} +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumLifetime.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumLifetime.cpp new file mode 100644 index 0000000..6ea2c2a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumLifetime.cpp @@ -0,0 +1,151 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumLifetime.h" +#include "CesiumRuntime.h" +#if WITH_EDITOR +#include "Editor.h" +#include "Editor/EditorEngine.h" +#include "Engine/Selection.h" +#endif +#include "Engine/StaticMesh.h" +#include "Engine/Texture2D.h" +#include "PhysicsEngine/BodySetup.h" +#include "Runtime/Launch/Resources/Version.h" +#include "StaticMeshResources.h" +#include "UObject/Object.h" +#include + +/*static*/ +AmortizedDestructor CesiumLifetime::amortizedDestructor = AmortizedDestructor(); + +/*static*/ void CesiumLifetime::destroy(UObject* pObject) { + amortizedDestructor.destroy(pObject); +} + +/*static*/ void +CesiumLifetime::destroyComponentRecursively(USceneComponent* pComponent) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::DestroyComponent) + UE_LOG( + LogCesium, + VeryVerbose, + TEXT("Destroying scene component recursively")); + + if (!pComponent) { + return; + } + + if (pComponent->IsRegistered()) { + pComponent->UnregisterComponent(); + } + + TArray children = pComponent->GetAttachChildren(); + for (USceneComponent* pChild : children) { + destroyComponentRecursively(pChild); + } + +#if WITH_EDITOR + // If the editor is currently selecting this, remove the reference + if (GEditor) { + USelection* editorSelection = GEditor->GetSelectedComponents(); + if (editorSelection && editorSelection->IsSelected(pComponent)) + editorSelection->Deselect(pComponent); + } +#endif + + pComponent->DestroyPhysicsState(); + pComponent->DestroyComponent(); + pComponent->ConditionalBeginDestroy(); + + UE_LOG(LogCesium, VeryVerbose, TEXT("Destroying scene component done")); +} + +void AmortizedDestructor::Tick(float DeltaTime) { processPending(); } + +ETickableTickType AmortizedDestructor::GetTickableTickType() const { + return ETickableTickType::Always; +} + +bool AmortizedDestructor::IsTickableWhenPaused() const { return true; } + +bool AmortizedDestructor::IsTickableInEditor() const { return true; } + +TStatId AmortizedDestructor::GetStatId() const { return TStatId(); } + +void AmortizedDestructor::destroy(UObject* pObject) { + if (!runDestruction(pObject)) { + addToPending(pObject); + } +} + +bool AmortizedDestructor::runDestruction(UObject* pObject) const { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::RunDestruction) + + if (!pObject) { + return true; + } + + pObject->MarkAsGarbage(); + + if (pObject->HasAnyFlags(RF_FinishDestroyed)) { + // Already done being destroyed. + return true; + } + + if (!pObject->HasAnyFlags(RF_BeginDestroyed)) { + pObject->ConditionalBeginDestroy(); + } + + if (!pObject->HasAnyFlags(RF_FinishDestroyed) && + pObject->IsReadyForFinishDestroy()) { + // Don't actually call ConditionalFinishDestroy here, because if we do the + // UE garbage collector will freak out that it's already been called. The + // IsReadyForFinishDestroy call is important, though. In some objects, + // calling that actually continues the async destruction! + finalizeDestroy(pObject); + return true; + } + + return false; +} + +void AmortizedDestructor::addToPending(UObject* pObject) { + _pending.Add(pObject); +} + +void AmortizedDestructor::processPending() { + std::swap(_nextPending, _pending); + _pending.Empty(); + + for (TWeakObjectPtr pObject : _nextPending) { + destroy(pObject.Get(true)); + } +} + +void AmortizedDestructor::finalizeDestroy(UObject* pObject) const { + // The freeing/clearing/destroying done here is normally done in these + // objects' FinishDestroy method, but unfortunately we can't call that + // directly without confusing the garbage collector if and when it _does_ + // run. So instead we manually release some critical resources here. + + UTexture2D* pTexture2D = Cast(pObject); + if (pTexture2D) { + pTexture2D->ReleaseResource(); + FTexturePlatformData* pPlatformData = pTexture2D->GetPlatformData(); + pTexture2D->SetPlatformData(nullptr); + delete pPlatformData; + } + + UStaticMesh* pMesh = Cast(pObject); + if (pMesh) { + pMesh->SetRenderData(nullptr); + } + + UBodySetup* pBodySetup = Cast(pObject); + if (pBodySetup) { + pBodySetup->UVInfo.IndexBuffer.Empty(); + pBodySetup->UVInfo.VertPositions.Empty(); + pBodySetup->UVInfo.VertUVs.Empty(); + pBodySetup->FaceRemap.Empty(); + pBodySetup->ClearPhysicsMeshes(); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumLifetime.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumLifetime.h new file mode 100644 index 0000000..4f09443 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumLifetime.h @@ -0,0 +1,38 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once +#include "Components/SceneComponent.h" +#include "Containers/Array.h" +#include "Tickable.h" +#include "UObject/WeakObjectPtrTemplates.h" + +class UObject; +class UTexture; + +class AmortizedDestructor : FTickableGameObject { +public: + void Tick(float DeltaTime) override; + ETickableTickType GetTickableTickType() const override; + bool IsTickableWhenPaused() const override; + bool IsTickableInEditor() const override; + TStatId GetStatId() const; + void destroy(UObject* pObject); + +private: + bool runDestruction(UObject* pObject) const; + void addToPending(UObject* pObject); + void processPending(); + void finalizeDestroy(UObject* pObject) const; + + TArray> _pending; + TArray> _nextPending; +}; + +class CesiumLifetime { +public: + static void destroy(UObject* pObject); + static void destroyComponentRecursively(USceneComponent* pComponent); + +private: + static AmortizedDestructor amortizedDestructor; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMaterialUserData.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMaterialUserData.cpp new file mode 100644 index 0000000..454b933 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMaterialUserData.cpp @@ -0,0 +1,27 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumMaterialUserData.h" +#include "Materials/MaterialInstance.h" +#include "Runtime/Launch/Resources/Version.h" + +void UCesiumMaterialUserData::PostEditChangeOwner() { + Super::PostEditChangeOwner(); + +#if WITH_EDITORONLY_DATA + this->LayerNames.Empty(); + + UMaterialInstance* pMaterial = Cast(this->GetOuter()); + if (pMaterial) { + const FStaticParameterSet& parameters = pMaterial->GetStaticParameters(); + + const TArray& layerNames = + parameters.EditorOnly.MaterialLayers.LayerNames; + + this->LayerNames.Reserve(layerNames.Num()); + + for (int32 i = 0; i < layerNames.Num(); ++i) { + this->LayerNames.Add(layerNames[i].ToString()); + } + } +#endif +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMaterialUserData.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMaterialUserData.h new file mode 100644 index 0000000..d0c3f6e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMaterialUserData.h @@ -0,0 +1,29 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Engine/AssetUserData.h" +#include "CesiumMaterialUserData.generated.h" + +/** + * Instances of this user data class are automatically attached to all materials + * that are used by Cesium for Unreal and that have a Layer Stack named + * "Cesium". It provides a way for Cesium for Unreal to access the names of the + * individual layers in the stack at runtime (i.e. outside the Editor) so that + * they can be mapped to raster overlays. + * + * It works by responding, in the Editor, to changes in the Material to which + * it's attached via the `PostEditChangeOwner` and updating its internal mirror + * of the layer names. At runtime, these layer names that were configured in the + * Editor can't be further changed, so the the mirrored list is still valid. + */ +UCLASS() +class UCesiumMaterialUserData : public UAssetUserData { + GENERATED_BODY() + +public: + virtual void PostEditChangeOwner() override; + + UPROPERTY() + TArray LayerNames; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataPickingBlueprintLibrary.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataPickingBlueprintLibrary.cpp new file mode 100644 index 0000000..8a8e0af --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataPickingBlueprintLibrary.cpp @@ -0,0 +1,305 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataPickingBlueprintLibrary.h" +#include "CesiumGltfComponent.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumMetadataValue.h" + +#include + +static TMap EmptyCesiumMetadataValueMap; + +TMap +UCesiumMetadataPickingBlueprintLibrary::GetMetadataValuesForFace( + const UPrimitiveComponent* Component, + int64 FaceIndex, + int64 FeatureIDSetIndex) { + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast(Component); + if (!IsValid(pGltfComponent)) { + return TMap(); + } + + const UCesiumGltfComponent* pModel = + Cast(pGltfComponent->GetOuter()); + if (!IsValid(pModel)) { + return TMap(); + } + const CesiumPrimitiveData& primData = pGltfComponent->getPrimitiveData(); + const FCesiumPrimitiveFeatures& features = primData.Features; + const TArray& featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets(features); + + if (FeatureIDSetIndex < 0 || FeatureIDSetIndex >= featureIDSets.Num()) { + return TMap(); + } + + const FCesiumFeatureIdSet& featureIDSet = featureIDSets[FeatureIDSetIndex]; + const int64 propertyTableIndex = + UCesiumFeatureIdSetBlueprintLibrary::GetPropertyTableIndex(featureIDSet); + + const TArray& propertyTables = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTables(pModel->Metadata); + if (propertyTableIndex < 0 || propertyTableIndex >= propertyTables.Num()) { + return TMap(); + } + + const FCesiumPropertyTable& propertyTable = + propertyTables[propertyTableIndex]; + + int64 featureID = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + features, + FaceIndex, + FeatureIDSetIndex); + if (featureID < 0) { + return TMap(); + } + + return UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeature( + propertyTable, + featureID); +} + +TMap +UCesiumMetadataPickingBlueprintLibrary::GetMetadataValuesForFaceAsStrings( + const UPrimitiveComponent* Component, + int64 FaceIndex, + int64 FeatureIDSetIndex) { + TMap values = + UCesiumMetadataPickingBlueprintLibrary::GetMetadataValuesForFace( + Component, + FaceIndex, + FeatureIDSetIndex); + TMap strings; + for (auto valuesIt : values) { + strings.Add( + valuesIt.Key, + UCesiumMetadataValueBlueprintLibrary::GetString(valuesIt.Value, "")); + } + + return strings; +} + +bool UCesiumMetadataPickingBlueprintLibrary::FindUVFromHit( + const FHitResult& Hit, + int64 GltfTexCoordSetIndex, + FVector2D& UV) { + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast(Hit.Component); + if (!IsValid(pGltfComponent)) { + return false; + } + + const CesiumPrimitiveData& primData = pGltfComponent->getPrimitiveData(); + + if (primData.PositionAccessor.status() != + CesiumGltf::AccessorViewStatus::Valid) { + return false; + } + + auto accessorIt = primData.TexCoordAccessorMap.find(GltfTexCoordSetIndex); + if (accessorIt == primData.TexCoordAccessorMap.end()) { + return false; + } + + auto VertexIndices = std::visit( + CesiumGltf::IndicesForFaceFromAccessor{ + Hit.FaceIndex, + primData.PositionAccessor.size(), + primData.pMeshPrimitive->mode}, + primData.IndexAccessor); + + // Adapted from UBodySetup::CalcUVAtLocation. Compute the barycentric + // coordinates of the point relative to the face, then use those to + // interpolate the UVs. + std::array UVs; + const CesiumGltf::TexCoordAccessorType& accessor = accessorIt->second; + for (size_t i = 0; i < UVs.size(); i++) { + auto maybeTexCoord = std::visit( + CesiumGltf::TexCoordFromAccessor{VertexIndices[i]}, + accessor); + if (!maybeTexCoord) { + return false; + } + const glm::dvec2& texCoord = *maybeTexCoord; + UVs[i] = FVector2D(texCoord[0], texCoord[1]); + } + + std::array Positions; + for (size_t i = 0; i < Positions.size(); i++) { + auto& Position = primData.PositionAccessor[VertexIndices[i]]; + // The Y-component of glTF positions must be inverted, and the positions + // must be scaled to match the UE meshes. + Positions[i] = FVector(Position[0], -Position[1], Position[2]) * + CesiumPrimitiveData::positionScaleFactor; + } + + const FVector Location = + pGltfComponent->GetComponentToWorld().InverseTransformPosition( + Hit.Location); + FVector BaryCoords = FMath::ComputeBaryCentric2D( + Location, + Positions[0], + Positions[1], + Positions[2]); + + UV = (BaryCoords.X * UVs[0]) + (BaryCoords.Y * UVs[1]) + + (BaryCoords.Z * UVs[2]); + + return true; +} + +namespace { +/* + * Returns std:nullopt if the component isn't an instanced static mesh or + * if it doesn't have instance feature IDs. This will prompt + * GetPropertyTableValuesFromHit() to search for feature IDs in the primitive's + * attributes. + */ +std::optional> +getInstancePropertyTableValues( + const FHitResult& Hit, + const UCesiumGltfComponent* pModel, + int64 FeatureIDSetIndex) { + const auto* pInstancedComponent = + Cast(Hit.Component); + if (!IsValid(pInstancedComponent)) { + return std::nullopt; + } + const TSharedPtr& pInstanceFeatures = + pInstancedComponent->pInstanceFeatures; + if (!pInstanceFeatures) { + return std::nullopt; + } + + const TArray& featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets( + *pInstanceFeatures); + if (FeatureIDSetIndex < 0 || FeatureIDSetIndex >= featureIDSets.Num()) { + return TMap(); + } + + const FCesiumFeatureIdSet& featureIDSet = featureIDSets[FeatureIDSetIndex]; + const int64 propertyTableIndex = + UCesiumFeatureIdSetBlueprintLibrary::GetPropertyTableIndex(featureIDSet); + + const TArray& propertyTables = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTables(pModel->Metadata); + if (propertyTableIndex < 0 || propertyTableIndex >= propertyTables.Num()) { + return TMap(); + } + const FCesiumPropertyTable& propertyTable = + propertyTables[propertyTableIndex]; + int64 featureID = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromInstance( + *pInstanceFeatures, + Hit.Item, + FeatureIDSetIndex); + if (featureID < 0) { + return TMap(); + } + return UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeature( + propertyTable, + featureID); +} +} // namespace + +TMap +UCesiumMetadataPickingBlueprintLibrary::GetPropertyTableValuesFromHit( + const FHitResult& Hit, + int64 FeatureIDSetIndex) { + const UCesiumGltfComponent* pModel = nullptr; + + if (const auto* pPrimComponent = Cast(Hit.Component); + !IsValid(pPrimComponent)) { + return TMap(); + } else { + pModel = Cast(pPrimComponent->GetOuter()); + } + + if (!IsValid(pModel)) { + return TMap(); + } + + // Query for instance-level metadata first. (EXT_instance_features) + std::optional> maybeProperties = + getInstancePropertyTableValues(Hit, pModel, FeatureIDSetIndex); + if (maybeProperties) { + return *maybeProperties; + } + + const auto* pCesiumPrimitive = Cast(Hit.Component); + if (!pCesiumPrimitive) { + return TMap(); + } + + // Query for primitive-level metadata. (EXT_mesh_features) + const CesiumPrimitiveData& primData = pCesiumPrimitive->getPrimitiveData(); + const FCesiumPrimitiveFeatures& features = primData.Features; + const TArray& featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets(features); + + if (FeatureIDSetIndex < 0 || FeatureIDSetIndex >= featureIDSets.Num()) { + return TMap(); + } + + const FCesiumFeatureIdSet& featureIDSet = featureIDSets[FeatureIDSetIndex]; + const int64 propertyTableIndex = + UCesiumFeatureIdSetBlueprintLibrary::GetPropertyTableIndex(featureIDSet); + + const TArray& propertyTables = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTables(pModel->Metadata); + if (propertyTableIndex < 0 || propertyTableIndex >= propertyTables.Num()) { + return TMap(); + } + + const FCesiumPropertyTable& propertyTable = + propertyTables[propertyTableIndex]; + + int64 featureID = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromHit( + features, + Hit, + FeatureIDSetIndex); + if (featureID < 0) { + return TMap(); + } + + return UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeature( + propertyTable, + featureID); +} + +TMap +UCesiumMetadataPickingBlueprintLibrary::GetPropertyTextureValuesFromHit( + const FHitResult& Hit, + int64 PropertyTextureIndex) { + if (!Hit.Component.IsValid()) { + return EmptyCesiumMetadataValueMap; + } + + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast(Hit.Component.Get()); + if (!IsValid(pGltfComponent)) { + return EmptyCesiumMetadataValueMap; + } + + const UCesiumGltfComponent* pModel = + Cast(pGltfComponent->GetOuter()); + if (!IsValid(pModel)) { + return EmptyCesiumMetadataValueMap; + } + + const TArray& propertyTextures = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTextures( + pModel->Metadata); + if (PropertyTextureIndex < 0 || + PropertyTextureIndex >= propertyTextures.Num()) { + return EmptyCesiumMetadataValueMap; + } + + return UCesiumPropertyTextureBlueprintLibrary::GetMetadataValuesFromHit( + propertyTextures[PropertyTextureIndex], + Hit); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataPrimitive.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataPrimitive.cpp new file mode 100644 index 0000000..38aad22 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataPrimitive.cpp @@ -0,0 +1,102 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataPrimitive.h" +#include "CesiumGltf/Model.h" + +PRAGMA_DISABLE_DEPRECATION_WARNINGS + +FCesiumMetadataPrimitive::FCesiumMetadataPrimitive( + const FCesiumPrimitiveFeatures& PrimitiveFeatures, + const FCesiumPrimitiveMetadata& PrimitiveMetadata, + const FCesiumModelMetadata& ModelMetadata) + : _pPrimitiveFeatures(&PrimitiveFeatures), + _pPrimitiveMetadata(&PrimitiveMetadata), + _pModelMetadata(&ModelMetadata) {} + +const TArray +UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdAttributes( + UPARAM(ref) const FCesiumMetadataPrimitive& MetadataPrimitive) { + TArray featureIDAttributes; + if (!MetadataPrimitive._pPrimitiveFeatures) { + return featureIDAttributes; + } + + const TArray featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSetsOfType( + *MetadataPrimitive._pPrimitiveFeatures, + ECesiumFeatureIdSetType::Attribute); + + featureIDAttributes.Reserve(featureIDSets.Num()); + for (const FCesiumFeatureIdSet& featureIDSet : featureIDSets) { + featureIDAttributes.Add( + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute( + featureIDSet)); + } + + return featureIDAttributes; +} + +const TArray +UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdTextures( + UPARAM(ref) const FCesiumMetadataPrimitive& MetadataPrimitive) { + TArray featureIDTextures; + if (!MetadataPrimitive._pPrimitiveFeatures) { + return featureIDTextures; + } + + const TArray featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSetsOfType( + *MetadataPrimitive._pPrimitiveFeatures, + ECesiumFeatureIdSetType::Texture); + + featureIDTextures.Reserve(featureIDSets.Num()); + for (const FCesiumFeatureIdSet& featureIDSet : featureIDSets) { + featureIDTextures.Add( + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDTexture( + featureIDSet)); + } + + return featureIDTextures; +} + +const TArray +UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureTextureNames( + UPARAM(ref) const FCesiumMetadataPrimitive& MetadataPrimitive) { + TArray propertyTextureNames; + if (!MetadataPrimitive._pPrimitiveMetadata || + !MetadataPrimitive._pModelMetadata) { + return TArray(); + } + + const TArray& propertyTextureIndices = + UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyTextureIndices( + *MetadataPrimitive._pPrimitiveMetadata); + + const TArray propertyTextures = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTexturesAtIndices( + *MetadataPrimitive._pModelMetadata, + propertyTextureIndices); + + propertyTextureNames.Reserve(propertyTextures.Num()); + for (auto propertyTexture : propertyTextures) { + propertyTextureNames.Add( + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureName( + propertyTexture)); + } + + return propertyTextureNames; +} + +int64 UCesiumMetadataPrimitiveBlueprintLibrary::GetFirstVertexIDFromFaceID( + UPARAM(ref) const FCesiumMetadataPrimitive& MetadataPrimitive, + int64 FaceID) { + if (!MetadataPrimitive._pPrimitiveFeatures) { + return -1; + } + + return UCesiumPrimitiveFeaturesBlueprintLibrary::GetFirstVertexFromFace( + *MetadataPrimitive._pPrimitiveFeatures, + FaceID); +} + +PRAGMA_ENABLE_DEPRECATION_WARNINGS diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataUtilityBlueprintLibrary.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataUtilityBlueprintLibrary.cpp new file mode 100644 index 0000000..a4df005 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataUtilityBlueprintLibrary.cpp @@ -0,0 +1,110 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +PRAGMA_DISABLE_DEPRECATION_WARNINGS + +#include "CesiumMetadataUtilityBlueprintLibrary.h" +#include "CesiumFeatureIdTexture.h" +#include "CesiumGltfComponent.h" +#include "CesiumGltfPrimitiveComponent.h" + +static FCesiumMetadataPrimitive EmptyMetadataPrimitive; + +const FCesiumMetadataPrimitive& +UCesiumMetadataUtilityBlueprintLibrary::GetPrimitiveMetadata( + const UPrimitiveComponent* component) { + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast(component); + if (!IsValid(pGltfComponent)) { + return EmptyMetadataPrimitive; + } + + return pGltfComponent->getPrimitiveData().Metadata_DEPRECATED; +} + +TMap +UCesiumMetadataUtilityBlueprintLibrary::GetMetadataValuesForFace( + const UPrimitiveComponent* component, + int64 FaceIndex) { + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast(component); + if (!IsValid(pGltfComponent)) { + return TMap(); + } + + const CesiumPrimitiveData& primData = pGltfComponent->getPrimitiveData(); + const UCesiumGltfComponent* pModel = + Cast(pGltfComponent->GetOuter()); + if (!IsValid(pModel)) { + return TMap(); + } + + const FCesiumPrimitiveFeatures& features = primData.Features; + const TArray& featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSetsOfType( + features, + ECesiumFeatureIdSetType::Attribute); + if (featureIDSets.Num() == 0) { + return TMap(); + } + + const FCesiumModelMetadata& modelMetadata = pModel->Metadata; + const FCesiumPrimitiveMetadata& primitiveMetadata = primData.Metadata; + + // For now, only considers the first feature ID set + const FCesiumFeatureIdSet& featureIDSet = featureIDSets[0]; + const int64 propertyTableIndex = + UCesiumFeatureIdSetBlueprintLibrary::GetPropertyTableIndex(featureIDSet); + + const TArray& propertyTables = + UCesiumModelMetadataBlueprintLibrary::GetPropertyTables(modelMetadata); + if (propertyTableIndex < 0 || propertyTableIndex >= propertyTables.Num()) { + return TMap(); + } + + const FCesiumPropertyTable& propertyTable = + propertyTables[propertyTableIndex]; + + int64 featureID = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + features, + FaceIndex, + 0); + if (featureID < 0) { + return TMap(); + } + + return UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeature( + propertyTable, + featureID); +} + +TMap +UCesiumMetadataUtilityBlueprintLibrary::GetMetadataValuesAsStringForFace( + const UPrimitiveComponent* Component, + int64 FaceIndex) { + TMap values = + UCesiumMetadataUtilityBlueprintLibrary::GetMetadataValuesForFace( + Component, + FaceIndex); + TMap strings; + for (auto valuesIt : values) { + strings.Add( + valuesIt.Key, + UCesiumMetadataValueBlueprintLibrary::GetString(valuesIt.Value, "")); + } + + return strings; +} + +int64 UCesiumMetadataUtilityBlueprintLibrary::GetFeatureIDFromFaceID( + UPARAM(ref) const FCesiumMetadataPrimitive& Primitive, + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIDAttribute, + int64 FaceID) { + return UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + FeatureIDAttribute, + UCesiumMetadataPrimitiveBlueprintLibrary::GetFirstVertexIDFromFaceID( + Primitive, + FaceID)); +} + +PRAGMA_ENABLE_DEPRECATION_WARNINGS diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataValue.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataValue.cpp new file mode 100644 index 0000000..8fac58f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataValue.cpp @@ -0,0 +1,319 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataValue.h" +#include "CesiumPropertyArray.h" +#include "UnrealMetadataConversions.h" +#include +#include + +FCesiumMetadataValue::FCesiumMetadataValue(FCesiumMetadataValue&& rhs) = + default; + +FCesiumMetadataValue& +FCesiumMetadataValue::operator=(FCesiumMetadataValue&& rhs) = default; + +FCesiumMetadataValue::FCesiumMetadataValue(const FCesiumMetadataValue& rhs) + : _value(), _valueType(rhs._valueType), _storage(rhs._storage) { + swl::visit( + [this](const auto& value) { + if constexpr (CesiumGltf::IsMetadataArray::value) { + if (!this->_storage.empty()) { + this->_value = decltype(value)(this->_storage); + } else { + this->_value = value; + } + } else { + this->_value = value; + } + }, + rhs._value); +} + +FCesiumMetadataValue& +FCesiumMetadataValue::operator=(const FCesiumMetadataValue& rhs) { + *this = FCesiumMetadataValue(rhs); + return *this; +} + +ECesiumMetadataBlueprintType +UCesiumMetadataValueBlueprintLibrary::GetBlueprintType( + UPARAM(ref) const FCesiumMetadataValue& Value) { + return CesiumMetadataValueTypeToBlueprintType(Value._valueType); +} + +ECesiumMetadataBlueprintType +UCesiumMetadataValueBlueprintLibrary::GetArrayElementBlueprintType( + UPARAM(ref) const FCesiumMetadataValue& Value) { + if (!Value._valueType.bIsArray) { + return ECesiumMetadataBlueprintType::None; + } + + FCesiumMetadataValueType types(Value._valueType); + types.bIsArray = false; + + return CesiumMetadataValueTypeToBlueprintType(types); +} + +FCesiumMetadataValueType UCesiumMetadataValueBlueprintLibrary::GetValueType( + UPARAM(ref) const FCesiumMetadataValue& Value) { + return Value._valueType; +} + +PRAGMA_DISABLE_DEPRECATION_WARNINGS + +ECesiumMetadataTrueType_DEPRECATED +UCesiumMetadataValueBlueprintLibrary::GetTrueType( + UPARAM(ref) const FCesiumMetadataValue& Value) { + return CesiumMetadataValueTypeToTrueType(Value._valueType); +} + +ECesiumMetadataTrueType_DEPRECATED +UCesiumMetadataValueBlueprintLibrary::GetTrueComponentType( + UPARAM(ref) const FCesiumMetadataValue& Value) { + FCesiumMetadataValueType type = Value._valueType; + type.bIsArray = false; + return CesiumMetadataValueTypeToTrueType(type); +} + +bool UCesiumMetadataValueBlueprintLibrary::GetBoolean( + UPARAM(ref) const FCesiumMetadataValue& Value, + bool DefaultValue) { + return swl::visit( + [DefaultValue](auto value) -> bool { + return CesiumGltf::MetadataConversions::convert( + value) + .value_or(DefaultValue); + }, + Value._value); +} + +PRAGMA_ENABLE_DEPRECATION_WARNINGS + +uint8 UCesiumMetadataValueBlueprintLibrary::GetByte( + UPARAM(ref) const FCesiumMetadataValue& Value, + uint8 DefaultValue) { + return swl::visit( + [DefaultValue](auto value) -> uint8 { + return CesiumGltf::MetadataConversions::convert( + value) + .value_or(DefaultValue); + }, + Value._value); +} + +int32 UCesiumMetadataValueBlueprintLibrary::GetInteger( + UPARAM(ref) const FCesiumMetadataValue& Value, + int32 DefaultValue) { + return swl::visit( + [DefaultValue](auto value) { + return CesiumGltf::MetadataConversions::convert( + value) + .value_or(DefaultValue); + }, + Value._value); +} + +int64 UCesiumMetadataValueBlueprintLibrary::GetInteger64( + UPARAM(ref) const FCesiumMetadataValue& Value, + int64 DefaultValue) { + return swl::visit( + [DefaultValue](auto value) -> int64 { + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + }, + Value._value); +} + +float UCesiumMetadataValueBlueprintLibrary::GetFloat( + UPARAM(ref) const FCesiumMetadataValue& Value, + float DefaultValue) { + return swl::visit( + [DefaultValue](auto value) -> float { + return CesiumGltf::MetadataConversions::convert( + value) + .value_or(DefaultValue); + }, + Value._value); +} + +double UCesiumMetadataValueBlueprintLibrary::GetFloat64( + UPARAM(ref) const FCesiumMetadataValue& Value, + double DefaultValue) { + return swl::visit( + [DefaultValue](auto value) -> double { + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + }, + Value._value); +} + +FIntPoint UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FIntPoint& DefaultValue) { + return swl::visit( + [&DefaultValue](auto value) -> FIntPoint { + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toIntPoint(value, DefaultValue); + } else { + auto maybeVec2 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec2 ? UnrealMetadataConversions::toIntPoint(*maybeVec2) + : DefaultValue; + } + }, + Value._value); +} + +FVector2D UCesiumMetadataValueBlueprintLibrary::GetVector2D( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FVector2D& DefaultValue) { + return swl::visit( + [&DefaultValue](auto value) -> FVector2D { + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector2D(value, DefaultValue); + } else { + auto maybeVec2 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec2 ? UnrealMetadataConversions::toVector2D(*maybeVec2) + : DefaultValue; + } + }, + Value._value); +} + +FIntVector UCesiumMetadataValueBlueprintLibrary::GetIntVector( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FIntVector& DefaultValue) { + return swl::visit( + [&DefaultValue](auto value) -> FIntVector { + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toIntVector(value, DefaultValue); + } else { + auto maybeVec3 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec3 ? UnrealMetadataConversions::toIntVector(*maybeVec3) + : DefaultValue; + } + }, + Value._value); +} + +FVector3f UCesiumMetadataValueBlueprintLibrary::GetVector3f( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FVector3f& DefaultValue) { + return swl::visit( + [&DefaultValue](auto value) -> FVector3f { + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector3f(value, DefaultValue); + } else { + auto maybeVec3 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec3 ? UnrealMetadataConversions::toVector3f(*maybeVec3) + : DefaultValue; + } + }, + Value._value); +} + +FVector UCesiumMetadataValueBlueprintLibrary::GetVector( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FVector& DefaultValue) { + return swl::visit( + [&DefaultValue](auto value) -> FVector { + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector(value, DefaultValue); + } else { + auto maybeVec3 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec3 ? UnrealMetadataConversions::toVector(*maybeVec3) + : DefaultValue; + } + }, + Value._value); +} + +FVector4 UCesiumMetadataValueBlueprintLibrary::GetVector4( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FVector4& DefaultValue) { + return swl::visit( + [&DefaultValue](auto value) -> FVector4 { + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector4(value, DefaultValue); + } else { + auto maybeVec4 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec4 ? UnrealMetadataConversions::toVector4(*maybeVec4) + : DefaultValue; + } + }, + Value._value); +} + +FMatrix UCesiumMetadataValueBlueprintLibrary::GetMatrix( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FMatrix& DefaultValue) { + auto maybeMat4 = swl::visit( + [&DefaultValue](auto value) -> std::optional { + return CesiumGltf::MetadataConversions:: + convert(value); + }, + Value._value); + + return maybeMat4 ? UnrealMetadataConversions::toMatrix(*maybeMat4) + : DefaultValue; +} + +FString UCesiumMetadataValueBlueprintLibrary::GetString( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FString& DefaultValue) { + return swl::visit( + [&DefaultValue](auto value) -> FString { + using ValueType = decltype(value); + if constexpr ( + CesiumGltf::IsMetadataVecN::value || + CesiumGltf::IsMetadataMatN::value || + CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toString(value); + } else { + auto maybeString = CesiumGltf:: + MetadataConversions::convert(value); + + return maybeString ? UnrealMetadataConversions::toString(*maybeString) + : DefaultValue; + } + }, + Value._value); +} + +FCesiumPropertyArray UCesiumMetadataValueBlueprintLibrary::GetArray( + UPARAM(ref) const FCesiumMetadataValue& Value) { + return swl::visit( + [](auto value) -> FCesiumPropertyArray { + if constexpr (CesiumGltf::IsMetadataArray::value) { + return FCesiumPropertyArray(value); + } + return FCesiumPropertyArray(); + }, + Value._value); +} + +bool UCesiumMetadataValueBlueprintLibrary::IsEmpty( + UPARAM(ref) const FCesiumMetadataValue& Value) { + return swl::holds_alternative(Value._value); +} + +TMap UCesiumMetadataValueBlueprintLibrary::GetValuesAsStrings( + const TMap& Values) { + TMap strings; + for (auto valuesIt : Values) { + strings.Add( + valuesIt.Key, + UCesiumMetadataValueBlueprintLibrary::GetString( + valuesIt.Value, + FString())); + } + + return strings; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumModelMetadata.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumModelMetadata.cpp new file mode 100644 index 0000000..4deb661 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumModelMetadata.cpp @@ -0,0 +1,133 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumModelMetadata.h" +#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltfComponent.h" +#include "CesiumGltfPrimitiveComponent.h" + +static FCesiumModelMetadata EmptyModelMetadata; + +static FCesiumPropertyTable EmptyPropertyTable; +static FCesiumPropertyTexture EmptyPropertyTexture; + +FCesiumModelMetadata::FCesiumModelMetadata( + const CesiumGltf::Model& InModel, + const CesiumGltf::ExtensionModelExtStructuralMetadata& Metadata) { + this->_propertyTables.Reserve(Metadata.propertyTables.size()); + for (const auto& propertyTable : Metadata.propertyTables) { + this->_propertyTables.Emplace(FCesiumPropertyTable(InModel, propertyTable)); + } + + this->_propertyTextures.Reserve(Metadata.propertyTextures.size()); + for (const auto& propertyTexture : Metadata.propertyTextures) { + this->_propertyTextures.Emplace( + FCesiumPropertyTexture(InModel, propertyTexture)); + } +} + +/*static*/ +const FCesiumModelMetadata& +UCesiumModelMetadataBlueprintLibrary::GetModelMetadata( + const UPrimitiveComponent* component) { + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast(component); + + if (!IsValid(pGltfComponent)) { + return EmptyModelMetadata; + } + + const UCesiumGltfComponent* pModel = + Cast(pGltfComponent->GetOuter()); + if (!IsValid(pModel)) { + return EmptyModelMetadata; + } + + return pModel->Metadata; +} + +/*static*/ const TMap +UCesiumModelMetadataBlueprintLibrary::GetFeatureTables( + UPARAM(ref) const FCesiumModelMetadata& ModelMetadata) { + TMap result; + for (const FCesiumPropertyTable& propertyTable : + ModelMetadata._propertyTables) { + result.Add( + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableName( + propertyTable), + propertyTable); + } + return result; +} + +/*static*/ const TMap +UCesiumModelMetadataBlueprintLibrary::GetFeatureTextures( + UPARAM(ref) const FCesiumModelMetadata& ModelMetadata) { + TMap result; + for (const FCesiumPropertyTexture& propertyTexture : + ModelMetadata._propertyTextures) { + result.Add( + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureName( + propertyTexture), + propertyTexture); + } + return result; +} + +/*static*/ +const TArray& +UCesiumModelMetadataBlueprintLibrary::GetPropertyTables( + UPARAM(ref) const FCesiumModelMetadata& ModelMetadata) { + return ModelMetadata._propertyTables; +} + +/*static*/ const FCesiumPropertyTable& +UCesiumModelMetadataBlueprintLibrary::GetPropertyTable( + UPARAM(ref) const FCesiumModelMetadata& ModelMetadata, + const int64 Index) { + if (Index < 0 || Index >= ModelMetadata._propertyTables.Num()) { + return EmptyPropertyTable; + } + + return ModelMetadata._propertyTables[Index]; +} + +/*static*/ const TArray +UCesiumModelMetadataBlueprintLibrary::GetPropertyTablesAtIndices( + UPARAM(ref) const FCesiumModelMetadata& ModelMetadata, + const TArray& Indices) { + TArray result; + for (int64 Index : Indices) { + result.Add(GetPropertyTable(ModelMetadata, Index)); + } + return result; +} + +/*static*/ +const TArray& +UCesiumModelMetadataBlueprintLibrary::GetPropertyTextures( + UPARAM(ref) const FCesiumModelMetadata& ModelMetadata) { + return ModelMetadata._propertyTextures; +} + +/*static*/ const FCesiumPropertyTexture& +UCesiumModelMetadataBlueprintLibrary::GetPropertyTexture( + UPARAM(ref) const FCesiumModelMetadata& ModelMetadata, + const int64 Index) { + if (Index < 0 || Index >= ModelMetadata._propertyTextures.Num()) { + return EmptyPropertyTexture; + } + + return ModelMetadata._propertyTextures[Index]; +} + +/*static*/ const TArray +UCesiumModelMetadataBlueprintLibrary::GetPropertyTexturesAtIndices( + UPARAM(ref) const FCesiumModelMetadata& ModelMetadata, + const TArray& Indices) { + TArray result; + for (int64 Index : Indices) { + result.Add(GetPropertyTexture(ModelMetadata, Index)); + } + return result; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumOriginShiftComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumOriginShiftComponent.cpp new file mode 100644 index 0000000..8a5fa3c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumOriginShiftComponent.cpp @@ -0,0 +1,155 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumOriginShiftComponent.h" +#include "CesiumGeoreference.h" +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumSubLevelComponent.h" +#include "CesiumSubLevelSwitcherComponent.h" +#include "CesiumWgs84Ellipsoid.h" +#include "LevelInstance/LevelInstanceActor.h" + +#if WITH_EDITOR +#include "Editor.h" +#endif + +ECesiumOriginShiftMode UCesiumOriginShiftComponent::GetMode() const { + return this->Mode; +} + +void UCesiumOriginShiftComponent::SetMode(ECesiumOriginShiftMode NewMode) { + this->Mode = NewMode; +} + +double UCesiumOriginShiftComponent::GetDistance() const { + return this->Distance; +} + +void UCesiumOriginShiftComponent::SetDistance(double NewDistance) { + this->Distance = NewDistance; +} + +UCesiumOriginShiftComponent::UCesiumOriginShiftComponent() { + this->PrimaryComponentTick.bCanEverTick = true; + this->PrimaryComponentTick.TickGroup = ETickingGroup::TG_PrePhysics; + this->bAutoActivate = true; +} + +namespace { +/** + * @brief Clamping addition. + * + * Returns the sum of the given values, clamping the result to + * the minimum/maximum value that can be represented as a 32 bit + * signed integer. + * + * @param f The floating point value + * @param i The integer value + * @return The clamped result + */ +int32 clampedAdd(double f, int32 i) { + int64 sum = static_cast(f) + static_cast(i); + int64 min = static_cast(TNumericLimits::Min()); + int64 max = static_cast(TNumericLimits::Max()); + int64 clamped = FMath::Max(min, FMath::Min(max, sum)); + return static_cast(clamped); +} +} // namespace + +void UCesiumOriginShiftComponent::TickComponent( + float DeltaTime, + ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) { + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + if (TickType != ELevelTick::LEVELTICK_All) + return; + + if (!this->IsActive() || this->Mode == ECesiumOriginShiftMode::Disabled) + return; + + UCesiumGlobeAnchorComponent* GlobeAnchor = this->GetGlobeAnchor(); + if (!IsValid(GlobeAnchor)) + return; + + ACesiumGeoreference* Georeference = GlobeAnchor->ResolveGeoreference(); + + if (!IsValid(Georeference)) + return; + + UCesiumEllipsoid* Ellipsoid = Georeference->GetEllipsoid(); + + check(IsValid(Ellipsoid)); + + UCesiumSubLevelSwitcherComponent* Switcher = + Georeference->GetSubLevelSwitcher(); + if (!Switcher) + return; + + const TArray>& Sublevels = + Switcher->GetRegisteredSubLevelsWeak(); + + // If we don't have any known sub-levels, and aren't origin shifting outside + // of sub-levels, then bail quickly to save ourselves a little work. + if (Sublevels.IsEmpty() && + this->Mode == ECesiumOriginShiftMode::SwitchSubLevelsOnly) { + return; + } + + FVector ActorEcef = GlobeAnchor->GetEarthCenteredEarthFixedPosition(); + + ALevelInstance* ClosestActiveLevel = nullptr; + double ClosestLevelDistance = std::numeric_limits::max(); + + for (int32 i = 0; i < Sublevels.Num(); ++i) { + ALevelInstance* Current = Sublevels[i].Get(); + if (!IsValid(Current)) + continue; + + UCesiumSubLevelComponent* SubLevelComponent = + Current->FindComponentByClass(); + if (!IsValid(SubLevelComponent)) + continue; + + if (!SubLevelComponent->GetEnabled()) + continue; + + FVector LevelEcef = + Ellipsoid->LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + FVector( + SubLevelComponent->GetOriginLongitude(), + SubLevelComponent->GetOriginLatitude(), + SubLevelComponent->GetOriginHeight())); + + double LevelDistance = FVector::Distance(LevelEcef, ActorEcef); + if (LevelDistance < SubLevelComponent->GetLoadRadius() && + LevelDistance < ClosestLevelDistance) { + ClosestActiveLevel = Current; + ClosestLevelDistance = LevelDistance; + } + } + + Switcher->SetTargetSubLevel(ClosestActiveLevel); + + // Only shift the origin when we're outside of all sub-levels. + bool doOriginShift = + Switcher->GetTargetSubLevel() == nullptr && + Switcher->GetCurrentSubLevel() == nullptr && + this->Mode != ECesiumOriginShiftMode::SwitchSubLevelsOnly; + + if (doOriginShift) { + // We're between sub-levels, but we also only want to shift the origin when + // the Actor has traveled more than Distance from the old origin. + AActor* Actor = this->GetOwner(); + doOriginShift = + IsValid(Actor) && Actor->GetActorLocation().SquaredLength() > + this->Distance * this->Distance; + } + + if (doOriginShift) { + if (this->Mode == ECesiumOriginShiftMode::ChangeCesiumGeoreference) { + Georeference->SetOriginEarthCenteredEarthFixed(ActorEcef); + } else { + check(false && "Missing ECesiumOriginShiftMode implementation.") + } + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPointAttenuationVertexFactory.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPointAttenuationVertexFactory.cpp new file mode 100644 index 0000000..6453a58 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPointAttenuationVertexFactory.cpp @@ -0,0 +1,211 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPointAttenuationVertexFactory.h" + +#include "DataDrivenShaderPlatformInfo.h" +#include "MaterialDomain.h" +#include "MeshBatch.h" +#include "MeshDrawShaderBindings.h" +#include "MeshMaterialShader.h" +#include "RenderCommandFence.h" +#include "Runtime/Launch/Resources/Version.h" + +void FCesiumPointAttenuationIndexBuffer::InitRHI( + FRHICommandListBase& RHICmdList) { + if (!bAttenuationSupported) { + return; + } + + // This must be called from Rendering thread + check(IsInRenderingThread()); + + FRHIResourceCreateInfo CreateInfo(TEXT("FCesiumPointAttenuationIndexBuffer")); + const uint32 NumIndices = NumPoints * 6; + const uint32 Size = NumIndices * sizeof(uint32); + + IndexBufferRHI = RHICmdList.CreateBuffer( + Size, + BUF_Static | BUF_IndexBuffer, + sizeof(uint32), + ERHIAccess::VertexOrIndexBuffer, + CreateInfo); + + uint32* Data = + (uint32*)RHICmdList.LockBuffer(IndexBufferRHI, 0, Size, RLM_WriteOnly); + + for (uint32 index = 0, bufferIndex = 0; bufferIndex < NumIndices; + index += 4) { + // Generate six indices per quad, each representing an attenuated point in + // the point cloud. + Data[bufferIndex++] = index; + Data[bufferIndex++] = index + 1; + Data[bufferIndex++] = index + 2; + Data[bufferIndex++] = index; + Data[bufferIndex++] = index + 2; + Data[bufferIndex++] = index + 3; + } + + RHICmdList.UnlockBuffer(IndexBufferRHI); +} + +class FCesiumPointAttenuationVertexFactoryShaderParameters + : public FVertexFactoryShaderParameters { + + DECLARE_TYPE_LAYOUT( + FCesiumPointAttenuationVertexFactoryShaderParameters, + NonVirtual); + +public: + void Bind(const FShaderParameterMap& ParameterMap) { + PositionBuffer.Bind(ParameterMap, TEXT("PositionBuffer")); + PackedTangentsBuffer.Bind(ParameterMap, TEXT("PackedTangentsBuffer")); + ColorBuffer.Bind(ParameterMap, TEXT("ColorBuffer")); + TexCoordBuffer.Bind(ParameterMap, TEXT("TexCoordBuffer")); + NumTexCoords.Bind(ParameterMap, TEXT("NumTexCoords")); + bHasPointColors.Bind(ParameterMap, TEXT("bHasPointColors")); + AttenuationParameters.Bind(ParameterMap, TEXT("AttenuationParameters")); + } + + void GetElementShaderBindings( + const FSceneInterface* Scene, + const FSceneView* View, + const FMeshMaterialShader* Shader, + const EVertexInputStreamType InputStreamType, + ERHIFeatureLevel::Type FeatureLevel, + const FVertexFactory* VertexFactory, + const FMeshBatchElement& BatchElement, + FMeshDrawSingleShaderBindings& ShaderBindings, + FVertexInputStreamArray& VertexStreams) const { + FCesiumPointAttenuationBatchElementUserData* UserData = + (FCesiumPointAttenuationBatchElementUserData*)BatchElement.UserData; + if (UserData->PositionBuffer && PositionBuffer.IsBound()) { + ShaderBindings.Add(PositionBuffer, UserData->PositionBuffer); + } + if (UserData->PackedTangentsBuffer && PackedTangentsBuffer.IsBound()) { + ShaderBindings.Add(PackedTangentsBuffer, UserData->PackedTangentsBuffer); + } + if (UserData->ColorBuffer && ColorBuffer.IsBound()) { + ShaderBindings.Add(ColorBuffer, UserData->ColorBuffer); + } + if (UserData->TexCoordBuffer && TexCoordBuffer.IsBound()) { + ShaderBindings.Add(TexCoordBuffer, UserData->TexCoordBuffer); + } + if (NumTexCoords.IsBound()) { + ShaderBindings.Add(NumTexCoords, UserData->NumTexCoords); + } + if (bHasPointColors.IsBound()) { + ShaderBindings.Add(bHasPointColors, UserData->bHasPointColors); + } + if (AttenuationParameters.IsBound()) { + ShaderBindings.Add( + AttenuationParameters, + UserData->AttenuationParameters); + } + } + +private: + LAYOUT_FIELD(FShaderResourceParameter, PositionBuffer); + LAYOUT_FIELD(FShaderResourceParameter, PackedTangentsBuffer); + LAYOUT_FIELD(FShaderResourceParameter, ColorBuffer); + LAYOUT_FIELD(FShaderResourceParameter, TexCoordBuffer); + LAYOUT_FIELD(FShaderParameter, NumTexCoords); + LAYOUT_FIELD(FShaderParameter, bHasPointColors); + LAYOUT_FIELD(FShaderParameter, AttenuationParameters); +}; + +/** + * A dummy vertex buffer to bind when rendering attenuated point clouds. This + * prevents rendering pipeline errors that can occur with zero-stream input + * layouts. + */ +class FCesiumPointAttenuationDummyVertexBuffer : public FVertexBuffer { +public: + virtual void InitRHI(FRHICommandListBase& RHICmdList) override; +}; + +void FCesiumPointAttenuationDummyVertexBuffer::InitRHI( + FRHICommandListBase& RHICmdList) { + FRHIResourceCreateInfo CreateInfo( + TEXT("FCesiumPointAttenuationDummyVertexBuffer")); + VertexBufferRHI = RHICmdList.CreateBuffer( + sizeof(FVector3f) * 4, + BUF_Static | BUF_VertexBuffer, + 0, + ERHIAccess::VertexOrIndexBuffer, + CreateInfo); + FVector3f* DummyContents = (FVector3f*)RHICmdList.LockBuffer( + VertexBufferRHI, + 0, + sizeof(FVector3f) * 4, + RLM_WriteOnly); + DummyContents[0] = FVector3f(0.0f, 0.0f, 0.0f); + DummyContents[1] = FVector3f(1.0f, 0.0f, 0.0f); + DummyContents[2] = FVector3f(0.0f, 1.0f, 0.0f); + DummyContents[3] = FVector3f(1.0f, 1.0f, 0.0f); + RHICmdList.UnlockBuffer(VertexBufferRHI); +} + +TGlobalResource + GCesiumPointAttenuationDummyVertexBuffer; + +FCesiumPointAttenuationVertexFactory::FCesiumPointAttenuationVertexFactory( + ERHIFeatureLevel::Type InFeatureLevel, + const FPositionVertexBuffer* PositionVertexBuffer) + : FLocalVertexFactory( + InFeatureLevel, + "FCesiumPointAttenuationVertexFactory") {} + +bool FCesiumPointAttenuationVertexFactory::ShouldCompilePermutation( + const FVertexFactoryShaderPermutationParameters& Parameters) { + if (!RHISupportsManualVertexFetch(Parameters.Platform)) { + return false; + } + + return Parameters.MaterialParameters.MaterialDomain == MD_Surface || + Parameters.MaterialParameters.bIsDefaultMaterial || + Parameters.MaterialParameters.bIsSpecialEngineMaterial; +} + +void FCesiumPointAttenuationVertexFactory::ModifyCompilationEnvironment( + const FVertexFactoryShaderPermutationParameters& Parameters, + FShaderCompilerEnvironment& OutEnvironment) { + FLocalVertexFactory::ModifyCompilationEnvironment(Parameters, OutEnvironment); +#if ENGINE_VERSION_5_4_OR_HIGHER + OutEnvironment.SetDefine(TEXT("ENGINE_VERSION_5_4_OR_HIGHER"), TEXT("1")); +#endif + +#if ENGINE_VERSION_5_5_OR_HIGHER + OutEnvironment.SetDefine(TEXT("ENGINE_VERSION_5_5_OR_HIGHER"), TEXT("1")); +#endif +} + +void FCesiumPointAttenuationVertexFactory::InitRHI( + FRHICommandListBase& RHICmdList) { + FVertexDeclarationElementList Elements; + Elements.Add(AccessStreamComponent( + FVertexStreamComponent( + &GCesiumPointAttenuationDummyVertexBuffer, + 0, + sizeof(FVector3f), + VET_Float3), + 0)); + InitDeclaration(Elements); +} + +void FCesiumPointAttenuationVertexFactory::ReleaseRHI() { + FVertexFactory::ReleaseRHI(); +} + +IMPLEMENT_TYPE_LAYOUT(FCesiumPointAttenuationVertexFactoryShaderParameters); + +IMPLEMENT_VERTEX_FACTORY_PARAMETER_TYPE( + FCesiumPointAttenuationVertexFactory, + SF_Vertex, + FCesiumPointAttenuationVertexFactoryShaderParameters); + +IMPLEMENT_VERTEX_FACTORY_TYPE( + FCesiumPointAttenuationVertexFactory, + "/Plugin/CesiumForUnreal/Private/CesiumPointAttenuationVertexFactory.ush", + EVertexFactoryFlags::UsedWithMaterials | + EVertexFactoryFlags::SupportsDynamicLighting | + EVertexFactoryFlags::SupportsPositionOnly); diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPointAttenuationVertexFactory.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPointAttenuationVertexFactory.h new file mode 100644 index 0000000..6b8f16c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPointAttenuationVertexFactory.h @@ -0,0 +1,74 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumCommon.h" +#include "Engine/StaticMesh.h" +#include "LocalVertexFactory.h" +#include "RHIDefinitions.h" +#include "RHIResources.h" +#include "Rendering/PositionVertexBuffer.h" +#include "Runtime/Launch/Resources/Version.h" +#include "SceneManagement.h" + +/** + * This generates the indices necessary for point attenuation in a + * FCesiumGltfPointsComponent. + */ +class FCesiumPointAttenuationIndexBuffer : public FIndexBuffer { +public: + FCesiumPointAttenuationIndexBuffer( + const int32& NumPoints, + const bool bAttenuationSupported) + : NumPoints(NumPoints), bAttenuationSupported(bAttenuationSupported) {} + + virtual void InitRHI(FRHICommandListBase& RHICmdList) override; + +private: + // The number of points in the original point mesh. Not to be confused with + // the number of vertices in the attenuated point mesh. + const int32 NumPoints; + const bool bAttenuationSupported; +}; + +/** + * The parameters to be passed as UserData to the + * shader. + */ +struct FCesiumPointAttenuationBatchElementUserData { + FRHIShaderResourceView* PositionBuffer; + FRHIShaderResourceView* PackedTangentsBuffer; + FRHIShaderResourceView* ColorBuffer; + FRHIShaderResourceView* TexCoordBuffer; + uint32 NumTexCoords; + uint32 bHasPointColors; + FVector3f AttenuationParameters; +}; + +class FCesiumPointAttenuationBatchElementUserDataWrapper + : public FOneFrameResource { +public: + FCesiumPointAttenuationBatchElementUserData Data; +}; + +class FCesiumPointAttenuationVertexFactory : public FLocalVertexFactory { + + DECLARE_VERTEX_FACTORY_TYPE(FCesiumPointAttenuationVertexFactory); + +public: + // Sets default values for this component's properties + FCesiumPointAttenuationVertexFactory( + ERHIFeatureLevel::Type InFeatureLevel, + const FPositionVertexBuffer* PositionVertexBuffer); + + static bool ShouldCompilePermutation( + const FVertexFactoryShaderPermutationParameters& Parameters); + + static void ModifyCompilationEnvironment( + const FVertexFactoryShaderPermutationParameters& Parameters, + FShaderCompilerEnvironment& OutEnvironment); + +private: + virtual void InitRHI(FRHICommandListBase& RHICmdList) override; + virtual void ReleaseRHI() override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPolygonRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPolygonRasterOverlay.cpp new file mode 100644 index 0000000..3f8a7ba --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPolygonRasterOverlay.cpp @@ -0,0 +1,80 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPolygonRasterOverlay.h" +#include "Cesium3DTilesSelection/RasterizedPolygonsTileExcluder.h" +#include "Cesium3DTilesSelection/Tileset.h" +#include "Cesium3DTileset.h" +#include "CesiumBingMapsRasterOverlay.h" +#include "CesiumCartographicPolygon.h" +#include "CesiumRasterOverlays/RasterizedPolygonsOverlay.h" + +using namespace Cesium3DTilesSelection; +using namespace CesiumGeospatial; +using namespace CesiumRasterOverlays; + +UCesiumPolygonRasterOverlay::UCesiumPolygonRasterOverlay() + : UCesiumRasterOverlay() { + this->MaterialLayerKey = TEXT("Clipping"); +} + +std::unique_ptr +UCesiumPolygonRasterOverlay::CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options) { + ACesium3DTileset* pTileset = this->GetOwner(); + + FTransform worldToTileset = + pTileset ? pTileset->GetActorTransform().Inverse() : FTransform::Identity; + + std::vector polygons; + polygons.reserve(this->Polygons.Num()); + + for (auto& pPolygon : this->Polygons) { + if (!pPolygon) { + continue; + } + + CartographicPolygon polygon = + pPolygon->CreateCartographicPolygon(worldToTileset); + polygons.emplace_back(std::move(polygon)); + } + + UCesiumEllipsoid* Ellipsoid = pTileset->ResolveGeoreference()->GetEllipsoid(); + check(IsValid(Ellipsoid)); + + return std::make_unique( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + polygons, + this->InvertSelection, + Ellipsoid->GetNativeEllipsoid(), + CesiumGeospatial::GeographicProjection(Ellipsoid->GetNativeEllipsoid()), + options); +} + +void UCesiumPolygonRasterOverlay::OnAdd( + Tileset* pTileset, + RasterOverlay* pOverlay) { + // If this overlay is used for culling, add it as an excluder too for + // efficiency. + if (pTileset && this->ExcludeSelectedTiles) { + RasterizedPolygonsOverlay* pPolygons = + static_cast(pOverlay); + assert(this->_pExcluder == nullptr); + this->_pExcluder = + std::make_shared(pPolygons); + pTileset->getOptions().excluders.push_back(this->_pExcluder); + } +} + +void UCesiumPolygonRasterOverlay::OnRemove( + Tileset* pTileset, + RasterOverlay* pOverlay) { + auto& excluders = pTileset->getOptions().excluders; + if (this->_pExcluder) { + auto it = std::find(excluders.begin(), excluders.end(), this->_pExcluder); + if (it != excluders.end()) { + excluders.erase(it); + } + + this->_pExcluder.reset(); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPrimitive.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPrimitive.cpp new file mode 100644 index 0000000..c4e8aef --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPrimitive.cpp @@ -0,0 +1,28 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPrimitive.h" + +void CesiumPrimitiveData::destroy() { + this->Features = FCesiumPrimitiveFeatures(); + this->Metadata = FCesiumPrimitiveMetadata(); + this->EncodedFeatures = + CesiumEncodedFeaturesMetadata::EncodedPrimitiveFeatures(); + this->EncodedMetadata = + CesiumEncodedFeaturesMetadata::EncodedPrimitiveMetadata(); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + this->Metadata_DEPRECATED = FCesiumMetadataPrimitive(); + this->EncodedMetadata_DEPRECATED.reset(); + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + this->pTilesetActor = nullptr; + this->pModel = nullptr; + this->pMeshPrimitive = nullptr; + + std::unordered_map emptyTexCoordMap; + this->GltfToUnrealTexCoordMap.swap(emptyTexCoordMap); + + std::unordered_map + emptyAccessorMap; + this->TexCoordAccessorMap.swap(emptyAccessorMap); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPrimitive.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPrimitive.h new file mode 100644 index 0000000..c8a65c7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPrimitive.h @@ -0,0 +1,146 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Cesium3DTileset.h" +#include "CesiumEncodedFeaturesMetadata.h" +#include "CesiumEncodedMetadataUtility.h" +#include "CesiumMetadataPrimitive.h" +#include "CesiumPrimitiveFeatures.h" +#include "CesiumPrimitiveMetadata.h" +#include "CesiumRasterOverlays.h" +#include +#include +#include +#include +#include + +#include "CesiumPrimitive.generated.h" + +namespace CesiumGltf { +struct Model; +struct MeshPrimitive; +} // namespace CesiumGltf + +/** + * Data that is common to the Cesium mesh component classes. + */ +class CesiumPrimitiveData { +public: + /** + * Represents the primitive's EXT_mesh_features extension. + */ + FCesiumPrimitiveFeatures Features; + /** + * Represents the primitive's EXT_structural_metadata extension. + */ + FCesiumPrimitiveMetadata Metadata; + + /** + * The encoded representation of the primitive's EXT_mesh_features extension. + */ + CesiumEncodedFeaturesMetadata::EncodedPrimitiveFeatures EncodedFeatures; + /** + * The encoded representation of the primitive's EXT_structural_metadata + * extension. + */ + CesiumEncodedFeaturesMetadata::EncodedPrimitiveMetadata EncodedMetadata; + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * For backwards compatibility with the EXT_feature_metadata implementation. + */ + FCesiumMetadataPrimitive Metadata_DEPRECATED; + + std::optional + EncodedMetadata_DEPRECATED; + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + ACesium3DTileset* pTilesetActor = nullptr; + const CesiumGltf::Model* pModel = nullptr; + const CesiumGltf::MeshPrimitive* pMeshPrimitive = nullptr; + + /** + * The double-precision transformation matrix for this glTF node. + */ + glm::dmat4x4 HighPrecisionNodeTransform; + + /** + * Maps an overlay texture coordinate ID to the index of the corresponding + * texture coordinates in the mesh's UVs array. + */ + OverlayTextureCoordinateIDMap overlayTextureCoordinateIDToUVIndex; + + /** + * Maps the accessor index in a glTF to its corresponding texture coordinate + * index in the Unreal mesh. The -1 key is reserved for implicit feature IDs + * (in other words, the vertex index). + */ + std::unordered_map GltfToUnrealTexCoordMap; + + /** + * Maps texture coordinate set indices in a glTF to AccessorViews. This stores + * accessor views on texture coordinate sets that will be used by feature ID + * textures or property textures for picking. + */ + std::unordered_map + TexCoordAccessorMap; + + /** + * The position accessor of the glTF primitive. This is used for computing + * the UV at a hit location on a primitive, and is safer to access than the + * mesh's RenderData. + */ + CesiumGltf::AccessorView PositionAccessor; + + /** + * The index accessor of the glTF primitive, if one is specified. This is used + * for computing the UV at a hit location on a primitive. + */ + CesiumGltf::IndexAccessorType IndexAccessor; + + std::optional boundingVolume; + + /** + * The factor by which the positions in the glTF primitive is scaled up when + * the Unreal mesh is populated. + * + * We scale up the meshes because Chaos has a degenerate triangle epsilon test + * in `TriangleMeshImplicitObject.cpp` that is almost laughably too eager. + * Perhaps it would be fine if our meshes actually used units of centimeters + * like UE, but they usually use meters instead. With a factor of 1.0, UE will + * consider a right triangle that is slightly less than ~10cm on each side to + * be degenerate. + * + * This value should be a power-of-two so the the scale affects only the + * exponent of coordinate values, not the mantissa, in order to reduce the + * chances of losing precision. + */ + static constexpr double positionScaleFactor = 1024.0; + + void destroy(); +}; + +UINTERFACE() +class UCesiumPrimitive : public UInterface { + GENERATED_BODY() +}; + +/** + * Common interface to Cesium data and functions for Cesium Components. + * + * The Cesium component classes inherit from different classes in the Unreal + * Component hierarchy, so a multiple inheritance interface approach is needed + * to access their common data. Other ad-hoc functions are added to increase + * code reuse and make certain functions (e.g., UpdateTransformFromCesium()) + * simpler. + */ +class ICesiumPrimitive { + GENERATED_BODY() +public: + virtual CesiumPrimitiveData& getPrimitiveData() = 0; + virtual const CesiumPrimitiveData& getPrimitiveData() const = 0; + + virtual void + UpdateTransformFromCesium(const glm::dmat4& CesiumToUnrealTransform) = 0; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPrimitiveFeatures.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPrimitiveFeatures.cpp new file mode 100644 index 0000000..0abb7a9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPrimitiveFeatures.cpp @@ -0,0 +1,142 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPrimitiveFeatures.h" +#include "CesiumGltf/ExtensionExtInstanceFeatures.h" +#include "CesiumGltf/ExtensionExtMeshFeatures.h" +#include "CesiumGltf/ExtensionExtMeshGpuInstancing.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltfPrimitiveComponent.h" + +static FCesiumPrimitiveFeatures EmptyPrimitiveFeatures; + +FCesiumPrimitiveFeatures::FCesiumPrimitiveFeatures( + const CesiumGltf::Model& Model, + const CesiumGltf::MeshPrimitive& Primitive, + const CesiumGltf::ExtensionExtMeshFeatures& Features) + : _vertexCount(0), _primitiveMode(Primitive.mode) { + this->_indexAccessor = CesiumGltf::getIndexAccessorView(Model, Primitive); + + auto positionIt = Primitive.attributes.find("POSITION"); + if (positionIt != Primitive.attributes.end()) { + const CesiumGltf::Accessor& positionAccessor = + Model.getSafe(Model.accessors, positionIt->second); + _vertexCount = positionAccessor.count; + } + + for (const CesiumGltf::FeatureId& FeatureId : Features.featureIds) { + this->_featureIdSets.Add(FCesiumFeatureIdSet(Model, Primitive, FeatureId)); + } +} + +FCesiumPrimitiveFeatures::FCesiumPrimitiveFeatures( + const CesiumGltf::Model& Model, + const CesiumGltf::Node& Node, + const CesiumGltf::ExtensionExtInstanceFeatures& InstanceFeatures) + : _vertexCount(0), _primitiveMode(-1) { + if (Node.mesh < 0 || Node.mesh >= Model.meshes.size()) { + return; + } + for (const auto& featureId : InstanceFeatures.featureIds) { + this->_featureIdSets.Emplace(Model, Node, featureId); + } +} + +const FCesiumPrimitiveFeatures& +UCesiumPrimitiveFeaturesBlueprintLibrary::GetPrimitiveFeatures( + const UPrimitiveComponent* component) { + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast(component); + if (!IsValid(pGltfComponent)) { + return EmptyPrimitiveFeatures; + } + + return pGltfComponent->getPrimitiveData().Features; +} + +const TArray& +UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets( + UPARAM(ref) const FCesiumPrimitiveFeatures& PrimitiveFeatures) { + return PrimitiveFeatures._featureIdSets; +} + +const TArray +UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSetsOfType( + UPARAM(ref) const FCesiumPrimitiveFeatures& PrimitiveFeatures, + ECesiumFeatureIdSetType Type) { + TArray featureIdSets; + for (int32 i = 0; i < PrimitiveFeatures._featureIdSets.Num(); i++) { + const FCesiumFeatureIdSet& featureIdSet = + PrimitiveFeatures._featureIdSets[i]; + if (UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + featureIdSet) == Type) { + featureIdSets.Add(featureIdSet); + } + } + return featureIdSets; +} + +int64 UCesiumPrimitiveFeaturesBlueprintLibrary::GetVertexCount( + UPARAM(ref) const FCesiumPrimitiveFeatures& PrimitiveFeatures) { + return PrimitiveFeatures._vertexCount; +} + +int64 UCesiumPrimitiveFeaturesBlueprintLibrary::GetFirstVertexFromFace( + UPARAM(ref) const FCesiumPrimitiveFeatures& PrimitiveFeatures, + int64 FaceIndex) { + if (FaceIndex < 0) { + return -1; + } + + auto VertexIndices = std::visit( + CesiumGltf::IndicesForFaceFromAccessor{ + FaceIndex, + PrimitiveFeatures._vertexCount, + PrimitiveFeatures._primitiveMode}, + PrimitiveFeatures._indexAccessor); + + return VertexIndices[0]; +} + +int64 UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + UPARAM(ref) const FCesiumPrimitiveFeatures& PrimitiveFeatures, + int64 FaceIndex, + int64 FeatureIDSetIndex) { + if (FeatureIDSetIndex < 0 || + FeatureIDSetIndex >= PrimitiveFeatures._featureIdSets.Num()) { + return -1; + } + + return UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForVertex( + PrimitiveFeatures._featureIdSets[FeatureIDSetIndex], + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFirstVertexFromFace( + PrimitiveFeatures, + FaceIndex)); +} + +int64 UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromInstance( + const FCesiumPrimitiveFeatures& InstanceFeatures, + int64 InstanceIndex, + int64 FeatureIDSetIndex) { + if (FeatureIDSetIndex < 0 || + FeatureIDSetIndex >= InstanceFeatures._featureIdSets.Num()) { + return -1; + } + const auto& featureIDSet = InstanceFeatures._featureIdSets[FeatureIDSetIndex]; + return UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForInstance( + featureIDSet, + InstanceIndex); +} + +int64 UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromHit( + UPARAM(ref) const FCesiumPrimitiveFeatures& PrimitiveFeatures, + const FHitResult& Hit, + int64 FeatureIDSetIndex) { + if (FeatureIDSetIndex < 0 || + FeatureIDSetIndex >= PrimitiveFeatures._featureIdSets.Num()) { + return -1; + } + + return UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDFromHit( + PrimitiveFeatures._featureIdSets[FeatureIDSetIndex], + Hit); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPrimitiveMetadata.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPrimitiveMetadata.cpp new file mode 100644 index 0000000..10d1532 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPrimitiveMetadata.cpp @@ -0,0 +1,48 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPrimitiveMetadata.h" +#include "CesiumGltf/AccessorView.h" +#include "CesiumGltf/ExtensionMeshPrimitiveExtStructuralMetadata.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltfPrimitiveComponent.h" + +static FCesiumPrimitiveMetadata EmptyPrimitiveMetadata; + +FCesiumPrimitiveMetadata::FCesiumPrimitiveMetadata( + const CesiumGltf::MeshPrimitive& Primitive, + const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata& Metadata) + : _propertyTextureIndices(), _propertyAttributeIndices() { + this->_propertyTextureIndices.Reserve(Metadata.propertyTextures.size()); + for (const int64 propertyTextureIndex : Metadata.propertyTextures) { + this->_propertyTextureIndices.Emplace(propertyTextureIndex); + } + + this->_propertyAttributeIndices.Reserve(Metadata.propertyAttributes.size()); + for (const int64 propertyAttributeIndex : Metadata.propertyAttributes) { + this->_propertyAttributeIndices.Emplace(propertyAttributeIndex); + } +} + +const FCesiumPrimitiveMetadata& +UCesiumPrimitiveMetadataBlueprintLibrary::GetPrimitiveMetadata( + const UPrimitiveComponent* component) { + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast(component); + if (!IsValid(pGltfComponent)) { + return EmptyPrimitiveMetadata; + } + + return pGltfComponent->getPrimitiveData().Metadata; +} + +const TArray& +UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyTextureIndices( + UPARAM(ref) const FCesiumPrimitiveMetadata& PrimitiveMetadata) { + return PrimitiveMetadata._propertyTextureIndices; +} + +const TArray& +UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyAttributeIndices( + UPARAM(ref) const FCesiumPrimitiveMetadata& PrimitiveMetadata) { + return PrimitiveMetadata._propertyAttributeIndices; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyArray.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyArray.cpp new file mode 100644 index 0000000..9003116 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyArray.cpp @@ -0,0 +1,33 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyArray.h" +#include + +FCesiumPropertyArray::FCesiumPropertyArray(FCesiumPropertyArray&& rhs) = + default; + +FCesiumPropertyArray& +FCesiumPropertyArray::operator=(FCesiumPropertyArray&& rhs) = default; + +FCesiumPropertyArray::FCesiumPropertyArray(const FCesiumPropertyArray& rhs) + : _value(), _elementType(rhs._elementType), _storage(rhs._storage) { + swl::visit( + [this](const auto& value) { + if constexpr (CesiumGltf::IsMetadataArray::value) { + if (!this->_storage.empty()) { + this->_value = decltype(value)(this->_storage); + } else { + this->_value = value; + } + } else { + this->_value = value; + } + }, + rhs._value); +} + +FCesiumPropertyArray& +FCesiumPropertyArray::operator=(const FCesiumPropertyArray& rhs) { + *this = FCesiumPropertyArray(rhs); + return *this; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyArrayBlueprintLibrary.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyArrayBlueprintLibrary.cpp new file mode 100644 index 0000000..341a1fd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyArrayBlueprintLibrary.cpp @@ -0,0 +1,179 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyArrayBlueprintLibrary.h" +#include "UnrealMetadataConversions.h" +#include + +ECesiumMetadataBlueprintType +UCesiumPropertyArrayBlueprintLibrary::GetElementBlueprintType( + UPARAM(ref) const FCesiumPropertyArray& array) { + return CesiumMetadataValueTypeToBlueprintType(array._elementType); +} + +ECesiumMetadataBlueprintType +UCesiumPropertyArrayBlueprintLibrary::GetBlueprintComponentType( + UPARAM(ref) const FCesiumPropertyArray& array) { + return CesiumMetadataValueTypeToBlueprintType(array._elementType); +} + +FCesiumMetadataValueType +UCesiumPropertyArrayBlueprintLibrary::GetElementValueType( + UPARAM(ref) const FCesiumPropertyArray& array) { + return array._elementType; +} + +int64 UCesiumPropertyArrayBlueprintLibrary::GetArraySize( + UPARAM(ref) const FCesiumPropertyArray& array) { + return swl::visit([](const auto& view) { return view.size(); }, array._value); +} + +int64 UCesiumPropertyArrayBlueprintLibrary::GetSize( + UPARAM(ref) const FCesiumPropertyArray& array) { + return swl::visit([](const auto& view) { return view.size(); }, array._value); +} + +FCesiumMetadataValue UCesiumPropertyArrayBlueprintLibrary::GetValue( + UPARAM(ref) const FCesiumPropertyArray& array, + int64 index) { + return swl::visit( + [index](const auto& v) -> FCesiumMetadataValue { + if (index < 0 || index >= v.size()) { + FFrame::KismetExecutionMessage( + *FString::Printf( + TEXT( + "Attempted to access index %d from CesiumPropertyArray of length %d!"), + index, + v.size()), + ELogVerbosity::Warning, + FName("CesiumPropertyArrayOutOfBoundsWarning")); + return FCesiumMetadataValue(); + } + return FCesiumMetadataValue(v[index]); + }, + array._value); +} + +ECesiumMetadataTrueType_DEPRECATED +UCesiumPropertyArrayBlueprintLibrary::GetTrueComponentType( + UPARAM(ref) const FCesiumPropertyArray& array) { + return CesiumMetadataValueTypeToTrueType(array._elementType); +} + +bool UCesiumPropertyArrayBlueprintLibrary::GetBoolean( + UPARAM(ref) const FCesiumPropertyArray& array, + int64 index, + bool defaultValue) { + return swl::visit( + [index, defaultValue](const auto& v) -> bool { + if (index < 0 || index >= v.size()) { + return defaultValue; + } + auto value = v[index]; + return CesiumGltf::MetadataConversions::convert( + value) + .value_or(defaultValue); + }, + array._value); +} + +uint8 UCesiumPropertyArrayBlueprintLibrary::GetByte( + UPARAM(ref) const FCesiumPropertyArray& array, + int64 index, + uint8 defaultValue) { + return swl::visit( + [index, defaultValue](const auto& v) -> uint8 { + if (index < 0 || index >= v.size()) { + return defaultValue; + } + auto value = v[index]; + return CesiumGltf::MetadataConversions::convert( + value) + .value_or(defaultValue); + }, + array._value); +} + +int32 UCesiumPropertyArrayBlueprintLibrary::GetInteger( + UPARAM(ref) const FCesiumPropertyArray& array, + int64 index, + int32 defaultValue) { + return swl::visit( + [index, defaultValue](const auto& v) -> int32 { + if (index < 0 || index >= v.size()) { + return defaultValue; + } + auto value = v[index]; + return CesiumGltf::MetadataConversions::convert( + value) + .value_or(defaultValue); + }, + array._value); +} + +int64 UCesiumPropertyArrayBlueprintLibrary::GetInteger64( + UPARAM(ref) const FCesiumPropertyArray& array, + int64 index, + int64 defaultValue) { + return swl::visit( + [index, defaultValue](const auto& v) -> int64 { + if (index < 0 || index >= v.size()) { + return defaultValue; + } + auto value = v[index]; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(defaultValue); + }, + array._value); +} + +float UCesiumPropertyArrayBlueprintLibrary::GetFloat( + UPARAM(ref) const FCesiumPropertyArray& array, + int64 index, + float defaultValue) { + return swl::visit( + [index, defaultValue](const auto& v) -> float { + if (index < 0 || index >= v.size()) { + return defaultValue; + } + auto value = v[index]; + return CesiumGltf::MetadataConversions::convert( + value) + .value_or(defaultValue); + }, + array._value); +} + +double UCesiumPropertyArrayBlueprintLibrary::GetFloat64( + UPARAM(ref) const FCesiumPropertyArray& array, + int64 index, + double defaultValue) { + return swl::visit( + [index, defaultValue](const auto& v) -> double { + auto value = v[index]; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(defaultValue); + }, + array._value); +} + +FString UCesiumPropertyArrayBlueprintLibrary::GetString( + UPARAM(ref) const FCesiumPropertyArray& array, + int64 index, + const FString& defaultValue) { + return swl::visit( + [index, defaultValue](const auto& v) -> FString { + if (index < 0 || index >= v.size()) { + return defaultValue; + } + auto value = v[index]; + auto maybeString = CesiumGltf:: + MetadataConversions::convert(value); + if (!maybeString) { + return defaultValue; + } + return UnrealMetadataConversions::toString(*maybeString); + }, + array._value); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyTable.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyTable.cpp new file mode 100644 index 0000000..83a16af --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyTable.cpp @@ -0,0 +1,135 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyTable.h" +#include "CesiumGltf/PropertyTableView.h" + +static FCesiumPropertyTableProperty EmptyPropertyTableProperty; + +FCesiumPropertyTable::FCesiumPropertyTable( + const CesiumGltf::Model& Model, + const CesiumGltf::PropertyTable& PropertyTable) + : _status(ECesiumPropertyTableStatus::ErrorInvalidPropertyTableClass), + _name(PropertyTable.name.value_or("").c_str()), + _className(PropertyTable.classProperty.c_str()), + _count(PropertyTable.count), + _properties() { + CesiumGltf::PropertyTableView propertyTableView{Model, PropertyTable}; + switch (propertyTableView.status()) { + case CesiumGltf::PropertyTableViewStatus::Valid: + _status = ECesiumPropertyTableStatus::Valid; + break; + default: + // Status was already set in initializer list. + return; + } + + propertyTableView.forEachProperty([&properties = _properties]( + const std::string& propertyName, + auto propertyValue) mutable { + FString key(UTF8_TO_TCHAR(propertyName.data())); + properties.Add(key, FCesiumPropertyTableProperty(propertyValue)); + }); +} + +/*static*/ ECesiumPropertyTableStatus +UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + UPARAM(ref) const FCesiumPropertyTable& PropertyTable) { + return PropertyTable._status; +} + +/*static*/ const FString& +UCesiumPropertyTableBlueprintLibrary::GetPropertyTableName( + UPARAM(ref) const FCesiumPropertyTable& PropertyTable) { + return PropertyTable._name; +} + +/*static*/ int64 UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + UPARAM(ref) const FCesiumPropertyTable& PropertyTable) { + if (PropertyTable._status != ECesiumPropertyTableStatus::Valid) { + return 0; + } + + return PropertyTable._count; +} + +/*static*/ const TMap& +UCesiumPropertyTableBlueprintLibrary::GetProperties( + UPARAM(ref) const FCesiumPropertyTable& PropertyTable) { + return PropertyTable._properties; +} + +/*static*/ const TArray +UCesiumPropertyTableBlueprintLibrary::GetPropertyNames( + UPARAM(ref) const FCesiumPropertyTable& PropertyTable) { + TArray names; + PropertyTable._properties.GenerateKeyArray(names); + return names; +} + +/*static*/ const FCesiumPropertyTableProperty& +UCesiumPropertyTableBlueprintLibrary::FindProperty( + UPARAM(ref) const FCesiumPropertyTable& PropertyTable, + const FString& PropertyName) { + const FCesiumPropertyTableProperty* property = + PropertyTable._properties.Find(PropertyName); + return property ? *property : EmptyPropertyTableProperty; +} + +/*static*/ TMap +UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeature( + UPARAM(ref) const FCesiumPropertyTable& PropertyTable, + int64 FeatureID) { + TMap values; + if (FeatureID < 0 || FeatureID >= PropertyTable._count) { + return values; + } + + for (const auto& pair : PropertyTable._properties) { + const FCesiumPropertyTableProperty& property = pair.Value; + ECesiumPropertyTablePropertyStatus status = + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property); + if (status == ECesiumPropertyTablePropertyStatus::Valid) { + values.Add( + pair.Key, + UCesiumPropertyTablePropertyBlueprintLibrary::GetValue( + pair.Value, + FeatureID)); + } else if ( + status == + ECesiumPropertyTablePropertyStatus::EmptyPropertyWithDefault) { + values.Add( + pair.Key, + UCesiumPropertyTablePropertyBlueprintLibrary::GetDefaultValue( + pair.Value)); + } + } + + return values; +} + +/*static*/ TMap +UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeatureAsStrings( + UPARAM(ref) const FCesiumPropertyTable& PropertyTable, + int64 FeatureID) { + TMap values; + if (FeatureID < 0 || FeatureID >= PropertyTable._count) { + return values; + } + + for (const auto& pair : PropertyTable._properties) { + const FCesiumPropertyTableProperty& property = pair.Value; + ECesiumPropertyTablePropertyStatus status = + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property); + if (status == ECesiumPropertyTablePropertyStatus::Valid) { + values.Add( + pair.Key, + UCesiumPropertyTablePropertyBlueprintLibrary::GetString( + pair.Value, + FeatureID)); + } + } + + return values; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyTableProperty.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyTableProperty.cpp new file mode 100644 index 0000000..dda61f6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyTableProperty.cpp @@ -0,0 +1,1463 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyTableProperty.h" +#include "CesiumGltf/MetadataConversions.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "UnrealMetadataConversions.h" +#include + +namespace { +/** + * Callback on a std::any, assuming that it contains a PropertyTablePropertyView + * of the specified type. If the type does not match, the callback is performed + * on an invalid PropertyTablePropertyView instead. + * + * @param property The std::any containing the property. + * @param callback The callback function. + * + * @tparam TProperty The property type. + * @tparam Normalized Whether the PropertyTablePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template < + typename TProperty, + bool Normalized, + typename TResult, + typename Callback> +TResult +propertyTablePropertyCallback(const std::any& property, Callback&& callback) { + const CesiumGltf::PropertyTablePropertyView* + pProperty = std::any_cast< + CesiumGltf::PropertyTablePropertyView>( + &property); + if (pProperty) { + return callback(*pProperty); + } + + return callback(CesiumGltf::PropertyTablePropertyView()); +} + +/** + * Callback on a std::any, assuming that it contains a PropertyTablePropertyView + * on a scalar type. If the valueType does not have a valid component type, the + * callback is performed on an invalid PropertyTablePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam Normalized Whether the PropertyTablePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult scalarPropertyTablePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.ComponentType) { + case ECesiumMetadataComponentType::Int8: + return propertyTablePropertyCallback( + property, + std::forward(callback)); + case ECesiumMetadataComponentType::Uint8: + return propertyTablePropertyCallback< + uint8_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int16: + return propertyTablePropertyCallback< + int16_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint16: + return propertyTablePropertyCallback< + uint16_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int32: + return propertyTablePropertyCallback< + int32_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint32: + return propertyTablePropertyCallback< + uint32_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int64: + return propertyTablePropertyCallback< + int64_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint64: + return propertyTablePropertyCallback< + uint64_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float32: + return propertyTablePropertyCallback( + property, + std::forward(callback)); + case ECesiumMetadataComponentType::Float64: + return propertyTablePropertyCallback( + property, + std::forward(callback)); + default: + return callback(CesiumGltf::PropertyTablePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a PropertyTablePropertyView + * on a scalar array type. If the valueType does not have a valid component + * type, the callback is performed on an invalid PropertyTablePropertyView + * instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam Normalized Whether the PropertyTablePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult scalarArrayPropertyTablePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.ComponentType) { + case ECesiumMetadataComponentType::Int8: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint8: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int16: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint16: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int32: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint32: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int64: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint64: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float32: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView, + false, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float64: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView, + false, + TResult, + Callback>(property, std::forward(callback)); + default: + return callback(CesiumGltf::PropertyTablePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a PropertyTablePropertyView + * on a glm::vecN type. If the valueType does not have a valid component type, + * the callback is performed on an invalid PropertyTablePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam N The dimensions of the glm::vecN + * @tparam Normalized Whether the PropertyTablePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult vecNPropertyTablePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.ComponentType) { + case ECesiumMetadataComponentType::Int8: + return propertyTablePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint8: + return propertyTablePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int16: + return propertyTablePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint16: + return propertyTablePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int32: + return propertyTablePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint32: + return propertyTablePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int64: + return propertyTablePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint64: + return propertyTablePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float32: + return propertyTablePropertyCallback< + glm::vec, + false, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float64: + return propertyTablePropertyCallback< + glm::vec, + false, + TResult, + Callback>(property, std::forward(callback)); + default: + return callback(CesiumGltf::PropertyTablePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a PropertyTablePropertyView + * on a glm::vecN type. If the valueType does not have a valid component type, + * the callback is performed on an invalid PropertyTablePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam Normalized Whether the PropertyTablePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult vecNPropertyTablePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + if (valueType.Type == ECesiumMetadataType::Vec2) { + return vecNPropertyTablePropertyCallback<2, Normalized, TResult, Callback>( + property, + valueType, + std::forward(callback)); + } + + if (valueType.Type == ECesiumMetadataType::Vec3) { + return vecNPropertyTablePropertyCallback<3, Normalized, TResult, Callback>( + property, + valueType, + std::forward(callback)); + } + + if (valueType.Type == ECesiumMetadataType::Vec4) { + return vecNPropertyTablePropertyCallback<4, Normalized, TResult, Callback>( + property, + valueType, + std::forward(callback)); + } + + return callback(CesiumGltf::PropertyTablePropertyView()); +} + +/** + * Callback on a std::any, assuming that it contains a PropertyTablePropertyView + * on a glm::vecN array type. If the valueType does not have a valid component + * type, the callback is performed on an invalid PropertyTablePropertyView + * instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam N The dimensions of the glm::vecN + * @tparam Normalized Whether the PropertyTablePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult vecNArrayPropertyTablePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.ComponentType) { + case ECesiumMetadataComponentType::Int8: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint8: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int16: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint16: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int32: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint32: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int64: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint64: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float32: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + false, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float64: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + false, + TResult, + Callback>(property, std::forward(callback)); + default: + return callback(CesiumGltf::PropertyTablePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a PropertyTablePropertyView + * on a glm::vecN array type. If the valueType does not have a valid component + * type, the callback is performed on an invalid PropertyTablePropertyView + * instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam Normalized Whether the PropertyTablePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult vecNArrayPropertyTablePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + if (valueType.Type == ECesiumMetadataType::Vec2) { + return vecNArrayPropertyTablePropertyCallback< + 2, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + } + + if (valueType.Type == ECesiumMetadataType::Vec3) { + return vecNArrayPropertyTablePropertyCallback< + 3, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + } + + if (valueType.Type == ECesiumMetadataType::Vec4) { + return vecNArrayPropertyTablePropertyCallback< + 4, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + } + + return callback(CesiumGltf::PropertyTablePropertyView()); +} + +/** + * Callback on a std::any, assuming that it contains a PropertyTablePropertyView + * on a glm::matN type. If the valueType does not have a valid component type, + * the callback is performed on an invalid PropertyTablePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam N The dimensions of the glm::matN + * @tparam TNormalized Whether the PropertyTablePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult matNPropertyTablePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.ComponentType) { + case ECesiumMetadataComponentType::Int8: + return propertyTablePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint8: + return propertyTablePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int16: + return propertyTablePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint16: + return propertyTablePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int32: + return propertyTablePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint32: + return propertyTablePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int64: + return propertyTablePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint64: + return propertyTablePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float32: + return propertyTablePropertyCallback< + glm::mat, + false, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float64: + return propertyTablePropertyCallback< + glm::mat, + false, + TResult, + Callback>(property, std::forward(callback)); + default: + return callback(CesiumGltf::PropertyTablePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a PropertyTablePropertyView + * on a glm::matN type. If the valueType does not have a valid component type, + * the callback is performed on an invalid PropertyTablePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam Normalized Whether the PropertyTablePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult matNPropertyTablePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + if (valueType.Type == ECesiumMetadataType::Mat2) { + return matNPropertyTablePropertyCallback<2, Normalized, TResult, Callback>( + property, + valueType, + std::forward(callback)); + } + + if (valueType.Type == ECesiumMetadataType::Mat3) { + return matNPropertyTablePropertyCallback<3, Normalized, TResult, Callback>( + property, + valueType, + std::forward(callback)); + } + + if (valueType.Type == ECesiumMetadataType::Mat4) { + return matNPropertyTablePropertyCallback<4, Normalized, TResult, Callback>( + property, + valueType, + std::forward(callback)); + } + + return callback(CesiumGltf::PropertyTablePropertyView()); +} + +/** + * Callback on a std::any, assuming that it contains a PropertyTablePropertyView + * on a glm::matN array type. If the valueType does not have a valid component + * type, the callback is performed on an invalid PropertyTablePropertyView + * instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam N The dimensions of the glm::matN + * @tparam TNormalized Whether the PropertyTablePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult matNArrayPropertyTablePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.ComponentType) { + case ECesiumMetadataComponentType::Int8: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint8: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int16: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint16: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int32: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint32: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int64: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint64: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float32: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + false, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float64: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView>, + false, + TResult, + Callback>(property, std::forward(callback)); + default: + return callback(CesiumGltf::PropertyTablePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a PropertyTablePropertyView + * on a glm::matN array type. If the valueType does not have a valid component + * type, the callback is performed on an invalid PropertyTablePropertyView + * instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam Normalized Whether the PropertyTablePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult matNArrayPropertyTablePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + if (valueType.Type == ECesiumMetadataType::Mat2) { + return matNArrayPropertyTablePropertyCallback< + 2, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + } + + if (valueType.Type == ECesiumMetadataType::Mat3) { + return matNArrayPropertyTablePropertyCallback< + 3, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + } + + if (valueType.Type == ECesiumMetadataType::Mat4) { + return matNArrayPropertyTablePropertyCallback< + 4, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + } + + return callback(CesiumGltf::PropertyTablePropertyView()); +} + +template +TResult arrayPropertyTablePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.Type) { + case ECesiumMetadataType::Scalar: + return scalarArrayPropertyTablePropertyCallback< + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + case ECesiumMetadataType::Vec2: + case ECesiumMetadataType::Vec3: + case ECesiumMetadataType::Vec4: + return vecNArrayPropertyTablePropertyCallback< + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + case ECesiumMetadataType::Mat2: + case ECesiumMetadataType::Mat3: + case ECesiumMetadataType::Mat4: + return matNArrayPropertyTablePropertyCallback< + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + case ECesiumMetadataType::Boolean: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView, + false, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataType::String: + return propertyTablePropertyCallback< + CesiumGltf::PropertyArrayView, + false, + TResult, + Callback>(property, std::forward(callback)); + default: + return callback(CesiumGltf::PropertyTablePropertyView()); + } +} + +template +TResult propertyTablePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + bool normalized, + Callback&& callback) { + if (valueType.bIsArray) { + return normalized + ? arrayPropertyTablePropertyCallback( + property, + valueType, + std::forward(callback)) + : arrayPropertyTablePropertyCallback( + property, + valueType, + std::forward(callback)); + } + + switch (valueType.Type) { + case ECesiumMetadataType::Scalar: + return normalized + ? scalarPropertyTablePropertyCallback( + property, + valueType, + std::forward(callback)) + : scalarPropertyTablePropertyCallback( + property, + valueType, + std::forward(callback)); + case ECesiumMetadataType::Vec2: + case ECesiumMetadataType::Vec3: + case ECesiumMetadataType::Vec4: + return normalized + ? vecNPropertyTablePropertyCallback( + property, + valueType, + std::forward(callback)) + : vecNPropertyTablePropertyCallback( + property, + valueType, + std::forward(callback)); + case ECesiumMetadataType::Mat2: + case ECesiumMetadataType::Mat3: + case ECesiumMetadataType::Mat4: + return normalized + ? matNPropertyTablePropertyCallback( + property, + valueType, + std::forward(callback)) + : matNPropertyTablePropertyCallback( + property, + valueType, + std::forward(callback)); + case ECesiumMetadataType::Boolean: + return propertyTablePropertyCallback( + property, + std::forward(callback)); + case ECesiumMetadataType::String: + return propertyTablePropertyCallback< + std::string_view, + false, + TResult, + Callback>(property, std::forward(callback)); + default: + return callback(CesiumGltf::PropertyTablePropertyView()); + } +} + +} // namespace + +ECesiumPropertyTablePropertyStatus +UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertyTablePropertyStatus( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return Property._status; +} + +ECesiumMetadataBlueprintType +UCesiumPropertyTablePropertyBlueprintLibrary::GetBlueprintType( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return CesiumMetadataValueTypeToBlueprintType(Property._valueType); +} + +ECesiumMetadataBlueprintType +UCesiumPropertyTablePropertyBlueprintLibrary::GetArrayElementBlueprintType( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + if (!Property._valueType.bIsArray) { + return ECesiumMetadataBlueprintType::None; + } + + FCesiumMetadataValueType valueType(Property._valueType); + valueType.bIsArray = false; + + return CesiumMetadataValueTypeToBlueprintType(valueType); +} + +FCesiumMetadataValueType +UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return Property._valueType; +} + +int64 UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> int64 { return view.size(); }); +} + +int64 UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> int64 { return view.arrayCount(); }); +} + +bool UCesiumPropertyTablePropertyBlueprintLibrary::GetBoolean( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + bool DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, DefaultValue](const auto& v) -> bool { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +uint8 UCesiumPropertyTablePropertyBlueprintLibrary::GetByte( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + uint8 DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, DefaultValue](const auto& v) -> uint8 { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +int32 UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + int32 DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, DefaultValue](const auto& v) -> int32 { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +int64 UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + int64 DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, DefaultValue](const auto& v) -> int64 { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +float UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + float DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, DefaultValue](const auto& v) -> float { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +double UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat64( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + double DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, DefaultValue](const auto& v) -> double { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +FIntPoint UCesiumPropertyTablePropertyBlueprintLibrary::GetIntPoint( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FIntPoint& DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, &DefaultValue](const auto& v) -> FIntPoint { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toIntPoint(value, DefaultValue); + } else { + auto maybeVec2 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec2 ? UnrealMetadataConversions::toIntPoint(*maybeVec2) + : DefaultValue; + } + }); +} + +FVector2D UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FVector2D& DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, &DefaultValue](const auto& v) -> FVector2D { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector2D(value, DefaultValue); + } else { + auto maybeVec2 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec2 ? UnrealMetadataConversions::toVector2D(*maybeVec2) + : DefaultValue; + } + }); +} + +FIntVector UCesiumPropertyTablePropertyBlueprintLibrary::GetIntVector( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FIntVector& DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, &DefaultValue](const auto& v) -> FIntVector { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toIntVector(value, DefaultValue); + } else { + auto maybeVec3 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec3 ? UnrealMetadataConversions::toIntVector(*maybeVec3) + : DefaultValue; + } + }); +} + +FVector3f UCesiumPropertyTablePropertyBlueprintLibrary::GetVector3f( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FVector3f& DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, &DefaultValue](const auto& v) -> FVector3f { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector3f(value, DefaultValue); + } else { + auto maybeVec3 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec3 ? UnrealMetadataConversions::toVector3f(*maybeVec3) + : DefaultValue; + } + }); +} + +FVector UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FVector& DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, &DefaultValue](const auto& v) -> FVector { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector(value, DefaultValue); + } else { + auto maybeVec3 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec3 ? UnrealMetadataConversions::toVector(*maybeVec3) + : DefaultValue; + } + }); +} + +FVector4 UCesiumPropertyTablePropertyBlueprintLibrary::GetVector4( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FVector4& DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, &DefaultValue](const auto& v) -> FVector4 { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector4(value, DefaultValue); + } else { + auto maybeVec4 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec4 ? UnrealMetadataConversions::toVector4(*maybeVec4) + : DefaultValue; + } + }); +} + +FMatrix UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FMatrix& DefaultValue) { + auto maybeMat4 = propertyTablePropertyCallback>( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID](const auto& v) -> std::optional { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return std::nullopt; + } + auto maybeValue = v.get(FeatureID); + if (!maybeValue) { + return std::nullopt; + } + + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value); + }); + + return maybeMat4 ? UnrealMetadataConversions::toMatrix(*maybeMat4) + : DefaultValue; +} + +FString UCesiumPropertyTablePropertyBlueprintLibrary::GetString( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FString& DefaultValue) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID, &DefaultValue](const auto& v) -> FString { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(FeatureID); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + using ValueType = decltype(value); + + if constexpr ( + CesiumGltf::IsMetadataVecN::value || + CesiumGltf::IsMetadataMatN::value || + CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toString(value); + } else { + auto maybeString = CesiumGltf:: + MetadataConversions::convert(value); + + return maybeString ? UnrealMetadataConversions::toString(*maybeString) + : DefaultValue; + } + }); +} + +FCesiumPropertyArray UCesiumPropertyTablePropertyBlueprintLibrary::GetArray( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID](const auto& v) -> FCesiumPropertyArray { + // size() returns zero if the view is invalid. + if (FeatureID < 0 || FeatureID >= v.size()) { + return FCesiumPropertyArray(); + } + auto maybeValue = v.get(FeatureID); + if (maybeValue) { + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataArray::value) { + return FCesiumPropertyArray(std::move(value)); + } + } + return FCesiumPropertyArray(); + }); +} + +FCesiumMetadataValue UCesiumPropertyTablePropertyBlueprintLibrary::GetValue( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID](const auto& view) -> FCesiumMetadataValue { + // size() returns zero if the view is invalid. + if (FeatureID >= 0 && FeatureID < view.size()) { + return FCesiumMetadataValue(view.get(FeatureID)); + } + return FCesiumMetadataValue(); + }); +} + +FCesiumMetadataValue UCesiumPropertyTablePropertyBlueprintLibrary::GetRawValue( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [FeatureID](const auto& view) -> FCesiumMetadataValue { + // Return an empty value if the property is empty. + if (view.status() == CesiumGltf::PropertyTablePropertyViewStatus:: + EmptyPropertyWithDefault) { + return FCesiumMetadataValue(); + } + + // size() returns zero if the view is invalid. + if (FeatureID >= 0 && FeatureID < view.size()) { + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.getRaw(FeatureID))); + } + + return FCesiumMetadataValue(); + }); +} + +bool UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return Property._normalized; +} + +FCesiumMetadataValue UCesiumPropertyTablePropertyBlueprintLibrary::GetOffset( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no offset is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.offset())); + }); +} + +FCesiumMetadataValue UCesiumPropertyTablePropertyBlueprintLibrary::GetScale( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no scale is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.scale())); + }); +} + +FCesiumMetadataValue +UCesiumPropertyTablePropertyBlueprintLibrary::GetMinimumValue( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no min is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.min())); + }); +} + +FCesiumMetadataValue +UCesiumPropertyTablePropertyBlueprintLibrary::GetMaximumValue( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no max is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.max())); + }); +} + +FCesiumMetadataValue +UCesiumPropertyTablePropertyBlueprintLibrary::GetNoDataValue( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no "no data" value is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.noData())); + }); +} + +FCesiumMetadataValue +UCesiumPropertyTablePropertyBlueprintLibrary::GetDefaultValue( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return propertyTablePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no default value is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.defaultValue())); + }); +} + +PRAGMA_DISABLE_DEPRECATION_WARNINGS + +ECesiumMetadataBlueprintType +UCesiumPropertyTablePropertyBlueprintLibrary::GetBlueprintComponentType( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return UCesiumPropertyTablePropertyBlueprintLibrary:: + GetArrayElementBlueprintType(Property); +} + +ECesiumMetadataTrueType_DEPRECATED +UCesiumPropertyTablePropertyBlueprintLibrary::GetTrueType( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return CesiumMetadataValueTypeToTrueType(Property._valueType); +} + +ECesiumMetadataTrueType_DEPRECATED +UCesiumPropertyTablePropertyBlueprintLibrary::GetTrueComponentType( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + FCesiumMetadataValueType type = Property._valueType; + type.bIsArray = false; + return CesiumMetadataValueTypeToTrueType(type); +} + +int64 UCesiumPropertyTablePropertyBlueprintLibrary::GetNumberOfFeatures( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + Property); +} + +int64 UCesiumPropertyTablePropertyBlueprintLibrary::GetComponentCount( + UPARAM(ref) const FCesiumPropertyTableProperty& Property) { + return UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(Property); +} + +FCesiumMetadataValue +UCesiumPropertyTablePropertyBlueprintLibrary::GetGenericValue( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID) { + return UCesiumPropertyTablePropertyBlueprintLibrary::GetValue( + Property, + FeatureID); +} + +PRAGMA_ENABLE_DEPRECATION_WARNINGS diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyTexture.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyTexture.cpp new file mode 100644 index 0000000..ffefd3e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyTexture.cpp @@ -0,0 +1,160 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyTexture.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltf/PropertyTexturePropertyView.h" +#include "CesiumGltf/PropertyTextureView.h" +#include "CesiumMetadataPickingBlueprintLibrary.h" + +static FCesiumPropertyTextureProperty EmptyPropertyTextureProperty; + +FCesiumPropertyTexture::FCesiumPropertyTexture( + const CesiumGltf::Model& Model, + const CesiumGltf::PropertyTexture& PropertyTexture) + : _status(ECesiumPropertyTextureStatus::ErrorInvalidPropertyTextureClass), + _name(PropertyTexture.name.value_or("").c_str()), + _className(PropertyTexture.classProperty.c_str()) { + CesiumGltf::PropertyTextureView propertyTextureView(Model, PropertyTexture); + switch (propertyTextureView.status()) { + case CesiumGltf::PropertyTextureViewStatus::Valid: + _status = ECesiumPropertyTextureStatus::Valid; + break; + default: + // Status was already set in initializer list. + return; + } + + const CesiumGltf::Class* pClass = propertyTextureView.getClass(); + for (const auto& classPropertyPair : pClass->properties) { + { + const auto& propertyPair = + PropertyTexture.properties.find(classPropertyPair.first); + if (propertyPair == PropertyTexture.properties.end()) { + continue; + } + + CesiumGltf::TextureViewOptions options; + options.applyKhrTextureTransformExtension = true; + + if (propertyPair->second.extras.find("makeImageCopy") != + propertyPair->second.extras.end()) { + options.makeImageCopy = propertyPair->second.extras.at("makeImageCopy") + .getBoolOrDefault(false); + } + + propertyTextureView.getPropertyView( + propertyPair->first, + [&properties = this->_properties]( + const std::string& propertyId, + auto propertyValue) mutable { + FString key(UTF8_TO_TCHAR(propertyId.data())); + properties.Add(key, FCesiumPropertyTextureProperty(propertyValue)); + }, + options); + } + } +} + +/*static*/ const ECesiumPropertyTextureStatus +UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + UPARAM(ref) const FCesiumPropertyTexture& PropertyTexture) { + return PropertyTexture._status; +} + +/*static*/ const FString& +UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureName( + UPARAM(ref) const FCesiumPropertyTexture& PropertyTexture) { + return PropertyTexture._name; +} + +/*static*/ const TMap +UCesiumPropertyTextureBlueprintLibrary::GetProperties( + UPARAM(ref) const FCesiumPropertyTexture& PropertyTexture) { + return PropertyTexture._properties; +} + +/*static*/ const TArray +UCesiumPropertyTextureBlueprintLibrary::GetPropertyNames( + UPARAM(ref) const FCesiumPropertyTexture& PropertyTexture) { + TArray names; + PropertyTexture._properties.GenerateKeyArray(names); + return names; +} + +/*static*/ const FCesiumPropertyTextureProperty& +UCesiumPropertyTextureBlueprintLibrary::FindProperty( + UPARAM(ref) const FCesiumPropertyTexture& PropertyTexture, + const FString& PropertyName) { + const FCesiumPropertyTextureProperty* property = + PropertyTexture._properties.Find(PropertyName); + return property ? *property : EmptyPropertyTextureProperty; +} + +/*static*/ TMap +UCesiumPropertyTextureBlueprintLibrary::GetMetadataValuesForUV( + UPARAM(ref) const FCesiumPropertyTexture& PropertyTexture, + const FVector2D& UV) { + TMap values; + + for (const auto& propertyIt : PropertyTexture._properties) { + const FCesiumPropertyTextureProperty& property = propertyIt.Value; + ECesiumPropertyTexturePropertyStatus status = + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property); + if (status == ECesiumPropertyTexturePropertyStatus::Valid) { + values.Add( + propertyIt.Key, + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValue( + propertyIt.Value, + UV)); + } else if ( + status == + ECesiumPropertyTexturePropertyStatus::EmptyPropertyWithDefault) { + values.Add( + propertyIt.Key, + UCesiumPropertyTexturePropertyBlueprintLibrary::GetDefaultValue( + propertyIt.Value)); + } + } + + return values; +} + +/*static*/ TMap +UCesiumPropertyTextureBlueprintLibrary::GetMetadataValuesFromHit( + UPARAM(ref) const FCesiumPropertyTexture& PropertyTexture, + const FHitResult& Hit) { + TMap values; + + for (const auto& propertyIt : PropertyTexture._properties) { + if (UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(propertyIt.Value) == + ECesiumPropertyTexturePropertyStatus::EmptyPropertyWithDefault) { + values.Add( + propertyIt.Key, + UCesiumPropertyTexturePropertyBlueprintLibrary::GetDefaultValue( + propertyIt.Value)); + continue; + } + + if (UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(propertyIt.Value) != + ECesiumPropertyTexturePropertyStatus::Valid) { + continue; + } + + auto glTFTexCoordIndex = propertyIt.Value.getTexCoordSetIndex(); + FVector2D UV; + if (UCesiumMetadataPickingBlueprintLibrary::FindUVFromHit( + Hit, + glTFTexCoordIndex, + UV)) { + values.Add( + propertyIt.Key, + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValue( + propertyIt.Value, + UV)); + } + } + return values; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyTextureProperty.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyTextureProperty.cpp new file mode 100644 index 0000000..082e2ff --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPropertyTextureProperty.cpp @@ -0,0 +1,855 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyTextureProperty.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "UnrealMetadataConversions.h" + +#include +#include +#include + +namespace { +/** + * Callback on a std::any, assuming that it contains a + * PropertyTexturePropertyView of the specified type. If the type does not + * match, the callback is performed on an invalid PropertyTexturePropertyView + * instead. + * + * @param property The std::any containing the property. + * @param callback The callback function. + * + * @tparam TProperty The property type. + * @tparam Normalized Whether the PropertyTexturePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template < + typename TProperty, + bool Normalized, + typename TResult, + typename Callback> +TResult +propertyTexturePropertyCallback(const std::any& property, Callback&& callback) { + const CesiumGltf::PropertyTexturePropertyView* + pProperty = std::any_cast< + CesiumGltf::PropertyTexturePropertyView>( + &property); + if (pProperty) { + return callback(*pProperty); + } + + return callback(CesiumGltf::PropertyTexturePropertyView()); +} + +/** + * Callback on a std::any, assuming that it contains a + * PropertyTexturePropertyView on a scalar type. If the valueType does not have + * a valid component type, the callback is performed on an invalid + * PropertyTexturePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam Normalized Whether the PropertyTexturePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult scalarPropertyTexturePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.ComponentType) { + case ECesiumMetadataComponentType::Int8: + return propertyTexturePropertyCallback< + int8_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint8: + return propertyTexturePropertyCallback< + uint8_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int16: + return propertyTexturePropertyCallback< + int16_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint16: + return propertyTexturePropertyCallback< + uint16_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int32: + return propertyTexturePropertyCallback< + int32_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint32: + return propertyTexturePropertyCallback< + uint32_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float32: + return propertyTexturePropertyCallback( + property, + std::forward(callback)); + default: + return callback(CesiumGltf::PropertyTexturePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a + * PropertyTexturePropertyView on a scalar array type. If the valueType does not + * have a valid component type, the callback is performed on an invalid + * PropertyTexturePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam Normalized Whether the PropertyTexturePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult scalarArrayPropertyTexturePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.ComponentType) { + case ECesiumMetadataComponentType::Int8: + return propertyTexturePropertyCallback< + CesiumGltf::PropertyArrayView, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint8: + return propertyTexturePropertyCallback< + CesiumGltf::PropertyArrayView, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int16: + return propertyTexturePropertyCallback< + CesiumGltf::PropertyArrayView, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint16: + return propertyTexturePropertyCallback< + CesiumGltf::PropertyArrayView, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + default: + return callback(CesiumGltf::PropertyTexturePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a + * PropertyTexturePropertyView on a glm::vecN type. If the valueType does not + * have a valid component type, the callback is performed on an invalid + * PropertyTexturePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam N The dimensions of the glm::vecN + * @tparam Normalized Whether the PropertyTexturePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult vecNPropertyTexturePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.ComponentType) { + case ECesiumMetadataComponentType::Int8: + return propertyTexturePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint8: + return propertyTexturePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int16: + return propertyTexturePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint16: + return propertyTexturePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + default: + return callback(CesiumGltf::PropertyTexturePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a + * PropertyTexturePropertyView on a glm::vecN type. If the valueType does not + * have a valid component type, the callback is performed on an invalid + * PropertyTexturePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam Normalized Whether the PropertyTexturePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult vecNPropertyTexturePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + if (valueType.Type == ECesiumMetadataType::Vec2) { + return vecNPropertyTexturePropertyCallback< + 2, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + } + + if (valueType.Type == ECesiumMetadataType::Vec3) { + return vecNPropertyTexturePropertyCallback< + 3, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + } + + if (valueType.Type == ECesiumMetadataType::Vec4) { + return vecNPropertyTexturePropertyCallback< + 4, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + } + + return callback(CesiumGltf::PropertyTexturePropertyView()); +} + +template +TResult propertyTexturePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + bool normalized, + Callback&& callback) { + + if (valueType.bIsArray && valueType.Type != ECesiumMetadataType::Scalar) { + + // Only scalar property arrays are supported. + return callback(CesiumGltf::PropertyTexturePropertyView()); + } + + if (valueType.bIsArray) { + return normalized ? scalarArrayPropertyTexturePropertyCallback< + true, + TResult, + Callback>( + property, + valueType, + std::forward(callback)) + : scalarArrayPropertyTexturePropertyCallback< + false, + TResult, + Callback>( + property, + valueType, + std::forward(callback)); + } + + switch (valueType.Type) { + case ECesiumMetadataType::Scalar: + return normalized + ? scalarPropertyTexturePropertyCallback( + property, + valueType, + std::forward(callback)) + : scalarPropertyTexturePropertyCallback< + false, + TResult, + Callback>( + property, + valueType, + std::forward(callback)); + case ECesiumMetadataType::Vec2: + case ECesiumMetadataType::Vec3: + case ECesiumMetadataType::Vec4: + return normalized + ? vecNPropertyTexturePropertyCallback( + property, + valueType, + std::forward(callback)) + : vecNPropertyTexturePropertyCallback( + property, + valueType, + std::forward(callback)); + default: + return callback(CesiumGltf::PropertyTexturePropertyView()); + } +} + +} // namespace + +const int64 FCesiumPropertyTextureProperty::getTexCoordSetIndex() const { + return propertyTexturePropertyCallback( + this->_property, + this->_valueType, + this->_normalized, + [](const auto& view) -> int64 { return view.getTexCoordSetIndex(); }); +} + +const CesiumGltf::Sampler* FCesiumPropertyTextureProperty::getSampler() const { + return propertyTexturePropertyCallback( + this->_property, + this->_valueType, + this->_normalized, + [](const auto& view) -> const CesiumGltf::Sampler* { + return view.getSampler(); + }); +} + +const CesiumGltf::ImageAsset* FCesiumPropertyTextureProperty::getImage() const { + return propertyTexturePropertyCallback( + this->_property, + this->_valueType, + this->_normalized, + [](const auto& view) -> const CesiumGltf::ImageAsset* { + return view.getImage(); + }); +} + +const std::optional +FCesiumPropertyTextureProperty::getTextureTransform() const { + return propertyTexturePropertyCallback< + std::optional>( + this->_property, + this->_valueType, + this->_normalized, + [](const auto& view) -> std::optional { + return view.getTextureTransform(); + }); +} + +ECesiumPropertyTexturePropertyStatus +UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return Property._status; +} + +ECesiumMetadataBlueprintType +UCesiumPropertyTexturePropertyBlueprintLibrary::GetBlueprintType( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return CesiumMetadataValueTypeToBlueprintType(Property._valueType); +} + +ECesiumMetadataBlueprintType +UCesiumPropertyTexturePropertyBlueprintLibrary::GetArrayElementBlueprintType( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + if (!Property._valueType.bIsArray) { + return ECesiumMetadataBlueprintType::None; + } + + FCesiumMetadataValueType valueType(Property._valueType); + valueType.bIsArray = false; + + return CesiumMetadataValueTypeToBlueprintType(valueType); +} + +FCesiumMetadataValueType +UCesiumPropertyTexturePropertyBlueprintLibrary::GetValueType( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return Property._valueType; +} + +int64 UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> int64 { return view.arrayCount(); }); +} + +int64 UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetGltfTextureCoordinateSetIndex( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return Property.getTexCoordSetIndex(); +} + +int64 UCesiumPropertyTexturePropertyBlueprintLibrary::GetUnrealUVChannel( + const UPrimitiveComponent* Component, + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + const UCesiumGltfPrimitiveComponent* pPrimitive = + Cast(Component); + if (!pPrimitive) { + return -1; + } + + int64_t texCoordSetIndex = UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetGltfTextureCoordinateSetIndex(Property); + const CesiumPrimitiveData& primData = pPrimitive->getPrimitiveData(); + auto textureCoordinateIndexIt = + primData.GltfToUnrealTexCoordMap.find(texCoordSetIndex); + if (textureCoordinateIndexIt == primData.GltfToUnrealTexCoordMap.end()) { + return -1; + } + + return textureCoordinateIndexIt->second; +} + +PRAGMA_DISABLE_DEPRECATION_WARNINGS +FString UCesiumPropertyTexturePropertyBlueprintLibrary::GetSwizzle( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + const std::string swizzle = + propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) { return view.getSwizzle(); }); + return UTF8_TO_TCHAR(swizzle.c_str()); +} + +int64 UCesiumPropertyTexturePropertyBlueprintLibrary::GetComponentCount( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) { + return static_cast(view.getChannels().size()); + }); +} +PRAGMA_ENABLE_DEPRECATION_WARNINGS + +TArray UCesiumPropertyTexturePropertyBlueprintLibrary::GetChannels( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return propertyTexturePropertyCallback>( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> TArray { + const std::vector& channels = view.getChannels(); + TArray result; + result.Reserve(static_cast(channels.size())); + for (size_t i = 0; i < channels.size(); i++) { + result.Emplace(channels[i]); + } + + return result; + }); +} + +uint8 UCesiumPropertyTexturePropertyBlueprintLibrary::GetByte( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + uint8 DefaultValue) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV, DefaultValue](const auto& view) -> uint8 { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { + return DefaultValue; + } + auto maybeValue = view.get(UV.X, UV.Y); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +int32 UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + int32 DefaultValue) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV, DefaultValue](const auto& view) -> int32 { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { + return DefaultValue; + } + auto maybeValue = view.get(UV.X, UV.Y); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +float UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + float DefaultValue) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV, DefaultValue](const auto& view) -> float { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { + return DefaultValue; + } + auto maybeValue = view.get(UV.X, UV.Y); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +double UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat64( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + double DefaultValue) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV, DefaultValue](const auto& view) -> double { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { + return DefaultValue; + } + auto maybeValue = view.get(UV.X, UV.Y); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +FIntPoint UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntPoint( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + const FIntPoint& DefaultValue) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV, &DefaultValue](const auto& view) -> FIntPoint { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { + return DefaultValue; + } + auto maybeValue = view.get(UV.X, UV.Y); + if (!maybeValue) { + return DefaultValue; + } + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toIntPoint( + *maybeValue, + DefaultValue); + } else { + auto maybeVec2 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec2 ? UnrealMetadataConversions::toIntPoint(*maybeVec2) + : DefaultValue; + } + }); +} + +FVector2D UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector2D( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + const FVector2D& DefaultValue) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV, &DefaultValue](const auto& view) -> FVector2D { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { + return DefaultValue; + } + auto maybeValue = view.get(UV.X, UV.Y); + if (!maybeValue) { + return DefaultValue; + } + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector2D(value, DefaultValue); + } else { + auto maybeVec2 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec2 ? UnrealMetadataConversions::toVector2D(*maybeVec2) + : DefaultValue; + } + }); +} + +FIntVector UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntVector( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + const FIntVector& DefaultValue) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV, &DefaultValue](const auto& view) -> FIntVector { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { + return DefaultValue; + } + auto maybeValue = view.get(UV.X, UV.Y); + if (!maybeValue) { + return DefaultValue; + } + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toIntVector(value, DefaultValue); + } else { + auto maybeVec3 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec3 ? UnrealMetadataConversions::toIntVector(*maybeVec3) + : DefaultValue; + } + }); +} + +FVector UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + const FVector& DefaultValue) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV, &DefaultValue](const auto& view) -> FVector { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { + return DefaultValue; + } + auto maybeValue = view.get(UV.X, UV.Y); + if (!maybeValue) { + return DefaultValue; + } + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector(value, DefaultValue); + } else { + auto maybeVec3 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec3 ? UnrealMetadataConversions::toVector(*maybeVec3) + : DefaultValue; + } + }); +} + +FVector4 UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector4( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + const FVector4& DefaultValue) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV, &DefaultValue](const auto& view) -> FVector4 { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { + return DefaultValue; + } + auto maybeValue = view.get(UV.X, UV.Y); + if (!maybeValue) { + return DefaultValue; + } + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector(value, DefaultValue); + } else { + auto maybeVec4 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec4 ? UnrealMetadataConversions::toVector4(*maybeVec4) + : DefaultValue; + } + }); +} + +FCesiumPropertyArray UCesiumPropertyTexturePropertyBlueprintLibrary::GetArray( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV](const auto& view) -> FCesiumPropertyArray { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { + return FCesiumPropertyArray(); + } + auto maybeValue = view.get(UV.X, UV.Y); + if (maybeValue) { + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataArray::value) { + return FCesiumPropertyArray(value); + } + } + return FCesiumPropertyArray(); + }); +} + +FCesiumMetadataValue UCesiumPropertyTexturePropertyBlueprintLibrary::GetValue( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV](const auto& view) -> FCesiumMetadataValue { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid && + view.status() != CesiumGltf::PropertyTexturePropertyViewStatus:: + EmptyPropertyWithDefault) { + return FCesiumMetadataValue(); + } + + return FCesiumMetadataValue(view.get(UV.X, UV.Y)); + }); +} + +FCesiumMetadataValue +UCesiumPropertyTexturePropertyBlueprintLibrary::GetRawValue( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV](const auto& view) -> FCesiumMetadataValue { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { + return FCesiumMetadataValue(); + } + + return FCesiumMetadataValue(view.getRaw(UV.X, UV.Y)); + }); +} + +bool UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return Property._normalized; +} + +FCesiumMetadataValue UCesiumPropertyTexturePropertyBlueprintLibrary::GetOffset( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no offset is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.offset())); + }); +} + +FCesiumMetadataValue UCesiumPropertyTexturePropertyBlueprintLibrary::GetScale( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no scale is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.scale())); + }); +} + +FCesiumMetadataValue +UCesiumPropertyTexturePropertyBlueprintLibrary::GetMinimumValue( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no min is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.min())); + }); +} + +FCesiumMetadataValue +UCesiumPropertyTexturePropertyBlueprintLibrary::GetMaximumValue( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no max is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.max())); + }); +} + +FCesiumMetadataValue +UCesiumPropertyTexturePropertyBlueprintLibrary::GetNoDataValue( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no "no data" value is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.noData())); + }); +} + +FCesiumMetadataValue +UCesiumPropertyTexturePropertyBlueprintLibrary::GetDefaultValue( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no default value is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.defaultValue())); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRasterOverlay.cpp new file mode 100644 index 0000000..1df30d0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRasterOverlay.cpp @@ -0,0 +1,215 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumRasterOverlay.h" +#include "Async/Async.h" +#include "Cesium3DTilesSelection/Tileset.h" +#include "Cesium3DTileset.h" +#include "CesiumAsync/IAssetResponse.h" +#include "CesiumRasterOverlays/RasterOverlayLoadFailureDetails.h" +#include "CesiumRuntime.h" + +FCesiumRasterOverlayLoadFailure OnCesiumRasterOverlayLoadFailure{}; + +// Sets default values for this component's properties +UCesiumRasterOverlay::UCesiumRasterOverlay() + : _pOverlay(nullptr), _overlaysBeingDestroyed(0) { + this->bAutoActivate = true; + + // Set this component to be initialized when the game starts, and to be ticked + // every frame. You can turn these features off to improve performance if you + // don't need them. + PrimaryComponentTick.bCanEverTick = false; + + // Allow DestroyComponent to be called from Blueprints by anyone. Without + // this, only the Actor (Cesium3DTileset) itself can destroy raster overlays. + // That's really annoying because it's fairly common to dynamically add/remove + // overlays at runtime. + bAllowAnyoneToDestroyMe = true; +} + +#if WITH_EDITOR +// Called when properties are changed in the editor +void UCesiumRasterOverlay::PostEditChangeProperty( + FPropertyChangedEvent& PropertyChangedEvent) { + Super::PostEditChangeProperty(PropertyChangedEvent); + + this->Refresh(); +} +#endif + +void UCesiumRasterOverlay::AddToTileset() { + if (this->_pOverlay) { + return; + } + + Cesium3DTilesSelection::Tileset* pTileset = FindTileset(); + if (!pTileset) { + return; + } + + CesiumRasterOverlays::RasterOverlayOptions options{}; + options.ellipsoid = pTileset->getOptions().ellipsoid; + options.maximumScreenSpaceError = this->MaximumScreenSpaceError; + options.maximumSimultaneousTileLoads = this->MaximumSimultaneousTileLoads; + options.maximumTextureSize = this->MaximumTextureSize; + options.subTileCacheBytes = this->SubTileCacheBytes; + options.showCreditsOnScreen = this->ShowCreditsOnScreen; + options.rendererOptions = &this->rendererOptions; + options.loadErrorCallback = + [this](const CesiumRasterOverlays::RasterOverlayLoadFailureDetails& + details) { + static_assert( + uint8_t(ECesiumRasterOverlayLoadType::CesiumIon) == + uint8_t(CesiumRasterOverlays::RasterOverlayLoadType::CesiumIon)); + static_assert( + uint8_t(ECesiumRasterOverlayLoadType::TileProvider) == + uint8_t(CesiumRasterOverlays::RasterOverlayLoadType::TileProvider)); + static_assert( + uint8_t(ECesiumRasterOverlayLoadType::Unknown) == + uint8_t(CesiumRasterOverlays::RasterOverlayLoadType::Unknown)); + + uint8_t typeValue = uint8_t(details.type); + assert( + uint8_t(details.type) <= + uint8_t( + Cesium3DTilesSelection::RasterOverlayLoadType::TilesetJson)); + assert(this->_pTileset == details.pTileset); + + FCesiumRasterOverlayLoadFailureDetails ueDetails{}; + ueDetails.Overlay = this; + ueDetails.Type = ECesiumRasterOverlayLoadType(typeValue); + ueDetails.HttpStatusCode = + details.pRequest && details.pRequest->response() + ? details.pRequest->response()->statusCode() + : 0; + ueDetails.Message = UTF8_TO_TCHAR(details.message.c_str()); + + // Broadcast the event from the game thread. + // Even if we're already in the game thread, let the stack unwind. + // Otherwise actions that destroy the Tileset will cause a deadlock. + AsyncTask( + ENamedThreads::GameThread, + [ueDetails = std::move(ueDetails)]() { + OnCesiumRasterOverlayLoadFailure.Broadcast(ueDetails); + }); + }; + + std::unique_ptr pOverlay = + this->CreateOverlay(options); + + if (pOverlay) { + this->_pOverlay = pOverlay.release(); + + pTileset->getOverlays().add(this->_pOverlay); + + this->OnAdd(pTileset, this->_pOverlay); + } +} + +void UCesiumRasterOverlay::RemoveFromTileset() { + if (!this->_pOverlay) { + return; + } + + Cesium3DTilesSelection::Tileset* pTileset = FindTileset(); + if (!pTileset) { + return; + } + + // Don't allow this RasterOverlay to be fully destroyed until + // any cesium-native RasterOverlays it created have wrapped up any async + // operations in progress and have been fully destroyed. + // See IsReadyForFinishDestroy. + ++this->_overlaysBeingDestroyed; + this->_pOverlay->getAsyncDestructionCompleteEvent(getAsyncSystem()) + .thenInMainThread([this]() { --this->_overlaysBeingDestroyed; }); + + this->OnRemove(pTileset, this->_pOverlay); + pTileset->getOverlays().remove(this->_pOverlay); + this->_pOverlay = nullptr; +} + +void UCesiumRasterOverlay::Refresh() { + this->RemoveFromTileset(); + if (this->IsActive()) { + this->AddToTileset(); + } +} + +double UCesiumRasterOverlay::GetMaximumScreenSpaceError() const { + return this->MaximumScreenSpaceError; +} + +void UCesiumRasterOverlay::SetMaximumScreenSpaceError(double Value) { + this->MaximumScreenSpaceError = Value; + this->Refresh(); +} + +int32 UCesiumRasterOverlay::GetMaximumTextureSize() const { + return this->MaximumTextureSize; +} + +void UCesiumRasterOverlay::SetMaximumTextureSize(int32 Value) { + this->MaximumTextureSize = Value; + this->Refresh(); +} + +int32 UCesiumRasterOverlay::GetMaximumSimultaneousTileLoads() const { + return this->MaximumSimultaneousTileLoads; +} + +void UCesiumRasterOverlay::SetMaximumSimultaneousTileLoads(int32 Value) { + this->MaximumSimultaneousTileLoads = Value; + + if (this->_pOverlay) { + this->_pOverlay->getOptions().maximumSimultaneousTileLoads = Value; + } +} + +int64 UCesiumRasterOverlay::GetSubTileCacheBytes() const { + return this->SubTileCacheBytes; +} + +void UCesiumRasterOverlay::SetSubTileCacheBytes(int64 Value) { + this->SubTileCacheBytes = Value; + + if (this->_pOverlay) { + this->_pOverlay->getOptions().subTileCacheBytes = Value; + } +} + +void UCesiumRasterOverlay::Activate(bool bReset) { + Super::Activate(bReset); + this->AddToTileset(); +} + +void UCesiumRasterOverlay::Deactivate() { + Super::Deactivate(); + this->RemoveFromTileset(); +} + +void UCesiumRasterOverlay::OnComponentDestroyed(bool bDestroyingHierarchy) { + this->RemoveFromTileset(); + Super::OnComponentDestroyed(bDestroyingHierarchy); +} + +bool UCesiumRasterOverlay::IsReadyForFinishDestroy() { + bool ready = Super::IsReadyForFinishDestroy(); + ready &= this->_overlaysBeingDestroyed == 0; + + if (!ready) { + getAssetAccessor()->tick(); + getAsyncSystem().dispatchMainThreadTasks(); + } + + return ready; +} + +Cesium3DTilesSelection::Tileset* UCesiumRasterOverlay::FindTileset() const { + ACesium3DTileset* pActor = this->GetOwner(); + if (!pActor) { + return nullptr; + } + + return pActor->GetTileset(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRasterOverlays.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRasterOverlays.h new file mode 100644 index 0000000..545e24a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRasterOverlays.h @@ -0,0 +1,12 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +constexpr size_t maximumOverlayTextureCoordinateIDs = 2; + +/** + * @brief Maps an overlay texture coordinate ID to the index of the + * corresponding texture coordinates in the static mesh's UVs array. + */ +using OverlayTextureCoordinateIDMap = + std::array; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRuntime.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRuntime.cpp new file mode 100644 index 0000000..e51e4b8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRuntime.cpp @@ -0,0 +1,127 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumRuntime.h" +#include "Cesium3DTilesContent/registerAllTileContentTypes.h" +#include "CesiumAsync/CachingAssetAccessor.h" +#include "CesiumAsync/GunzipAssetAccessor.h" +#include "CesiumAsync/SqliteCache.h" +#include "CesiumRuntimeSettings.h" +#include "CesiumUtility/Tracing.h" +#include "HAL/FileManager.h" +#include "HttpModule.h" +#include "Interfaces/IPluginManager.h" +#include "Misc/Paths.h" +#include "ShaderCore.h" +#include "SpdlogUnrealLoggerSink.h" +#include "UnrealAssetAccessor.h" +#include "UnrealTaskProcessor.h" +#include +#include +#include +#include + +#if CESIUM_TRACING_ENABLED +#include +#endif + +#define LOCTEXT_NAMESPACE "FCesiumRuntimeModule" + +DEFINE_LOG_CATEGORY(LogCesium); + +void FCesiumRuntimeModule::StartupModule() { + Cesium3DTilesContent::registerAllTileContentTypes(); + + std::shared_ptr pLogger = spdlog::default_logger(); + pLogger->sinks() = {std::make_shared()}; + + FModuleManager::Get().LoadModuleChecked(TEXT("HTTP")); + + CESIUM_TRACE_INIT( + "cesium-trace-" + + std::to_string(std::chrono::time_point_cast( + std::chrono::steady_clock::now()) + .time_since_epoch() + .count()) + + ".json"); + + FString PluginShaderDir = FPaths::Combine( + IPluginManager::Get().FindPlugin(TEXT("CesiumForUnreal"))->GetBaseDir(), + TEXT("Shaders")); + AddShaderSourceDirectoryMapping( + TEXT("/Plugin/CesiumForUnreal"), + PluginShaderDir); +} + +void FCesiumRuntimeModule::ShutdownModule() { CESIUM_TRACE_SHUTDOWN(); } + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FCesiumRuntimeModule, CesiumRuntime) + +FCesium3DTilesetIonTroubleshooting OnCesium3DTilesetIonTroubleshooting{}; +FCesiumRasterOverlayIonTroubleshooting + OnCesiumRasterOverlayIonTroubleshooting{}; + +CesiumAsync::AsyncSystem& getAsyncSystem() noexcept { + static CesiumAsync::AsyncSystem asyncSystem( + std::make_shared()); + return asyncSystem; +} + +namespace { + +std::string getCacheDatabaseName() { +#if PLATFORM_ANDROID + FString BaseDirectory = FPaths::ProjectPersistentDownloadDir(); +#elif PLATFORM_IOS + FString BaseDirectory = + FPaths::Combine(*FPaths::ProjectSavedDir(), TEXT("Cesium")); + if (!IFileManager::Get().DirectoryExists(*BaseDirectory)) { + IFileManager::Get().MakeDirectory(*BaseDirectory, true); + } +#else + FString BaseDirectory = FPaths::EngineUserDir(); +#endif + + FString CesiumDBFile = + FPaths::Combine(*BaseDirectory, TEXT("cesium-request-cache.sqlite")); + FString PlatformAbsolutePath = + IFileManager::Get().ConvertToAbsolutePathForExternalAppForWrite( + *CesiumDBFile); + + UE_LOG( + LogCesium, + Display, + TEXT("Caching Cesium requests in %s"), + *PlatformAbsolutePath); + + return TCHAR_TO_UTF8(*PlatformAbsolutePath); +} + +} // namespace + +std::shared_ptr& getCacheDatabase() { + static int MaxCacheItems = + GetDefault()->MaxCacheItems; + + static std::shared_ptr pCacheDatabase = + std::make_shared( + spdlog::default_logger(), + getCacheDatabaseName(), + MaxCacheItems); + + return pCacheDatabase; +} + +const std::shared_ptr& getAssetAccessor() { + static int RequestsPerCachePrune = + GetDefault()->RequestsPerCachePrune; + static std::shared_ptr pAssetAccessor = + std::make_shared( + std::make_shared( + spdlog::default_logger(), + std::make_shared(), + getCacheDatabase(), + RequestsPerCachePrune)); + return pAssetAccessor; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRuntimeSettings.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRuntimeSettings.cpp new file mode 100644 index 0000000..9fce0eb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRuntimeSettings.cpp @@ -0,0 +1,9 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumRuntimeSettings.h" + +UCesiumRuntimeSettings::UCesiumRuntimeSettings( + const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) { + CategoryName = FName(TEXT("Plugins")); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSampleHeightMostDetailedAsyncAction.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSampleHeightMostDetailedAsyncAction.cpp new file mode 100644 index 0000000..24d0619 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSampleHeightMostDetailedAsyncAction.cpp @@ -0,0 +1,34 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors +#include "CesiumSampleHeightMostDetailedAsyncAction.h" +#include "Cesium3DTileset.h" +#include "CesiumRuntime.h" + +/*static*/ UCesiumSampleHeightMostDetailedAsyncAction* +UCesiumSampleHeightMostDetailedAsyncAction::SampleHeightMostDetailed( + ACesium3DTileset* Tileset, + const TArray& LongitudeLatitudeHeightArray) { + UCesiumSampleHeightMostDetailedAsyncAction* pAsyncAction = + NewObject(); + pAsyncAction->_pTileset = Tileset; + pAsyncAction->_longitudeLatitudeHeightArray = LongitudeLatitudeHeightArray; + + return pAsyncAction; +} + +void UCesiumSampleHeightMostDetailedAsyncAction::Activate() { + this->RegisterWithGameInstance(this->_pTileset); + + this->_pTileset->SampleHeightMostDetailed( + this->_longitudeLatitudeHeightArray, + FCesiumSampleHeightMostDetailedCallback::CreateUObject( + this, + &UCesiumSampleHeightMostDetailedAsyncAction::RaiseOnHeightsSampled)); +} + +void UCesiumSampleHeightMostDetailedAsyncAction::RaiseOnHeightsSampled( + ACesium3DTileset* Tileset, + const TArray& Result, + const TArray& Warnings) { + this->OnHeightsSampled.Broadcast(Result, Warnings); + this->SetReadyToDestroy(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSubLevelComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSubLevelComponent.cpp new file mode 100644 index 0000000..3831d70 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSubLevelComponent.cpp @@ -0,0 +1,582 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumSubLevelComponent.h" +#include "Cesium3DTileset.h" +#include "CesiumActors.h" +#include "CesiumGeoreference.h" +#include "CesiumGeospatial/LocalHorizontalCoordinateSystem.h" +#include "CesiumRuntime.h" +#include "CesiumSubLevelSwitcherComponent.h" +#include "CesiumUtility/Math.h" +#include "EngineUtils.h" +#include "LevelInstance/LevelInstanceActor.h" +#include "VecMath.h" +#include + +#if WITH_EDITOR +#include "EditorViewportClient.h" +#include "LevelInstance/LevelInstanceLevelStreaming.h" +#include "ScopedTransaction.h" +#endif + +using namespace CesiumGeospatial; + +bool UCesiumSubLevelComponent::GetEnabled() const { return this->Enabled; } + +void UCesiumSubLevelComponent::SetEnabled(bool value) { this->Enabled = value; } + +double UCesiumSubLevelComponent::GetOriginLongitude() const { + return this->OriginLongitude; +} + +void UCesiumSubLevelComponent::SetOriginLongitude(double value) { + this->OriginLongitude = value; + this->UpdateGeoreferenceIfSubLevelIsActive(); +} + +double UCesiumSubLevelComponent::GetOriginLatitude() const { + return this->OriginLatitude; +} + +void UCesiumSubLevelComponent::SetOriginLatitude(double value) { + this->OriginLatitude = value; + this->UpdateGeoreferenceIfSubLevelIsActive(); +} + +double UCesiumSubLevelComponent::GetOriginHeight() const { + return this->OriginHeight; +} + +void UCesiumSubLevelComponent::SetOriginHeight(double value) { + this->OriginHeight = value; + this->UpdateGeoreferenceIfSubLevelIsActive(); +} + +double UCesiumSubLevelComponent::GetLoadRadius() const { + return this->LoadRadius; +} + +void UCesiumSubLevelComponent::SetLoadRadius(double value) { + this->LoadRadius = value; +} + +TSoftObjectPtr +UCesiumSubLevelComponent::GetGeoreference() const { + return this->Georeference; +} + +void UCesiumSubLevelComponent::SetGeoreference( + TSoftObjectPtr NewGeoreference) { + this->Georeference = NewGeoreference; + this->_invalidateResolvedGeoreference(); + + ALevelInstance* pOwner = this->_getLevelInstance(); + if (pOwner) { + this->ResolveGeoreference(); + + UCesiumSubLevelSwitcherComponent* pSwitcher = this->_getSwitcher(); + pSwitcher->RegisterSubLevel(pOwner); + } +} + +ACesiumGeoreference* UCesiumSubLevelComponent::GetResolvedGeoreference() const { + return this->ResolvedGeoreference; +} + +ACesiumGeoreference* +UCesiumSubLevelComponent::ResolveGeoreference(bool bForceReresolve) { + if (IsValid(this->ResolvedGeoreference) && !bForceReresolve) { + return this->ResolvedGeoreference; + } + + ACesiumGeoreference* Previous = this->ResolvedGeoreference; + ACesiumGeoreference* Next = nullptr; + + if (IsValid(this->Georeference.Get())) { + Next = this->Georeference.Get(); + } else { + Next = + ACesiumGeoreference::GetDefaultGeoreferenceForActor(this->GetOwner()); + } + + if (Previous != Next) { + this->_invalidateResolvedGeoreference(); + } + + this->ResolvedGeoreference = Next; + return this->ResolvedGeoreference; +} + +void UCesiumSubLevelComponent::SetOriginLongitudeLatitudeHeight( + const FVector& longitudeLatitudeHeight) { + if (this->OriginLongitude != longitudeLatitudeHeight.X || + this->OriginLatitude != longitudeLatitudeHeight.Y || + this->OriginHeight != longitudeLatitudeHeight.Z) { + this->OriginLongitude = longitudeLatitudeHeight.X; + this->OriginLatitude = longitudeLatitudeHeight.Y; + this->OriginHeight = longitudeLatitudeHeight.Z; + this->UpdateGeoreferenceIfSubLevelIsActive(); + } +} + +#if WITH_EDITOR + +namespace { + +ULevelStreaming* getLevelStreamingForSubLevel(ALevelInstance* SubLevel) { + if (!IsValid(SubLevel)) + return nullptr; + + ULevelStreaming* const* ppStreaming = + SubLevel->GetWorld()->GetStreamingLevels().FindByPredicate( + [SubLevel](ULevelStreaming* pStreaming) { + ULevelStreamingLevelInstance* pInstanceStreaming = + Cast(pStreaming); + if (!pInstanceStreaming) + return false; + + return pInstanceStreaming->GetLevelInstance() == SubLevel; + }); + + return ppStreaming ? *ppStreaming : nullptr; +} + +} // namespace + +void UCesiumSubLevelComponent::PlaceGeoreferenceOriginAtSubLevelOrigin() { + ACesiumGeoreference* pGeoreference = this->ResolveGeoreference(); + if (!IsValid(pGeoreference)) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Cannot place the origin because the sub-level does not have a CesiumGeoreference.")); + return; + } + + ALevelInstance* pOwner = this->_getLevelInstance(); + if (!IsValid(pOwner)) { + return; + } + + USceneComponent* Root = pOwner->GetRootComponent(); + if (!IsValid(Root)) { + return; + } + + FVector UnrealPosition = + pGeoreference->GetActorTransform().InverseTransformPosition( + pOwner->GetActorLocation()); + + FVector NewOriginEcef = + pGeoreference->TransformUnrealPositionToEarthCenteredEarthFixed( + UnrealPosition); + this->PlaceOriginAtEcef(NewOriginEcef); +} + +void UCesiumSubLevelComponent::PlaceGeoreferenceOriginHere() { + ACesiumGeoreference* pGeoreference = this->ResolveGeoreference(); + if (!IsValid(pGeoreference)) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Cannot place the origin because the sub-level does not have a CesiumGeoreference.")); + return; + } + + FViewport* pViewport = GEditor->GetActiveViewport(); + if (!pViewport) + return; + + FViewportClient* pViewportClient = pViewport->GetClient(); + if (!pViewportClient) + return; + + FEditorViewportClient* pEditorViewportClient = + static_cast(pViewportClient); + + FVector ViewLocation = pEditorViewportClient->GetViewLocation(); + + // Transform the world-space view location to the CesiumGeoreference's frame. + ViewLocation = + pGeoreference->GetActorTransform().InverseTransformPosition(ViewLocation); + + FVector CameraEcefPosition = + pGeoreference->TransformUnrealPositionToEarthCenteredEarthFixed( + ViewLocation); + this->PlaceOriginAtEcef(CameraEcefPosition); +} + +void UCesiumSubLevelComponent::PlaceOriginAtEcef(const FVector& NewOriginEcef) { + ACesiumGeoreference* pGeoreference = this->ResolveGeoreference(); + if (!IsValid(pGeoreference)) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Cannot place the origin because the sub-level does not have a CesiumGeoreference.")); + return; + } + + ALevelInstance* pOwner = this->_getLevelInstance(); + if (!IsValid(pOwner)) { + return; + } + + if (pOwner->IsEditing()) { + UE_LOG( + LogCesium, + Error, + TEXT( + "The georeference origin cannot be moved while the sub-level is being edited.")); + return; + } + + UCesiumEllipsoid* pEllipsoid = pGeoreference->GetEllipsoid(); + check(IsValid(pEllipsoid)); + + const Ellipsoid& pNativeEllipsoid = pEllipsoid->GetNativeEllipsoid(); + + // Another sub-level might be active right now, so we construct the correct + // GeoTransforms instead of using the CesiumGeoreference's. + FVector CurrentOriginEcef = + pEllipsoid->LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + FVector( + this->OriginLongitude, + this->OriginLatitude, + this->OriginHeight)); + GeoTransforms CurrentTransforms( + pNativeEllipsoid, + VecMath::createVector3D(CurrentOriginEcef), + pGeoreference->GetScale() / 100.0); + + // Construct new geotransforms at the new origin + GeoTransforms NewTransforms( + pNativeEllipsoid, + VecMath::createVector3D(NewOriginEcef), + pGeoreference->GetScale() / 100.0); + + // Transform the level instance from the old origin to the new one. + glm::dmat4 OldToEcef = + CurrentTransforms.GetAbsoluteUnrealWorldToEllipsoidCenteredTransform(); + glm::dmat4 EcefToNew = + NewTransforms.GetEllipsoidCenteredToAbsoluteUnrealWorldTransform(); + glm::dmat4 OldToNew = EcefToNew * OldToEcef; + glm::dmat4 OldTransform = + VecMath::createMatrix4D(pOwner->GetActorTransform().ToMatrixWithScale()); + glm::dmat4 NewLevelTransform = OldToNew * OldTransform; + + FScopedTransaction transaction(FText::FromString("Place Origin At Location")); + + ULevelStreaming* LevelStreaming = getLevelStreamingForSubLevel(pOwner); + ULevel* Level = + IsValid(LevelStreaming) ? LevelStreaming->GetLoadedLevel() : nullptr; + + bool bHasTilesets = Level && IsValid(Level) && + Level->Actors.FindByPredicate([](AActor* Actor) { + return Cast(Actor) != nullptr; + }) != nullptr; + + FTransform OldLevelTransform; + if (bHasTilesets) { + OldLevelTransform = LevelStreaming->LevelTransform; + } + + pOwner->Modify(); + pOwner->SetActorTransform( + FTransform(VecMath::createMatrix(NewLevelTransform))); + + // Set the new sub-level georeference origin. + this->Modify(); + this->SetOriginLongitudeLatitudeHeight( + pEllipsoid->EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight( + NewOriginEcef)); + + // Also update the viewport so the level doesn't appear to shift. + FViewport* pViewport = GEditor->GetActiveViewport(); + FViewportClient* pViewportClient = pViewport->GetClient(); + FEditorViewportClient* pEditorViewportClient = + static_cast(pViewportClient); + + glm::dvec3 ViewLocation = + VecMath::createVector3D(pEditorViewportClient->GetViewLocation()); + ViewLocation = glm::dvec3(OldToNew * glm::dvec4(ViewLocation, 1.0)); + pEditorViewportClient->SetViewLocation(VecMath::createVector(ViewLocation)); + + glm::dmat4 ViewportRotation = VecMath::createMatrix4D( + pEditorViewportClient->GetViewRotation().Quaternion().ToMatrix()); + ViewportRotation = OldToNew * ViewportRotation; + + // At this point, viewportRotation will keep the viewport orientation in ECEF + // exactly as it was before. But that means if it was tilted before, it will + // still be tilted. We instead want an orientation that maintains the exact + // same forward direction but has an "up" direction aligned with +Z. + glm::dvec3 CameraFront = glm::normalize(glm::dvec3(ViewportRotation[0])); + glm::dvec3 CameraRight = + glm::normalize(glm::cross(glm::dvec3(0.0, 0.0, 1.0), CameraFront)); + glm::dvec3 CameraUp = glm::normalize(glm::cross(CameraFront, CameraRight)); + + pEditorViewportClient->SetViewRotation( + FMatrix( + FVector(CameraFront.x, CameraFront.y, CameraFront.z), + FVector(CameraRight.x, CameraRight.y, CameraRight.z), + FVector(CameraUp.x, CameraUp.y, CameraUp.z), + FVector::ZeroVector) + .Rotator()); + + // Restore the previous tileset transforms. We'll enter Edit mode of the + // sub-level, make the modifications, and let the user choose whether to + // commit them. + if (bHasTilesets) { + pOwner->EnterEdit(); + Level = pOwner->GetLoadedLevel(); + for (AActor* Actor : Level->Actors) { + ACesium3DTileset* Tileset = Cast(Actor); + if (!IsValid(Tileset)) + continue; + + USceneComponent* Root = Tileset->GetRootComponent(); + if (!IsValid(Root)) + continue; + + // Change of basis of the old tileset relative transform to the new + // coordinate system. + glm::dmat4 NewToEcef = + NewTransforms.GetAbsoluteUnrealWorldToEllipsoidCenteredTransform(); + glm::dmat4 oldRelativeTransform = VecMath::createMatrix4D( + (Root->GetRelativeTransform() * OldLevelTransform) + .ToMatrixWithScale()); + glm::dmat4 NewToOld = glm::affineInverse(OldToNew); + glm::dmat4 RelativeTransformInNew = + glm::affineInverse(NewLevelTransform) * OldToNew * + oldRelativeTransform * NewToOld; + + Tileset->Modify(); + Root->Modify(); + Root->SetRelativeTransform( + FTransform(VecMath::createMatrix(RelativeTransformInNew)), + false, + nullptr, + ETeleportType::TeleportPhysics); + } + } +} + +#endif // #if WITH_EDITOR + +void UCesiumSubLevelComponent::UpdateGeoreferenceIfSubLevelIsActive() { + ALevelInstance* pOwner = this->_getLevelInstance(); + if (!pOwner) { + return; + } + + if (!IsValid(this->ResolvedGeoreference)) { + // This sub-level is not associated with a georeference yet. + return; + } + + UCesiumSubLevelSwitcherComponent* pSwitcher = this->_getSwitcher(); + if (!pSwitcher) + return; + + ALevelInstance* pCurrent = pSwitcher->GetCurrentSubLevel(); + ALevelInstance* pTarget = pSwitcher->GetTargetSubLevel(); + + // This sub-level's origin is active if it is the current level or if it's the + // target level and there is no current level. + if (pCurrent == pOwner || (pCurrent == nullptr && pTarget == pOwner)) { + // Apply the sub-level's origin to the georeference, if it's different. + if (this->OriginLongitude != + this->ResolvedGeoreference->GetOriginLongitude() || + this->OriginLatitude != + this->ResolvedGeoreference->GetOriginLatitude() || + this->OriginHeight != this->ResolvedGeoreference->GetOriginHeight()) { + this->ResolvedGeoreference->SetOriginLongitudeLatitudeHeight(FVector( + this->OriginLongitude, + this->OriginLatitude, + this->OriginHeight)); + } + } +} + +void UCesiumSubLevelComponent::BeginDestroy() { + this->_invalidateResolvedGeoreference(); + Super::BeginDestroy(); +} + +void UCesiumSubLevelComponent::OnComponentCreated() { + Super::OnComponentCreated(); + + this->ResolveGeoreference(); + + UCesiumSubLevelSwitcherComponent* pSwitcher = this->_getSwitcher(); + if (pSwitcher && this->ResolvedGeoreference) { + this->OriginLongitude = this->ResolvedGeoreference->GetOriginLongitude(); + this->OriginLatitude = this->ResolvedGeoreference->GetOriginLatitude(); + this->OriginHeight = this->ResolvedGeoreference->GetOriginHeight(); + + // In Editor worlds, make the newly-created sub-level the active one. Unless + // it's already hidden. +#if WITH_EDITOR + if (GEditor && IsValid(this->GetWorld()) && + !this->GetWorld()->IsGameWorld()) { + ALevelInstance* pOwner = Cast(this->GetOwner()); + if (IsValid(pOwner) && !pOwner->IsTemporarilyHiddenInEditor(true)) { + pSwitcher->SetTargetSubLevel(pOwner); + } + } +#endif + } +} + +#if WITH_EDITOR + +void UCesiumSubLevelComponent::PostEditChangeProperty( + FPropertyChangedEvent& PropertyChangedEvent) { + Super::PostEditChangeProperty(PropertyChangedEvent); + + if (!PropertyChangedEvent.Property) { + return; + } + + FName propertyName = PropertyChangedEvent.Property->GetFName(); + + if (propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumSubLevelComponent, OriginLongitude) || + propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumSubLevelComponent, OriginLatitude) || + propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumSubLevelComponent, OriginHeight)) { + this->UpdateGeoreferenceIfSubLevelIsActive(); + } +} + +#endif + +void UCesiumSubLevelComponent::BeginPlay() { + Super::BeginPlay(); + + this->ResolveGeoreference(); + + UCesiumSubLevelSwitcherComponent* pSwitcher = this->_getSwitcher(); + if (!pSwitcher) + return; + + ALevelInstance* pLevel = this->_getLevelInstance(); + if (!pLevel) + return; + + pSwitcher->RegisterSubLevel(pLevel); +} + +void UCesiumSubLevelComponent::OnRegister() { + Super::OnRegister(); + + // We set this to true here so that the CesiumEditorSubLevelMutex in the + // CesiumEditor module is invoked for this component when the + // ALevelInstance's visibility is toggled in the Editor. + bRenderStateCreated = true; + + ALevelInstance* pOwner = this->_getLevelInstance(); + if (!pOwner) { + return; + } + +#if WITH_EDITOR + if (pOwner->GetIsSpatiallyLoaded() || + pOwner->DesiredRuntimeBehavior != + ELevelInstanceRuntimeBehavior::LevelStreaming) { + pOwner->Modify(); + + // Cesium sub-levels must not be loaded and unloaded by the World + // Partition system. + if (pOwner->GetIsSpatiallyLoaded()) { + pOwner->SetIsSpatiallyLoaded(false); + } + + // Cesium sub-levels must use LevelStreaming behavior). The default + // (Partitioned), will dump the actors in the sub-level into the main + // level, which will prevent us from being to turn the sub-level on and + // off at runtime. + pOwner->DesiredRuntimeBehavior = + ELevelInstanceRuntimeBehavior::LevelStreaming; + + UE_LOG( + LogCesium, + Warning, + TEXT( + "Cesium changed the \"Is Spatially Loaded\" or \"Desired Runtime Behavior\" " + "settings on Level Instance %s in order to work as a Cesium sub-level. If " + "you're using World Partition, you may need to reload the main level in order " + "for these changes to take effect."), + *pOwner->GetName()); + } +#endif + + this->ResolveGeoreference(); + + UCesiumSubLevelSwitcherComponent* pSwitcher = this->_getSwitcher(); + if (pSwitcher) + pSwitcher->RegisterSubLevel(pOwner); + + this->UpdateGeoreferenceIfSubLevelIsActive(); +} + +void UCesiumSubLevelComponent::OnUnregister() { + Super::OnUnregister(); + + ALevelInstance* pOwner = this->_getLevelInstance(); + if (!pOwner) { + return; + } + + UCesiumSubLevelSwitcherComponent* pSwitcher = this->_getSwitcher(); + if (pSwitcher) + pSwitcher->UnregisterSubLevel(pOwner); +} + +#if WITH_EDITOR +bool UCesiumSubLevelComponent::CanEditChange( + const FProperty* InProperty) const { + // Don't allow editing this property if the parent Actor isn't editable. + return Super::CanEditChange(InProperty) && + (!IsValid(GetOwner()) || GetOwner()->CanEditChange(InProperty)); +} +#endif + +UCesiumSubLevelSwitcherComponent* +UCesiumSubLevelComponent::_getSwitcher() noexcept { + // Ignore transient level instances, like those that are created when + // dragging from Create Actors but before releasing the mouse button. + if (!IsValid(this->ResolvedGeoreference) || this->HasAllFlags(RF_Transient)) + return nullptr; + + return this->ResolvedGeoreference + ->FindComponentByClass(); +} + +ALevelInstance* UCesiumSubLevelComponent::_getLevelInstance() const noexcept { + ALevelInstance* pOwner = Cast(this->GetOwner()); + if (!pOwner) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "A CesiumSubLevelComponent can only be attached a LevelInstance Actor.")); + } + return pOwner; +} + +void UCesiumSubLevelComponent::_invalidateResolvedGeoreference() { + if (IsValid(this->ResolvedGeoreference)) { + UCesiumSubLevelSwitcherComponent* pSwitcher = this->_getSwitcher(); + if (pSwitcher) { + ALevelInstance* pOwner = this->_getLevelInstance(); + if (pOwner) { + pSwitcher->UnregisterSubLevel(Cast(pOwner)); + } + } + } + this->ResolvedGeoreference = nullptr; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSubLevelSwitcherComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSubLevelSwitcherComponent.cpp new file mode 100644 index 0000000..df1166c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSubLevelSwitcherComponent.cpp @@ -0,0 +1,365 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumSubLevelSwitcherComponent.h" +#include "CesiumCommon.h" +#include "CesiumRuntime.h" +#include "CesiumSubLevelComponent.h" +#include "Engine/LevelStreaming.h" +#include "Engine/World.h" +#include "LevelInstance/LevelInstanceActor.h" +#include "LevelInstance/LevelInstanceLevelStreaming.h" +#include "LevelInstance/LevelInstanceSubsystem.h" +#include "Runtime/Launch/Resources/Version.h" + +#if WITH_EDITOR +#include "Editor.h" +#endif + +namespace { + +FString GetActorLabel(AActor* pActor) { + if (!IsValid(pActor)) + return TEXT(""); + +#if WITH_EDITOR + return pActor->GetActorLabel(); +#else + return pActor->GetName(); +#endif +} + +} // namespace + +UCesiumSubLevelSwitcherComponent::UCesiumSubLevelSwitcherComponent() { + this->PrimaryComponentTick.bCanEverTick = true; +} + +void UCesiumSubLevelSwitcherComponent::RegisterSubLevel( + ALevelInstance* pSubLevel) noexcept { + this->_sublevels.AddUnique(pSubLevel); + + // Do extra checks on the next tick so that if we're in a game and this level + // is already loaded and shouldn't be, we can unload it. + this->_doExtraChecksOnNextTick = true; + + // In the Editor, sub-levels other than the target must initially be hidden. +#if WITH_EDITOR + if (GEditor && IsValid(this->GetWorld()) && + !this->GetWorld()->IsGameWorld()) { + if (this->_pTarget != pSubLevel) { + pSubLevel->SetIsTemporarilyHiddenInEditor(true); + } + } +#endif +} + +void UCesiumSubLevelSwitcherComponent::UnregisterSubLevel( + ALevelInstance* pSubLevel) noexcept { + this->_sublevels.Remove(pSubLevel); + + // Next tick, we need to check if the target is still registered, in case this + // method call just removed it. But we can't actually do the check here + // because the Editor UI goes through an unregister/re-register cycle + // _constantly_, and we don't want to forget the target sub-level just because + // it was edited in the UI. + this->_doExtraChecksOnNextTick = true; +} + +TArray +UCesiumSubLevelSwitcherComponent::GetRegisteredSubLevels() const noexcept { + TArray result; + result.Reserve(this->_sublevels.Num()); + for (const TWeakObjectPtr& pWeak : this->_sublevels) { + ALevelInstance* p = pWeak.Get(); + if (p) + result.Add(p); + } + return result; +} + +ALevelInstance* +UCesiumSubLevelSwitcherComponent::GetCurrentSubLevel() const noexcept { + return this->_pCurrent.Get(); +} + +ALevelInstance* +UCesiumSubLevelSwitcherComponent::GetTargetSubLevel() const noexcept { + return this->_pTarget.Get(); +} + +void UCesiumSubLevelSwitcherComponent::SetTargetSubLevel( + ALevelInstance* pLevelInstance) noexcept { + if (this->_pTarget != pLevelInstance) { + if (pLevelInstance) { + UE_LOG( + LogCesium, + Display, + TEXT("New target sub-level %s."), + *GetActorLabel(pLevelInstance)); + } else { + UE_LOG(LogCesium, Display, TEXT("New target sub-level ")); + } + + this->_pTarget = pLevelInstance; + this->_isTransitioningSubLevels = true; + } +} + +void UCesiumSubLevelSwitcherComponent::TickComponent( + float DeltaTime, + enum ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) { + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + if (this->_doExtraChecksOnNextTick) { + if (this->_pTarget != nullptr && + this->_sublevels.Find(this->_pTarget) == INDEX_NONE) { + // Target level is no longer registered, so the new target is "none". + this->SetTargetSubLevel(nullptr); + } + + // In game, make sure that any sub-levels that aren't pCurrent or pTarget + // are unloaded. This is primarily needed because ALevelInstances are loaded + // by default and there doesn't seem to be any way to disable this. In the + // Editor, levels pretty much stay loaded all the time. + if (this->GetWorld()->IsGameWorld()) { + bool anyLevelsStillLoaded = false; + for (int32 i = 0; i < this->_sublevels.Num(); ++i) { + ALevelInstance* pSubLevel = this->_sublevels[i].Get(); + if (!IsValid(pSubLevel)) + continue; + + if (pSubLevel == this->_pCurrent || pSubLevel == this->_pTarget) + continue; + + ULevelStreaming* pStreaming = + this->_getLevelStreamingForSubLevel(pSubLevel); + ELevelStreamingState state = IsValid(pStreaming) + ? pStreaming->GetLevelStreamingState() + : ELevelStreamingState::Unloaded; + + switch (state) { + case ELevelStreamingState::Loading: + case ELevelStreamingState::MakingInvisible: + case ELevelStreamingState::MakingVisible: + anyLevelsStillLoaded = true; + break; + case ELevelStreamingState::LoadedNotVisible: + case ELevelStreamingState::LoadedVisible: + pSubLevel->UnloadLevelInstance(); + anyLevelsStillLoaded = true; + break; + case ELevelStreamingState::FailedToLoad: + case ELevelStreamingState::Removed: + case ELevelStreamingState::Unloaded: + break; + } + } + + if (anyLevelsStillLoaded) { + // Don't do anything else until the levels are unloaded. + return; + } + } + + this->_doExtraChecksOnNextTick = false; + } + +#if WITH_EDITOR + UWorld* pWorld = this->GetWorld(); + if (!IsValid(pWorld)) + return; + + if (!this->GetWorld()->IsGameWorld()) { + this->_updateSubLevelStateEditor(); + return; + } +#endif + + this->_updateSubLevelStateGame(); +} + +void UCesiumSubLevelSwitcherComponent::_updateSubLevelStateGame() { + if (this->_isTransitioningSubLevels && this->_pCurrent == this->_pTarget) { + // It's possible that the pCurrent sub-level was active, then we briefly set + // pTarget to something else to trigger an unload of pCurrent, and then + // immediately set pTarget back to pCurrent. So we detect that here. + this->_pCurrent = nullptr; + } + + if (this->_pCurrent == this->_pTarget) { + // We already match the desired state, so there's nothing to do! + return; + } + + this->_isTransitioningSubLevels = false; + + if (this->_pCurrent != nullptr) { + // Work toward unloading the current level. + + ULevelStreaming* pStreaming = + this->_getLevelStreamingForSubLevel(this->_pCurrent.Get()); + + ELevelStreamingState state = ELevelStreamingState::Unloaded; + if (IsValid(pStreaming)) { + state = pStreaming->GetLevelStreamingState(); + + } else if (this->_pCurrent->GetWorldAsset().IsNull()) { + // There is no level associated with the target at all, so mark it + // unloaded but also deactivate it for the benefit of the Editor UI. + this->_pCurrent->UnloadLevelInstance(); + } + + switch (state) { + case ELevelStreamingState::Loading: + case ELevelStreamingState::MakingInvisible: + case ELevelStreamingState::MakingVisible: + // Wait for these transitions to finish before doing anything further. + // TODO: maybe we can cancel these transitions somehow? + UE_LOG( + LogCesium, + Log, + TEXT( + "Waiting for sub-level %s to transition out of an intermediate state while unloading it."), + *GetActorLabel(this->_pCurrent.Get())); + this->_isTransitioningSubLevels = true; + break; + case ELevelStreamingState::FailedToLoad: + case ELevelStreamingState::LoadedNotVisible: + case ELevelStreamingState::LoadedVisible: + UE_LOG( + LogCesium, + Display, + TEXT("Starting unload of sub-level %s."), + *GetActorLabel(this->_pCurrent.Get())); + this->_isTransitioningSubLevels = true; + this->_pCurrent->UnloadLevelInstance(); + break; + case ELevelStreamingState::Removed: + case ELevelStreamingState::Unloaded: + UE_LOG( + LogCesium, + Display, + TEXT("Finished unloading sub-level %s."), + *GetActorLabel(this->_pCurrent.Get())); + this->_pCurrent = nullptr; + break; + } + } + + if (this->_pCurrent == nullptr && this->_pTarget != nullptr) { + // Now that the current level is unloaded, work toward loading the target + // level. + + // At this point there's no Current sub-level, so it's safe to activate the + // Target one even though it's not loaded yet. This way, by the time the + // level _is_ loaded, it will be at the right location because the + // georeference has been updated. + UCesiumSubLevelComponent* pTargetComponent = + this->_pTarget->FindComponentByClass(); + if (pTargetComponent) + pTargetComponent->UpdateGeoreferenceIfSubLevelIsActive(); + + ULevelStreaming* pStreaming = + this->_getLevelStreamingForSubLevel(this->_pTarget.Get()); + + ELevelStreamingState state = ELevelStreamingState::Unloaded; + if (IsValid(pStreaming)) { + state = pStreaming->GetLevelStreamingState(); + } else if (this->_pTarget.Get()->GetWorldAsset().IsNull()) { + // There is no level associated with the target at all, so mark it failed + // to load because this is as loaded as it will ever be. + state = ELevelStreamingState::FailedToLoad; + } + + switch (state) { + case ELevelStreamingState::Loading: + case ELevelStreamingState::MakingInvisible: + case ELevelStreamingState::MakingVisible: + // Wait for these transitions to finish before doing anything further. + UE_LOG( + LogCesium, + Log, + TEXT( + "Waiting for sub-level %s to transition out of an intermediate state while loading it."), + *GetActorLabel(this->_pTarget.Get())); + this->_isTransitioningSubLevels = true; + break; + case ELevelStreamingState::FailedToLoad: + case ELevelStreamingState::LoadedNotVisible: + case ELevelStreamingState::LoadedVisible: + // Loading complete! + UE_LOG( + LogCesium, + Display, + TEXT("Finished loading sub-level %s."), + *GetActorLabel(this->_pTarget.Get())); + + // Double-check that we're not actively trying to unload this level + // already. If we are, wait longer. + if ((IsValid(pStreaming) && pStreaming->ShouldBeLoaded()) || + this->_pTarget.Get()->GetWorldAsset().IsNull()) { + this->_pCurrent = this->_pTarget; + } else { + this->_isTransitioningSubLevels = true; + } + break; + case ELevelStreamingState::Removed: + case ELevelStreamingState::Unloaded: + // Start loading this level + UE_LOG( + LogCesium, + Display, + TEXT("Starting load of sub-level %s."), + *GetActorLabel(this->_pTarget.Get())); + this->_isTransitioningSubLevels = true; + this->_pTarget.Get()->LoadLevelInstance(); + break; + } + } +} + +#if WITH_EDITOR + +void UCesiumSubLevelSwitcherComponent::_updateSubLevelStateEditor() { + if (this->_pTarget == this->_pCurrent) { + // We already match the desired state, so there's nothing to do! + return; + } + + if (this->_pCurrent != nullptr) { + this->_pCurrent.Get()->SetIsTemporarilyHiddenInEditor(true); + this->_pCurrent = nullptr; + } + + if (this->_pTarget != nullptr) { + UCesiumSubLevelComponent* pTargetComponent = + this->_pTarget.Get()->FindComponentByClass(); + if (pTargetComponent) + pTargetComponent->UpdateGeoreferenceIfSubLevelIsActive(); + this->_pTarget.Get()->SetIsTemporarilyHiddenInEditor(false); + this->_pCurrent = this->_pTarget; + } +} + +#endif + +ULevelStreaming* +UCesiumSubLevelSwitcherComponent::_getLevelStreamingForSubLevel( + ALevelInstance* SubLevel) const { + if (!IsValid(SubLevel)) + return nullptr; + + ULevelStreaming* const* ppStreaming = + GetWorld()->GetStreamingLevels().FindByPredicate( + [SubLevel](ULevelStreaming* pStreaming) { + ULevelStreamingLevelInstance* pInstanceStreaming = + Cast(pStreaming); + if (!pInstanceStreaming) + return false; + + return pInstanceStreaming->GetLevelInstance() == SubLevel; + }); + + return ppStreaming ? *ppStreaming : nullptr; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSunSky.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSunSky.cpp new file mode 100644 index 0000000..4f09410 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSunSky.cpp @@ -0,0 +1,618 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumSunSky.h" +#include "CesiumCustomVersion.h" +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumRuntime.h" +#include "Engine/World.h" +#include "GameFramework/Pawn.h" +#include "Kismet/GameplayStatics.h" +#include "SunPosition.h" +#include "TimerManager.h" +#include "UObject/ConstructorHelpers.h" +#include "VecMath.h" + +#if WITH_EDITOR +#include "Editor.h" +#include "EditorViewportClient.h" +#include "LevelEditorViewport.h" +#endif + +// The UE SkyAtmosphere assumes Earth is a sphere. But it's closer to an oblate +// spheroid, where the radius at the poles is ~21km less than the radius at the +// equator. And on top of that, there's terrain, causing bumps of up to 8km or +// so (Mount Everest). Mean Sea Level is nowhere more than 100 meters different +// from the ellipsoid, and the lowest dry land point on Earth is the Dead +// Sea at about 432 meters below sea level. So all up, the worst case "ground +// radius" for atmosphere purposes ranges from about 6356km to about 6387km +// depending on where you are on Earth. That's a range of 31km, which definitely +// matters. We can't pick a single globe radius that will work everywhere on +// Earth. +// +// So, our strategy here is: +// * When close to the surface, it's important that the radius not be too +// large, or else there will be a gap between the bottom of the atmosphere and +// the top of the terrain. To avoid that, we want to use a tight fitting globe +// radius that approximates mean sea level at the camera's position and is +// guaranteed to be below it. Rather than actually calculate sea level, an +// ellipsoid height of -100meters will be close enough. +// * When far from the surface, we can see a lot of the Earth, and it's +// essential that no bits of the surface extend outside the atmosphere, because +// that creates a very distracting artifact. So we want to choose a globe +// radius that is guaranteed to encapsulate all visible parts of the globe. +// * In between these two extremes, we need to blend smoothly. + +// Sets default values +ACesiumSunSky::ACesiumSunSky() : AActor() { + PrimaryActorTick.bCanEverTick = true; + +#if WITH_EDITOR + this->SetIsSpatiallyLoaded(false); +#endif + + Scene = CreateDefaultSubobject(TEXT("Scene")); + SetRootComponent(Scene); + + DirectionalLight = CreateDefaultSubobject( + TEXT("DirectionalLight")); + DirectionalLight->SetupAttachment(Scene); + DirectionalLight->Intensity = 111000.f; + DirectionalLight->LightSourceAngle = 0.5; + DirectionalLight->DynamicShadowCascades = 5; + DirectionalLight->CascadeDistributionExponent = 2.0; + DirectionalLight->DynamicShadowDistanceMovableLight = 500000.f; + + // We need to set both of these, because in the case of a pre-UE5 asset, UE5 + // will replace the normal atmosphere sun light flag with the value of the + // deprecated one on load. + DirectionalLight->bUsedAsAtmosphereSunLight_DEPRECATED = true; + DirectionalLight->SetAtmosphereSunLight(true); + + DirectionalLight->SetRelativeLocation(FVector(0, 0, 0)); + + if (!SkySphereClass) { + static ConstructorHelpers::FClassFinder skySphereFinder( + TEXT("Blueprint'/CesiumForUnreal/MobileSkySphere.MobileSkySphere_C'")); + if (skySphereFinder.Succeeded()) { + SkySphereClass = skySphereFinder.Class; + } + } + + // Always create these components and hide them if not needed (e.g. on mobile) + SkyLight = CreateDefaultSubobject(TEXT("SkyLight")); + SkyLight->SetupAttachment(Scene); + SkyLight->SetMobility(EComponentMobility::Movable); + SkyLight->bRealTimeCapture = true; + SkyLight->bLowerHemisphereIsBlack = false; + SkyLight->bTransmission = true; + SkyLight->SamplesPerPixel = 2; + + SkyLight->CastRaytracedShadow = ECastRayTracedShadow::Enabled; + + // Initially put the SkyLight at the world origin. + // This is updated in UpdateSun. + SkyLight->SetUsingAbsoluteLocation(true); + SkyLight->SetWorldLocation(FVector(0, 0, 0)); + + // The Sky Atmosphere should be positioned relative to the + // Scene/RootComponent, which is kept at the center of the Earth by the + // GlobeAnchorComponent. + SkyAtmosphere = + CreateDefaultSubobject(TEXT("SkyAtmosphere")); + SkyAtmosphere->SetupAttachment(Scene); + SkyAtmosphere->TransformMode = + ESkyAtmosphereTransformMode::PlanetCenterAtComponentTransform; + SkyAtmosphere->TransmittanceMinLightElevationAngle = 90.0f; + + this->GlobeAnchor = + CreateDefaultSubobject(TEXT("GlobeAnchor")); + this->GlobeAnchor->SetAdjustOrientationForGlobeWhenMoving(false); +} + +void ACesiumSunSky::_handleTransformUpdated( + USceneComponent* InRootComponent, + EUpdateTransformFlags UpdateTransformFlags, + ETeleportType Teleport) { + // This Actor generally shouldn't move with respect to the globe, but this + // method will be called on georeference change. We need to update the sun + // position for the new UE coordinate system. + this->UpdateSun(); +} + +void ACesiumSunSky::OnConstruction(const FTransform& Transform) { + Super::OnConstruction(Transform); + + UE_LOG( + LogCesium, + Verbose, + TEXT("Called OnConstruction for CesiumSunSky %s"), + *this->GetName()); + + if (IsValid(this->GlobeAnchor)) { + this->GlobeAnchor->MoveToEarthCenteredEarthFixedPosition( + FVector(0.0, 0.0, 0.0)); + } + + UE_LOG( + LogCesium, + Verbose, + TEXT("Spawn new sky sphere: %s"), + _wantsSpawnMobileSkySphere ? TEXT("true") : TEXT("false")); + if (UseMobileRendering) { + DirectionalLight->Intensity = MobileDirectionalLightIntensity; + if (_wantsSpawnMobileSkySphere && SkySphereClass) { + _spawnSkySphere(); + } + } + _setSkyAtmosphereVisibility(!UseMobileRendering); + + this->UpdateSun(); +} + +void ACesiumSunSky::_spawnSkySphere() { + UWorld* pWorld = GetWorld(); + if (!UseMobileRendering || !IsValid(pWorld)) { + return; + } + + ACesiumGeoreference* pGeoreference = this->GetGeoreference(); + if (!IsValid(pGeoreference)) { + return; + } + + // Create a new Sky Sphere Actor and anchor it to the center of the Earth. + this->SkySphereActor = pWorld->SpawnActor(SkySphereClass); + + // Anchor it to the center of the Earth. + UCesiumGlobeAnchorComponent* GlobeAnchorComponent = + NewObject( + SkySphereActor, + TEXT("GlobeAnchor")); + this->SkySphereActor->AddInstanceComponent(GlobeAnchorComponent); + GlobeAnchorComponent->SetAdjustOrientationForGlobeWhenMoving(false); + GlobeAnchorComponent->SetGeoreference(pGeoreference); + GlobeAnchorComponent->MoveToEarthCenteredEarthFixedPosition( + FVector(0.0, 0.0, 0.0)); + + _wantsSpawnMobileSkySphere = false; + + _setSkySphereDirectionalLight(); +} + +double ACesiumSunSky::_computeScale() const { + // The SkyAtmosphere is not affected by Actor scaling, so we do it manually. + FVector actorScale = this->GetActorScale(); + return actorScale.GetMax(); +} + +void ACesiumSunSky::UpdateSkySphere() { + if (!UseMobileRendering || !IsValid(SkySphereActor)) { + return; + } + UFunction* UpdateSkySphere = + this->SkySphereActor->FindFunction(TEXT("RefreshMaterial")); + if (UpdateSkySphere) { + this->SkySphereActor->ProcessEvent(UpdateSkySphere, NULL); + } +} + +void ACesiumSunSky::BeginPlay() { + Super::BeginPlay(); + + if (IsValid(this->GlobeAnchor)) { + this->GlobeAnchor->MoveToEarthCenteredEarthFixedPosition( + FVector(0.0, 0.0, 0.0)); + } + + this->_transformUpdatedSubscription = + this->RootComponent->TransformUpdated.AddUObject( + this, + &ACesiumSunSky::_handleTransformUpdated); + + _setSkyAtmosphereVisibility(!UseMobileRendering); + + this->UpdateSun(); + + if (this->UpdateAtmosphereAtRuntime) { + this->UpdateAtmosphereRadius(); + } +} + +void ACesiumSunSky::EndPlay(const EEndPlayReason::Type EndPlayReason) { + if (this->_transformUpdatedSubscription.IsValid()) { + this->RootComponent->TransformUpdated.Remove( + this->_transformUpdatedSubscription); + this->_transformUpdatedSubscription.Reset(); + } + + Super::EndPlay(EndPlayReason); +} + +void ACesiumSunSky::Serialize(FArchive& Ar) { + Super::Serialize(Ar); + + Ar.UsingCustomVersion(FCesiumCustomVersion::GUID); + + const int32 CesiumVersion = Ar.CustomVer(FCesiumCustomVersion::GUID); + + if (Ar.IsLoading() && + CesiumVersion < FCesiumCustomVersion::GeoreferenceRefactoring) { + // Now that CesiumSunSky is a C++ class, its Components should be marked + // with a CreationMethod of Native, and they are to start. But because + // CesiumSunSky was a Blueprints class in old versions, the CreationMethod + // of its components gets set to SimpleConstructionScript on load, which + // causes those components to later (and erroneously) be removed. So we + // reset the creation method here. + Ar.Preload(this->RootComponent); + this->RootComponent->CreationMethod = EComponentCreationMethod::Native; + Ar.Preload(this->SkyLight); + this->SkyLight->CreationMethod = EComponentCreationMethod::Native; + Ar.Preload(this->DirectionalLight); + this->DirectionalLight->CreationMethod = EComponentCreationMethod::Native; + Ar.Preload(this->SkyAtmosphere); + this->SkyAtmosphere->CreationMethod = EComponentCreationMethod::Native; + } +} + +void ACesiumSunSky::Tick(float DeltaSeconds) { + Super::Tick(DeltaSeconds); + + if (this->UpdateAtmosphereAtRuntime) { + this->UpdateAtmosphereRadius(); + } + + if (IsValid(this->SkyAtmosphere)) { + double scale = this->_computeScale(); + + float atmosphereHeight = float(scale * this->AtmosphereHeight); + if (atmosphereHeight != this->SkyAtmosphere->AtmosphereHeight) { + this->SkyAtmosphere->SetAtmosphereHeight(atmosphereHeight); + } + + float aerialPerspectiveViewDistanceScale = + float(this->AerialPerspectiveViewDistanceScale / scale); + if (aerialPerspectiveViewDistanceScale != + this->SkyAtmosphere->AerialPespectiveViewDistanceScale) { + this->SkyAtmosphere->SetAerialPespectiveViewDistanceScale( + aerialPerspectiveViewDistanceScale); + } + + float rayleighExponentialDistribution = + float(scale * this->RayleighExponentialDistribution); + if (rayleighExponentialDistribution != + this->SkyAtmosphere->RayleighExponentialDistribution) { + this->SkyAtmosphere->SetRayleighExponentialDistribution( + rayleighExponentialDistribution); + } + + float mieExponentialDistribution = + float(scale * this->MieExponentialDistribution); + if (mieExponentialDistribution != + this->SkyAtmosphere->MieExponentialDistribution) { + this->SkyAtmosphere->SetMieExponentialDistribution( + mieExponentialDistribution); + } + } +} + +void ACesiumSunSky::PostLoad() { + Super::PostLoad(); + + // For backward compatibility, copy the value of the deprecated Georeference + // property to its new home in the GlobeAnchor. It doesn't appear to be + // possible to do this in Serialize: + // https://udn.unrealengine.com/s/question/0D54z00007CAbHFCA1/backward-compatibile-serialization-for-uobject-pointers + const int32 CesiumVersion = + this->GetLinkerCustomVersion(FCesiumCustomVersion::GUID); + if (CesiumVersion < FCesiumCustomVersion::GeoreferenceRefactoring) { + if (this->Georeference_DEPRECATED != nullptr && this->GlobeAnchor && + this->GlobeAnchor->GetGeoreference() == nullptr) { + this->GlobeAnchor->SetGeoreference(this->Georeference_DEPRECATED); + } + } +} + +bool ACesiumSunSky::ShouldTickIfViewportsOnly() const { return true; } + +void ACesiumSunSky::_setSkyAtmosphereVisibility(bool bVisible) { + if (IsValid(SkyLight)) { + SkyLight->SetVisibility(bVisible); + } + if (IsValid(SkyAtmosphere)) { + SkyAtmosphere->SetVisibility(bVisible); + } +} + +void ACesiumSunSky::_setSkySphereDirectionalLight() { + if (!UseMobileRendering || !SkySphereClass || !IsValid(SkySphereActor)) { + return; + } + + for (TFieldIterator PropertyIterator(SkySphereClass); + PropertyIterator; + ++PropertyIterator) { + FProperty* prop = *PropertyIterator; + FName const propName = prop->GetFName(); + if (propName == TEXT("DirectionalLightComponent")) { + FObjectProperty* objectProp = CastField(prop); + if (objectProp) { + UDirectionalLightComponent* directionalLightComponent = nullptr; + if (UseLevelDirectionalLight) { +// Getting the component from a DirectionalLight actor is editor-only +#if WITH_EDITORONLY_DATA + directionalLightComponent = LevelDirectionalLight->GetComponent(); +#endif + } else { + directionalLightComponent = DirectionalLight; + } + objectProp->SetPropertyValue_InContainer( + this->SkySphereActor, + directionalLightComponent); + } + } + } +} + +#if WITH_EDITOR +void ACesiumSunSky::PostEditChangeProperty( + FPropertyChangedEvent& PropertyChangedEvent) { + + const FName propertyName = (PropertyChangedEvent.Property) + ? PropertyChangedEvent.Property->GetFName() + : NAME_None; + if (propertyName == GET_MEMBER_NAME_CHECKED(ACesiumSunSky, SkySphereClass)) { + _wantsSpawnMobileSkySphere = true; + if (SkySphereActor) { + SkySphereActor->Destroy(); + } + } + if (propertyName == + GET_MEMBER_NAME_CHECKED(ACesiumSunSky, UseMobileRendering)) { + _wantsSpawnMobileSkySphere = UseMobileRendering; + _setSkyAtmosphereVisibility(!UseMobileRendering); + if (!UseMobileRendering && SkySphereActor) { + SkySphereActor->Destroy(); + } + } + if (propertyName == + GET_MEMBER_NAME_CHECKED(ACesiumSunSky, UseLevelDirectionalLight) || + propertyName == + GET_MEMBER_NAME_CHECKED(ACesiumSunSky, LevelDirectionalLight)) { + _setSkySphereDirectionalLight(); + if (IsValid(LevelDirectionalLight)) { + LevelDirectionalLight->GetComponent()->SetAtmosphereSunLight(true); + LevelDirectionalLight->GetComponent()->MarkRenderStateDirty(); + } + } + // Place superclass method after variables are updated, so that a new sky + // sphere can be spawned if needed + Super::PostEditChangeProperty(PropertyChangedEvent); +} +#endif + +ACesiumGeoreference* ACesiumSunSky::GetGeoreference() const { + if (!IsValid(this->GlobeAnchor)) { + UE_LOG( + LogCesium, + Error, + TEXT("ACesiumSunSky %s does not have a GlobeAnchorComponent"), + *this->GetName()); + return nullptr; + } + return this->GlobeAnchor->ResolveGeoreference(); +} + +void ACesiumSunSky::UpdateSun_Implementation() { + // Put the Sky Light at the Georeference origin. + // TODO: should it follow the player? + this->SkyLight->SetUsingAbsoluteLocation(true); + this->SkyLight->SetWorldLocation(FVector(0, 0, 0)); + + bool isDST = this->IsDST( + this->UseDaylightSavingTime, + this->DSTStartMonth, + this->DSTStartDay, + this->DSTEndMonth, + this->DSTEndDay, + this->DSTSwitchHour); + + int32 hours, minutes, seconds; + this->GetHMSFromSolarTime(this->SolarTime, hours, minutes, seconds); + + FSunPositionData sunPosition; + USunPositionFunctionLibrary::GetSunPosition( + this->GetGeoreference()->GetOriginLatitude(), + this->GetGeoreference()->GetOriginLongitude(), + this->TimeZone, + isDST, + this->Year, + this->Month, + this->Day, + hours, + minutes, + seconds, + sunPosition); + + this->Elevation = sunPosition.Elevation - 180.0f; + this->CorrectedElevation = sunPosition.CorrectedElevation - 180.0f; + this->Azimuth = sunPosition.Azimuth; + + FRotator newRotation( + -this->CorrectedElevation, + 180.0f + (this->Azimuth + this->NorthOffset), + 0.0f); + + FTransform transform{}; + USceneComponent* pRootComponent = this->GetRootComponent(); + if (IsValid(pRootComponent)) { + USceneComponent* pParent = pRootComponent->GetAttachParent(); + if (IsValid(pParent)) { + transform = pParent->GetComponentToWorld(); + } + } + + FQuat worldRotation = transform.TransformRotation(newRotation.Quaternion()); + + // Orient sun / directional light + if (this->UseLevelDirectionalLight && IsValid(this->LevelDirectionalLight) && + IsValid(this->LevelDirectionalLight->GetRootComponent())) { + this->LevelDirectionalLight->GetRootComponent()->SetWorldRotation( + worldRotation); + } else { + this->DirectionalLight->SetWorldRotation(worldRotation); + } + + // Mobile only + this->UpdateSkySphere(); +} + +namespace { + +FVector getViewLocation(UWorld* pWorld) { +#if WITH_EDITOR + if (!pWorld->IsGameWorld()) { + // Grab the location of the active viewport. + FViewport* pViewport = GEditor->GetActiveViewport(); + + const TArray& viewportClients = + GEditor->GetAllViewportClients(); + for (FEditorViewportClient* pEditorViewportClient : viewportClients) { + if (pEditorViewportClient && pViewport && + pEditorViewportClient == pViewport->GetClient()) { + return pEditorViewportClient->GetViewLocation(); + } + } + } +#endif + + // Get the player's current globe location. + APawn* pPawn = UGameplayStatics::GetPlayerPawn(pWorld, 0); + if (pPawn) { + return pPawn->GetActorLocation(); + } + + return FVector(0.0f, 0.0f, 0.0f); +} + +} // namespace + +void ACesiumSunSky::UpdateAtmosphereRadius() { + UWorld* pWorld = this->GetWorld(); + if (!IsValid(pWorld)) { + UE_LOG( + LogCesium, + Error, + TEXT("ACesiumSunSky %s GetWorld() returned nullptr"), + *this->GetName()); + return; + } + + // This Actor is located at the center of the Earth (the CesiumGlobeAnchor + // keeps it there), so we ignore this Actor's transform and use only its + // parent transform. + FTransform transform{}; + USceneComponent* pRootComponent = this->GetRootComponent(); + if (IsValid(pRootComponent)) { + USceneComponent* pParent = pRootComponent->GetAttachParent(); + if (IsValid(pParent)) { + transform = pParent->GetComponentToWorld().Inverse(); + } + } + + ACesiumGeoreference* pGeoreference = this->GetGeoreference(); + if (!IsValid(pGeoreference)) { + UE_LOG( + LogCesium, + Error, + TEXT("ACesiumSunSky %s can't find an ACesiumGeoreference"), + *this->GetName()); + return; + } + + UCesiumEllipsoid* pEllipsoid = pGeoreference->GetEllipsoid(); + check(IsValid(pEllipsoid)); + + FVector location = transform.TransformPosition(getViewLocation(pWorld)); + FVector llh = + pGeoreference->TransformUnrealPositionToLongitudeLatitudeHeight(location); + + // An atmosphere of this radius should circumscribe all Earth terrain. + double maxRadius = + pEllipsoid->GetMaximumRadius() + this->CircumscribedGroundHeight * 1000.0; + + if (llh.Z / 1000.0 > this->CircumscribedGroundThreshold) { + this->SetSkyAtmosphereGroundRadius( + this->SkyAtmosphere, + maxRadius * this->_computeScale() / 1000.0); + } else { + // Find the ellipsoid radius 100m below the surface at this location. See + // the comment at the top of this file. + glm::dvec3 ecef = pEllipsoid->GetNativeEllipsoid().cartographicToCartesian( + CesiumGeospatial::Cartographic::fromDegrees(llh.X, llh.Y, -100.0)); + double minRadius = glm::length(ecef); + + if (llh.Z / 1000.0 < this->InscribedGroundThreshold) { + this->SetSkyAtmosphereGroundRadius( + this->SkyAtmosphere, + minRadius * this->_computeScale() / 1000.0); + } else { + double t = + ((llh.Z / 1000.0) - this->InscribedGroundThreshold) / + (this->CircumscribedGroundThreshold - this->InscribedGroundThreshold); + double radius = glm::mix(minRadius, maxRadius, t); + this->SetSkyAtmosphereGroundRadius( + this->SkyAtmosphere, + radius * this->_computeScale() / 1000.0); + } + } +} + +void ACesiumSunSky::GetHMSFromSolarTime( + double InSolarTime, + int32& Hour, + int32& Minute, + int32& Second) { + Hour = FMath::TruncToInt(InSolarTime) % 24; + Minute = FMath::TruncToInt((InSolarTime - Hour) * 60) % 60; + + // Convert hours + minutes so far to seconds, and subtract from InSolarTime. + Second = FMath::RoundToInt((InSolarTime - Hour - Minute / 60) * 3600) % 60; +} + +bool ACesiumSunSky::IsDST( + bool DSTEnable, + int32 InDSTStartMonth, + int32 InDSTStartDay, + int32 InDSTEndMonth, + int32 InDSTEndDay, + int32 InDSTSwitchHour) const { + if (!DSTEnable) { + return false; + } + int32 hour, minute, second; + this->GetHMSFromSolarTime(SolarTime, hour, minute, second); + + // Editor will crash if we create an invalid FDateTime, so validate these + // settings first + if (!FDateTime::Validate(Year, Month, Day, hour, minute, second, 0)) { + return false; + } + FDateTime current = FDateTime(Year, Month, Day, hour, minute, second); + FDateTime dstStart = + FDateTime(Year, InDSTStartMonth, InDSTStartDay, InDSTSwitchHour); + FDateTime dstEnd = + FDateTime(Year, InDSTEndMonth, InDSTEndDay, InDSTSwitchHour); + return current >= dstStart && current <= dstEnd; +} + +void ACesiumSunSky::SetSkyAtmosphereGroundRadius( + USkyAtmosphereComponent* Sky, + double Radius) { + // Only update if there's a significant change to be made + float radiusFloat = float(Radius); + if (Sky && !FMath::IsNearlyEqualByULP(radiusFloat, Sky->BottomRadius)) { + Sky->BottomRadius = radiusFloat; + Sky->MarkRenderStateDirty(); + UE_LOG(LogCesium, Verbose, TEXT("GroundRadius now %f"), Sky->BottomRadius); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureResource.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureResource.cpp new file mode 100644 index 0000000..148bcf6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureResource.cpp @@ -0,0 +1,738 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumTextureResource.h" +#include "CesiumRuntime.h" +#include "CesiumTextureUtility.h" +#include "Misc/CoreStats.h" +#include "RenderUtils.h" +#include + +namespace { + +/** + * A Cesium texture resource that uses an already-created `FRHITexture`. This is + * used when `GRHISupportsAsyncTextureCreation` is true and so we were already + * able to create the FRHITexture in a worker thread. It is also used when a + * single glTF `Image` is referenced by multiple glTF `Texture` instances. We + * only need one `FRHITexture` is this case, but we need multiple + * `FTextureResource` instances to support the different sampler settings that + * are likely used in the different textures. + */ +class FCesiumUseExistingTextureResource : public FCesiumTextureResource { +public: + FCesiumUseExistingTextureResource( + FTextureRHIRef existingTexture, + TextureGroup textureGroup, + uint32 width, + uint32 height, + EPixelFormat format, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipsIfAvailable, + uint32 extData, + bool isPrimary); + + FCesiumUseExistingTextureResource( + const TSharedPtr& pExistingTexture, + TextureGroup textureGroup, + uint32 width, + uint32 height, + EPixelFormat format, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipsIfAvailable, + uint32 extData, + bool isPrimary); + +protected: + virtual FTextureRHIRef InitializeTextureRHI() override; + +private: + TSharedPtr _pExistingTexture; +}; + +/** + * A Cesium texture resource that creates an `FRHITexture` from a glTF + * `ImageCesium` when `InitRHI` is called from the render thread. When + * `GRHISupportsAsyncTextureCreation` is false (everywhere but Direct3D), we can + * only create a `FRHITexture` on the render thread, so this is the code that + * does it. + * + * Upon passing an `ImageAsset` to this class's constructor, its `pixelData` and + * `mipPositions` fields are cleared. That is, this class takes ownership of + * that data. + */ +class FCesiumCreateNewTextureResource : public FCesiumTextureResource { +public: + FCesiumCreateNewTextureResource( + CesiumGltf::ImageAsset& image, + TextureGroup textureGroup, + uint32 width, + uint32 height, + EPixelFormat format, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipsIfAvailable, + uint32 extData); + +protected: + virtual FTextureRHIRef InitializeTextureRHI() override; + +private: + std::vector _mipPositions; + std::vector _pixelData; +}; + +ESamplerFilter convertFilter(TextureFilter filter) { + switch (filter) { + case TF_Nearest: + return ESamplerFilter::SF_Point; + case TF_Bilinear: + return ESamplerFilter::SF_Bilinear; + default: + // case TF_Trilinear: + // case TF_Default: + // case TF_MAX: + return ESamplerFilter::SF_AnisotropicLinear; + } +} + +ESamplerAddressMode convertAddressMode(TextureAddress address) { + switch (address) { + case TA_Wrap: + return ESamplerAddressMode::AM_Wrap; + case TA_Mirror: + return ESamplerAddressMode::AM_Mirror; + default: + // case TA_Clamp: + // case TA_MAX: + return ESamplerAddressMode::AM_Clamp; + } +} + +/** + * @brief Copies an in-memory glTF mip to the destination. Respects arbitrary + * row strides at the destination. + * + * @param pDest The pre-allocated destination. + * @param destPitch The row stride in bytes, at the destination. If this is 0, + * the source mip will be bulk copied. + * @param format The pixel format. + * @param src The source image to copy from. + * @param mipIndex The mip index to copy over. + */ +void CopyMip( + void* pDest, + uint32 destPitch, + EPixelFormat format, + int32_t width, + int32_t height, + const std::vector& srcPixelData, + const std::vector& srcMipPositions, + uint32 mipIndex) { + size_t byteOffset = 0; + size_t byteSize = 0; + if (srcMipPositions.empty()) { + byteOffset = 0; + byteSize = srcPixelData.size(); + } else { + const CesiumGltf::ImageAssetMipPosition& mipPos = srcMipPositions[mipIndex]; + byteOffset = mipPos.byteOffset; + byteSize = mipPos.byteSize; + } + uint32 mipWidth = + FMath::Max(static_cast(width) >> mipIndex, 1); + uint32 mipHeight = + FMath::Max(static_cast(height) >> mipIndex, 1); + + const void* pSrcData = static_cast(&srcPixelData[byteOffset]); + + // for platforms that returned 0 pitch from Lock, we need to just use the bulk + // data directly, never do runtime block size checking, conversion, or the + // like + if (destPitch == 0) { + FMemory::Memcpy(pDest, pSrcData, byteSize); + } else { + const uint32 blockSizeX = + GPixelFormats[format].BlockSizeX; // Block width in pixels + const uint32 blockSizeY = + GPixelFormats[format].BlockSizeY; // Block height in pixels + const uint32 blockBytes = GPixelFormats[format].BlockBytes; + uint32 numColumns = + (mipWidth + blockSizeX - 1) / + blockSizeX; // Num-of columns in the source data (in blocks) + uint32 numRows = (mipHeight + blockSizeY - 1) / + blockSizeY; // Num-of rows in the source data (in blocks) + if (format == PF_PVRTC2 || format == PF_PVRTC4) { + // PVRTC has minimum 2 blocks width and height + numColumns = FMath::Max(numColumns, 2); + numRows = FMath::Max(numRows, 2); + } + + const uint32 srcPitch = + numColumns * blockBytes; // Num-of bytes per row in the source data + + // Copy the texture data. + CopyTextureData2D(pSrcData, pDest, mipHeight, format, srcPitch, destPitch); + } +} + +FTexture2DRHIRef createAsyncTextureAndWait( + uint32 SizeX, + uint32 SizeY, + uint8 Format, + uint32 NumMips, + ETextureCreateFlags Flags, + void** InitialMipData, + uint32 NumInitialMips) { + +#if ENGINE_VERSION_5_4_OR_HIGHER + FGraphEventRef CompletionEvent; + + FTexture2DRHIRef result = RHIAsyncCreateTexture2D( + SizeX, + SizeY, + Format, + NumMips, + Flags, + ERHIAccess::Unknown, + InitialMipData, + NumInitialMips, + TEXT("CesiumTexture"), + CompletionEvent); + + if (CompletionEvent) { + CompletionEvent->Wait(); + } + + return result; +#else + FGraphEventRef CompletionEvent; + + FTexture2DRHIRef result = RHIAsyncCreateTexture2D( + SizeX, + SizeY, + Format, + NumMips, + Flags, + InitialMipData, + NumInitialMips, + CompletionEvent); + + if (CompletionEvent) { + CompletionEvent->Wait(); + } + + return result; +#endif +} + +/** + * @brief Create an RHI texture on this thread. This requires + * GRHISupportsAsyncTextureCreation to be true. + * + * @param image The CPU image to create on the GPU. + * @param format The pixel format of the image. + * @param Whether to use a sRGB color-space. + * @return The RHI texture reference. + */ +FTexture2DRHIRef CreateRHITexture2D_Async( + const CesiumGltf::ImageAsset& image, + EPixelFormat format, + bool sRGB) { + check(GRHISupportsAsyncTextureCreation); + + ETextureCreateFlags textureFlags = TexCreate_ShaderResource; + + // Just like in FCesiumCreateNewTextureResource, we're assuming here that we + // can create an FRHITexture as sRGB, and later create another + // UTexture2D / FTextureResource pointing to the same FRHITexture that is not + // sRGB (or vice-versa), and that Unreal will effectively ignore the flag on + // FRHITexture. + if (sRGB) { + textureFlags |= TexCreate_SRGB; + } + + if (!image.mipPositions.empty()) { + // Here 16 is a generously large (but arbitrary) hard limit for number of + // mips. + uint32 mipCount = static_cast(image.mipPositions.size()); + if (mipCount > 16) { + mipCount = 16; + } + + void* mipsData[16]; + for (size_t i = 0; i < mipCount; ++i) { + const CesiumGltf::ImageAssetMipPosition& mipPos = image.mipPositions[i]; + mipsData[i] = (void*)(&image.pixelData[mipPos.byteOffset]); + } + + return createAsyncTextureAndWait( + static_cast(image.width), + static_cast(image.height), + format, + mipCount, + textureFlags, + mipsData, + mipCount); + } else { + void* pTextureData = (void*)(image.pixelData.data()); + return createAsyncTextureAndWait( + static_cast(image.width), + static_cast(image.height), + format, + 1, + textureFlags, + &pTextureData, + 1); + } +} + +} // namespace + +void FCesiumTextureResourceDeleter::operator()(FCesiumTextureResource* p) { + FCesiumTextureResource::Destroy(p); +} + +/*static*/ FCesiumTextureResourceUniquePtr FCesiumTextureResource::CreateNew( + CesiumGltf::ImageAsset& imageCesium, + TextureGroup textureGroup, + const std::optional& overridePixelFormat, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool needsMipMaps) { + if (imageCesium.pixelData.empty()) { + return nullptr; + } + + if (needsMipMaps) { + std::optional errorMessage = + CesiumGltfReader::ImageDecoder::generateMipMaps(imageCesium); + if (errorMessage) { + UE_LOG( + LogCesium, + Warning, + TEXT("%s"), + UTF8_TO_TCHAR(errorMessage->c_str())); + } + } + + std::optional maybePixelFormat = + CesiumTextureUtility::getPixelFormatForImageAsset( + imageCesium, + overridePixelFormat); + if (!maybePixelFormat) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "Image cannot be created because it has an unsupported compressed pixel format (%d)."), + imageCesium.compressedPixelFormat); + return nullptr; + } + + // Store the current size of the pixel data, because + // we're about to clear it but we still want to have + // an accurate estimation of the size of the image for + // caching purposes. + imageCesium.sizeBytes = int64_t(imageCesium.pixelData.size()); + + if (GRHISupportsAsyncTextureCreation) { + // Create RHI texture resource on this worker + // thread, and then hand it off to the renderer + // thread. + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CreateRHITexture2D) + + FTexture2DRHIRef textureReference = + CreateRHITexture2D_Async(imageCesium, *maybePixelFormat, sRGB); + // textureReference->SetName( + // FName(UTF8_TO_TCHAR(imageCesium.getUniqueAssetId().c_str()))); + auto pResult = + FCesiumTextureResourceUniquePtr(new FCesiumUseExistingTextureResource( + textureReference, + textureGroup, + imageCesium.width, + imageCesium.height, + *maybePixelFormat, + filter, + addressX, + addressY, + sRGB, + needsMipMaps, + 0, + true)); + + // Clear the now-unnecessary copy of the pixel data. + // Calling clear() isn't good enough because it + // won't actually release the memory. + std::vector pixelData; + imageCesium.pixelData.swap(pixelData); + + std::vector mipPositions; + imageCesium.mipPositions.swap(mipPositions); + + return pResult; + } else { + // The RHI texture will be created later on the + // render thread, directly from this texture source. + // We need valid pixelData here, though. + auto pResult = + FCesiumTextureResourceUniquePtr(new FCesiumCreateNewTextureResource( + imageCesium, + textureGroup, + imageCesium.width, + imageCesium.height, + *maybePixelFormat, + filter, + addressX, + addressY, + sRGB, + needsMipMaps, + 0)); + return pResult; + } +} + +FCesiumTextureResourceUniquePtr FCesiumTextureResource::CreateWrapped( + const TSharedPtr& pExistingResource, + TextureGroup textureGroup, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipMapsIfAvailable) { + if (pExistingResource == nullptr) + return nullptr; + + return FCesiumTextureResourceUniquePtr(new FCesiumUseExistingTextureResource( + pExistingResource, + textureGroup, + pExistingResource->_width, + pExistingResource->_height, + pExistingResource->_format, + filter, + addressX, + addressY, + sRGB, + useMipMapsIfAvailable, + 0, + false)); +} + +/*static*/ void FCesiumTextureResource::Destroy(FCesiumTextureResource* p) { + if (p == nullptr) + return; + + ENQUEUE_RENDER_COMMAND(DeleteResource) + ([p](FRHICommandListImmediate& RHICmdList) { + p->ReleaseResource(); + delete p; + }); +} + +FCesiumTextureResource::FCesiumTextureResource( + TextureGroup textureGroup, + uint32 width, + uint32 height, + EPixelFormat format, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipsIfAvailable, + uint32 extData, + bool isPrimary) + : _textureGroup(textureGroup), + _width(width), + _height(height), + _format(format), + _filter(convertFilter(filter)), + _addressX(convertAddressMode(addressX)), + _addressY(convertAddressMode(addressY)), + _useMipsIfAvailable(useMipsIfAvailable), + _platformExtData(extData), + _isPrimary(isPrimary) { + this->bGreyScaleFormat = (_format == PF_G8) || (_format == PF_BC4); + this->bSRGB = sRGB; + STAT(this->_lodGroupStatName = TextureGroupStatFNames[this->_textureGroup]); +} + +void FCesiumTextureResource::InitRHI(FRHICommandListBase& RHICmdList) { + FSamplerStateInitializerRHI samplerStateInitializer( + this->_filter, + this->_addressX, + this->_addressY, + AM_Wrap, + 0.0f, + 0, + 0.0f, + this->_useMipsIfAvailable ? FLT_MAX : 1.0f); + this->SamplerStateRHI = GetOrCreateSamplerState(samplerStateInitializer); + + // Create a custom sampler state for using this texture in a deferred pass, + // where ddx / ddy are discontinuous + FSamplerStateInitializerRHI deferredSamplerStateInitializer( + this->_filter, + this->_addressX, + this->_addressY, + AM_Wrap, + 0.0f, + // Disable anisotropic filtering, since aniso doesn't respect MaxLOD + 1, + 0.0f, + // Prevent the less detailed mip levels from being used, which hides + // artifacts on silhouettes due to ddx / ddy being very large. This has + // the side effect that it increases minification aliasing on light + // functions + this->_useMipsIfAvailable ? 2.0f : 1.0f); + this->DeferredPassSamplerStateRHI = + GetOrCreateSamplerState(deferredSamplerStateInitializer); + + this->TextureRHI = this->InitializeTextureRHI(); + + RHIUpdateTextureReference(TextureReferenceRHI, this->TextureRHI); + +#if STATS + if (this->_isPrimary) { + ETextureCreateFlags textureFlags = TexCreate_ShaderResource; + if (this->bSRGB) { + textureFlags |= TexCreate_SRGB; + } + + const FIntPoint MipExtents = + CalcMipMapExtent(this->_width, this->_height, this->_format, 0); + const FRHIResourceCreateInfo CreateInfo(this->_platformExtData); + + uint32 alignment; + this->_textureSize = RHICalcTexture2DPlatformSize( + MipExtents.X, + MipExtents.Y, + this->_format, + this->GetCurrentMipCount(), + 1, + textureFlags, + FRHIResourceCreateInfo(this->_platformExtData), + alignment); + + INC_DWORD_STAT_BY(STAT_TextureMemory, this->_textureSize); + INC_DWORD_STAT_FNAME_BY(this->_lodGroupStatName, this->_textureSize); + } +#endif +} + +void FCesiumTextureResource::ReleaseRHI() { +#if STATS + if (this->_isPrimary) { + DEC_DWORD_STAT_BY(STAT_TextureMemory, this->_textureSize); + DEC_DWORD_STAT_FNAME_BY(this->_lodGroupStatName, this->_textureSize); + } +#endif + + RHIUpdateTextureReference(TextureReferenceRHI, nullptr); + + FTextureResource::ReleaseRHI(); +} + +#if STATS + +// This is copied from TextureResource.cpp. Unfortunately we can't use +// FTextureResource::TextureGroupStatFNames, even though it's static and public, +// because, inexplicably, it isn't DLL exported. So instead we duplicate it +// here. +namespace { +DECLARE_STATS_GROUP( + TEXT("Texture Group"), + STATGROUP_TextureGroup, + STATCAT_Advanced); + +// Declare the stats for each Texture Group. +#define DECLARETEXTUREGROUPSTAT(Group) \ + DECLARE_MEMORY_STAT(TEXT(#Group), STAT_##Group, STATGROUP_TextureGroup); +FOREACH_ENUM_TEXTUREGROUP(DECLARETEXTUREGROUPSTAT) +#undef DECLARETEXTUREGROUPSTAT +} // namespace + +FName FCesiumTextureResource::TextureGroupStatFNames[TEXTUREGROUP_MAX] = { +#define ASSIGNTEXTUREGROUPSTATNAME(Group) GET_STATFNAME(STAT_##Group), + FOREACH_ENUM_TEXTUREGROUP(ASSIGNTEXTUREGROUPSTATNAME) +#undef ASSIGNTEXTUREGROUPSTATNAME +}; + +#endif // #if STATS + +FCesiumUseExistingTextureResource::FCesiumUseExistingTextureResource( + FTextureRHIRef existingTexture, + TextureGroup textureGroup, + uint32 width, + uint32 height, + EPixelFormat format, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipsIfAvailable, + uint32 extData, + bool isPrimary) + : FCesiumTextureResource( + textureGroup, + width, + height, + format, + filter, + addressX, + addressY, + sRGB, + useMipsIfAvailable, + extData, + isPrimary), + _pExistingTexture(nullptr) { + this->TextureRHI = std::move(existingTexture); +} + +FCesiumUseExistingTextureResource::FCesiumUseExistingTextureResource( + const TSharedPtr& pExistingTexture, + TextureGroup textureGroup, + uint32 width, + uint32 height, + EPixelFormat format, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipsIfAvailable, + uint32 extData, + bool isPrimary) + : FCesiumTextureResource( + textureGroup, + width, + height, + format, + filter, + addressX, + addressY, + sRGB, + useMipsIfAvailable, + extData, + isPrimary), + _pExistingTexture(pExistingTexture) {} + +FTextureRHIRef FCesiumUseExistingTextureResource::InitializeTextureRHI() { + if (this->_pExistingTexture) { + return this->_pExistingTexture->TextureRHI; + } else { + return this->TextureRHI; + } +} + +FCesiumCreateNewTextureResource::FCesiumCreateNewTextureResource( + CesiumGltf::ImageAsset& image, + TextureGroup textureGroup, + uint32 width, + uint32 height, + EPixelFormat format, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipsIfAvailable, + uint32 extData) + : FCesiumTextureResource( + textureGroup, + width, + height, + format, + filter, + addressX, + addressY, + sRGB, + useMipsIfAvailable, + extData, + true), + _mipPositions(std::move(image.mipPositions)), + _pixelData(std::move(image.pixelData)) {} + +FTextureRHIRef FCesiumCreateNewTextureResource::InitializeTextureRHI() { + // Use the asset ID as the name of the texture so it will be visible in the + // Render Resource Viewer. + FString debugName = TEXT("CesiumTextureUtility"); + // if (!this->_image.getUniqueAssetId().empty()) { + // debugName = UTF8_TO_TCHAR(this->_image.getUniqueAssetId().c_str()); + // } + + FRHIResourceCreateInfo createInfo{*debugName}; + createInfo.BulkData = nullptr; + createInfo.ExtData = _platformExtData; + + ETextureCreateFlags textureFlags = TexCreate_ShaderResource; + + // What if a texture is treated as sRGB in one context but not another? + // In glTF, whether or not a texture should be treated as sRGB depends on how + // it's _used_. A texture used for baseColorFactor or emissiveFactor should be + // sRGB, while all others should be linear. It's unlikely - but not impossible + // - for a single glTF Texture or Image to be used in one context where it + // must be sRGB, and another where it must be linear. Unreal also has an sRGB + // flag on FTextureResource and on UTexture2D (neither of which are shared), + // so _hopefully_ those will apply even if the underlying FRHITexture (which + // is shared) says differently. If not, we'll likely end up treating the + // second texture incorrectly. Confirming an answer here will be time + // consuming, and the scenario is quite unlikely, so we're strategically + // leaving this an open question. + if (this->bSRGB) { + textureFlags |= TexCreate_SRGB; + } + + uint32 mipCount = + FMath::Max(1, static_cast(this->_mipPositions.size())); + + // Create a new RHI texture, initially empty. + + // RHICreateTexture2D can actually copy over all the mips in one shot, + // but it expects a particular memory layout. Might be worth configuring + // Cesium Native's mip-map generation to obey a standard memory layout. + FTexture2DRHIRef rhiTexture = + RHICreateTexture(FRHITextureCreateDesc::Create2D(createInfo.DebugName) + .SetExtent(int32(this->_width), int32(this->_height)) + .SetFormat(this->_format) + .SetNumMips(uint8(mipCount)) + .SetNumSamples(1) + .SetFlags(textureFlags) + .SetInitialState(ERHIAccess::Unknown) + .SetExtData(createInfo.ExtData) + .SetGPUMask(createInfo.GPUMask) + .SetClearValue(createInfo.ClearValueBinding)); + + // Copy over all image data (including mip levels) + for (uint32 i = 0; i < mipCount; ++i) { + uint32 DestPitch; + void* pDestination = + RHILockTexture2D(rhiTexture, i, RLM_WriteOnly, DestPitch, false); + CopyMip( + pDestination, + DestPitch, + this->_format, + this->_width, + this->_height, + this->_pixelData, + this->_mipPositions, + i); + RHIUnlockTexture2D(rhiTexture, i, false); + } + + // Clear the now-unnecessary copy of the pixel data. Calling clear() isn't + // good enough because it won't actually release the memory. + std::vector pixelData; + this->_pixelData.swap(pixelData); + + std::vector mipPositions; + this->_mipPositions.swap(mipPositions); + + return rhiTexture; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureResource.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureResource.h new file mode 100644 index 0000000..266acff --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureResource.h @@ -0,0 +1,121 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumCommon.h" +#include "Engine/Texture.h" +#include "TextureResource.h" +#include +#include + +class FCesiumTextureResource; + +struct FCesiumTextureResourceDeleter { + void operator()(FCesiumTextureResource* p); +}; + +using FCesiumTextureResourceUniquePtr = + TUniquePtr; + +/** + * The base class for Cesium texture resources, making Cesium's texture data + * available to Unreal's RHI. The actual creation of the RHI texture is deferred + * to a pure virtual method, `InitializeTextureRHI`. + */ +class FCesiumTextureResource : public FTextureResource { +public: + /** + * Create a new FCesiumTextureResource from an `ImageAsset` and the given + * sampling parameters. This method is intended to be called from a worker + * thread, not from the game or render thread. + * + * @param imageCesium The image data from which to create the texture + * resource. After this method returns, the `pixelData` will be empty, and + * `sizeBytes` will be set to its previous size. + * @param textureGroup The texture group in which to create this texture. + * @param overridePixelFormat Overrides the pixel format. If std::nullopt, the + * format is inferred from the `ImageAsset`. + * @param filter The texture filtering to use when sampling this texture. + * @param addressX The X texture addressing mode to use when sampling this + * texture. + * @param addressY The Y texture addressing mode to use when sampling this + * texture. + * @param sRGB True if the image data stored in this texture should be treated + * as sRGB. + * @param needsMipMaps True if this texture requires mipmaps. They will be + * generated if they don't already exist. + * @return The created texture resource, or nullptr if a texture could not be + * created. + */ + static FCesiumTextureResourceUniquePtr CreateNew( + CesiumGltf::ImageAsset& imageCesium, + TextureGroup textureGroup, + const std::optional& overridePixelFormat, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool needsMipMaps); + + /** + * Create a new FCesiumTextureResource wrapping an existing one and providing + * new sampling parameters. This method is intended to be called from a worker + * thread, not from the game or render thread. + */ + static FCesiumTextureResourceUniquePtr CreateWrapped( + const TSharedPtr& pExistingResource, + TextureGroup textureGroup, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipMapsIfAvailable); + + /** + * Destroys an FCesiumTextureResource. Unreal TextureResources must be + * destroyed on the render thread, so it is important not to call `delete` + * directly. + * + * \param p + */ + static void Destroy(FCesiumTextureResource* p); + + FCesiumTextureResource( + TextureGroup textureGroup, + uint32 width, + uint32 height, + EPixelFormat format, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipsIfAvailable, + uint32 extData, + bool isPrimary); + + uint32 GetSizeX() const override { return this->_width; } + uint32 GetSizeY() const override { return this->_height; } + + virtual void InitRHI(FRHICommandListBase& RHICmdList) override; + virtual void ReleaseRHI() override; + +#if STATS + static FName TextureGroupStatFNames[TEXTUREGROUP_MAX]; +#endif + +protected: + virtual FTextureRHIRef InitializeTextureRHI() = 0; + + TextureGroup _textureGroup; + uint32 _width; + uint32 _height; + EPixelFormat _format; + ESamplerFilter _filter; + ESamplerAddressMode _addressX; + ESamplerAddressMode _addressY; + bool _useMipsIfAvailable; + uint32 _platformExtData; + FName _lodGroupStatName; + uint64 _textureSize; + bool _isPrimary; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureUtility.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureUtility.cpp new file mode 100644 index 0000000..de72f00 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureUtility.cpp @@ -0,0 +1,487 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumTextureUtility.h" +#include "Async/Async.h" +#include "Async/Future.h" +#include "Async/TaskGraphInterfaces.h" +#include "CesiumCommon.h" +#include "CesiumLifetime.h" +#include "CesiumRuntime.h" +#include "CesiumTextureResource.h" +#include "Containers/ResourceArray.h" +#include "DynamicRHI.h" +#include "ExtensionImageAssetUnreal.h" +#include "GenericPlatform/GenericPlatformProcess.h" +#include "PixelFormat.h" +#include "RHICommandList.h" +#include "RHIDefinitions.h" +#include "RHIResources.h" +#include "RenderUtils.h" +#include "RenderingThread.h" +#include "Runtime/Launch/Resources/Version.h" +#include "TextureResource.h" +#include "UObject/Package.h" +#include +#include +#include +#include +#include +#include + +namespace { + +struct ExtensionUnrealTexture { + static inline constexpr const char* TypeName = "ExtensionUnrealTexture"; + static inline constexpr const char* ExtensionName = "PRIVATE_unreal_texture"; + + CesiumUtility::IntrusivePointer< + CesiumTextureUtility::ReferenceCountedUnrealTexture> + pTexture = nullptr; +}; + +} // namespace + +namespace CesiumTextureUtility { + +ReferenceCountedUnrealTexture::ReferenceCountedUnrealTexture() noexcept + : _pUnrealTexture(nullptr), _pTextureResource(nullptr) {} + +ReferenceCountedUnrealTexture::~ReferenceCountedUnrealTexture() noexcept { + UTexture2D* pLocal = this->_pUnrealTexture; + this->_pUnrealTexture = nullptr; + + if (IsValid(pLocal)) { + if (IsInGameThread()) { + pLocal->RemoveFromRoot(); + CesiumLifetime::destroy(pLocal); + } else { + AsyncTask(ENamedThreads::GameThread, [pLocal]() { + pLocal->RemoveFromRoot(); + CesiumLifetime::destroy(pLocal); + }); + } + } +} + +TObjectPtr ReferenceCountedUnrealTexture::getUnrealTexture() const { + return this->_pUnrealTexture; +} + +void ReferenceCountedUnrealTexture::setUnrealTexture( + const TObjectPtr& p) { + if (p == this->_pUnrealTexture) + return; + + if (p) { + p->AddToRoot(); + } + + if (this->_pUnrealTexture) { + this->_pUnrealTexture->RemoveFromRoot(); + } + + this->_pUnrealTexture = p; +} + +const FCesiumTextureResourceUniquePtr& +ReferenceCountedUnrealTexture::getTextureResource() const { + return this->_pTextureResource; +} + +FCesiumTextureResourceUniquePtr& +ReferenceCountedUnrealTexture::getTextureResource() { + return this->_pTextureResource; +} + +void ReferenceCountedUnrealTexture::setTextureResource( + FCesiumTextureResourceUniquePtr&& p) { + this->_pTextureResource = std::move(p); +} + +std::optional getSourceIndexFromModelAndTexture( + const CesiumGltf::Model& model, + const CesiumGltf::Texture& texture) { + const CesiumGltf::ExtensionKhrTextureBasisu* pKtxExtension = + texture.getExtension(); + const CesiumGltf::ExtensionTextureWebp* pWebpExtension = + texture.getExtension(); + + int32_t source = -1; + if (pKtxExtension) { + if (pKtxExtension->source < 0 || + pKtxExtension->source >= model.images.size()) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "KTX texture source index must be non-negative and less than %d, but is %d"), + model.images.size(), + pKtxExtension->source); + return std::nullopt; + } + return std::optional(pKtxExtension->source); + } else if (pWebpExtension) { + if (pWebpExtension->source < 0 || + pWebpExtension->source >= model.images.size()) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "WebP texture source index must be non-negative and less than %d, but is %d"), + model.images.size(), + pWebpExtension->source); + return std::nullopt; + } + return std::optional(pWebpExtension->source); + } else { + if (texture.source < 0 || texture.source >= model.images.size()) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "Texture source index must be non-negative and less than %d, but is %d"), + model.images.size(), + texture.source); + return std::nullopt; + } + return std::optional(texture.source); + } +} + +TUniquePtr loadTextureFromModelAnyThreadPart( + CesiumGltf::Model& model, + CesiumGltf::Texture& texture, + bool sRGB) { + int64_t textureIndex = + model.textures.empty() ? -1 : &texture - &model.textures[0]; + if (textureIndex < 0 || size_t(textureIndex) >= model.textures.size()) { + textureIndex = -1; + } + + ExtensionUnrealTexture& extension = + texture.addExtension(); + if (extension.pTexture && (extension.pTexture->getUnrealTexture() || + extension.pTexture->getTextureResource())) { + // There's an existing Unreal texture for this glTF texture. This will + // happen if this texture is used by multiple primitives on the same + // model. It will also be the case when this model was upsampled from a + // parent tile. + TUniquePtr pResult = MakeUnique(); + pResult->pTexture = extension.pTexture; + pResult->textureIndex = textureIndex; + return pResult; + } + + std::optional optionalSourceIndex = + getSourceIndexFromModelAndTexture(model, texture); + if (!optionalSourceIndex.has_value()) { + return nullptr; + }; + + CesiumGltf::Image& image = model.images[*optionalSourceIndex]; + if (image.pAsset == nullptr) { + return nullptr; + } + + const CesiumGltf::Sampler& sampler = + model.getSafe(model.samplers, texture.sampler); + + TUniquePtr result = + loadTextureFromImageAndSamplerAnyThreadPart(*image.pAsset, sampler, sRGB); + + if (result) { + extension.pTexture = result->pTexture; + result->textureIndex = textureIndex; + } + + return result; +} + +TextureFilter getTextureFilterFromSampler(const CesiumGltf::Sampler& sampler) { + // Unreal Engine's available filtering modes are only nearest, bilinear, + // trilinear, and "default". Default means "use the texture group settings", + // and the texture group settings are defined in a config file and can + // vary per platform. All filter modes can use mipmaps if they're available, + // but only TF_Default will ever use anisotropic texture filtering. + // + // Unreal also doesn't separate the minification filter from the + // magnification filter. So we'll just ignore the magFilter unless it's the + // only filter specified. + // + // Generally our bias is toward TF_Default, because that gives the user more + // control via texture groups. + + if (sampler.magFilter && !sampler.minFilter) { + // Only a magnification filter is specified, so use it. + return sampler.magFilter.value() == CesiumGltf::Sampler::MagFilter::NEAREST + ? TextureFilter::TF_Nearest + : TextureFilter::TF_Default; + } else if (sampler.minFilter) { + // Use specified minFilter. + switch (sampler.minFilter.value()) { + case CesiumGltf::Sampler::MinFilter::NEAREST: + case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_NEAREST: + return TextureFilter::TF_Nearest; + case CesiumGltf::Sampler::MinFilter::LINEAR: + case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_NEAREST: + return TextureFilter::TF_Bilinear; + default: + return TextureFilter::TF_Default; + } + } else { + // No filtering specified at all, let the texture group decide. + return TextureFilter::TF_Default; + } +} + +bool getUseMipmapsIfAvailableFromSampler(const CesiumGltf::Sampler& sampler) { + switch (sampler.minFilter.value_or( + CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR)) { + case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR: + case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_NEAREST: + case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_LINEAR: + case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_NEAREST: + return true; + default: // LINEAR and NEAREST + return false; + } +} + +TUniquePtr loadTextureFromImageAndSamplerAnyThreadPart( + CesiumGltf::ImageAsset& image, + const CesiumGltf::Sampler& sampler, + bool sRGB) { + return loadTextureAnyThreadPart( + image, + convertGltfWrapSToUnreal(sampler.wrapS), + convertGltfWrapTToUnreal(sampler.wrapT), + getTextureFilterFromSampler(sampler), + getUseMipmapsIfAvailableFromSampler(sampler), + // TODO: allow texture group to be configured on Cesium3DTileset. + TEXTUREGROUP_World, + sRGB, + std::nullopt); +} + +static UTexture2D* CreateTexture2D(LoadedTextureResult* pHalfLoadedTexture) { + if (!pHalfLoadedTexture || !pHalfLoadedTexture->pTexture) { + return nullptr; + } + + UTexture2D* pTexture = pHalfLoadedTexture->pTexture->getUnrealTexture(); + if (!pTexture) { + pTexture = NewObject( + GetTransientPackage(), + MakeUniqueObjectName( + GetTransientPackage(), + UTexture2D::StaticClass(), + "CesiumRuntimeTexture"), + RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + + pTexture->AddressX = pHalfLoadedTexture->addressX; + pTexture->AddressY = pHalfLoadedTexture->addressY; + pTexture->Filter = pHalfLoadedTexture->filter; + pTexture->LODGroup = pHalfLoadedTexture->group; + pTexture->SRGB = pHalfLoadedTexture->sRGB; + + pTexture->NeverStream = true; + + pHalfLoadedTexture->pTexture->setUnrealTexture(pTexture); + } + + return pTexture; +} + +TUniquePtr loadTextureAnyThreadPart( + CesiumGltf::ImageAsset& image, + TextureAddress addressX, + TextureAddress addressY, + TextureFilter filter, + bool useMipMapsIfAvailable, + TextureGroup group, + bool sRGB, + std::optional overridePixelFormat) { + // The FCesiumTextureResource for the ImageAsset should already be created at + // this point, if it can be. + const ExtensionImageAssetUnreal& extension = + ExtensionImageAssetUnreal::getOrCreate( + CesiumAsync::AsyncSystem(nullptr), + image, + sRGB, + useMipMapsIfAvailable, + overridePixelFormat); + check(extension.getFuture().isReady()); + if (extension.getTextureResource() == nullptr) { + return nullptr; + } + + auto pResource = FCesiumTextureResource::CreateWrapped( + extension.getTextureResource(), + group, + filter, + addressX, + addressY, + sRGB, + useMipMapsIfAvailable); + + TUniquePtr pResult = MakeUnique(); + pResult->pTexture = new ReferenceCountedUnrealTexture(); + + pResult->addressX = addressX; + pResult->addressY = addressY; + pResult->filter = filter; + pResult->group = group; + pResult->sRGB = sRGB; + pResult->pTexture->setTextureResource(MoveTemp(pResource)); + + return pResult; +} + +CesiumUtility::IntrusivePointer +loadTextureGameThreadPart( + CesiumGltf::Model& model, + LoadedTextureResult* pHalfLoadedTexture) { + if (pHalfLoadedTexture == nullptr) + return nullptr; + + CesiumUtility::IntrusivePointer pResult = + loadTextureGameThreadPart(pHalfLoadedTexture); + + if (pResult && pHalfLoadedTexture && pHalfLoadedTexture->textureIndex >= 0 && + size_t(pHalfLoadedTexture->textureIndex) < model.textures.size()) { + CesiumGltf::Texture& texture = + model.textures[pHalfLoadedTexture->textureIndex]; + ExtensionUnrealTexture& extension = + texture.addExtension(); + extension.pTexture = pHalfLoadedTexture->pTexture; + } + + return pHalfLoadedTexture->pTexture; +} + +CesiumUtility::IntrusivePointer +loadTextureGameThreadPart(LoadedTextureResult* pHalfLoadedTexture) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::LoadTexture) + + FCesiumTextureResourceUniquePtr& pTextureResource = + pHalfLoadedTexture->pTexture->getTextureResource(); + if (pTextureResource == nullptr) { + // Texture is already loaded (or unloadable). + return pHalfLoadedTexture->pTexture; + } + + UTexture2D* pTexture = CreateTexture2D(pHalfLoadedTexture); + if (pTexture == nullptr) { + return nullptr; + } + + if (pTextureResource) { + // Give the UTexture2D exclusive ownership of this FCesiumTextureResource. + pTexture->SetResource(pTextureResource.Release()); + + ENQUEUE_RENDER_COMMAND(Cesium_InitResource) + ([pTexture, pTextureResource = pTexture->GetResource()]( + FRHICommandListImmediate& RHICmdList) { + pTextureResource->SetTextureReference( + pTexture->TextureReference.TextureReferenceRHI); + pTextureResource->InitResource( + FRHICommandListImmediate::Get()); // Init Resource now requires a + // command list. + }); + } + + return pHalfLoadedTexture->pTexture; +} + +TextureAddress convertGltfWrapSToUnreal(int32_t wrapS) { + // glTF spec: "When undefined, a sampler with repeat wrapping and auto + // filtering should be used." + switch (wrapS) { + case CesiumGltf::Sampler::WrapS::CLAMP_TO_EDGE: + return TextureAddress::TA_Clamp; + case CesiumGltf::Sampler::WrapS::MIRRORED_REPEAT: + return TextureAddress::TA_Mirror; + case CesiumGltf::Sampler::WrapS::REPEAT: + default: + return TextureAddress::TA_Wrap; + } +} + +TextureAddress convertGltfWrapTToUnreal(int32_t wrapT) { + // glTF spec: "When undefined, a sampler with repeat wrapping and auto + // filtering should be used." + switch (wrapT) { + case CesiumGltf::Sampler::WrapT::CLAMP_TO_EDGE: + return TextureAddress::TA_Clamp; + case CesiumGltf::Sampler::WrapT::MIRRORED_REPEAT: + return TextureAddress::TA_Mirror; + case CesiumGltf::Sampler::WrapT::REPEAT: + default: + return TextureAddress::TA_Wrap; + } +} + +std::optional getPixelFormatForImageAsset( + const CesiumGltf::ImageAsset& imageCesium, + const std::optional overridePixelFormat) { + if (imageCesium.compressedPixelFormat != + CesiumGltf::GpuCompressedPixelFormat::NONE) { + switch (imageCesium.compressedPixelFormat) { + case CesiumGltf::GpuCompressedPixelFormat::ETC1_RGB: + return EPixelFormat::PF_ETC1; + break; + case CesiumGltf::GpuCompressedPixelFormat::ETC2_RGBA: + return EPixelFormat::PF_ETC2_RGBA; + break; + case CesiumGltf::GpuCompressedPixelFormat::BC1_RGB: + return EPixelFormat::PF_DXT1; + break; + case CesiumGltf::GpuCompressedPixelFormat::BC3_RGBA: + return EPixelFormat::PF_DXT5; + break; + case CesiumGltf::GpuCompressedPixelFormat::BC4_R: + return EPixelFormat::PF_BC4; + break; + case CesiumGltf::GpuCompressedPixelFormat::BC5_RG: + return EPixelFormat::PF_BC5; + break; + case CesiumGltf::GpuCompressedPixelFormat::BC7_RGBA: + return EPixelFormat::PF_BC7; + break; + case CesiumGltf::GpuCompressedPixelFormat::ASTC_4x4_RGBA: + return EPixelFormat::PF_ASTC_4x4; + break; + case CesiumGltf::GpuCompressedPixelFormat::PVRTC2_4_RGBA: + return EPixelFormat::PF_PVRTC2; + break; + case CesiumGltf::GpuCompressedPixelFormat::ETC2_EAC_R11: + return EPixelFormat::PF_ETC2_R11_EAC; + break; + case CesiumGltf::GpuCompressedPixelFormat::ETC2_EAC_RG11: + return EPixelFormat::PF_ETC2_RG11_EAC; + break; + default: + // Unsupported compressed texture format. + return std::nullopt; + }; + } else if (overridePixelFormat) { + return *overridePixelFormat; + } else { + switch (imageCesium.channels) { + case 1: + return PF_R8; + break; + case 2: + return PF_R8G8; + break; + case 3: + case 4: + default: + return PF_R8G8B8A8; + }; + } + + return std::nullopt; +} + +} // namespace CesiumTextureUtility diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureUtility.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureUtility.h new file mode 100644 index 0000000..a698968 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureUtility.h @@ -0,0 +1,202 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumAsync/SharedAssetDepot.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltf/Texture.h" +#include "CesiumMetadataValueType.h" +#include "CesiumTextureResource.h" +#include "Engine/Texture.h" +#include "Engine/Texture2D.h" +#include "Engine/TextureDefines.h" +#include "RHI.h" +#include "Runtime/Launch/Resources/Version.h" +#include "Templates/UniquePtr.h" +#include +#include + +namespace CesiumGltf { +struct ImageAsset; +struct Texture; +} // namespace CesiumGltf + +namespace CesiumTextureUtility { + +// A slightly roundabout way to a hold a UTexture2D. +// +// We can't let Unreal's garbage collector be exclusively responsible for the +// lifetime of our textures because it doesn't run often enough (and not at all +// in the Editor). And we also need shared ownership of UTexture2Ds when a tile +// is "upsampled" from its parent for raster overlays. So this class allows us +// to control the lifetime of a UTexture2D via reference counting. +// +// Yes, this means we're controlling the lifetime of a garbage collected +// `UTexture2D` object via reference counting. +// +// Instances of this class are created whenever we create a UTexture2D. A +// pointer to the instance is held in `LoadedTextureResult` as well as in a +// private extension added to the glTF `Texture` from which the UTexture2D was +// created. +struct ReferenceCountedUnrealTexture + : CesiumUtility::ReferenceCountedThreadSafe { + ReferenceCountedUnrealTexture() noexcept; + ~ReferenceCountedUnrealTexture() noexcept; + + // The texture game object, once it's created. + TObjectPtr getUnrealTexture() const; + void setUnrealTexture(const TObjectPtr& p); + + // The renderer / RHI FTextureResource holding the pixel data. + const FCesiumTextureResourceUniquePtr& getTextureResource() const; + FCesiumTextureResourceUniquePtr& getTextureResource(); + void setTextureResource(FCesiumTextureResourceUniquePtr&& p); + +private: + TObjectPtr _pUnrealTexture; + FCesiumTextureResourceUniquePtr _pTextureResource; +}; + +/** + * @brief Half-loaded Unreal texture with info on how to finish loading the + * texture on the game thread and render thread. + */ +struct LoadedTextureResult { + TextureAddress addressX; + TextureAddress addressY; + TextureFilter filter; + TextureGroup group; + bool sRGB{true}; + + // The index of the `CesiumGltf::Texture` instance with the glTF. Or -1 if + // this result wasn't created from a texture in a glTF. + int64_t textureIndex = -1; + + // The UTexture2D that has already been created, if any. + CesiumUtility::IntrusivePointer pTexture; +}; + +/** + * Does the asynchronous part of renderer resource preparation for a `Texture` + * in a glTF. Should be called in a worker thread. + * + * The `cesium.pixelData` will be removed from the image associated with the + * texture so that it can be passed to Unreal's renderer thread without copying + * it. + * + * @param model The glTF Model for which to load this texture. + * @param texture The glTF Texture to load. This parameter is non-const because + * a private extension will be added to this `Texture` in order to track the + * associated Unreal texture. + * @param sRGB True if the texture should be treated as sRGB; false if it should + * be treated as linear. + * {@link CesiumGltf::Model::images}, and all pointers must be initialized to + * nullptr before the first call to `loadTextureFromModelAnyThreadPart` during + * the glTF load process. + */ +TUniquePtr loadTextureFromModelAnyThreadPart( + CesiumGltf::Model& model, + CesiumGltf::Texture& texture, + bool sRGB); + +/** + * Does the asynchronous part of renderer resource preparation for a glTF + * `Image` with the given `Sampler` settings. + * + * The `cesium.pixelData` will be removed from the image so that it can be + * passed to Unreal's renderer thread without copying it. + * + * @param image The glTF image for each to create a texture. + * @param sampler The sampler settings to use with the texture. + * @param sRGB True if the texture should be treated as sRGB; false if it should + * be treated as linear. + */ +TUniquePtr loadTextureFromImageAndSamplerAnyThreadPart( + CesiumGltf::ImageAsset& image, + const CesiumGltf::Sampler& sampler, + bool sRGB); + +/** + * @brief Does the asynchronous part of renderer resource preparation for + * a texture.The given image _must_ be prepared before calling this method by + * calling {@link ExtensionImageAssetUnreal::getOrCreate} and then waiting + * for {@link ExtensionImageAssetUnreal::getFuture} to resolve. This method + * should be called in a background thread. + * + * @param image The image. + * @param addressX The X addressing mode. + * @param addressY The Y addressing mode. + * @param filter The sampler filtering to use for this texture. + * @param useMipMapsIfAvailable true to use this image's mipmaps for sampling, + * if they exist; false to ignore any mipmaps that might be present. + * @param group The texture group of this texture. + * @param sRGB Whether this texture uses a sRGB color space. + * @param overridePixelFormat The explicit pixel format to use. If std::nullopt, + * the pixel format is inferred from the image. + * @return The loaded texture. + */ +TUniquePtr loadTextureAnyThreadPart( + CesiumGltf::ImageAsset& image, + TextureAddress addressX, + TextureAddress addressY, + TextureFilter filter, + bool useMipMapsIfAvailable, + TextureGroup group, + bool sRGB, + std::optional overridePixelFormat); + +/** + * @brief Does the main-thread part of render resource preparation for this + * image and queues up any required render-thread tasks to finish preparing the + * image. + * + * @param model The model with which this texture is associated. This is used to + * store a pointer to the created texture in an extension on the glTF texture so + * that it can be reused later. + * @param pHalfLoadedTexture The half-loaded renderer texture. + * @return The Unreal texture result. + */ +CesiumUtility::IntrusivePointer +loadTextureGameThreadPart( + CesiumGltf::Model& model, + LoadedTextureResult* pHalfLoadedTexture); + +/** + * @brief Does the main-thread part of render resource preparation for this + * image and queues up any required render-thread tasks to finish preparing the + * image. + * + * @param pHalfLoadedTexture The half-loaded renderer texture. + * @return The Unreal texture result. + */ +CesiumUtility::IntrusivePointer +loadTextureGameThreadPart(LoadedTextureResult* pHalfLoadedTexture); + +/** + * @brief Convert a glTF {@link CesiumGltf::Sampler::WrapS} value to an Unreal + * `TextureAddress` value. + * + * @param wrapS The glTF wrapS value. + * @returns The Unreal equivalent, or `TextureAddress::TA_Wrap` if the glTF + * value is unknown or invalid. + */ +TextureAddress convertGltfWrapSToUnreal(int32_t wrapS); + +/** + * @brief Convert a glTF {@link CesiumGltf::Sampler::WrapT} value to an Unreal + * `TextureAddress` value. + * + * @param wrapT The glTF wrapT value. + * @returns The Unreal equivalent, or `TextureAddress::TA_Wrap` if the glTF + * value is unknown or invalid. + */ +TextureAddress convertGltfWrapTToUnreal(int32_t wrapT); + +std::optional getPixelFormatForImageAsset( + const CesiumGltf::ImageAsset& imageCesium, + const std::optional overridePixelFormat); + +std::optional +getUnrealTextureFromGltfTexture(const CesiumGltf::Texture& texture); + +} // namespace CesiumTextureUtility diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTile.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTile.cpp new file mode 100644 index 0000000..6e6254e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTile.cpp @@ -0,0 +1,34 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumTile.h" +#include "CalcBounds.h" +#include "CesiumTransforms.h" +#include "Components/PrimitiveComponent.h" +#include "VecMath.h" + +bool UCesiumTile::TileBoundsOverlapsPrimitive( + const UPrimitiveComponent* Other) const { + if (IsValid(Other)) { + return Bounds.GetBox().Intersect(Other->Bounds.GetBox()) && + Bounds.GetSphere().Intersects(Other->Bounds.GetSphere()); + } else { + return false; + } +} + +bool UCesiumTile::PrimitiveBoxFullyContainsTileBounds( + const UPrimitiveComponent* Other) const { + if (IsValid(Other)) { + return Bounds.GetBox().Intersect(Other->Bounds.GetBox()) || + Bounds.GetSphere().Intersects(Other->Bounds.GetSphere()); + } else { + return false; + } +} + +FBoxSphereBounds UCesiumTile::CalcBounds(const FTransform& LocalToWorld) const { + FBoxSphereBounds bounds = std::visit( + CalcBoundsOperation{LocalToWorld, this->_tileTransform}, + _tileBounds); + return bounds; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileExcluder.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileExcluder.cpp new file mode 100644 index 0000000..3c09ae7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileExcluder.cpp @@ -0,0 +1,114 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumTileExcluder.h" +#include "Cesium3DTileset.h" +#include "CesiumLifetime.h" +#include "CesiumTileExcluderAdapter.h" + +using namespace Cesium3DTilesSelection; + +namespace { +auto findExistingExcluder( + const std::vector>& excluders, + const CesiumTileExcluderAdapter& excluder) { + return std::find_if( + excluders.begin(), + excluders.end(), + [&excluder](const std::shared_ptr& pCandidate) { + return pCandidate.get() == &excluder; + }); +} +} // namespace + +UCesiumTileExcluder::UCesiumTileExcluder( + const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) { + PrimaryComponentTick.bCanEverTick = false; + bAutoActivate = true; +} + +void UCesiumTileExcluder::AddToTileset() { + ACesium3DTileset* CesiumTileset = this->GetOwner(); + if (!CesiumTileset) + return; + Tileset* pTileset = CesiumTileset->GetTileset(); + if (!pTileset) + return; + + std::vector>& excluders = + pTileset->getOptions().excluders; + + auto it = findExistingExcluder(excluders, *this->pExcluderAdapter); + if (it != excluders.end()) + return; + + CesiumTile = NewObject(this); + CesiumTile->SetVisibility(false); + CesiumTile->SetMobility(EComponentMobility::Movable); + CesiumTile->SetFlags( + RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + CesiumTile->SetupAttachment(CesiumTileset->GetRootComponent()); + CesiumTile->RegisterComponent(); + + auto pAdapter = std::make_shared( + TWeakObjectPtr(this), + CesiumTileset->ResolveGeoreference(), + CesiumTile); + pExcluderAdapter = pAdapter.get(); + excluders.push_back(std::move(pAdapter)); +} + +void UCesiumTileExcluder::RemoveFromTileset() { + ACesium3DTileset* CesiumTileset = this->GetOwner(); + if (!CesiumTileset) + return; + Tileset* pTileset = CesiumTileset->GetTileset(); + if (!pTileset) + return; + + std::vector>& excluders = + pTileset->getOptions().excluders; + + auto it = findExistingExcluder(excluders, *pExcluderAdapter); + if (it != excluders.end()) { + excluders.erase(it); + } + + CesiumLifetime::destroyComponentRecursively(CesiumTile); +} + +void UCesiumTileExcluder::Refresh() { + this->RemoveFromTileset(); + this->AddToTileset(); +} + +bool UCesiumTileExcluder::ShouldExclude_Implementation( + const UCesiumTile* TileObject) { + return false; +} + +void UCesiumTileExcluder::Activate(bool bReset) { + Super::Activate(bReset); + this->AddToTileset(); +} + +void UCesiumTileExcluder::Deactivate() { + Super::Deactivate(); + this->RemoveFromTileset(); +} + +void UCesiumTileExcluder::OnComponentDestroyed(bool bDestroyingHierarchy) { + this->RemoveFromTileset(); + Super::OnComponentDestroyed(bDestroyingHierarchy); +} + +#if WITH_EDITOR +// Called when properties are changed in the editor +void UCesiumTileExcluder::PostEditChangeProperty( + FPropertyChangedEvent& PropertyChangedEvent) { + Super::PostEditChangeProperty(PropertyChangedEvent); + + this->RemoveFromTileset(); + this->AddToTileset(); +} +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileExcluderAdapter.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileExcluderAdapter.cpp new file mode 100644 index 0000000..c6a9a6b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileExcluderAdapter.cpp @@ -0,0 +1,36 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumTileExcluderAdapter.h" +#include "Cesium3DTilesSelection/Tile.h" +#include "CesiumGeoreference.h" +#include "VecMath.h" + +bool CesiumTileExcluderAdapter::shouldExclude( + const Cesium3DTilesSelection::Tile& tile) const noexcept { + if (!this->IsExcluderValid) { + return false; + } + Tile->_tileBounds = tile.getBoundingVolume(); + Tile->UpdateBounds(); + return Excluder->ShouldExclude(Tile); +} + +void CesiumTileExcluderAdapter::startNewFrame() noexcept { + if (!Excluder.IsValid() || !IsValid(Tile) || !IsValid(Georeference)) { + IsExcluderValid = false; + return; + } + + IsExcluderValid = true; + Tile->_tileTransform = VecMath::createMatrix4D( + Georeference->ComputeUnrealToEarthCenteredEarthFixedTransformation()); +} + +CesiumTileExcluderAdapter::CesiumTileExcluderAdapter( + TWeakObjectPtr pExcluder, + ACesiumGeoreference* pGeoreference, + UCesiumTile* pTile) + : Excluder(pExcluder), + Tile(pTile), + Georeference(pGeoreference), + IsExcluderValid(true){}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileExcluderAdapter.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileExcluderAdapter.h new file mode 100644 index 0000000..1b03864 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileExcluderAdapter.h @@ -0,0 +1,30 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once +#include "CesiumTile.h" +#include "CesiumTileExcluder.h" +#include + +class ACesiumGeoreference; + +namespace Cesium3DTilesSelection { +class Tile; +} + +class CesiumTileExcluderAdapter : public Cesium3DTilesSelection::ITileExcluder { + virtual bool shouldExclude( + const Cesium3DTilesSelection::Tile& tile) const noexcept override; + virtual void startNewFrame() noexcept override; + +private: + TWeakObjectPtr Excluder; + UCesiumTile* Tile; + ACesiumGeoreference* Georeference; + bool IsExcluderValid; + +public: + CesiumTileExcluderAdapter( + TWeakObjectPtr pExcluder, + ACesiumGeoreference* pGeoreference, + UCesiumTile* pTile); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileMapServiceRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileMapServiceRasterOverlay.cpp new file mode 100644 index 0000000..8f0f7b2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileMapServiceRasterOverlay.cpp @@ -0,0 +1,26 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumTileMapServiceRasterOverlay.h" +#include "CesiumRasterOverlays/TileMapServiceRasterOverlay.h" +#include "CesiumRuntime.h" + +std::unique_ptr +UCesiumTileMapServiceRasterOverlay::CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options) { + if (this->Url.IsEmpty()) { + // Don't create an overlay with an empty URL. + return nullptr; + } + + CesiumRasterOverlays::TileMapServiceRasterOverlayOptions tmsOptions; + if (MaximumLevel > MinimumLevel && bSpecifyZoomLevels) { + tmsOptions.minimumLevel = MinimumLevel; + tmsOptions.maximumLevel = MaximumLevel; + } + return std::make_unique( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + TCHAR_TO_UTF8(*this->Url), + std::vector(), + tmsOptions, + options); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTransforms.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTransforms.cpp new file mode 100644 index 0000000..a82afd9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTransforms.cpp @@ -0,0 +1,30 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumTransforms.h" + +const double CesiumTransforms::metersToCentimeters = 100.0; +const double CesiumTransforms::centimetersToMeters = 0.01; + +// Scale Cesium's meters up to Unreal's centimeters. +const glm::dmat4x4 CesiumTransforms::scaleToUnrealWorld = + glm::dmat4x4(glm::dmat3x3(metersToCentimeters)); + +// Scale down Unreal's centimeters into Cesium's meters. +const glm::dmat4x4 CesiumTransforms::scaleToCesium = + glm::dmat4x4(glm::dmat3x3(centimetersToMeters)); + +// We're initializing with a static function instead of inline to avoid an +// internal compiler error in MSVC v14.27.29110. +static glm::dmat4 createUnrealToOrFromCesium() { + return glm::dmat4x4( + glm::dvec4(1.0, 0.0, 0.0, 0.0), + glm::dvec4(0.0, -1.0, 0.0, 0.0), + glm::dvec4(0.0, 0.0, 1.0, 0.0), + glm::dvec4(0.0, 0.0, 0.0, 1.0)); +} + +// Transform Cesium's right-handed, Z-up coordinate system to Unreal's +// left-handed, Z-up coordinate system by inverting the Y coordinate. This same +// transformation can also go the other way. +const glm::dmat4x4 CesiumTransforms::unrealToOrFromCesium = + createUnrealToOrFromCesium(); \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTransforms.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTransforms.h new file mode 100644 index 0000000..c807f4a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTransforms.h @@ -0,0 +1,39 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include + +/** + * Constants useful for transformation between Cesium and Unreal Engine + * coordinate systems. + */ +class CesiumTransforms { +public: + /** + * The constant to multiply to transform meters to centimeters (100.0). + */ + static const double metersToCentimeters; + + /** + * The constant to multiply to transform centimeters to meters (0.01). + */ + static const double centimetersToMeters; + + /** + * A matrix to scale Cesium's meters up to Unreal's centimeters. + */ + static const glm::dmat4x4 scaleToUnrealWorld; + + /** + * A matrix to scale down Unreal's centimeters into Cesium's meters. + */ + static const glm::dmat4x4 scaleToCesium; + + /** + * A matrix to transform Cesium's right-handed, Z-up coordinate system to + * Unreal's left-handed, Z-up coordinate system by inverting the Y coordinate. + * This same transformation can also go the other way. + */ + static const glm::dmat4x4 unrealToOrFromCesium; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumViewExtension.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumViewExtension.cpp new file mode 100644 index 0000000..04a8978 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumViewExtension.cpp @@ -0,0 +1,208 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumViewExtension.h" + +#include "Cesium3DTileset.h" +#include "CesiumCommon.h" +#include "Runtime/Launch/Resources/Version.h" + +using namespace Cesium3DTilesSelection; + +CesiumViewExtension::CesiumViewExtension(const FAutoRegister& autoRegister) + : FSceneViewExtensionBase(autoRegister) {} + +CesiumViewExtension::~CesiumViewExtension() = default; + +TileOcclusionState CesiumViewExtension::getPrimitiveOcclusionState( + const FPrimitiveComponentId& id, + bool previouslyOccluded, + float frameTimeCutoff) const { + if (_currentOcclusionResults.occlusionResultsByView.size() == 0) { + return TileOcclusionState::OcclusionUnavailable; + } + + bool isOccluded = false; + bool historyMissing = false; + + for (const SceneViewOcclusionResults& viewOcclusionResults : + _currentOcclusionResults.occlusionResultsByView) { + const PrimitiveOcclusionResult* pOcclusionResult = + viewOcclusionResults.PrimitiveOcclusionResults.Find(id); + + if (pOcclusionResult && + pOcclusionResult->LastConsideredTime >= frameTimeCutoff) { + if (!pOcclusionResult->OcclusionStateWasDefiniteLastFrame) { + return TileOcclusionState::OcclusionUnavailable; + } + + if (previouslyOccluded) { + if (pOcclusionResult->LastPixelsPercentage > 0.01f) { + return TileOcclusionState::NotOccluded; + } + } else if (!pOcclusionResult->WasOccludedLastFrame) { + return TileOcclusionState::NotOccluded; + } + + isOccluded = true; + } else { + historyMissing = true; + } + } + + if (historyMissing) { + return TileOcclusionState::OcclusionUnavailable; + } else if (isOccluded) { + return TileOcclusionState::Occluded; + } else { + return TileOcclusionState::NotOccluded; + } +} + +void CesiumViewExtension::SetupViewFamily(FSceneViewFamily& InViewFamily) {} + +void CesiumViewExtension::SetupView( + FSceneViewFamily& InViewFamily, + FSceneView& InView) {} + +void CesiumViewExtension::BeginRenderViewFamily( + FSceneViewFamily& InViewFamily) { + if (!this->_isEnabled) + return; + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::DequeueOcclusionResults) + if (!_occlusionResultsQueue.IsEmpty()) { + // Recycle the current occlusion results. + for (SceneViewOcclusionResults& occlusionResults : + _currentOcclusionResults.occlusionResultsByView) { + occlusionResults.PrimitiveOcclusionResults.Reset(); + _recycledOcclusionResultSets.Enqueue( + std::move(occlusionResults.PrimitiveOcclusionResults)); + } + _currentOcclusionResults = {}; + + // Update occlusion results from the queue. + _currentOcclusionResults = std::move(*_occlusionResultsQueue.Peek()); + _occlusionResultsQueue.Pop(); + } +} + +namespace { + +const TSet& +getOcclusionHistorySet(const FSceneViewState* pViewState) { + return pViewState->Occlusion.PrimitiveOcclusionHistorySet; +} + +} // namespace + +void CesiumViewExtension::PostRenderViewFamily_RenderThread( + FRDGBuilder& GraphBuilder, + FSceneViewFamily& InViewFamily) { + if (!this->_isEnabled) + return; + + if (_frameNumber_renderThread != InViewFamily.FrameNumber) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EnqueueAggregatedOcclusion) + if (_frameNumber_renderThread != -1) { + _occlusionResultsQueue.Enqueue( + std::move(_currentAggregation_renderThread)); + _currentAggregation_renderThread = {}; + } + + _frameNumber_renderThread = InViewFamily.FrameNumber; + } + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::AggregateOcclusionForViewFamily) + for (const FSceneView* pView : InViewFamily.Views) { + if (pView == nullptr || pView->State == nullptr) + continue; + + const FSceneViewState* pViewState = pView->State->GetConcreteViewState(); + if (pViewState && getOcclusionHistorySet(pViewState).Num()) { + SceneViewOcclusionResults& occlusionResults = + _currentAggregation_renderThread.occlusionResultsByView + .emplace_back(); + // Do we actually need the view? + occlusionResults.pView = pView; + + if (!_recycledOcclusionResultSets.IsEmpty()) { + // Recycle a previously allocated occlusion history set, if one is + // available. + occlusionResults.PrimitiveOcclusionResults = + std::move(*_recycledOcclusionResultSets.Peek()); + _recycledOcclusionResultSets.Pop(); + } else { + // If no previously-allocated set exists, just allocate a new one. It + // will be recycled later. + } + + occlusionResults.PrimitiveOcclusionResults.Reserve( + getOcclusionHistorySet(pViewState).Num()); + for (const auto& element : getOcclusionHistorySet(pViewState)) { + occlusionResults.PrimitiveOcclusionResults.Emplace(element); + } + + // Unreal will not execute occlusion queries that get frustum culled in a + // particular view, leaving the occlusion results indefinite. And by just + // looking at the PrimitiveOcclusionHistorySet, we can't distinguish + // occlusion queries that haven't completed "yet" from occlusion queries + // that were culled. So here we detect primitives that have been + // conclusively proven to be not visible (outside the view frustum) and + // also mark them definitely occluded. + FScene* pScene = InViewFamily.Scene->GetRenderScene(); + if (pView->bIsViewInfo && pScene != nullptr) { + const FViewInfo* pViewInfo = static_cast(pView); + const FSceneBitArray& visibility = pViewInfo->PrimitiveVisibilityMap; + auto& occlusion = occlusionResults.PrimitiveOcclusionResults; + + const uint32 PrimitiveCount = pScene->Primitives.Num(); + for (uint32 i = 0; i < PrimitiveCount; ++i) { + FPrimitiveSceneInfo* pSceneInfo = pScene->Primitives[i]; + if (pSceneInfo == nullptr) + continue; + + bool setOcclusionState = false; + bool isOccluded = false; + + // Unreal will never compute occlusion for primitives that are + // selected in the Editor. So treat these as unoccluded. +#if WITH_EDITOR + if (GIsEditor) { + if (pScene->PrimitivesSelected[i]) { + setOcclusionState = true; + isOccluded = false; + } + } +#endif + + // If this primitive is not visible at all (and also not selected!), + // treat is as occluded. + if (!setOcclusionState && !visibility[i]) { + setOcclusionState = true; + isOccluded = true; + } + + if (setOcclusionState) { + const PrimitiveOcclusionResult* pOcclusionResult = + occlusion.Find(pSceneInfo->PrimitiveComponentId); + if (!pOcclusionResult || pOcclusionResult->LastConsideredTime < + pViewState->LastRenderTime) { + // No valid occlusion history for this culled primitive, so create + // it. + occlusion.Emplace(PrimitiveOcclusionResult( + pSceneInfo->PrimitiveComponentId, + pViewState->LastRenderTime, + isOccluded ? 0.0f : 100.0f, + true, + isOccluded)); + } + } + } + } + } + } +} + +void CesiumViewExtension::SetEnabled(bool enabled) { + this->_isEnabled = enabled; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumViewExtension.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumViewExtension.h new file mode 100644 index 0000000..df87825 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumViewExtension.h @@ -0,0 +1,116 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Containers/Queue.h" +#include "Containers/Set.h" +#include "Runtime/Renderer/Private/ScenePrivate.h" +#include "SceneTypes.h" +#include "SceneView.h" +#include "SceneViewExtension.h" +#include +#include +#include + +class ACesium3DTileset; + +class CesiumViewExtension : public FSceneViewExtensionBase { +private: + // Occlusion results for a single view. + struct PrimitiveOcclusionResult { + PrimitiveOcclusionResult( + const FPrimitiveComponentId primitiveId, + float lastConsideredTime, + float lastPixelsPercentage, + bool occlusionStateWasDefiniteLastFrame, + bool wasOccludedLastFrame) + : PrimitiveId(primitiveId), + LastConsideredTime(lastConsideredTime), + LastPixelsPercentage(lastPixelsPercentage), + OcclusionStateWasDefiniteLastFrame( + occlusionStateWasDefiniteLastFrame), + WasOccludedLastFrame(wasOccludedLastFrame) {} + + PrimitiveOcclusionResult(const FPrimitiveOcclusionHistory& renderer) + : PrimitiveId(renderer.PrimitiveId), + LastConsideredTime(renderer.LastConsideredTime), + LastPixelsPercentage(renderer.LastPixelsPercentage), + OcclusionStateWasDefiniteLastFrame( + renderer.OcclusionStateWasDefiniteLastFrame), + WasOccludedLastFrame(renderer.WasOccludedLastFrame) {} + + FPrimitiveComponentId PrimitiveId; + float LastConsideredTime; + float LastPixelsPercentage; + bool OcclusionStateWasDefiniteLastFrame; + bool WasOccludedLastFrame; + }; + + // Defines how PrimitiveOcclusionResult is stored in a TSet + struct PrimitiveOcclusionResultKeyFuncs + : BaseKeyFuncs { + typedef FPrimitiveComponentId KeyInitType; + + static KeyInitType GetSetKey(const PrimitiveOcclusionResult& Element) { + return Element.PrimitiveId; + } + + static bool Matches(KeyInitType A, KeyInitType B) { return A == B; } + + static uint32 GetKeyHash(KeyInitType Key) { + return GetTypeHash(Key.PrimIDValue); + } + }; + + // The occlusion results for a single view. + struct SceneViewOcclusionResults { + const FSceneView* pView = nullptr; + TSet + PrimitiveOcclusionResults{}; + }; + + // A collection of occlusion results by view. + struct AggregatedOcclusionUpdate { + std::vector occlusionResultsByView{}; + }; + + // The current collection of occlusion results for this frame. + AggregatedOcclusionUpdate _currentAggregation_renderThread{}; + AggregatedOcclusionUpdate _currentOcclusionResults{}; + + // A queue to pass occlusion results from the render thread to the game + // thread. + TQueue _occlusionResultsQueue; + + // A queue to recycle the previously-allocated occlusion result sets. The + // game thread recycles the sets by moving them into the queue and sending + // them back to the render thread. + TQueue< + TSet, + EQueueMode::Spsc> + _recycledOcclusionResultSets; + + // The last known frame number. This is used to determine when an occlusion + // results aggregation is complete. + int64_t _frameNumber_renderThread = -1; + + std::atomic _isEnabled = false; + +public: + CesiumViewExtension(const FAutoRegister& autoRegister); + ~CesiumViewExtension(); + + Cesium3DTilesSelection::TileOcclusionState getPrimitiveOcclusionState( + const FPrimitiveComponentId& id, + bool previouslyOccluded, + float frameTimeCutoff) const; + + void SetupViewFamily(FSceneViewFamily& InViewFamily) override; + void SetupView(FSceneViewFamily& InViewFamily, FSceneView& InView) override; + void BeginRenderViewFamily(FSceneViewFamily& InViewFamily) override; + void PostRenderViewFamily_RenderThread( + FRDGBuilder& GraphBuilder, + FSceneViewFamily& InViewFamily) override; + + void SetEnabled(bool enabled); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumWebMapServiceRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumWebMapServiceRasterOverlay.cpp new file mode 100644 index 0000000..82da5da --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumWebMapServiceRasterOverlay.cpp @@ -0,0 +1,30 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumWebMapServiceRasterOverlay.h" +#include "Algo/Transform.h" +#include "CesiumRasterOverlays/WebMapServiceRasterOverlay.h" +#include "CesiumRuntime.h" + +std::unique_ptr +UCesiumWebMapServiceRasterOverlay::CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options) { + if (this->BaseUrl.IsEmpty()) { + // Don't create an overlay with an empty base URL. + return nullptr; + } + + CesiumRasterOverlays::WebMapServiceRasterOverlayOptions wmsOptions; + if (MaximumLevel > MinimumLevel) { + wmsOptions.minimumLevel = MinimumLevel; + wmsOptions.maximumLevel = MaximumLevel; + } + wmsOptions.layers = TCHAR_TO_UTF8(*Layers); + wmsOptions.tileWidth = TileWidth; + wmsOptions.tileHeight = TileHeight; + return std::make_unique( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + TCHAR_TO_UTF8(*this->BaseUrl), + std::vector(), + wmsOptions, + options); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumWebMapTileServiceRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumWebMapTileServiceRasterOverlay.cpp new file mode 100644 index 0000000..ecefeca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumWebMapTileServiceRasterOverlay.cpp @@ -0,0 +1,112 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumWebMapTileServiceRasterOverlay.h" + +#include "CesiumCustomVersion.h" +#include "CesiumGeometry/QuadtreeTilingScheme.h" +#include "CesiumGeospatial/GlobeRectangle.h" +#include "CesiumGeospatial/Projection.h" +#include "CesiumRasterOverlays/WebMapTileServiceRasterOverlay.h" + +#include "CesiumRuntime.h" + +void UCesiumWebMapTileServiceRasterOverlay::Serialize(FArchive& Ar) { + Super::Serialize(Ar); + + Ar.UsingCustomVersion(FCesiumCustomVersion::GUID); + + const int32 CesiumVersion = Ar.CustomVer(FCesiumCustomVersion::GUID); + + if (CesiumVersion < FCesiumCustomVersion::WebMapTileServiceProjectionAsEnum) { + // In previous versions, the projection of the overlay was controlled by + // boolean, rather than being explicitly specified by an enum. + this->Projection = + this->UseWebMercatorProjection_DEPRECATED + ? ECesiumWebMapTileServiceRasterOverlayProjection::WebMercator + : ECesiumWebMapTileServiceRasterOverlayProjection::Geographic; + } +} + +std::unique_ptr +UCesiumWebMapTileServiceRasterOverlay::CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options) { + if (this->BaseUrl.IsEmpty()) { + // Don't create an overlay with an empty base URL. + return nullptr; + } + + CesiumRasterOverlays::WebMapTileServiceRasterOverlayOptions wmtsOptions; + if (!Style.IsEmpty()) { + wmtsOptions.style = TCHAR_TO_UTF8(*this->Style); + } + if (!Layer.IsEmpty()) { + wmtsOptions.layer = TCHAR_TO_UTF8(*this->Layer); + } + if (!Format.IsEmpty()) { + wmtsOptions.format = TCHAR_TO_UTF8(*this->Format); + } + if (!TileMatrixSetID.IsEmpty()) { + wmtsOptions.tileMatrixSetID = TCHAR_TO_UTF8(*this->TileMatrixSetID); + } + + if (bSpecifyZoomLevels && MaximumLevel > MinimumLevel) { + wmtsOptions.minimumLevel = MinimumLevel; + wmtsOptions.maximumLevel = MaximumLevel; + } + + wmtsOptions.tileWidth = this->TileWidth; + wmtsOptions.tileHeight = this->TileHeight; + + const CesiumGeospatial::Ellipsoid& ellipsoid = options.ellipsoid; + + if (this->Projection == + ECesiumWebMapTileServiceRasterOverlayProjection::Geographic) { + wmtsOptions.projection = CesiumGeospatial::GeographicProjection(ellipsoid); + } else { + wmtsOptions.projection = CesiumGeospatial::WebMercatorProjection(ellipsoid); + } + + if (bSpecifyTilingScheme) { + CesiumGeospatial::GlobeRectangle globeRectangle = + CesiumGeospatial::GlobeRectangle::fromDegrees( + RectangleWest, + RectangleSouth, + RectangleEast, + RectangleNorth); + CesiumGeometry::Rectangle coverageRectangle = + CesiumGeospatial::projectRectangleSimple( + *wmtsOptions.projection, + globeRectangle); + wmtsOptions.coverageRectangle = coverageRectangle; + wmtsOptions.tilingScheme = CesiumGeometry::QuadtreeTilingScheme( + coverageRectangle, + RootTilesX, + RootTilesY); + } + + if (bSpecifyTileMatrixSetLabels) { + if (!TileMatrixSetLabels.IsEmpty()) { + std::vector labels; + for (const auto& label : this->TileMatrixSetLabels) { + labels.emplace_back(TCHAR_TO_UTF8(*label)); + } + wmtsOptions.tileMatrixLabels = labels; + } + } else { + if (!TileMatrixSetLabelPrefix.IsEmpty()) { + std::vector labels; + for (size_t level = 0; level <= 25; ++level) { + FString label(TileMatrixSetLabelPrefix); + label.AppendInt(level); + labels.emplace_back(TCHAR_TO_UTF8(*label)); + } + wmtsOptions.tileMatrixLabels = labels; + } + } + return std::make_unique( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + TCHAR_TO_UTF8(*this->BaseUrl), + std::vector(), + wmtsOptions, + options); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumWgs84Ellipsoid.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumWgs84Ellipsoid.cpp new file mode 100644 index 0000000..3ca1c06 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumWgs84Ellipsoid.cpp @@ -0,0 +1,59 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumWgs84Ellipsoid.h" +#include "CesiumEllipsoidFunctions.h" +#include "VecMath.h" +#include + +using namespace CesiumGeospatial; +using namespace CesiumUtility; + +FVector UCesiumWgs84Ellipsoid::GetRadii() { + const glm::dvec3& radii = Ellipsoid::WGS84.getRadii(); + return VecMath::createVector(radii); +} + +double UCesiumWgs84Ellipsoid::GetMaximumRadius() { + return Ellipsoid::WGS84.getRadii().x; +} + +double UCesiumWgs84Ellipsoid::GetMinimumRadius() { + return Ellipsoid::WGS84.getRadii().z; +} + +FVector UCesiumWgs84Ellipsoid::ScaleToGeodeticSurface( + const FVector& EarthCenteredEarthFixedPosition) { + return CesiumEllipsoidFunctions::ScaleToGeodeticSurface( + Ellipsoid::WGS84, + EarthCenteredEarthFixedPosition); +} + +FVector UCesiumWgs84Ellipsoid::GeodeticSurfaceNormal( + const FVector& EarthCenteredEarthFixedPosition) { + return CesiumEllipsoidFunctions::GeodeticSurfaceNormal( + Ellipsoid::WGS84, + EarthCenteredEarthFixedPosition); +} + +FVector UCesiumWgs84Ellipsoid::LongitudeLatitudeHeightToEarthCenteredEarthFixed( + const FVector& LongitudeLatitudeHeight) { + return CesiumEllipsoidFunctions:: + LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + Ellipsoid::WGS84, + LongitudeLatitudeHeight); +} + +FVector UCesiumWgs84Ellipsoid::EarthCenteredEarthFixedToLongitudeLatitudeHeight( + const FVector& EarthCenteredEarthFixedPosition) { + return CesiumEllipsoidFunctions:: + EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight( + Ellipsoid::WGS84, + EarthCenteredEarthFixedPosition); +} + +FMatrix UCesiumWgs84Ellipsoid::EastNorthUpToEarthCenteredEarthFixed( + const FVector& EarthCenteredEarthFixedPosition) { + return CesiumEllipsoidFunctions::EastNorthUpToEllipsoidCenteredEllipsoidFixed( + Ellipsoid::WGS84, + EarthCenteredEarthFixedPosition); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CreateGltfOptions.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CreateGltfOptions.h new file mode 100644 index 0000000..c809652 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CreateGltfOptions.h @@ -0,0 +1,67 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumEncodedMetadataComponent.h" +#include "CesiumGltf/Mesh.h" +#include "CesiumGltf/MeshPrimitive.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltf/Node.h" +#include "LoadGltfResult.h" + +// TODO: internal documentation +namespace CreateGltfOptions { +struct CreateModelOptions { + const FCesiumFeaturesMetadataDescription* pFeaturesMetadataDescription = + nullptr; + CesiumGltf::Model* pModel = nullptr; + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + const FMetadataDescription* pEncodedMetadataDescription_DEPRECATED = nullptr; + PRAGMA_ENABLE_DEPRECATION_WARNINGS + bool alwaysIncludeTangents = false; + bool createPhysicsMeshes = true; + bool ignoreKhrMaterialsUnlit = false; + + Cesium3DTilesSelection::TileLoadResult tileLoadResult; + +public: + CreateModelOptions(Cesium3DTilesSelection::TileLoadResult&& tileLoadResult_) + : tileLoadResult(std::move(tileLoadResult_)) { + pModel = std::get_if(&this->tileLoadResult.contentKind); + } + + CreateModelOptions(CreateModelOptions&& other) + : pFeaturesMetadataDescription(other.pFeaturesMetadataDescription), + pEncodedMetadataDescription_DEPRECATED( + other.pEncodedMetadataDescription_DEPRECATED), + alwaysIncludeTangents(other.alwaysIncludeTangents), + createPhysicsMeshes(other.createPhysicsMeshes), + ignoreKhrMaterialsUnlit(other.ignoreKhrMaterialsUnlit), + tileLoadResult(std::move(other.tileLoadResult)) { + pModel = std::get_if(&this->tileLoadResult.contentKind); + } + + CreateModelOptions(const CreateModelOptions&) = delete; + CreateModelOptions& operator=(const CreateModelOptions&) = delete; + CreateModelOptions& operator=(CreateModelOptions&&) = delete; +}; + +struct CreateNodeOptions { + const CreateModelOptions* pModelOptions = nullptr; + const LoadGltfResult::LoadModelResult* pHalfConstructedModelResult = nullptr; + const CesiumGltf::Node* pNode = nullptr; +}; + +struct CreateMeshOptions { + const CreateNodeOptions* pNodeOptions = nullptr; + const LoadGltfResult::LoadNodeResult* pHalfConstructedNodeResult = nullptr; + int32_t meshIndex = -1; +}; + +struct CreatePrimitiveOptions { + const CreateMeshOptions* pMeshOptions = nullptr; + const LoadGltfResult::LoadMeshResult* pHalfConstructedMeshResult = nullptr; + int32_t primitiveIndex = -1; +}; +} // namespace CreateGltfOptions diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.cpp new file mode 100644 index 0000000..df3e402 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.cpp @@ -0,0 +1,114 @@ +#include "ExtensionImageAssetUnreal.h" +#include "CesiumRuntime.h" +#include "CesiumTextureUtility.h" +#include +#include + +using namespace CesiumAsync; +using namespace CesiumGltfReader; + +namespace { + +std::mutex createExtensionMutex; + +std::pair>> +getOrCreateImageFuture( + const AsyncSystem& asyncSystem, + CesiumGltf::ImageAsset& imageCesium); + +} // namespace + +/*static*/ const ExtensionImageAssetUnreal& +ExtensionImageAssetUnreal::getOrCreate( + const CesiumAsync::AsyncSystem& asyncSystem, + CesiumGltf::ImageAsset& imageCesium, + bool sRGB, + bool needsMipMaps, + const std::optional& overridePixelFormat) { + auto [extension, maybePromise] = + getOrCreateImageFuture(asyncSystem, imageCesium); + if (!maybePromise) { + // Another thread is already working on this image. + return extension; + } + + // Proceed to load the image in this thread. + TUniquePtr pResource = + FCesiumTextureResource::CreateNew( + imageCesium, + TextureGroup::TEXTUREGROUP_World, + overridePixelFormat, + TextureFilter::TF_Default, + TextureAddress::TA_Clamp, + TextureAddress::TA_Clamp, + sRGB, + needsMipMaps); + + extension._pTextureResource = + MakeShareable(pResource.Release(), [](FCesiumTextureResource* p) { + FCesiumTextureResource ::Destroy(p); + }); + + // For texture resources created from glTF _textures_, this will happen later + // (after we created the UTexture2D). But this texture resource, created for + // an ImageAsset, will never have a UTexture2D, so we initialize its resources + // here. + ENQUEUE_RENDER_COMMAND(Cesium_InitResource) + ([pResource = extension._pTextureResource]( + FRHICommandListImmediate& RHICmdList) mutable { + pResource->InitResource( + FRHICommandListImmediate::Get()); // Init Resource now requires a + // command list. + }); + + maybePromise->resolve(); + + return extension; +} + +ExtensionImageAssetUnreal::ExtensionImageAssetUnreal( + const CesiumAsync::SharedFuture& future) + : _pTextureResource(nullptr), _futureCreateResource(future) {} + +const TSharedPtr& +ExtensionImageAssetUnreal::getTextureResource() const { + return this->_pTextureResource; +} + +CesiumAsync::SharedFuture& ExtensionImageAssetUnreal::getFuture() { + return this->_futureCreateResource; +} + +const CesiumAsync::SharedFuture& +ExtensionImageAssetUnreal::getFuture() const { + return this->_futureCreateResource; +} + +namespace { + +// Returns the ExtensionImageAssetUnreal, which is created if it does not +// already exist. It _may_ also return a Promise, in which case the calling +// thread is responsible for doing the loading and should resolve the Promise +// when it's done. +std::pair>> +getOrCreateImageFuture( + const AsyncSystem& asyncSystem, + CesiumGltf::ImageAsset& imageCesium) { + std::scoped_lock lock(createExtensionMutex); + + ExtensionImageAssetUnreal* pExtension = + imageCesium.getExtension(); + if (!pExtension) { + // This thread will work on this image. + Promise promise = asyncSystem.createPromise(); + ExtensionImageAssetUnreal& extension = + imageCesium.addExtension( + promise.getFuture().share()); + return {extension, std::move(promise)}; + } else { + // Another thread is already working on this image. + return {*pExtension, std::nullopt}; + } +} + +} // namespace diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.h new file mode 100644 index 0000000..824bc4d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.h @@ -0,0 +1,90 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumTextureResource.h" +#include "PixelFormat.h" +#include "Templates/SharedPointer.h" +#include +#include + +namespace CesiumGltf { +struct ImageAsset; +} + +/** + * @brief An extension attached to an ImageAsset in order to hold + * Unreal-specific information about it. + * + * ImageAsset instances are shared between multiple textures on a single model, + * and even between models in some cases, but we strive to have only one copy of + * the image bytes in GPU memory. + * + * The Unreal / GPU resource is held in `pTextureResource`, which may be either + * a `FCesiumCreateNewTextureResource` or a `FCesiumUseExistingTextureResource` + * depending on how it was created. We'll never actually sample directly from + * this resource, however. Instead, a separate + * `FCesiumUseExistingTextureResource` will be created for each glTF Texture + * that references this image, and it will point to the instance managed by this + * extension. + * + * Because we'll never be sampling from this texture resource, the texture + * filtering and addressing parameters have default values. + */ +struct ExtensionImageAssetUnreal { + static inline constexpr const char* TypeName = "ExtensionImageAssetUnreal"; + static inline constexpr const char* ExtensionName = + "PRIVATE_ImageAsset_Unreal"; + + /** + * @brief Gets an Unreal texture resource from the given `ImageAsset`, + * creating it if necessary. + * + * When this function is called for the first time on a particular + * `ImageAsset`, the asynchronous process to create an Unreal + * `FTextureResource` from it is kicked off. On successive invocations + * (perhaps from other threads), the existing instance is returned. It is safe + * to call this method on the same `ImageAsset` instance from multiple + * threads simultaneously as long as no other thread is modifying the instance + * at the same time. + * + * To determine if the asynchronous `FTextureResource` creation process has + * completed, use {@link getFuture}. + */ + static const ExtensionImageAssetUnreal& getOrCreate( + const CesiumAsync::AsyncSystem& asyncSystem, + CesiumGltf::ImageAsset& imageCesium, + bool sRGB, + bool needsMipMaps, + const std::optional& overridePixelFormat); + + /** + * Constructs a new instance. + * + * @param future The future that will resolve when loading of the + * {@link getTextureResource} is complete. + */ + ExtensionImageAssetUnreal(const CesiumAsync::SharedFuture& future); + + /** + * Gets the created texture resource. This resource should not be accessed or + * used before the future returned by {@link getFuture} resolves. + */ + const TSharedPtr& getTextureResource() const; + + /** + * Gets the future that will resolve when loading of the + * {@link getTextureResource} is complete. This future will not reject. + */ + CesiumAsync::SharedFuture& getFuture(); + + /** + * Gets the future that will resolve when loading of the + * {@link getTextureResource} is complete. This future will not reject. + */ + const CesiumAsync::SharedFuture& getFuture() const; + +private: + TSharedPtr _pTextureResource; + CesiumAsync::SharedFuture _futureCreateResource; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GeoTransforms.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GeoTransforms.cpp new file mode 100644 index 0000000..6859759 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GeoTransforms.cpp @@ -0,0 +1,218 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "GeoTransforms.h" + +#include "CesiumGeospatial/GlobeTransforms.h" +#include "CesiumRuntime.h" +#include "CesiumTransforms.h" +#include "VecMath.h" +#include + +#define GLM_ENABLE_EXPERIMENTAL +#include + +using namespace CesiumGeospatial; + +namespace { + +LocalHorizontalCoordinateSystem createCoordinateSystem( + const Ellipsoid& ellipsoid, + const glm::dvec3& center, + double scale) { + return LocalHorizontalCoordinateSystem( + center, + LocalDirection::East, + LocalDirection::South, + LocalDirection::Up, + 1.0 / (scale * 100.0), + ellipsoid); +} + +} // namespace + +GeoTransforms::GeoTransforms() + : _coordinateSystem( + glm::dvec3(0.0), + LocalDirection::East, + LocalDirection::North, + LocalDirection::Up, + 1.0, + CesiumGeospatial::Ellipsoid::WGS84), + _ellipsoid(CesiumGeospatial::Ellipsoid::WGS84), + _center(0.0), + _scale(1.0), + _ecefToUnreal(), + _unrealToEcef() { + // Coordinate system is initialized with the default values. This function + // overrides them with proper values. + this->updateTransforms(); +} + +GeoTransforms::GeoTransforms( + const CesiumGeospatial::Ellipsoid& ellipsoid, + const glm::dvec3& center, + double scale) + : _coordinateSystem( + glm::dvec3(0.0), + LocalDirection::East, + LocalDirection::North, + LocalDirection::Up, + 1.0, + ellipsoid), + _ellipsoid(ellipsoid), + _center(center), + _scale(scale), + _ecefToUnreal(), + _unrealToEcef() { + // Coordinate system is initialized with the default values. This function + // overrides them with proper values. + this->updateTransforms(); +} + +void GeoTransforms::setCenter(const glm::dvec3& center) noexcept { + if (this->_center != center) { + this->_center = center; + updateTransforms(); + } +} + +void GeoTransforms::setEllipsoid( + const CesiumGeospatial::Ellipsoid& ellipsoid) noexcept { + if (this->_ellipsoid.getRadii() != ellipsoid.getRadii()) { + this->_ellipsoid = ellipsoid; + updateTransforms(); + } +} + +glm::dquat GeoTransforms::ComputeSurfaceNormalRotation( + const glm::dvec3& oldPosition, + const glm::dvec3& newPosition) const { + const glm::dvec3 oldEllipsoidNormal = + this->ComputeGeodeticSurfaceNormal(oldPosition); + const glm::dvec3 newEllipsoidNormal = + this->ComputeGeodeticSurfaceNormal(newPosition); + return glm::rotation(oldEllipsoidNormal, newEllipsoidNormal); +} + +glm::dquat GeoTransforms::ComputeSurfaceNormalRotationUnreal( + const glm::dvec3& oldPosition, + const glm::dvec3& newPosition) const { + const glm::dmat3 ecefToUnreal = + glm::dmat3(this->GetEllipsoidCenteredToAbsoluteUnrealWorldTransform()); + const glm::dvec3 oldEllipsoidNormalUnreal = glm::normalize( + ecefToUnreal * this->ComputeGeodeticSurfaceNormal(oldPosition)); + const glm::dvec3 newEllipsoidNormalUnreal = glm::normalize( + ecefToUnreal * this->ComputeGeodeticSurfaceNormal(newPosition)); + return glm::rotation(oldEllipsoidNormalUnreal, newEllipsoidNormalUnreal); +} + +void GeoTransforms::updateTransforms() noexcept { + this->_coordinateSystem = + createCoordinateSystem(this->_ellipsoid, this->_center, this->_scale); + this->_ecefToUnreal = VecMath::createMatrix( + this->_coordinateSystem.getEcefToLocalTransformation()); + this->_unrealToEcef = VecMath::createMatrix( + this->_coordinateSystem.getLocalToEcefTransformation()); + + UE_LOG( + LogCesium, + Verbose, + TEXT( + "GeoTransforms::updateTransforms with center %f %f %f and ellipsoid radii %f %f %f"), + _center.x, + _center.y, + _center.z, + _ellipsoid.getRadii().x, + _ellipsoid.getRadii().y, + _ellipsoid.getRadii().z); +} + +glm::dvec3 GeoTransforms::TransformLongitudeLatitudeHeightToEcef( + const glm::dvec3& longitudeLatitudeHeight) const noexcept { + return _ellipsoid.cartographicToCartesian( + CesiumGeospatial::Cartographic::fromDegrees( + longitudeLatitudeHeight.x, + longitudeLatitudeHeight.y, + longitudeLatitudeHeight.z)); +} + +glm::dvec3 GeoTransforms::TransformEcefToLongitudeLatitudeHeight( + const glm::dvec3& ecef) const noexcept { + std::optional llh = + _ellipsoid.cartesianToCartographic(ecef); + if (!llh) { + // TODO: since degenerate cases only happen close to Earth's center + // would it make more sense to assign an arbitrary but correct LLH + // coordinate to this case such as (0.0, 0.0, -_EARTH_RADIUS_)? + return glm::dvec3(0.0, 0.0, 0.0); + } + return glm::dvec3( + glm::degrees(llh->longitude), + glm::degrees(llh->latitude), + llh->height); +} + +glm::dvec3 GeoTransforms::TransformLongitudeLatitudeHeightToUnreal( + const glm::dvec3& origin, + const glm::dvec3& longitudeLatitudeHeight) const noexcept { + glm::dvec3 ecef = + this->TransformLongitudeLatitudeHeightToEcef(longitudeLatitudeHeight); + return this->TransformEcefToUnreal(origin, ecef); +} + +glm::dvec3 GeoTransforms::TransformUnrealToLongitudeLatitudeHeight( + const glm::dvec3& origin, + const glm::dvec3& ue) const noexcept { + glm::dvec3 ecef = this->TransformUnrealToEcef(origin, ue); + return this->TransformEcefToLongitudeLatitudeHeight(ecef); +} + +glm::dvec3 GeoTransforms::TransformEcefToUnreal( + const glm::dvec3& origin, + const glm::dvec3& ecef) const noexcept { + return this->_coordinateSystem.ecefPositionToLocal(ecef) - origin; +} + +glm::dvec3 GeoTransforms::TransformUnrealToEcef( + const glm::dvec3& origin, + const glm::dvec3& ue) const noexcept { + return this->_coordinateSystem.localPositionToEcef(ue + origin); +} + +glm::dquat GeoTransforms::TransformRotatorUnrealToEastSouthUp( + const glm::dvec3& origin, + const glm::dquat& UERotator, + const glm::dvec3& ueLocation) const noexcept { + glm::dmat3 esuToUe = + glm::dmat3(this->ComputeEastSouthUpToUnreal(origin, ueLocation)); + glm::dmat3 ueToEsu = glm::affineInverse(esuToUe); + glm::dquat ueToEsuQuat = glm::quat_cast(ueToEsu); + return ueToEsuQuat * UERotator; +} + +glm::dquat GeoTransforms::TransformRotatorEastSouthUpToUnreal( + const glm::dvec3& origin, + const glm::dquat& ESURotator, + const glm::dvec3& ueLocation) const noexcept { + + glm::dmat3 esuToUe = + glm::dmat3(this->ComputeEastSouthUpToUnreal(origin, ueLocation)); + glm::dquat esuToUeQuat = glm::quat_cast(esuToUe); + return esuToUeQuat * ESURotator; +} + +glm::dmat4 GeoTransforms::ComputeEastSouthUpToUnreal( + const glm::dvec3& origin, + const glm::dvec3& ue) const noexcept { + glm::dvec3 ecef = this->TransformUnrealToEcef(origin, ue); + LocalHorizontalCoordinateSystem newLocal = + createCoordinateSystem(this->_ellipsoid, ecef, this->_scale); + return newLocal.computeTransformationToAnotherLocal(this->_coordinateSystem); +} + +glm::dmat3 +GeoTransforms::ComputeEastNorthUpToEcef(const glm::dvec3& ecef) const noexcept { + return glm::dmat3(CesiumGeospatial::GlobeTransforms::eastNorthUpToFixedFrame( + ecef, + _ellipsoid)); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GlmLogging.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GlmLogging.cpp new file mode 100644 index 0000000..1569e17 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GlmLogging.cpp @@ -0,0 +1,54 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "GlmLogging.h" +#include "CesiumRuntime.h" + +#include +#include + +void GlmLogging::logVector(const std::string& name, const glm::dvec3& vector) { + UE_LOG( + LogCesium, + Verbose, + TEXT("%s: %16.6f %16.6f %16.6f"), + *FString(name.c_str()), + vector.x, + vector.y, + vector.z); +} + +void GlmLogging::logMatrix(const std::string& name, const glm::dmat4& matrix) { + UE_LOG(LogCesium, Verbose, TEXT("%s:"), *FString(name.c_str())); + UE_LOG( + LogCesium, + Verbose, + TEXT(" %16.6f %16.6f %16.6f %16.6f"), + matrix[0][0], + matrix[1][0], + matrix[2][0], + matrix[3][0]); + UE_LOG( + LogCesium, + Verbose, + TEXT(" %16.6f %16.6f %16.6f %16.6f"), + matrix[0][1], + matrix[1][1], + matrix[2][1], + matrix[3][1]); + UE_LOG( + LogCesium, + Verbose, + TEXT(" %16.6f %16.6f %16.6f %16.6f"), + matrix[0][2], + matrix[1][2], + matrix[2][2], + matrix[3][2]); + UE_LOG( + LogCesium, + Verbose, + TEXT(" %16.6f %16.6f %16.6f %16.6f"), + matrix[0][3], + matrix[1][3], + matrix[2][3], + matrix[3][3]); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GlmLogging.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GlmLogging.h new file mode 100644 index 0000000..533ee6b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GlmLogging.h @@ -0,0 +1,30 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include +#include + +/** + * @brief Utility functions for logging GLM data in Unreal + */ +class GlmLogging { +public: + /** + * Print the given vector as a verbose `LogCesium` + * message, with unspecified formatting. + * + * @param name The name that will be part of the message + * @param vector The vector + */ + static void logVector(const std::string& name, const glm::dvec3& vector); + + /** + * Print the given matrix as a verbose `LogCesium` + * message, with unspecified formatting. + * + * @param name The name that will be part of the message + * @param matrix The matrix + */ + static void logMatrix(const std::string& name, const glm::dmat4& matrix); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GlobeAwareDefaultPawn.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GlobeAwareDefaultPawn.cpp new file mode 100644 index 0000000..558037d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GlobeAwareDefaultPawn.cpp @@ -0,0 +1,394 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "GlobeAwareDefaultPawn.h" +#include "Camera/CameraComponent.h" +#include "CesiumActors.h" +#include "CesiumCustomVersion.h" +#include "CesiumFlyToComponent.h" +#include "CesiumGeoreference.h" +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumRuntime.h" +#include "CesiumTransforms.h" +#include "CesiumUtility/Math.h" +#include "CesiumWgs84Ellipsoid.h" +#include "Curves/CurveFloat.h" +#include "DrawDebugHelpers.h" +#include "Engine/World.h" +#include "GameFramework/PlayerController.h" +#include "UObject/ConstructorHelpers.h" +#include "VecMath.h" +#include +#include +#include +#include +#include + +#if WITH_EDITOR +#include "Editor.h" +#endif + +AGlobeAwareDefaultPawn::AGlobeAwareDefaultPawn() : ADefaultPawn() { + // Structure to hold one-time initialization + struct FConstructorStatics { + ConstructorHelpers::FObjectFinder ProgressCurve; + ConstructorHelpers::FObjectFinder HeightPercentageCurve; + ConstructorHelpers::FObjectFinder MaximumHeightByDistanceCurve; + FConstructorStatics() + : ProgressCurve(TEXT( + "/CesiumForUnreal/Curves/FlyTo/Curve_CesiumFlyToDefaultProgress_Float.Curve_CesiumFlyToDefaultProgress_Float")), + HeightPercentageCurve(TEXT( + "/CesiumForUnreal/Curves/FlyTo/Curve_CesiumFlyToDefaultHeightPercentage_Float.Curve_CesiumFlyToDefaultHeightPercentage_Float")), + MaximumHeightByDistanceCurve(TEXT( + "/CesiumForUnreal/Curves/FlyTo/Curve_CesiumFlyToDefaultMaximumHeightByDistance_Float.Curve_CesiumFlyToDefaultMaximumHeightByDistance_Float")) { + } + }; + static FConstructorStatics ConstructorStatics; + + this->FlyToProgressCurve_DEPRECATED = ConstructorStatics.ProgressCurve.Object; + this->FlyToAltitudeProfileCurve_DEPRECATED = + ConstructorStatics.HeightPercentageCurve.Object; + this->FlyToMaximumAltitudeCurve_DEPRECATED = + ConstructorStatics.MaximumHeightByDistanceCurve.Object; + +#if WITH_EDITOR + this->SetIsSpatiallyLoaded(false); +#endif + this->GlobeAnchor = + CreateDefaultSubobject(TEXT("GlobeAnchor")); +} + +void AGlobeAwareDefaultPawn::MoveRight(float Val) { + this->_moveAlongViewAxis(EAxis::Y, Val); +} + +void AGlobeAwareDefaultPawn::MoveForward(float Val) { + this->_moveAlongViewAxis(EAxis::X, Val); +} + +void AGlobeAwareDefaultPawn::MoveUp_World(float Val) { + if (Val == 0.0f) { + return; + } + + ACesiumGeoreference* pGeoreference = this->GetGeoreference(); + if (!IsValid(pGeoreference)) { + return; + } + + UCesiumEllipsoid* pEllipsoid = pGeoreference->GetEllipsoid(); + check(IsValid(pEllipsoid)); + + FVector upEcef = pEllipsoid->GeodeticSurfaceNormal( + this->GlobeAnchor->GetEarthCenteredEarthFixedPosition()); + FVector up = + pGeoreference->TransformEarthCenteredEarthFixedDirectionToUnreal(upEcef); + + FTransform transform{}; + USceneComponent* pRootComponent = this->GetRootComponent(); + if (IsValid(pRootComponent)) { + USceneComponent* pParent = pRootComponent->GetAttachParent(); + if (IsValid(pParent)) { + transform = pParent->GetComponentToWorld(); + } + } + + this->_moveAlongVector(transform.TransformVector(up), Val); +} + +FRotator AGlobeAwareDefaultPawn::GetViewRotation() const { + if (!Controller) { + return this->GetActorRotation(); + } + + ACesiumGeoreference* pGeoreference = this->GetGeoreference(); + if (!pGeoreference) { + return this->GetActorRotation(); + } + + // The control rotation is expressed in a left-handed East-South-Up (ESU) + // coordinate system: + // * Yaw: Clockwise from East: 0 is East, 90 degrees is + // South, 180 degrees is West, 270 degrees is North. + // * Pitch: Angle above level, Positive is looking up, negative is looking + // down + // * Roll: Rotation around the look direction. Positive is a barrel roll to + // the right (clockwise). + FRotator localRotation = Controller->GetControlRotation(); + + FTransform transform{}; + USceneComponent* pRootComponent = this->GetRootComponent(); + if (IsValid(pRootComponent)) { + USceneComponent* pParent = pRootComponent->GetAttachParent(); + if (IsValid(pParent)) { + transform = pParent->GetComponentToWorld(); + } + } + + // Transform the rotation in the ESU frame to the Unreal world frame. + FVector globePosition = + transform.InverseTransformPosition(this->GetPawnViewLocation()); + FMatrix esuAdjustmentMatrix = + pGeoreference->ComputeEastSouthUpToUnrealTransformation(globePosition) * + transform.ToMatrixNoScale(); + + return FRotator(esuAdjustmentMatrix.ToQuat() * localRotation.Quaternion()); +} + +FRotator AGlobeAwareDefaultPawn::GetBaseAimRotation() const { + return this->GetViewRotation(); +} + +const FTransform& +AGlobeAwareDefaultPawn::GetGlobeToUnrealWorldTransform() const { + AActor* pParent = this->GetAttachParentActor(); + if (IsValid(pParent)) { + return pParent->GetActorTransform(); + } + return FTransform::Identity; +} + +void AGlobeAwareDefaultPawn::FlyToLocationECEF( + const FVector& ECEFDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving) { + UCesiumFlyToComponent* FlyTo = + this->FindComponentByClass(); + if (!IsValid(FlyTo)) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "Cannot call deprecated FlyToLocationLongitudeLatitudeHeight because the GlobeAwareDefaultPawn does not have a CesiumFlyToComponent.")) + return; + } + + // Make sure functions attached to the deprecated delegates will be called. + FlyTo->OnFlightComplete.AddUniqueDynamic( + this, + &AGlobeAwareDefaultPawn::_onFlightComplete); + FlyTo->OnFlightInterrupted.AddUniqueDynamic( + this, + &AGlobeAwareDefaultPawn::_onFlightInterrupted); + + FlyTo->FlyToLocationEarthCenteredEarthFixed( + ECEFDestination, + YawAtDestination, + PitchAtDestination, + CanInterruptByMoving); +} + +void AGlobeAwareDefaultPawn::FlyToLocationLongitudeLatitudeHeight( + const FVector& LongitudeLatitudeHeightDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving) { + UCesiumFlyToComponent* FlyTo = + this->FindComponentByClass(); + if (!IsValid(FlyTo)) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "Cannot call deprecated FlyToLocationLongitudeLatitudeHeight because the GlobeAwareDefaultPawn does not have a CesiumFlyToComponent.")) + return; + } + + // Make sure functions attached to the deprecated delegates will be called. + FlyTo->OnFlightComplete.AddUniqueDynamic( + this, + &AGlobeAwareDefaultPawn::_onFlightComplete); + FlyTo->OnFlightInterrupted.AddUniqueDynamic( + this, + &AGlobeAwareDefaultPawn::_onFlightInterrupted); + + FlyTo->FlyToLocationLongitudeLatitudeHeight( + LongitudeLatitudeHeightDestination, + YawAtDestination, + PitchAtDestination, + CanInterruptByMoving); +} + +void AGlobeAwareDefaultPawn::Serialize(FArchive& Ar) { + Super::Serialize(Ar); + + Ar.UsingCustomVersion(FCesiumCustomVersion::GUID); +} + +void AGlobeAwareDefaultPawn::PostLoad() { + Super::PostLoad(); + + // For backward compatibility, copy the value of the deprecated Georeference + // property to its new home in the GlobeAnchor. It doesn't appear to be + // possible to do this in Serialize: + // https://udn.unrealengine.com/s/question/0D54z00007CAbHFCA1/backward-compatibile-serialization-for-uobject-pointers + const int32 CesiumVersion = + this->GetLinkerCustomVersion(FCesiumCustomVersion::GUID); + if (CesiumVersion < FCesiumCustomVersion::GeoreferenceRefactoring) { + if (this->Georeference_DEPRECATED != nullptr && this->GlobeAnchor && + this->GlobeAnchor->GetGeoreference() == nullptr) { + this->GlobeAnchor->SetGeoreference(this->Georeference_DEPRECATED); + } + } + +#if WITH_EDITOR + if (CesiumVersion < FCesiumCustomVersion::FlyToComponent && + !HasAnyFlags(RF_ClassDefaultObject)) { + // If this is a Blueprint object, like DynamicPawn, its construction + // scripts may not have been run yet at this point. Doing so might cause + // a Fly To component to be added. So we force it to happen here so + // that we don't end up adding a duplicate CesiumFlyToComponent. + this->RerunConstructionScripts(); + + UCesiumFlyToComponent* FlyTo = + this->FindComponentByClass(); + if (!FlyTo) { + FlyTo = Cast(this->AddComponentByClass( + UCesiumFlyToComponent::StaticClass(), + false, + FTransform::Identity, + false)); + FlyTo->SetFlags(RF_Transactional); + this->AddInstanceComponent(FlyTo); + + UE_LOG( + LogCesium, + Warning, + TEXT( + "Added CesiumFlyToComponent to %s in order to preserve backward compatibility."), + *this->GetName()); + } + + FlyTo->RotationToUse = ECesiumFlyToRotation::ControlRotationInEastSouthUp; + FlyTo->ProgressCurve = this->FlyToProgressCurve_DEPRECATED; + FlyTo->HeightPercentageCurve = this->FlyToAltitudeProfileCurve_DEPRECATED; + FlyTo->MaximumHeightByDistanceCurve = + this->FlyToMaximumAltitudeCurve_DEPRECATED; + FlyTo->Duration = this->FlyToDuration_DEPRECATED; + } +#endif +} + +ACesiumGeoreference* AGlobeAwareDefaultPawn::GetGeoreference() const { + if (!IsValid(this->GlobeAnchor)) { + UE_LOG( + LogCesium, + Error, + TEXT( + "GlobeAwareDefaultPawn %s does not have a valid GlobeAnchorComponent."), + *this->GetName()); + return nullptr; + } + + ACesiumGeoreference* pGeoreference = this->GlobeAnchor->ResolveGeoreference(); + if (!IsValid(pGeoreference)) { + UE_LOG( + LogCesium, + Error, + TEXT( + "GlobeAwareDefaultPawn %s does not have a valid CesiumGeoreference."), + *this->GetName()); + pGeoreference = nullptr; + } + + return pGeoreference; +} + +UCurveFloat* AGlobeAwareDefaultPawn::GetFlyToProgressCurve_DEPRECATED() const { + UCesiumFlyToComponent* FlyTo = + this->FindComponentByClass(); + if (!IsValid(FlyTo)) + return nullptr; + return FlyTo->ProgressCurve; +} + +void AGlobeAwareDefaultPawn::SetFlyToProgressCurve_DEPRECATED( + UCurveFloat* NewValue) { + UCesiumFlyToComponent* FlyTo = + this->FindComponentByClass(); + if (!IsValid(FlyTo)) + return; + FlyTo->ProgressCurve = NewValue; +} + +UCurveFloat* +AGlobeAwareDefaultPawn::GetFlyToAltitudeProfileCurve_DEPRECATED() const { + UCesiumFlyToComponent* FlyTo = + this->FindComponentByClass(); + if (!IsValid(FlyTo)) + return nullptr; + return FlyTo->HeightPercentageCurve; +} + +void AGlobeAwareDefaultPawn::SetFlyToAltitudeProfileCurve_DEPRECATED( + UCurveFloat* NewValue) { + UCesiumFlyToComponent* FlyTo = + this->FindComponentByClass(); + if (!IsValid(FlyTo)) + return; + FlyTo->HeightPercentageCurve = NewValue; +} + +UCurveFloat* +AGlobeAwareDefaultPawn::GetFlyToMaximumAltitudeCurve_DEPRECATED() const { + UCesiumFlyToComponent* FlyTo = + this->FindComponentByClass(); + if (!IsValid(FlyTo)) + return nullptr; + return FlyTo->MaximumHeightByDistanceCurve; +} + +void AGlobeAwareDefaultPawn::SetFlyToMaximumAltitudeCurve_DEPRECATED( + UCurveFloat* NewValue) { + UCesiumFlyToComponent* FlyTo = + this->FindComponentByClass(); + if (!IsValid(FlyTo)) + return; + FlyTo->MaximumHeightByDistanceCurve = NewValue; +} + +float AGlobeAwareDefaultPawn::GetFlyToDuration_DEPRECATED() const { + UCesiumFlyToComponent* FlyTo = + this->FindComponentByClass(); + if (!IsValid(FlyTo)) + return 0.0f; + return FlyTo->Duration; +} + +void AGlobeAwareDefaultPawn::SetFlyToDuration_DEPRECATED(float NewValue) { + UCesiumFlyToComponent* FlyTo = + this->FindComponentByClass(); + if (!IsValid(FlyTo)) + return; + FlyTo->Duration = NewValue; +} + +void AGlobeAwareDefaultPawn::_moveAlongViewAxis(EAxis::Type axis, double Val) { + if (Val == 0.0) { + return; + } + + FRotator worldRotation = this->GetViewRotation(); + this->_moveAlongVector( + FRotationMatrix(worldRotation).GetScaledAxis(axis), + Val); +} + +void AGlobeAwareDefaultPawn::_moveAlongVector( + const FVector& vector, + double Val) { + if (Val == 0.0) { + return; + } + + FRotator worldRotation = this->GetViewRotation(); + AddMovementInput(vector, Val); +} + +void AGlobeAwareDefaultPawn::_onFlightComplete() { + this->OnFlightComplete_DEPRECATED.Broadcast(); +} + +void AGlobeAwareDefaultPawn::_onFlightInterrupted() { + this->OnFlightInterrupt_DEPRECATED.Broadcast(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/LoadGltfResult.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/LoadGltfResult.h new file mode 100644 index 0000000..6d01fe2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/LoadGltfResult.h @@ -0,0 +1,211 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumCommon.h" +#include "CesiumEncodedFeaturesMetadata.h" +#include "CesiumMetadataPrimitive.h" +#include "CesiumModelMetadata.h" +#include "CesiumPrimitiveFeatures.h" +#include "CesiumPrimitiveMetadata.h" +#include "CesiumRasterOverlays.h" +#include "CesiumTextureUtility.h" +#include "Chaos/TriangleMeshImplicitObject.h" +#include "Containers/Map.h" +#include "Containers/UnrealString.h" +#include "Math/TransformNonVectorized.h" +#include "StaticMeshResources.h" +#include "Templates/SharedPointer.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace LoadGltfResult { +/** + * Represents the result of loading a glTF primitive on a game thread. + * Temporarily holds render data that will be used in the Unreal material, as + * well as any data that needs to be transferred to the corresponding + * CesiumGltfPrimitiveComponent after it is created on the main thread. + * + * This type is move-only due to the use of TUniquePtr. + */ +struct LoadPrimitiveResult { +#pragma region Temporary render data + + LoadPrimitiveResult(const LoadPrimitiveResult&) = delete; + + LoadPrimitiveResult() {} + LoadPrimitiveResult(LoadPrimitiveResult&& other) = default; + + /** + * The render data. This is populated so it can be set on the static mesh + * created on the main thread. + */ + TUniquePtr RenderData = nullptr; + + /** + * The index of the material for this primitive within the parent model, or -1 + * if none. + */ + int32_t materialIndex = -1; + + glm::dmat4x4 transform{1.0}; +#if ENGINE_VERSION_5_4_OR_HIGHER + Chaos::FTriangleMeshImplicitObjectPtr pCollisionMesh = nullptr; +#else + TSharedPtr + pCollisionMesh = nullptr; +#endif + std::string name{}; + + TUniquePtr baseColorTexture; + TUniquePtr + metallicRoughnessTexture; + TUniquePtr normalTexture; + TUniquePtr emissiveTexture; + TUniquePtr occlusionTexture; + TUniquePtr waterMaskTexture; + std::unordered_map textureCoordinateParameters; + /** + * A map of feature ID set names to their corresponding texture coordinate + * indices in the Unreal mesh. + */ + TMap FeaturesMetadataTexCoordParameters; + + bool isUnlit = false; + + bool onlyLand = true; + bool onlyWater = false; + + double waterMaskTranslationX = 0.0; + double waterMaskTranslationY = 0.0; + double waterMaskScale = 1.0; + + /** + * The dimensions of the primitive. Passed to a CesiumGltfPointsComponent for + * use in computing attenuation. + */ + glm::vec3 dimensions; + +#pragma endregion + +#pragma region CesiumGltfPrimitiveComponent data + int32_t meshIndex = -1; + int32_t primitiveIndex = -1; + + /** Parses EXT_mesh_features from a mesh primitive.*/ + FCesiumPrimitiveFeatures Features{}; + /** Parses EXT_structural_metadata from a mesh primitive.*/ + FCesiumPrimitiveMetadata Metadata{}; + + /** Encodes the EXT_mesh_features on a mesh primitive.*/ + CesiumEncodedFeaturesMetadata::EncodedPrimitiveFeatures EncodedFeatures{}; + /** Encodes the EXT_structural_metadata on a mesh primitive.*/ + CesiumEncodedFeaturesMetadata::EncodedPrimitiveMetadata EncodedMetadata{}; + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + // For backwards compatibility with CesiumEncodedMetadataComponent. + FCesiumMetadataPrimitive Metadata_DEPRECATED{}; + std::optional + EncodedMetadata_DEPRECATED = std::nullopt; + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * Maps an overlay texture coordinate ID to the index of the corresponding + * texture coordinates in the mesh's UVs array. + */ + OverlayTextureCoordinateIDMap overlayTextureCoordinateIDToUVIndex{}; + + /** + * Maps the accessor index in a glTF to its corresponding texture coordinate + * index in the Unreal mesh. The -1 key is reserved for implicit feature IDs + * (in other words, the vertex index). + */ + std::unordered_map GltfToUnrealTexCoordMap; + + /** + * Maps texture coordinate set indices in a glTF to AccessorViews. This stores + * accessor views on texture coordinate sets that will be used by feature ID + * textures or property textures for picking. + */ + std::unordered_map + TexCoordAccessorMap; + + /** + * The position accessor of the glTF primitive. This is used for computing + * the UV at a hit location on a primitive, and is safer to access than the + * mesh's RenderData. + */ + CesiumGltf::AccessorView PositionAccessor; + + /** + * The index accessor of the glTF primitive, if one is specified. This is used + * for computing the UV at a hit location on a primitive. + */ + CesiumGltf::IndexAccessorType IndexAccessor; + +#pragma endregion +}; + +/** + * Represents the result of loading a glTF mesh on a game thread. + */ +struct LoadMeshResult { + LoadMeshResult() {} + + LoadMeshResult(const LoadMeshResult&) = delete; + LoadMeshResult(LoadMeshResult&& other) = default; + LoadMeshResult& operator=(LoadMeshResult&& other) = default; + + std::vector primitiveResults{}; +}; + +/** + * Represents the result of loading a glTF node on a game thread. + */ +struct LoadNodeResult { + LoadNodeResult() {} + + LoadNodeResult(const LoadNodeResult&) = delete; + LoadNodeResult(LoadNodeResult&& other) = default; + + std::optional meshResult = std::nullopt; + /** + * Array of instance transforms, if any. + */ + std::vector InstanceTransforms; + /** + * Features from EXT_instance_features. A pointer is used for shared ownership + * because there may be multiple primitives in the same mesh belonging to a + * single instance. + */ + TSharedPtr pInstanceFeatures = nullptr; +}; + +/** + * Represents the result of loading a glTF model on a game thread. + * Temporarily holds data that needs to be transferred to the corresponding + * CesiumGltfComponent after it is created on the main thread. + */ +struct LoadModelResult { + std::vector nodeResults{}; + + // Parses the root EXT_structural_metadata extension. + FCesiumModelMetadata Metadata{}; + + // Encodes the EXT_structural_metadata on a glTF model. + CesiumEncodedFeaturesMetadata::EncodedModelMetadata EncodedMetadata{}; + + // For backwards compatibility with CesiumEncodedMetadataComponent. + std::optional + EncodedMetadata_DEPRECATED{}; +}; +} // namespace LoadGltfResult diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ScreenCreditsWidget.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ScreenCreditsWidget.cpp new file mode 100644 index 0000000..e58161e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ScreenCreditsWidget.cpp @@ -0,0 +1,282 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "ScreenCreditsWidget.h" +#include "Components/BackgroundBlur.h" +#include "Components/RichTextBlock.h" +#include "Engine/Font.h" +#include "Engine/Texture2D.h" +#include "Framework/Application/SlateApplication.h" +#include "HttpModule.h" +#include "ImageUtils.h" +#include "Interfaces/IHttpResponse.h" +#include "Math/UnrealMathUtility.h" +#include "Misc/Base64.h" +#include "Rendering/DrawElements.h" +#include "Runtime/Launch/Resources/Version.h" +#include "Slate/SlateGameResources.h" +#include "UObject/ConstructorHelpers.h" +#include "Widgets/DeclarativeSyntaxSupport.h" +#include "Widgets/Images/SImage.h" +#include "Widgets/Input/SRichTextHyperlink.h" +#include "Widgets/Layout/SBox.h" +#include "Widgets/SCompoundWidget.h" +#include +#include + +class SCreditImage : public SCompoundWidget { +public: + SLATE_BEGIN_ARGS(SCreditImage) {} + SLATE_END_ARGS() + +public: + void Construct(const FArguments& InArgs, const FSlateBrush* Brush) { + if (ensure(Brush)) { + ChildSlot[SNew(SBox).VAlign(VAlign_Center)[SNew(SImage).Image(Brush)]]; + } + } +}; + +class SCreditHyperlinkImage : public SCompoundWidget { +public: + SLATE_BEGIN_ARGS(SCreditImage) {} + SLATE_END_ARGS() + +public: + void Construct( + const FArguments& InArgs, + const FSlateBrush* Brush, + const FString& Url) { + if (ensure(Brush)) { + ButtonStyle.SetNormal(*Brush); + ButtonStyle.SetHovered(*Brush); + ButtonStyle.SetPressed(*Brush); + + ChildSlot + [SNew(SButton).ButtonStyle(&ButtonStyle).OnClicked_Lambda([Url]() { + FPlatformProcess::LaunchURL(*Url, NULL, NULL); + return FReply::Handled(); + })]; + + this->SetCursor(EMouseCursor::Hand); + } + } + +private: + FButtonStyle ButtonStyle; +}; + +class SCreditHyperlink : public SCompoundWidget { +public: + SLATE_BEGIN_ARGS(SCreditImage) {} + SLATE_END_ARGS() + +public: + void Construct( + const FArguments& InArgs, + const FString& Text, + const FString& Url, + const UCreditsDecorator* InDecorator) { + + TSharedPtr model = + MakeShareable(new FSlateHyperlinkRun::FWidgetViewModel); + + ChildSlot[SNew(SRichTextHyperlink, model.ToSharedRef()) + .Text(FText::FromString(Text)) + .OnNavigate_Lambda([Url, InDecorator]() { + if (Url.Equals("popup")) { + InDecorator->PopupClicked.Execute(); + } else { + FPlatformProcess::LaunchURL(*Url, NULL, NULL); + } + })]; + } +}; + +class FScreenCreditsDecorator : public FRichTextDecorator { +public: + FScreenCreditsDecorator( + URichTextBlock* InOwner, + UCreditsDecorator* InDecorator) + : FRichTextDecorator(InOwner), Decorator(InDecorator) {} + + virtual bool Supports( + const FTextRunParseResults& RunParseResult, + const FString& Text) const override { + if (RunParseResult.Name == TEXT("credits") && + (RunParseResult.MetaData.Contains(TEXT("id")) || + RunParseResult.MetaData.Contains(TEXT("url")))) { + return true; + } + return false; + } + +protected: + virtual TSharedPtr CreateDecoratorWidget( + const FTextRunInfo& RunInfo, + const FTextBlockStyle&) const override { + FString Text; + FString Url; + const FSlateBrush* Brush = nullptr; + if (RunInfo.MetaData.Contains(TEXT("url"))) { + Url = *RunInfo.MetaData[TEXT("url")]; + } + if (RunInfo.MetaData.Contains(TEXT("text"))) { + Text = *RunInfo.MetaData[TEXT("text")]; + } + if (RunInfo.MetaData.Contains(TEXT("id"))) { + int32 id = FCString::Atoi(*RunInfo.MetaData[TEXT("id")]); + Brush = Decorator->FindImageBrush(id); + } + if (Brush) { + if (Url.IsEmpty()) { + return SNew(SCreditImage, Brush); + } else { + return SNew(SCreditHyperlinkImage, Brush, Url); + } + } else + return SNew(SCreditHyperlink, Text, Url, Decorator); + } + +private: + UCreditsDecorator* Decorator; +}; + +UCreditsDecorator::UCreditsDecorator( + const FObjectInitializer& ObjectInitializer) + : URichTextBlockDecorator(ObjectInitializer) {} + +TSharedPtr +UCreditsDecorator::CreateDecorator(URichTextBlock* InOwner) { + return MakeShareable(new FScreenCreditsDecorator(InOwner, this)); +} + +const FSlateBrush* UCreditsDecorator::FindImageBrush(int32 id) { + if (CreditsWidget->_creditImages.Num() > id) { + return CreditsWidget->_creditImages[id]; + } + return nullptr; +} + +UScreenCreditsWidget::UScreenCreditsWidget( + const FObjectInitializer& ObjectInitializer) + : UUserWidget(ObjectInitializer) { + static ConstructorHelpers::FObjectFinder RobotoFontObj( + *UWidget::GetDefaultFontName()); + _font = FSlateFontInfo(RobotoFontObj.Object, 8); +} + +UScreenCreditsWidget::~UScreenCreditsWidget() { + for (int i = 0; i < _creditImages.Num(); i++) { + if (_creditImages[i]) { + delete _creditImages[i]; + } + } +} + +void UScreenCreditsWidget::OnPopupClicked() { + _showPopup = !_showPopup; + BackgroundBlur->SetVisibility( + _showPopup ? ESlateVisibility::Visible : ESlateVisibility::Hidden); +} + +void UScreenCreditsWidget::NativeConstruct() { + + Super::NativeConstruct(); + + if (RichTextOnScreen) { + RichTextOnScreen->SetDefaultFont(_font); + RichTextOnScreen->SetDefaultColorAndOpacity( + FSlateColor(FLinearColor(1.f, 1.f, 1.f, 1.f))); + _decoratorOnScreen = + static_cast(RichTextOnScreen->GetDecoratorByClass( + UCreditsDecorator::StaticClass())); + + _decoratorOnScreen->PopupClicked.BindUObject( + this, + &UScreenCreditsWidget::OnPopupClicked); + _decoratorOnScreen->CreditsWidget = this; + } + if (RichTextPopup) { + RichTextPopup->SetDefaultFont(_font); + RichTextPopup->SetDefaultColorAndOpacity( + FSlateColor(FLinearColor(1.f, 1.f, 1.f, 1.f))); + _decoratorPopup = static_cast( + RichTextPopup->GetDecoratorByClass(UCreditsDecorator::StaticClass())); + + _decoratorPopup->CreditsWidget = this; + } +} + +void UScreenCreditsWidget::HandleImageRequest( + FHttpRequestPtr HttpRequest, + FHttpResponsePtr HttpResponse, + bool bSucceeded, + int32 id) { + UTexture2D* texture = nullptr; + if (bSucceeded && HttpResponse.IsValid() && + HttpResponse->GetContentLength() > 0 && + (texture = FImageUtils::ImportBufferAsTexture2D( + HttpResponse->GetContent())) != nullptr) { + texture->SRGB = true; + texture->UpdateResource(); + _textures.Add(texture); + FTexturePlatformData* pPlatformData = texture->GetPlatformData(); + int32 SizeX = pPlatformData->SizeX; + int32 SizeY = pPlatformData->SizeY; + _creditImages[id] = new FSlateImageBrush(texture, FVector2D(SizeX, SizeY)); + } + // Only update credits after all of the images are done loading. + --_numImagesLoading; + if (_numImagesLoading == 0) { + SetCredits(_credits, _onScreenCredits); + } +} + +std::string UScreenCreditsWidget::LoadImage(const std::string& url) { + const std::string base64Prefix = "data:image/png;base64,"; + if (url.rfind(base64Prefix, 0) == 0) { + TArray dataBuffer; + FString base64 = UTF8_TO_TCHAR(url.c_str() + base64Prefix.length()); + if (FBase64::Decode(base64, dataBuffer)) { + UTexture2D* texture = FImageUtils::ImportBufferAsTexture2D(dataBuffer); + texture->SRGB = true; + texture->UpdateResource(); + _textures.Add(texture); + FTexturePlatformData* pPlatformData = texture->GetPlatformData(); + int32 SizeX = pPlatformData->SizeX; + int32 SizeY = pPlatformData->SizeY; + _creditImages.Add(new FSlateImageBrush(texture, FVector2D(SizeX, SizeY))); + } + } else { + ++_numImagesLoading; + TSharedRef HttpRequest = + FHttpModule::Get().CreateRequest(); + + _creditImages.AddDefaulted(); + HttpRequest->OnProcessRequestComplete().BindUObject( + this, + &UScreenCreditsWidget::HandleImageRequest, + _creditImages.Num() - 1); + + HttpRequest->SetURL(UTF8_TO_TCHAR(url.c_str())); + HttpRequest->SetVerb(TEXT("GET")); + HttpRequest->ProcessRequest(); + } + return std::to_string(_creditImages.Num() - 1); +} + +void UScreenCreditsWidget::SetCredits( + const FString& InCredits, + const FString& InOnScreenCredits) { + if (_numImagesLoading != 0) { + _credits = InCredits; + _onScreenCredits = InOnScreenCredits; + return; + } + if (RichTextPopup) { + RichTextPopup->SetText(FText::FromString(InCredits)); + } + if (RichTextOnScreen) { + RichTextOnScreen->SetText(FText::FromString(InOnScreenCredits)); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ScreenCreditsWidget.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ScreenCreditsWidget.h new file mode 100644 index 0000000..51c2668 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ScreenCreditsWidget.h @@ -0,0 +1,77 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Blueprint/UserWidget.h" +#include "Components/RichTextBlockDecorator.h" +#include "CoreMinimal.h" +#include "Interfaces/IHttpRequest.h" +#include +#include +#include "ScreenCreditsWidget.generated.h" + +DECLARE_DELEGATE(FOnPopupClicked) + +UCLASS() +class UScreenCreditsWidget : public UUserWidget { + GENERATED_BODY() +public: + /** + * Attempts to load an image from the given URL and returns the name of the + * image to be referenced in RTF. + */ + std::string LoadImage(const std::string& url); + + void SetCredits(const FString& InCredits, const FString& InOnScreenCredits); + +private: + UScreenCreditsWidget(const FObjectInitializer& ObjectInitializer); + ~UScreenCreditsWidget(); + virtual void NativeConstruct() override; + + void OnPopupClicked(); + + void HandleImageRequest( + FHttpRequestPtr HttpRequest, + FHttpResponsePtr HttpResponse, + bool bSucceeded, + int32 id); + + UPROPERTY(meta = (BindWidget)) + class URichTextBlock* RichTextOnScreen; + + UPROPERTY(meta = (BindWidget)) + class URichTextBlock* RichTextPopup; + + UPROPERTY(meta = (BindWidget)) + class UBackgroundBlur* BackgroundBlur; + + UPROPERTY() + TArray _textures; + + FString _credits = ""; + FString _onScreenCredits = ""; + bool _showPopup = false; + class UCreditsDecorator* _decoratorOnScreen; + class UCreditsDecorator* _decoratorPopup; + int32 _numImagesLoading; + FSlateFontInfo _font; + TArray _creditImages; + friend class UCreditsDecorator; +}; + +UCLASS() +class UCreditsDecorator : public URichTextBlockDecorator { + GENERATED_BODY() + +public: + UCreditsDecorator(const FObjectInitializer& ObjectInitializer); + + virtual TSharedPtr + CreateDecorator(URichTextBlock* InOwner) override; + + virtual const FSlateBrush* FindImageBrush(int32 id); + + UScreenCreditsWidget* CreditsWidget; + FOnPopupClicked PopupClicked; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/SpdlogUnrealLoggerSink.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/SpdlogUnrealLoggerSink.cpp new file mode 100644 index 0000000..a11270f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/SpdlogUnrealLoggerSink.cpp @@ -0,0 +1,44 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "SpdlogUnrealLoggerSink.h" +#include "CesiumRuntime.h" +#include "CoreMinimal.h" + +void SpdlogUnrealLoggerSink::sink_it_(const spdlog::details::log_msg& msg) { + switch (msg.level) { + case SPDLOG_LEVEL_TRACE: + UE_LOG(LogCesium, VeryVerbose, TEXT("%s"), *this->formatMessage(msg)); + break; + case SPDLOG_LEVEL_DEBUG: + UE_LOG(LogCesium, Verbose, TEXT("%s"), *this->formatMessage(msg)); + break; + case SPDLOG_LEVEL_INFO: + UE_LOG(LogCesium, Display, TEXT("%s"), *this->formatMessage(msg)); + break; + case SPDLOG_LEVEL_WARN: + UE_LOG(LogCesium, Warning, TEXT("%s"), *this->formatMessage(msg)); + break; + case SPDLOG_LEVEL_ERROR: + UE_LOG(LogCesium, Error, TEXT("%s"), *this->formatMessage(msg)); + break; + case SPDLOG_LEVEL_CRITICAL: + UE_LOG(LogCesium, Fatal, TEXT("%s"), *this->formatMessage(msg)); + break; + } +} + +void SpdlogUnrealLoggerSink::flush_() { + // Nothing to do here +} + +FString SpdlogUnrealLoggerSink::formatMessage( + const spdlog::details::log_msg& msg) const { + // Frustratingly, spdlog::formatter isn't thread safe. So even though our sink + // itself doesn't need to be protected by a mutex, the formatter does. + // See https://github.com/gabime/spdlog/issues/897 + std::scoped_lock lock(this->_formatMutex); + + spdlog::memory_buf_t formatted; + this->formatter_->format(msg, formatted); + return UTF8_TO_TCHAR(fmt::to_string(formatted).c_str()); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/SpdlogUnrealLoggerSink.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/SpdlogUnrealLoggerSink.h new file mode 100644 index 0000000..71b5917 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/SpdlogUnrealLoggerSink.h @@ -0,0 +1,25 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include +#include +#include +#include + +/** + * @brief Internal implementation of a spdlog sink that forwards the messages + * to Unreal log macros. + */ +class SpdlogUnrealLoggerSink + : public spdlog::sinks::base_sink { +protected: + virtual void sink_it_(const spdlog::details::log_msg& msg) override; + virtual void flush_() override; + +private: + FString formatMessage(const spdlog::details::log_msg& msg) const; + + mutable std::mutex _formatMutex; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/Cesium3DTileset.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/Cesium3DTileset.spec.cpp new file mode 100644 index 0000000..3b12352 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/Cesium3DTileset.spec.cpp @@ -0,0 +1,92 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "Cesium3DTileset.h" +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumGltfComponent.h" +#include "CesiumLoadTestCore.h" +#include "CesiumSceneGeneration.h" +#include "CesiumSunSky.h" +#include "CesiumTestHelpers.h" +#include "Engine/World.h" +#include "GlobeAwareDefaultPawn.h" +#include "Interfaces/IPluginManager.h" +#include "Misc/AutomationTest.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationTestSettings.h" +#include +#include + +#define TEST_SCREEN_WIDTH 1280 +#define TEST_SCREEN_HEIGHT 720 + +namespace Cesium { + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FCesium3DTilesetSharedImages, + "Cesium.Unit.3DTileset.SharedImages", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter); + +static void setupForSharedImages(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(21.16677692, -67.38013505, -6375355.1944), + FVector(-12, -1300, -5), + FRotator(0, 90, 0), + 60.0f); + + context.georeference->SetOriginEarthCenteredEarthFixed(FVector(0, 0, 0)); + context.pawn->SetActorLocation(FVector(485.0, 2400.0, 520.0)); + context.pawn->SetActorRotation(FQuat::MakeFromEuler(FVector(0, 0, 270))); + + context.sunSky->TimeZone = 9.0f; + context.sunSky->UpdateSun(); + + ACesiumGeoreference* georeference = + context.world->SpawnActor(); + check(georeference != nullptr); + georeference->SetOriginPlacement(EOriginPlacement::TrueOrigin); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + tileset->SetIonAssetID(2757071); + tileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + + tileset->SetActorLabel(TEXT("SharedImages")); + tileset->SetGeoreference(georeference); + tileset->SuspendUpdate = false; + tileset->LogSelectionStats = true; + context.tilesets.push_back(tileset); + + UCesiumGlobeAnchorComponent* GlobeAnchorComponent = + NewObject(tileset, TEXT("GlobeAnchor")); + tileset->AddInstanceComponent(GlobeAnchorComponent); + GlobeAnchorComponent->SetAdjustOrientationForGlobeWhenMoving(false); + GlobeAnchorComponent->SetGeoreference(georeference); + GlobeAnchorComponent->RegisterComponent(); + GlobeAnchorComponent->MoveToEarthCenteredEarthFixedPosition( + FVector(0.0, 0.0, 0.0)); + + ADirectionalLight* Light = context.world->SpawnActor(); + Light->SetActorRotation(FQuat::MakeFromEuler(FVector(0, 0, 270))); +} + +void tilesetPass( + SceneGenerationContext& context, + TestPass::TestingParameter parameter) {} + +bool FCesium3DTilesetSharedImages::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Refresh Pass", tilesetPass, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForSharedImages, + testPasses, + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); +} + +} // namespace Cesium + +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumCameraManager.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumCameraManager.spec.cpp new file mode 100644 index 0000000..a852d54 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumCameraManager.spec.cpp @@ -0,0 +1,90 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumCameraManager.h" +#include "CesiumTestHelpers.h" +#include "Engine/World.h" +#include "Misc/AutomationTest.h" + +BEGIN_DEFINE_SPEC( + FCesiumCameraManagerSpec, + "Cesium.Unit.CameraManager", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +END_DEFINE_SPEC(FCesiumCameraManagerSpec) + +void FCesiumCameraManagerSpec::Define() { + + Describe("GetDefaultCameraManager", [this]() { + It("should get the default camera manager", [this]() { + UWorld* world = CesiumTestHelpers::getGlobalWorldContext(); + ACesiumCameraManager* cameraManager = + ACesiumCameraManager::GetDefaultCameraManager(world); + TestNotNull("Returned pointer is valid", cameraManager); + }); + + It("should fail to get the default camera manager, when world context is null", + [this]() { + ACesiumCameraManager* cameraManager = + ACesiumCameraManager::GetDefaultCameraManager(nullptr); + TestNull("Returned pointer should be null", cameraManager); + }); + }); + + Describe("AddCamera", [this]() { + It("should add and remove a single camera", [this]() { + UWorld* world = CesiumTestHelpers::getGlobalWorldContext(); + ACesiumCameraManager* cameraManager = + ACesiumCameraManager::GetDefaultCameraManager(world); + TestNotNull("Returned pointer is valid", cameraManager); + + const TMap& camerasMapRef = + cameraManager->GetCameras(); + TestEqual("Starting camera count is 0", camerasMapRef.Num(), 0); + + FCesiumCamera newCamera; + int32 newCameraId = cameraManager->AddCamera(newCamera); + TestEqual( + "Camera count is 1 after camera is added", + camerasMapRef.Num(), + 1); + + bool removeSuccess = cameraManager->RemoveCamera(newCameraId); + TestTrue("Remove function returns success", removeSuccess); + TestEqual("Camera count returns to 0", camerasMapRef.Num(), 0); + }); + + It("should fail to remove a camera, when the id is invalid", [this]() { + UWorld* world = CesiumTestHelpers::getGlobalWorldContext(); + ACesiumCameraManager* cameraManager = + ACesiumCameraManager::GetDefaultCameraManager(world); + TestNotNull("Returned pointer is valid", cameraManager); + + const TMap& camerasMapRef = + cameraManager->GetCameras(); + TestEqual("Starting camera count is 0", camerasMapRef.Num(), 0); + + int32 bogusZeroCameraId = 0; + bool removeSuccess = cameraManager->RemoveCamera(bogusZeroCameraId); + TestFalse( + "Remove function fails with bogus zero camera id", + removeSuccess); + TestEqual("Camera count remains at 0", camerasMapRef.Num(), 0); + + int32 bogusPositiveCameraId = 5; + removeSuccess = cameraManager->RemoveCamera(bogusPositiveCameraId); + TestFalse( + "Remove function fails with bogus positive camera id", + removeSuccess); + TestEqual("Camera count remains at 0", camerasMapRef.Num(), 0); + + int32 bogusNegativeCameraId = -5; + removeSuccess = cameraManager->RemoveCamera(bogusNegativeCameraId); + TestFalse( + "Remove function fails with bogus negative camera id", + removeSuccess); + TestEqual("Camera count remains at 0", camerasMapRef.Num(), 0); + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdAttribute.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdAttribute.spec.cpp new file mode 100644 index 0000000..b517b4c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdAttribute.spec.cpp @@ -0,0 +1,279 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumFeatureIdAttribute.h" +#include "CesiumGltf/ExtensionExtMeshFeatures.h" +#include "CesiumGltfSpecUtility.h" +#include "Misc/AutomationTest.h" + +BEGIN_DEFINE_SPEC( + FCesiumFeatureIdAttributeSpec, + "Cesium.Unit.FeatureIdAttribute", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +CesiumGltf::Model model; +CesiumGltf::MeshPrimitive* pPrimitive; +END_DEFINE_SPEC(FCesiumFeatureIdAttributeSpec) + +void FCesiumFeatureIdAttributeSpec::Define() { + Describe("Constructor", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + }); + + It("constructs invalid instance for empty attribute", [this]() { + FCesiumFeatureIdAttribute featureIDAttribute; + + TestEqual("AttributeIndex", featureIDAttribute.getAttributeIndex(), -1); + TestEqual( + "FeatureIDAttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(featureIDAttribute), + ECesiumFeatureIdAttributeStatus::ErrorInvalidAttribute); + }); + + It("constructs invalid instance for nonexistent attribute", [this]() { + const int64 attributeIndex = 0; + FCesiumFeatureIdAttribute featureIDAttribute( + model, + *pPrimitive, + attributeIndex, + "PropertyTableName"); + TestEqual( + "AttributeIndex", + featureIDAttribute.getAttributeIndex(), + attributeIndex); + TestEqual( + "FeatureIDAttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(featureIDAttribute), + ECesiumFeatureIdAttributeStatus::ErrorInvalidAttribute); + }); + + It("constructs invalid instance for attribute with nonexistent accessor", + [this]() { + const int64 attributeIndex = 0; + pPrimitive->attributes.insert({"_FEATURE_ID_0", 0}); + + FCesiumFeatureIdAttribute featureIDAttribute( + model, + *pPrimitive, + attributeIndex, + "PropertyTableName"); + TestEqual( + "AttributeIndex", + featureIDAttribute.getAttributeIndex(), + attributeIndex); + TestEqual( + "FeatureIDAttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(featureIDAttribute), + ECesiumFeatureIdAttributeStatus::ErrorInvalidAccessor); + }); + + It("constructs invalid instance for attribute with invalid accessor", + [this]() { + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.type = CesiumGltf::AccessorSpec::Type::VEC2; + accessor.componentType = + CesiumGltf::AccessorSpec::ComponentType::FLOAT; + const int64 attributeIndex = 0; + pPrimitive->attributes.insert({"_FEATURE_ID_0", 0}); + + FCesiumFeatureIdAttribute featureIDAttribute( + model, + *pPrimitive, + attributeIndex, + "PropertyTableName"); + TestEqual( + "AttributeIndex", + featureIDAttribute.getAttributeIndex(), + attributeIndex); + TestEqual( + "FeatureIDAttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(featureIDAttribute), + ECesiumFeatureIdAttributeStatus::ErrorInvalidAccessor); + }); + + It("constructs valid instance", [this]() { + const int64 attributeIndex = 0; + const std::vector featureIDs{0, 0, 0, 3, 3, 3, 1, 1, 1, 2, 2, 2}; + AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 4, + attributeIndex); + + FCesiumFeatureIdAttribute featureIDAttribute( + model, + *pPrimitive, + attributeIndex, + "PropertyTableName"); + TestEqual( + "AttributeIndex", + featureIDAttribute.getAttributeIndex(), + attributeIndex); + TestEqual( + "FeatureIDAttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(featureIDAttribute), + ECesiumFeatureIdAttributeStatus::Valid); + }); + }); + + Describe("GetCount", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + }); + + It("returns 0 for invalid attribute", [this]() { + const int64 attributeIndex = 0; + pPrimitive->attributes.insert({"_FEATURE_ID_0", 0}); + + FCesiumFeatureIdAttribute featureIDAttribute( + model, + *pPrimitive, + attributeIndex, + "PropertyTableName"); + TestEqual( + "FeatureIDAttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(featureIDAttribute), + ECesiumFeatureIdAttributeStatus::ErrorInvalidAccessor); + TestEqual( + "VertexCount", + UCesiumFeatureIdAttributeBlueprintLibrary::GetCount( + featureIDAttribute), + 0); + }); + + It("returns correct value for valid attribute", [this]() { + const int64 attributeIndex = 0; + const std::vector featureIDs{0, 0, 0, 3, 3, 3, 1, 1, 1, 2, 2, 2}; + const int64 vertexCount = static_cast(featureIDs.size()); + AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 4, + attributeIndex); + + FCesiumFeatureIdAttribute featureIDAttribute( + model, + *pPrimitive, + attributeIndex, + "PropertyTableName"); + TestEqual( + "FeatureIDAttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(featureIDAttribute), + ECesiumFeatureIdAttributeStatus::Valid); + TestEqual( + "VertexCount", + UCesiumFeatureIdAttributeBlueprintLibrary::GetCount( + featureIDAttribute), + vertexCount); + }); + }); + + Describe("GetFeatureID", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + }); + + It("returns -1 for invalid attribute", [this]() { + const int64 attribute = 0; + pPrimitive->attributes.insert({"_FEATURE_ID_0", 0}); + + FCesiumFeatureIdAttribute featureIDAttribute( + model, + *pPrimitive, + attribute, + "PropertyTableName"); + TestEqual( + "FeatureIDAttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(featureIDAttribute), + ECesiumFeatureIdAttributeStatus::ErrorInvalidAccessor); + TestEqual( + "FeatureIDForVertex", + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + featureIDAttribute, + 0), + -1); + }); + + It("returns -1 for out-of-bounds index", [this]() { + const int64 attributeIndex = 0; + const std::vector featureIDs{0, 0, 0, 1, 1, 1}; + AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 2, + attributeIndex); + + FCesiumFeatureIdAttribute featureIDAttribute( + model, + *pPrimitive, + attributeIndex, + "PropertyTableName"); + TestEqual( + "FeatureIDAttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(featureIDAttribute), + ECesiumFeatureIdAttributeStatus::Valid); + TestEqual( + "FeatureIDForNegativeVertex", + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + featureIDAttribute, + -1), + -1); + TestEqual( + "FeatureIDForOutOfBoundsVertex", + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + featureIDAttribute, + 10), + -1); + }); + + It("returns correct value for valid attribute", [this]() { + const int64 attributeIndex = 0; + const std::vector featureIDs{0, 0, 0, 3, 3, 3, 1, 1, 1, 2, 2, 2}; + AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 4, + attributeIndex); + + FCesiumFeatureIdAttribute featureIDAttribute( + model, + *pPrimitive, + attributeIndex, + "PropertyTableName"); + TestEqual( + "FeatureIDAttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(featureIDAttribute), + ECesiumFeatureIdAttributeStatus::Valid); + for (size_t i = 0; i < featureIDs.size(); i++) { + TestEqual( + "FeatureIDForVertex", + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID( + featureIDAttribute, + static_cast(i)), + featureIDs[i]); + } + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdSet.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdSet.spec.cpp new file mode 100644 index 0000000..7da2be0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdSet.spec.cpp @@ -0,0 +1,655 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumFeatureIdSet.h" +#include "CesiumGltf/ExtensionExtMeshFeatures.h" +#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumGltfSpecUtility.h" +#include "Misc/AutomationTest.h" + +BEGIN_DEFINE_SPEC( + FCesiumFeatureIdSetSpec, + "Cesium.Unit.FeatureIdSet", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +CesiumGltf::Model model; +CesiumGltf::MeshPrimitive* pPrimitive; +TObjectPtr pPrimitiveComponent; +END_DEFINE_SPEC(FCesiumFeatureIdSetSpec) + +void FCesiumFeatureIdSetSpec::Define() { + Describe("Constructor", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + pPrimitive->addExtension(); + }); + + It("constructs from empty feature ID set", [this]() { + // This is technically disallowed by the spec, but just make sure it's + // handled reasonably. + CesiumGltf::FeatureId featureId; + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + TestEqual( + "FeatureIDType", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + featureIDSet), + ECesiumFeatureIdSetType::None); + TestEqual( + "FeatureCount", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(featureIDSet), + 0); + }); + + It("constructs implicit feature ID set", [this]() { + CesiumGltf::FeatureId featureId; + featureId.featureCount = 10; + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + TestEqual( + "FeatureIDType", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + featureIDSet), + ECesiumFeatureIdSetType::Implicit); + TestEqual( + "FeatureCount", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(featureIDSet), + static_cast(featureId.featureCount)); + }); + + It("constructs set with feature ID attribute", [this]() { + const int64 attributeIndex = 0; + const std::vector featureIDs{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 4, + attributeIndex); + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureID); + TestEqual( + "FeatureIDType", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + featureIDSet), + ECesiumFeatureIdSetType::Attribute); + TestEqual( + "FeatureCount", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(featureIDSet), + static_cast(featureID.featureCount)); + }); + + It("constructs set with feature ID texture", [this]() { + const std::vector featureIDs{0, 3, 1, 2}; + const std::vector texCoords{ + glm::vec2(0, 0), + glm::vec2(0.5, 0), + glm::vec2(0, 0.5), + glm::vec2(0.5, 0.5)}; + + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords, + 0); + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + TestEqual( + "FeatureIDType", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + featureIDSet), + ECesiumFeatureIdSetType::Texture); + TestEqual( + "FeatureCount", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(featureIDSet), + static_cast(featureId.featureCount)); + }); + + It("constructs with null feature ID", [this]() { + CesiumGltf::FeatureId featureId; + featureId.featureCount = 10; + featureId.nullFeatureId = 0; + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + TestEqual( + "FeatureIDType", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + featureIDSet), + ECesiumFeatureIdSetType::Implicit); + TestEqual( + "FeatureCount", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(featureIDSet), + static_cast(featureId.featureCount)); + TestEqual( + "NullFeatureID", + UCesiumFeatureIdSetBlueprintLibrary::GetNullFeatureID(featureIDSet), + static_cast(*featureId.nullFeatureId)); + }); + + It("constructs with property table index", [this]() { + CesiumGltf::FeatureId featureId; + featureId.featureCount = 10; + featureId.propertyTable = 1; + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + TestEqual( + "FeatureIDType", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + featureIDSet), + ECesiumFeatureIdSetType::Implicit); + TestEqual( + "FeatureCount", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(featureIDSet), + static_cast(featureId.featureCount)); + TestEqual( + "PropertyTableIndex", + UCesiumFeatureIdSetBlueprintLibrary::GetPropertyTableIndex( + featureIDSet), + static_cast(featureId.propertyTable)); + }); + }); + + Describe("GetAsFeatureIDAttribute", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + }); + + It("returns empty instance for non-attribute feature ID set", [this]() { + CesiumGltf::FeatureId featureId; + featureId.featureCount = 10; + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + const FCesiumFeatureIdAttribute attribute = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute( + featureIDSet); + TestEqual( + "AttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(attribute), + ECesiumFeatureIdAttributeStatus::ErrorInvalidAttribute); + TestEqual("AttributeIndex", attribute.getAttributeIndex(), -1); + }); + + It("returns valid instance for attribute feature ID set", [this]() { + const int64 attributeIndex = 0; + const std::vector featureIDs{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 4, + attributeIndex); + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureID); + const FCesiumFeatureIdAttribute attribute = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute( + featureIDSet); + TestEqual( + "AttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(attribute), + ECesiumFeatureIdAttributeStatus::Valid); + TestEqual( + "AttributeIndex", + attribute.getAttributeIndex(), + attributeIndex); + }); + }); + + Describe("GetAsFeatureIDTexture", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + }); + + It("returns empty instance for non-texture feature ID set", [this]() { + CesiumGltf::FeatureId featureId; + featureId.featureCount = 10; + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + const FCesiumFeatureIdTexture texture = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDTexture( + featureIDSet); + TestEqual( + "TextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + texture), + ECesiumFeatureIdTextureStatus::ErrorInvalidTexture); + + auto featureIDTextureView = texture.getFeatureIdTextureView(); + TestEqual( + "FeatureIDTextureViewStatus", + featureIDTextureView.status(), + CesiumGltf::FeatureIdTextureViewStatus::ErrorUninitialized); + }); + + It("returns valid instance for texture feature ID set", [this]() { + const std::vector featureIDs{0, 3, 1, 2}; + const std::vector texCoords{ + glm::vec2(0, 0), + glm::vec2(0.5, 0), + glm::vec2(0, 0.5), + glm::vec2(0.5, 0.5)}; + + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords, + 0); + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + const FCesiumFeatureIdTexture texture = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDTexture( + featureIDSet); + TestEqual( + "TextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + texture), + ECesiumFeatureIdTextureStatus::Valid); + + auto featureIDTextureView = texture.getFeatureIdTextureView(); + TestEqual( + "FeatureIDTextureViewStatus", + featureIDTextureView.status(), + CesiumGltf::FeatureIdTextureViewStatus::Valid); + }); + }); + + Describe("GetFeatureIDForVertex", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + }); + + It("returns -1 for empty feature ID set", [this]() { + FCesiumFeatureIdSet featureIDSet; + TestEqual( + "FeatureIDForVertex", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForVertex( + featureIDSet, + 0), + -1); + }); + + It("returns -1 for out of bounds index", [this]() { + CesiumGltf::FeatureId featureId; + featureId.featureCount = 10; + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + TestEqual( + "FeatureIDForVertex", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForVertex( + featureIDSet, + -1), + -1); + TestEqual( + "FeatureIDForVertex", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForVertex( + featureIDSet, + 11), + -1); + }); + + It("returns correct value for implicit set", [this]() { + CesiumGltf::FeatureId featureId; + featureId.featureCount = 10; + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + for (int64 i = 0; i < featureId.featureCount; i++) { + TestEqual( + "FeatureIDForVertex", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForVertex( + featureIDSet, + i), + i); + } + }); + + It("returns correct value for attribute set", [this]() { + const int64 attributeIndex = 0; + const std::vector featureIDs{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 4, + attributeIndex); + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureID); + for (size_t i = 0; i < featureIDs.size(); i++) { + TestEqual( + "FeatureIDForVertex", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForVertex( + featureIDSet, + static_cast(i)), + featureIDs[i]); + } + }); + + It("returns correct value for texture set", [this]() { + const std::vector featureIDs{0, 3, 1, 2}; + const std::vector texCoords{ + glm::vec2(0, 0), + glm::vec2(0.5, 0), + glm::vec2(0, 0.5), + glm::vec2(0.5, 0.5)}; + + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords, + 0); + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureID); + for (size_t i = 0; i < featureIDs.size(); i++) { + TestEqual( + "FeatureIDForVertex", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForVertex( + featureIDSet, + static_cast(i)), + featureIDs[i]); + } + }); + }); + + Describe("GetFeatureIDFromHit", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + pPrimitive->mode = CesiumGltf::MeshPrimitive::Mode::TRIANGLES; + pPrimitiveComponent = NewObject(); + pPrimitiveComponent->getPrimitiveData().pMeshPrimitive = pPrimitive; + + std::vector positions{ + glm::vec3(-1, 0, 0), + glm::vec3(0, 1, 0), + glm::vec3(1, 0, 0), + glm::vec3(-1, 3, 0), + glm::vec3(0, 4, 0), + glm::vec3(1, 3, 0), + }; + + CreateAttributeForPrimitive( + model, + *pPrimitive, + "POSITION", + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, + positions); + }); + + It("returns -1 for empty feature ID set", [this]() { + FCesiumFeatureIdSet featureIDSet; + TestEqual( + "FeatureIDForVertex", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForVertex( + featureIDSet, + 0), + -1); + }); + + It("returns -1 for invalid hit component", [this]() { + CesiumGltf::FeatureId featureId; + featureId.featureCount = 6; + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = CesiumGltf::AccessorView( + model, + static_cast(model.accessors.size() - 1)); + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + + FHitResult Hit; + Hit.Component = nullptr; + Hit.FaceIndex = 0; + + TestEqual( + "FeatureIDFromHit", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDFromHit( + featureIDSet, + Hit), + -1); + }); + + It("returns correct value for texture set", [this]() { + int32 positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + // For convenience when testing, the UVs are the same as the positions + // they correspond to. This means that the interpolated UV value should be + // directly equal to the barycentric coordinates of the triangle. + std::vector texCoords{ + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0), + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0)}; + const std::vector featureIDs{0, 3, 1, 2}; + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords, + 0); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + primData.TexCoordAccessorMap.emplace( + 0, + CesiumGltf::AccessorView>( + model, + static_cast(model.accessors.size() - 1))); + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureID); + + FHitResult Hit; + Hit.Component = pPrimitiveComponent; + Hit.FaceIndex = 0; + + std::array locations{ + FVector_NetQuantize(1, 0, 0), + FVector_NetQuantize(0, -1, 0), + FVector_NetQuantize(0.0, -0.25, 0)}; + std::array expected{3, 1, 0}; + + for (size_t i = 0; i < locations.size(); i++) { + Hit.Location = locations[i] * CesiumPrimitiveData::positionScaleFactor; + TestEqual( + "FeatureIDFromHit", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDFromHit( + featureIDSet, + Hit), + expected[i]); + } + }); + + It("returns correct value for implicit set", [this]() { + CesiumGltf::FeatureId featureId; + featureId.featureCount = 6; + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = CesiumGltf::AccessorView( + model, + static_cast(model.accessors.size() - 1)); + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + + FHitResult Hit; + Hit.Component = pPrimitiveComponent; + Hit.FaceIndex = 0; + + std::array faceIndices{0, 1, 0}; + std::array locations{ + FVector_NetQuantize(1, 0, 0), + FVector_NetQuantize(0, -4, 0), + FVector_NetQuantize(-1, 0, 0)}; + std::array expected{0, 3, 0}; + for (size_t i = 0; i < locations.size(); i++) { + Hit.FaceIndex = faceIndices[i]; + Hit.Location = locations[i] * CesiumPrimitiveData::positionScaleFactor; + TestEqual( + "FeatureIDFromHit", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDFromHit( + featureIDSet, + Hit), + expected[i]); + } + }); + + It("returns correct value for attribute set", [this]() { + int32_t positionAccessorIndex = + static_cast(model.accessors.size() - 1); + const int64 attributeIndex = 0; + const std::vector featureIDs{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 2, + attributeIndex); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); + + FHitResult Hit; + Hit.Component = pPrimitiveComponent; + Hit.FaceIndex = 0; + Hit.Location = FVector_NetQuantize(0, -1, 0) * + CesiumPrimitiveData::positionScaleFactor; + TestEqual( + "FeatureIDFromHit", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDFromHit( + featureIDSet, + Hit), + 0); + + Hit.FaceIndex = 1; + Hit.Location = FVector_NetQuantize(0, -4, 0) * + CesiumPrimitiveData::positionScaleFactor; + TestEqual( + "FeatureIDFromHit", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDFromHit( + featureIDSet, + Hit), + 1); + }); + }); + + Describe("Deprecated", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + }); + + It("backwards compatibility for FCesiumFeatureIdAttribute.GetFeatureTableName", + [this]() { + const int64 attributeIndex = 0; + const std::vector featureIDs{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 4, + attributeIndex); + featureID.propertyTable = 0; + + const std::string expectedName = "PropertyTableName"; + + CesiumGltf::ExtensionModelExtStructuralMetadata& metadataExtension = + model.addExtension< + CesiumGltf::ExtensionModelExtStructuralMetadata>(); + CesiumGltf::PropertyTable& propertyTable = + metadataExtension.propertyTables.emplace_back(); + propertyTable.name = expectedName; + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureID); + const FCesiumFeatureIdAttribute attribute = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute( + featureIDSet); + TestEqual( + "AttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(attribute), + ECesiumFeatureIdAttributeStatus::Valid); + TestEqual( + "GetFeatureTableName", + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureTableName( + attribute), + FString(expectedName.c_str())); + }); + + It("backwards compatibility for FCesiumFeatureIdTexture.GetFeatureTableName", + [this]() { + const std::vector featureIDs{0, 3, 1, 2}; + const std::vector texCoords{ + glm::vec2(0, 0), + glm::vec2(0.5, 0), + glm::vec2(0, 0.5), + glm::vec2(0.5, 0.5)}; + + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords, + 0); + featureID.propertyTable = 0; + + const std::string expectedName = "PropertyTableName"; + + CesiumGltf::ExtensionModelExtStructuralMetadata& metadataExtension = + model.addExtension< + CesiumGltf::ExtensionModelExtStructuralMetadata>(); + CesiumGltf::PropertyTable& propertyTable = + metadataExtension.propertyTables.emplace_back(); + propertyTable.name = expectedName; + + FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureID); + const FCesiumFeatureIdTexture texture = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDTexture( + featureIDSet); + TestEqual( + "TextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + texture), + ECesiumFeatureIdTextureStatus::Valid); + TestEqual( + "GetFeatureTableName", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureTableName( + texture), + FString(expectedName.c_str())); + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdTexture.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdTexture.spec.cpp new file mode 100644 index 0000000..982d475 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdTexture.spec.cpp @@ -0,0 +1,921 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumFeatureIdTexture.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumGltfSpecUtility.h" +#include "Misc/AutomationTest.h" +#include +#include +#include + +BEGIN_DEFINE_SPEC( + FCesiumFeatureIdTextureSpec, + "Cesium.Unit.FeatureIdTexture", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +CesiumGltf::Model model; +CesiumGltf::MeshPrimitive* pPrimitive; +const std::vector texCoords{ + glm::vec2(0, 0), + glm::vec2(0.5, 0), + glm::vec2(0, 0.5), + glm::vec2(0.5, 0.5)}; +TObjectPtr pPrimitiveComponent; +END_DEFINE_SPEC(FCesiumFeatureIdTextureSpec) + +void FCesiumFeatureIdTextureSpec::Define() { + Describe("Constructor", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + }); + + It("constructs invalid instance for empty texture", [this]() { + FCesiumFeatureIdTexture featureIDTexture; + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::ErrorInvalidTexture); + + auto featureIDTextureView = featureIDTexture.getFeatureIdTextureView(); + TestEqual( + "FeatureIDTextureViewStatus", + featureIDTextureView.status(), + CesiumGltf::FeatureIdTextureViewStatus::ErrorUninitialized); + }); + + It("constructs invalid instance for nonexistent texture", [this]() { + CesiumGltf::FeatureIdTexture texture; + texture.index = -1; + texture.texCoord = 0; + texture.channels = {0}; + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::ErrorInvalidTexture); + + auto featureIDTextureView = featureIDTexture.getFeatureIdTextureView(); + TestEqual( + "FeatureIDTextureViewStatus", + featureIDTextureView.status(), + CesiumGltf::FeatureIdTextureViewStatus::ErrorInvalidTexture); + }); + + It("constructs invalid instance for texture with invalid image", [this]() { + CesiumGltf::Texture& gltfTexture = model.textures.emplace_back(); + gltfTexture.source = -1; + + CesiumGltf::FeatureIdTexture texture; + texture.index = 0; + texture.texCoord = 0; + texture.channels = {0}; + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::ErrorInvalidTexture); + + auto featureIDTextureView = featureIDTexture.getFeatureIdTextureView(); + TestEqual( + "FeatureIDTextureViewStatus", + featureIDTextureView.status(), + CesiumGltf::FeatureIdTextureViewStatus::ErrorInvalidImage); + }); + + It("constructs valid instance", [this]() { + const std::vector featureIDs{0, 3, 1, 2}; + + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords, + 0); + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + *featureId.texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + auto featureIDTextureView = featureIDTexture.getFeatureIdTextureView(); + TestEqual( + "FeatureIDTextureViewStatus", + featureIDTextureView.status(), + CesiumGltf::FeatureIdTextureViewStatus::Valid); + }); + + It("constructs valid instance for texture with nonexistent texcoord attribute", + [this]() { + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset.emplace(); + image.pAsset->width = image.pAsset->height = 1; + image.pAsset->channels = 1; + image.pAsset->pixelData.push_back(std::byte(42)); + + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); + sampler.wrapS = CesiumGltf::Sampler::WrapS::CLAMP_TO_EDGE; + sampler.wrapT = CesiumGltf::Sampler::WrapT::CLAMP_TO_EDGE; + + CesiumGltf::Texture& gltfTexture = model.textures.emplace_back(); + gltfTexture.source = 0; + gltfTexture.sampler = 0; + + CesiumGltf::FeatureIdTexture texture; + texture.index = 0; + texture.texCoord = 0; + texture.channels = {0}; + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + auto featureIDTextureView = featureIDTexture.getFeatureIdTextureView(); + TestEqual( + "FeatureIDTextureViewStatus", + featureIDTextureView.status(), + CesiumGltf::FeatureIdTextureViewStatus::Valid); + }); + + It("constructs valid instance for texture with invalid texcoord accessor", + [this]() { + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset.emplace(); + image.pAsset->width = image.pAsset->height = 1; + image.pAsset->channels = 1; + image.pAsset->pixelData.push_back(std::byte(42)); + + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); + sampler.wrapS = CesiumGltf::Sampler::WrapS::CLAMP_TO_EDGE; + sampler.wrapT = CesiumGltf::Sampler::WrapT::CLAMP_TO_EDGE; + + CesiumGltf::Texture& gltfTexture = model.textures.emplace_back(); + gltfTexture.source = 0; + gltfTexture.sampler = 0; + + CesiumGltf::FeatureIdTexture texture; + texture.index = 0; + texture.texCoord = 0; + texture.channels = {0}; + + pPrimitive->attributes.insert({"TEXCOORD_0", 0}); + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + auto featureIDTextureView = featureIDTexture.getFeatureIdTextureView(); + TestEqual( + "FeatureIDTextureViewStatus", + featureIDTextureView.status(), + CesiumGltf::FeatureIdTextureViewStatus::Valid); + }); + }); + + Describe("GetFeatureIDForUV", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + }); + + It("returns -1 for invalid texture", [this]() { + CesiumGltf::Texture& gltfTexture = model.textures.emplace_back(); + gltfTexture.source = -1; + + CesiumGltf::FeatureIdTexture texture; + texture.index = 0; + texture.texCoord = 0; + texture.channels = {0}; + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + texture, + "PropertyTableName"); + + TestNotEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + TestEqual( + "FeatureID", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForUV( + featureIDTexture, + FVector2D::Zero()), + -1); + }); + + It("returns correct value for valid attribute", [this]() { + const std::vector featureIDs{0, 3, 1, 2}; + + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords, + 0); + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + *featureId.texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + const glm::vec2& texCoord = texCoords[i]; + int64 featureID = + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForUV( + featureIDTexture, + {texCoord.x, texCoord.y}); + TestEqual("FeatureID", featureID, featureIDs[i]); + } + }); + + It("returns correct value with KHR_texture_transform", [this]() { + const std::vector featureIDs{1, 2, 0, 7}; + const std::vector rawTexCoords{ + glm::vec2(0, 0), + glm::vec2(1, 0), + glm::vec2(0, 1), + glm::vec2(1, 1)}; + + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + rawTexCoords, + 0, + CesiumGltf::Sampler::WrapS::REPEAT, + CesiumGltf::Sampler::WrapT::REPEAT); + + assert(featureId.texture != std::nullopt); + CesiumGltf::ExtensionKhrTextureTransform& textureTransform = + featureId.texture + ->addExtension(); + textureTransform.offset = {0.5, -0.5}; + textureTransform.rotation = UE_DOUBLE_HALF_PI; + textureTransform.scale = {0.5, 0.5}; + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + *featureId.texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + // (0, 0) -> (0.5, -0.5) -> wraps to (0.5, 0.5) + // (1, 0) -> (0.5, -1) -> wraps to (0.5, 0) + // (0, 1) -> (1, -0.5) -> wraps to (0, 0.5) + // (1, 1) -> (1, -1) -> wraps to (0.0, 0.0) + std::vector expected{7, 2, 0, 1}; + + for (size_t i = 0; i < texCoords.size(); i++) { + const glm::vec2& texCoord = rawTexCoords[i]; + int64 featureID = + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForUV( + featureIDTexture, + {texCoord.x, texCoord.y}); + TestEqual("FeatureID", featureID, expected[i]); + } + }); + }); + + Describe("GetFeatureIDForVertex", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + }); + + It("returns -1 for invalid texture", [this]() { + CesiumGltf::FeatureIdTexture texture; + texture.index = -1; + texture.texCoord = 0; + texture.channels = {0}; + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + texture, + "PropertyTableName"); + + TestNotEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + TestEqual( + "FeatureIDForVertex", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex( + featureIDTexture, + 0), + -1); + }); + + It("returns -1 for out-of-bounds index", [this]() { + const std::vector featureIDs{0, 3, 1, 2}; + + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords, + 0); + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + *featureId.texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + TestEqual( + "FeatureIDForNegativeVertex", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex( + featureIDTexture, + -1), + -1); + + TestEqual( + "FeatureIDForOutOfBoundsVertex", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex( + featureIDTexture, + 10), + -1); + }); + + It("returns correct value for valid texture", [this]() { + const std::vector featureIDs{0, 3, 1, 2}; + + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords, + 0); + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + *featureId.texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + for (size_t i = 0; i < featureIDs.size(); i++) { + int64 featureID = + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex( + featureIDTexture, + static_cast(i)); + TestEqual("FeatureIDForVertex", featureID, featureIDs[i]); + } + }); + + It("returns correct value for primitive with multiple texcoords", [this]() { + const std::vector texCoord0{ + glm::vec2(0, 0), + glm::vec2(0.5, 0), + glm::vec2(0, 0.5), + glm::vec2(0.5, 0.5)}; + + std::vector values(texCoord0.size()); + std::memcpy(values.data(), texCoord0.data(), values.size()); + + CreateAttributeForPrimitive( + model, + *pPrimitive, + "TEXCOORD_0", + CesiumGltf::AccessorSpec::Type::VEC2, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, + std::move(values)); + + const std::vector texCoord1{ + glm::vec2(0.5, 0.5), + glm::vec2(0, 0), + glm::vec2(0.5, 0), + glm::vec2(0.0, 0.5)}; + + const std::vector featureIDs{0, 3, 1, 2}; + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoord1, + 1); + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + *featureId.texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + const std::vector expected{2, 0, 3, 1}; + for (size_t i = 0; i < featureIDs.size(); i++) { + int64 featureID = + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex( + featureIDTexture, + static_cast(i)); + TestEqual("FeatureIDForVertex", featureID, expected[i]); + } + }); + }); + + Describe("GetFeatureIDFromHit", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + pPrimitive->mode = CesiumGltf::MeshPrimitive::Mode::TRIANGLES; + pPrimitiveComponent = NewObject(); + pPrimitiveComponent->getPrimitiveData().pMeshPrimitive = pPrimitive; + + std::vector positions{ + glm::vec3(-1, 0, 0), + glm::vec3(0, 1, 0), + glm::vec3(1, 0, 0), + glm::vec3(-1, 3, 0), + glm::vec3(0, 4, 0), + glm::vec3(1, 3, 0), + }; + + CreateAttributeForPrimitive( + model, + *pPrimitive, + "POSITION", + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, + positions); + }); + + It("returns -1 for invalid texture", [this]() { + CesiumGltf::FeatureIdTexture texture; + texture.index = -1; + texture.texCoord = 0; + texture.channels = {0}; + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + texture, + "PropertyTableName"); + + TestNotEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + FHitResult Hit; + Hit.Location = FVector_NetQuantize::Zero() * + CesiumPrimitiveData::positionScaleFactor; + Hit.Component = pPrimitiveComponent; + Hit.FaceIndex = 0; + + TestEqual( + "FeatureIDFromHit", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit( + featureIDTexture, + Hit), + -1); + }); + + It("returns -1 if hit has no valid component", [this]() { + int32 positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + // For convenience when testing, the UVs are the same as the positions + // they correspond to. This means that the interpolated UV value should be + // directly equal to the barycentric coordinates of the triangle. + std::vector texCoords0{ + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0), + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0)}; + + const std::vector featureIDs{0, 3, 1, 2}; + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords0, + 0); + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + primData.TexCoordAccessorMap.emplace( + 0, + CesiumGltf::AccessorView>( + model, + static_cast(model.accessors.size() - 1))); + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + *featureId.texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + FHitResult Hit; + Hit.Location = FVector_NetQuantize(0, -1, 0) * + CesiumPrimitiveData::positionScaleFactor; + Hit.FaceIndex = 0; + Hit.Component = nullptr; + + TestEqual( + "FeatureIDFromHit", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit( + featureIDTexture, + Hit), + -1); + }); + + It("returns -1 if specified texcoord set does not exist", [this]() { + int32 positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + // For convenience when testing, the UVs are the same as the positions + // they correspond to. This means that the interpolated UV value should be + // directly equal to the barycentric coordinates of the triangle. + std::vector texCoords0{ + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0), + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0)}; + + const std::vector featureIDs{0, 3, 1, 2}; + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords0, + 0); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + primData.TexCoordAccessorMap.emplace( + 1, + CesiumGltf::AccessorView>( + model, + static_cast(model.accessors.size() - 1))); + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + *featureId.texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + FHitResult Hit; + Hit.Location = FVector_NetQuantize(0, -1, 0) * + CesiumPrimitiveData::positionScaleFactor; + Hit.FaceIndex = 0; + Hit.Component = pPrimitiveComponent; + + TestEqual( + "FeatureIDFromHit", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit( + featureIDTexture, + Hit), + -1); + }); + + It("returns correct value for valid texture", [this]() { + int32 positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + // For convenience when testing, the UVs are the same as the positions + // they correspond to. This means that the interpolated UV value should be + // directly equal to the barycentric coordinates of the triangle. + std::vector texCoords0{ + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0), + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0)}; + + const std::vector featureIDs{0, 3, 1, 2}; + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords0, + 0); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + primData.TexCoordAccessorMap.emplace( + 0, + CesiumGltf::AccessorView>( + model, + static_cast(model.accessors.size() - 1))); + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + *featureId.texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + FHitResult Hit; + Hit.FaceIndex = 0; + Hit.Component = pPrimitiveComponent; + + std::array locations{ + FVector_NetQuantize(1, 0, 0), + FVector_NetQuantize(0, -1, 0), + FVector_NetQuantize(0.0, -0.25, 0)}; + std::array expected{3, 1, 0}; + + for (size_t i = 0; i < locations.size(); i++) { + Hit.Location = locations[i] * CesiumPrimitiveData::positionScaleFactor; + int64 featureID = + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit( + featureIDTexture, + Hit); + TestEqual("FeatureIDFromHit", featureID, expected[i]); + } + }); + + It("returns correct value for different face", [this]() { + int32 positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + // For convenience when testing, the UVs are the same as the positions + // they correspond to. This means that the interpolated UV value should be + // directly equal to the barycentric coordinates of the triangle. + std::vector texCoords0{ + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0), + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0)}; + + const std::vector featureIDs{0, 3, 1, 2}; + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords0, + 0); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + primData.TexCoordAccessorMap.emplace( + 0, + CesiumGltf::AccessorView>( + model, + static_cast(model.accessors.size() - 1))); + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + *featureId.texture, + "PropertyTableName"); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + FHitResult Hit; + Hit.FaceIndex = 1; + Hit.Component = pPrimitiveComponent; + + std::array locations{ + FVector_NetQuantize(1, 3, 0), + FVector_NetQuantize(0, -4, 0), + FVector_NetQuantize(0.0, -3.25, 0)}; + std::array expected{3, 1, 0}; + + for (size_t i = 0; i < locations.size(); i++) { + Hit.Location = locations[i] * CesiumPrimitiveData::positionScaleFactor; + int64 featureID = + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit( + featureIDTexture, + Hit); + TestEqual("FeatureIDFromHit", featureID, expected[i]); + } + }); + + It("returns correct value for primitive with multiple texcoords", [this]() { + int32 positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + // For convenience when testing, the UVs are the same as the positions + // they correspond to. This means that the interpolated UV value should be + // directly equal to the barycentric coordinates of the triangle. + std::vector texCoords0{ + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0), + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0)}; + + CreateAttributeForPrimitive( + model, + *pPrimitive, + "TEXCOORD_0", + CesiumGltf::AccessorSpec::Type::VEC2, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, + GetValuesAsBytes(texCoords0)); + int32 texCoord0AccessorIndex = + static_cast(model.accessors.size() - 1); + + std::vector texCoords1{ + glm::vec2(0.5, 0.5), + glm::vec2(0, 1.0), + glm::vec2(1, 0), + glm::vec2(0.5, 0.5), + glm::vec2(0, 1.0), + glm::vec2(1, 0), + }; + const std::vector featureIDs{0, 3, 1, 2}; + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + featureIDs, + 4, + 2, + 2, + texCoords1, + 1); + + FCesiumFeatureIdTexture featureIDTexture( + model, + *pPrimitive, + *featureId.texture, + "PropertyTableName"); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + primData.TexCoordAccessorMap.emplace( + 0, + CesiumGltf::AccessorView>( + model, + texCoord0AccessorIndex)); + primData.TexCoordAccessorMap.emplace( + 0, + CesiumGltf::AccessorView>( + model, + 1)); + primData.TexCoordAccessorMap.emplace( + 1, + CesiumGltf::AccessorView>( + model, + static_cast(model.accessors.size() - 1))); + + TestEqual( + "FeatureIDTextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + featureIDTexture), + ECesiumFeatureIdTextureStatus::Valid); + + FHitResult Hit; + Hit.FaceIndex = 0; + Hit.Component = pPrimitiveComponent; + + std::array locations{ + FVector_NetQuantize(1, 0, 0), + FVector_NetQuantize(0, -1, 0), + FVector_NetQuantize(-1, 0, 0)}; + std::array expected{3, 1, 2}; + + for (size_t i = 0; i < locations.size(); i++) { + Hit.Location = locations[i] * CesiumPrimitiveData::positionScaleFactor; + int64 featureID = + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit( + featureIDTexture, + Hit); + TestEqual("FeatureIDFromHit", featureID, expected[i]); + } + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGeoreference.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGeoreference.spec.cpp new file mode 100644 index 0000000..754b26e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGeoreference.spec.cpp @@ -0,0 +1,219 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGeoreference.h" +#include "CesiumGeospatial/Ellipsoid.h" +#include "CesiumTestHelpers.h" +#include "CesiumUtility/Math.h" +#include "GeoTransforms.h" +#include "Misc/AutomationTest.h" + +using namespace CesiumGeospatial; +using namespace CesiumUtility; + +BEGIN_DEFINE_SPEC( + FCesiumGeoreferenceSpec, + "Cesium.Unit.Georeference", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) + +TObjectPtr pGeoreferenceNullIsland; +TObjectPtr pGeoreference90Longitude; + +END_DEFINE_SPEC(FCesiumGeoreferenceSpec) + +void FCesiumGeoreferenceSpec::Define() { + BeforeEach([this]() { + UWorld* pWorld = CesiumTestHelpers::getGlobalWorldContext(); + pGeoreferenceNullIsland = pWorld->SpawnActor(); + pGeoreferenceNullIsland->SetOriginLongitudeLatitudeHeight( + FVector(0.0, 0.0, 0.0)); + pGeoreference90Longitude = pWorld->SpawnActor(); + pGeoreference90Longitude->SetOriginLongitudeLatitudeHeight( + FVector(90.0, 0.0, 0.0)); + }); + + Describe("Position Transformation", [this]() { + It("transforms longitude-latitude-height positions to Unreal", [this]() { + FVector nullIslandUnreal = + pGeoreferenceNullIsland + ->TransformLongitudeLatitudeHeightPositionToUnreal( + FVector(0.0, 0.0, 0.0)); + TestEqual("nullIslandUnreal", nullIslandUnreal, FVector(0.0, 0.0, 0.0)); + + FVector antiMeridianUnreal = + pGeoreferenceNullIsland + ->TransformLongitudeLatitudeHeightPositionToUnreal( + FVector(180.0, 0.0, 0.0)); + TestEqual( + "antiMeridianUnreal", + antiMeridianUnreal, + FVector( + 0.0, + 0.0, + -2.0 * Ellipsoid::WGS84.getMaximumRadius() * 100.0)); + }); + + It("transforms Earth-Centered, Earth-Fixed positions to Unreal", [this]() { + FVector nullIslandUnreal = + pGeoreferenceNullIsland + ->TransformEarthCenteredEarthFixedPositionToUnreal( + FVector(Ellipsoid::WGS84.getMaximumRadius(), 0.0, 0.0)); + TestEqual("nullIslandUnreal", nullIslandUnreal, FVector(0.0, 0.0, 0.0)); + + FVector antiMeridianUnreal = + pGeoreferenceNullIsland + ->TransformEarthCenteredEarthFixedPositionToUnreal( + FVector(-Ellipsoid::WGS84.getMaximumRadius(), 0.0, 0.0)); + TestEqual( + "antiMeridianUnreal", + antiMeridianUnreal, + FVector( + 0.0, + 0.0, + -2.0 * Ellipsoid::WGS84.getMaximumRadius() * 100.0)); + }); + + It("transforms Unreal positions to longitude-latitude-height", [this]() { + FVector nullIslandLLH = + pGeoreferenceNullIsland + ->TransformUnrealPositionToLongitudeLatitudeHeight( + FVector(0.0, 0.0, 0.0)); + TestEqual("nullIslandLLH", nullIslandLLH, FVector(0.0, 0.0, 0.0)); + + FVector antiMeridianLLH = + pGeoreferenceNullIsland + ->TransformUnrealPositionToLongitudeLatitudeHeight(FVector( + 0.0, + 0.0, + -2.0 * Ellipsoid::WGS84.getMaximumRadius() * 100.0)); + TestEqual("antiMeridianLLH", antiMeridianLLH, FVector(180.0, 0.0, 0.0)); + }); + + It("transforms Unreal positions to Earth-Centered, Earth-Fixed", [this]() { + FVector nullIslandEcef = + pGeoreferenceNullIsland + ->TransformUnrealPositionToEarthCenteredEarthFixed( + FVector(0.0, 0.0, 0.0)); + TestEqual( + "nullIslandEcef", + nullIslandEcef, + FVector(Ellipsoid::WGS84.getMaximumRadius(), 0.0, 0.0)); + + FVector antiMeridianEcef = + pGeoreferenceNullIsland + ->TransformUnrealPositionToEarthCenteredEarthFixed(FVector( + 0.0, + 0.0, + -2.0 * Ellipsoid::WGS84.getMaximumRadius() * 100.0)); + TestEqual( + "antiMeridianEcef", + antiMeridianEcef, + FVector(-Ellipsoid::WGS84.getMaximumRadius(), 0.0, 0.0)); + }); + }); + + Describe("Direction Transformation", [this]() { + It("transforms Earth-Centered, Earth-Fixed directions to Unreal", [this]() { + FVector northAtNullIslandUnreal = + pGeoreferenceNullIsland + ->TransformEarthCenteredEarthFixedDirectionToUnreal( + FVector(0.0, 0.0, 1.0)); + TestEqual( + "northAtNullIslandUnreal", + northAtNullIslandUnreal, + FVector(0.0, -100.0, 0.0)); // meters -> centimeters + + FVector westAtAntiMeridianUnreal = + pGeoreferenceNullIsland + ->TransformEarthCenteredEarthFixedDirectionToUnreal( + FVector(0.0, 1.0, 0.0)); + TestEqual( + "westAtAntiMeridianUnreal", + westAtAntiMeridianUnreal, + FVector( + 100.0, // West at anti-merdian is East at null island + 0.0, + 0.0)); + }); + + It("transforms Unreal directions to Earth-Centered, Earth-Fixed", [this]() { + FVector northAtNullIslandEcef = + pGeoreferenceNullIsland + ->TransformUnrealDirectionToEarthCenteredEarthFixed( + FVector(0.0, -1.0, 0.0)); + TestEqual( + "northAtNullIslandEcef", + northAtNullIslandEcef, + FVector(0.0, 0.0, 1.0 / 100.0)); // centimeters -> meters + + // West at anti-merdian is East at null island + FVector westAtAntiMeridianEcef = + pGeoreferenceNullIsland + ->TransformUnrealDirectionToEarthCenteredEarthFixed( + FVector(1.0, 0.0, 0.0)); + TestEqual( + "westAtAntiMeridianEcef", + westAtAntiMeridianEcef, + FVector(0.0, 1.0 / 100.0, 0.0)); + }); + }); + + Describe("Rotator Transformation", [this]() { + It("treats Unreal and East-South-Up as identical at the georeference origin", + [this]() { + FRotator atOrigin1 = + pGeoreferenceNullIsland->TransformEastSouthUpRotatorToUnreal( + FRotator(1.0, 2.0, 3.0), + FVector(0.0, 0.0, 0.0)); + TestEqual("atOrigin1", atOrigin1, FRotator(1.0, 2.0, 3.0)); + + FRotator atOrigin2 = + pGeoreferenceNullIsland->TransformUnrealRotatorToEastSouthUp( + FRotator(1.0, 2.0, 3.0), + FVector(0.0, 0.0, 0.0)); + TestEqual("atOrigin2", atOrigin2, FRotator(1.0, 2.0, 3.0)); + }); + + It("transforms East-South-Up Rotators to Unreal", [this]() { + FRotator rotationAt90DegreesLongitude = FRotator(1.0, 2.0, 3.0); + FVector originOf90DegreesLongitudeInNullIslandCoordinates = + pGeoreferenceNullIsland + ->TransformLongitudeLatitudeHeightPositionToUnreal( + FVector(90.0, 0.0, 0.0)); + + FRotator rotationAtNullIsland = + pGeoreferenceNullIsland->TransformEastSouthUpRotatorToUnreal( + rotationAt90DegreesLongitude, + originOf90DegreesLongitudeInNullIslandCoordinates); + + CesiumTestHelpers::TestRotatorsAreEquivalent( + this, + pGeoreference90Longitude, + rotationAt90DegreesLongitude, + pGeoreferenceNullIsland, + rotationAtNullIsland); + }); + + It("transforms Unreal Rotators to East-South-Up", [this]() { + FRotator rotationAtNullIsland = FRotator(1.0, 2.0, 3.0); + FVector originOf90DegreesLongitudeInNullIslandCoordinates = + pGeoreferenceNullIsland + ->TransformLongitudeLatitudeHeightPositionToUnreal( + FVector(90.0, 0.0, 0.0)); + + FRotator rotationAt90DegreesLongitude = + pGeoreferenceNullIsland->TransformUnrealRotatorToEastSouthUp( + rotationAtNullIsland, + originOf90DegreesLongitudeInNullIslandCoordinates); + + CesiumTestHelpers::TestRotatorsAreEquivalent( + this, + pGeoreferenceNullIsland, + rotationAtNullIsland, + pGeoreference90Longitude, + rotationAt90DegreesLongitude); + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGlobeAnchor.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGlobeAnchor.spec.cpp new file mode 100644 index 0000000..897ab41 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGlobeAnchor.spec.cpp @@ -0,0 +1,266 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGeoreference.h" +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumTestHelpers.h" +#include "CesiumWgs84Ellipsoid.h" +#include "Misc/AutomationTest.h" + +BEGIN_DEFINE_SPEC( + FCesiumGlobeAnchorSpec, + "Cesium.Unit.GlobeAnchor", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) + +TObjectPtr pActor; +TObjectPtr pGlobeAnchor; +TObjectPtr pEllipsoid; + +END_DEFINE_SPEC(FCesiumGlobeAnchorSpec) + +void FCesiumGlobeAnchorSpec::Define() { + BeforeEach([this]() { + UWorld* pWorld = CesiumTestHelpers::getGlobalWorldContext(); + this->pActor = pWorld->SpawnActor(); + this->pActor->AddComponentByClass( + USceneComponent::StaticClass(), + false, + FTransform::Identity, + false); + this->pActor->SetActorRelativeTransform(FTransform()); + + this->pEllipsoid = NewObject(); + this->pEllipsoid->SetRadii(UCesiumWgs84Ellipsoid::GetRadii()); + + ACesiumGeoreference* pGeoreference = + ACesiumGeoreference::GetDefaultGeoreferenceForActor(pActor); + pGeoreference->SetOriginLongitudeLatitudeHeight(FVector(1.0, 2.0, 3.0)); + pGeoreference->SetEllipsoid(this->pEllipsoid); + + this->pGlobeAnchor = + Cast(pActor->AddComponentByClass( + UCesiumGlobeAnchorComponent::StaticClass(), + false, + FTransform::Identity, + false)); + }); + + It("immediately syncs globe position from transform when added", [this]() { + TestEqual("Longitude", this->pGlobeAnchor->GetLongitude(), 1.0); + TestEqual("Latitude", this->pGlobeAnchor->GetLatitude(), 2.0); + TestEqual("Height", this->pGlobeAnchor->GetHeight(), 3.0); + }); + + It("maintains globe position when switching to a new georeference", [this]() { + FTransform beforeTransform = this->pActor->GetActorTransform(); + FVector beforeLLH = this->pGlobeAnchor->GetLongitudeLatitudeHeight(); + + UWorld* pWorld = this->pActor->GetWorld(); + ACesiumGeoreference* pNewGeoref = pWorld->SpawnActor(); + pNewGeoref->SetOriginLongitudeLatitudeHeight(FVector(10.0, 20.0, 30.0)); + this->pGlobeAnchor->SetGeoreference(pNewGeoref); + + TestEqual( + "ResolvedGeoreference", + this->pGlobeAnchor->GetResolvedGeoreference(), + pNewGeoref); + TestFalse( + "Transforms are equal", + this->pActor->GetActorTransform().Equals(beforeTransform)); + TestEqual( + "Globe Position", + this->pGlobeAnchor->GetLongitudeLatitudeHeight(), + beforeLLH); + }); + + It("updates actor transform when globe anchor position is changed", [this]() { + FTransform beforeTransform = this->pActor->GetActorTransform(); + this->pGlobeAnchor->MoveToLongitudeLatitudeHeight(FVector(4.0, 5.0, 6.0)); + TestEqual( + "LongitudeLatitudeHeight", + this->pGlobeAnchor->GetLongitudeLatitudeHeight(), + FVector(4.0, 5.0, 6.0)); + TestFalse( + "Transforms are equal", + this->pActor->GetActorTransform().Equals(beforeTransform)); + }); + + It("updates globe anchor position when actor transform is changed", [this]() { + FVector beforeLLH = this->pGlobeAnchor->GetLongitudeLatitudeHeight(); + this->pActor->SetActorLocation(FVector(1000.0, 2000.0, 3000.0)); + TestNotEqual( + "globe position", + this->pGlobeAnchor->GetLongitudeLatitudeHeight(), + beforeLLH); + }); + + It("allows the actor transform to be set when not registered", [this]() { + FVector beforeLLH = this->pGlobeAnchor->GetLongitudeLatitudeHeight(); + + this->pGlobeAnchor->UnregisterComponent(); + this->pActor->SetActorLocation(FVector(1000.0, 2000.0, 3000.0)); + + // Globe position doesn't initially update while unregistered + TestEqual( + "globe position", + this->pGlobeAnchor->GetLongitudeLatitudeHeight(), + beforeLLH); + + // After we re-register, actor transform should be maintained and globe + // transform should be updated. + this->pGlobeAnchor->RegisterComponent(); + TestEqual( + "actor position", + this->pActor->GetActorLocation(), + FVector(1000.0, 2000.0, 3000.0)); + TestNotEqual( + "globe position", + this->pGlobeAnchor->GetLongitudeLatitudeHeight(), + beforeLLH); + }); + + It("adjusts orientation for globe when actor position is set immediately after adding anchor", + [this]() { + FRotator beforeRotation = this->pActor->GetActorRotation(); + + ACesiumGeoreference* pGeoreference = + this->pGlobeAnchor->GetResolvedGeoreference(); + this->pActor->SetActorLocation( + pGeoreference->TransformLongitudeLatitudeHeightPositionToUnreal( + FVector(90.0, 2.0, 3.0))); + TestNotEqual( + "rotation", + this->pActor->GetActorRotation(), + beforeRotation); + }); + + It("adjusts orientation for globe when globe position is set immediately after adding anchor", + [this]() { + FRotator beforeRotation = this->pActor->GetActorRotation(); + + this->pGlobeAnchor->MoveToLongitudeLatitudeHeight( + FVector(90.0, 2.0, 3.0)); + TestNotEqual( + "rotation", + this->pActor->GetActorRotation(), + beforeRotation); + }); + + It("does not adjust orientation for globe when that feature is disabled", + [this]() { + this->pGlobeAnchor->SetAdjustOrientationForGlobeWhenMoving(false); + FRotator beforeRotation = this->pActor->GetActorRotation(); + + ACesiumGeoreference* pGeoreference = + this->pGlobeAnchor->GetResolvedGeoreference(); + this->pActor->SetActorLocation( + pGeoreference->TransformLongitudeLatitudeHeightPositionToUnreal( + FVector(90.0, 2.0, 3.0))); + TestEqual("rotation", this->pActor->GetActorRotation(), beforeRotation); + + this->pGlobeAnchor->MoveToLongitudeLatitudeHeight( + FVector(45.0, 25.0, 300.0)); + TestEqual("rotation", this->pActor->GetActorRotation(), beforeRotation); + }); + + It("gains correct orientation on call to SnapToEastSouthUp", [this]() { + ACesiumGeoreference* pGeoreference = + this->pGlobeAnchor->GetResolvedGeoreference(); + + this->pGlobeAnchor->MoveToLongitudeLatitudeHeight( + FVector(-20.0, -10.0, 1000.0)); + this->pGlobeAnchor->SnapToEastSouthUp(); + + const FTransform& transform = this->pActor->GetActorTransform(); + FVector actualEcefEast = + pGeoreference + ->TransformUnrealDirectionToEarthCenteredEarthFixed( + transform.TransformVector(FVector::XAxisVector)) + .GetSafeNormal(); + FVector actualEcefSouth = + pGeoreference + ->TransformUnrealDirectionToEarthCenteredEarthFixed( + transform.TransformVector(FVector::YAxisVector)) + .GetSafeNormal(); + FVector actualEcefUp = + pGeoreference + ->TransformUnrealDirectionToEarthCenteredEarthFixed( + transform.TransformVector(FVector::ZAxisVector)) + .GetSafeNormal(); + + FMatrix enuToEcef = + UCesiumWgs84Ellipsoid::EastNorthUpToEarthCenteredEarthFixed( + this->pGlobeAnchor->GetEarthCenteredEarthFixedPosition()); + FVector expectedEcefEast = + enuToEcef.TransformVector(FVector::XAxisVector).GetSafeNormal(); + FVector expectedEcefSouth = + -enuToEcef.TransformVector(FVector::YAxisVector).GetSafeNormal(); + FVector expectedEcefUp = + enuToEcef.TransformVector(FVector::ZAxisVector).GetSafeNormal(); + + TestEqual("east", actualEcefEast, expectedEcefEast); + TestEqual("south", actualEcefSouth, expectedEcefSouth); + TestEqual("up", actualEcefUp, expectedEcefUp); + }); + + It("gains correct orientation on call to SnapLocalUpToEllipsoidNormal", + [this]() { + ACesiumGeoreference* pGeoreference = + this->pGlobeAnchor->GetResolvedGeoreference(); + + this->pGlobeAnchor->MoveToLongitudeLatitudeHeight( + FVector(-20.0, -10.0, 1000.0)); + this->pActor->SetActorRotation(FQuat::Identity); + this->pGlobeAnchor->SnapLocalUpToEllipsoidNormal(); + + const FTransform& transform = this->pActor->GetActorTransform(); + FVector actualEcefUp = + pGeoreference + ->TransformUnrealDirectionToEarthCenteredEarthFixed( + transform.TransformVector(FVector::ZAxisVector)) + .GetSafeNormal(); + + FVector surfaceNormal = UCesiumWgs84Ellipsoid::GeodeticSurfaceNormal( + this->pGlobeAnchor->GetEarthCenteredEarthFixedPosition()); + + TestEqual("up", actualEcefUp, surfaceNormal); + }); + + It("gives correct results for different ellipsoids", [this]() { + const FVector Position = FVector(-20.0, -10.0, 1000.0); + + // Check with WGS84 ellipsoid (the default) + this->pGlobeAnchor->MoveToLongitudeLatitudeHeight(Position); + + FVector wgs84EcefPos = + UCesiumWgs84Ellipsoid::LongitudeLatitudeHeightToEarthCenteredEarthFixed( + Position); + + TestEqual( + "ecef", + this->pGlobeAnchor->GetEarthCenteredEarthFixedPosition(), + wgs84EcefPos); + + // Check with unit ellipsoid + TObjectPtr pUnitEllipsoid = NewObject(); + pUnitEllipsoid->SetRadii(FVector::One()); + + ACesiumGeoreference* pGeoreference = + ACesiumGeoreference::GetDefaultGeoreferenceForActor(this->pActor); + pGeoreference->SetEllipsoid(pUnitEllipsoid); + + this->pGlobeAnchor->MoveToLongitudeLatitudeHeight(Position); + + FVector unitEcefPos = + pUnitEllipsoid + ->LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + Position); + + TestEqual( + "ecef", + this->pGlobeAnchor->GetEarthCenteredEarthFixedPosition(), + unitEcefPos); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.cpp new file mode 100644 index 0000000..3af0ffc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.cpp @@ -0,0 +1,117 @@ +#include "CesiumGltfSpecUtility.h" + +int32_t AddBufferToModel( + CesiumGltf::Model& model, + const std::string& type, + const int32_t componentType, + const std::vector&& values) { + CesiumGltf::Buffer& buffer = model.buffers.emplace_back(); + buffer.byteLength = values.size(); + buffer.cesium.data = std::move(values); + + CesiumGltf::BufferView& bufferView = model.bufferViews.emplace_back(); + bufferView.buffer = static_cast(model.buffers.size() - 1); + bufferView.byteLength = buffer.byteLength; + bufferView.byteOffset = 0; + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.bufferView = static_cast(model.bufferViews.size() - 1); + accessor.type = type; + accessor.componentType = componentType; + + const int64_t elementByteSize = + CesiumGltf::Accessor::computeByteSizeOfComponent(componentType) * + CesiumGltf::Accessor::computeNumberOfComponents(type); + accessor.count = buffer.byteLength / elementByteSize; + + return static_cast(model.accessors.size() - 1); +} + +CesiumGltf::FeatureId& AddFeatureIDsAsAttributeToModel( + CesiumGltf::Model& model, + CesiumGltf::MeshPrimitive& primitive, + const std::vector& featureIDs, + const int64_t featureCount, + const int64_t setIndex) { + std::vector values = GetValuesAsBytes(featureIDs); + + CreateAttributeForPrimitive( + model, + primitive, + "_FEATURE_ID_" + std::to_string(setIndex), + CesiumGltf::AccessorSpec::Type::SCALAR, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, + std::move(values)); + + CesiumGltf::ExtensionExtMeshFeatures* pExtension = + primitive.getExtension(); + if (pExtension == nullptr) { + pExtension = + &primitive.addExtension(); + } + + CesiumGltf::FeatureId& featureID = pExtension->featureIds.emplace_back(); + featureID.featureCount = featureCount; + featureID.attribute = setIndex; + + return featureID; +} + +CesiumGltf::FeatureId& AddFeatureIDsAsTextureToModel( + CesiumGltf::Model& model, + CesiumGltf::MeshPrimitive& primitive, + const std::vector& featureIDs, + const int64_t featureCount, + const int32_t imageWidth, + const int32_t imageHeight, + const std::vector& texCoords, + const int64_t texcoordSetIndex, + const int32_t samplerWrapS, + const int32_t samplerWrapT) { + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset.emplace(); + image.pAsset->bytesPerChannel = 1; + image.pAsset->channels = 1; + image.pAsset->width = imageWidth; + image.pAsset->height = imageHeight; + + std::vector& data = image.pAsset->pixelData; + data.resize(imageWidth * imageHeight); + std::memcpy(data.data(), featureIDs.data(), data.size()); + + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); + sampler.wrapS = samplerWrapS; + sampler.wrapT = samplerWrapT; + + CesiumGltf::Texture& texture = model.textures.emplace_back(); + texture.sampler = 0; + texture.source = 0; + + std::vector values = GetValuesAsBytes(texCoords); + CreateAttributeForPrimitive( + model, + primitive, + "TEXCOORD_" + std::to_string(texcoordSetIndex), + CesiumGltf::AccessorSpec::Type::VEC2, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, + std::move(values)); + + CesiumGltf::ExtensionExtMeshFeatures* pExtension = + primitive.getExtension(); + if (pExtension == nullptr) { + pExtension = + &primitive.addExtension(); + } + + CesiumGltf::FeatureId& featureID = pExtension->featureIds.emplace_back(); + featureID.featureCount = featureCount; + + CesiumGltf::FeatureIdTexture featureIDTexture; + featureIDTexture.channels = {0}; + featureIDTexture.index = 0; + featureIDTexture.texCoord = texcoordSetIndex; + + featureID.texture = featureIDTexture; + + return featureID; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.h new file mode 100644 index 0000000..a166f8d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.h @@ -0,0 +1,227 @@ +#pragma once + +#include "CesiumGltf/ExtensionExtMeshFeatures.h" +#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include +#include +#include + +/** + * @brief Converts the given vector of values into a std::vector of bytes. + * + * @returns The values as a std::vector of bytes. + */ +template +std::vector GetValuesAsBytes(const std::vector& values) { + std::vector bytes(values.size() * sizeof(T)); + std::memcpy(bytes.data(), values.data(), bytes.size()); + + return bytes; +} + +/** + * @brief Adds the buffer to the given model, creating a buffer view and + * accessor in the process. + * @returns The index of the accessor. + */ +int32_t AddBufferToModel( + CesiumGltf::Model& model, + const std::string& type, + const int32_t componentType, + const std::vector&& values); + +/** + * @brief Creates an attribute on the given primitive, including a buffer, + * buffer view, and accessor for the given values. + */ +template +void CreateAttributeForPrimitive( + CesiumGltf::Model& model, + CesiumGltf::MeshPrimitive& primitive, + const std::string& attributeName, + const std::string& type, + const int32_t componentType, + const std::vector& values) { + std::vector data = GetValuesAsBytes(values); + const int32_t accessor = + AddBufferToModel(model, type, componentType, std::move(data)); + primitive.attributes.insert({attributeName, accessor}); +} + +/** + * @brief Creates indices for the given primitive, including a buffer, + * buffer view, and accessor for the given values. + */ +template +void CreateIndicesForPrimitive( + CesiumGltf::Model& model, + CesiumGltf::MeshPrimitive& primitive, + const int32_t componentType, + const std::vector& indices) { + std::vector values = GetValuesAsBytes(indices); + const int32_t accessor = AddBufferToModel( + model, + CesiumGltf::AccessorSpec::Type::SCALAR, + componentType, + std::move(values)); + primitive.indices = accessor; +} + +/** + * @brief Adds the feature IDs to the given primitive as a feature ID attribute + * in EXT_mesh_features. If the primitive doesn't already contain + * EXT_mesh_features, this function adds it. + * + * @returns The newly created feature ID in the primitive extension. + */ +CesiumGltf::FeatureId& AddFeatureIDsAsAttributeToModel( + CesiumGltf::Model& model, + CesiumGltf::MeshPrimitive& primitive, + const std::vector& featureIDs, + const int64_t featureCount, + const int64_t setIndex); + +/** + * @brief Adds the feature IDs to the given primitive as a feature ID texture + * in EXT_mesh_features. This also adds the given texcoords to the primitive as + * a TEXCOORD attribute. If the primitive doesn't already contain + * EXT_mesh_features, this function adds it. + * + * @returns The newly created feature ID in the primitive extension. + */ +CesiumGltf::FeatureId& AddFeatureIDsAsTextureToModel( + CesiumGltf::Model& model, + CesiumGltf::MeshPrimitive& primitive, + const std::vector& featureIDs, + const int64_t featureCount, + const int32_t imageWidth, + const int32_t imageHeight, + const std::vector& texCoords, + const int64_t texcoordSetIndex, + const int32_t samplerWrapS = CesiumGltf::Sampler::WrapS::CLAMP_TO_EDGE, + const int32_t samplerWrapT = CesiumGltf::Sampler::WrapT::CLAMP_TO_EDGE); + +/** + * @brief Adds the given values to the given model as a property table property + * in EXT_structural_metadata. This also creates a class property definition for + * the new property in the schema. If the model doesn't already contain + * EXT_structural_metadata, this function adds it. + * + * This assumes the given values are not arrays or strings. + * + * @returns The newly created property table property in the model extension. + */ +template +CesiumGltf::PropertyTableProperty& AddPropertyTablePropertyToModel( + CesiumGltf::Model& model, + CesiumGltf::PropertyTable& propertyTable, + const std::string& propertyName, + const std::string& type, + const std::optional& componentType, + const std::vector& values) { + CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension = + model.getExtension(); + if (pExtension == nullptr) { + pExtension = + &model.addExtension(); + } + + if (!pExtension->schema) { + pExtension->schema.emplace(); + } + CesiumGltf::Schema& schema = *pExtension->schema; + + const std::string& className = propertyTable.classProperty; + CesiumGltf::Class& theClass = schema.classes[className]; + + CesiumGltf::ClassProperty& classProperty = theClass.properties[propertyName]; + classProperty.type = type; + classProperty.componentType = componentType; + + CesiumGltf::Buffer& buffer = model.buffers.emplace_back(); + buffer.cesium.data.resize(values.size() * sizeof(T)); + std::memcpy( + buffer.cesium.data.data(), + values.data(), + buffer.cesium.data.size()); + buffer.byteLength = buffer.cesium.data.size(); + + CesiumGltf::BufferView& bufferView = model.bufferViews.emplace_back(); + bufferView.buffer = static_cast(model.buffers.size() - 1); + bufferView.byteLength = buffer.byteLength; + bufferView.byteOffset = 0; + + CesiumGltf::PropertyTableProperty& property = + propertyTable.properties[propertyName]; + property.values = static_cast(model.bufferViews.size() - 1); + + return property; +} + +/** + * @brief Adds the given values to the given model as a property texture + * property in EXT_structural_metadata. This also creates a class property + * definition for the new property in the schema. If the model doesn't already + * contain EXT_structural_metadata, this function adds it. + * + * This assumes the given values are not arrays or strings. The values will be + * stored in a 2x2 image with the correct number of channels. + * + * @returns The newly created property texture property in the model extension. + */ +template +CesiumGltf::PropertyTextureProperty& AddPropertyTexturePropertyToModel( + CesiumGltf::Model& model, + CesiumGltf::PropertyTexture& propertyTexture, + const std::string& propertyName, + const std::string& type, + const std::optional& componentType, + const std::array& values, + const std::vector& channels) { + CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension = + model.getExtension(); + if (pExtension == nullptr) { + pExtension = + &model.addExtension(); + } + + if (!pExtension->schema) { + pExtension->schema.emplace(); + } + CesiumGltf::Schema& schema = *pExtension->schema; + + const std::string& className = propertyTexture.classProperty; + CesiumGltf::Class& theClass = schema.classes[className]; + + CesiumGltf::ClassProperty& classProperty = theClass.properties[propertyName]; + classProperty.type = type; + classProperty.componentType = componentType; + + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset.emplace(); + image.pAsset->width = 2; + image.pAsset->height = 2; + image.pAsset->channels = sizeof(T); + image.pAsset->bytesPerChannel = 1; + image.pAsset->pixelData.resize(values.size() * sizeof(T)); + std::memcpy( + image.pAsset->pixelData.data(), + values.data(), + image.pAsset->pixelData.size()); + + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); + sampler.wrapS = CesiumGltf::Sampler::WrapS::CLAMP_TO_EDGE; + sampler.wrapT = CesiumGltf::Sampler::WrapT::CLAMP_TO_EDGE; + + CesiumGltf::Texture& texture = model.textures.emplace_back(); + texture.sampler = static_cast(model.samplers.size() - 1); + texture.source = static_cast(model.images.size() - 1); + + CesiumGltf::PropertyTextureProperty& property = + propertyTexture.properties[propertyName]; + property.channels = channels; + property.index = static_cast(model.textures.size() - 1); + return property; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp new file mode 100644 index 0000000..d285371 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp @@ -0,0 +1,285 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "CesiumLoadTestCore.h" + +#include "CesiumAsync/ICacheDatabase.h" +#include "CesiumRuntime.h" + +#include "Editor.h" +#include "Settings/LevelEditorPlaySettings.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "UnrealClient.h" + +namespace Cesium { + +struct LoadTestContext { + FString testName; + std::vector testPasses; + + SceneGenerationContext creationContext; + SceneGenerationContext playContext; + + float cameraFieldOfView = 90.0f; + + ReportCallback reportStep; + + void reset() { + testName.Reset(); + testPasses.clear(); + creationContext = playContext = SceneGenerationContext(); + reportStep = nullptr; + } +}; + +LoadTestContext gLoadTestContext; + +DEFINE_LATENT_AUTOMATION_COMMAND_FOUR_PARAMETER( + TimeLoadingCommand, + FString, + loggingName, + SceneGenerationContext&, + creationContext, + SceneGenerationContext&, + playContext, + TestPass&, + pass); +bool TimeLoadingCommand::Update() { + + if (!pass.testInProgress) { + + // Set up the world for this pass + playContext.syncWorldCamera(); + if (pass.setupStep) + pass.setupStep(playContext, pass.optionalParameter); + + // Start test mark, turn updates back on + pass.startMark = FPlatformTime::Seconds(); + UE_LOG(LogCesium, Display, TEXT("-- Load start mark -- %s"), *loggingName); + + playContext.setSuspendUpdate(false); + + pass.testInProgress = true; + + // Return, let world tick + return false; + } + + double timeMark = FPlatformTime::Seconds(); + + pass.elapsedTime = timeMark - pass.startMark; + + // The command is over if tilesets are loaded, or timed out + // Wait for a maximum of 30 seconds + const size_t testTimeout = 30; + bool tilesetsloaded = playContext.areTilesetsDoneLoading(); + bool timedOut = pass.elapsedTime >= testTimeout; + + if (timedOut) { + UE_LOG( + LogCesium, + Error, + TEXT("TIMED OUT: Loading stopped after %.2f seconds"), + pass.elapsedTime); + // Command is done + pass.testInProgress = false; + return true; + } + + if (tilesetsloaded) { + // Run verify step as part of timing + // This is useful for running additional logic after a load, or if the step + // exists in the pass solely, timing very specific functionality (like + // terrain queries) + bool verifyComplete = true; + if (pass.verifyStep) + verifyComplete = + pass.verifyStep(creationContext, playContext, pass.optionalParameter); + + if (verifyComplete) { + pass.endMark = FPlatformTime::Seconds(); + UE_LOG(LogCesium, Display, TEXT("-- Load end mark -- %s"), *loggingName); + + pass.elapsedTime = pass.endMark - pass.startMark; + UE_LOG( + LogCesium, + Display, + TEXT("Pass completed in %.2f seconds"), + pass.elapsedTime); + + pass.testInProgress = false; + + // Command is done + return true; + } + } + + // Let world tick, we'll come back to this command + return false; +} + +DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER( + LoadTestScreenshotCommand, + FString, + screenshotName); +bool LoadTestScreenshotCommand::Update() { + UE_LOG( + LogCesium, + Display, + TEXT("Requesting screenshot to /Saved/Screenshots/WindowsEditor...")); + + // Add a dash to separate name from unique index of screen shot + // Also add a dot to keep the base path logic from stripping away too much + FString requestFilename = screenshotName + "-" + "."; + FScreenshotRequest::RequestScreenshot(requestFilename, false, true); + return true; +} + +void defaultReportStep(const std::vector& testPasses) { + FString reportStr; + reportStr += "\n\nTest Results\n"; + reportStr += "-----------------------------\n"; + reportStr += "(measured time) - (pass name)\n"; + std::vector::const_iterator it; + for (it = testPasses.begin(); it != testPasses.end(); ++it) { + const TestPass& pass = *it; + reportStr += + FString::Printf(TEXT("%.2f secs - %s\n"), pass.elapsedTime, *pass.name); + } + reportStr += "-----------------------------\n"; + + UE_LOG(LogCesium, Display, TEXT("%s"), *reportStr); +} + +DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER( + TestCleanupCommand, + LoadTestContext&, + context); +bool TestCleanupCommand::Update() { + // Tag the fastest pass + if (context.testPasses.size() > 0) { + size_t fastestPass = 0; + double fastestTime = -1.0; + for (size_t index = 0; index < context.testPasses.size(); ++index) { + const TestPass& pass = context.testPasses[index]; + if (fastestTime == -1.0 || pass.elapsedTime < fastestTime) { + fastestPass = index; + fastestTime = pass.elapsedTime; + } + } + context.testPasses[fastestPass].isFastest = true; + } + + if (context.reportStep) + context.reportStep(context.testPasses); + else + defaultReportStep(context.testPasses); + + return true; +} + +DEFINE_LATENT_AUTOMATION_COMMAND_TWO_PARAMETER( + InitForPlayWhenReady, + SceneGenerationContext&, + creationContext, + SceneGenerationContext&, + playContext); +bool InitForPlayWhenReady::Update() { + if (!GEditor || !GEditor->IsPlayingSessionInEditor()) + return false; + UE_LOG(LogCesium, Display, TEXT("Play in Editor ready...")); + playContext.initForPlay(creationContext); + return true; +} + +bool RunLoadTest( + const FString& testName, + std::function locationSetup, + const std::vector& testPasses, + int viewportWidth, + int viewportHeight, + ReportCallback optionalReportStep) { + + LoadTestContext& context = gLoadTestContext; + + context.reset(); + + context.testName = testName; + context.testPasses = testPasses; + context.reportStep = optionalReportStep; + + // + // Programmatically set up the world + // + UE_LOG(LogCesium, Display, TEXT("Creating common world objects...")); + createCommonWorldObjects(context.creationContext); + + // Configure location specific objects + UE_LOG(LogCesium, Display, TEXT("Setting up location...")); + locationSetup(context.creationContext); + context.creationContext.trackForPlay(); + + // Halt tileset updates and reset them + context.creationContext.setSuspendUpdate(true); + context.creationContext.refreshTilesets(); + + // Let the editor viewports see the same thing the test will + context.creationContext.syncWorldCamera(); + + // + // Start async commands + // + + // Wait for shaders. Shader compiles could affect performance + ADD_LATENT_AUTOMATION_COMMAND(FWaitForShadersToFinishCompiling); + + // Queue play in editor and set desired viewport size + FRequestPlaySessionParams Params; + Params.WorldType = EPlaySessionWorldType::PlayInEditor; + Params.EditorPlaySettings = NewObject(); + Params.EditorPlaySettings->NewWindowWidth = viewportWidth; + Params.EditorPlaySettings->NewWindowHeight = viewportHeight; + Params.EditorPlaySettings->EnableGameSound = false; + GEditor->RequestPlaySession(Params); + + // Wait until PIE is ready + ADD_LATENT_AUTOMATION_COMMAND( + InitForPlayWhenReady(context.creationContext, context.playContext)); + + // Wait to show distinct gap in profiler + ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.0f)); + + std::vector::iterator it; + for (it = context.testPasses.begin(); it != context.testPasses.end(); ++it) { + TestPass& pass = *it; + + // Do our timing capture + FString loggingName = testName + "-" + pass.name; + + ADD_LATENT_AUTOMATION_COMMAND(TimeLoadingCommand( + loggingName, + context.creationContext, + context.playContext, + pass)); + + ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.0f)); + + FString screenshotName = testName + "-" + pass.name; + ADD_LATENT_AUTOMATION_COMMAND(LoadTestScreenshotCommand(screenshotName)) + + ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.0f)); + } + + // End play in editor + ADD_LATENT_AUTOMATION_COMMAND(FEndPlayMapCommand()); + + ADD_LATENT_AUTOMATION_COMMAND(TestCleanupCommand(context)); + + return true; +} + +}; // namespace Cesium + +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.h new file mode 100644 index 0000000..ef09a10 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.h @@ -0,0 +1,47 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#if WITH_EDITOR + +#include +#include + +#include "CesiumSceneGeneration.h" + +namespace Cesium { + +struct TestPass { + typedef swl::variant TestingParameter; + typedef std::function + SetupCallback; + typedef std::function< + bool(SceneGenerationContext&, SceneGenerationContext&, TestingParameter)> + VerifyCallback; + + FString name; + SetupCallback setupStep; + VerifyCallback verifyStep; + TestingParameter optionalParameter; + + bool testInProgress = false; + double startMark = 0; + double endMark = 0; + double elapsedTime = 0; + + bool isFastest = false; +}; + +typedef std::function&)> ReportCallback; + +bool RunLoadTest( + const FString& testName, + std::function locationSetup, + const std::vector& testPasses, + int viewportWidth, + int viewportHeight, + ReportCallback optionalReportStep = nullptr); + +}; // namespace Cesium + +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp new file mode 100644 index 0000000..099c593 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp @@ -0,0 +1,1369 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataPickingBlueprintLibrary.h" +#include "CesiumGltf/ExtensionExtMeshFeatures.h" +#include "CesiumGltf/ExtensionMeshPrimitiveExtStructuralMetadata.h" +#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltfComponent.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumGltfSpecUtility.h" +#include "Misc/AutomationTest.h" + +BEGIN_DEFINE_SPEC( + FCesiumMetadataPickingSpec, + "Cesium.Unit.MetadataPicking", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +CesiumGltf::Model model; +CesiumGltf::MeshPrimitive* pPrimitive; +CesiumGltf::ExtensionExtMeshFeatures* pMeshFeatures; +CesiumGltf::ExtensionModelExtStructuralMetadata* pModelMetadata; +CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata* pPrimitiveMetadata; +CesiumGltf::PropertyTable* pPropertyTable; +CesiumGltf::PropertyTexture* pPropertyTexture; +TObjectPtr pModelComponent; +TObjectPtr pPrimitiveComponent; +END_DEFINE_SPEC(FCesiumMetadataPickingSpec) + +void FCesiumMetadataPickingSpec::Define() { + Describe("FindUVFromHit", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + pPrimitive->mode = CesiumGltf::MeshPrimitive::Mode::TRIANGLES; + pPrimitiveComponent = NewObject(); + pPrimitiveComponent->getPrimitiveData().pMeshPrimitive = pPrimitive; + + std::vector positions{ + glm::vec3(-1, 0, 0), + glm::vec3(0, 1, 0), + glm::vec3(1, 0, 0), + glm::vec3(-1, 3, 0), + glm::vec3(0, 4, 0), + glm::vec3(1, 3, 0), + }; + CreateAttributeForPrimitive( + model, + *pPrimitive, + "POSITION", + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, + positions); + int32_t positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + // For convenience when testing, the UVs are the same as the positions + // they correspond to. This means that the interpolated UV value should be + // directly equal to the barycentric coordinates of the triangle. + std::vector texCoords{ + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0), + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0)}; + CreateAttributeForPrimitive( + model, + *pPrimitive, + "TEXCOORD_0", + CesiumGltf::AccessorSpec::Type::VEC2, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, + texCoords); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + primData.TexCoordAccessorMap.emplace( + 0, + CesiumGltf::AccessorView>( + model, + static_cast(model.accessors.size() - 1))); + }); + + It("returns false if hit has no valid component", [this]() { + FHitResult Hit; + Hit.Location = FVector_NetQuantize(0, -1, 0) * + CesiumPrimitiveData::positionScaleFactor; + Hit.FaceIndex = 0; + Hit.Component = nullptr; + + FVector2D UV; + TestFalse( + "found hit", + UCesiumMetadataPickingBlueprintLibrary::FindUVFromHit(Hit, 0, UV)); + }); + + It("returns false if specified texcoord set does not exist", [this]() { + FHitResult Hit; + Hit.Location = FVector_NetQuantize(0, -1, 0) * + CesiumPrimitiveData::positionScaleFactor; + Hit.FaceIndex = 0; + Hit.Component = pPrimitiveComponent; + + FVector2D UV; + TestFalse( + "found hit", + UCesiumMetadataPickingBlueprintLibrary::FindUVFromHit(Hit, 1, UV)); + }); + + It("gets hit for primitive without indices", [this]() { + FHitResult Hit; + Hit.Location = FVector_NetQuantize(0, -1, 0) * + CesiumPrimitiveData::positionScaleFactor; + Hit.FaceIndex = 0; + Hit.Component = pPrimitiveComponent; + + FVector2D UV = FVector2D::Zero(); + TestTrue( + "found hit", + UCesiumMetadataPickingBlueprintLibrary::FindUVFromHit(Hit, 0, UV)); + TestTrue("UV at point (X)", FMath::IsNearlyEqual(UV[0], 0.0)); + TestTrue("UV at point (Y)", FMath::IsNearlyEqual(UV[1], 1.0)); + + Hit.Location = FVector_NetQuantize(0, -0.5, 0) * + CesiumPrimitiveData::positionScaleFactor; + TestTrue( + "found hit", + UCesiumMetadataPickingBlueprintLibrary::FindUVFromHit(Hit, 0, UV)); + TestTrue( + "UV at point inside triangle (X)", + FMath::IsNearlyEqual(UV[0], 0.0)); + TestTrue( + "UV at point inside triangle (Y)", + FMath::IsNearlyEqual(UV[1], 0.5)); + + Hit.FaceIndex = 1; + Hit.Location = FVector_NetQuantize(0, -4, 0) * + CesiumPrimitiveData::positionScaleFactor; + TestTrue( + "found hit", + UCesiumMetadataPickingBlueprintLibrary::FindUVFromHit(Hit, 0, UV)); + TestTrue("UV at point (X)", FMath::IsNearlyEqual(UV[0], 0.0)); + TestTrue("UV at point (Y)", FMath::IsNearlyEqual(UV[1], 1.0)); + }); + + It("gets hit for primitive with indices", [this]() { + // Switch the order of the triangles. + const std::vector indices{3, 4, 5, 0, 1, 2}; + CreateIndicesForPrimitive( + model, + *pPrimitive, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, + indices); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.IndexAccessor = CesiumGltf::AccessorView( + model, + static_cast(model.accessors.size() - 1)); + + FHitResult Hit; + Hit.Location = FVector_NetQuantize(0, -4, 0) * + CesiumPrimitiveData::positionScaleFactor; + Hit.FaceIndex = 0; + Hit.Component = pPrimitiveComponent; + + FVector2D UV = FVector2D::Zero(); + + TestTrue( + "found hit", + UCesiumMetadataPickingBlueprintLibrary::FindUVFromHit(Hit, 0, UV)); + TestTrue("UV at point (X)", FMath::IsNearlyEqual(UV[0], 0.0)); + TestTrue("UV at point (Y)", FMath::IsNearlyEqual(UV[1], 1.0)); + + Hit.Location = FVector_NetQuantize(0, -3.5, 0) * + CesiumPrimitiveData::positionScaleFactor; + TestTrue( + "found hit", + UCesiumMetadataPickingBlueprintLibrary::FindUVFromHit(Hit, 0, UV)); + TestTrue( + "UV at point inside triangle (X)", + FMath::IsNearlyEqual(UV[0], 0.0)); + TestTrue( + "UV at point inside triangle (Y)", + FMath::IsNearlyEqual(UV[1], 0.5)); + + Hit.FaceIndex = 1; + Hit.Location = FVector_NetQuantize(0, -1, 0) * + CesiumPrimitiveData::positionScaleFactor; + TestTrue( + "found hit", + UCesiumMetadataPickingBlueprintLibrary::FindUVFromHit(Hit, 0, UV)); + TestTrue("UV at point (X)", FMath::IsNearlyEqual(UV[0], 0.0)); + TestTrue("UV at point (Y)", FMath::IsNearlyEqual(UV[1], 1.0)); + }); + }); + + Describe("GetPropertyTableValuesFromHit", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + pPrimitive->mode = CesiumGltf::MeshPrimitive::Mode::TRIANGLES; + + // Two disconnected triangles. + std::vector positions{ + glm::vec3(-1, 1, 0), + glm::vec3(1, 1, 0), + glm::vec3(1, -1, 0), + glm::vec3(2, 2, 0), + glm::vec3(-2, 2, 0), + glm::vec3(-2, -2, 0), + }; + std::vector positionData(positions.size() * sizeof(glm::vec3)); + std::memcpy(positionData.data(), positions.data(), positionData.size()); + CreateAttributeForPrimitive( + model, + *pPrimitive, + "POSITION", + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, + std::move(positionData)); + + pMeshFeatures = + &pPrimitive->addExtension(); + pModelMetadata = + &model + .addExtension(); + + std::string className = "testClass"; + pModelMetadata->schema.emplace(); + pModelMetadata->schema->classes[className]; + + pPropertyTable = &pModelMetadata->propertyTables.emplace_back(); + pPropertyTable->classProperty = className; + + pModelComponent = NewObject(); + pPrimitiveComponent = + NewObject(pModelComponent); + pPrimitiveComponent->AttachToComponent( + pModelComponent, + FAttachmentTransformRules(EAttachmentRule::KeepRelative, false)); + pPrimitiveComponent->getPrimitiveData().pMeshPrimitive = pPrimitive; + }); + + It("returns empty map for invalid component", [this]() { + int32_t positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + std::vector featureIDs{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureId = + AddFeatureIDsAsAttributeToModel(model, *pPrimitive, featureIDs, 2, 0); + featureId.propertyTable = + static_cast(pModelMetadata->propertyTables.size() - 1); + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + + std::vector scalarValues{1, 2}; + pPropertyTable->count = static_cast(scalarValues.size()); + const std::string scalarPropertyName("scalarProperty"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + pModelComponent->Metadata = FCesiumModelMetadata(model, *pModelMetadata); + primData.Features = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pMeshFeatures); + + FHitResult Hit; + Hit.FaceIndex = -1; + Hit.Component = nullptr; + + auto values = + UCesiumMetadataPickingBlueprintLibrary::GetPropertyTableValuesFromHit( + Hit); + TestTrue("empty values for invalid hit", values.IsEmpty()); + }); + + It("returns empty map for invalid feature ID set index", [this]() { + int32_t positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + std::vector featureIDs{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureId = + AddFeatureIDsAsAttributeToModel(model, *pPrimitive, featureIDs, 2, 0); + featureId.propertyTable = + static_cast(pModelMetadata->propertyTables.size() - 1); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + + std::vector scalarValues{1, 2}; + pPropertyTable->count = static_cast(scalarValues.size()); + const std::string scalarPropertyName("scalarProperty"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + pModelComponent->Metadata = FCesiumModelMetadata(model, *pModelMetadata); + primData.Features = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pMeshFeatures); + + FHitResult Hit; + Hit.FaceIndex = 0; + Hit.Component = pPrimitiveComponent; + + auto values = + UCesiumMetadataPickingBlueprintLibrary::GetPropertyTableValuesFromHit( + Hit, + -1); + TestTrue("empty values for negative index", values.IsEmpty()); + + values = + UCesiumMetadataPickingBlueprintLibrary::GetPropertyTableValuesFromHit( + Hit, + 1); + TestTrue( + "empty values for positive out-of-range index", + values.IsEmpty()); + }); + + It("returns empty values if feature ID set is not associated with a property table", + [this]() { + int32_t positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + std::vector featureIDs{0, 0, 0, 1, 1, 1}; + AddFeatureIDsAsAttributeToModel(model, *pPrimitive, featureIDs, 2, 0); + + CesiumPrimitiveData& primData = + pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + + std::vector scalarValues{1, 2}; + pPropertyTable->count = static_cast(scalarValues.size()); + const std::string scalarPropertyName("scalarProperty"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(3.1f, -4.0f)}; + const std::string vec2PropertyName("vec2Property"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + pModelComponent->Metadata = + FCesiumModelMetadata(model, *pModelMetadata); + primData.Features = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pMeshFeatures); + + FHitResult Hit; + Hit.FaceIndex = 0; + Hit.Component = pPrimitiveComponent; + + const auto values = UCesiumMetadataPickingBlueprintLibrary:: + GetPropertyTableValuesFromHit(Hit); + TestTrue("values are empty", values.IsEmpty()); + }); + + It("returns values for first feature ID set by default", [this]() { + int32_t positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + std::vector featureIDs{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureId = + AddFeatureIDsAsAttributeToModel(model, *pPrimitive, featureIDs, 2, 0); + featureId.propertyTable = + static_cast(pModelMetadata->propertyTables.size() - 1); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + + std::vector scalarValues{1, 2}; + pPropertyTable->count = static_cast(scalarValues.size()); + const std::string scalarPropertyName("scalarProperty"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(3.1f, -4.0f)}; + const std::string vec2PropertyName("vec2Property"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + pModelComponent->Metadata = FCesiumModelMetadata(model, *pModelMetadata); + primData.Features = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pMeshFeatures); + + FHitResult Hit; + Hit.Component = pPrimitiveComponent; + + for (size_t i = 0; i < scalarValues.size(); i++) { + Hit.FaceIndex = i; + + const auto values = UCesiumMetadataPickingBlueprintLibrary:: + GetPropertyTableValuesFromHit(Hit); + + TestEqual("number of values", values.Num(), 2); + TestTrue( + "contains scalar value", + values.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "contains vec2 value", + values.Contains(FString(vec2PropertyName.c_str()))); + + const FCesiumMetadataValue* pScalarValue = + values.Find(FString(scalarPropertyName.c_str())); + if (pScalarValue) { + TestEqual( + "scalar value", + UCesiumMetadataValueBlueprintLibrary::GetInteger( + *pScalarValue, + 0), + scalarValues[i]); + } + + const FCesiumMetadataValue* pVec2Value = + values.Find(FString(vec2PropertyName.c_str())); + if (pVec2Value) { + FVector2D expected( + static_cast(vec2Values[i][0]), + static_cast(vec2Values[i][1])); + TestEqual( + "vec2 value", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + *pVec2Value, + FVector2D::Zero()), + expected); + } + } + }); + + It("returns values for specified feature ID set", [this]() { + int32_t positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + std::vector featureIDs0{1, 1, 1, 0, 0, 0}; + CesiumGltf::FeatureId& featureId0 = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs0, + 2, + 0); + std::vector featureIDs1{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureId1 = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs1, + 2, + 1); + featureId0.propertyTable = featureId1.propertyTable = + static_cast(pModelMetadata->propertyTables.size() - 1); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + + std::vector scalarValues{1, 2}; + pPropertyTable->count = static_cast(scalarValues.size()); + const std::string scalarPropertyName("scalarProperty"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(3.1f, -4.0f)}; + const std::string vec2PropertyName("vec2Property"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + pModelComponent->Metadata = FCesiumModelMetadata(model, *pModelMetadata); + primData.Features = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pMeshFeatures); + + FHitResult Hit; + Hit.Component = pPrimitiveComponent; + + for (size_t i = 0; i < scalarValues.size(); i++) { + Hit.FaceIndex = i; + + const auto values = UCesiumMetadataPickingBlueprintLibrary:: + GetPropertyTableValuesFromHit(Hit, 1); + TestEqual("number of values", values.Num(), 2); + TestTrue( + "contains scalar value", + values.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "contains vec2 value", + values.Contains(FString(vec2PropertyName.c_str()))); + + const FCesiumMetadataValue* pScalarValue = + values.Find(FString(scalarPropertyName.c_str())); + if (pScalarValue) { + TestEqual( + "scalar value", + UCesiumMetadataValueBlueprintLibrary::GetInteger( + *pScalarValue, + 0), + scalarValues[i]); + } + + const FCesiumMetadataValue* pVec2Value = + values.Find(FString(vec2PropertyName.c_str())); + FVector2D expected( + static_cast(vec2Values[i][0]), + static_cast(vec2Values[i][1])); + if (pVec2Value) { + TestEqual( + "vec2 value", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + *pVec2Value, + FVector2D::Zero()), + expected); + } + } + }); + }); + + Describe("GetPropertyTextureValuesFromHit", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + pPrimitive->mode = CesiumGltf::MeshPrimitive::Mode::TRIANGLES; + + std::vector positions{ + glm::vec3(-1, 0, 0), + glm::vec3(0, 1, 0), + glm::vec3(1, 0, 0), + glm::vec3(-1, 3, 0), + glm::vec3(0, 4, 0), + glm::vec3(1, 3, 0), + }; + + CreateAttributeForPrimitive( + model, + *pPrimitive, + "POSITION", + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, + GetValuesAsBytes(positions)); + + int32_t positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + // For convenience when testing, the UVs are the same as the positions + // they correspond to. This means that the interpolated UV value should be + // directly equal to the barycentric coordinates of the triangle. + std::vector texCoords0{ + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0), + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0)}; + + CreateAttributeForPrimitive( + model, + *pPrimitive, + "TEXCOORD_0", + CesiumGltf::AccessorSpec::Type::VEC2, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, + texCoords0); + + pModelMetadata = + &model + .addExtension(); + + std::string className = "testClass"; + pModelMetadata->schema.emplace(); + pModelMetadata->schema->classes[className]; + + pPropertyTexture = &pModelMetadata->propertyTextures.emplace_back(); + pPropertyTexture->classProperty = className; + + pPrimitiveMetadata = &pPrimitive->addExtension< + CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata>(); + pPrimitiveMetadata->propertyTextures.push_back(0); + + pModelComponent = NewObject(); + pPrimitiveComponent = + NewObject(pModelComponent); + + pPrimitiveComponent->AttachToComponent( + pModelComponent, + FAttachmentTransformRules(EAttachmentRule::KeepRelative, false)); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.pMeshPrimitive = pPrimitive; + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + primData.TexCoordAccessorMap.emplace( + 0, + CesiumGltf::AccessorView>( + model, + static_cast(model.accessors.size() - 1))); + }); + + It("returns empty map for invalid component", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::array scalarValues{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT8, + scalarValues, + {0}); + + pModelComponent->Metadata = FCesiumModelMetadata(model, *pModelMetadata); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.Metadata = + FCesiumPrimitiveMetadata(*pPrimitive, *pPrimitiveMetadata); + + FHitResult Hit; + Hit.FaceIndex = -1; + Hit.Component = nullptr; + + auto values = UCesiumMetadataPickingBlueprintLibrary:: + GetPropertyTextureValuesFromHit(Hit); + TestTrue("empty values for invalid hit", values.IsEmpty()); + }); + + It("returns empty map for invalid primitive property texture index", + [this]() { + std::string scalarPropertyName("scalarProperty"); + std::array scalarValues{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT8, + scalarValues, + {0}); + + pModelComponent->Metadata = + FCesiumModelMetadata(model, *pModelMetadata); + CesiumPrimitiveData& primData = + pPrimitiveComponent->getPrimitiveData(); + primData.Metadata = + FCesiumPrimitiveMetadata(*pPrimitive, *pPrimitiveMetadata); + + FHitResult Hit; + Hit.FaceIndex = 0; + Hit.Component = pPrimitiveComponent; + + auto values = UCesiumMetadataPickingBlueprintLibrary:: + GetPropertyTextureValuesFromHit(Hit, -1); + TestTrue("empty values for negative index", values.IsEmpty()); + + values = UCesiumMetadataPickingBlueprintLibrary:: + GetPropertyTextureValuesFromHit(Hit, 1); + TestTrue( + "empty values for positive out-of-range index", + values.IsEmpty()); + }); + + It("returns empty values if property texture does not exist in model metadata", + [this]() { + std::string scalarPropertyName("scalarProperty"); + std::array scalarValues{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT8, + scalarValues, + {0}); + + pModelComponent->Metadata = FCesiumModelMetadata(); + + pPrimitiveMetadata->propertyTextures.clear(); + pPrimitiveMetadata->propertyTextures.push_back(1); + CesiumPrimitiveData& primData = + pPrimitiveComponent->getPrimitiveData(); + primData.Metadata = + FCesiumPrimitiveMetadata(*pPrimitive, *pPrimitiveMetadata); + + FHitResult Hit; + Hit.FaceIndex = 0; + Hit.Component = pPrimitiveComponent; + + const auto values = UCesiumMetadataPickingBlueprintLibrary:: + GetPropertyTextureValuesFromHit(Hit); + TestTrue("values are empty", values.IsEmpty()); + }); + + It("returns values for first primitive property texture by default", + [this]() { + std::string scalarPropertyName("scalarProperty"); + std::array scalarValues{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT8, + scalarValues, + {0}); + + std::array vec2Values{ + glm::u8vec2(1, 2), + glm::u8vec2(0, 4), + glm::u8vec2(8, 8), + glm::u8vec2(10, 23)}; + const std::string vec2PropertyName("vec2Property"); + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::UINT8, + vec2Values, + {0, 1}); + + pModelComponent->Metadata = + FCesiumModelMetadata(model, *pModelMetadata); + CesiumPrimitiveData& primData = + pPrimitiveComponent->getPrimitiveData(); + primData.Metadata = + FCesiumPrimitiveMetadata(*pPrimitive, *pPrimitiveMetadata); + + FHitResult Hit; + Hit.FaceIndex = 0; + Hit.Component = pPrimitiveComponent; + + std::array locations{ + FVector_NetQuantize(1, 0, 0), + FVector_NetQuantize(0, -1, 0), + FVector_NetQuantize(0, -0.25, 0)}; + std::array expectedScalar{ + scalarValues[1], + scalarValues[2], + scalarValues[0]}; + std::array expectedVec2{ + FVector2D(vec2Values[1][0], vec2Values[1][1]), + FVector2D(vec2Values[2][0], vec2Values[2][1]), + FVector2D(vec2Values[0][0], vec2Values[0][1])}; + + for (size_t i = 0; i < locations.size(); i++) { + Hit.Location = + locations[i] * CesiumPrimitiveData::positionScaleFactor; + + const auto values = UCesiumMetadataPickingBlueprintLibrary:: + GetPropertyTextureValuesFromHit(Hit); + + TestEqual("number of values", values.Num(), 2); + TestTrue( + "contains scalar value", + values.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "contains vec2 value", + values.Contains(FString(vec2PropertyName.c_str()))); + + const FCesiumMetadataValue* pScalarValue = + values.Find(FString(scalarPropertyName.c_str())); + if (pScalarValue) { + TestEqual( + "scalar value", + UCesiumMetadataValueBlueprintLibrary::GetInteger( + *pScalarValue, + 0), + expectedScalar[i]); + } + + const FCesiumMetadataValue* pVec2Value = + values.Find(FString(vec2PropertyName.c_str())); + if (pVec2Value) { + TestEqual( + "vec2 value", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + *pVec2Value, + FVector2D::Zero()), + expectedVec2[i]); + } + } + }); + + It("returns values for specified property texture", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::array scalarValues{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT8, + scalarValues, + {0}); + + // Make another property texture + CesiumGltf::PropertyTexture& propertyTexture = + pModelMetadata->propertyTextures.emplace_back(); + propertyTexture.classProperty = "testClass"; + std::array newScalarValues = {100, -20, 33, -4}; + AddPropertyTexturePropertyToModel( + model, + propertyTexture, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT8, + newScalarValues, + {0}); + + pModelComponent->Metadata = FCesiumModelMetadata(model, *pModelMetadata); + + pPrimitiveMetadata->propertyTextures.push_back(1); + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.Metadata = + FCesiumPrimitiveMetadata(*pPrimitive, *pPrimitiveMetadata); + + FHitResult Hit; + Hit.Component = pPrimitiveComponent; + Hit.FaceIndex = 0; + + std::array locations{ + FVector_NetQuantize(1, 0, 0), + FVector_NetQuantize(0, -1, 0), + FVector_NetQuantize(0, -0.25, 0)}; + std::array expectedScalar{ + newScalarValues[1], + newScalarValues[2], + newScalarValues[0]}; + for (size_t i = 0; i < locations.size(); i++) { + Hit.Location = locations[i] * CesiumPrimitiveData::positionScaleFactor; + + const auto values = UCesiumMetadataPickingBlueprintLibrary:: + GetPropertyTextureValuesFromHit(Hit, 1); + TestEqual("number of values", values.Num(), 1); + TestTrue( + "contains scalar value", + values.Contains(FString(scalarPropertyName.c_str()))); + + const FCesiumMetadataValue* pScalarValue = + values.Find(FString(scalarPropertyName.c_str())); + if (pScalarValue) { + TestEqual( + "scalar value", + UCesiumMetadataValueBlueprintLibrary::GetInteger( + *pScalarValue, + 0), + expectedScalar[i]); + } + } + }); + }); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + Describe("Deprecated", [this]() { + Describe("GetMetadataValuesForFace", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + + // Two disconnected triangles. + std::vector positions{ + glm::vec3(-1, 1, 0), + glm::vec3(1, 1, 0), + glm::vec3(1, -1, 0), + glm::vec3(2, 2, 0), + glm::vec3(-2, 2, 0), + glm::vec3(-2, -2, 0), + }; + std::vector positionData( + positions.size() * sizeof(glm::vec3)); + std::memcpy(positionData.data(), positions.data(), positionData.size()); + CreateAttributeForPrimitive( + model, + *pPrimitive, + "POSITION", + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, + std::move(positionData)); + + pMeshFeatures = + &pPrimitive->addExtension(); + pModelMetadata = &model.addExtension< + CesiumGltf::ExtensionModelExtStructuralMetadata>(); + + std::string className = "testClass"; + pModelMetadata->schema.emplace(); + pModelMetadata->schema->classes[className]; + + pPropertyTable = &pModelMetadata->propertyTables.emplace_back(); + pPropertyTable->classProperty = className; + + pModelComponent = NewObject(); + pPrimitiveComponent = + NewObject(pModelComponent); + pPrimitiveComponent->AttachToComponent( + pModelComponent, + FAttachmentTransformRules(EAttachmentRule::KeepRelative, false)); + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData = pPrimitiveComponent->getPrimitiveData(); + }); + + It("returns empty map for invalid face index", [this]() { + std::vector featureIDs{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 2, + 0); + featureId.propertyTable = + static_cast(pModelMetadata->propertyTables.size() - 1); + + std::vector scalarValues{1, 2}; + pPropertyTable->count = static_cast(scalarValues.size()); + const std::string scalarPropertyName("scalarProperty"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + pModelComponent->Metadata = + FCesiumModelMetadata(model, *pModelMetadata); + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.Features = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pMeshFeatures); + + auto values = + UCesiumMetadataPickingBlueprintLibrary::GetMetadataValuesForFace( + pPrimitiveComponent, + -1); + TestTrue("empty values for negative index", values.IsEmpty()); + + values = + UCesiumMetadataPickingBlueprintLibrary::GetMetadataValuesForFace( + pPrimitiveComponent, + 2); + TestTrue( + "empty values for positive out-of-range index", + values.IsEmpty()); + }); + + It("returns empty map for invalid feature ID set index", [this]() { + std::vector featureIDs{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 2, + 0); + featureId.propertyTable = + static_cast(pModelMetadata->propertyTables.size() - 1); + + std::vector scalarValues{1, 2}; + pPropertyTable->count = static_cast(scalarValues.size()); + const std::string scalarPropertyName("scalarProperty"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + pModelComponent->Metadata = + FCesiumModelMetadata(model, *pModelMetadata); + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.Features = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pMeshFeatures); + + auto values = + UCesiumMetadataPickingBlueprintLibrary::GetMetadataValuesForFace( + pPrimitiveComponent, + 0, + -1); + TestTrue("empty values for negative index", values.IsEmpty()); + + values = + UCesiumMetadataPickingBlueprintLibrary::GetMetadataValuesForFace( + pPrimitiveComponent, + 0, + 1); + TestTrue( + "empty values for positive out-of-range index", + values.IsEmpty()); + }); + + It("returns empty values if feature ID set is not associated with a property table", + [this]() { + std::vector featureIDs{0, 0, 0, 1, 1, 1}; + AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 2, + 0); + + std::vector scalarValues{1, 2}; + pPropertyTable->count = static_cast(scalarValues.size()); + const std::string scalarPropertyName("scalarProperty"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(3.1f, -4.0f)}; + const std::string vec2PropertyName("vec2Property"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + pModelComponent->Metadata = + FCesiumModelMetadata(model, *pModelMetadata); + CesiumPrimitiveData& primData = + pPrimitiveComponent->getPrimitiveData(); + primData.Features = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pMeshFeatures); + + const auto values = + UCesiumMetadataPickingBlueprintLibrary::GetMetadataValuesForFace( + pPrimitiveComponent, + 0); + TestTrue("values are empty", values.IsEmpty()); + }); + + It("returns values for first feature ID set by default", [this]() { + std::vector featureIDs{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 2, + 0); + featureId.propertyTable = + static_cast(pModelMetadata->propertyTables.size() - 1); + + std::vector scalarValues{1, 2}; + pPropertyTable->count = static_cast(scalarValues.size()); + const std::string scalarPropertyName("scalarProperty"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(3.1f, -4.0f)}; + const std::string vec2PropertyName("vec2Property"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + pModelComponent->Metadata = + FCesiumModelMetadata(model, *pModelMetadata); + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.Features = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pMeshFeatures); + + for (size_t i = 0; i < scalarValues.size(); i++) { + const auto values = + UCesiumMetadataPickingBlueprintLibrary::GetMetadataValuesForFace( + pPrimitiveComponent, + static_cast(i)); + TestEqual("number of values", values.Num(), 2); + TestTrue( + "contains scalar value", + values.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "contains vec2 value", + values.Contains(FString(vec2PropertyName.c_str()))); + + const FCesiumMetadataValue* pScalarValue = + values.Find(FString(scalarPropertyName.c_str())); + if (pScalarValue) { + TestEqual( + "scalar value", + UCesiumMetadataValueBlueprintLibrary::GetInteger( + *pScalarValue, + 0), + scalarValues[i]); + } + + const FCesiumMetadataValue* pVec2Value = + values.Find(FString(vec2PropertyName.c_str())); + if (pVec2Value) { + FVector2D expected( + static_cast(vec2Values[i][0]), + static_cast(vec2Values[i][1])); + TestEqual( + "vec2 value", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + *pVec2Value, + FVector2D::Zero()), + expected); + } + } + }); + + It("returns values for specified feature ID set", [this]() { + std::vector featureIDs0{1, 1, 1, 0, 0, 0}; + CesiumGltf::FeatureId& featureId0 = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs0, + 2, + 0); + std::vector featureIDs1{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureId1 = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs1, + 2, + 1); + featureId0.propertyTable = featureId1.propertyTable = + static_cast(pModelMetadata->propertyTables.size() - 1); + + std::vector scalarValues{1, 2}; + pPropertyTable->count = static_cast(scalarValues.size()); + const std::string scalarPropertyName("scalarProperty"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(3.1f, -4.0f)}; + const std::string vec2PropertyName("vec2Property"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + pModelComponent->Metadata = + FCesiumModelMetadata(model, *pModelMetadata); + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.Features = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pMeshFeatures); + + for (size_t i = 0; i < scalarValues.size(); i++) { + const auto values = + UCesiumMetadataPickingBlueprintLibrary::GetMetadataValuesForFace( + pPrimitiveComponent, + i, + 1); + TestEqual("number of values", values.Num(), 2); + TestTrue( + "contains scalar value", + values.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "contains vec2 value", + values.Contains(FString(vec2PropertyName.c_str()))); + + const FCesiumMetadataValue& scalarValue = + *values.Find(FString(scalarPropertyName.c_str())); + TestEqual( + "scalar value", + UCesiumMetadataValueBlueprintLibrary::GetInteger(scalarValue, 0), + scalarValues[i]); + + const FCesiumMetadataValue& vec2Value = + *values.Find(FString(vec2PropertyName.c_str())); + FVector2D expected( + static_cast(vec2Values[i][0]), + static_cast(vec2Values[i][1])); + TestEqual( + "vec2 value", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + vec2Value, + FVector2D::Zero()), + expected); + } + }); + }); + + Describe("GetMetadataValuesForFaceAsStrings", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + + // Two disconnected triangles. + std::vector positions{ + glm::vec3(-1, 1, 0), + glm::vec3(1, 1, 0), + glm::vec3(1, -1, 0), + glm::vec3(2, 2, 0), + glm::vec3(-2, 2, 0), + glm::vec3(-2, -2, 0), + }; + std::vector positionData( + positions.size() * sizeof(glm::vec3)); + std::memcpy(positionData.data(), positions.data(), positionData.size()); + CreateAttributeForPrimitive( + model, + *pPrimitive, + "POSITION", + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, + std::move(positionData)); + + pMeshFeatures = + &pPrimitive->addExtension(); + pModelMetadata = &model.addExtension< + CesiumGltf::ExtensionModelExtStructuralMetadata>(); + + std::string className = "testClass"; + pModelMetadata->schema.emplace(); + pModelMetadata->schema->classes[className]; + + pPropertyTable = &pModelMetadata->propertyTables.emplace_back(); + pPropertyTable->classProperty = className; + + pModelComponent = NewObject(); + pPrimitiveComponent = + NewObject(pModelComponent); + pPrimitiveComponent->AttachToComponent( + pModelComponent, + FAttachmentTransformRules(EAttachmentRule::KeepRelative, false)); + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData = pPrimitiveComponent->getPrimitiveData(); + }); + + It("returns values for first feature ID set by default", [this]() { + std::vector featureIDs{0, 0, 0, 1, 1, 1}; + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + featureIDs, + 2, + 0); + featureId.propertyTable = + static_cast(pModelMetadata->propertyTables.size() - 1); + + std::vector scalarValues{1, 2}; + pPropertyTable->count = static_cast(scalarValues.size()); + const std::string scalarPropertyName("scalarProperty"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(3.1f, -4.0f)}; + const std::string vec2PropertyName("vec2Property"); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + pModelComponent->Metadata = + FCesiumModelMetadata(model, *pModelMetadata); + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.Features = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pMeshFeatures); + + for (size_t i = 0; i < scalarValues.size(); i++) { + const auto strings = UCesiumMetadataPickingBlueprintLibrary:: + GetMetadataValuesForFaceAsStrings( + pPrimitiveComponent, + static_cast(i)); + TestEqual("number of strings", strings.Num(), 2); + TestTrue( + "contains scalar value", + strings.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "contains vec2 value", + strings.Contains(FString(vec2PropertyName.c_str()))); + + const FString* pScalarString = + strings.Find(FString(scalarPropertyName.c_str())); + if (pScalarString) { + TestEqual( + "scalar value", + *pScalarString, + FString(std::to_string(scalarValues[i]).c_str())); + } + + const FString* pVec2String = + strings.Find(FString(vec2PropertyName.c_str())); + if (pVec2String) { + std::string expected( + "X=" + std::to_string(vec2Values[i][0]) + + " Y=" + std::to_string(vec2Values[i][1])); + TestEqual("vec2 value", *pVec2String, FString(expected.c_str())); + } + } + }); + }); + }); + PRAGMA_ENABLE_DEPRECATION_WARNINGS +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumMetadataValue.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumMetadataValue.spec.cpp new file mode 100644 index 0000000..be829c7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumMetadataValue.spec.cpp @@ -0,0 +1,1242 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataValue.h" +#include "CesiumPropertyArrayBlueprintLibrary.h" +#include "Misc/AutomationTest.h" + +#include + +BEGIN_DEFINE_SPEC( + FCesiumMetadataValueSpec, + "Cesium.Unit.MetadataValue", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +END_DEFINE_SPEC(FCesiumMetadataValueSpec) + +void FCesiumMetadataValueSpec::Define() { + Describe("Constructor", [this]() { + It("constructs value with unknown type by default", [this]() { + FCesiumMetadataValue value; + FCesiumMetadataValueType valueType = + UCesiumMetadataValueBlueprintLibrary::GetValueType(value); + TestEqual("Type", valueType.Type, ECesiumMetadataType::Invalid); + TestEqual( + "ComponentType", + valueType.ComponentType, + ECesiumMetadataComponentType::None); + TestFalse("IsArray", valueType.bIsArray); + }); + + It("constructs boolean value with correct type", [this]() { + FCesiumMetadataValue value(true); + FCesiumMetadataValueType valueType = + UCesiumMetadataValueBlueprintLibrary::GetValueType(value); + TestEqual("Type", valueType.Type, ECesiumMetadataType::Boolean); + TestEqual( + "ComponentType", + valueType.ComponentType, + ECesiumMetadataComponentType::None); + TestFalse("IsArray", valueType.bIsArray); + }); + + It("constructs scalar value with correct type", [this]() { + FCesiumMetadataValue value(1.6); + FCesiumMetadataValueType valueType = + UCesiumMetadataValueBlueprintLibrary::GetValueType(value); + TestEqual("Type", valueType.Type, ECesiumMetadataType::Scalar); + TestEqual( + "ComponentType", + valueType.ComponentType, + ECesiumMetadataComponentType::Float64); + TestFalse("IsArray", valueType.bIsArray); + }); + + It("constructs vecN value with correct type", [this]() { + FCesiumMetadataValue value(glm::u8vec4(1, 2, 3, 4)); + FCesiumMetadataValueType valueType = + UCesiumMetadataValueBlueprintLibrary::GetValueType(value); + TestEqual("Type", valueType.Type, ECesiumMetadataType::Vec4); + TestEqual( + "ComponentType", + valueType.ComponentType, + ECesiumMetadataComponentType::Uint8); + TestFalse("IsArray", valueType.bIsArray); + }); + + It("constructs matN value with correct type", [this]() { + FCesiumMetadataValue value(glm::imat2x2(-1, -2, 3, 0)); + FCesiumMetadataValueType valueType = + UCesiumMetadataValueBlueprintLibrary::GetValueType(value); + TestEqual("Type", valueType.Type, ECesiumMetadataType::Mat2); + TestEqual( + "ComponentType", + valueType.ComponentType, + ECesiumMetadataComponentType::Int32); + TestFalse("IsArray", valueType.bIsArray); + }); + + It("constructs string value with correct type", [this]() { + FCesiumMetadataValue value(std::string_view("Hello")); + FCesiumMetadataValueType valueType = + UCesiumMetadataValueBlueprintLibrary::GetValueType(value); + TestEqual("Type", valueType.Type, ECesiumMetadataType::String); + TestEqual( + "ComponentType", + valueType.ComponentType, + ECesiumMetadataComponentType::None); + TestFalse("IsArray", valueType.bIsArray); + }); + + It("constructs array value with correct type", [this]() { + CesiumGltf::PropertyArrayCopy arrayView; + FCesiumMetadataValue value(arrayView); + FCesiumMetadataValueType valueType = + UCesiumMetadataValueBlueprintLibrary::GetValueType(value); + TestEqual("Type", valueType.Type, ECesiumMetadataType::Scalar); + TestEqual( + "ComponentType", + valueType.ComponentType, + ECesiumMetadataComponentType::Uint8); + TestTrue("IsArray", valueType.bIsArray); + }); + }); + + Describe("GetBoolean", [this]() { + It("gets from boolean", [this]() { + FCesiumMetadataValue value(true); + TestTrue( + "true", + UCesiumMetadataValueBlueprintLibrary::GetBoolean(value, false)); + }); + + It("gets from scalar", [this]() { + FCesiumMetadataValue value(1.0f); + TestTrue( + "true", + UCesiumMetadataValueBlueprintLibrary::GetBoolean(value, false)); + }); + + It("gets from string", [this]() { + FCesiumMetadataValue value(std::string_view("true")); + TestTrue( + "true", + UCesiumMetadataValueBlueprintLibrary::GetBoolean(value, false)); + }); + }); + + Describe("GetByte", [this]() { + It("gets from uint8", [this]() { + FCesiumMetadataValue value(static_cast(23)); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 0), + 23); + }); + + It("gets from boolean", [this]() { + FCesiumMetadataValue value(true); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 0), + 1); + }); + + It("gets from in-range integers", [this]() { + FCesiumMetadataValue value(static_cast(255)); + TestEqual( + "larger signed integer", + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 0), + 255); + + value = FCesiumMetadataValue(static_cast(255)); + TestEqual( + "larger unsigned integer", + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 0), + 255); + }); + + It("gets from in-range floating-point numbers", [this]() { + FCesiumMetadataValue value(254.5f); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 0), + 254); + + value = FCesiumMetadataValue(0.85); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 255), + 0); + }); + + It("gets from string", [this]() { + FCesiumMetadataValue value(std::string_view("123")); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 0), + 123); + }); + + It("returns default value for out-of-range numbers", [this]() { + FCesiumMetadataValue value(static_cast(-1)); + TestEqual( + "negative integer", + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 255), + 255); + + value = FCesiumMetadataValue(-1.0); + TestEqual( + "negative floating-point number", + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 255), + 255); + + value = FCesiumMetadataValue(256); + TestEqual( + "positive integer", + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 0), + 0); + + value = FCesiumMetadataValue(255.5f); + TestEqual( + "positive floating-point number", + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 0), + 0); + }); + }); + + Describe("GetInteger", [this]() { + It("gets from in-range integers", [this]() { + FCesiumMetadataValue value(static_cast(123)); + TestEqual( + "int32_t", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + 123); + + value = FCesiumMetadataValue(static_cast(-123)); + TestEqual( + "larger signed integer", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + -123); + + value = FCesiumMetadataValue(static_cast(456)); + TestEqual( + "larger unsigned integer", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + 456); + }); + + It("gets from boolean", [this]() { + FCesiumMetadataValue value(false); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, -1), + 0); + }); + + It("gets from in-range floating point number", [this]() { + FCesiumMetadataValue value(1234.56f); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + 1234); + + value = FCesiumMetadataValue(-78.9); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + -78); + }); + + It("gets from string", [this]() { + FCesiumMetadataValue value(std::string_view("-1234")); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + -1234); + }); + + It("returns default value for out-of-range numbers", [this]() { + FCesiumMetadataValue value(std::numeric_limits::min()); + TestEqual( + "negative integer", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + 0); + + value = FCesiumMetadataValue(std::numeric_limits::lowest()); + TestEqual( + "negative floating-point number", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + 0); + + value = FCesiumMetadataValue(std::numeric_limits::max()); + TestEqual( + "positive integer", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + 0); + + value = FCesiumMetadataValue(std::numeric_limits::max()); + TestEqual( + "positive floating-point number", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + 0); + }); + }); + + Describe("GetInteger64", [this]() { + const int64_t defaultValue = static_cast(0); + + It("gets from in-range integers", [this, defaultValue]() { + FCesiumMetadataValue value(std::numeric_limits::max() - 1); + TestEqual( + "int64_t", + UCesiumMetadataValueBlueprintLibrary::GetInteger64( + value, + defaultValue), + std::numeric_limits::max() - 1); + + value = FCesiumMetadataValue(static_cast(-12345)); + TestEqual( + "smaller signed integer", + UCesiumMetadataValueBlueprintLibrary::GetInteger64( + value, + defaultValue), + static_cast(-12345)); + + value = FCesiumMetadataValue(static_cast(255)); + TestEqual( + "smaller unsigned integer", + UCesiumMetadataValueBlueprintLibrary::GetInteger64( + value, + defaultValue), + static_cast(255)); + }); + + It("gets from boolean", [this, defaultValue]() { + FCesiumMetadataValue value(true); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetInteger64( + value, + defaultValue), + static_cast(1)); + }); + + It("gets from in-range floating point number", [this, defaultValue]() { + FCesiumMetadataValue value(1234.56f); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetInteger64( + value, + defaultValue), + static_cast(1234)); + + value = FCesiumMetadataValue(-78.9); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetInteger64( + value, + defaultValue), + static_cast(-78)); + }); + + It("gets from string", [this, defaultValue]() { + FCesiumMetadataValue value(std::string_view("-1234")); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetInteger64( + value, + defaultValue), + static_cast(-1234)); + }); + + It("returns default value for out-of-range numbers", + [this, defaultValue]() { + FCesiumMetadataValue value(std::numeric_limits::lowest()); + TestEqual( + "negative floating-point number", + UCesiumMetadataValueBlueprintLibrary::GetInteger64( + value, + defaultValue), + defaultValue); + + value = FCesiumMetadataValue(std::numeric_limits::max()); + TestEqual( + "positive integer", + UCesiumMetadataValueBlueprintLibrary::GetInteger64( + value, + defaultValue), + defaultValue); + + value = FCesiumMetadataValue(std::numeric_limits::max()); + TestEqual( + "positive floating-point number", + UCesiumMetadataValueBlueprintLibrary::GetInteger64( + value, + defaultValue), + defaultValue); + }); + }); + + Describe("GetFloat", [this]() { + It("gets from in-range floating point number", [this]() { + FCesiumMetadataValue value(1234.56f); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetFloat(value, 0.0f), + 1234.56f); + + double doubleValue = -78.9; + value = FCesiumMetadataValue(doubleValue); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetFloat(value, 0.0f), + static_cast(doubleValue)); + }); + + It("gets from integer", [this]() { + FCesiumMetadataValue value(-12345); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetFloat(value, 0.0f), + static_cast(-12345)); + }); + + It("gets from boolean", [this]() { + FCesiumMetadataValue value(true); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetFloat(value, -1.0f), + 1.0f); + }); + + It("gets from string", [this]() { + FCesiumMetadataValue value(std::string_view("-123.01")); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetFloat(value, 0.0f), + static_cast(-123.01)); + }); + + It("returns default value for out-of-range numbers", [this]() { + FCesiumMetadataValue value(std::numeric_limits::lowest()); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetFloat(value, 0.0f), + 0.0f); + }); + }); + + Describe("GetFloat64", [this]() { + It("gets from floating point number", [this]() { + FCesiumMetadataValue value(78.91); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + 78.91); + + value = FCesiumMetadataValue(1234.56f); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + static_cast(1234.56f)); + }); + + It("gets from integer", [this]() { + FCesiumMetadataValue value(-12345); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0f), + static_cast(-12345)); + }); + + It("gets from boolean", [this]() { + FCesiumMetadataValue value(true); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, -1.0), + 1.0); + }); + + It("gets from string", [this]() { + FCesiumMetadataValue value(std::string_view("-1234.05")); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + -1234.05); + }); + }); + + Describe("GetIntPoint", [this]() { + It("gets from vec2", [this]() { + FCesiumMetadataValue value(glm::ivec2(1, -2)); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + value, + FIntPoint(0)), + FIntPoint(1, -2)); + + value = FCesiumMetadataValue(glm::vec2(-5.2f, 6.68f)); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + value, + FIntPoint(0)), + FIntPoint(-5, 6)); + }); + + It("gets from vec3", [this]() { + FCesiumMetadataValue value(glm::u8vec3(4, 5, 12)); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + value, + FIntPoint(0)), + FIntPoint(4, 5)); + + value = FCesiumMetadataValue(glm::vec3(-5.2f, 6.68f, -23.8f)); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + value, + FIntPoint(0)), + FIntPoint(-5, 6)); + }); + + It("gets from vec4", [this]() { + FCesiumMetadataValue value(glm::i16vec4(4, 2, 5, 12)); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + value, + FIntPoint(0)), + FIntPoint(4, 2)); + + value = FCesiumMetadataValue(glm::vec4(1.01f, -5.2f, 6.68f, -23.8f)); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + value, + FIntPoint(0)), + FIntPoint(1, -5)); + }); + + It("gets from scalar", [this]() { + FCesiumMetadataValue value(123); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + value, + FIntPoint(0)), + FIntPoint(123)); + + value = FCesiumMetadataValue(1234.56f); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + value, + FIntPoint(0)), + FIntPoint(1234)); + }); + + It("gets from boolean", [this]() { + FCesiumMetadataValue value(true); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + value, + FIntPoint(-1)), + FIntPoint(1)); + }); + + It("gets from string", [this]() { + FCesiumMetadataValue value(std::string_view("X=1 Y=2")); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + value, + FIntPoint(0)), + FIntPoint(1, 2)); + }); + }); + + Describe("GetVector2D", [this]() { + It("gets from vec2", [this]() { + FCesiumMetadataValue value(glm::ivec2(1, -2)); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + value, + FVector2D::Zero()), + FVector2D(static_cast(1), static_cast(-2))); + + value = FCesiumMetadataValue(glm::dvec2(-5.2, 6.68)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + value, + FVector2D::Zero()), + FVector2D(-5.2, 6.68)); + }); + + It("gets from vec3", [this]() { + FCesiumMetadataValue value(glm::u8vec3(4, 5, 12)); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + value, + FVector2D::Zero()), + FVector2D(static_cast(4), static_cast(5))); + + value = FCesiumMetadataValue(glm::dvec3(-5.2, 6.68, -23)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + value, + FVector2D::Zero()), + FVector2D(-5.2, 6.68)); + }); + + It("gets from vec4", [this]() { + FCesiumMetadataValue value(glm::i16vec4(4, 2, 5, 12)); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + value, + FVector2D::Zero()), + FVector2D(static_cast(4), static_cast(2))); + + value = FCesiumMetadataValue(glm::dvec4(1.01, -5.2, 6.68, -23.8)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + value, + FVector2D::Zero()), + FVector2D(1.01, -5.2)); + }); + + It("gets from scalar", [this]() { + FCesiumMetadataValue value(123); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + value, + FVector2D::Zero()), + FVector2D(static_cast(123))); + + value = FCesiumMetadataValue(1234.56f); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + value, + FVector2D::Zero()), + FVector2D(static_cast(1234.56f))); + }); + + It("gets from boolean", [this]() { + FCesiumMetadataValue value(true); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + value, + FVector2D(-1.0)), + FVector2D(1.0)); + }); + + It("gets from string", [this]() { + FCesiumMetadataValue value(std::string_view("X=1.5 Y=2.5")); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + value, + FVector2D::Zero()), + FVector2D(1.5, 2.5)); + }); + }); + + Describe("GetIntVector", [this]() { + It("gets from vec3", [this]() { + FCesiumMetadataValue value(glm::u8vec3(4, 5, 12)); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetIntVector( + value, + FIntVector(0)), + FIntVector(4, 5, 12)); + + value = FCesiumMetadataValue(glm::vec3(-5.2f, 6.68f, -23.8f)); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetIntVector( + value, + FIntVector(0)), + FIntVector(-5, 6, -23)); + }); + + It("gets from vec2", [this]() { + FCesiumMetadataValue value(glm::ivec2(1, -2)); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetIntVector( + value, + FIntVector(0)), + FIntVector(1, -2, 0)); + + value = FCesiumMetadataValue(glm::vec2(-5.2f, 6.68f)); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetIntVector( + value, + FIntVector(0)), + FIntVector(-5, 6, 0)); + }); + + It("gets from vec4", [this]() { + FCesiumMetadataValue value(glm::i16vec4(4, 2, 5, 12)); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetIntVector( + value, + FIntVector(0)), + FIntVector(4, 2, 5)); + + value = FCesiumMetadataValue(glm::vec4(1.01f, -5.2f, 6.68f, -23.8f)); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetIntVector( + value, + FIntVector(0)), + FIntVector(1, -5, 6)); + }); + + It("gets from scalar", [this]() { + FCesiumMetadataValue value(123); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetIntVector( + value, + FIntVector(0)), + FIntVector(123)); + + value = FCesiumMetadataValue(1234.56f); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetIntVector( + value, + FIntVector(0)), + FIntVector(1234)); + }); + + It("gets from boolean", [this]() { + FCesiumMetadataValue value(true); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetIntVector( + value, + FIntVector(-1)), + FIntVector(1)); + }); + + It("gets from string", [this]() { + FCesiumMetadataValue value(std::string_view("X=1 Y=2")); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + value, + FIntPoint(0)), + FIntPoint(1, 2)); + }); + }); + + Describe("GetVector3f", [this]() { + It("gets from vec3", [this]() { + FCesiumMetadataValue value(glm::vec3(-5.2f, 6.68f, -23.8f)); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetVector3f( + value, + FVector3f::Zero()), + FVector3f(-5.2f, 6.68f, -23.8f)); + }); + + It("gets from vec2", [this]() { + FCesiumMetadataValue value(glm::vec2(-5.2f, 6.68f)); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetVector3f( + value, + FVector3f::Zero()), + FVector3f(-5.2f, 6.68f, 0.0f)); + }); + + It("gets from vec4", [this]() { + FCesiumMetadataValue value(glm::vec4(1.01f, -5.2f, 6.68f, -23.8f)); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetVector3f( + value, + FVector3f::Zero()), + FVector3f(1.01f, -5.2f, 6.68f)); + }); + + It("gets from scalar", [this]() { + FCesiumMetadataValue value(1234.56f); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetVector3f( + value, + FVector3f::Zero()), + FVector3f(1234.56f)); + }); + + It("gets from boolean", [this]() { + FCesiumMetadataValue value(true); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetVector3f( + value, + FVector3f(-1.0f)), + FVector3f(1.0f)); + }); + + It("gets from string", [this]() { + FCesiumMetadataValue value(std::string_view("X=1 Y=2 Z=3")); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetVector3f( + value, + FVector3f::Zero()), + FVector3f(1, 2, 3)); + }); + }); + + Describe("GetVector", [this]() { + It("gets from vec3", [this]() { + FCesiumMetadataValue value(glm::dvec3(-5.2, 6.68, -23.8)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetVector( + value, + FVector::Zero()), + FVector(-5.2, 6.68, -23.8)); + }); + + It("gets from vec2", [this]() { + FCesiumMetadataValue value(glm::dvec2(-5.2, 6.68)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetVector( + value, + FVector::Zero()), + FVector(-5.2, 6.68, 0.0)); + }); + + It("gets from vec4", [this]() { + FCesiumMetadataValue value(glm::dvec4(1.01, -5.2, 6.68, -23.8)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetVector( + value, + FVector::Zero()), + FVector(1.01, -5.2, 6.68)); + }); + + It("gets from scalar", [this]() { + FCesiumMetadataValue value(12345); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetVector( + value, + FVector::Zero()), + FVector(static_cast(12345))); + }); + + It("gets from boolean", [this]() { + FCesiumMetadataValue value(true); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetVector(value, FVector(-1.0)), + FVector(1.0)); + }); + + It("gets from string", [this]() { + FCesiumMetadataValue value(std::string_view("X=1.5 Y=2.5 Z=3.5")); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetVector( + value, + FVector::Zero()), + FVector(1.5, 2.5, 3.5)); + }); + }); + + Describe("GetVector4", [this]() { + It("gets from vec4", [this]() { + FCesiumMetadataValue value(glm::dvec4(1.01, -5.2, 6.68, -23.8)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetVector4( + value, + FVector4::Zero()), + FVector4(1.01, -5.2, 6.68, -23.8)); + }); + + It("gets from vec3", [this]() { + FCesiumMetadataValue value(glm::dvec3(-5.2, 6.68, -23.8)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetVector4( + value, + FVector4::Zero()), + FVector4(-5.2, 6.68, -23.8, 0.0)); + }); + + It("gets from vec2", [this]() { + FCesiumMetadataValue value(glm::dvec2(-5.2, 6.68)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetVector4( + value, + FVector4::Zero()), + FVector4(-5.2, 6.68, 0.0, 0.0)); + }); + + It("gets from scalar", [this]() { + float floatValue = 7.894f; + double doubleValue = static_cast(floatValue); + FCesiumMetadataValue value(floatValue); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetVector4( + value, + FVector4::Zero()), + FVector4(doubleValue, doubleValue, doubleValue, doubleValue)); + }); + + It("gets from boolean", [this]() { + FCesiumMetadataValue value(false); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetVector4( + value, + FVector4(-1.0)), + FVector4::Zero()); + }); + + It("gets from string", [this]() { + FCesiumMetadataValue value(std::string_view("X=1.5 Y=2.5 Z=3.5 W=4.5")); + TestEqual( + "value without W-component", + UCesiumMetadataValueBlueprintLibrary::GetVector4( + value, + FVector4::Zero()), + FVector4(1.5, 2.5, 3.5, 4.5)); + + value = FCesiumMetadataValue(std::string_view("X=1.5 Y=2.5 Z=3.5")); + TestEqual( + "value without W-component", + UCesiumMetadataValueBlueprintLibrary::GetVector4( + value, + FVector4::Zero()), + FVector4(1.5, 2.5, 3.5, 1.0)); + }); + }); + + Describe("GetMatrix", [this]() { + It("gets from mat4", [this]() { + // clang-format off + glm::dmat4 input = glm::dmat4( + 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, + 9.0, 11.0, 4.0, 1.0, + 10.0, 12.0, 3.0, 1.0); + // clang-format on + input = glm::transpose(input); + + FCesiumMetadataValue value(input); + FMatrix expected( + FPlane4d(1.0, 2.0, 3.0, 4.0), + FPlane4d(5.0, 6.0, 7.0, 8.0), + FPlane4d(9.0, 11.0, 4.0, 1.0), + FPlane4d(10.0, 12.0, 3.0, 1.0)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetMatrix( + value, + FMatrix::Identity), + expected); + }); + + It("gets from mat3", [this]() { + // clang-format off + glm::dmat3 input = glm::dmat3( + 1.0, 2.0, 3.0, + 4.0, 5.0, 6.0, + 7.0, 8.0, 9.0); + // clang-format on + input = glm::transpose(input); + + FCesiumMetadataValue value(input); + FMatrix expected( + FPlane4d(1.0, 2.0, 3.0, 0.0), + FPlane4d(4.0, 5.0, 6.0, 0.0), + FPlane4d(7.0, 8.0, 9.0, 0.0), + FPlane4d(0.0, 0.0, 0.0, 0.0)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetMatrix( + value, + FMatrix::Identity), + expected); + }); + + It("gets from mat2", [this]() { + // clang-format off + glm::dmat2 input = glm::dmat2( + 1.0, 2.0, + 3.0, 4.0); + // clang-format on + input = glm::transpose(input); + + FCesiumMetadataValue value(input); + FMatrix expected( + FPlane4d(1.0, 2.0, 0.0, 0.0), + FPlane4d(3.0, 4.0, 0.0, 0.0), + FPlane4d(0.0, 0.0, 0.0, 0.0), + FPlane4d(0.0, 0.0, 0.0, 0.0)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetMatrix( + value, + FMatrix::Identity), + expected); + }); + + It("gets from scalar", [this]() { + FCesiumMetadataValue value(7.894); + FMatrix expected( + FPlane4d(7.894, 0.0, 0.0, 0.0), + FPlane4d(0.0, 7.894, 0.0, 0.0), + FPlane4d(0.0, 0.0, 7.894, 0.0), + FPlane4d(0.0, 0.0, 0.0, 7.894)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetMatrix( + value, + FMatrix::Identity), + expected); + }); + + It("gets from boolean", [this]() { + FCesiumMetadataValue value(false); + FMatrix expected( + FPlane4d(0.0, 0.0, 0.0, 0.0), + FPlane4d(0.0, 0.0, 0.0, 0.0), + FPlane4d(0.0, 0.0, 0.0, 0.0), + FPlane4d(0.0, 0.0, 0.0, 0.0)); + TestEqual( + "double", + UCesiumMetadataValueBlueprintLibrary::GetMatrix( + value, + FMatrix::Identity), + expected); + }); + }); + + Describe("GetFString", [this]() { + It("gets from string", [this]() { + FCesiumMetadataValue value(std::string_view("Hello")); + TestEqual( + "value", + UCesiumMetadataValueBlueprintLibrary::GetString(value, FString("")), + FString("Hello")); + }); + + It("gets from boolean", [this]() { + FCesiumMetadataValue value(true); + TestEqual( + "true", + UCesiumMetadataValueBlueprintLibrary::GetString(value, FString("")), + FString("true")); + + value = FCesiumMetadataValue(false); + TestEqual( + "false", + UCesiumMetadataValueBlueprintLibrary::GetString(value, FString("")), + FString("false")); + }); + + It("gets from scalar", [this]() { + FCesiumMetadataValue value(1234); + TestEqual( + "integer", + UCesiumMetadataValueBlueprintLibrary::GetString(value, FString("")), + FString("1234")); + + value = FCesiumMetadataValue(1.2345f); + TestEqual( + "float", + UCesiumMetadataValueBlueprintLibrary::GetString(value, FString("")), + FString(std::to_string(1.2345f).c_str())); + }); + + It("gets from vecN", [this]() { + FCesiumMetadataValue value(glm::ivec4(1, 2, 3, 4)); + TestEqual( + "vec4", + UCesiumMetadataValueBlueprintLibrary::GetString(value, FString("")), + FString("X=1 Y=2 Z=3 W=4")); + }); + + It("gets from matN", [this]() { + // clang-format off + FCesiumMetadataValue value( + glm::i32mat4x4( + 1, 2, 3, -7, + 4, 5, 6, 88, + 0, -1, -4, 4, + 2 , 70, 8, 9)); + // clang-format on + std::string expected("[1 4 0 2] [2 5 -1 70] [3 6 -4 8] [-7 88 4 9]"); + TestEqual( + "mat4", + UCesiumMetadataValueBlueprintLibrary::GetString(value, FString("")), + FString(expected.c_str())); + }); + }); + + Describe("GetArray", [this]() { + It("gets empty array from non-array value", [this]() { + FCesiumMetadataValue value(std::string_view("not an array")); + FCesiumPropertyArray array = + UCesiumMetadataValueBlueprintLibrary::GetArray(value); + TestEqual( + "array size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(0)); + + FCesiumMetadataValueType elementType = + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array); + TestEqual( + "array element type", + elementType.Type, + ECesiumMetadataType::Invalid); + TestEqual( + "array element component type", + elementType.ComponentType, + ECesiumMetadataComponentType::None); + }); + + It("gets array from array value", [this]() { + std::vector arrayValues{1, 2}; + CesiumGltf::PropertyArrayCopy arrayView = + std::vector(arrayValues); + + FCesiumMetadataValue value(arrayView); + FCesiumPropertyArray array = + UCesiumMetadataValueBlueprintLibrary::GetArray(value); + TestEqual( + "array size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(arrayValues.size())); + + FCesiumMetadataValueType elementType = + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array); + TestEqual( + "array element type", + elementType.Type, + ECesiumMetadataType::Scalar); + TestEqual( + "array element component type", + elementType.ComponentType, + ECesiumMetadataComponentType::Uint8); + }); + }); + + Describe("IsEmpty", [this]() { + It("returns true for default value", [this]() { + FCesiumMetadataValue value; + TestTrue("IsEmpty", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + }); + + It("returns false for boolean value", [this]() { + FCesiumMetadataValue value(true); + TestFalse( + "IsEmpty", + UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + }); + + It("returns false for scalar value", [this]() { + FCesiumMetadataValue value(1.6); + TestFalse( + "IsEmpty", + UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + }); + + It("returns false for vecN value", [this]() { + FCesiumMetadataValue value(glm::u8vec4(1, 2, 3, 4)); + TestFalse( + "IsEmpty", + UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + }); + + It("returns false for matN value", [this]() { + FCesiumMetadataValue value(glm::imat2x2(-1, -2, 3, 0)); + TestFalse( + "IsEmpty", + UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + }); + + It("returns false for string value", [this]() { + FCesiumMetadataValue value(std::string_view("Hello")); + TestFalse( + "IsEmpty", + UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + }); + + It("returns false for array value", [this]() { + CesiumGltf::PropertyArrayCopy arrayView; + FCesiumMetadataValue value(arrayView); + TestFalse( + "IsEmpty", + UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + }); + }); + + Describe("GetValuesAsStrings", [this]() { + It("returns empty map if input is empty", [this]() { + TMap values; + const auto strings = + UCesiumMetadataValueBlueprintLibrary::GetValuesAsStrings(values); + TestTrue("values map is empty", strings.IsEmpty()); + }); + + It("returns values as strings", [this]() { + TMap values; + values.Add({"scalar", FCesiumMetadataValue(-1)}); + values.Add({"vec2", FCesiumMetadataValue(glm::u8vec2(2, 3))}); + values.Add( + {"array", + FCesiumMetadataValue( + CesiumGltf::PropertyArrayCopy({1, 2, 3}))}); + + const auto strings = + UCesiumMetadataValueBlueprintLibrary::GetValuesAsStrings(values); + TestEqual("map count", values.Num(), strings.Num()); + + const FString* pString = strings.Find(FString("scalar")); + TestTrue("has scalar value", pString != nullptr); + TestEqual("scalar value as string", *pString, FString("-1")); + + pString = strings.Find(FString("vec2")); + TestTrue("has vec2 value", pString != nullptr); + TestEqual("vec2 value as string", *pString, FString("X=2 Y=3")); + + pString = strings.Find(FString("array")); + TestTrue("has array value", pString != nullptr); + TestEqual("array value as string", *pString, FString()); + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumOriginShiftComponent.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumOriginShiftComponent.spec.cpp new file mode 100644 index 0000000..1b6e4be --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumOriginShiftComponent.spec.cpp @@ -0,0 +1,169 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "CesiumOriginShiftComponent.h" +#include "CesiumGeoreference.h" +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumSubLevelComponent.h" +#include "CesiumTestHelpers.h" +#include "Editor.h" +#include "Engine/StaticMeshActor.h" +#include "Engine/World.h" +#include "EngineUtils.h" +#include "LevelInstance/LevelInstanceActor.h" +#include "Misc/AutomationTest.h" +#include "Tests/AutomationEditorCommon.h" + +BEGIN_DEFINE_SPEC( + FCesiumOriginShiftComponentSpec, + "Cesium.Unit.OriginShiftComponent", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) + +TObjectPtr pWorld; +TObjectPtr pGeoreference; +TObjectPtr pOriginShiftActor; +TObjectPtr pOriginShiftComponent; +FDelegateHandle subscriptionPostPIEStarted; + +END_DEFINE_SPEC(FCesiumOriginShiftComponentSpec) + +using namespace CesiumTestHelpers; + +void FCesiumOriginShiftComponentSpec::Define() { + BeforeEach([this]() { + if (IsValid(pWorld)) { + // Only run the below once in order to save time loading/unloading + // levels for every little test. + return; + } + + pWorld = FAutomationEditorCommonUtils::CreateNewMap(); + + pOriginShiftActor = pWorld->SpawnActor(); + pOriginShiftActor->SetMobility(EComponentMobility::Movable); + trackForPlay(pOriginShiftActor); + + pOriginShiftComponent = Cast( + pOriginShiftActor->AddComponentByClass( + UCesiumOriginShiftComponent::StaticClass(), + false, + FTransform::Identity, + false)); + trackForPlay(pOriginShiftComponent); + + pGeoreference = nullptr; + for (TActorIterator it(pWorld); it; ++it) { + pGeoreference = *it; + } + + trackForPlay(pGeoreference); + }); + + AfterEach([this]() {}); + + It("automatically adds a globe anchor to go with the origin shift", [this]() { + UCesiumGlobeAnchorComponent* pGlobeAnchor = + pOriginShiftActor->FindComponentByClass(); + TestNotNull("pGlobeAnchor", pGlobeAnchor); + }); + + Describe( + "does not shift origin when in between sub-levels when mode is SwitchSubLevelsOnly", + [this]() { + LatentBeforeEach( + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + subscriptionPostPIEStarted = + FEditorDelegates::PostPIEStarted.AddLambda( + [done](bool isSimulating) { done.Execute(); }); + FRequestPlaySessionParams params{}; + GEditor->RequestPlaySession(params); + }); + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + FEditorDelegates::PostPIEStarted.Remove(subscriptionPostPIEStarted); + + findInPlay(pOriginShiftActor) + ->SetActorLocation(FVector(10000.0, 20000.0, 300.0)); + }); + It("", [this]() { + TestEqual( + "location", + findInPlay(pOriginShiftActor)->GetActorLocation(), + FVector(10000.0, 20000.0, 300.0)); + }); + AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() { + GEditor->RequestEndPlayMap(); + }); + }); + + Describe( + "shifts origin by changing georeference when mode is ChangeCesiumGeoreference", + [this]() { + LatentBeforeEach( + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + subscriptionPostPIEStarted = + FEditorDelegates::PostPIEStarted.AddLambda( + [done](bool isSimulating) { done.Execute(); }); + FRequestPlaySessionParams params{}; + GEditor->RequestPlaySession(params); + }); + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + FEditorDelegates::PostPIEStarted.Remove(subscriptionPostPIEStarted); + + // Start with the Actor at the origin at LLH 0,0,0. + UCesiumGlobeAnchorComponent* pGlobeAnchor = + findInPlay(pOriginShiftActor) + ->FindComponentByClass(); + pGlobeAnchor->MoveToLongitudeLatitudeHeight(FVector(0.0, 0.0, 0.0)); + findInPlay(pGeoreference) + ->SetOriginLongitudeLatitudeHeight(FVector(0.0, 0.0, 0.0)); + pGlobeAnchor->SnapToEastSouthUp(); + + // Activate georeference origin shifting + findInPlay(pOriginShiftComponent) + ->SetMode(ECesiumOriginShiftMode::ChangeCesiumGeoreference); + + // Move it to 90 degrees longitude. + FVector location = FVector( + CesiumGeospatial::Ellipsoid::WGS84.getMaximumRadius() * 100.0, + 0.0, + -CesiumGeospatial::Ellipsoid::WGS84.getMaximumRadius() * 100.0); + findInPlay(pOriginShiftActor)->SetActorLocation(location); + TestEqual("Longitude", pGlobeAnchor->GetLongitude(), 90.0); + TestEqual("Latitude", pGlobeAnchor->GetLatitude(), 0.0); + TestEqual("Height", pGlobeAnchor->GetHeight(), 0.0); + TestTrue( + "Rotation", + pGlobeAnchor->GetEastSouthUpRotation().Equals(FQuat::Identity)); + }); + It("", [this]() { + TestEqual( + "location", + findInPlay(pOriginShiftActor)->GetActorLocation(), + FVector::Zero()); + + UCesiumGlobeAnchorComponent* pGlobeAnchor = + findInPlay(pOriginShiftActor) + ->FindComponentByClass(); + TestEqual("Longitude", pGlobeAnchor->GetLongitude(), 90.0); + TestEqual("Latitude", pGlobeAnchor->GetLatitude(), 0.0); + TestEqual("Height", pGlobeAnchor->GetHeight(), 0.0); + + // The Actor should still be aligned with the new East-South-Up + // because moving it will rotate it for globe curvature. + TestTrue( + "Rotation", + pGlobeAnchor->GetEastSouthUpRotation().Equals(FQuat::Identity)); + }); + AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() { + GEditor->RequestEndPlayMap(); + }); + }); +} + +#endif // #if WITH_EDITOR diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPrimitiveFeatures.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPrimitiveFeatures.spec.cpp new file mode 100644 index 0000000..7dd21d9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPrimitiveFeatures.spec.cpp @@ -0,0 +1,752 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPrimitiveFeatures.h" +#include "CesiumGltf/ExtensionExtMeshFeatures.h" +#include "CesiumGltfSpecUtility.h" +#include "Misc/AutomationTest.h" + +BEGIN_DEFINE_SPEC( + FCesiumPrimitiveFeaturesSpec, + "Cesium.Unit.PrimitiveFeatures", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +CesiumGltf::Model model; +CesiumGltf::MeshPrimitive* pPrimitive; +CesiumGltf::ExtensionExtMeshFeatures* pExtension; +END_DEFINE_SPEC(FCesiumPrimitiveFeaturesSpec) + +void FCesiumPrimitiveFeaturesSpec::Define() { + Describe("Constructor", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + pExtension = + &pPrimitive->addExtension(); + }); + + It("constructs with no feature ID sets", [this]() { + // This is technically disallowed by the spec, but just make sure it's + // handled reasonably. + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + TArray featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets( + primitiveFeatures); + TestEqual("Number of FeatureIDSets", featureIDSets.Num(), 0); + }); + + It("constructs with single feature ID set", [this]() { + CesiumGltf::FeatureId& featureID = pExtension->featureIds.emplace_back(); + featureID.featureCount = 10; + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + const TArray& featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets( + primitiveFeatures); + TestEqual("Number of FeatureIDSets", featureIDSets.Num(), 1); + + const FCesiumFeatureIdSet& featureIDSet = featureIDSets[0]; + TestEqual( + "Feature Count", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(featureIDSet), + static_cast(featureID.featureCount)); + TestEqual( + "FeatureIDType", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + featureIDSet), + ECesiumFeatureIdSetType::Implicit); + }); + + It("constructs with multiple feature ID sets", [this]() { + const std::vector attributeIDs{0, 0, 0}; + AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 1, 0); + + const std::vector textureIDs{1, 2, 3}; + const std::vector texCoords{ + glm::vec2(0, 0), + glm::vec2(0.34, 0), + glm::vec2(0.67, 0)}; + AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + textureIDs, + 3, + 3, + 1, + texCoords, + 0); + + CesiumGltf::FeatureId& implicitIDs = + pExtension->featureIds.emplace_back(); + implicitIDs.featureCount = 3; + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + const TArray& featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets( + primitiveFeatures); + TestEqual("Number of FeatureIDSets", featureIDSets.Num(), 3); + + const std::vector expectedTypes{ + ECesiumFeatureIdSetType::Attribute, + ECesiumFeatureIdSetType::Texture, + ECesiumFeatureIdSetType::Implicit}; + + for (size_t i = 0; i < featureIDSets.Num(); i++) { + const FCesiumFeatureIdSet& featureIDSet = + featureIDSets[static_cast(i)]; + const CesiumGltf::FeatureId& gltfFeatureID = pExtension->featureIds[i]; + TestEqual( + "Feature Count", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(featureIDSet), + static_cast(gltfFeatureID.featureCount)); + TestEqual( + "FeatureIDType", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + featureIDSet), + expectedTypes[i]); + } + }); + }); + + Describe("GetFeatureIDSetsOfType", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + pExtension = + &pPrimitive->addExtension(); + + const std::vector attributeIDs{0, 0, 0}; + AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 1, 0); + + const std::vector textureIDs{1, 2, 3}; + const std::vector texCoords{ + glm::vec2(0, 0), + glm::vec2(0.34, 0), + glm::vec2(0.67, 0)}; + AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + textureIDs, + 3, + 3, + 1, + texCoords, + 0); + + CesiumGltf::FeatureId& implicitIDs = + pExtension->featureIds.emplace_back(); + implicitIDs.featureCount = 3; + }); + + It("gets feature ID attribute", [this]() { + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + const TArray featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSetsOfType( + primitiveFeatures, + ECesiumFeatureIdSetType::Attribute); + TestEqual("Number of FeatureIDSets", featureIDSets.Num(), 1); + + const FCesiumFeatureIdSet& featureIDSet = featureIDSets[0]; + TestEqual( + "FeatureIDType", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + featureIDSet), + ECesiumFeatureIdSetType::Attribute); + + const FCesiumFeatureIdAttribute& attribute = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute( + featureIDSet); + TestEqual( + "AttributeStatus", + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDAttributeStatus(attribute), + ECesiumFeatureIdAttributeStatus::Valid); + }); + + It("gets feature ID texture", [this]() { + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + const TArray featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSetsOfType( + primitiveFeatures, + ECesiumFeatureIdSetType::Texture); + TestEqual("Number of FeatureIDSets", featureIDSets.Num(), 1); + + const FCesiumFeatureIdSet& featureIDSet = featureIDSets[0]; + TestEqual( + "FeatureIDType", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + featureIDSet), + ECesiumFeatureIdSetType::Texture); + + const FCesiumFeatureIdTexture& texture = + UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDTexture( + featureIDSet); + TestEqual( + "TextureStatus", + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( + texture), + ECesiumFeatureIdTextureStatus::Valid); + }); + + It("gets implicit feature ID", [this]() { + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + const TArray featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSetsOfType( + primitiveFeatures, + ECesiumFeatureIdSetType::Implicit); + TestEqual("Number of FeatureIDSets", featureIDSets.Num(), 1); + + const FCesiumFeatureIdSet& featureIDSet = featureIDSets[0]; + TestEqual( + "FeatureIDType", + UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType( + featureIDSet), + ECesiumFeatureIdSetType::Implicit); + }); + }); + + Describe("GetFirstVertexFromFace", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + pExtension = + &pPrimitive->addExtension(); + }); + + It("returns -1 for out-of-bounds face index", [this]() { + const std::vector indices{0, 1, 2, 0, 2, 3}; + CreateIndicesForPrimitive( + model, + *pPrimitive, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, + indices); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + TestEqual( + "VertexIndexForNegativeFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFirstVertexFromFace( + primitiveFeatures, + -1), + -1); + TestEqual( + "VertexIndexForOutOfBoundsFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFirstVertexFromFace( + primitiveFeatures, + 2), + -1); + }); + + It("returns correct value for primitive without indices", [this]() { + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 9; + const int64 numFaces = accessor.count / 3; + + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + for (int64 i = 0; i < numFaces; i++) { + TestEqual( + "VertexIndexForFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFirstVertexFromFace( + primitiveFeatures, + i), + i * 3); + } + }); + + It("returns correct value for primitive with indices", [this]() { + const std::vector indices{0, 1, 2, 0, 2, 3, 4, 5, 6}; + CreateIndicesForPrimitive( + model, + *pPrimitive, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, + indices); + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 7; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + const size_t numFaces = indices.size() / 3; + for (size_t i = 0; i < numFaces; i++) { + TestEqual( + "VertexIndexForFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFirstVertexFromFace( + primitiveFeatures, + static_cast(i)), + indices[i * 3]); + } + }); + }); + + Describe("GetFeatureIDFromFace", [this]() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + pExtension = + &pPrimitive->addExtension(); + }); + + It("returns -1 for primitive with empty feature ID sets", [this]() { + const std::vector indices{0, 1, 2, 0, 2, 3}; + CreateIndicesForPrimitive( + model, + *pPrimitive, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, + indices); + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 6; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + // Adds empty feature ID. + pExtension->featureIds.emplace_back(); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + const TArray& featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets( + primitiveFeatures); + + TestEqual( + "FeatureIDForPrimitiveWithNoSets", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 0), + -1); + }); + + It("returns -1 for out of bounds feature ID set index", [this]() { + std::vector attributeIDs{1, 1, 1, 1, 0, 0, 0}; + AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 2, 0); + + const std::vector indices{0, 1, 2, 0, 2, 3, 4, 5, 6}; + CreateIndicesForPrimitive( + model, + *pPrimitive, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, + indices); + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 7; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + const TArray& featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets( + primitiveFeatures); + + TestEqual( + "FeatureIDForOutOfBoundsSetIndex", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 0, + -1), + -1); + TestEqual( + "FeatureIDForOutOfBoundsSetIndex", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 0, + 2), + -1); + }); + + Describe("FeatureIDAttribute", [this]() { + It("returns -1 for out-of-bounds face index", [this]() { + std::vector attributeIDs{1, 1, 1}; + AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 1, 0); + + const std::vector indices{0, 1, 2}; + CreateIndicesForPrimitive( + model, + *pPrimitive, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, + indices); + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 3; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + TestEqual( + "FeatureIDForNegativeFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + -1), + -1); + TestEqual( + "FeatureIDForOutOfBoundsFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 2), + -1); + }); + + It("returns correct values for primitive without indices", [this]() { + std::vector attributeIDs{1, 1, 1, 2, 2, 2, 0, 0, 0}; + AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 3, 0); + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 9; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + const size_t numFaces = static_cast(accessor.count / 3); + for (size_t i = 0; i < numFaces; i++) { + TestEqual( + "FeatureIDForFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + static_cast(i)), + attributeIDs[i * 3]); + } + }); + + It("returns correct values for primitive with indices", [this]() { + std::vector attributeIDs{1, 1, 1, 1, 0, 0, 0}; + AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 2, 0); + + const std::vector indices{0, 1, 2, 0, 2, 3, 4, 5, 6}; + CreateIndicesForPrimitive( + model, + *pPrimitive, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, + indices); + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 7; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + const size_t numFaces = indices.size() / 3; + for (size_t i = 0; i < numFaces; i++) { + TestEqual( + "FeatureIDForFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + static_cast(i)), + attributeIDs[i * 3]); + } + }); + }); + + Describe("FeatureIDTexture", [this]() { + It("returns -1 for out-of-bounds face index", [this]() { + const std::vector textureIDs{0}; + const std::vector texCoords{ + glm::vec2(0, 0), + glm::vec2(0, 0), + glm::vec2(0, 0)}; + AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + textureIDs, + 4, + 4, + 1, + texCoords, + 0); + + const std::vector indices{0, 1, 2}; + CreateIndicesForPrimitive( + model, + *pPrimitive, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, + indices); + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 3; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + TestEqual( + "FeatureIDForNegativeFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + -1), + -1); + TestEqual( + "FeatureIDForOutOfBoundsFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 2), + -1); + }); + + It("returns correct values for primitive without indices", [this]() { + const std::vector textureIDs{0, 1, 2, 3}; + const std::vector texCoords{ + glm::vec2(0, 0), + glm::vec2(0, 0), + glm::vec2(0, 0), + glm::vec2(0.75, 0), + glm::vec2(0.75, 0), + glm::vec2(0.75, 0)}; + AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + textureIDs, + 4, + 4, + 1, + texCoords, + 0); + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 6; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + TestEqual( + "FeatureIDForFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 0), + 0); + TestEqual( + "FeatureIDForFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 1), + 3); + }); + + It("returns correct values for primitive with indices", [this]() { + const std::vector textureIDs{0, 1, 2, 3}; + const std::vector texCoords{ + glm::vec2(0, 0), + glm::vec2(0.25, 0), + glm::vec2(0.5, 0), + glm::vec2(0.75, 0)}; + AddFeatureIDsAsTextureToModel( + model, + *pPrimitive, + textureIDs, + 4, + 4, + 1, + texCoords, + 0); + + const std::vector indices{0, 1, 2, 2, 0, 3}; + CreateIndicesForPrimitive( + model, + *pPrimitive, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, + indices); + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 4; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + TestEqual( + "FeatureIDForFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 0), + 0); + TestEqual( + "FeatureIDForFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 1), + 2); + }); + }); + + Describe("ImplicitFeatureIDs", [this]() { + BeforeEach([this]() { + CesiumGltf::FeatureId& implicitIDs = + pExtension->featureIds.emplace_back(); + implicitIDs.featureCount = 6; + }); + + It("returns -1 for out-of-bounds face index", [this]() { + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 6; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + TestEqual( + "FeatureIDForNegativeFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + -1), + -1); + TestEqual( + "FeatureIDForOutOfBoundsFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 10), + -1); + }); + + It("returns correct values for primitive without indices", [this]() { + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 6; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + TestEqual( + "FeatureIDForFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 0), + 0); + TestEqual( + "FeatureIDForFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 1), + 3); + }); + + It("returns correct values for primitive with indices", [this]() { + const std::vector indices{2, 1, 0, 3, 4, 5}; + CreateIndicesForPrimitive( + model, + *pPrimitive, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, + indices); + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 4; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + TestEqual( + "FeatureIDForFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 0), + 2); + TestEqual( + "FeatureIDForFace", + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + 1), + 3); + }); + }); + + It("gets feature ID from correct set with specified feature ID set index", + [this]() { + // First feature ID set is attribute + std::vector attributeIDs{1, 1, 1, 1, 0, 0, 0}; + AddFeatureIDsAsAttributeToModel( + model, + *pPrimitive, + attributeIDs, + 2, + 0); + + const std::vector indices{0, 1, 2, 0, 2, 3, 4, 5, 6}; + CreateIndicesForPrimitive( + model, + *pPrimitive, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, + indices); + + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.count = 7; + pPrimitive->attributes.insert( + {"POSITION", static_cast(model.accessors.size() - 1)}); + + // Second feature ID set is implicit + CesiumGltf::FeatureId& implicitIDs = + pExtension->featureIds.emplace_back(); + implicitIDs.featureCount = 7; + + FCesiumPrimitiveFeatures primitiveFeatures = + FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension); + + const TArray& featureIDSets = + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets( + primitiveFeatures); + TestEqual("FeatureIDSetCount", featureIDSets.Num(), 2); + + int64 setIndex = 0; + for (size_t index = 0; index < indices.size(); index += 3) { + std::string label("FeatureIDAttribute" + std::to_string(index)); + int64 faceIndex = static_cast(index) / 3; + int64 featureID = static_cast(attributeIDs[indices[index]]); + TestEqual( + FString(label.c_str()), + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + faceIndex, + setIndex), + featureID); + } + + setIndex = 1; + for (size_t index = 0; index < indices.size(); index += 3) { + std::string label("ImplicitFeatureID" + std::to_string(index)); + int64 faceIndex = static_cast(index) / 3; + int64 featureID = static_cast(indices[index]); + TestEqual( + FString(label.c_str()), + UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace( + primitiveFeatures, + faceIndex, + setIndex), + featureID); + } + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyArray.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyArray.spec.cpp new file mode 100644 index 0000000..1c5e51b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyArray.spec.cpp @@ -0,0 +1,145 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataValue.h" +#include "CesiumPropertyArrayBlueprintLibrary.h" +#include "Misc/AutomationTest.h" + +BEGIN_DEFINE_SPEC( + FCesiumPropertyArraySpec, + "Cesium.Unit.PropertyArray", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +END_DEFINE_SPEC(FCesiumPropertyArraySpec) + +void FCesiumPropertyArraySpec::Define() { + Describe("Constructor", [this]() { + It("constructs empty array by default", [this]() { + FCesiumPropertyArray array; + TestEqual( + "size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + 0); + + FCesiumMetadataValueType valueType = + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array); + TestEqual("type", valueType.Type, ECesiumMetadataType::Invalid); + TestEqual( + "componentType", + valueType.ComponentType, + ECesiumMetadataComponentType::None); + + TestEqual( + "blueprint type", + UCesiumPropertyArrayBlueprintLibrary::GetElementBlueprintType(array), + ECesiumMetadataBlueprintType::None); + }); + + It("constructs empty array from empty view", [this]() { + CesiumGltf::PropertyArrayCopy arrayView; + FCesiumPropertyArray array(arrayView); + TestEqual( + "size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + 0); + + FCesiumMetadataValueType valueType = + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array); + TestEqual("type", valueType.Type, ECesiumMetadataType::Scalar); + TestEqual( + "componentType", + valueType.ComponentType, + ECesiumMetadataComponentType::Uint8); + + TestEqual( + "blueprint type", + UCesiumPropertyArrayBlueprintLibrary::GetElementBlueprintType(array), + ECesiumMetadataBlueprintType::Byte); + }); + + It("constructs non-empty array", [this]() { + std::vector values{1, 2, 3, 4}; + CesiumGltf::PropertyArrayCopy arrayView = std::vector(values); + FCesiumPropertyArray array(arrayView); + TestEqual( + "size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(values.size())); + + FCesiumMetadataValueType valueType = + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array); + TestEqual("type", valueType.Type, ECesiumMetadataType::Scalar); + TestEqual( + "componentType", + valueType.ComponentType, + ECesiumMetadataComponentType::Uint8); + + TestEqual( + "blueprint type", + UCesiumPropertyArrayBlueprintLibrary::GetElementBlueprintType(array), + ECesiumMetadataBlueprintType::Byte); + }); + }); + + Describe("GetValue", [this]() { + It("gets bogus value for out-of-bounds index", [this]() { + std::vector values{1}; + CesiumGltf::PropertyArrayCopy arrayView = std::vector(values); + FCesiumPropertyArray array(arrayView); + TestEqual( + "size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(values.size())); + + FCesiumMetadataValue value = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, -1); + FCesiumMetadataValueType valueType = + UCesiumMetadataValueBlueprintLibrary::GetValueType(value); + + TestEqual("type", valueType.Type, ECesiumMetadataType::Invalid); + TestEqual( + "componentType", + valueType.ComponentType, + ECesiumMetadataComponentType::None); + + value = UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 1); + valueType = UCesiumMetadataValueBlueprintLibrary::GetValueType(value); + TestEqual("type", valueType.Type, ECesiumMetadataType::Invalid); + TestEqual( + "componentType", + valueType.ComponentType, + ECesiumMetadataComponentType::None); + }); + + It("gets value for valid index", [this]() { + std::vector values{1, 2, 3, 4}; + CesiumGltf::PropertyArrayCopy arrayView = std::vector(values); + FCesiumPropertyArray array(arrayView); + TestEqual( + "size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyArrayBlueprintLibrary::GetValue( + array, + static_cast(i)); + + FCesiumMetadataValueType valueType = + UCesiumMetadataValueBlueprintLibrary::GetValueType(value); + TestEqual("type", valueType.Type, ECesiumMetadataType::Scalar); + TestEqual( + "componentType", + valueType.ComponentType, + ECesiumMetadataComponentType::Uint8); + + TestEqual( + "byte value", + UCesiumMetadataValueBlueprintLibrary::GetByte(value, 0), + values[i]); + } + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyTable.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyTable.spec.cpp new file mode 100644 index 0000000..d04e56a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyTable.spec.cpp @@ -0,0 +1,844 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyTable.h" +#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltfSpecUtility.h" +#include "Misc/AutomationTest.h" +#include + +BEGIN_DEFINE_SPEC( + FCesiumPropertyTableSpec, + "Cesium.Unit.PropertyTable", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +CesiumGltf::Model model; +CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension; +CesiumGltf::PropertyTable* pPropertyTable; +END_DEFINE_SPEC(FCesiumPropertyTableSpec) + +void FCesiumPropertyTableSpec::Define() { + BeforeEach([this]() { + model = CesiumGltf::Model(); + pExtension = + &model.addExtension(); + pExtension->schema.emplace(); + pPropertyTable = &pExtension->propertyTables.emplace_back(); + }); + + Describe("Constructor", [this]() { + It("constructs invalid instance by default", [this]() { + FCesiumPropertyTable propertyTable; + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::ErrorInvalidPropertyTable); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(0)); + }); + + It("constructs invalid instance for missing schema", [this]() { + pExtension->schema.reset(); + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::ErrorInvalidPropertyTableClass); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(0)); + }); + + It("constructs invalid instance for missing class", [this]() { + pPropertyTable->classProperty = "nonexistent class"; + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::ErrorInvalidPropertyTableClass); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(0)); + }); + + It("constructs valid instance with valid property", [this]() { + pPropertyTable->classProperty = "testClass"; + std::string propertyName("testProperty"); + std::vector values{1, 2, 3, 4}; + pPropertyTable->count = static_cast(values.size()); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + propertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + values); + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(values.size())); + }); + + It("constructs valid instance with invalid property", [this]() { + // Even if one of its properties is invalid, the property table itself is + // still valid. + pPropertyTable->classProperty = "testClass"; + std::string propertyName("testProperty"); + std::vector values{1, 2, 3, 4}; + pPropertyTable->count = static_cast(values.size()); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + propertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, // Incorrect + // component type + values); + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(values.size())); + }); + }); + + Describe("GetProperties", [this]() { + BeforeEach([this]() { pPropertyTable->classProperty = "testClass"; }); + + It("returns no properties for invalid property table", [this]() { + FCesiumPropertyTable propertyTable; + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::ErrorInvalidPropertyTable); + const auto properties = + UCesiumPropertyTableBlueprintLibrary::GetProperties(propertyTable); + TestTrue("properties are empty", properties.IsEmpty()); + }); + + It("gets valid properties", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::vector scalarValues{1, 2, 3, 4}; + pPropertyTable->count = static_cast(scalarValues.size()); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::string vec2PropertyName("vec2Property"); + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(-0.7f, 4.9f), + glm::vec2(8.0f, 2.0f), + glm::vec2(11.0f, 0.0f), + }; + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(scalarValues.size())); + + const auto properties = + UCesiumPropertyTableBlueprintLibrary::GetProperties(propertyTable); + + TestTrue( + "has scalar property", + properties.Contains(FString(scalarPropertyName.c_str()))); + const FCesiumPropertyTableProperty& scalarProperty = + *properties.Find(FString(scalarPropertyName.c_str())); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(scalarProperty), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + scalarProperty), + static_cast(scalarValues.size())); + for (size_t i = 0; i < scalarValues.size(); i++) { + std::string label("Property value " + std::to_string(i)); + TestEqual( + label.c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger( + scalarProperty, + static_cast(i)), + scalarValues[i]); + } + + TestTrue( + "has vec2 property", + properties.Contains(FString(vec2PropertyName.c_str()))); + const FCesiumPropertyTableProperty& vec2Property = + *properties.Find(FString(vec2PropertyName.c_str())); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(vec2Property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + vec2Property), + static_cast(vec2Values.size())); + for (size_t i = 0; i < vec2Values.size(); i++) { + std::string label("Property value " + std::to_string(i)); + FVector2D expected( + static_cast(vec2Values[i][0]), + static_cast(vec2Values[i][1])); + TestEqual( + label.c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( + vec2Property, + static_cast(i), + FVector2D::Zero()), + expected); + } + }); + + It("gets invalid property", [this]() { + // Even invalid properties should still be retrieved. + std::vector values{0, 1, 2}; + pPropertyTable->count = static_cast(values.size()); + std::string propertyName("badProperty"); + + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + propertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + values); + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(values.size())); + + const auto properties = + UCesiumPropertyTableBlueprintLibrary::GetProperties(propertyTable); + + TestTrue( + "has invalid property", + properties.Contains(FString(propertyName.c_str()))); + const FCesiumPropertyTableProperty& property = + *properties.Find(FString(propertyName.c_str())); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidPropertyData); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + 0); + }); + }); + + Describe("GetPropertyNames", [this]() { + BeforeEach([this]() { pPropertyTable->classProperty = "testClass"; }); + + It("returns empty array for invalid property table", [this]() { + FCesiumPropertyTable propertyTable; + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::ErrorInvalidPropertyTable); + const auto properties = + UCesiumPropertyTableBlueprintLibrary::GetProperties(propertyTable); + TestTrue("properties are empty", properties.IsEmpty()); + }); + + It("gets all property names", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::vector scalarValues{1, 2, 3, 4}; + pPropertyTable->count = static_cast(scalarValues.size()); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::string vec2PropertyName("vec2Property"); + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(-0.7f, 4.9f), + glm::vec2(8.0f, 2.0f), + glm::vec2(11.0f, 0.0f), + }; + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + std::string invalidPropertyName("badProperty"); + std::vector invalidPropertyValues{0, 1, 2}; + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + invalidPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, // Incorrect + // component type + invalidPropertyValues); + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(scalarValues.size())); + + const auto propertyNames = + UCesiumPropertyTableBlueprintLibrary::GetPropertyNames(propertyTable); + TestEqual("number of names", propertyNames.Num(), 3); + TestTrue( + "has scalar property name", + propertyNames.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "has vec2 property name", + propertyNames.Contains(FString(vec2PropertyName.c_str()))); + TestTrue( + "has invalid property name", + propertyNames.Contains(FString(invalidPropertyName.c_str()))); + }); + }); + + Describe("FindProperty", [this]() { + BeforeEach([this]() { pPropertyTable->classProperty = "testClass"; }); + + It("returns invalid instance for nonexistent property", [this]() { + std::string propertyName("testProperty"); + std::vector values{1, 2, 3, 4}; + pPropertyTable->count = static_cast(values.size()); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + propertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + values); + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(values.size())); + + FCesiumPropertyTableProperty property = + UCesiumPropertyTableBlueprintLibrary::FindProperty( + propertyTable, + FString("nonexistent property")); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(0)); + }); + + It("finds existing properties", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::vector scalarValues{1, 2, 3, 4}; + pPropertyTable->count = static_cast(scalarValues.size()); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::string vec2PropertyName("vec2Property"); + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(-0.7f, 4.9f), + glm::vec2(8.0f, 2.0f), + glm::vec2(11.0f, 0.0f), + }; + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(scalarValues.size())); + + FCesiumPropertyTableProperty scalarProperty = + UCesiumPropertyTableBlueprintLibrary::FindProperty( + propertyTable, + FString(scalarPropertyName.c_str())); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(scalarProperty), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + scalarProperty), + static_cast(scalarValues.size())); + + FCesiumPropertyTableProperty vec2Property = + UCesiumPropertyTableBlueprintLibrary::FindProperty( + propertyTable, + FString(vec2PropertyName.c_str())); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(vec2Property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + vec2Property), + static_cast(vec2Values.size())); + }); + }); + + Describe("GetMetadataValuesForFeature", [this]() { + BeforeEach([this]() { pPropertyTable->classProperty = "testClass"; }); + + It("returns empty map for invalid property table", [this]() { + FCesiumPropertyTable propertyTable; + + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::ErrorInvalidPropertyTable); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(0)); + + const auto values = + UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeature( + propertyTable, + 0); + TestTrue("values map is empty", values.IsEmpty()); + }); + + It("returns empty map for out-of-bounds feature IDs", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::vector scalarValues{1, 2, 3, 4}; + pPropertyTable->count = static_cast(scalarValues.size()); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::string vec2PropertyName("vec2Property"); + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(-0.7f, 4.9f), + glm::vec2(8.0f, 2.0f), + glm::vec2(11.0f, 0.0f), + }; + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(scalarValues.size())); + + auto values = + UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeature( + propertyTable, + -1); + TestTrue("no values for for negative feature ID", values.IsEmpty()); + + values = + UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeature( + propertyTable, + 10); + TestTrue( + "no values for positive out-of-range feature ID", + values.IsEmpty()); + }); + + It("returns values of valid properties", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::vector scalarValues{1, 2, 3, 4}; + pPropertyTable->count = static_cast(scalarValues.size()); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::string vec2PropertyName("vec2Property"); + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(-0.7f, 4.9f), + glm::vec2(8.0f, 2.0f), + glm::vec2(11.0f, 0.0f), + }; + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(scalarValues.size())); + + for (size_t i = 0; i < scalarValues.size(); i++) { + const auto values = + UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeature( + propertyTable, + static_cast(i)); + TestEqual("number of values", values.Num(), 2); + + TestTrue( + "contains scalar value", + values.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "contains vec2 value", + values.Contains(FString(vec2PropertyName.c_str()))); + + const FCesiumMetadataValue& scalarValue = + *values.Find(FString(scalarPropertyName.c_str())); + TestEqual( + "scalar value", + UCesiumMetadataValueBlueprintLibrary::GetInteger(scalarValue, 0), + scalarValues[i]); + + const FCesiumMetadataValue& vec2Value = + *values.Find(FString(vec2PropertyName.c_str())); + FVector2D expected(vec2Values[i][0], vec2Values[i][1]); + TestEqual( + "vec2 value", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + vec2Value, + FVector2D::Zero()), + expected); + } + }); + + It("does not return value for invalid property", [this]() { + std::vector propertyValues{0, 1, 2}; + pPropertyTable->count = static_cast(propertyValues.size()); + std::string propertyName("badProperty"); + + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + propertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + propertyValues); + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(propertyValues.size())); + + const auto values = + UCesiumPropertyTableBlueprintLibrary::GetMetadataValuesForFeature( + propertyTable, + 0); + TestTrue("values map is empty", values.IsEmpty()); + }); + }); + + Describe("GetMetadataValuesForFeatureAsStrings", [this]() { + BeforeEach([this]() { pPropertyTable->classProperty = "testClass"; }); + + It("returns empty map for invalid property table", [this]() { + FCesiumPropertyTable propertyTable; + + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::ErrorInvalidPropertyTable); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(0)); + + const auto values = UCesiumPropertyTableBlueprintLibrary:: + GetMetadataValuesForFeatureAsStrings(propertyTable, 0); + TestTrue("values map is empty", values.IsEmpty()); + }); + + It("returns empty map for out-of-bounds feature IDs", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::vector scalarValues{1, 2, 3, 4}; + pPropertyTable->count = static_cast(scalarValues.size()); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::string vec2PropertyName("vec2Property"); + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(-0.7f, 4.9f), + glm::vec2(8.0f, 2.0f), + glm::vec2(11.0f, 0.0f), + }; + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(scalarValues.size())); + + auto values = UCesiumPropertyTableBlueprintLibrary:: + GetMetadataValuesForFeatureAsStrings(propertyTable, -1); + TestTrue("no values for for negative feature ID", values.IsEmpty()); + + values = UCesiumPropertyTableBlueprintLibrary:: + GetMetadataValuesForFeatureAsStrings(propertyTable, 10); + TestTrue( + "no values for positive out-of-range feature ID", + values.IsEmpty()); + }); + + It("returns values of valid properties", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::vector scalarValues{1, 2, 3, 4}; + pPropertyTable->count = static_cast(scalarValues.size()); + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + scalarPropertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + scalarValues); + + std::string vec2PropertyName("vec2Property"); + std::vector vec2Values{ + glm::vec2(1.0f, 2.5f), + glm::vec2(-0.7f, 4.9f), + glm::vec2(8.0f, 2.0f), + glm::vec2(11.0f, 0.0f), + }; + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + vec2PropertyName, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, + vec2Values); + + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(scalarValues.size())); + + for (size_t i = 0; i < scalarValues.size(); i++) { + const auto values = UCesiumPropertyTableBlueprintLibrary:: + GetMetadataValuesForFeatureAsStrings( + propertyTable, + static_cast(i)); + TestEqual("number of values", values.Num(), 2); + + TestTrue( + "contains scalar value", + values.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "contains vec2 value", + values.Contains(FString(vec2PropertyName.c_str()))); + + const FString& scalarValue = + *values.Find(FString(scalarPropertyName.c_str())); + FString expected(std::to_string(scalarValues[i]).c_str()); + TestEqual("scalar value as string", scalarValue, expected); + + const FString& vec2Value = + *values.Find(FString(vec2PropertyName.c_str())); + std::string expectedString( + "X=" + std::to_string(vec2Values[i][0]) + + " Y=" + std::to_string(vec2Values[i][1])); + expected = FString(expectedString.c_str()); + TestEqual("vec2 value as string", vec2Value, expected); + } + }); + + It("does not return value for invalid property", [this]() { + std::vector propertyValues{0, 1, 2}; + pPropertyTable->count = static_cast(propertyValues.size()); + std::string propertyName("badProperty"); + + AddPropertyTablePropertyToModel( + model, + *pPropertyTable, + propertyName, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, + propertyValues); + FCesiumPropertyTable propertyTable(model, *pPropertyTable); + + TestEqual( + "PropertyTableStatus", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableStatus( + propertyTable), + ECesiumPropertyTableStatus::Valid); + TestEqual( + "Count", + UCesiumPropertyTableBlueprintLibrary::GetPropertyTableCount( + propertyTable), + static_cast(propertyValues.size())); + + const auto values = UCesiumPropertyTableBlueprintLibrary:: + GetMetadataValuesForFeatureAsStrings(propertyTable, 0); + TestTrue("values map is empty", values.IsEmpty()); + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp new file mode 100644 index 0000000..e158006 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp @@ -0,0 +1,4285 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyTableProperty.h" +#include "CesiumGltfSpecUtility.h" +#include "CesiumPropertyArrayBlueprintLibrary.h" +#include "Misc/AutomationTest.h" +#include + +BEGIN_DEFINE_SPEC( + FCesiumPropertyTablePropertySpec, + "Cesium.Unit.PropertyTableProperty", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +END_DEFINE_SPEC(FCesiumPropertyTablePropertySpec) + +void FCesiumPropertyTablePropertySpec::Define() { + using namespace CesiumGltf; + + Describe("Constructor", [this]() { + It("constructs invalid instance by default", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + 0); + + FCesiumMetadataValueType expectedType; // Invalid type + TestTrue( + "ValueType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + }); + + It("constructs invalid instance from view with invalid definition", + [this]() { + CesiumGltf::PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyViewStatus:: + ErrorArrayTypeMismatch); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + 0); + + FCesiumMetadataValueType expectedType; // Invalid type + TestTrue( + "ValueType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + }); + + It("constructs invalid instance from view with invalid data", [this]() { + CesiumGltf::PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyViewStatus:: + ErrorBufferViewOutOfBounds); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidPropertyData); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + 0); + + FCesiumMetadataValueType expectedType; // Invalid type + TestTrue( + "ValueType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + }); + + It("constructs valid instance", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + std::vector values{1, 2, 3, 4}; + std::vector data = GetValuesAsBytes(values); + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + false); + TestTrue( + "ValueType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Integer); + + TestFalse( + "IsNormalized", + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); + + // Test that the returns are as expected for non-array properties. + TestEqual( + "ArraySize", + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), + static_cast(0)); + TestEqual( + "ArrayElementBlueprintType", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetArrayElementBlueprintType(property), + ECesiumMetadataBlueprintType::None); + + // Check that undefined properties return empty values + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetOffset(property); + TestTrue("Offset", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetScale(property); + TestTrue("Scale", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetMaximumValue( + property); + TestTrue("Max", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetMinimumValue( + property); + TestTrue("Min", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetNoDataValue( + property); + TestTrue("NoData", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetDefaultValue( + property); + TestTrue("Default", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + }); + + It("constructs valid normalized instance", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + std::vector values{0, 1, 255, 128}; + std::vector data = GetValuesAsBytes(values); + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Uint8, + false); + TestTrue( + "ValueType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Byte); + + TestTrue( + "IsNormalized", + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); + + // Test that the returns are as expected for non-array properties. + TestEqual( + "ArraySize", + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), + static_cast(0)); + TestEqual( + "ArrayElementBlueprintType", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetArrayElementBlueprintType(property), + ECesiumMetadataBlueprintType::None); + }); + + It("constructs instance for fixed-length array property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + classProperty.array = true; + classProperty.count = 3; + + std::vector values{1, 2, 3, 4, 5, 6}; + const int64_t size = + static_cast(values.size()) / *classProperty.count; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + std::span(data.data(), data.size()), + std::span(), + std::span(), + PropertyComponentType::None, + PropertyComponentType::None); + + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(size)); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + true); + TestTrue( + "ValueType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Array); + + TestFalse( + "IsNormalized", + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); + + TestEqual( + "ArraySize", + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), + *classProperty.count); + TestEqual( + "ArrayElementBlueprintType", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetArrayElementBlueprintType(property), + ECesiumMetadataBlueprintType::Integer); + }); + + It("constructs instance for variable-length array property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + classProperty.array = true; + + std::vector values{1, 2, 3, 4, 5, 6}; + std::vector data = GetValuesAsBytes(values); + + std::vector offsets{0, 1, 3, 6}; + std::vector offsetsData = GetValuesAsBytes(offsets); + + int64_t size = static_cast(offsets.size()) - 1; + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + std::span(data.data(), data.size()), + std::span( + offsetsData.data(), + offsetsData.size()), + std::span(), + PropertyComponentType::Uint16, + PropertyComponentType::None); + + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + size); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + true); + TestTrue( + "ValueType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Array); + + TestFalse( + "IsNormalized", + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); + + // The arrays vary in length, so GetArraySize() should return zero. + TestEqual( + "ArraySize", + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), + static_cast(0)); + TestEqual( + "ArrayElementBlueprintType", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetArrayElementBlueprintType(property), + ECesiumMetadataBlueprintType::Integer); + }); + + It("constructs valid instance with additional properties", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + classProperty.normalized = true; + + double offset = 1.0; + double scale = 2.0; + double min = 1.0; + double max = 3.0; + int32_t noData = 1; + double defaultValue = 12.3; + + classProperty.offset = offset; + classProperty.scale = scale; + classProperty.min = min; + classProperty.max = max; + classProperty.noData = noData; + classProperty.defaultProperty = defaultValue; + + std::vector values{1, 2, 3, 4}; + std::vector data = GetValuesAsBytes(values); + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + false); + TestTrue( + "ValueType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Integer); + + TestTrue( + "IsNormalized", + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); + + // Test that the returns are as expected for non-array properties. + TestEqual( + "ArraySize", + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), + static_cast(0)); + TestEqual( + "ArrayElementBlueprintType", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetArrayElementBlueprintType(property), + ECesiumMetadataBlueprintType::None); + + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetOffset(property); + TestEqual( + "Offset", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + offset); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetScale(property); + TestEqual( + "Scale", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + scale); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetMaximumValue( + property); + TestEqual( + "Max", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + max); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetMinimumValue( + property); + TestEqual( + "Min", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + min); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetNoDataValue( + property); + TestEqual( + "NoData", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0.0), + noData); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetDefaultValue( + property); + TestEqual( + "Default", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + defaultValue); + }); + + It("constructs valid array instance with additional properties", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + classProperty.normalized = true; + classProperty.array = true; + classProperty.count = 2; + + std::vector offset = {1.0, 2.0}; + std::vector scale = {2.0, -1.0}; + std::vector min = {1.0, 1.0}; + std::vector max = {3.0, 2.0}; + std::vector noData = {-1, -1}; + std::vector defaultValue = {12.3, 4.5}; + + classProperty.offset = {offset[0], offset[1]}; + classProperty.scale = {scale[0], scale[1]}; + classProperty.min = {min[0], min[1]}; + classProperty.max = {max[0], max[1]}; + classProperty.noData = {noData[0], noData[1]}; + classProperty.defaultProperty = {defaultValue[0], defaultValue[1]}; + + std::vector values{1, 2, 3, 4, 5, 6, -1, -1}; + std::vector data = GetValuesAsBytes(values); + CesiumGltf::PropertyTablePropertyView, true> + propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + true); + TestTrue( + "ValueType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyTablePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Array); + + TestTrue( + "IsNormalized", + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); + + TestEqual( + "ArraySize", + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), + static_cast(*classProperty.count)); + TestEqual( + "ArrayElementBlueprintType", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetArrayElementBlueprintType(property), + ECesiumMetadataBlueprintType::Integer); + + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetOffset(property); + FCesiumPropertyArray array = + UCesiumMetadataValueBlueprintLibrary::GetArray(value); + + TestEqual( + TEXT("Size"), + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(*classProperty.count)); + TestEqual( + "Offset0", + UCesiumMetadataValueBlueprintLibrary::GetFloat64( + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 0), + 0.0), + offset[0]); + TestEqual( + "Offset1", + UCesiumMetadataValueBlueprintLibrary::GetFloat64( + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 1), + 0.0), + offset[1]); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetScale(property); + array = UCesiumMetadataValueBlueprintLibrary::GetArray(value); + + TestEqual( + TEXT("Size"), + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(*classProperty.count)); + TestEqual( + "Scale0", + UCesiumMetadataValueBlueprintLibrary::GetFloat64( + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 0), + 0.0), + scale[0]); + TestEqual( + "Scale1", + UCesiumMetadataValueBlueprintLibrary::GetFloat64( + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 1), + 0.0), + scale[1]); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetMaximumValue( + property); + array = UCesiumMetadataValueBlueprintLibrary::GetArray(value); + + TestEqual( + TEXT("Size"), + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(*classProperty.count)); + TestEqual( + "Max0", + UCesiumMetadataValueBlueprintLibrary::GetFloat64( + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 0), + 0.0), + max[0]); + TestEqual( + "Max1", + UCesiumMetadataValueBlueprintLibrary::GetFloat64( + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 1), + 0.0), + max[1]); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetMinimumValue( + property); + array = UCesiumMetadataValueBlueprintLibrary::GetArray(value); + + TestEqual( + TEXT("Size"), + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(*classProperty.count)); + TestEqual( + "Min0", + UCesiumMetadataValueBlueprintLibrary::GetFloat64( + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 0), + 0.0), + min[0]); + TestEqual( + "Min1", + UCesiumMetadataValueBlueprintLibrary::GetFloat64( + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 1), + 0.0), + min[1]); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetNoDataValue( + property); + array = UCesiumMetadataValueBlueprintLibrary::GetArray(value); + + TestEqual( + TEXT("Size"), + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(*classProperty.count)); + TestEqual( + "NoData0", + UCesiumMetadataValueBlueprintLibrary::GetInteger( + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 0), + 0), + noData[0]); + TestEqual( + "NoData1", + UCesiumMetadataValueBlueprintLibrary::GetInteger( + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 1), + 0), + noData[1]); + + value = UCesiumPropertyTablePropertyBlueprintLibrary::GetDefaultValue( + property); + array = UCesiumMetadataValueBlueprintLibrary::GetArray(value); + + TestEqual( + TEXT("Size"), + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(*classProperty.count)); + TestEqual( + "DefaultValue0", + UCesiumMetadataValueBlueprintLibrary::GetFloat64( + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 0), + 0.0), + defaultValue[0]); + TestEqual( + "DefaultValue1", + UCesiumMetadataValueBlueprintLibrary::GetFloat64( + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 1), + 0.0), + defaultValue[1]); + }); + }); + + Describe("GetBoolean", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestFalse( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetBoolean( + property, + 0)); + }); + + It("returns default value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::BOOLEAN; + + std::vector data{static_cast(0b10110001)}; + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(8), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(8)); + + TestFalse( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetBoolean( + property, + -1)); + TestFalse( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetBoolean( + property, + 10)); + }); + + It("gets from boolean property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::BOOLEAN; + + std::vector data{static_cast(0b10110001)}; + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(8), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + + std::vector + expected{true, false, false, false, true, true, false, true}; + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(expected.size())); + + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetBoolean( + property, + static_cast(i), + false), + expected[i]); + } + }); + + It("converts compatible values", [this]() { + std::vector + values{"yes", "false", "invalid value", "true", "yeah", "1"}; + size_t totalSize = 0; + for (const auto& value : values) { + totalSize += value.size(); + } + + std::vector data(totalSize); + std::vector offsets(values.size() + 1); + uint32_t currentOffset = 0; + for (size_t i = 0; i < values.size(); ++i) { + std::memcpy( + data.data() + currentOffset, + values[i].data(), + values[i].size()); + offsets[i] = currentOffset; + currentOffset += static_cast(values[i].size()); + } + offsets[offsets.size() - 1] = currentOffset; + std::vector offsetsData = GetValuesAsBytes(offsets); + + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::STRING; + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size()), + std::span(), + std::span(offsetsData.data(), offsetsData.size()), + PropertyComponentType::None, + PropertyComponentType::Uint32); + + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected{true, false, false, true, false, true}; + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetBoolean( + property, + static_cast(i), + false), + expected[i]); + } + }); + }); + + Describe("GetByte", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetByte(property, 0), + 0); + }); + + It("returns default value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + + std::vector values{1, 2, 3, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetByte(property, -1), + 0); + TestEqual( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetByte(property, 10), + 0); + }); + + It("gets from uint8 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + + std::vector values{1, 2, 3, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetByte( + property, + static_cast(i), + 0), + values[i]); + } + }); + + It("converts compatible values", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + std::vector values{1, 24, 255, 256, -1, 28}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected{1, 24, 255, 0, 0, 28}; + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetByte( + property, + static_cast(i), + 0), + expected[i]); + } + }); + + It("gets with noData / default value", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + + uint8_t noDataValue = 0; + uint8_t defaultValue = 255; + + classProperty.noData = noDataValue; + classProperty.defaultProperty = defaultValue; + + std::vector values{1, 2, 3, 0, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + if (values[i] == noDataValue) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetByte( + property, + static_cast(i), + 0), + defaultValue); + } else { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetByte( + property, + static_cast(i), + 0), + values[i]); + } + } + }); + }); + + Describe("GetInteger", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger(property, 0), + 0); + }); + + It("returns default value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger( + property, + -1), + 0); + TestEqual( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger( + property, + 10), + 0); + }); + + It("gets from int32 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger( + property, + static_cast(i), + 0), + values[i]); + } + }); + + It("converts compatible values", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + 1.234f, + -24.5f, + std::numeric_limits::lowest(), + 2456.80f, + std::numeric_limits::max(), + }; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected{1, -24, 0, 2456, 0}; + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger( + property, + static_cast(i), + 0), + expected[i]); + } + }); + + It("gets with noData / default value", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + int32_t noDataValue = 0; + int32_t defaultValue = 10; + + classProperty.noData = noDataValue; + classProperty.defaultProperty = defaultValue; + + std::vector values{-1, 2, -3, 0, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + if (values[i] == noDataValue) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger( + property, + static_cast(i), + 0), + defaultValue); + } else { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger( + property, + static_cast(i), + 0), + values[i]); + } + } + }); + }); + + Describe("GetInteger64", [this]() { + int64_t defaultInt64 = static_cast(0); + + It("returns default value for invalid property", [this, defaultInt64]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( + property, + 0), + defaultInt64); + }); + + It("returns default value for invalid feature ID", [this, defaultInt64]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT64; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( + property, + -1), + defaultInt64); + TestEqual( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( + property, + 10), + defaultInt64); + }); + + It("gets from int64 property", [this, defaultInt64]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT64; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( + property, + static_cast(i), + defaultInt64), + values[i]); + } + }); + + It("converts compatible values", [this, defaultInt64]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT64; + + std::vector values{ + 10, + 20, + 30, + static_cast(std::numeric_limits::max()) + 100}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected{10, 20, 30, 0}; + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( + property, + static_cast(i), + defaultInt64), + expected[i]); + } + }); + + It("gets with noData / default value", [this, defaultInt64]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT64; + + int64_t noDataValue = 0; + int64_t defaultValue = 10; + + classProperty.noData = noDataValue; + classProperty.defaultProperty = defaultValue; + + std::vector values{-1, 2, 0, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + if (values[i] == noDataValue) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( + property, + static_cast(i), + defaultInt64), + defaultValue); + } else { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( + property, + static_cast(i), + defaultInt64), + values[i]); + } + } + }); + }); + + Describe("GetFloat", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat( + property, + 0.0f), + 0.0f); + }); + + It("returns default value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{-1.1f, 2.2f, -3.3f, 4.0f}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat(property, -1), + 0.0f); + TestEqual( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat(property, 10), + 0.0f); + }); + + It("gets from float property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{-1.1f, 2.2f, -3.3f, 4.0f}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat( + property, + static_cast(i), + 0), + values[i]); + } + }); + + It("converts compatible values", [this]() { + std::vector values{ + -1.1, + 2.2, + -3.3, + std::numeric_limits::max()}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected(4); + for (size_t i = 0; i < values.size(); i++) { + expected[i] = static_cast(values[i]); + } + expected[3] = 0.0f; + + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat( + property, + static_cast(i), + 0.0f), + expected[i]); + } + }); + + It("gets with offset / scale", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + float offset = 5.0f; + float scale = 2.0f; + + classProperty.offset = offset; + classProperty.scale = scale; + + std::vector values{-1.1f, 2.2f, -3.3f, 4.0f}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat( + property, + static_cast(i), + 0), + values[i] * scale + offset); + } + }); + }); + + Describe("GetFloat64", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat64( + property, + 0.0), + 0.0); + }); + + It("returns default value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + std::vector values{-1.1, 2.2, -3.3, 4.0}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat64( + property, + -1), + 0.0); + TestEqual( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat64( + property, + 10), + 0.0); + }); + + It("gets from double property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + std::vector values{-1.1, 2.2, -3.3, 4.0}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat64( + property, + static_cast(i), + 0), + values[i]); + } + }); + + It("gets from normalized uint8 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + std::vector values{0, 128, 255, 0}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestTrue( + "IsNormalized", + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat64( + property, + static_cast(i), + 0), + static_cast(values[i]) / 255.0); + } + }); + + It("converts compatible values", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::STRING; + + std::vector values{"not a number", "10", "-2"}; + size_t totalSize = 0; + for (const auto& value : values) { + totalSize += value.size(); + } + + std::vector data(totalSize); + std::vector offsets(values.size() + 1); + uint8_t currentOffset = 0; + for (size_t i = 0; i < values.size(); ++i) { + std::memcpy( + data.data() + currentOffset, + values[i].data(), + values[i].size()); + offsets[i] = currentOffset; + currentOffset += static_cast(values[i].size()); + } + offsets[offsets.size() - 1] = currentOffset; + std::vector offsetsData = GetValuesAsBytes(offsets); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size()), + std::span(), + std::span(offsetsData.data(), offsetsData.size()), + PropertyComponentType::None, + PropertyComponentType::Uint8); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected{ + 0.0, + static_cast(10), + static_cast(-2)}; + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat64( + property, + static_cast(i), + 0.0), + expected[i]); + } + }); + + It("gets with offset / scale", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + float offset = 5.0; + float scale = 2.0; + + classProperty.offset = offset; + classProperty.scale = scale; + + std::vector values{-1.1, 2.2, -3.3, 4.0}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat64( + property, + static_cast(i), + 0), + values[i] * scale + offset); + } + }); + }); + + Describe("GetIntPoint", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetIntPoint( + property, + 0, + FIntPoint(0)), + FIntPoint(0)); + }); + + It("returns default value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + std::vector values{ + glm::ivec2(1, 1), + glm::ivec2(-1, -1), + glm::ivec2(10, 4)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetIntPoint( + property, + -1, + FIntPoint(0)), + FIntPoint(0)); + TestEqual( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetIntPoint( + property, + 10, + FIntPoint(0)), + FIntPoint(0)); + }); + + It("gets from glm::ivec2 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + std::vector values{ + glm::ivec2(1, 1), + glm::ivec2(-1, -1), + glm::ivec2(10, 4)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FIntPoint expected(values[i][0], values[i][1]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetIntPoint( + property, + static_cast(i), + FIntPoint(0)), + expected); + } + }); + + It("converts compatible values", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec3(1.0f, 2.0f, 3.0f), + glm::vec3(20.5f, -1.5f, std::numeric_limits::lowest()), + glm::vec3(std::numeric_limits::max(), -1.0f, 2.0f)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected{ + FIntPoint(1, 2), + FIntPoint(20, -1), + FIntPoint(0)}; + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetIntPoint( + property, + static_cast(i), + FIntPoint(0)), + expected[i]); + } + }); + + It("gets with noData / default value", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + glm::ivec2 noData(-1, -1); + FIntPoint defaultValue(5, 22); + + classProperty.noData = {noData[0], noData[1]}; + classProperty.defaultProperty = {defaultValue[0], defaultValue[1]}; + + std::vector values{ + glm::ivec2(1, 1), + glm::ivec2(-1, -1), + glm::ivec2(10, 4)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FIntPoint expected; + if (values[i] == noData) { + expected = defaultValue; + } else { + expected = FIntPoint(values[i][0], values[i][1]); + } + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetIntPoint( + property, + static_cast(i), + FIntPoint(0)), + expected); + } + }); + }); + + Describe("GetVector2D", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( + property, + 0, + FVector2D::Zero()), + FVector2D::Zero()); + }); + + It("returns default value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + std::vector values{ + glm::dvec2(-1.0, 2.0), + glm::dvec2(3.4, 5.6), + glm::dvec2(1.5, -1.5)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( + property, + -1, + FVector2D::Zero()), + FVector2D::Zero()); + TestEqual( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( + property, + 10, + FVector2D::Zero()), + FVector2D::Zero()); + }); + + It("gets from glm::dvec2 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + std::vector values{ + glm::dvec2(-1.0, 2.0), + glm::dvec2(3.4, 5.6), + glm::dvec2(1.5, -1.5)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FVector2D expected(values[i][0], values[i][1]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( + property, + static_cast(i), + FVector2D::Zero()), + expected); + } + }); + + It("gets from normalized glm::u8vec2 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + std::vector values{ + glm::u8vec2(1, 1), + glm::u8vec2(0, 255), + glm::u8vec2(10, 4)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestTrue( + "IsNormalized", + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); + + for (size_t i = 0; i < values.size(); i++) { + glm::dvec2 expected = glm::dvec2(values[i][0], values[i][1]) / 255.0; + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( + property, + static_cast(i), + FVector2D::Zero()), + FVector2D(expected[0], expected[1])); + } + }); + + It("converts compatible values", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::STRING; + + std::vector values{"X=10 Y=3", "not a vector", "X=-2 Y=4"}; + size_t totalSize = 0; + for (const auto& value : values) { + totalSize += value.size(); + } + + std::vector data(totalSize); + std::vector offsets(values.size() + 1); + uint8_t currentOffset = 0; + for (size_t i = 0; i < values.size(); ++i) { + std::memcpy( + data.data() + currentOffset, + values[i].data(), + values[i].size()); + offsets[i] = currentOffset; + currentOffset += static_cast(values[i].size()); + } + offsets[offsets.size() - 1] = currentOffset; + std::vector offsetsData = GetValuesAsBytes(offsets); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size()), + std::span(), + std::span(offsetsData.data(), offsetsData.size()), + PropertyComponentType::None, + PropertyComponentType::Uint8); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected{ + FVector2D(10, 3), + FVector2D::Zero(), + FVector2D(-2, 4)}; + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( + property, + static_cast(i), + FVector2D::Zero()), + expected[i]); + } + }); + + It("gets with offset / scale", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + FVector2D offset(3.0, 2.4); + FVector2D scale(2.0, -1.0); + + classProperty.offset = {offset[0], offset[1]}; + classProperty.scale = {scale[0], scale[1]}; + + std::vector values{ + glm::dvec2(-1.0, 2.0), + glm::dvec2(3.4, 5.6), + glm::dvec2(1.5, -1.5)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FVector2D expected( + values[i][0] * scale[0] + offset[0], + values[i][1] * scale[1] + offset[1]); + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( + property, + static_cast(i), + FVector2D::Zero()), + expected); + } + }); + }); + + Describe("GetIntVector", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetIntVector( + property, + 0, + FIntVector(0)), + FIntVector(0)); + }); + + It("returns default value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + std::vector values{ + glm::ivec3(1, 1, -1), + glm::ivec3(-1, -1, 2), + glm::ivec3(10, 4, 5)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetIntVector( + property, + -1, + FIntVector(0)), + FIntVector(0)); + TestEqual( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetIntVector( + property, + 10, + FIntVector(0)), + FIntVector(0)); + }); + + It("gets from glm::ivec3 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + std::vector values{ + glm::ivec3(1, 1, -1), + glm::ivec3(-1, -1, 2), + glm::ivec3(10, 4, 5)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FIntVector expected(values[i][0], values[i][1], values[i][2]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetIntVector( + property, + static_cast(i), + FIntVector(0)), + expected); + } + }); + + It("converts compatible values", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec3(1.0f, 2.0f, 3.0f), + glm::vec3(-5.9f, 8.2f, 1.15f), + glm::vec3(20.5f, -1.5f, std::numeric_limits::lowest()), + glm::vec3(std::numeric_limits::max(), -1.0f, 2.0f)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected{ + FIntVector(1, 2, 3), + FIntVector(-5, 8, 1), + FIntVector(0), + FIntVector(0)}; + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetIntVector( + property, + static_cast(i), + FIntVector(0)), + expected[i]); + } + }); + + It("gets with noData / default value", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + glm::ivec3 noData(-1, -1, -1); + FIntVector defaultValue(1, 2, 3); + + classProperty.noData = {noData[0], noData[1], noData[2]}; + classProperty.defaultProperty = { + defaultValue[0], + defaultValue[1], + defaultValue[2]}; + + std::vector values{ + glm::ivec3(1, 1, -1), + glm::ivec3(-1, -1, -1), + glm::ivec3(-1, -1, 2), + glm::ivec3(10, 4, 5)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FIntVector expected; + if (values[i] == noData) { + expected = defaultValue; + } else { + expected = FIntVector(values[i][0], values[i][1], values[i][2]); + } + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetIntVector( + property, + static_cast(i), + FIntVector(0)), + expected); + } + }); + }); + + Describe("GetVector3f", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector3f( + property, + 0, + FVector3f::Zero()), + FVector3f::Zero()); + }); + + It("returns default value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec3(1.0f, 1.9f, -1.0f), + glm::vec3(-1.0f, -1.8f, 2.5f), + glm::vec3(10.0f, 4.4f, 5.4f)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector3f( + property, + -1, + FVector3f::Zero()), + FVector3f::Zero()); + TestEqual( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector3f( + property, + 10, + FVector3f::Zero()), + FVector3f::Zero()); + }); + + It("gets from glm::vec3 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec3(1.0f, 1.9f, -1.0f), + glm::vec3(-1.0f, -1.8f, 2.5f), + glm::vec3(10.0f, 4.4f, 5.4f)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FVector3f expected(values[i][0], values[i][1], values[i][2]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector3f( + property, + static_cast(i), + FVector3f(0)), + expected); + } + }); + + It("converts compatible values", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + std::vector values{ + glm::dvec2(1.0, 2.0), + glm::dvec2(-5.9, 8.2), + glm::dvec2(20.5, std::numeric_limits::lowest()), + glm::dvec2(std::numeric_limits::max(), -1.0)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected(4); + for (size_t i = 0; i < 2; i++) { + expected[i] = FVector3f( + static_cast(values[i][0]), + static_cast(values[i][1]), + 0.0f); + } + expected[2] = expected[3] = FVector3f::Zero(); + + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector3f( + property, + static_cast(i), + FVector3f::Zero()), + expected[i]); + } + }); + + It("gets with offset / scale", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + FVector3f offset(1.0f, 4.5f, -2.0f); + FVector3f scale(0.5f, -1.0f, 2.2f); + + classProperty.offset = {offset[0], offset[1], offset[2]}; + classProperty.scale = {scale[0], scale[1], scale[2]}; + + std::vector values{ + glm::vec3(1.0f, 1.9f, -1.0f), + glm::vec3(-1.0f, -1.8f, 2.5f), + glm::vec3(10.0f, 4.4f, 5.4f)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FVector3f expected( + values[i][0] * scale[0] + offset[0], + values[i][1] * scale[1] + offset[1], + values[i][2] * scale[2] + offset[2]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector3f( + property, + static_cast(i), + FVector3f(0)), + expected); + } + }); + }); + + Describe("GetVector", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( + property, + 0, + FVector::Zero()), + FVector::Zero()); + }); + + It("returns default value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + std::vector values{ + glm::dvec3(-1.0, 2.0, 5.0), + glm::dvec3(3.4, 5.6, 7.8), + glm::dvec3(1.5, -1.5, -2.01)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( + property, + -1, + FVector::Zero()), + FVector::Zero()); + TestEqual( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( + property, + 10, + FVector::Zero()), + FVector::Zero()); + }); + + It("gets from glm::dvec3 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + std::vector values{ + glm::dvec3(-1.0, 2.0, 5.0), + glm::dvec3(3.4, 5.6, 7.8), + glm::dvec3(1.5, -1.5, -2.01)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FVector expected(values[i][0], values[i][1], values[i][2]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( + property, + static_cast(i), + FVector::Zero()), + expected); + } + }); + + It("gets from normalized glm::i8vec3 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::INT8; + classProperty.normalized = true; + + std::vector values{ + glm::i8vec3(-1, 2, 5), + glm::i8vec3(3, 5, 7), + glm::i8vec3(1, -1, -2)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestTrue( + "IsNormalized", + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); + + for (size_t i = 0; i < values.size(); i++) { + glm::dvec3 expected = + glm::dvec3(values[i][0], values[i][1], values[i][2]) / 127.0; + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( + property, + static_cast(i), + FVector::Zero()), + FVector(expected[0], expected[1], expected[2])); + } + }); + + It("converts compatible values", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::STRING; + + std::vector values{ + "X=10 Y=3 Z=4", + "not a vector", + "X=-2 Y=4 Z=5"}; + size_t totalSize = 0; + for (const auto& value : values) { + totalSize += value.size(); + } + + std::vector data(totalSize); + std::vector offsets(values.size() + 1); + uint8_t currentOffset = 0; + for (size_t i = 0; i < values.size(); ++i) { + std::memcpy( + data.data() + currentOffset, + values[i].data(), + values[i].size()); + offsets[i] = currentOffset; + currentOffset += static_cast(values[i].size()); + } + offsets[offsets.size() - 1] = currentOffset; + std::vector offsetsData = GetValuesAsBytes(offsets); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size()), + std::span(), + std::span(offsetsData.data(), offsetsData.size()), + PropertyComponentType::None, + PropertyComponentType::Uint8); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected{ + FVector(10, 3, 4), + FVector::Zero(), + FVector(-2, 4, 5)}; + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( + property, + static_cast(i), + FVector::Zero()), + expected[i]); + } + }); + + It("gets with offset / scale", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + FVector offset(1.0, 2.0, 3.0); + FVector scale(0.5, -1.0, 2.0); + + classProperty.offset = {offset[0], offset[1], offset[2]}; + classProperty.scale = {scale[0], scale[1], scale[2]}; + + std::vector values{ + glm::dvec3(-1.0, 2.0, 5.0), + glm::dvec3(3.4, 5.6, 7.8), + glm::dvec3(1.5, -1.5, -2.01)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FVector expected( + values[i][0] * scale[0] + offset[0], + values[i][1] * scale[1] + offset[1], + values[i][2] * scale[2] + offset[2]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( + property, + static_cast(i), + FVector::Zero()), + expected); + } + }); + }); + + Describe("GetVector4", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector4( + property, + 0, + FVector4::Zero()), + FVector4::Zero()); + }); + + It("returns default value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC4; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + std::vector values{ + glm::dvec4(-1.0, 2.0, 5.0, 8.8), + glm::dvec4(3.4, 5.6, 7.8, 0.2), + glm::dvec4(1.5, -1.5, -2.01, 5.5)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector4( + property, + -1, + FVector4::Zero()), + FVector4::Zero()); + TestEqual( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector4( + property, + 10, + FVector4::Zero()), + FVector4::Zero()); + }); + + It("gets from glm::dvec4 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC4; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + std::vector values{ + glm::dvec4(-1.0, 2.0, 5.0, 8.8), + glm::dvec4(3.4, 5.6, 7.8, 0.2), + glm::dvec4(1.5, -1.5, -2.01, 5.5)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FVector4 expected( + values[i][0], + values[i][1], + values[i][2], + values[i][3]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( + property, + static_cast(i), + FVector4::Zero()), + expected); + } + }); + + It("gets from glm::i8vec4 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC4; + classProperty.componentType = ClassProperty::ComponentType::INT8; + classProperty.normalized = true; + + std::vector values{ + glm::i8vec4(-1, 2, 5, 8), + glm::i8vec4(3, 5, 7, 0), + glm::i8vec4(1, -1, -2, 5)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestTrue( + "IsNormalized", + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); + + for (size_t i = 0; i < values.size(); i++) { + glm::dvec4 expected( + values[i][0], + values[i][1], + values[i][2], + values[i][3]); + expected /= 127.0; + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( + property, + static_cast(i), + FVector4::Zero()), + FVector4(expected[0], expected[1], expected[2], expected[3])); + } + }); + + It("converts compatible values", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::STRING; + + std::vector values{ + "X=10 Y=3 Z=4 W=2", + "not a vector", + "X=-2 Y=4 Z=5"}; + size_t totalSize = 0; + for (const auto& value : values) { + totalSize += value.size(); + } + + std::vector data(totalSize); + std::vector offsets(values.size() + 1); + uint8_t currentOffset = 0; + for (size_t i = 0; i < values.size(); ++i) { + std::memcpy( + data.data() + currentOffset, + values[i].data(), + values[i].size()); + offsets[i] = currentOffset; + currentOffset += static_cast(values[i].size()); + } + offsets[offsets.size() - 1] = currentOffset; + std::vector offsetsData = GetValuesAsBytes(offsets); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size()), + std::span(), + std::span(offsetsData.data(), offsetsData.size()), + PropertyComponentType::None, + PropertyComponentType::Uint8); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected{ + FVector4(10, 3, 4, 2), + FVector::Zero(), + FVector4(-2, 4, 5, 1)}; + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector4( + property, + static_cast(i), + FVector4::Zero()), + expected[i]); + } + }); + + It("gets with offset / scale", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC4; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + FVector4 offset(1.0, 2.0, 4.5, -3.0); + FVector4 scale(0.5, -1.0, 2.0, -2.5); + + classProperty.offset = {offset[0], offset[1], offset[2], offset[3]}; + classProperty.scale = {scale[0], scale[1], scale[2], scale[3]}; + + std::vector values{ + glm::dvec4(-1.0, 2.0, 5.0, 8.8), + glm::dvec4(3.4, 5.6, 7.8, 0.2), + glm::dvec4(1.5, -1.5, -2.01, 5.5)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + FVector4 expected( + values[i][0] * scale[0] + offset[0], + values[i][1] * scale[1] + offset[1], + values[i][2] * scale[2] + offset[2], + values[i][3] * scale[3] + offset[3]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( + property, + static_cast(i), + FVector4::Zero()), + expected); + } + }); + }); + + Describe("GetMatrix", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( + property, + 0, + FMatrix::Identity), + FMatrix::Identity); + }); + + It("returns default value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::MAT4; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + // clang-format off + std::vector values{ + glm::dmat4( + 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0), + glm::dmat4( + 1.0, 0.0, 0.0, 0.0, + 0.0, -2.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + -1.5, 4.0, 2.0, 1.0), + }; + // clang-format on + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( + property, + -1, + FMatrix::Identity), + + FMatrix::Identity); + TestEqual( + "out-of-range positive index", + UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( + property, + 10, + FMatrix::Identity), + FMatrix::Identity); + }); + + It("gets from glm::dmat4 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::MAT4; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + // clang-format off + std::vector values{ + glm::dmat4( + 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0), + glm::dmat4( + 1.0, 0.0, 0.0, 0.0, + 0.0, -2.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + -1.5, 4.0, 2.0, 1.0), + }; + // clang-format on + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected(2); + expected[0] = FMatrix( + FPlane4d(1.0, 5.0, 9.0, 13.0), + FPlane4d(2.0, 6.0, 10.0, 14.0), + FPlane4d(3.0, 7.0, 11.0, 15.0), + FPlane4d(4.0, 8.0, 12.0, 16.0)); + expected[1] = FMatrix( + FPlane4d(1.0, 0.0, 0.0, -1.5), + FPlane4d(0.0, -2.5, 0.0, 4.0), + FPlane4d(0.0, 0.0, 0.5, 2.0), + FPlane4d(0.0, 0.0, 0.0, 1.0)); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( + property, + static_cast(i), + FMatrix::Identity), + expected[i]); + } + }); + + It("gets from glm::u8mat4x4 property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::MAT4; + classProperty.componentType = ClassProperty::ComponentType::INT8; + classProperty.normalized = true; + + // clang-format off + std::vector values{ + glm::i8mat4x4( + 127, 0, 0, 0, + 0, 127, 0, 0, + 0, 0, 127, 0, + 0, 0, -127, 127), + glm::i8mat4x4( + 0, -127, 0, 0, + 127, 0, 0, 0, + 0, 0, 127, 0, + 0, 0, 127, 127), + }; + // clang-format on + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestTrue( + "IsNormalized", + UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); + + std::vector expected(2); + expected[0] = FMatrix( + FPlane4d(1.0, 0.0, 0.0, 0.0), + FPlane4d(0.0, 1.0, 0.0, 0.0), + FPlane4d(0.0, 0.0, 1.0, -1.0), + FPlane4d(0.0, 0.0, 0.0, 1.0)); + expected[1] = FMatrix( + FPlane4d(0.0, 1.0, 0.0, 0.0), + FPlane4d(-1.0, 0.0, 0.0, 0.0), + FPlane4d(0.0, 0.0, 1.0, 1.0), + FPlane4d(0.0, 0.0, 0.0, 1.0)); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( + property, + static_cast(i), + FMatrix::Identity), + expected[i]); + } + }); + + It("converts compatible values", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + std::vector values{-2.0, 10.5}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected(2); + expected[0] = FMatrix( + FPlane4d(-2.0, 0.0, 0.0, 0.0), + FPlane4d(0.0, -2.0, 0.0, 0.0), + FPlane4d(0.0, 0.0, -2.0, 0.0), + FPlane4d(0.0, 0.0, 0.0, -2.0)); + expected[1] = FMatrix( + FPlane4d(10.5, 0.0, 0.0, 0.0), + FPlane4d(0.0, 10.5, 0.0, 0.0), + FPlane4d(0.0, 0.0, 10.5, 0.0), + FPlane4d(0.0, 0.0, 0.0, 10.5)); + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( + property, + static_cast(i), + FMatrix::Identity), + expected[i]); + } + }); + + It("returns default values for incompatible type", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec2(-2.0f, 10.5f), + glm::vec2(1.5f, 0.1f)}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( + property, + static_cast(i), + FMatrix::Identity), + FMatrix::Identity); + } + }); + + It("gets with offset / scale", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::MAT4; + classProperty.componentType = ClassProperty::ComponentType::FLOAT64; + + double offset = 1.0; + double scale = 2.0; + + CesiumUtility::JsonValue::Array offsetArray(16); + CesiumUtility::JsonValue::Array scaleArray(16); + for (size_t i = 0; i < 16; i++) { + offsetArray[i] = offset; + scaleArray[i] = scale; + } + + classProperty.offset = offsetArray; + classProperty.scale = scaleArray; + + // clang-format off + std::vector values{ + glm::dmat4( + 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0), + glm::dmat4( + 1.0, 0.0, 0.0, 0.0, + 0.0, -2.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + -1.5, 4.0, 2.0, 1.0), + }; + // clang-format on + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + std::vector expected(2); + expected[0] = FMatrix( + FPlane4d(3.0, 11.0, 19.0, 27.0), + FPlane4d(5.0, 13.0, 21.0, 29.0), + FPlane4d(7.0, 15.0, 23.0, 31.0), + FPlane4d(9.0, 17.0, 25.0, 33.0)); + expected[1] = FMatrix( + FPlane4d(3.0, 1.0, 1.0, -2.0), + FPlane4d(1.0, -4.0, 1.0, 9.0), + FPlane4d(1.0, 1.0, 2.0, 5.0), + FPlane4d(1.0, 1.0, 1.0, 3.0)); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( + property, + static_cast(i), + FMatrix::Identity), + expected[i]); + } + }); + }); + + Describe("GetArray", [this]() { + It("returns empty array for non-array property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + std::vector values{1, 2, 3, 4, 5, 6}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + FCesiumPropertyArray array = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, 0); + TestEqual( + "array size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + 0); + FCesiumMetadataValueType valueType; // Unknown type + TestTrue( + "array type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + }); + + It("returns empty array for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + + FCesiumPropertyArray array = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, 0); + TestEqual( + "array size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + 0); + FCesiumMetadataValueType valueType; // Unknown type + TestTrue( + "array type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + }); + + It("returns empty array for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + classProperty.array = true; + classProperty.count = 2; + + std::vector values{1, 2, 3, 4, 5, 6}; + std::vector data = GetValuesAsBytes(values); + int64 size = static_cast(values.size()) / *classProperty.count; + + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + std::span(data.data(), data.size()), + std::span(), + std::span(), + PropertyComponentType::None, + PropertyComponentType::None); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + size); + + FCesiumPropertyArray array = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, -1); + TestEqual( + "negative index array size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + 0); + FCesiumMetadataValueType valueType; // Unknown type + TestTrue( + "negative index array type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + + array = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, 10); + TestEqual( + "out-of-range positive index array size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + 0); + TestTrue( + "out-of-range positive index array type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + }); + + It("returns array for fixed-length array property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + classProperty.array = true; + classProperty.count = 2; + + std::vector values{1, 2, 3, 4, 5, 6}; + std::vector data = GetValuesAsBytes(values); + int64 size = static_cast(values.size()) / *classProperty.count; + + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + std::span(data.data(), data.size()), + std::span(), + std::span(), + PropertyComponentType::None, + PropertyComponentType::None); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + size); + TestEqual( + "ArraySize", + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), + *classProperty.count); + + for (int64 i = 0; i < size; i++) { + FCesiumPropertyArray array = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, i); + int64 arraySize = UCesiumPropertyArrayBlueprintLibrary::GetSize(array); + TestEqual("array size", arraySize, *classProperty.count); + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + false); + TestTrue( + "array element type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + + int64 arrayOffset = i * arraySize; + for (int64 j = 0; j < arraySize; j++) { + std::string label( + "array" + std::to_string(i) + " value" + std::to_string(j)); + FCesiumMetadataValue value = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, j); + TestEqual( + label.c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[static_cast(arrayOffset + j)]); + } + } + }); + + It("returns array for variable-length array property", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + classProperty.array = true; + + std::vector values{1, 2, 3, 4, 5, 6}; + std::vector data = GetValuesAsBytes(values); + + std::vector offsets{0, 2, 3, 6}; + std::vector offsetsData = GetValuesAsBytes(offsets); + int64 size = static_cast(offsets.size() - 1); + + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + std::span(data.data(), data.size()), + std::span( + offsetsData.data(), + offsetsData.size()), + std::span(), + PropertyComponentType::Uint16, + PropertyComponentType::None); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + size); + TestEqual( + "ArraySize", + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), + static_cast(0)); + + std::vector> expected{{1, 2}, {3}, {4, 5, 6}}; + for (int64 i = 0; i < size; i++) { + const std::vector& expectedArray = + expected[static_cast(i)]; + FCesiumPropertyArray array = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, i); + TestEqual( + "array size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(expectedArray.size())); + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + false); + TestTrue( + "element type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + + for (size_t j = 0; j < expectedArray.size(); j++) { + std::string label( + "array" + std::to_string(i) + " value" + std::to_string(j)); + FCesiumMetadataValue value = + UCesiumPropertyArrayBlueprintLibrary::GetValue( + array, + static_cast(j)); + TestEqual( + label.c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + expectedArray[j]); + } + } + }); + + It("gets with noData value", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + classProperty.array = true; + classProperty.count = 2; + + classProperty.noData = {-1, -1}; + + std::vector values{1, 2, 3, 4, 5, 6, -1, -1}; + std::vector data = GetValuesAsBytes(values); + int64 size = static_cast(values.size()) / *classProperty.count; + + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + std::span(data.data(), data.size()), + std::span(), + std::span(), + PropertyComponentType::None, + PropertyComponentType::None); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + size); + TestEqual( + "ArraySize", + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), + *classProperty.count); + + for (int64 i = 0; i < size - 1; i++) { + FCesiumPropertyArray array = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, i); + int64 arraySize = UCesiumPropertyArrayBlueprintLibrary::GetSize(array); + TestEqual("array size", arraySize, *classProperty.count); + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + false); + TestTrue( + "array element type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + + int64 arrayOffset = i * arraySize; + for (int64 j = 0; j < arraySize; j++) { + std::string label( + "array" + std::to_string(i) + " value" + std::to_string(j)); + FCesiumMetadataValue value = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, j); + TestEqual( + label.c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[static_cast(arrayOffset + j)]); + } + } + + // Check that the "no data" value resolves to an empty array of an invalid + // type. + FCesiumPropertyArray array = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArray( + property, + size - 1); + TestEqual( + "array size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(0)); + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Invalid, + ECesiumMetadataComponentType::None, + false); + TestTrue( + "array element type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + }); + + It("gets with noData / default value", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + classProperty.array = true; + classProperty.count = 2; + + classProperty.noData = {-1, -1}; + classProperty.defaultProperty = {10, 20}; + + std::vector values{1, 2, 3, 4, 5, 6, -1, -1}; + std::vector data = GetValuesAsBytes(values); + int64 size = static_cast(values.size()) / *classProperty.count; + + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + std::span(data.data(), data.size()), + std::span(), + std::span(), + PropertyComponentType::None, + PropertyComponentType::None); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + size); + TestEqual( + "ArraySize", + UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), + *classProperty.count); + + for (int64 i = 0; i < size; i++) { + FCesiumPropertyArray array = + UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, i); + int64 arraySize = UCesiumPropertyArrayBlueprintLibrary::GetSize(array); + TestEqual("array size", arraySize, *classProperty.count); + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + false); + TestTrue( + "array element type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + + if (i == size - 1) { + std::string label("array" + std::to_string(i)); + // Check that the "no data" value resolves to the default array value. + FCesiumMetadataValue value0 = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 0); + TestEqual( + label.c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value0, 0), + 10); + FCesiumMetadataValue value1 = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 1); + TestEqual( + label.c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value1, 0), + 20); + } else { + int64 arrayOffset = i * arraySize; + for (int64 j = 0; j < arraySize; j++) { + std::string label( + "array" + std::to_string(i) + " value" + std::to_string(j)); + FCesiumMetadataValue value = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, j); + TestEqual( + label.c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[static_cast(arrayOffset + j)]); + } + } + } + }); + }); + + Describe("GetValue", [this]() { + It("returns empty value for invalid property", [this]() { + FCesiumPropertyTableProperty property; + TestEqual( + "PropertyTablePropertyStatus", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); + TestEqual( + "Size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(0)); + + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetValue(property, 0); + FCesiumMetadataValueType valueType; // Unknown type + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + }); + + It("returns empty value for invalid feature ID", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetValue(property, -1); + FCesiumMetadataValueType valueType; // Unknown type + TestTrue( + "negative index value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + + value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetValue(property, 10); + TestTrue( + "out-of-range positive index value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + }); + + It("gets value for valid feature IDs", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + false); + for (size_t i = 0; i < values.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetValue(property, i); + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[i]); + } + }); + + It("gets with offset / scale", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{-1.1f, 2.0f, -3.5f, 4.0f}; + std::vector data = GetValuesAsBytes(values); + + float offset = 1.0f; + float scale = 2.0f; + + classProperty.offset = offset; + classProperty.scale = scale; + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Float32, + false); + for (size_t i = 0; i < values.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetValue(property, i); + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetFloat(value, 0), + values[i] * scale + offset); + } + }); + + It("gets with noData", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + int32_t noData = -1; + classProperty.noData = noData; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + false); + for (size_t i = 0; i < values.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetValue(property, i); + if (values[i] == noData) { + // Empty value indicated by invalid value type. + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + FCesiumMetadataValueType()); + } else { + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[i]); + } + } + }); + + It("gets with noData / default value", [this]() { + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + int32_t noData = -1; + int32_t defaultValue = 15; + + classProperty.noData = noData; + classProperty.defaultProperty = defaultValue; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + CesiumGltf::PropertyTablePropertyView propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + std::span(data.data(), data.size())); + FCesiumPropertyTableProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTablePropertyBlueprintLibrary:: + GetPropertyTablePropertyStatus(property), + ECesiumPropertyTablePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + false); + for (size_t i = 0; i < values.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyTablePropertyBlueprintLibrary::GetValue(property, i); + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + if (values[i] == noData) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + defaultValue); + } else { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[i]); + } + } + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyTexture.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyTexture.spec.cpp new file mode 100644 index 0000000..8465832 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyTexture.spec.cpp @@ -0,0 +1,823 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyTexture.h" +#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltfComponent.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumGltfSpecUtility.h" +#include "Misc/AutomationTest.h" +#include + +BEGIN_DEFINE_SPEC( + FCesiumPropertyTextureSpec, + "Cesium.Unit.PropertyTexture", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +CesiumGltf::Model model; +CesiumGltf::MeshPrimitive* pPrimitive; +CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension; +CesiumGltf::PropertyTexture* pPropertyTexture; +TObjectPtr pModelComponent; +TObjectPtr pPrimitiveComponent; + +const std::vector texCoords{ + FVector2D(0, 0), + FVector2D(0.5, 0), + FVector2D(0, 0.5), + FVector2D(0.5, 0.5)}; +END_DEFINE_SPEC(FCesiumPropertyTextureSpec) + +void FCesiumPropertyTextureSpec::Define() { + using namespace CesiumGltf; + + BeforeEach([this]() { + model = Model(); + pExtension = &model.addExtension(); + pExtension->schema.emplace(); + pPropertyTexture = &pExtension->propertyTextures.emplace_back(); + }); + + Describe("Constructor", [this]() { + It("constructs invalid instance by default", [this]() { + FCesiumPropertyTexture propertyTexture; + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::ErrorInvalidPropertyTexture); + TestTrue( + "Properties", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .IsEmpty()); + }); + + It("constructs invalid instance for missing schema", [this]() { + pExtension->schema.reset(); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::ErrorInvalidPropertyTextureClass); + TestTrue( + "Properties", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .IsEmpty()); + }); + + It("constructs invalid instance for missing class", [this]() { + pPropertyTexture->classProperty = "nonexistent class"; + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::ErrorInvalidPropertyTextureClass); + TestTrue( + "Properties", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .IsEmpty()); + }); + + It("constructs valid instance with valid property", [this]() { + pPropertyTexture->classProperty = "testClass"; + std::string propertyName("testProperty"); + std::array values{1, 2, 3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + propertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + values, + {0}); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .Num(), + 1); + }); + + It("constructs valid instance with invalid property", [this]() { + // Even if one of its properties is invalid, the property texture itself + // is still valid. + pPropertyTexture->classProperty = "testClass"; + std::string propertyName("testProperty"); + std::array values{1, 2, 3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + propertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT32, // Incorrect component type + values, + {0}); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .Num(), + 1); + }); + }); + + Describe("GetProperties", [this]() { + BeforeEach([this]() { pPropertyTexture->classProperty = "testClass"; }); + + It("returns no properties for invalid property texture", [this]() { + FCesiumPropertyTexture propertyTexture; + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::ErrorInvalidPropertyTexture); + const auto properties = + UCesiumPropertyTextureBlueprintLibrary::GetProperties( + propertyTexture); + TestTrue("properties are empty", properties.IsEmpty()); + }); + + It("gets valid properties", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::array scalarValues{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + scalarPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + scalarValues, + {0}); + + std::string vec2PropertyName("vec2Property"); + std::array vec2Values{ + glm::u8vec2(1, 2), + glm::u8vec2(0, 4), + glm::u8vec2(8, 9), + glm::u8vec2(11, 0), + }; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + vec2PropertyName, + ClassProperty::Type::VEC2, + ClassProperty::ComponentType::UINT8, + vec2Values, + {0, 1}); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::Valid); + + const auto properties = + UCesiumPropertyTextureBlueprintLibrary::GetProperties( + propertyTexture); + + TestTrue( + "has scalar property", + properties.Contains(FString(scalarPropertyName.c_str()))); + const FCesiumPropertyTextureProperty& scalarProperty = + *properties.Find(FString(scalarPropertyName.c_str())); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(scalarProperty), + ECesiumPropertyTexturePropertyStatus::Valid); + for (size_t i = 0; i < texCoords.size(); i++) { + std::string label("Property value " + std::to_string(i)); + TestEqual( + label.c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger( + scalarProperty, + texCoords[i]), + scalarValues[i]); + } + + TestTrue( + "has vec2 property", + properties.Contains(FString(vec2PropertyName.c_str()))); + const FCesiumPropertyTextureProperty& vec2Property = + *properties.Find(FString(vec2PropertyName.c_str())); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(vec2Property), + ECesiumPropertyTexturePropertyStatus::Valid); + for (size_t i = 0; i < texCoords.size(); i++) { + std::string label("Property value " + std::to_string(i)); + FVector2D expected( + static_cast(vec2Values[i][0]), + static_cast(vec2Values[i][1])); + TestEqual( + label.c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector2D( + vec2Property, + texCoords[i], + FVector2D::Zero()), + expected); + } + }); + + It("gets invalid property", [this]() { + // Even invalid properties should still be retrieved. + std::array values{0, 1, 2, 3}; + std::string propertyName("badProperty"); + + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + propertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT32, + values, + {0}); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::Valid); + + const auto properties = + UCesiumPropertyTextureBlueprintLibrary::GetProperties( + propertyTexture); + + TestTrue( + "has invalid property", + properties.Contains(FString(propertyName.c_str()))); + const FCesiumPropertyTextureProperty& property = + *properties.Find(FString(propertyName.c_str())); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidPropertyData); + }); + }); + + Describe("GetPropertyNames", [this]() { + BeforeEach([this]() { pPropertyTexture->classProperty = "testClass"; }); + + It("returns empty array for invalid property texture", [this]() { + FCesiumPropertyTexture propertyTexture; + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::ErrorInvalidPropertyTexture); + const auto properties = + UCesiumPropertyTextureBlueprintLibrary::GetProperties( + propertyTexture); + TestTrue("properties are empty", properties.IsEmpty()); + }); + + It("gets all property names", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::array scalarValues{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + scalarPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + scalarValues, + {0}); + + std::string vec2PropertyName("vec2Property"); + std::array vec2Values{ + glm::u8vec2(1, 2), + glm::u8vec2(0, 4), + glm::u8vec2(8, 9), + glm::u8vec2(11, 0), + }; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + vec2PropertyName, + ClassProperty::Type::VEC2, + ClassProperty::ComponentType::UINT8, + vec2Values, + {0, 1}); + + std::string invalidPropertyName("badProperty"); + std::array invalidPropertyValues{0, 1, 2, 3}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + invalidPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT32, // Incorrect component type + invalidPropertyValues, + {0}); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::Valid); + + const auto propertyNames = + UCesiumPropertyTextureBlueprintLibrary::GetPropertyNames( + propertyTexture); + TestEqual("number of names", propertyNames.Num(), 3); + TestTrue( + "has scalar property name", + propertyNames.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "has vec2 property name", + propertyNames.Contains(FString(vec2PropertyName.c_str()))); + TestTrue( + "has invalid property name", + propertyNames.Contains(FString(invalidPropertyName.c_str()))); + }); + }); + + Describe("FindProperty", [this]() { + BeforeEach([this]() { pPropertyTexture->classProperty = "testClass"; }); + + It("returns invalid instance for nonexistent property", [this]() { + std::string propertyName("testProperty"); + std::array values{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + propertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + values, + {0}); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .Num(), + 1); + + FCesiumPropertyTextureProperty property = + UCesiumPropertyTextureBlueprintLibrary::FindProperty( + propertyTexture, + FString("nonexistent property")); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + }); + + It("finds existing properties", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::array scalarValues{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + scalarPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + scalarValues, + {0}); + + std::string vec2PropertyName("vec2Property"); + std::array vec2Values{ + glm::u8vec2(1, 2), + glm::u8vec2(0, 4), + glm::u8vec2(8, 9), + glm::u8vec2(11, 0), + }; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + vec2PropertyName, + ClassProperty::Type::VEC2, + ClassProperty::ComponentType::UINT8, + vec2Values, + {0, 1}); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .Num(), + 2); + + FCesiumPropertyTextureProperty scalarProperty = + UCesiumPropertyTextureBlueprintLibrary::FindProperty( + propertyTexture, + FString(scalarPropertyName.c_str())); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(scalarProperty), + ECesiumPropertyTexturePropertyStatus::Valid); + + FCesiumPropertyTextureProperty vec2Property = + UCesiumPropertyTextureBlueprintLibrary::FindProperty( + propertyTexture, + FString(vec2PropertyName.c_str())); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(vec2Property), + ECesiumPropertyTexturePropertyStatus::Valid); + }); + }); + + Describe("GetMetadataValuesForUV", [this]() { + BeforeEach([this]() { pPropertyTexture->classProperty = "testClass"; }); + + It("returns empty map for invalid property texture", [this]() { + FCesiumPropertyTexture propertyTexture; + + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::ErrorInvalidPropertyTexture); + TestTrue( + "Properties", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .IsEmpty()); + + const auto values = + UCesiumPropertyTextureBlueprintLibrary::GetMetadataValuesForUV( + propertyTexture, + FVector2D::Zero()); + TestTrue("values map is empty", values.IsEmpty()); + }); + + It("returns values of valid properties", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::array scalarValues{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + scalarPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + scalarValues, + {0}); + + std::string vec2PropertyName("vec2Property"); + std::array vec2Values{ + glm::u8vec2(1, 2), + glm::u8vec2(0, 4), + glm::u8vec2(8, 9), + glm::u8vec2(11, 0), + }; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + vec2PropertyName, + ClassProperty::Type::VEC2, + ClassProperty::ComponentType::UINT8, + vec2Values, + {0, 1}); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .Num(), + 2); + + for (size_t i = 0; i < texCoords.size(); i++) { + const auto values = + UCesiumPropertyTextureBlueprintLibrary::GetMetadataValuesForUV( + propertyTexture, + texCoords[i]); + TestEqual("number of values", values.Num(), 2); + + TestTrue( + "contains scalar value", + values.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "contains vec2 value", + values.Contains(FString(vec2PropertyName.c_str()))); + + const FCesiumMetadataValue& scalarValue = + *values.Find(FString(scalarPropertyName.c_str())); + TestEqual( + "scalar value", + UCesiumMetadataValueBlueprintLibrary::GetInteger(scalarValue, 0), + scalarValues[i]); + + const FCesiumMetadataValue& vec2Value = + *values.Find(FString(vec2PropertyName.c_str())); + FVector2D expected(vec2Values[i][0], vec2Values[i][1]); + TestEqual( + "vec2 value", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + vec2Value, + FVector2D::Zero()), + expected); + } + }); + + It("does not return value for invalid property", [this]() { + std::string propertyName("badProperty"); + std::array data{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + propertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT32, + data, + {0}); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .Num(), + 1); + + const auto values = + UCesiumPropertyTextureBlueprintLibrary::GetMetadataValuesForUV( + propertyTexture, + FVector2D::Zero()); + TestTrue("values map is empty", values.IsEmpty()); + }); + }); + + Describe("GetMetadataValuesFromHit", [this]() { + BeforeEach([this]() { + Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + pPrimitive->mode = MeshPrimitive::Mode::TRIANGLES; + + std::vector positions{ + glm::vec3(-1, 0, 0), + glm::vec3(0, 1, 0), + glm::vec3(1, 0, 0), + glm::vec3(-1, 3, 0), + glm::vec3(0, 4, 0), + glm::vec3(1, 3, 0), + }; + + CreateAttributeForPrimitive( + model, + *pPrimitive, + "POSITION", + AccessorSpec::Type::VEC3, + AccessorSpec::ComponentType::FLOAT, + positions); + + int32_t positionAccessorIndex = + static_cast(model.accessors.size() - 1); + + // For convenience when testing, the UVs are the same as the positions + // they correspond to. This means that the interpolated UV value should be + // directly equal to the barycentric coordinates of the triangle. + std::vector texCoords0{ + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0), + glm::vec2(-1, 0), + glm::vec2(0, 1), + glm::vec2(1, 0)}; + + CreateAttributeForPrimitive( + model, + *pPrimitive, + "TEXCOORD_0", + AccessorSpec::Type::VEC2, + AccessorSpec::ComponentType::FLOAT, + texCoords0); + + pModelComponent = NewObject(); + pPrimitiveComponent = + NewObject(pModelComponent); + pPrimitiveComponent->AttachToComponent( + pModelComponent, + FAttachmentTransformRules(EAttachmentRule::KeepRelative, false)); + + CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); + primData.pMeshPrimitive = pPrimitive; + primData.PositionAccessor = + CesiumGltf::AccessorView(model, positionAccessorIndex); + primData.TexCoordAccessorMap.emplace( + 0, + AccessorView>( + model, + static_cast(model.accessors.size() - 1))); + + pPropertyTexture->classProperty = "testClass"; + }); + + It("returns empty map for invalid hit component", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::array scalarValues{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + scalarPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + scalarValues, + {0}); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .Num(), + 1); + + FHitResult Hit; + Hit.Component = nullptr; + Hit.FaceIndex = 0; + Hit.Location = FVector_NetQuantize{0, 0, 0} * + CesiumPrimitiveData::positionScaleFactor; + + const auto values = + UCesiumPropertyTextureBlueprintLibrary::GetMetadataValuesFromHit( + propertyTexture, + Hit); + TestTrue("values is empty", values.IsEmpty()); + }); + + It("returns values of valid properties", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::array scalarValues{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + scalarPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + scalarValues, + {0}); + + std::string vec2PropertyName("vec2Property"); + std::array vec2Values{ + glm::u8vec2(1, 2), + glm::u8vec2(0, 4), + glm::u8vec2(8, 9), + glm::u8vec2(11, 0), + }; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + vec2PropertyName, + ClassProperty::Type::VEC2, + ClassProperty::ComponentType::UINT8, + vec2Values, + {0, 1}); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .Num(), + 2); + + FHitResult Hit; + Hit.Component = pPrimitiveComponent; + Hit.FaceIndex = 0; + + std::array locations{ + FVector_NetQuantize(1, 0, 0), + FVector_NetQuantize(0, -1, 0), + FVector_NetQuantize(0, -0.25, 0)}; + std::array expectedScalar{2, -3, -1}; + std::array expectedVec2{ + FIntPoint(0, 4), + FIntPoint(8, 9), + FIntPoint(1, 2)}; + + for (size_t i = 0; i < locations.size(); i++) { + Hit.Location = locations[i] * CesiumPrimitiveData::positionScaleFactor; + const auto values = + UCesiumPropertyTextureBlueprintLibrary::GetMetadataValuesFromHit( + propertyTexture, + Hit); + TestEqual("number of values", values.Num(), 2); + + TestTrue( + "contains scalar value", + values.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "contains vec2 value", + values.Contains(FString(vec2PropertyName.c_str()))); + + const FCesiumMetadataValue* pScalarValue = + values.Find(FString(scalarPropertyName.c_str())); + if (pScalarValue) { + TestEqual( + "scalar value", + UCesiumMetadataValueBlueprintLibrary::GetInteger( + *pScalarValue, + 0), + expectedScalar[i]); + } + + const FCesiumMetadataValue* pVec2Value = + values.Find(FString(vec2PropertyName.c_str())); + if (pVec2Value) { + TestEqual( + "vec2 value", + UCesiumMetadataValueBlueprintLibrary::GetIntPoint( + *pVec2Value, + FIntPoint(0)), + expectedVec2[i]); + } + } + }); + + It("does not return value for invalid property", [this]() { + std::string propertyName("badProperty"); + std::array data{-1, 2, -3, 4}; + AddPropertyTexturePropertyToModel( + model, + *pPropertyTexture, + propertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT32, + data, + {0}); + + FCesiumPropertyTexture propertyTexture(model, *pPropertyTexture); + + TestEqual( + "PropertyTextureStatus", + UCesiumPropertyTextureBlueprintLibrary::GetPropertyTextureStatus( + propertyTexture), + ECesiumPropertyTextureStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyTextureBlueprintLibrary::GetProperties(propertyTexture) + .Num(), + 1); + + FHitResult Hit; + Hit.Component = pPrimitiveComponent; + Hit.FaceIndex = 0; + Hit.Location = FVector_NetQuantize{0, 0, 0} * + CesiumPrimitiveData::positionScaleFactor; + + const auto values = + UCesiumPropertyTextureBlueprintLibrary::GetMetadataValuesFromHit( + propertyTexture, + Hit); + TestTrue("values map is empty", values.IsEmpty()); + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyTextureProperty.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyTextureProperty.spec.cpp new file mode 100644 index 0000000..0c23881 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumPropertyTextureProperty.spec.cpp @@ -0,0 +1,2500 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyTextureProperty.h" +#include "CesiumGltfSpecUtility.h" +#include "CesiumPropertyArrayBlueprintLibrary.h" +#include "Misc/AutomationTest.h" +#include + +BEGIN_DEFINE_SPEC( + FCesiumPropertyTexturePropertySpec, + "Cesium.Unit.PropertyTextureProperty", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +const std::vector texCoords{ + FVector2D(0, 0), + FVector2D(0.5, 0), + FVector2D(0, 0.5), + FVector2D(0.5, 0.5)}; +END_DEFINE_SPEC(FCesiumPropertyTexturePropertySpec) + +void FCesiumPropertyTexturePropertySpec::Define() { + using namespace CesiumGltf; + + Describe("Constructor", [this]() { + It("constructs invalid instance by default", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + + FCesiumMetadataValueType expectedType; // Invalid type + TestTrue( + "ValueType", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + }); + + It("constructs invalid instance from view with invalid definition", + [this]() { + PropertyTexturePropertyView propertyView( + PropertyTexturePropertyViewStatus::ErrorArrayTypeMismatch); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + + FCesiumMetadataValueType expectedType; // Invalid type + TestTrue( + "ValueType", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + }); + + It("constructs invalid instance from view with invalid data", [this]() { + PropertyTexturePropertyView propertyView( + PropertyTexturePropertyViewStatus::ErrorInvalidImage); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidPropertyData); + + FCesiumMetadataValueType expectedType; // Invalid type + TestTrue( + "ValueType", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + }); + + It("constructs valid instance", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 1; + image.bytesPerChannel = 1; + + std::vector values{1, 2, 3, 4}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Uint8, + false); + TestTrue( + "ValueType", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Byte); + + TestFalse( + "IsNormalized", + UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized( + property)); + + // Test that the returns are as expected for non-array properties. + TestEqual( + "ArraySize", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( + property), + static_cast(0)); + TestEqual( + "ArrayElementBlueprintType", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetArrayElementBlueprintType(property), + ECesiumMetadataBlueprintType::None); + + // Check that undefined properties return empty values + FCesiumMetadataValue value = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetOffset(property); + TestTrue("Offset", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetScale(property); + TestTrue("Scale", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyTexturePropertyBlueprintLibrary::GetMaximumValue( + property); + TestTrue("Max", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyTexturePropertyBlueprintLibrary::GetMinimumValue( + property); + TestTrue("Min", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyTexturePropertyBlueprintLibrary::GetNoDataValue( + property); + TestTrue("NoData", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyTexturePropertyBlueprintLibrary::GetDefaultValue( + property); + TestTrue("Default", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + }); + + It("constructs valid normalized instance", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 1; + image.bytesPerChannel = 1; + + std::vector values{0, 1, 255, 128}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Uint8, + false); + TestTrue( + "ValueType", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Byte); + + TestTrue( + "IsNormalized", + UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized( + property)); + + // Test that the returns are as expected for non-array properties. + TestEqual( + "ArraySize", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( + property), + static_cast(0)); + TestEqual( + "ArrayElementBlueprintType", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetArrayElementBlueprintType(property), + ECesiumMetadataBlueprintType::None); + }); + + It("constructs instance for fixed-length array property", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.array = true; + classProperty.count = 2; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 2; + image.bytesPerChannel = 1; + + std::vector values{1, 2, 3, 4, 5, 6, 7, 8}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView> propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Uint8, + true); + TestTrue( + "ValueType", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Array); + + TestFalse( + "IsNormalized", + UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized( + property)); + + TestEqual( + "ArraySize", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( + property), + *classProperty.count); + TestEqual( + "ArrayElementBlueprintType", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetArrayElementBlueprintType(property), + ECesiumMetadataBlueprintType::Byte); + }); + + It("constructs valid instance with additional properties", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + double offset = 1.0; + double scale = 2.0; + double min = 1.0; + double max = 3.0; + int32_t noData = 1; + double defaultValue = 12.3; + + classProperty.offset = offset; + classProperty.scale = scale; + classProperty.min = min; + classProperty.max = max; + classProperty.noData = noData; + classProperty.defaultProperty = defaultValue; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 1; + image.bytesPerChannel = 1; + + std::vector values{1, 2, 3, 4}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Uint8, + false); + TestTrue( + "ValueType", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Byte); + + TestTrue( + "IsNormalized", + UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized( + property)); + + // Test that the returns are as expected for non-array properties. + TestEqual( + "ArraySize", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( + property), + static_cast(0)); + TestEqual( + "ArrayElementBlueprintType", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetArrayElementBlueprintType(property), + ECesiumMetadataBlueprintType::None); + + FCesiumMetadataValue value = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetOffset(property); + TestEqual( + "Offset", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + offset); + + value = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetScale(property); + TestEqual( + "Scale", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + scale); + + value = UCesiumPropertyTexturePropertyBlueprintLibrary::GetMaximumValue( + property); + TestEqual( + "Max", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + max); + + value = UCesiumPropertyTexturePropertyBlueprintLibrary::GetMinimumValue( + property); + TestEqual( + "Min", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + min); + + value = UCesiumPropertyTexturePropertyBlueprintLibrary::GetNoDataValue( + property); + TestEqual( + "NoData", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0.0), + noData); + + value = UCesiumPropertyTexturePropertyBlueprintLibrary::GetDefaultValue( + property); + TestEqual( + "Default", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + defaultValue); + }); + }); + + Describe("GetByte", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetByte( + property, + FVector2D::Zero()), + 0); + }); + + It("gets from uint8 property", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 1; + image.bytesPerChannel = 1; + + std::vector values{1, 2, 3, 4}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetByte( + property, + texCoords[i]), + values[i]); + } + }); + + It("converts compatible values", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT16; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 2; + image.bytesPerChannel = 1; + + std::vector values{-1, 2, 256, 4}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1}; + } else { + propertyTextureProperty.channels = {1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + std::vector expected{0, 2, 0, 4}; + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetByte( + property, + texCoords[i], + 0), + expected[i]); + } + }); + + It("gets with noData / default value", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + + uint8_t noDataValue = 0; + uint8_t defaultValue = 255; + + classProperty.noData = noDataValue; + classProperty.defaultProperty = defaultValue; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 1; + image.bytesPerChannel = 1; + + std::vector values{1, 2, 3, 0}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + if (values[i] == noDataValue) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetByte( + property, + texCoords[i]), + defaultValue); + } else { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetByte( + property, + texCoords[i]), + values[i]); + } + } + }); + }); + + Describe("GetInteger", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger( + property, + FVector2D::Zero()), + 0); + }); + + It("gets from int32 property", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{-1, 2, -3, 4}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger( + property, + texCoords[i]), + values[i]); + } + }); + + It("converts compatible values", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{ + 1.234f, + -24.5f, + std::numeric_limits::lowest(), + 2456.80f}; + image.pixelData = GetValuesAsBytes(values); + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + std::vector expected{1, -24, 0, 2456}; + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger( + property, + texCoords[i]), + expected[i]); + } + }); + + It("gets with noData / default value", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + int32_t noDataValue = -1; + int32_t defaultValue = 10; + + classProperty.noData = noDataValue; + classProperty.defaultProperty = defaultValue; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{-1, 2, -3, 4}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + if (values[i] == noDataValue) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger( + property, + texCoords[i]), + defaultValue); + } else { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger( + property, + texCoords[i]), + values[i]); + } + } + }); + }); + + Describe("GetFloat", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat( + property, + FVector2D::Zero()), + 0.0f); + }); + + It("gets from float property", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{-1.1f, 2.2f, -3.3f, 4.0f}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat( + property, + texCoords[i]), + values[i]); + } + }); + + It("converts uint8 values", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 1; + image.bytesPerChannel = 1; + + std::vector values{1, 2, 3, 4}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat( + property, + texCoords[i]), + static_cast(values[i])); + } + }); + + It("gets with offset / scale", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + float offset = 5.0f; + float scale = 2.0f; + + classProperty.offset = offset; + classProperty.scale = scale; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{-1.1f, 2.2f, -3.3f, 4.0f}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat( + property, + texCoords[i]), + values[i] * scale + offset); + } + }); + }); + + Describe("GetFloat64", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat64( + property, + FVector2D::Zero()), + 0.0); + }); + + It("gets from normalized uint8 property", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 1; + image.bytesPerChannel = 1; + + std::vector values{0, 128, 255, 0}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + TestTrue( + "IsNormalized", + UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized( + property)); + + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat64( + property, + texCoords[i]), + static_cast(values[i]) / 255.0); + } + }); + + It("converts float values", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{-1.1, 2.2, -3.3, 4.0}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat64( + property, + texCoords[i]), + static_cast(values[i])); + } + }); + + It("gets with offset / scale", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + float offset = 5.0; + float scale = 2.0; + + classProperty.offset = offset; + classProperty.scale = scale; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 1; + image.bytesPerChannel = 1; + + std::vector values{0, 128, 255, 0}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat64( + property, + texCoords[i]), + (static_cast(values[i]) / 255.0) * scale + offset); + } + }); + }); + + Describe("GetIntPoint", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntPoint( + property, + FVector2D::Zero(), + FIntPoint(0)), + FIntPoint(0)); + }); + + It("gets from i8vec2 property", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 2; + image.bytesPerChannel = 1; + + std::vector values{ + glm::i8vec2(1, 1), + glm::i8vec2(-1, -1), + glm::i8vec2(2, 4), + glm::i8vec2(0, -8)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + FIntPoint expected(values[i][0], values[i][1]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntPoint( + property, + texCoords[i], + FIntPoint(0)), + expected); + } + }); + + It("converts compatible values", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{ + 1.234f, + -24.5f, + std::numeric_limits::lowest(), + 2456.80f}; + image.pixelData = GetValuesAsBytes(values); + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + std::vector expected{1, -24, 0, 2456}; + for (size_t i = 0; i < texCoords.size(); i++) { + FIntPoint expectedIntPoint(expected[i]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntPoint( + property, + texCoords[i], + FIntPoint(0)), + expectedIntPoint); + } + }); + + It("gets with noData / default value", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + glm::i8vec2 noData(-1, -1); + FIntPoint defaultValue(5, 22); + + classProperty.noData = {noData[0], noData[1]}; + classProperty.defaultProperty = {defaultValue[0], defaultValue[1]}; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 2; + image.bytesPerChannel = 1; + + std::vector values{ + glm::i8vec2(1, 1), + glm::i8vec2(-1, -1), + glm::i8vec2(2, 4), + glm::i8vec2(0, -8)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + FIntPoint expected; + if (values[i] == noData) { + expected = defaultValue; + } else { + expected = FIntPoint(values[i][0], values[i][1]); + } + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntPoint( + property, + texCoords[i], + FIntPoint(0)), + expected); + } + }); + }); + + Describe("GetVector2D", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector2D( + property, + FVector2D::Zero(), + FVector2D::Zero()), + FVector2D::Zero()); + }); + + It("gets from normalized glm::u8vec2 property", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 2; + image.bytesPerChannel = 1; + + std::vector values{ + glm::u8vec2(1, 1), + glm::u8vec2(0, 255), + glm::u8vec2(10, 4), + glm::u8vec2(128, 8)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + TestTrue( + "IsNormalized", + UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized( + property)); + + for (size_t i = 0; i < texCoords.size(); i++) { + glm::dvec2 expected = glm::dvec2(values[i][0], values[i][1]) / 255.0; + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector2D( + property, + texCoords[i], + FVector2D::Zero()), + FVector2D(expected[0], expected[1])); + } + }); + + It("converts unnormalized glm::u8vec2 values", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 2; + image.bytesPerChannel = 1; + + std::vector values{ + glm::u8vec2(1, 1), + glm::u8vec2(0, 255), + glm::u8vec2(10, 4), + glm::u8vec2(128, 8)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector2D( + property, + texCoords[i], + FVector2D::Zero()), + FVector2D(values[i][0], values[i][1])); + } + }); + + It("gets with offset / scale", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + FVector2D offset(3.0, 2.4); + FVector2D scale(2.0, -1.0); + + classProperty.offset = {offset[0], offset[1]}; + classProperty.scale = {scale[0], scale[1]}; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 2; + image.bytesPerChannel = 1; + + std::vector values{ + glm::u8vec2(1, 1), + glm::u8vec2(0, 255), + glm::u8vec2(10, 4), + glm::u8vec2(128, 8)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + FVector2D expected( + static_cast(values[i][0]) / 255.0 * scale[0] + offset[0], + static_cast(values[i][1]) / 255.0 * scale[1] + offset[1]); + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector2D( + property, + texCoords[i], + FVector2D::Zero()), + expected); + } + }); + }); + + Describe("GetIntVector", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntVector( + property, + FVector2D::Zero(), + FIntVector(0)), + FIntVector(0)); + }); + + It("gets from glm::i8vec3 property", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1, 2}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 3; + image.bytesPerChannel = 1; + + std::vector values{ + glm::i8vec3(1, 1, -1), + glm::i8vec3(-1, -1, 2), + glm::i8vec3(0, 4, 2), + glm::i8vec3(10, 8, 5)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + FIntVector expected(values[i][0], values[i][1], values[i][2]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntVector( + property, + texCoords[i], + FIntVector(0)), + expected); + } + }); + + It("converts compatible values", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{ + 1.234f, + -24.5f, + std::numeric_limits::lowest(), + 2456.80f}; + image.pixelData = GetValuesAsBytes(values); + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + std::vector expected{1, -24, 0, 2456}; + for (size_t i = 0; i < texCoords.size(); i++) { + FIntVector expectedIntVector(expected[i]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntVector( + property, + texCoords[i], + FIntVector(0)), + expectedIntVector); + } + }); + + It("gets with noData / default value", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1, 2}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + glm::i8vec3 noData(-1, -1, 2); + FIntVector defaultValue(1, 2, 3); + + classProperty.noData = {noData[0], noData[1], noData[2]}; + classProperty.defaultProperty = { + defaultValue[0], + defaultValue[1], + defaultValue[2]}; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 3; + image.bytesPerChannel = 1; + + std::vector values{ + glm::i8vec3(1, 1, -1), + glm::i8vec3(-1, -1, 2), + glm::i8vec3(0, 4, 2), + glm::i8vec3(10, 8, 5)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + FIntVector expected; + if (values[i] == noData) { + expected = defaultValue; + } else { + expected = FIntVector(values[i][0], values[i][1], values[i][2]); + } + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntVector( + property, + texCoords[i], + FIntVector(0)), + expected); + } + }); + }); + + Describe("GetVector", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector( + property, + FVector2D::Zero(), + FVector::Zero()), + FVector::Zero()); + }); + + It("gets from normalized glm::i8vec3 property", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1, 2}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::INT8; + classProperty.normalized = true; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 3; + image.bytesPerChannel = 1; + + std::vector values{ + glm::i8vec3(1, 1, -1), + glm::i8vec3(-1, -1, 2), + glm::i8vec3(0, 4, 2), + glm::i8vec3(10, 8, 5)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + TestTrue( + "IsNormalized", + UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized( + property)); + + for (size_t i = 0; i < texCoords.size(); i++) { + glm::dvec3 expected = + glm::dvec3(values[i][0], values[i][1], values[i][2]) / 127.0; + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector( + property, + texCoords[i], + FVector::Zero()), + FVector(expected[0], expected[1], expected[2])); + } + }); + + It("converts unnormalized glm::i8vec3 values", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1, 2}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 3; + image.bytesPerChannel = 1; + + std::vector values{ + glm::i8vec3(1, 1, -1), + glm::i8vec3(-1, -1, 2), + glm::i8vec3(0, 4, 2), + glm::i8vec3(10, 8, 5)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector( + property, + texCoords[i], + FVector::Zero()), + FVector(values[i][0], values[i][1], values[i][2])); + } + }); + + It("gets with offset / scale", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1, 2}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + FVector offset(1.0, 2.0, 3.0); + FVector scale(0.5, -1.0, 2.0); + + classProperty.offset = {offset[0], offset[1], offset[2]}; + classProperty.scale = {scale[0], scale[1], scale[2]}; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 3; + image.bytesPerChannel = 1; + + std::vector values{ + glm::u8vec3(0, 128, 255), + glm::u8vec3(255, 255, 255), + glm::u8vec3(10, 20, 30), + glm::u8vec3(128, 0, 0)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + FVector expected( + static_cast(values[i][0]) / 255.0 * scale[0] + offset[0], + static_cast(values[i][1]) / 255.0 * scale[1] + offset[1], + static_cast(values[i][2]) / 255.0 * scale[2] + offset[2]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector( + property, + texCoords[i], + FVector::Zero()), + expected); + } + }); + }); + + Describe("GetVector4", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector4( + property, + FVector2D::Zero(), + FVector4::Zero()), + FVector4::Zero()); + }); + + It("gets from normalized glm::i8vec4 property", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1, 2, 3}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC4; + classProperty.componentType = ClassProperty::ComponentType::INT8; + classProperty.normalized = true; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{ + glm::i8vec4(1, 1, -1, 1), + glm::i8vec4(-1, -1, 2, 0), + glm::i8vec4(0, 4, 2, -8), + glm::i8vec4(10, 8, 5, 27)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + TestTrue( + "IsNormalized", + UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized( + property)); + + for (size_t i = 0; i < texCoords.size(); i++) { + glm::dvec4 expected( + values[i][0], + values[i][1], + values[i][2], + values[i][3]); + expected /= 127.0; + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector( + property, + texCoords[i], + FVector4::Zero()), + FVector4(expected[0], expected[1], expected[2], expected[3])); + } + }); + + It("converts unnormalized glm::i8vec4 values", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1, 2, 3}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC4; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{ + glm::i8vec4(-1, 2, 5, 8), + glm::i8vec4(-1, -1, 2, 0), + glm::i8vec4(3, 5, 7, 0), + glm::i8vec4(1, -1, -2, 5)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + glm::dvec4 expected( + values[i][0], + values[i][1], + values[i][2], + values[i][3]); + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector4( + property, + texCoords[i], + FVector4::Zero()), + FVector4(expected[0], expected[1], expected[2], expected[3])); + } + }); + + It("gets with offset / scale", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1, 2, 3}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC4; + classProperty.componentType = ClassProperty::ComponentType::INT8; + classProperty.normalized = true; + + FVector4 offset(1.0, 2.0, 3.0, -1.0); + FVector4 scale(0.5, -1.0, 2.0, 3.5); + + classProperty.offset = {offset[0], offset[1], offset[2], offset[3]}; + classProperty.scale = {scale[0], scale[1], scale[2], scale[3]}; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{ + glm::i8vec4(1, 1, -1, 1), + glm::i8vec4(-1, -1, 2, 0), + glm::i8vec4(0, 4, 2, -8), + glm::i8vec4(10, 8, 5, 27)}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + FVector4 expected( + values[i][0] / 127.0 * scale[0] + offset[0], + values[i][1] / 127.0 * scale[1] + offset[1], + values[i][2] / 127.0 * scale[2] + offset[2], + values[i][3] / 127.0 * scale[3] + offset[3]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector( + property, + texCoords[i], + FVector4::Zero()), + expected); + } + }); + }); + + Describe("GetArray", [this]() { + It("returns empty array for non-array property", [this]() { + PropertyTextureProperty propertyTextureProperty; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{1, 2, 3, 4}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + FCesiumPropertyArray array = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArray( + property, + FVector2D::Zero()); + TestEqual( + "array size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + 0); + FCesiumMetadataValueType valueType; // Unknown type + TestTrue( + "array type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + }); + + It("returns empty array for invalid property", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + + FCesiumPropertyArray array = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArray( + property, + FVector2D::Zero()); + TestEqual( + "array size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + 0); + FCesiumMetadataValueType valueType; // Unknown type + TestTrue( + "array type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + }); + + It("returns array for fixed-length array property", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.array = true; + classProperty.count = 2; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 2; + image.bytesPerChannel = 1; + + std::vector values{1, 2, 3, 4, 5, 6, 7, 8}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView> propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + TestEqual( + "ArraySize", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( + property), + *classProperty.count); + + for (size_t i = 0; i < texCoords.size(); i++) { + FCesiumPropertyArray array = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArray( + property, + texCoords[i]); + int64 arraySize = UCesiumPropertyArrayBlueprintLibrary::GetSize(array); + TestEqual("array size", arraySize, *classProperty.count); + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Uint8, + false); + TestTrue( + "array element type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + + int64 arrayOffset = i * arraySize; + for (int64 j = 0; j < arraySize; j++) { + std::string label( + "array" + std::to_string(i) + " value" + std::to_string(j)); + FCesiumMetadataValue value = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, j); + TestEqual( + label.c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[static_cast(arrayOffset + j)]); + } + } + }); + + It("gets with noData value", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.array = true; + classProperty.count = 2; + classProperty.noData = {0, 0}; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 2; + image.bytesPerChannel = 1; + + std::vector values{1, 2, 3, 4, 5, 6, 0, 0}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView> propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + TestEqual( + "ArraySize", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( + property), + *classProperty.count); + + for (size_t i = 0; i < texCoords.size() - 1; i++) { + FCesiumPropertyArray array = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArray( + property, + texCoords[i]); + int64 arraySize = UCesiumPropertyArrayBlueprintLibrary::GetSize(array); + TestEqual("array size", arraySize, *classProperty.count); + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Uint8, + false); + TestTrue( + "array element type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + + int64 arrayOffset = i * arraySize; + for (int64 j = 0; j < arraySize; j++) { + std::string label( + "array" + std::to_string(i) + " value" + std::to_string(j)); + FCesiumMetadataValue value = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, j); + TestEqual( + label.c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[static_cast(arrayOffset + j)]); + } + } + + // Check that the "no data" value resolves to an empty array of an invalid + // type. + FCesiumPropertyArray array = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArray( + property, + texCoords[texCoords.size() - 1]); + TestEqual( + "array size", + UCesiumPropertyArrayBlueprintLibrary::GetSize(array), + static_cast(0)); + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Invalid, + ECesiumMetadataComponentType::None, + false); + TestTrue( + "array element type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + }); + + It("gets with noData / default value", [this]() { + PropertyTextureProperty propertyTextureProperty; + propertyTextureProperty.channels = {0, 1}; + + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.array = true; + classProperty.count = 2; + classProperty.noData = {0, 0}; + classProperty.defaultProperty = {10, 20}; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 2; + image.bytesPerChannel = 1; + + std::vector values{1, 2, 3, 4, 5, 6, 0, 0}; + image.pixelData = GetValuesAsBytes(values); + + PropertyTexturePropertyView> propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + TestEqual( + "ArraySize", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( + property), + *classProperty.count); + + for (size_t i = 0; i < texCoords.size(); i++) { + FCesiumPropertyArray array = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetArray( + property, + texCoords[i]); + int64 arraySize = UCesiumPropertyArrayBlueprintLibrary::GetSize(array); + TestEqual("array size", arraySize, *classProperty.count); + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Uint8, + false); + TestTrue( + "array element type", + UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == + valueType); + + if (i == texCoords.size() - 1) { + std::string label("array" + std::to_string(i)); + // Check that the "no data" value resolves to the default array value. + FCesiumMetadataValue value0 = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 0); + TestEqual( + label.c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value0, 0), + 10); + FCesiumMetadataValue value1 = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, 1); + TestEqual( + label.c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value1, 0), + 20); + } else { + int64 arrayOffset = i * arraySize; + for (int64 j = 0; j < arraySize; j++) { + std::string label( + "array" + std::to_string(i) + " value" + std::to_string(j)); + FCesiumMetadataValue value = + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, j); + TestEqual( + label.c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[static_cast(arrayOffset + j)]); + } + } + } + }); + }); + + Describe("GetValue", [this]() { + It("returns empty value for invalid property", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "PropertyTexturePropertyStatus", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + + FCesiumMetadataValue value = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValue( + property, + FVector2D::Zero()); + FCesiumMetadataValueType valueType; // Unknown type + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + }); + + It("gets value", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{1, 2, 3, 4}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + false); + for (size_t i = 0; i < texCoords.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValue( + property, + texCoords[i]); + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[i]); + } + }); + + It("gets with offset / scale", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + float offset = 1.0f; + float scale = 2.0f; + + classProperty.offset = offset; + classProperty.scale = scale; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{-1.1f, 2.0f, -3.5f, 4.0f}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Float32, + false); + for (size_t i = 0; i < texCoords.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValue( + property, + texCoords[i]); + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetFloat(value, 0), + values[i] * scale + offset); + } + }); + + It("gets with noData", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + int32_t noData = -1; + classProperty.noData = noData; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{-1, 2, -3, 4}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + false); + for (size_t i = 0; i < texCoords.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValue( + property, + texCoords[i]); + if (values[i] == noData) { + // Empty value indicated by invalid value type. + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + FCesiumMetadataValueType()); + } else { + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[i]); + } + } + }); + + It("gets with noData / default value", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT32; + + int32_t noData = -1; + int32_t defaultValue = 15; + + classProperty.noData = noData; + classProperty.defaultProperty = defaultValue; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{-1, 2, -3, 4}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int32, + false); + for (size_t i = 0; i < texCoords.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyTexturePropertyBlueprintLibrary::GetValue( + property, + texCoords[i]); + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + if (values[i] == noData) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + defaultValue); + } else { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[i]); + } + } + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp new file mode 100644 index 0000000..0d65eb8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -0,0 +1,170 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "CesiumSceneGeneration.h" + +#include "Tests/AutomationEditorCommon.h" + +#include "GameFramework/PlayerStart.h" +#include "LevelEditorViewport.h" + +#include "Cesium3DTileset.h" +#include "CesiumGeoreference.h" +#include "CesiumSunSky.h" +#include "GlobeAwareDefaultPawn.h" + +#include "CesiumTestHelpers.h" + +namespace Cesium { + +FString SceneGenerationContext::testIonToken( + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIwNzA3YWIzNS0xMjI5LTQ3MWEtOTgyNS05OTk0YThlOTE4NzMiLCJpZCI6MjU5LCJpYXQiOjE3Mjc3MzgxNjJ9.vll2Xe-NPuNPiC0KSe8uN7hgG-ldlalcXfdDBxxDkXY"); + +void SceneGenerationContext::setCommonProperties( + const FVector& origin, + const FVector& position, + const FRotator& rotation, + float fieldOfView) { + startPosition = position; + startRotation = rotation; + startFieldOfView = fieldOfView; + + georeference->SetOriginLongitudeLatitudeHeight(origin); + + pawn->SetActorLocation(startPosition); + pawn->SetActorRotation(startRotation); + + TInlineComponentArray cameras; + pawn->GetComponents(cameras); + for (UCameraComponent* cameraComponent : cameras) + cameraComponent->SetFieldOfView(startFieldOfView); +} + +void SceneGenerationContext::refreshTilesets() { + std::vector::iterator it; + for (it = tilesets.begin(); it != tilesets.end(); ++it) + (*it)->RefreshTileset(); +} + +void SceneGenerationContext::setSuspendUpdate(bool suspend) { + std::vector::iterator it; + for (it = tilesets.begin(); it != tilesets.end(); ++it) + (*it)->SuspendUpdate = suspend; +} + +void SceneGenerationContext::setMaximumSimultaneousTileLoads(int value) { + std::vector::iterator it; + for (it = tilesets.begin(); it != tilesets.end(); ++it) + (*it)->MaximumSimultaneousTileLoads = value; +} + +bool SceneGenerationContext::areTilesetsDoneLoading() { + if (tilesets.empty()) + return false; + + std::vector::const_iterator it; + for (it = tilesets.begin(); it != tilesets.end(); ++it) { + ACesium3DTileset* tileset = *it; + + int progress = (int)tileset->GetLoadProgress(); + if (progress != 100) { + // We aren't done + return false; + } + } + return true; +} + +void SceneGenerationContext::trackForPlay() { + CesiumTestHelpers::trackForPlay(sunSky); + CesiumTestHelpers::trackForPlay(georeference); + CesiumTestHelpers::trackForPlay(pawn); + + std::vector::iterator it; + for (it = tilesets.begin(); it != tilesets.end(); ++it) { + ACesium3DTileset* tileset = *it; + CesiumTestHelpers::trackForPlay(tileset); + } +} + +void SceneGenerationContext::initForPlay( + SceneGenerationContext& creationContext) { + world = GEditor->PlayWorld; + sunSky = CesiumTestHelpers::findInPlay(creationContext.sunSky); + georeference = CesiumTestHelpers::findInPlay(creationContext.georeference); + pawn = CesiumTestHelpers::findInPlay(creationContext.pawn); + + startPosition = creationContext.startPosition; + startRotation = creationContext.startRotation; + startFieldOfView = creationContext.startFieldOfView; + + tilesets.clear(); + + std::vector& creationTilesets = creationContext.tilesets; + std::vector::iterator it; + for (it = creationTilesets.begin(); it != creationTilesets.end(); ++it) { + ACesium3DTileset* creationTileset = *it; + ACesium3DTileset* tileset = CesiumTestHelpers::findInPlay(creationTileset); + tilesets.push_back(tileset); + } +} + +void SceneGenerationContext::syncWorldCamera() { + assert(GEditor); + + if (GEditor->IsPlayingSessionInEditor()) { + // If in PIE, set the player + assert(world->GetNumPlayerControllers() == 1); + + APlayerController* controller = world->GetFirstPlayerController(); + assert(controller); + + controller->ClientSetLocation(startPosition, startRotation); + + APlayerCameraManager* cameraManager = controller->PlayerCameraManager; + assert(cameraManager); + + cameraManager->SetFOV(startFieldOfView); + } else { + // If editing, set any viewports + for (FLevelEditorViewportClient* ViewportClient : + GEditor->GetLevelViewportClients()) { + if (ViewportClient == NULL) + continue; + ViewportClient->SetViewLocation(startPosition); + ViewportClient->SetViewRotation(startRotation); + if (ViewportClient->ViewportType == LVT_Perspective) + ViewportClient->ViewFOV = startFieldOfView; + ViewportClient->Invalidate(); + } + } +} + +void createCommonWorldObjects(SceneGenerationContext& context) { + + context.world = FAutomationEditorCommonUtils::CreateNewMap(); + + context.sunSky = context.world->SpawnActor(); + + APlayerStart* playerStart = context.world->SpawnActor(); + + FSoftObjectPath objectPath( + TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); + TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); + + context.georeference = + ACesiumGeoreference::GetDefaultGeoreference(context.world); + context.pawn = context.world->SpawnActor( + Cast(DynamicPawn.LoadSynchronous())); + + context.pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; + + AWorldSettings* pWorldSettings = context.world->GetWorldSettings(); + if (pWorldSettings) + pWorldSettings->bEnableWorldBoundsChecks = false; +} + +} // namespace Cesium + +#endif // #if WITH_EDITOR diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h new file mode 100644 index 0000000..7503e09 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h @@ -0,0 +1,51 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#if WITH_EDITOR + +#include + +class UWorld; +class ACesiumSunSky; +class ACesiumGeoreference; +class AGlobeAwareDefaultPawn; +class ACesium3DTileset; +class ACesiumCameraManager; + +namespace Cesium { + +struct SceneGenerationContext { + UWorld* world; + ACesiumSunSky* sunSky; + ACesiumGeoreference* georeference; + AGlobeAwareDefaultPawn* pawn; + std::vector tilesets; + + FVector startPosition; + FRotator startRotation; + float startFieldOfView; + + void setCommonProperties( + const FVector& origin, + const FVector& position, + const FRotator& rotation, + float fieldOfView); + + void refreshTilesets(); + void setSuspendUpdate(bool suspend); + void setMaximumSimultaneousTileLoads(int32 value); + bool areTilesetsDoneLoading(); + + void trackForPlay(); + void initForPlay(SceneGenerationContext& creationContext); + void syncWorldCamera(); + + static FString testIonToken; +}; + +void createCommonWorldObjects(SceneGenerationContext& context); + +}; // namespace Cesium + +#endif // #if WITH_EDITOR diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.cpp new file mode 100644 index 0000000..34dcdf0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.cpp @@ -0,0 +1,111 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumTestHelpers.h" +#include "CesiumGeoreference.h" +#include "Engine/Engine.h" + +#if WITH_EDITOR +#include "Editor/EditorPerformanceSettings.h" +#include "Interfaces/IPluginManager.h" +#endif + +namespace CesiumTestHelpers { + +UWorld* getGlobalWorldContext() { + const TIndirectArray& worldContexts = + GEngine->GetWorldContexts(); + FWorldContext firstWorldContext = worldContexts[0]; + return firstWorldContext.World(); +} + +void TestRotatorsAreEquivalent( + FAutomationTestBase* pSpec, + ACesiumGeoreference* pGeoreferenceExpected, + const FRotator& rotatorExpected, + ACesiumGeoreference* pGeoreferenceActual, + const FRotator& rotatorActual) { + FVector xEcefExpected = + pGeoreferenceExpected->TransformUnrealDirectionToEarthCenteredEarthFixed( + rotatorExpected.RotateVector(FVector::XAxisVector)); + FVector yEcefExpected = + pGeoreferenceExpected->TransformUnrealDirectionToEarthCenteredEarthFixed( + rotatorExpected.RotateVector(FVector::YAxisVector)); + FVector zEcefExpected = + pGeoreferenceExpected->TransformUnrealDirectionToEarthCenteredEarthFixed( + rotatorExpected.RotateVector(FVector::ZAxisVector)); + + FVector xEcefActual = + pGeoreferenceActual->TransformUnrealDirectionToEarthCenteredEarthFixed( + rotatorActual.RotateVector(FVector::XAxisVector)); + FVector yEcefActual = + pGeoreferenceActual->TransformUnrealDirectionToEarthCenteredEarthFixed( + rotatorActual.RotateVector(FVector::YAxisVector)); + FVector zEcefActual = + pGeoreferenceActual->TransformUnrealDirectionToEarthCenteredEarthFixed( + rotatorActual.RotateVector(FVector::ZAxisVector)); + + pSpec->TestEqual("xEcefActual", xEcefActual, xEcefExpected); + pSpec->TestEqual("yEcefActual", yEcefActual, yEcefExpected); + pSpec->TestEqual("zEcefActual", zEcefActual, zEcefExpected); +} + +void waitForNextFrame( + const FDoneDelegate& done, + UWorld* pWorld, + float timeoutSeconds) { + uint64 start = GFrameCounter; + waitFor(done, pWorld, timeoutSeconds, [start]() { + uint64 current = GFrameCounter; + return current > start; + }); +} + +FName getUniqueTag(AActor* pActor) { + return FName(FString::Printf(TEXT("%lld"), pActor)); +} + +FName getUniqueTag(UActorComponent* pComponent) { + return FName(FString::Printf(TEXT("%lld"), pComponent)); +} + +#if WITH_EDITOR +namespace { +size_t timesAllowingEditorTick = 0; +bool originalEditorTickState = true; +} // namespace +#endif + +void pushAllowTickInEditor() { +#if WITH_EDITOR + if (timesAllowingEditorTick == 0) { + UEditorPerformanceSettings* pSettings = + GetMutableDefault(); + originalEditorTickState = pSettings->bThrottleCPUWhenNotForeground; + pSettings->bThrottleCPUWhenNotForeground = false; + } + + ++timesAllowingEditorTick; +#endif +} + +void popAllowTickInEditor() { +#if WITH_EDITOR + --timesAllowingEditorTick; + if (timesAllowingEditorTick == 0) { + UEditorPerformanceSettings* pSettings = + GetMutableDefault(); + pSettings->bThrottleCPUWhenNotForeground = originalEditorTickState; + } +#endif +} + +void trackForPlay(AActor* pEditorActor) { + pEditorActor->Tags.Add(getUniqueTag(pEditorActor)); +} + +void trackForPlay(UActorComponent* pEditorComponent) { + trackForPlay(pEditorComponent->GetOwner()); + pEditorComponent->ComponentTags.Add(getUniqueTag(pEditorComponent)); +} + +} // namespace CesiumTestHelpers diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h new file mode 100644 index 0000000..932eebd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h @@ -0,0 +1,217 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumRuntime.h" +#include "EngineUtils.h" +#include "Kismet/GameplayStatics.h" +#include "Math/MathFwd.h" +#include "Misc/AutomationTest.h" +#include "TimerManager.h" + +#if WITH_EDITOR +#include "Editor.h" +#endif + +class UWorld; +class ACesiumGeoreference; + +namespace CesiumTestHelpers { + +UWorld* getGlobalWorldContext(); + +/// +/// Verify that two rotations (expressed relative to two different +/// georeferences) are equivalent by using them to rotate the principal axis +/// vectors and then transforming those vectors to ECEF. The ECEF vectors should +/// be the same in both cases. +/// +void TestRotatorsAreEquivalent( + FAutomationTestBase* pSpec, + ACesiumGeoreference* pGeoreferenceExpected, + const FRotator& rotatorExpected, + ACesiumGeoreference* pGeoreferenceActual, + const FRotator& rotatorActual); + +template +void waitForImpl( + const FDoneDelegate& done, + UWorld* pWorld, + T&& condition, + FTimerHandle& timerHandle) { + if (condition()) { + pWorld->GetTimerManager().ClearTimer(timerHandle); + done.Execute(); + } else if (pWorld->GetTimerManager().GetTimerRemaining(timerHandle) <= 0.0f) { + // Timeout + UE_LOG( + LogCesium, + Error, + TEXT("Timed out waiting for a condition to become true.")); + pWorld->GetTimerManager().ClearTimer(timerHandle); + done.Execute(); + } else { + pWorld->GetTimerManager().SetTimerForNextTick( + [done, + pWorld, + condition = std::forward(condition), + timerHandle]() mutable { + waitForImpl(done, pWorld, std::move(condition), timerHandle); + }); + } +} + +/// +/// Waits for a provided lambda function to become true, ticking through render +/// frames in the meantime. If the timeout elapses before the condition becomes +/// true, an error is logged (which will cause a test failure) and the done +/// delegate is invoked anyway. +/// +/// +/// The done delegate provided by a LatentIt or +/// LatentBeforeEach. It will be invoked when the condition is true or when the +/// timeout elapses. +/// The world in which to check the condition. +/// The maximum time to wait for the condition to +/// become true. +/// A lambda that is invoked each +/// frame. If this function returns false, waiting continues. +template +void waitFor( + const FDoneDelegate& done, + UWorld* pWorld, + float timeoutSeconds, + T&& condition) { + FTimerHandle timerHandle; + pWorld->GetTimerManager().SetTimer(timerHandle, timeoutSeconds, false); + waitForImpl(done, pWorld, std::forward(condition), timerHandle); +} + +void waitForNextFrame( + const FDoneDelegate& done, + UWorld* pWorld, + float timeoutSeconds); + +/// +/// Gets the first Actor that has a given tag. +/// +/// The Actor type. +/// The world in which to search for the Actor. +/// The tag to look for. +/// The Actor, or nullptr if it does not exist. +template T* getActorWithTag(UWorld* pWorld, const FName& tag) { + TArray temp; + UGameplayStatics::GetAllActorsWithTag(pWorld, tag, temp); + if (temp.Num() < 1) + return nullptr; + + return Cast(temp[0]); +} + +/// +/// Gets the first ActorComponent that has a given tag. +/// +/// The ActorComponent type. +/// The Actor whose components to search. +/// The tag to look for. +/// The ActorComponent, or nullptr if it does not exist. +template T* getComponentWithTag(AActor* pOwner, const FName& tag) { + TArray components = + pOwner->GetComponentsByTag(T::StaticClass(), tag); + if (components.Num() < 1) + return nullptr; + + return Cast(components[0]); +} + +/// +/// Gets a tag that can be used to uniquely identify a given Actor. +/// +/// The actor. +/// The unique tag. +FName getUniqueTag(AActor* pActor); + +/// +/// Gets a tag that can be used to uniquely identify a given ActorComponent. +/// +/// The actor. +/// The unique tag. +FName getUniqueTag(UActorComponent* pComponent); + +/// +/// By default, UE 5.3+ don't tick in a headless Editor, which is often used to +/// run tests. Call this at the start of a test that requires ticking to +/// override this default. Call popAllowTickInEditor after the test to restore +/// the default. +/// +void pushAllowTickInEditor(); + +/// +/// Call this after a test that needs working ticking to restore the default +/// state. +/// +void popAllowTickInEditor(); + +#if WITH_EDITOR + +/// +/// Tracks a provided Edit-mode Actor, so the equivalent object can later be +/// found in Play mode. +/// +/// The Actor in the Editor world to track. +void trackForPlay(AActor* pEditorActor); + +/// +/// Tracks a provided Edit-mode ActorComponent, so the equivalent object can +/// later be found in Play mode. +/// +/// The ActorComponent in the Editor world to +/// track. +void trackForPlay(UActorComponent* pEditorComponent); + +/// +/// Finds a Play-mode object equivalent to a given Editor-mode one that was +/// previously tracked with . This works on instances +/// derived from AActor and UActorComponent. +/// +/// The type of the object to find. +/// The Editor object for which to find a Play-mode +/// equivalent. +/// The play mode equivalent, or nullptr is one is not found. +template T* findInPlay(T* pEditorObject) { + if (!IsValid(pEditorObject)) + return nullptr; + + UWorld* pWorld = GEditor->PlayWorld; + if constexpr (std::is_base_of_v) { + return getActorWithTag(pWorld, getUniqueTag(pEditorObject)); + } else if constexpr (std::is_base_of_v) { + AActor* pEditorOwner = pEditorObject->GetOwner(); + if (!pEditorOwner) + return nullptr; + AActor* pPlayOwner = findInPlay(pEditorOwner); + if (!pPlayOwner) + return nullptr; + return getComponentWithTag(pPlayOwner, getUniqueTag(pEditorObject)); + } else { + return nullptr; + } +} + +/// +/// Finds a Play-mode object equivalent to a given Editor-mode one that was +/// previously tracked with . This works on instances +/// derived from AActor and UActorComponent. +/// +/// The type of the object to find. +/// The Editor object for which to find a Play-mode +/// equivalent. +/// The play mode equivalent, or nullptr is one is +/// not found. +template T* findInPlay(TObjectPtr pEditorObject) { + return findInPlay(pEditorObject.Get()); +} + +#endif // #if WITH_EDITOR + +} // namespace CesiumTestHelpers diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumTextureUtility.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumTextureUtility.spec.cpp new file mode 100644 index 0000000..fea05be --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumTextureUtility.spec.cpp @@ -0,0 +1,547 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumTextureUtility.h" +#include "CesiumAsync/AsyncSystem.h" +#include "ExtensionImageAssetUnreal.h" +#include "Misc/AutomationTest.h" +#include "RenderingThread.h" +#include +#include +#include + +using namespace CesiumTextureUtility; +using namespace CesiumUtility; + +BEGIN_DEFINE_SPEC( + CesiumTextureUtilitySpec, + "Cesium.Unit.CesiumTextureUtility", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter | EAutomationTestFlags::NonNullRHI) +std::vector originalPixels; +std::vector originalMipPixels; +std::vector expectedMipPixelsIfGenerated; +CesiumUtility::IntrusivePointer pImageAsset; + +void RunTests(); + +void CheckPixels( + const IntrusivePointer& pRefCountedTexture, + bool requireMips = false); +void CheckSRGB( + const IntrusivePointer& pRefCountedTexture, + bool expectedSRGB); +void CheckAddress( + const IntrusivePointer& pRefCountedTexture, + TextureAddress expectedAddressX, + TextureAddress expectedAddressY); +void CheckFilter( + const IntrusivePointer& pRefCountedTexture, + TextureFilter expectedFilter); +void CheckGroup( + const IntrusivePointer& pRefCountedTexture, + TextureGroup expectedGroup); +END_DEFINE_SPEC(CesiumTextureUtilitySpec) + +void CesiumTextureUtilitySpec::Define() { + Describe("Without Mips", [this]() { + BeforeEach([this]() { + originalPixels = {0x20, 0x40, 0x80, 0xF0, 0x21, 0x41, 0x81, 0xF1, + 0x22, 0x42, 0x82, 0xF2, 0x23, 0x43, 0x83, 0xF3, + 0x24, 0x44, 0x84, 0xF4, 0x25, 0x45, 0x85, 0xF5}; + originalMipPixels.clear(); + + pImageAsset.emplace(); + pImageAsset->width = 3; + pImageAsset->height = 2; + TestEqual( + "image buffer size is correct", + originalPixels.size(), + pImageAsset->width * pImageAsset->height * + pImageAsset->bytesPerChannel * pImageAsset->channels); + pImageAsset->pixelData.resize(originalPixels.size()); + + std::memcpy( + pImageAsset->pixelData.data(), + originalPixels.data(), + originalPixels.size()); + + CesiumUtility::IntrusivePointer pCopy = + new CesiumGltf::ImageAsset(*pImageAsset); + CesiumGltfReader::ImageDecoder::generateMipMaps(*pCopy); + + expectedMipPixelsIfGenerated.clear(); + + if (pCopy->mipPositions.size() >= 2) { + expectedMipPixelsIfGenerated.resize(pCopy->mipPositions[1].byteSize); + for (size_t iSrc = pCopy->mipPositions[1].byteOffset, iDest = 0; + iDest < pCopy->mipPositions[1].byteSize; + ++iSrc, ++iDest) { + expectedMipPixelsIfGenerated[iDest] = uint8_t(pCopy->pixelData[iSrc]); + } + } + }); + + RunTests(); + }); + + Describe("With Mips", [this]() { + BeforeEach([this]() { + pImageAsset.emplace(); + pImageAsset->width = 3; + pImageAsset->height = 2; + + // Original image (3x2) + originalPixels = {0x20, 0x40, 0x80, 0xF0, 0x21, 0x41, 0x81, 0xF1, + 0x22, 0x42, 0x82, 0xF2, 0x23, 0x43, 0x83, 0xF3, + 0x24, 0x44, 0x84, 0xF4, 0x25, 0x45, 0x85, 0xF5}; + pImageAsset->mipPositions.emplace_back( + CesiumGltf::ImageAssetMipPosition{0, originalPixels.size()}); + + // Mip 1 (1x1) + originalMipPixels = {0x26, 0x46, 0x86, 0xF6}; + pImageAsset->mipPositions.emplace_back(CesiumGltf::ImageAssetMipPosition{ + pImageAsset->mipPositions[0].byteSize, + originalMipPixels.size()}); + + pImageAsset->pixelData.resize( + originalPixels.size() + originalMipPixels.size()); + std::memcpy( + pImageAsset->pixelData.data(), + originalPixels.data(), + originalPixels.size()); + std::memcpy( + pImageAsset->pixelData.data() + originalPixels.size(), + originalMipPixels.data(), + originalMipPixels.size()); + }); + + RunTests(); + }); +} + +void CesiumTextureUtilitySpec::RunTests() { + It("ImageAsset non-sRGB", [this]() { + TUniquePtr pHalfLoaded = loadTextureAnyThreadPart( + *pImageAsset, + TextureAddress::TA_Mirror, + TextureAddress::TA_Wrap, + TextureFilter::TF_Bilinear, + true, + TextureGroup::TEXTUREGROUP_Cinematic, + false, + std::nullopt); + TestNotNull("pHalfLoaded", pHalfLoaded.Get()); + + IntrusivePointer pRefCountedTexture = + loadTextureGameThreadPart(pHalfLoaded.Get()); + CheckPixels(pRefCountedTexture, true); + CheckSRGB(pRefCountedTexture, false); + CheckAddress( + pRefCountedTexture, + TextureAddress::TA_Mirror, + TextureAddress::TA_Wrap); + CheckFilter(pRefCountedTexture, TextureFilter::TF_Bilinear); + CheckGroup(pRefCountedTexture, TextureGroup::TEXTUREGROUP_Cinematic); + }); + + It("ImageAsset sRGB", [this]() { + TUniquePtr pHalfLoaded = loadTextureAnyThreadPart( + *pImageAsset, + TextureAddress::TA_Clamp, + TextureAddress::TA_Mirror, + TextureFilter::TF_Trilinear, + true, + TextureGroup::TEXTUREGROUP_Bokeh, + true, + std::nullopt); + TestNotNull("pHalfLoaded", pHalfLoaded.Get()); + + IntrusivePointer pRefCountedTexture = + loadTextureGameThreadPart(pHalfLoaded.Get()); + CheckPixels(pRefCountedTexture, true); + CheckSRGB(pRefCountedTexture, true); + CheckAddress( + pRefCountedTexture, + TextureAddress::TA_Clamp, + TextureAddress::TA_Mirror); + CheckFilter(pRefCountedTexture, TextureFilter::TF_Trilinear); + CheckGroup(pRefCountedTexture, TextureGroup::TEXTUREGROUP_Bokeh); + }); + + It("Image and Sampler", [this]() { + CesiumGltf::Sampler sampler; + sampler.minFilter = CesiumGltf::Sampler::MinFilter::NEAREST; + sampler.magFilter = CesiumGltf::Sampler::MagFilter::NEAREST; + sampler.wrapS = CesiumGltf::Sampler::WrapS::MIRRORED_REPEAT; + sampler.wrapT = CesiumGltf::Sampler::WrapT::CLAMP_TO_EDGE; + + TUniquePtr pHalfLoaded = + loadTextureFromImageAndSamplerAnyThreadPart( + *pImageAsset, + sampler, + false); + TestNotNull("pHalfLoaded", pHalfLoaded.Get()); + + IntrusivePointer pRefCountedTexture = + loadTextureGameThreadPart(pHalfLoaded.Get()); + CheckPixels(pRefCountedTexture, false); + CheckSRGB(pRefCountedTexture, false); + CheckAddress( + pRefCountedTexture, + TextureAddress::TA_Mirror, + TextureAddress::TA_Clamp); + CheckFilter(pRefCountedTexture, TextureFilter::TF_Nearest); + CheckGroup(pRefCountedTexture, TextureGroup::TEXTUREGROUP_World); + }); + + It("Model", [this]() { + CesiumGltf::Model model; + + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset = pImageAsset; + + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); + sampler.minFilter = CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR; + sampler.magFilter = CesiumGltf::Sampler::MagFilter::LINEAR; + sampler.wrapS = CesiumGltf::Sampler::WrapS::REPEAT; + sampler.wrapT = CesiumGltf::Sampler::WrapT::MIRRORED_REPEAT; + + CesiumGltf::Texture& texture = model.textures.emplace_back(); + texture.source = 0; + texture.sampler = 0; + + TUniquePtr pHalfLoaded = + loadTextureFromModelAnyThreadPart(model, texture, true); + TestNotNull("pHalfLoaded", pHalfLoaded.Get()); + TestNotNull("pHalfLoaded->pTexture", pHalfLoaded->pTexture.get()); + + IntrusivePointer pRefCountedTexture = + loadTextureGameThreadPart(model, pHalfLoaded.Get()); + CheckPixels(pRefCountedTexture, true); + CheckSRGB(pRefCountedTexture, true); + CheckAddress( + pRefCountedTexture, + TextureAddress::TA_Wrap, + TextureAddress::TA_Mirror); + CheckFilter(pRefCountedTexture, TextureFilter::TF_Default); + CheckGroup(pRefCountedTexture, TextureGroup::TEXTUREGROUP_World); + }); + + It("Two textures referencing one image", [this]() { + CesiumGltf::Model model; + + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset = pImageAsset; + + CesiumGltf::Sampler& sampler1 = model.samplers.emplace_back(); + sampler1.minFilter = CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR; + sampler1.magFilter = CesiumGltf::Sampler::MagFilter::LINEAR; + sampler1.wrapS = CesiumGltf::Sampler::WrapS::REPEAT; + sampler1.wrapT = CesiumGltf::Sampler::WrapT::MIRRORED_REPEAT; + + CesiumGltf::Texture& texture1 = model.textures.emplace_back(); + texture1.source = 0; + texture1.sampler = 0; + + CesiumGltf::Sampler& sampler2 = model.samplers.emplace_back(); + sampler2.minFilter = CesiumGltf::Sampler::MinFilter::NEAREST; + sampler2.magFilter = CesiumGltf::Sampler::MagFilter::NEAREST; + sampler2.wrapS = CesiumGltf::Sampler::WrapS::MIRRORED_REPEAT; + sampler2.wrapT = CesiumGltf::Sampler::WrapT::REPEAT; + + CesiumGltf::Texture& texture2 = model.textures.emplace_back(); + texture2.source = 0; + texture2.sampler = 1; + + TUniquePtr pHalfLoaded1 = + loadTextureFromModelAnyThreadPart(model, model.textures[0], true); + TestNotNull("pHalfLoaded1", pHalfLoaded1.Get()); + TestNotNull("pHalfLoaded1->pTexture", pHalfLoaded1->pTexture.get()); + + TUniquePtr pHalfLoaded2 = + loadTextureFromModelAnyThreadPart(model, model.textures[1], false); + TestNotNull("pHalfLoaded2", pHalfLoaded2.Get()); + TestNotNull("pHalfLoaded2->pTexture", pHalfLoaded2->pTexture.get()); + + IntrusivePointer pRefCountedTexture1 = + loadTextureGameThreadPart(model, pHalfLoaded1.Get()); + IntrusivePointer pRefCountedTexture2 = + loadTextureGameThreadPart(model, pHalfLoaded2.Get()); + + CheckPixels(pRefCountedTexture1, true); + CheckSRGB(pRefCountedTexture1, true); + CheckAddress( + pRefCountedTexture1, + TextureAddress::TA_Wrap, + TextureAddress::TA_Mirror); + CheckFilter(pRefCountedTexture1, TextureFilter::TF_Default); + CheckGroup(pRefCountedTexture1, TextureGroup::TEXTUREGROUP_World); + + CheckPixels(pRefCountedTexture2, false); + CheckSRGB(pRefCountedTexture2, false); + CheckAddress( + pRefCountedTexture2, + TextureAddress::TA_Mirror, + TextureAddress::TA_Wrap); + CheckFilter(pRefCountedTexture2, TextureFilter::TF_Nearest); + CheckGroup(pRefCountedTexture2, TextureGroup::TEXTUREGROUP_World); + + TestEqual( + "Textures share RHI resource", + pRefCountedTexture1->getUnrealTexture()->GetResource()->GetTextureRHI(), + pRefCountedTexture2->getUnrealTexture() + ->GetResource() + ->GetTextureRHI()); + }); + + It("Loading the same texture twice", [this]() { + CesiumGltf::Model model; + + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset = pImageAsset; + + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); + sampler.minFilter = CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR; + sampler.magFilter = CesiumGltf::Sampler::MagFilter::LINEAR; + sampler.wrapS = CesiumGltf::Sampler::WrapS::REPEAT; + sampler.wrapT = CesiumGltf::Sampler::WrapT::MIRRORED_REPEAT; + + CesiumGltf::Texture& texture = model.textures.emplace_back(); + texture.source = 0; + texture.sampler = 0; + + TUniquePtr pHalfLoaded = + loadTextureFromModelAnyThreadPart(model, texture, true); + TestNotNull("pHalfLoaded", pHalfLoaded.Get()); + TestNotNull("pHalfLoaded->pTexture", pHalfLoaded->pTexture.get()); + + IntrusivePointer pRefCountedTexture = + loadTextureGameThreadPart(model, pHalfLoaded.Get()); + CheckPixels(pRefCountedTexture, true); + CheckSRGB(pRefCountedTexture, true); + CheckAddress( + pRefCountedTexture, + TextureAddress::TA_Wrap, + TextureAddress::TA_Mirror); + CheckFilter(pRefCountedTexture, TextureFilter::TF_Default); + CheckGroup(pRefCountedTexture, TextureGroup::TEXTUREGROUP_World); + + // Copy the model and load the same texture again. + // This time there's no more pixel data, so it's necessary to use the + // previously-created texture. + CesiumGltf::Model model2 = model; + TUniquePtr pHalfLoaded2 = + loadTextureFromModelAnyThreadPart(model2, model.textures[0], true); + TestNotNull("pHalfLoaded2", pHalfLoaded2.Get()); + TestNotNull("pHalfLoaded2->pTexture", pHalfLoaded2->pTexture.get()); + TestNull( + "pHalfLoaded2->pTexture->getTextureResource()", + pHalfLoaded2->pTexture->getTextureResource().Get()); + + IntrusivePointer pRefCountedTexture2 = + loadTextureGameThreadPart(model, pHalfLoaded.Get()); + TestEqual("Same textures", pRefCountedTexture2, pRefCountedTexture); + }); + + It("Loading the same texture twice from one model", [this]() { + CesiumGltf::Model model; + + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset = pImageAsset; + + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); + sampler.minFilter = CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR; + sampler.magFilter = CesiumGltf::Sampler::MagFilter::LINEAR; + sampler.wrapS = CesiumGltf::Sampler::WrapS::REPEAT; + sampler.wrapT = CesiumGltf::Sampler::WrapT::MIRRORED_REPEAT; + + CesiumGltf::Texture& texture = model.textures.emplace_back(); + texture.source = 0; + texture.sampler = 0; + + TUniquePtr pHalfLoaded = + loadTextureFromModelAnyThreadPart(model, texture, true); + TestNotNull("pHalfLoaded", pHalfLoaded.Get()); + TestNotNull("pHalfLoaded->pTexture", pHalfLoaded->pTexture.get()); + + IntrusivePointer pRefCountedTexture = + loadTextureGameThreadPart(model, pHalfLoaded.Get()); + CheckPixels(pRefCountedTexture, true); + CheckSRGB(pRefCountedTexture, true); + CheckAddress( + pRefCountedTexture, + TextureAddress::TA_Wrap, + TextureAddress::TA_Mirror); + CheckFilter(pRefCountedTexture, TextureFilter::TF_Default); + CheckGroup(pRefCountedTexture, TextureGroup::TEXTUREGROUP_World); + + // Load the same texture again. + // This time there's no more pixel data, so it's necessary to use the + // previously-created texture. + TUniquePtr pHalfLoaded2 = + loadTextureFromModelAnyThreadPart(model, model.textures[0], true); + TestNotNull("pHalfLoaded2", pHalfLoaded2.Get()); + TestNotNull("pHalfLoaded2->pTexture", pHalfLoaded2->pTexture.get()); + TestNull( + "pHalfLoaded2->pTexture->getTextureResource()", + pHalfLoaded2->pTexture->getTextureResource().Get()); + + IntrusivePointer pRefCountedTexture2 = + loadTextureGameThreadPart(model, pHalfLoaded.Get()); + TestEqual("Same textures", pRefCountedTexture2, pRefCountedTexture); + }); +} + +void CesiumTextureUtilitySpec::CheckPixels( + const IntrusivePointer& pRefCountedTexture, + bool requireMips) { + TestNotNull("pRefCountedTexture", pRefCountedTexture.get()); + TestNotNull( + "pRefCountedTexture->getUnrealTexture()", + pRefCountedTexture->getUnrealTexture().Get()); + + UTexture2D* pTexture = pRefCountedTexture->getUnrealTexture(); + TestNotNull("pTexture", pTexture); + if (pTexture == nullptr) + return; + + FTextureResource* pResource = pTexture->GetResource(); + TestNotNull("pResource", pResource); + if (pResource == nullptr) + return; + + TArray readPixels; + TArray readPixelsMip1; + + ENQUEUE_RENDER_COMMAND(ReadSurfaceCommand) + ([pResource, &readPixels, &readPixelsMip1]( + FRHICommandListImmediate& RHICmdList) { + FRHITexture* pRHITexture = pResource->GetTextureRHI(); + if (pRHITexture == nullptr) + return; + + FReadSurfaceDataFlags flags{}; + flags.SetLinearToGamma(false); + RHICmdList + .ReadSurfaceData(pRHITexture, FIntRect(0, 0, 3, 2), readPixels, flags); + + if (pRHITexture->GetNumMips() > 1) { + flags.SetMip(1); + RHICmdList.ReadSurfaceData( + pRHITexture, + FIntRect(0, 0, 1, 1), + readPixelsMip1, + flags); + } + }); + FlushRenderingCommands(); + + TestEqual("read buffer size", readPixels.Num() * 4, originalPixels.size()); + for (size_t i = 0; i < readPixels.Num(); ++i) { + TestEqual("pixel-red", readPixels[i].R, originalPixels[i * 4]); + TestEqual("pixel-green", readPixels[i].G, originalPixels[i * 4 + 1]); + TestEqual("pixel-blue", readPixels[i].B, originalPixels[i * 4 + 2]); + TestEqual("pixel-alpha", readPixels[i].A, originalPixels[i * 4 + 3]); + } + + if (requireMips) { + TestTrue("Has Mips", !readPixelsMip1.IsEmpty()); + } + + if (!readPixelsMip1.IsEmpty()) { + std::vector& pixelsToMatch = originalMipPixels.empty() + ? expectedMipPixelsIfGenerated + : originalMipPixels; + + TestEqual( + "read buffer size", + readPixelsMip1.Num() * 4, + pixelsToMatch.size()); + for (size_t i = 0; + i < readPixelsMip1.Num() && (i * 4 + 3) < pixelsToMatch.size(); + ++i) { + TestEqual("mip pixel-red", readPixelsMip1[i].R, pixelsToMatch[i * 4]); + TestEqual( + "mip pixel-green", + readPixelsMip1[i].G, + pixelsToMatch[i * 4 + 1]); + TestEqual( + "mip pixel-blue", + readPixelsMip1[i].B, + pixelsToMatch[i * 4 + 2]); + TestEqual( + "mip pixel-alpha", + readPixelsMip1[i].A, + pixelsToMatch[i * 4 + 3]); + } + } +} + +void CesiumTextureUtilitySpec::CheckSRGB( + const IntrusivePointer& pRefCountedTexture, + bool expectedSRGB) { + TestNotNull("pRefCountedTexture", pRefCountedTexture.get()); + if (!pRefCountedTexture) + return; + + UTexture2D* pTexture = pRefCountedTexture->getUnrealTexture(); + TestNotNull("pTexture", pTexture); + if (!pTexture) + return; + + TestEqual("SRGB", pTexture->SRGB, expectedSRGB); + + FTextureResource* pResource = pTexture->GetResource(); + TestNotNull("pResource", pResource); + if (!pResource) + return; + + TestEqual("RHI sRGB", pResource->bSRGB, expectedSRGB); +} + +void CesiumTextureUtilitySpec::CheckAddress( + const IntrusivePointer& pRefCountedTexture, + TextureAddress expectedAddressX, + TextureAddress expectedAddressY) { + TestNotNull("pRefCountedTexture", pRefCountedTexture.get()); + if (!pRefCountedTexture) + return; + + UTexture2D* pTexture = pRefCountedTexture->getUnrealTexture(); + TestNotNull("pTexture", pTexture); + if (!pTexture) + return; + + TestEqual("AddressX", pTexture->AddressX, expectedAddressX); + TestEqual("AddressY", pTexture->AddressY, expectedAddressY); +} + +void CesiumTextureUtilitySpec::CheckFilter( + const IntrusivePointer& pRefCountedTexture, + TextureFilter expectedFilter) { + TestNotNull("pRefCountedTexture", pRefCountedTexture.get()); + if (!pRefCountedTexture) + return; + + UTexture2D* pTexture = pRefCountedTexture->getUnrealTexture(); + TestNotNull("pTexture", pTexture); + if (!pTexture) + return; + + TestEqual("Filter", pTexture->Filter, expectedFilter); +} + +void CesiumTextureUtilitySpec::CheckGroup( + const IntrusivePointer& pRefCountedTexture, + TextureGroup expectedGroup) { + TestNotNull("pRefCountedTexture", pRefCountedTexture.get()); + if (!pRefCountedTexture) + return; + + UTexture2D* pTexture = pRefCountedTexture->getUnrealTexture(); + TestNotNull("pTexture", pTexture); + if (!pTexture) + return; + + TestEqual("LODGroup", pTexture->LODGroup, expectedGroup); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/GeoTransforms.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/GeoTransforms.spec.cpp new file mode 100644 index 0000000..117f0b0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/GeoTransforms.spec.cpp @@ -0,0 +1,33 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "GeoTransforms.h" +#include "CesiumGeospatial/Ellipsoid.h" +#include "CesiumUtility/Math.h" +#include "Misc/AutomationTest.h" + +using namespace CesiumGeospatial; +using namespace CesiumUtility; + +BEGIN_DEFINE_SPEC( + FGeoTransformsSpec, + "Cesium.Unit.GeoTransforms", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +END_DEFINE_SPEC(FGeoTransformsSpec) + +void FGeoTransformsSpec::Define() { + Describe("TransformLongitudeLatitudeHeightToUnreal", [this]() { + It("returns the origin when given the origin LLH", [this]() { + GeoTransforms geotransforms{}; + glm::dvec3 center = geotransforms.TransformLongitudeLatitudeHeightToEcef( + glm::dvec3(12.0, 23.0, 1000.0)); + geotransforms.setCenter(center); + glm::dvec3 ue = geotransforms.TransformLongitudeLatitudeHeightToUnreal( + glm::dvec3(0.0), + glm::dvec3(12.0, 23.0, 1000.0)); + TestEqual("is at the origin", ue, glm::dvec3(0.0)); + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/GlobeAwareDefaultPawn.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/GlobeAwareDefaultPawn.spec.cpp new file mode 100644 index 0000000..8409847 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/GlobeAwareDefaultPawn.spec.cpp @@ -0,0 +1,351 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "GlobeAwareDefaultPawn.h" +#include "CesiumFlyToComponent.h" +#include "CesiumGeoreference.h" +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumTestHelpers.h" +#include "CesiumWgs84Ellipsoid.h" +#include "Editor.h" +#include "Engine/World.h" +#include "EngineUtils.h" +#include "Misc/AutomationTest.h" +#include "Tests/AutomationEditorCommon.h" + +BEGIN_DEFINE_SPEC( + FGlobeAwareDefaultPawnSpec, + "Cesium.Unit.GlobeAwareDefaultPawn", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) + +FDelegateHandle subscriptionPostPIEStarted; + +END_DEFINE_SPEC(FGlobeAwareDefaultPawnSpec) + +void FGlobeAwareDefaultPawnSpec::Define() { + const FVector philadelphiaEcef = + FVector(1253264.69280105, -4732469.91065521, 4075112.40412297); + + // The antipodal position from the philadelphia coordinates above + const FVector philadelphiaAntipodeEcef = + FVector(-1253369.920224856, 4732412.7444064, -4075146.2160252854); + + const FVector tokyoEcef = + FVector(-3960158.65587452, 3352568.87555906, 3697235.23506459); + + Describe( + "should not spike altitude when very close to final destination", + [this]() { + LatentBeforeEach( + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + UWorld* pWorld = FAutomationEditorCommonUtils::CreateNewMap(); + + AGlobeAwareDefaultPawn* pPawn = + pWorld->SpawnActor(); + UCesiumFlyToComponent* pFlyTo = + Cast(pPawn->AddComponentByClass( + UCesiumFlyToComponent::StaticClass(), + false, + FTransform::Identity, + false)); + pFlyTo->RotationToUse = + ECesiumFlyToRotation::ControlRotationInEastSouthUp; + + subscriptionPostPIEStarted = + FEditorDelegates::PostPIEStarted.AddLambda( + [done](bool isSimulating) { done.Execute(); }); + FRequestPlaySessionParams params{}; + GEditor->RequestPlaySession(params); + }); + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + FEditorDelegates::PostPIEStarted.Remove(subscriptionPostPIEStarted); + }); + AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() { + GEditor->RequestEndPlayMap(); + }); + It("", [this]() { + UWorld* pWorld = GEditor->PlayWorld; + + TActorIterator it(pWorld); + AGlobeAwareDefaultPawn* pPawn = *it; + UCesiumFlyToComponent* pFlyTo = + pPawn->FindComponentByClass(); + TestNotNull("pFlyTo", pFlyTo); + pFlyTo->Duration = 5.0f; + + UCesiumGlobeAnchorComponent* pGlobeAnchor = + pPawn->FindComponentByClass(); + TestNotNull("pGlobeAnchor", pGlobeAnchor); + + // Start flying somewhere else + pFlyTo->FlyToLocationLongitudeLatitudeHeight( + FVector(25.0, 10.0, 100.0), + 0.0, + 0.0, + false); + + // Tick almost to the end + Cast(pFlyTo)->TickComponent( + 4.9999f, + ELevelTick::LEVELTICK_All, + nullptr); + + // The height should be close to the final height. + FVector llh = pGlobeAnchor->GetLongitudeLatitudeHeight(); + TestTrue( + "Height is close to final height", + FMath::IsNearlyEqual(llh.Z, 100.0, 10.0)); + + pPawn->Destroy(); + }); + }); + + Describe( + "should interpolate between positions and rotations correctly", + [this, tokyoEcef, philadelphiaEcef, philadelphiaAntipodeEcef]() { + LatentBeforeEach( + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + UWorld* pWorld = FAutomationEditorCommonUtils::CreateNewMap(); + + AGlobeAwareDefaultPawn* pPawn = + pWorld->SpawnActor(); + UCesiumFlyToComponent* pFlyTo = + Cast(pPawn->AddComponentByClass( + UCesiumFlyToComponent::StaticClass(), + false, + FTransform::Identity, + false)); + pFlyTo->RotationToUse = + ECesiumFlyToRotation::ControlRotationInEastSouthUp; + + subscriptionPostPIEStarted = + FEditorDelegates::PostPIEStarted.AddLambda( + [done](bool isSimulating) { done.Execute(); }); + FRequestPlaySessionParams params{}; + GEditor->RequestPlaySession(params); + }); + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + FEditorDelegates::PostPIEStarted.Remove(subscriptionPostPIEStarted); + }); + AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() { + GEditor->RequestEndPlayMap(); + }); + It("should match the beginning and ending points of the fly-to", + [this]() { + UWorld* pWorld = GEditor->PlayWorld; + + TActorIterator it(pWorld); + AGlobeAwareDefaultPawn* pPawn = *it; + UCesiumFlyToComponent* pFlyTo = + pPawn->FindComponentByClass(); + TestNotNull("pFlyTo", pFlyTo); + pFlyTo->Duration = 5.0f; + + UCesiumGlobeAnchorComponent* pGlobeAnchor = + pPawn->FindComponentByClass(); + TestNotNull("pGlobeAnchor", pGlobeAnchor); + + pGlobeAnchor->MoveToLongitudeLatitudeHeight( + FVector(25.0, 10.0, 100.0)); + + // Start flying somewhere else + pFlyTo->FlyToLocationLongitudeLatitudeHeight( + FVector(25.0, 25.0, 100.0), + 0.0, + 0.0, + false); + + TestEqual( + "Location is the same as the start point", + pGlobeAnchor->GetLongitudeLatitudeHeight(), + FVector(25.0, 10.0, 100.0)); + + // Tick to the end + Cast(pFlyTo)->TickComponent( + 5.0f, + ELevelTick::LEVELTICK_All, + nullptr); + + TestEqual( + "Location is the same as the end point", + pGlobeAnchor->GetLongitudeLatitudeHeight(), + FVector(25.0, 25.0, 100.0)); + + pPawn->Destroy(); + }); + It("should correctly compute the midpoint of the flight", + [this, tokyoEcef, philadelphiaEcef]() { + UWorld* pWorld = GEditor->PlayWorld; + + TActorIterator it(pWorld); + AGlobeAwareDefaultPawn* pPawn = *it; + UCesiumFlyToComponent* pFlyTo = + pPawn->FindComponentByClass(); + TestNotNull("pFlyTo", pFlyTo); + pFlyTo->Duration = 5.0f; + pFlyTo->HeightPercentageCurve = nullptr; + pFlyTo->MaximumHeightByDistanceCurve = nullptr; + pFlyTo->ProgressCurve = nullptr; + + UCesiumGlobeAnchorComponent* pGlobeAnchor = + pPawn->FindComponentByClass(); + TestNotNull("pGlobeAnchor", pGlobeAnchor); + + pGlobeAnchor->MoveToEarthCenteredEarthFixedPosition( + philadelphiaEcef); + pFlyTo->FlyToLocationEarthCenteredEarthFixed(tokyoEcef, 0, 0, 0); + + // Tick half way through + Cast(pFlyTo)->TickComponent( + 2.5f, + ELevelTick::LEVELTICK_All, + nullptr); + + FVector expectedResult = FVector( + -2062499.3622640674, + -1052346.4221710551, + 5923430.4378960524); + + // calculate relative epsilon + const float epsilon = FMath::Max3( + expectedResult.X, + expectedResult.Y, + expectedResult.Z) * + 1e-6; + + TestEqual( + "Midpoint location is correct", + pGlobeAnchor->GetEarthCenteredEarthFixedPosition(), + expectedResult, + epsilon); + + pPawn->Destroy(); + }); + It("should match the start and end rotations", + [this, tokyoEcef, philadelphiaEcef]() { + UWorld* pWorld = GEditor->PlayWorld; + + TActorIterator it(pWorld); + AGlobeAwareDefaultPawn* pPawn = *it; + UCesiumFlyToComponent* pFlyTo = + pPawn->FindComponentByClass(); + TestNotNull("pFlyTo", pFlyTo); + pFlyTo->Duration = 5.0f; + pFlyTo->HeightPercentageCurve = nullptr; + pFlyTo->MaximumHeightByDistanceCurve = nullptr; + pFlyTo->ProgressCurve = nullptr; + + UCesiumGlobeAnchorComponent* pGlobeAnchor = + pPawn->FindComponentByClass(); + TestNotNull("pGlobeAnchor", pGlobeAnchor); + + FQuat sourceRotation = FRotator(0, 0, 0).Quaternion(); + FQuat targetRotation = FRotator(45, 180, 0).Quaternion(); + FQuat midpointRotation = + FQuat::Slerp(sourceRotation, targetRotation, 0.5); + + pGlobeAnchor->MoveToEarthCenteredEarthFixedPosition( + philadelphiaEcef); + pGlobeAnchor->SetEastSouthUpRotation(sourceRotation); + pFlyTo->FlyToLocationEarthCenteredEarthFixed( + tokyoEcef, + 180, + 45, + false); + + TestTrue( + "Start rotation is correct", + pPawn->Controller->GetControlRotation().Quaternion().Equals( + sourceRotation, + CesiumUtility::Math::Epsilon4)); + + // Tick half way through + Cast(pFlyTo)->TickComponent( + 2.5f, + ELevelTick::LEVELTICK_All, + nullptr); + + TestTrue( + "Midpoint rotation is correct", + pPawn->Controller->GetControlRotation().Quaternion().Equals( + midpointRotation, + CesiumUtility::Math::Epsilon4)); + + FVector currentEastSouthRotationEuler = + pGlobeAnchor->GetEastSouthUpRotation().Euler(); + FVector midpointEuler = midpointRotation.Euler(); + + // Tick to the end + Cast(pFlyTo)->TickComponent( + 2.5f, + ELevelTick::LEVELTICK_All, + nullptr); + + TestTrue( + "End location is correct", + pPawn->Controller->GetControlRotation().Quaternion().Equals( + targetRotation, + CesiumUtility::Math::Epsilon4)); + + FVector endEastSouthRotationEuler = + pGlobeAnchor->GetEastSouthUpRotation().Euler(); + FVector endpointEuler = targetRotation.Euler(); + + pPawn->Destroy(); + }); + It("shouldn't fly through the earth", + [this, philadelphiaEcef, philadelphiaAntipodeEcef]() { + UWorld* pWorld = GEditor->PlayWorld; + + TActorIterator it(pWorld); + AGlobeAwareDefaultPawn* pPawn = *it; + UCesiumFlyToComponent* pFlyTo = + pPawn->FindComponentByClass(); + TestNotNull("pFlyTo", pFlyTo); + + pFlyTo->Duration = 5.0f; + pFlyTo->HeightPercentageCurve = nullptr; + pFlyTo->MaximumHeightByDistanceCurve = nullptr; + pFlyTo->ProgressCurve = nullptr; + + UCesiumGlobeAnchorComponent* pGlobeAnchor = + pPawn->FindComponentByClass(); + TestNotNull("pGlobeAnchor", pGlobeAnchor); + + pGlobeAnchor->MoveToEarthCenteredEarthFixedPosition( + philadelphiaEcef); + pFlyTo->FlyToLocationEarthCenteredEarthFixed( + philadelphiaAntipodeEcef, + 0, + 0, + false); + + const int steps = 100; + const double timeStep = 5.0 / (double)steps; + + double time = 0; + for (int i = 0; i <= steps; i++) { + Cast(pFlyTo)->TickComponent( + (float)timeStep, + ELevelTick::LEVELTICK_All, + nullptr); + + const FVector cartographic = UCesiumWgs84Ellipsoid:: + EarthCenteredEarthFixedToLongitudeLatitudeHeight( + pGlobeAnchor->GetEarthCenteredEarthFixedPosition()); + + TestTrue("height above zero", cartographic.Z > 0); + + time += timeStep; + } + }); + }); +} + +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/GooglePhotorealistic3dTilesLoad.perf.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/GooglePhotorealistic3dTilesLoad.perf.cpp new file mode 100644 index 0000000..f1039fb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/GooglePhotorealistic3dTilesLoad.perf.cpp @@ -0,0 +1,315 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "CesiumLoadTestCore.h" + +#include "Engine/World.h" +#include "Misc/AutomationTest.h" + +#include "Cesium3DTileset.h" +#include "CesiumAsync/ICacheDatabase.h" +#include "CesiumRuntime.h" +#include "CesiumSunSky.h" + +using namespace Cesium; + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetGooglePompidou, + "Cesium.Performance.Tileset Loading.Google P3DT Pompidou", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetGoogleChrysler, + "Cesium.Performance.Tileset Loading.Google P3DT Chrysler", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetGoogleChryslerWarm, + "Cesium.Performance.Tileset Loading.Google P3DT Chrysler, warm cache", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetGoogleGuggenheim, + "Cesium.Performance.Tileset Loading.Google P3DT Guggenheim", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetGoogleDeathValley, + "Cesium.Performance.Tileset Loading.Google P3DT DeathValley", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetGoogleDeathValleyWarm, + "Cesium.Performance.Tileset Loading.Google P3DT DeathValley, warm cache", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetGoogleTokyo, + "Cesium.Performance.Tileset Loading.Google P3DT Tokyo", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetGoogleGoogleplex, + "Cesium.Performance.Tileset Loading.Google P3DT Googleplex", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetGoogleChryslerVaryMaxTileLoads, + "Cesium.Performance.Tileset Loading.Google P3DT Chrysler, vary max tile loads", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +#define TEST_SCREEN_WIDTH 1280 +#define TEST_SCREEN_HEIGHT 720 + +void googleSetupRefreshTilesets( + SceneGenerationContext& context, + TestPass::TestingParameter parameter) { + context.refreshTilesets(); +} + +void googleSetupClearCache( + SceneGenerationContext& context, + TestPass::TestingParameter parameter) { + std::shared_ptr pCacheDatabase = + getCacheDatabase(); + pCacheDatabase->clearAll(); +} + +void setupForPompidou(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(2.352200, 48.860600, 200), + FVector(0, 0, 0), + FRotator(-20.0, -90.0, 0.0), + 60.0f); + + context.sunSky->TimeZone = 2.0f; + context.sunSky->UpdateSun(); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + tileset->SetIonAssetID(2275207); + tileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + tileset->SetActorLabel(TEXT("Center Pompidou, Paris, France")); + context.tilesets.push_back(tileset); +} + +void setupForChrysler(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-73.9752624659, 40.74697185903, 307.38), + FVector(0, 0, 0), + FRotator(-15.0, -90.0, 0.0), + 60.0f); + + context.sunSky->TimeZone = -4.0f; + context.sunSky->UpdateSun(); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + tileset->SetIonAssetID(2275207); + tileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + tileset->SetActorLabel(TEXT("Chrysler Building, NYC")); + context.tilesets.push_back(tileset); +} + +void setupForGuggenheim(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-2.937, 43.2685, 150), + FVector(0, 0, 0), + FRotator(-15.0, 0.0, 0.0), + 60.0f); + + context.sunSky->TimeZone = 2.0f; + context.sunSky->UpdateSun(); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + tileset->SetIonAssetID(2275207); + tileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + tileset->SetActorLabel(TEXT("Guggenheim Museum, Bilbao, Spain")); + context.tilesets.push_back(tileset); +} + +void setupForDeathValley(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-116.812278, 36.42, 300), + FVector(0, 0, 0), + FRotator(0, 0.0, 0.0), + 60.0f); + + context.sunSky->TimeZone = -7.0f; + context.sunSky->UpdateSun(); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + tileset->SetIonAssetID(2275207); + tileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + tileset->SetActorLabel( + TEXT("Zabriskie Point, Death Valley National Park, California")); + context.tilesets.push_back(tileset); +} + +void setupForTokyo(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(139.7563178458, 35.652798383944, 525.62), + FVector(0, 0, 0), + FRotator(-15, -150, 0.0), + 60.0f); + + context.sunSky->TimeZone = 9.0f; + context.sunSky->UpdateSun(); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + tileset->SetIonAssetID(2275207); + tileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + tileset->SetActorLabel(TEXT("Tokyo Tower, Tokyo, Japan")); + context.tilesets.push_back(tileset); +} + +void setupForGoogleplex(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-122.083969, 37.424492, 142.859116), + FVector(0, 0, 0), + FRotator(-25, 95, 0), + 90.0f); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + tileset->SetIonAssetID(2275207); + tileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + tileset->SetActorLabel(TEXT("Google Photorealistic 3D Tiles")); + + context.tilesets.push_back(tileset); +} + +bool FLoadTilesetGooglePompidou::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", googleSetupClearCache, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForPompidou, + testPasses, + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); +} + +bool FLoadTilesetGoogleChrysler::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", googleSetupClearCache, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForChrysler, + testPasses, + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); +} + +bool FLoadTilesetGoogleChryslerWarm::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back( + TestPass{"Warm Cache", googleSetupRefreshTilesets, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForChrysler, + testPasses, + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); +} + +bool FLoadTilesetGoogleGuggenheim::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", googleSetupClearCache, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForGuggenheim, + testPasses, + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); +} + +bool FLoadTilesetGoogleDeathValley::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", googleSetupClearCache, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForDeathValley, + testPasses, + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); +} + +bool FLoadTilesetGoogleDeathValleyWarm::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back( + TestPass{"Warm Cache", googleSetupRefreshTilesets, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForDeathValley, + testPasses, + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); +} + +bool FLoadTilesetGoogleTokyo::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", googleSetupClearCache, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForTokyo, + testPasses, + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); +} + +bool FLoadTilesetGoogleGoogleplex::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", googleSetupClearCache, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForGoogleplex, + testPasses, + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); +} + +bool FLoadTilesetGoogleChryslerVaryMaxTileLoads::RunTest( + const FString& Parameters) { + auto setupPass = [this]( + SceneGenerationContext& context, + TestPass::TestingParameter parameter) { + std::shared_ptr pCacheDatabase = + getCacheDatabase(); + pCacheDatabase->clearAll(); + + int maxLoadsTarget = swl::get(parameter); + context.setMaximumSimultaneousTileLoads(maxLoadsTarget); + + context.refreshTilesets(); + }; + + std::vector testPasses; + testPasses.push_back(TestPass{"Default", googleSetupClearCache, NULL}); + testPasses.push_back(TestPass{"12", setupPass, NULL, 12}); + testPasses.push_back(TestPass{"16", setupPass, NULL, 16}); + testPasses.push_back(TestPass{"20", setupPass, NULL, 20}); + testPasses.push_back(TestPass{"24", setupPass, NULL, 24}); + testPasses.push_back(TestPass{"28", setupPass, NULL, 28}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForChrysler, + testPasses, + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); +} + +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleHeightCallbackReceiver.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleHeightCallbackReceiver.h new file mode 100644 index 0000000..7c354d6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleHeightCallbackReceiver.h @@ -0,0 +1,39 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumSampleHeightMostDetailedAsyncAction.h" +#include "UObject/Object.h" +#include "UObject/ObjectMacros.h" +#include +#include "SampleHeightCallbackReceiver.generated.h" + +UCLASS() +class USampleHeightCallbackReceiver : public UObject { + GENERATED_BODY() + +public: + using TFunction = std::function< + void(const TArray&, const TArray&)>; + + static void + Bind(FCesiumSampleHeightMostDetailedComplete& delegate, TFunction callback) { + USampleHeightCallbackReceiver* p = + NewObject(); + p->_callback = callback; + p->AddToRoot(); + + delegate.AddUniqueDynamic(p, &USampleHeightCallbackReceiver::Receiver); + } + +private: + UFUNCTION() + void Receiver( + const TArray& Result, + const TArray& Warnings) { + this->_callback(Result, Warnings); + this->RemoveFromRoot(); + } + + TFunction _callback; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleHeightMostDetailed.perf.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleHeightMostDetailed.perf.cpp new file mode 100644 index 0000000..f544416 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleHeightMostDetailed.perf.cpp @@ -0,0 +1,484 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "CesiumLoadTestCore.h" + +#include "Misc/AutomationTest.h" + +#include "CesiumAsync/ICacheDatabase.h" +#include "CesiumGltfComponent.h" +#include "CesiumIonRasterOverlay.h" +#include "CesiumRuntime.h" +#include "CesiumSunSky.h" +#include "GlobeAwareDefaultPawn.h" + +#include "Engine/StaticMeshActor.h" + +using namespace Cesium; +using namespace std::chrono_literals; + +namespace { +void setupDenverHillsCesiumWorldTerrain(SceneGenerationContext& context); +void setupDenverHillsGoogle(SceneGenerationContext& context); +bool RunSingleQueryTest( + const FString& testName, + std::function setup); +bool RunMultipleQueryTest( + const FString& testName, + std::function setup); +} // namespace + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FSampleHeightMostDetailedCesiumWorldTerrainSingle, + "Cesium.Performance.SampleHeightMostDetailed.Single query against Cesium World Terrain", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FSampleHeightMostDetailedCesiumWorldTerrainMultiple, + "Cesium.Performance.SampleHeightMostDetailed.Multiple queries against Cesium World Terrain", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FSampleHeightMostDetailedGoogleSingle, + "Cesium.Performance.SampleHeightMostDetailed.Single query against Google Photorealistic 3D Tiles", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FSampleHeightMostDetailedGoogleMultiple, + "Cesium.Performance.SampleHeightMostDetailed.Multiple queries against Google Photorealistic 3D Tiles", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +bool FSampleHeightMostDetailedCesiumWorldTerrainSingle::RunTest( + const FString& Parameters) { + return RunSingleQueryTest( + this->GetBeautifiedTestName(), + setupDenverHillsCesiumWorldTerrain); +} + +bool FSampleHeightMostDetailedCesiumWorldTerrainMultiple::RunTest( + const FString& Parameters) { + return RunMultipleQueryTest( + this->GetBeautifiedTestName(), + setupDenverHillsCesiumWorldTerrain); +} + +bool FSampleHeightMostDetailedGoogleSingle::RunTest(const FString& Parameters) { + return RunSingleQueryTest( + this->GetBeautifiedTestName(), + setupDenverHillsGoogle); +} + +bool FSampleHeightMostDetailedGoogleMultiple::RunTest( + const FString& Parameters) { + return RunMultipleQueryTest( + this->GetBeautifiedTestName(), + setupDenverHillsGoogle); +} + +namespace { +// Our test model path +// +// Uses a simple cube, but to see trees instead, download 'temperate Vegetation: +// Spruce Forest' from the Unreal Engine Marketplace then use the following +// path... +// "'/Game/PN_interactiveSpruceForest/Meshes/full/low/spruce_full_01_low.spruce_full_01_low'" +FString terrainQueryTestModelPath( + TEXT("StaticMesh'/Engine/BasicShapes/Cube.Cube'")); + +void setupDenverHillsCesiumWorldTerrain(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-105.238887, 39.756177, 1887.175525), + FVector(0, 0, 0), + FRotator(-7, -226, -5), + 90.0f); + + // Add Cesium World Terrain + ACesium3DTileset* worldTerrainTileset = + context.world->SpawnActor(); + worldTerrainTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + worldTerrainTileset->SetIonAssetID(1); + worldTerrainTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + worldTerrainTileset->SetActorLabel(TEXT("Cesium World Terrain")); + worldTerrainTileset->MaximumCachedBytes = 0; + + context.tilesets.push_back(worldTerrainTileset); +} + +void setupDenverHillsGoogle(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-105.238887, 39.756177, 1887.175525), + FVector(0, 0, 0), + FRotator(-7, -226, -5), + 90.0f); + + // Add Cesium World Terrain + ACesium3DTileset* googleTileset = + context.world->SpawnActor(); + googleTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + googleTileset->SetIonAssetID(2275207); + googleTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + googleTileset->SetActorLabel(TEXT("Google Photorealistic 3D Tiles")); + googleTileset->MaximumCachedBytes = 0; + + context.tilesets.push_back(googleTileset); +} + +bool RunSingleQueryTest( + const FString& testName, + std::function setup) { + auto clearCache = [](SceneGenerationContext& context, + TestPass::TestingParameter parameter) { + std::shared_ptr pCacheDatabase = + getCacheDatabase(); + pCacheDatabase->clearAll(); + }; + + struct TestResults { + std::atomic queryFinished = false; + TArray heightResults; + TArray warnings; + }; + + static TestResults testResults; + + auto issueQueries = [&testResults = testResults]( + SceneGenerationContext& context, + TestPass::TestingParameter parameter) { + // Test right at camera position + double testLongitude = -105.257595; + double testLatitude = 39.743103; + + // Make a grid of test points + const size_t gridRowCount = 20; + const size_t gridColumnCount = 20; + double cartographicSpacing = 0.001; + + TArray queryInput; + + for (size_t rowIndex = 0; rowIndex < gridRowCount; ++rowIndex) { + double rowLatitude = testLatitude + (cartographicSpacing * rowIndex); + + for (size_t columnIndex = 0; columnIndex < gridColumnCount; + ++columnIndex) { + FVector queryInstance = { + testLongitude + (cartographicSpacing * columnIndex), + rowLatitude, + 0.0}; + + queryInput.Add(queryInstance); + } + } + + ACesium3DTileset* tileset = context.tilesets[0]; + + tileset->SampleHeightMostDetailed( + queryInput, + FCesiumSampleHeightMostDetailedCallback::CreateLambda( + [&testResults]( + ACesium3DTileset* Tileset, + const TArray& Results, + const TArray& Warnings) { + testResults.heightResults = Results; + testResults.warnings = Warnings; + testResults.queryFinished = true; + })); + }; + + auto waitForQueries = [&testResults = testResults]( + SceneGenerationContext& creationContext, + SceneGenerationContext& playContext, + TestPass::TestingParameter parameter) { + return (bool)testResults.queryFinished; + }; + + auto showResults = [&testResults = testResults]( + SceneGenerationContext& creationContext, + SceneGenerationContext& playContext, + TestPass::TestingParameter parameter) { + // Turn on the editor tileset updates so we can see what we loaded + creationContext.setSuspendUpdate(false); + + // Place an object on the ground to verify position + UWorld* World = creationContext.world; + + UStaticMesh* testMesh = + LoadObject(nullptr, *terrainQueryTestModelPath); + + ACesium3DTileset* tileset = playContext.tilesets[0]; + Cesium3DTilesSelection::Tileset* nativeTileset = tileset->GetTileset(); + + // Log any warnings + for (const FString& warning : testResults.warnings) { + UE_LOG(LogCesium, Warning, TEXT("Height query warning: %s"), *warning); + } + + int32 resultCount = testResults.heightResults.Num(); + for (int32 resultIndex = 0; resultIndex < resultCount; ++resultIndex) { + const FVector& queryLongitudeLatitudeHeight = + testResults.heightResults[resultIndex].LongitudeLatitudeHeight; + + if (!testResults.heightResults[resultIndex].SampleSuccess) { + UE_LOG( + LogCesium, + Error, + TEXT("The height at (%f,%f) was not sampled successfully."), + queryLongitudeLatitudeHeight.X, + queryLongitudeLatitudeHeight.Y); + continue; + } + + FVector unrealPosition = + tileset->ResolveGeoreference() + ->TransformLongitudeLatitudeHeightPositionToUnreal( + queryLongitudeLatitudeHeight); + + // Now bring the hit point to unreal world coordinates + FVector unrealWorldPosition = + tileset->GetActorTransform().TransformFVector4(unrealPosition); + + AStaticMeshActor* staticMeshActor = World->SpawnActor(); + staticMeshActor->GetStaticMeshComponent()->SetStaticMesh(testMesh); + staticMeshActor->SetActorLocation(unrealWorldPosition); + staticMeshActor->SetActorScale3D(FVector(7, 7, 7)); + staticMeshActor->SetActorLabel( + FString::Printf(TEXT("Hit %d"), resultIndex)); + staticMeshActor->SetFolderPath("/QueryResults"); + } + + return true; + }; + + std::vector testPasses; + testPasses.push_back( + TestPass{"Load terrain from cold cache", clearCache, nullptr}); + testPasses.push_back( + TestPass{"Issue height queries and wait", issueQueries, waitForQueries}); + testPasses.push_back( + TestPass{"Populate scene with results", nullptr, showResults}); + + return RunLoadTest(testName, setup, testPasses, 1280, 768); +} + +bool RunMultipleQueryTest( + const FString& testName, + std::function setup) { + struct QueryObject { + FVector coordinateDegrees; + + AStaticMeshActor* creationMeshActor = nullptr; + AStaticMeshActor* playMeshActor = nullptr; + + bool queryFinished = false; + }; + + struct TestProcess { + std::vector queryObjects; + }; + + auto pProcess = std::make_shared(); + + // + // Setup all object positions that will receive queries + // + // Test right at camera position + double testLongitude = -105.257595; + double testLatitude = 39.743103; + + // Make a grid of test points + const size_t gridRowCount = 20; + const size_t gridColumnCount = 20; + double cartographicSpacing = 0.001; + + for (size_t rowIndex = 0; rowIndex < gridRowCount; ++rowIndex) { + double rowLatitude = testLatitude + (cartographicSpacing * rowIndex); + + for (size_t columnIndex = 0; columnIndex < gridColumnCount; ++columnIndex) { + FVector position( + testLongitude + (cartographicSpacing * columnIndex), + rowLatitude, + 2190.0); + + QueryObject newQueryObject = {position}; + + pProcess->queryObjects.push_back(std::move(newQueryObject)); + } + } + + auto clearCache = [](SceneGenerationContext&, TestPass::TestingParameter) { + std::shared_ptr pCacheDatabase = + getCacheDatabase(); + pCacheDatabase->clearAll(); + }; + + auto addTestObjects = [pProcess]( + SceneGenerationContext& creationContext, + SceneGenerationContext& playContext, + TestPass::TestingParameter) { + // Place an object on the ground to verify position + UWorld* creationWorld = creationContext.world; + UWorld* playWorld = playContext.world; + + UStaticMesh* testMesh = + LoadObject(nullptr, *terrainQueryTestModelPath); + + ACesium3DTileset* tileset = playContext.tilesets[0]; + Cesium3DTilesSelection::Tileset* nativeTileset = tileset->GetTileset(); + + for (size_t queryIndex = 0; queryIndex < pProcess->queryObjects.size(); + ++queryIndex) { + QueryObject& queryObject = pProcess->queryObjects[queryIndex]; + + FVector unrealPosition = + tileset->ResolveGeoreference() + ->TransformLongitudeLatitudeHeightPositionToUnreal( + queryObject.coordinateDegrees); + + // Now bring the hit point to unreal world coordinates + FVector unrealWorldPosition = + tileset->GetActorTransform().TransformFVector4(unrealPosition); + + { + AStaticMeshActor* staticMeshActor = + creationWorld->SpawnActor(); + staticMeshActor->SetMobility(EComponentMobility::Movable); + staticMeshActor->GetStaticMeshComponent()->SetStaticMesh(testMesh); + staticMeshActor->SetActorLocation(unrealWorldPosition); + staticMeshActor->SetActorScale3D(FVector(7, 7, 7)); + staticMeshActor->SetActorLabel( + FString::Printf(TEXT("Hit %d"), queryIndex)); + staticMeshActor->SetFolderPath("/QueryResults"); + queryObject.creationMeshActor = staticMeshActor; + } + + { + AStaticMeshActor* staticMeshActor = + playWorld->SpawnActor(); + staticMeshActor->SetMobility(EComponentMobility::Movable); + staticMeshActor->GetStaticMeshComponent()->SetStaticMesh(testMesh); + staticMeshActor->SetActorLocation(unrealWorldPosition); + staticMeshActor->SetActorScale3D(FVector(7, 7, 7)); + staticMeshActor->SetActorLabel( + FString::Printf(TEXT("Hit %d"), queryIndex)); + staticMeshActor->SetFolderPath("/QueryResults"); + queryObject.playMeshActor = staticMeshActor; + } + } + return true; + }; + + auto issueQueries = [pProcess]( + SceneGenerationContext& context, + TestPass::TestingParameter) { + ACesium3DTileset* tileset = context.tilesets[0]; + + for (QueryObject& queryObject : pProcess->queryObjects) { + tileset->SampleHeightMostDetailed( + {queryObject.coordinateDegrees}, + FCesiumSampleHeightMostDetailedCallback::CreateLambda( + [tileset, &queryObject]( + ACesium3DTileset* pTileset, + const TArray& results, + const TArray& warnings) { + queryObject.queryFinished = true; + + // Log any warnings + for (const FString& warning : warnings) { + UE_LOG( + LogCesium, + Warning, + TEXT("Height query traversal warning: %s"), + *warning); + } + + if (results.Num() != 1) { + UE_LOG( + LogCesium, + Warning, + TEXT("Unexpected number of results received")); + return; + } + + const FVector& newCoordinate = + results[0].LongitudeLatitudeHeight; + if (!results[0].SampleSuccess) { + UE_LOG( + LogCesium, + Error, + TEXT( + "The height at (%f,%f) was not sampled successfully."), + newCoordinate.X, + newCoordinate.Y); + return; + } + + const FVector& originalCoordinate = + queryObject.coordinateDegrees; + + if (!FMath::IsNearlyEqual( + originalCoordinate.X, + newCoordinate.X, + 1e-12) || + !FMath::IsNearlyEqual( + originalCoordinate.Y, + newCoordinate.Y, + 1e-12)) { + UE_LOG( + LogCesium, + Warning, + TEXT("Hit result doesn't match original input")); + return; + } + + FVector unrealPosition = + tileset->ResolveGeoreference() + ->TransformLongitudeLatitudeHeightPositionToUnreal( + newCoordinate); + + // Now bring the hit point to unreal world coordinates + FVector unrealWorldPosition = + tileset->GetActorTransform().TransformFVector4( + unrealPosition); + + queryObject.creationMeshActor->SetActorLocation( + unrealWorldPosition); + + queryObject.playMeshActor->SetActorLocation( + unrealWorldPosition); + })); + } + }; + + auto waitForQueries = [pProcess]( + SceneGenerationContext&, + SceneGenerationContext&, + TestPass::TestingParameter) { + for (QueryObject& queryObject : pProcess->queryObjects) { + if (!queryObject.queryFinished) + return false; + } + return true; + }; + + auto showResults = [](SceneGenerationContext& creationContext, + SceneGenerationContext&, + TestPass::TestingParameter) { + // Turn on the editor tileset updates so we can see what we loaded + creationContext.setSuspendUpdate(false); + return true; + }; + + std::vector testPasses; + testPasses.push_back( + TestPass{"Load terrain from cold cache", clearCache, nullptr}); + testPasses.push_back(TestPass{"Add test objects", nullptr, addTestObjects}); + testPasses.push_back( + TestPass{"Issue height queries and wait", issueQueries, waitForQueries}); + testPasses.push_back(TestPass{"Show results", nullptr, showResults}); + + return RunLoadTest(testName, setup, testPasses, 1280, 720); +} + +} // namespace + +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleHeightMostDetailed.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleHeightMostDetailed.spec.cpp new file mode 100644 index 0000000..479e63b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleHeightMostDetailed.spec.cpp @@ -0,0 +1,358 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "Cesium3DTileset.h" +#include "CesiumSampleHeightMostDetailedAsyncAction.h" +#include "CesiumSceneGeneration.h" +#include "CesiumTestHelpers.h" +#include "Misc/AutomationTest.h" +#include "SampleHeightCallbackReceiver.h" + +BEGIN_DEFINE_SPEC( + FSampleHeightMostDetailedSpec, + "Cesium.Unit.SampleHeightMostDetailed", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) + +TObjectPtr pTileset; + +END_DEFINE_SPEC(FSampleHeightMostDetailedSpec) + +// The intention of these tests is not to verify that height querying produces +// correct heights, because the cesium-native tests already do that. It's just +// to verify that the Unreal wrapper API around cesium-native is working +// correctly. + +void FSampleHeightMostDetailedSpec::Define() { + Describe("Cesium World Terrain", [this]() { + BeforeEach([this]() { + CesiumTestHelpers::pushAllowTickInEditor(); + + UWorld* pWorld = CesiumTestHelpers::getGlobalWorldContext(); + pTileset = pWorld->SpawnActor(); + pTileset->SetIonAssetID(1); +#if WITH_EDITOR + pTileset->SetIonAccessToken(Cesium::SceneGenerationContext::testIonToken); + pTileset->SetActorLabel(TEXT("Cesium World Terrain")); +#endif + }); + + AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() { + pTileset->Destroy(); + + CesiumTestHelpers::popAllowTickInEditor(); + }); + + LatentIt( + "works with an empty array of positions", + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + pTileset->SampleHeightMostDetailed( + {}, + FCesiumSampleHeightMostDetailedCallback::CreateLambda( + [this, done]( + ACesium3DTileset* pTileset, + const TArray& result, + const TArray& warnings) { + TestEqual("Number of results", result.Num(), 0); + TestEqual("Number of warnings", warnings.Num(), 0); + done.ExecuteIfBound(); + })); + }); + + LatentIt( + "works with a single position", + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + pTileset->SampleHeightMostDetailed( + {FVector(-105.1, 40.1, 1.0)}, + FCesiumSampleHeightMostDetailedCallback::CreateLambda( + [this, done]( + ACesium3DTileset* pTileset, + const TArray& result, + const TArray& warnings) { + TestEqual("Number of results", result.Num(), 1); + TestEqual("Number of warnings", warnings.Num(), 0); + TestTrue("SampleSuccess", result[0].SampleSuccess); + TestEqual( + "Longitude", + result[0].LongitudeLatitudeHeight.X, + -105.1, + 1e-12); + TestEqual( + "Latitude", + result[0].LongitudeLatitudeHeight.Y, + 40.1, + 1e-12); + TestTrue( + "Height", + !FMath::IsNearlyEqual( + result[0].LongitudeLatitudeHeight.Z, + 1.0, + 1.0)); + done.ExecuteIfBound(); + })); + }); + + LatentIt( + "works with multiple positions", + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + pTileset->SampleHeightMostDetailed( + {FVector(-105.1, 40.1, 1.0), FVector(105.1, -40.1, 1.0)}, + FCesiumSampleHeightMostDetailedCallback::CreateLambda( + [this, done]( + ACesium3DTileset* pTileset, + const TArray& result, + const TArray& warnings) { + TestEqual("Number of results", result.Num(), 2); + TestEqual("Number of warnings", warnings.Num(), 0); + TestTrue("SampleSuccess", result[0].SampleSuccess); + TestEqual( + "Longitude", + result[0].LongitudeLatitudeHeight.X, + -105.1, + 1e-12); + TestEqual( + "Latitude", + result[0].LongitudeLatitudeHeight.Y, + 40.1, + 1e-12); + TestTrue( + "Height", + !FMath::IsNearlyEqual( + result[0].LongitudeLatitudeHeight.Z, + 1.0, + 1.0)); + TestTrue("SampleSuccess", result[1].SampleSuccess); + TestEqual( + "Longitude", + result[1].LongitudeLatitudeHeight.X, + 105.1, + 1e-12); + TestEqual( + "Latitude", + result[1].LongitudeLatitudeHeight.Y, + -40.1, + 1e-12); + TestTrue( + "Height", + !FMath::IsNearlyEqual( + result[1].LongitudeLatitudeHeight.Z, + 1.0, + 1.0)); + done.ExecuteIfBound(); + })); + }); + }); + + Describe("Melbourne Photogrammetry", [this]() { + BeforeEach([this]() { + CesiumTestHelpers::pushAllowTickInEditor(); + + UWorld* pWorld = CesiumTestHelpers::getGlobalWorldContext(); + pTileset = pWorld->SpawnActor(); + pTileset->SetIonAssetID(69380); +#if WITH_EDITOR + pTileset->SetIonAccessToken(Cesium::SceneGenerationContext::testIonToken); + pTileset->SetActorLabel(TEXT("Melbourne Photogrammetry")); +#endif + }); + + AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() { + pTileset->Destroy(); + + CesiumTestHelpers::popAllowTickInEditor(); + }); + + LatentIt( + "indicates !HeightSampled for position outside tileset", + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + pTileset->SampleHeightMostDetailed( + // Somewhere in Sydney, not Melbourne + {FVector(151.20972, -33.87100, 1.0)}, + FCesiumSampleHeightMostDetailedCallback::CreateLambda( + [this, done]( + ACesium3DTileset* pTileset, + const TArray& result, + const TArray& warnings) { + TestEqual("Number of results", result.Num(), 1); + TestEqual("Number of warnings", warnings.Num(), 0); + TestTrue("SampleSuccess", !result[0].SampleSuccess); + TestEqual( + "Longitude", + result[0].LongitudeLatitudeHeight.X, + 151.20972, + 1e-12); + TestEqual( + "Latitude", + result[0].LongitudeLatitudeHeight.Y, + -33.87100, + 1e-12); + TestEqual( + "Height", + result[0].LongitudeLatitudeHeight.Z, + 1.0, + 1e-12); + done.ExecuteIfBound(); + })); + }); + + LatentIt( + "can be queried via Blueprint interface", + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + UCesiumSampleHeightMostDetailedAsyncAction* pAsync = + UCesiumSampleHeightMostDetailedAsyncAction:: + SampleHeightMostDetailed( + pTileset, + {FVector(144.93406, -37.82457, 1.0)}); + + USampleHeightCallbackReceiver::Bind( + pAsync->OnHeightsSampled, + [this, done]( + const TArray& result, + const TArray& warnings) { + TestEqual("Number of results", result.Num(), 1); + TestEqual("Number of warnings", warnings.Num(), 0); + TestTrue("SampleSuccess", result[0].SampleSuccess); + TestEqual( + "Longitude", + result[0].LongitudeLatitudeHeight.X, + 144.93406, + 1e-12); + TestEqual( + "Latitude", + result[0].LongitudeLatitudeHeight.Y, + -37.82457, + 1e-12); + TestTrue( + "Height", + !FMath::IsNearlyEqual( + result[0].LongitudeLatitudeHeight.Z, + 1.0, + 1.0)); + done.ExecuteIfBound(); + }); + + pAsync->Activate(); + }); + }); + + Describe("Two tilesets in rapid succession", [this]() { + BeforeEach([this]() { CesiumTestHelpers::pushAllowTickInEditor(); }); + + AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() { + CesiumTestHelpers::popAllowTickInEditor(); + }); + + LatentIt( + "", + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + UWorld* pWorld = CesiumTestHelpers::getGlobalWorldContext(); + + ACesium3DTileset* pTileset1 = pWorld->SpawnActor(); + pTileset1->SetIonAssetID(1); +#if WITH_EDITOR + pTileset1->SetIonAccessToken( + Cesium::SceneGenerationContext::testIonToken); +#endif + + pTileset1->SampleHeightMostDetailed( + {FVector(-105.1, 40.1, 1.0)}, + FCesiumSampleHeightMostDetailedCallback::CreateLambda( + [this, pWorld, done]( + ACesium3DTileset* pTileset, + const TArray& result, + const TArray& warnings) { + TestEqual("Number of results", result.Num(), 1); + TestEqual("Number of warnings", warnings.Num(), 0); + TestTrue("SampleSuccess", result[0].SampleSuccess); + + ACesium3DTileset* pTileset2 = + pWorld->SpawnActor(); + pTileset2->SetIonAssetID(1); +#if WITH_EDITOR + pTileset2->SetIonAccessToken( + Cesium::SceneGenerationContext::testIonToken); +#endif + pTileset2->SampleHeightMostDetailed( + {FVector(105.1, 40.1, 1.0)}, + FCesiumSampleHeightMostDetailedCallback::CreateLambda( + [this, pWorld, done]( + ACesium3DTileset* pTileset, + const TArray& result, + const TArray& warnings) { + TestEqual("Number of results", result.Num(), 1); + TestEqual( + "Number of warnings", + warnings.Num(), + 0); + TestTrue( + "SampleSuccess", + result[0].SampleSuccess); + + done.ExecuteIfBound(); + })); + })); + }); + }); + + Describe("Broken tileset", [this]() { + BeforeEach([this]() { CesiumTestHelpers::pushAllowTickInEditor(); }); + + AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() { + CesiumTestHelpers::popAllowTickInEditor(); + }); + + LatentIt( + "", + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + // Two slightly different error messages will occur, depending on + // whether there's a web server running on localhost. + this->AddExpectedError( + TEXT("(Errors when loading)|(error occurred)")); + + UWorld* pWorld = CesiumTestHelpers::getGlobalWorldContext(); + + ACesium3DTileset* pTileset = pWorld->SpawnActor(); + pTileset->SetTilesetSource(ETilesetSource::FromUrl); + pTileset->SetUrl("http://localhost/notgonnawork"); + + pTileset->SampleHeightMostDetailed( + {FVector(-105.1, 40.1, 1.0)}, + FCesiumSampleHeightMostDetailedCallback::CreateLambda( + [this, done]( + ACesium3DTileset* pTileset, + const TArray& result, + const TArray& warnings) { + TestEqual("Number of results", result.Num(), 1); + TestEqual("Number of warnings", warnings.Num(), 1); + TestFalse("SampleSuccess", result[0].SampleSuccess); + TestEqual( + "Longitude", + result[0].LongitudeLatitudeHeight.X, + -105.1, + 1e-12); + TestEqual( + "Latitude", + result[0].LongitudeLatitudeHeight.Y, + 40.1, + 1e-12); + TestEqual( + "Height", + result[0].LongitudeLatitudeHeight.Z, + 1.0, + 1e-12); + TestTrue( + "Error message", + warnings[0].Contains(TEXT("failed to load"))); + done.ExecuteIfBound(); + })); + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleTilesetsLoad.perf.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleTilesetsLoad.perf.cpp new file mode 100644 index 0000000..18de2f3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleTilesetsLoad.perf.cpp @@ -0,0 +1,280 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "CesiumLoadTestCore.h" + +#include "Misc/AutomationTest.h" + +#include "CesiumAsync/ICacheDatabase.h" +#include "CesiumGltfComponent.h" +#include "CesiumIonRasterOverlay.h" +#include "CesiumRuntime.h" +#include "CesiumSunSky.h" +#include "GlobeAwareDefaultPawn.h" + +using namespace Cesium; + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetDenver, + "Cesium.Performance.Tileset Loading.Aerometrex Denver", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetMelbourne, + "Cesium.Performance.Tileset Loading.Melbourne photogrammetry (open data)", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetMontrealPointCloud, + "Cesium.Performance.Tileset Loading.Montreal point cloud (open data)", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FLoadTilesetMelbourneVaryMaxTileLoads, + "Cesium.Performance.Tileset Loading.Melbourne photogrammetry (open data), vary max tile loads", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +void samplesClearCache(SceneGenerationContext&, TestPass::TestingParameter) { + std::shared_ptr pCacheDatabase = + getCacheDatabase(); + pCacheDatabase->clearAll(); +} + +void samplesRefreshTilesets( + SceneGenerationContext& context, + TestPass::TestingParameter parameter) { + context.refreshTilesets(); +} + +void setupForDenver(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-104.988892, 39.743462, 1798.679443), + FVector(0, 0, 0), + FRotator(-5.2, -149.4, 0), + 90.0f); + + // Add Cesium World Terrain + ACesium3DTileset* worldTerrainTileset = + context.world->SpawnActor(); + worldTerrainTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + worldTerrainTileset->SetIonAssetID(1); + worldTerrainTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + worldTerrainTileset->SetActorLabel(TEXT("Cesium World Terrain")); + + // Bing Maps Aerial overlay + UCesiumIonRasterOverlay* pOverlay = NewObject( + worldTerrainTileset, + FName("Bing Maps Aerial"), + RF_Transactional); + pOverlay->MaterialLayerKey = TEXT("Overlay0"); + pOverlay->IonAssetID = 2; + pOverlay->SetActive(true); + pOverlay->OnComponentCreated(); + worldTerrainTileset->AddInstanceComponent(pOverlay); + + // Aerometrex Denver + ACesium3DTileset* aerometrexTileset = + context.world->SpawnActor(); + aerometrexTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + aerometrexTileset->SetIonAssetID(354307); + aerometrexTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + aerometrexTileset->SetMaximumScreenSpaceError(2.0); + aerometrexTileset->SetActorLabel(TEXT("Aerometrex Denver")); + + context.tilesets.push_back(worldTerrainTileset); + context.tilesets.push_back(aerometrexTileset); +} + +void setupForMelbourne(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(144.951538, -37.809871, 140.334974), + FVector(1052, 506, 23651), + FRotator(-32, 20, 0), + 90.0f); + + context.sunSky->SolarTime = 16.8; + context.sunSky->UpdateSun(); + + // Add Cesium World Terrain + ACesium3DTileset* worldTerrainTileset = + context.world->SpawnActor(); + worldTerrainTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + worldTerrainTileset->SetIonAssetID(1); + worldTerrainTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + worldTerrainTileset->SetActorLabel(TEXT("Cesium World Terrain")); + + // Bing Maps Aerial overlay + UCesiumIonRasterOverlay* pOverlay = NewObject( + worldTerrainTileset, + FName("Bing Maps Aerial"), + RF_Transactional); + pOverlay->MaterialLayerKey = TEXT("Overlay0"); + pOverlay->IonAssetID = 2; + pOverlay->SetActive(true); + pOverlay->OnComponentCreated(); + worldTerrainTileset->AddInstanceComponent(pOverlay); + + ACesium3DTileset* melbourneTileset = + context.world->SpawnActor(); + melbourneTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + melbourneTileset->SetIonAssetID(69380); + melbourneTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + melbourneTileset->SetMaximumScreenSpaceError(6.0); + melbourneTileset->SetActorLabel(TEXT("Melbourne Photogrammetry")); + melbourneTileset->SetActorLocation(FVector(0, 0, 900)); + + context.tilesets.push_back(worldTerrainTileset); + context.tilesets.push_back(melbourneTileset); +} + +void setupForMontrealPointCloud(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-73.616526, 45.57335, 95.048859), + FVector(0, 0, 0), + FRotator(-90.0, 0.0, 0.0), + 90.0f); + + ACesium3DTileset* montrealTileset = + context.world->SpawnActor(); + montrealTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + montrealTileset->SetIonAssetID(28945); + montrealTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + montrealTileset->SetMaximumScreenSpaceError(16.0); + montrealTileset->SetActorLabel(TEXT("Montreal Point Cloud")); + + context.tilesets.push_back(montrealTileset); +} + +bool FLoadTilesetDenver::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", samplesClearCache, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", samplesRefreshTilesets, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForDenver, + testPasses, + 1024, + 768); +} + +bool FLoadTilesetMelbourne::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", samplesClearCache, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", samplesRefreshTilesets, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForMelbourne, + testPasses, + 1024, + 768); +} + +bool FLoadTilesetMontrealPointCloud::RunTest(const FString& Parameters) { + auto adjustCamera = [this]( + SceneGenerationContext& context, + TestPass::TestingParameter parameter) { + // Zoom way out + context.startPosition = FVector(0, 0, 7240000.0); + context.startRotation = FRotator(-90.0, 0.0, 0.0); + context.syncWorldCamera(); + + context.pawn->SetActorLocation(context.startPosition); + }; + + auto verifyVisibleTiles = [this]( + SceneGenerationContext& creationContext, + SceneGenerationContext& playContext, + TestPass::TestingParameter parameter) { + Cesium3DTilesSelection::Tileset* pTileset = + playContext.tilesets[0]->GetTileset(); + if (TestNotNull("Tileset", pTileset)) { + int visibleTiles = 0; + pTileset->forEachLoadedTile([&](Cesium3DTilesSelection::Tile& tile) { + if (tile.getState() != Cesium3DTilesSelection::TileLoadState::Done) + return; + const Cesium3DTilesSelection::TileContent& content = tile.getContent(); + const Cesium3DTilesSelection::TileRenderContent* pRenderContent = + content.getRenderContent(); + if (!pRenderContent) { + return; + } + + UCesiumGltfComponent* Gltf = static_cast( + pRenderContent->getRenderResources()); + if (Gltf && Gltf->IsVisible()) { + ++visibleTiles; + } + }); + + TestEqual("visibleTiles", visibleTiles, 1); + } + + return true; + }; + + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", samplesClearCache, nullptr}); + testPasses.push_back(TestPass{"Adjust", adjustCamera, verifyVisibleTiles}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForMontrealPointCloud, + testPasses, + 512, + 512); +} + +bool FLoadTilesetMelbourneVaryMaxTileLoads::RunTest(const FString& Parameters) { + + auto setupPass = [this]( + SceneGenerationContext& context, + TestPass::TestingParameter parameter) { + std::shared_ptr pCacheDatabase = + getCacheDatabase(); + pCacheDatabase->clearAll(); + + int maxLoadsTarget = swl::get(parameter); + context.setMaximumSimultaneousTileLoads(maxLoadsTarget); + + context.refreshTilesets(); + }; + + auto reportStep = [this](const std::vector& testPasses) { + FString reportStr; + reportStr += "\n\nTest Results\n"; + reportStr += "------------------------------------------------------\n"; + reportStr += "(measured time) - (MaximumSimultaneousTileLoads value)\n"; + reportStr += "------------------------------------------------------\n"; + std::vector::const_iterator it; + for (it = testPasses.begin(); it != testPasses.end(); ++it) { + const TestPass& pass = *it; + reportStr += + FString::Printf(TEXT("%.2f secs - %s"), pass.elapsedTime, *pass.name); + if (pass.isFastest) + reportStr += " <-- fastest"; + reportStr += "\n"; + } + reportStr += "------------------------------------------------------\n"; + UE_LOG(LogCesium, Display, TEXT("%s"), *reportStr); + }; + + std::vector testPasses; + testPasses.push_back(TestPass{"Default", samplesClearCache, NULL}); + testPasses.push_back(TestPass{"12", setupPass, NULL, 12}); + testPasses.push_back(TestPass{"16", setupPass, NULL, 16}); + testPasses.push_back(TestPass{"20", setupPass, NULL, 20}); + testPasses.push_back(TestPass{"24", setupPass, NULL, 24}); + testPasses.push_back(TestPass{"28", setupPass, NULL, 28}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForMelbourne, + testPasses, + 1024, + 768, + reportStep); +} +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SubLevels.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SubLevels.spec.cpp new file mode 100644 index 0000000..383c17b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SubLevels.spec.cpp @@ -0,0 +1,357 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "CesiumGeoreference.h" +#include "CesiumOriginShiftComponent.h" +#include "CesiumSubLevelComponent.h" +#include "CesiumTestHelpers.h" +#include "Editor.h" +#include "Engine/World.h" +#include "EngineUtils.h" +#include "GameFramework/PlayerController.h" +#include "GlobeAwareDefaultPawn.h" +#include "LevelInstance/LevelInstanceActor.h" +#include "Misc/AutomationTest.h" +#include "Tests/AutomationEditorCommon.h" + +BEGIN_DEFINE_SPEC( + FSubLevelsSpec, + "Cesium.Unit.SubLevels", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) + +TObjectPtr pWorld; +TObjectPtr pSubLevel1; +TObjectPtr pLevelComponent1; +TObjectPtr pSubLevel2; +TObjectPtr pLevelComponent2; +TObjectPtr pGeoreference; +TObjectPtr pPawn; +FDelegateHandle subscriptionPostPIEStarted; + +END_DEFINE_SPEC(FSubLevelsSpec) + +using namespace CesiumTestHelpers; + +void FSubLevelsSpec::Define() { + BeforeEach([this]() { + if (IsValid(pWorld)) { + // Only run the below once in order to save time loading/unloading + // levels for every little test. + return; + } + + pWorld = FAutomationEditorCommonUtils::CreateNewMap(); + + pSubLevel1 = pWorld->SpawnActor(); + trackForPlay(pSubLevel1); + pSubLevel1->SetWorldAsset(TSoftObjectPtr( + FSoftObjectPath("/CesiumForUnreal/Tests/Maps/SingleCube.SingleCube"))); + pSubLevel1->SetIsTemporarilyHiddenInEditor(true); + pLevelComponent1 = + Cast(pSubLevel1->AddComponentByClass( + UCesiumSubLevelComponent::StaticClass(), + false, + FTransform::Identity, + false)); + trackForPlay(pLevelComponent1); + pLevelComponent1->SetOriginLongitudeLatitudeHeight( + FVector(10.0, 20.0, 1000.0)); + pSubLevel1->AddInstanceComponent(pLevelComponent1); + + pSubLevel2 = pWorld->SpawnActor(); + trackForPlay(pSubLevel2); + pSubLevel2->SetWorldAsset(TSoftObjectPtr(FSoftObjectPath( + "/CesiumForUnreal/Tests/Maps/ConeAndCylinder.ConeAndCylinder"))); + pSubLevel2->SetIsTemporarilyHiddenInEditor(true); + pLevelComponent2 = + Cast(pSubLevel2->AddComponentByClass( + UCesiumSubLevelComponent::StaticClass(), + false, + FTransform::Identity, + false)); + trackForPlay(pLevelComponent2); + pLevelComponent2->SetOriginLongitudeLatitudeHeight( + FVector(-25.0, 15.0, -5000.0)); + pSubLevel2->AddInstanceComponent(pLevelComponent2); + + pSubLevel1->LoadLevelInstance(); + pSubLevel2->LoadLevelInstance(); + + pGeoreference = nullptr; + for (TActorIterator it(pWorld); it; ++it) { + pGeoreference = *it; + } + + trackForPlay(pGeoreference); + + pPawn = pWorld->SpawnActor(); + pPawn->AddComponentByClass( + UCesiumOriginShiftComponent::StaticClass(), + false, + FTransform::Identity, + false); + trackForPlay(pPawn); + pPawn->AutoPossessPlayer = EAutoReceiveInput::Player0; + }); + + AfterEach([this]() { + pSubLevel1->SetIsTemporarilyHiddenInEditor(true); + pSubLevel2->SetIsTemporarilyHiddenInEditor(true); + }); + + It("initially hides sub-levels in the Editor", [this]() { + TestTrue("pGeoreference is valid", IsValid(pGeoreference)); + TestTrue("pSubLevel1 is valid", IsValid(pSubLevel1)); + TestTrue("pSubLevel2 is valid", IsValid(pSubLevel2)); + TestTrue( + "pSubLevel1 is hidden", + pSubLevel1->IsTemporarilyHiddenInEditor(true)); + TestTrue( + "pSubLevel2 is hidden", + pSubLevel1->IsTemporarilyHiddenInEditor(true)); + }); + + Describe( + "copies CesiumGeoreference origin changes to the active sub-level in the Editor", + [this]() { + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + pSubLevel1->SetIsTemporarilyHiddenInEditor(false); + }); + It("", EAsyncExecution::TaskGraphMainThread, [this]() { + TestFalse( + "pSubLevel1 is hidden", + pSubLevel1->IsTemporarilyHiddenInEditor(true)); + + pGeoreference->SetOriginLongitudeLatitudeHeight( + FVector(1.0, 2.0, 3.0)); + TestEqual("Longitude", pLevelComponent1->GetOriginLongitude(), 1.0); + TestEqual("Latitude", pLevelComponent1->GetOriginLatitude(), 2.0); + TestEqual("Height", pLevelComponent1->GetOriginHeight(), 3.0); + }); + }); + + Describe( + "copies active sub-level origin changes to the CesiumGeoreference in the Editor", + [this]() { + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + pSubLevel1->SetIsTemporarilyHiddenInEditor(false); + }); + It("", EAsyncExecution::TaskGraphMainThread, [this]() { + TestFalse( + "pSubLevel1 is hidden", + pSubLevel1->IsTemporarilyHiddenInEditor(true)); + + pLevelComponent1->SetOriginLongitudeLatitudeHeight( + FVector(4.0, 5.0, 6.0)); + TestEqual("Longitude", pGeoreference->GetOriginLongitude(), 4.0); + TestEqual("Latitude", pGeoreference->GetOriginLatitude(), 5.0); + TestEqual("Height", pGeoreference->GetOriginHeight(), 6.0); + }); + }); + + Describe( + "does not copy inactive sub-level origin changes to the CesiumGeoreference in the Editor", + [this]() { + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + // Set the sub-level active, wait a frame so it becomes so. + pSubLevel1->SetIsTemporarilyHiddenInEditor(false); + }); + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + // Set the sub-level inactive, wait a frame so it becomes so. + pSubLevel1->SetIsTemporarilyHiddenInEditor(true); + }); + It("", EAsyncExecution::TaskGraphMainThread, [this]() { + // Verify that the previously-active sub-level isn't affected by + // georeference origin changes. + double expectedLongitude = pGeoreference->GetOriginLongitude(); + double expectedLatitude = pGeoreference->GetOriginLatitude(); + double expectedHeight = pGeoreference->GetOriginHeight(); + + TestNotEqual("Longitude", expectedLongitude, 7.0); + TestNotEqual("Latitude", expectedLatitude, 8.0); + TestNotEqual("Height", expectedHeight, 9.0); + + pLevelComponent1->SetOriginLongitudeLatitudeHeight( + FVector(7.0, 8.0, 9.0)); + TestEqual( + "Longitude", + pGeoreference->GetOriginLongitude(), + expectedLongitude); + TestEqual( + "Latitude", + pGeoreference->GetOriginLatitude(), + expectedLatitude); + TestEqual("Height", pGeoreference->GetOriginHeight(), expectedHeight); + }); + }); + + Describe( + "ensures only one sub-level instance is visible in the editor at a time", + [this]() { + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + pSubLevel1->SetIsTemporarilyHiddenInEditor(false); + }); + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + TestFalse( + "pSubLevel1 is hidden", + pSubLevel1->IsTemporarilyHiddenInEditor(true)); + TestTrue( + "pSubLevel2 is hidden", + pSubLevel2->IsTemporarilyHiddenInEditor(true)); + + pSubLevel2->SetIsTemporarilyHiddenInEditor(false); + }); + It("", EAsyncExecution::TaskGraphMainThread, [this]() { + TestTrue( + "pSubLevel1 is hidden", + pSubLevel1->IsTemporarilyHiddenInEditor(true)); + TestFalse( + "pSubLevel2 is hidden", + pSubLevel2->IsTemporarilyHiddenInEditor(true)); + }); + }); + + Describe("activates the closest sub-level that is in range", [this]() { + LatentBeforeEach( + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + subscriptionPostPIEStarted = + FEditorDelegates::PostPIEStarted.AddLambda( + [done](bool isSimulating) { done.Execute(); }); + FRequestPlaySessionParams params{}; + GEditor->RequestPlaySession(params); + }); + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + FEditorDelegates::PostPIEStarted.Remove(subscriptionPostPIEStarted); + }); + LatentBeforeEach( + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + waitFor(done, GEditor->PlayWorld, 5.0f, [this]() { + return !findInPlay(pSubLevel1)->IsLoaded() && + !findInPlay(pSubLevel2)->IsLoaded(); + }); + }); + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + TestFalse("pSubLevel1 is loaded", findInPlay(pSubLevel1)->IsLoaded()); + TestFalse("pSubLevel2 is loaded", findInPlay(pSubLevel2)->IsLoaded()); + + // Move the player within range of the first sub-level + UCesiumSubLevelComponent* pPlayLevelComponent1 = + findInPlay(pLevelComponent1); + FVector origin1 = + findInPlay(pGeoreference) + ->TransformLongitudeLatitudeHeightPositionToUnreal(FVector( + pPlayLevelComponent1->GetOriginLongitude(), + pPlayLevelComponent1->GetOriginLatitude(), + pPlayLevelComponent1->GetOriginHeight())); + findInPlay(pPawn)->SetActorLocation(origin1); + }); + LatentBeforeEach( + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + waitFor(done, GEditor->PlayWorld, 5.0f, [this]() { + return findInPlay(pSubLevel1)->IsLoaded(); + }); + }); + It("", EAsyncExecution::TaskGraphMainThread, [this]() { + TestTrue("pSubLevel1 is loaded", findInPlay(pSubLevel1)->IsLoaded()); + TestFalse("pSubLevel2 is loaded", findInPlay(pSubLevel2)->IsLoaded()); + }); + AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() { + GEditor->RequestEndPlayMap(); + }); + }); + + Describe("handles a rapid load / unload / reload cycle", [this]() { + LatentBeforeEach( + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + subscriptionPostPIEStarted = + FEditorDelegates::PostPIEStarted.AddLambda( + [done](bool isSimulating) { done.Execute(); }); + FRequestPlaySessionParams params{}; + GEditor->RequestPlaySession(params); + }); + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + FEditorDelegates::PostPIEStarted.Remove(subscriptionPostPIEStarted); + }); + LatentBeforeEach( + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + waitFor(done, GEditor->PlayWorld, 5.0f, [this]() { + return !findInPlay(pSubLevel1)->IsLoaded() && + !findInPlay(pSubLevel2)->IsLoaded(); + }); + }); + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + TestFalse("pSubLevel1 is loaded", findInPlay(pSubLevel1)->IsLoaded()); + TestFalse("pSubLevel2 is loaded", findInPlay(pSubLevel2)->IsLoaded()); + + // Move the player within range of the first sub-level + UCesiumSubLevelComponent* pPlayLevelComponent1 = + findInPlay(pLevelComponent1); + FVector origin1 = + findInPlay(pGeoreference) + ->TransformLongitudeLatitudeHeightPositionToUnreal(FVector( + pPlayLevelComponent1->GetOriginLongitude(), + pPlayLevelComponent1->GetOriginLatitude(), + pPlayLevelComponent1->GetOriginHeight())); + findInPlay(pPawn)->SetActorLocation(origin1); + }); + LatentBeforeEach( + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + // Wait for the level to load. + waitFor(done, GEditor->PlayWorld, 5.0f, [this]() { + return findInPlay(pSubLevel1)->IsLoaded(); + }); + }); + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + // Move the player outside the sub-level, triggering an unload. + UCesiumSubLevelComponent* pPlayLevelComponent1 = + findInPlay(pLevelComponent1); + FVector origin1 = + findInPlay(pGeoreference) + ->TransformLongitudeLatitudeHeightPositionToUnreal(FVector( + pPlayLevelComponent1->GetOriginLongitude(), + pPlayLevelComponent1->GetOriginLatitude(), + pPlayLevelComponent1->GetOriginHeight() + 100000.0)); + findInPlay(pPawn)->SetActorLocation(origin1); + }); + BeforeEach(EAsyncExecution::TaskGraphMainThread, [this]() { + // Without waiting for the level to finish unloading, move the player back + // inside it. + UCesiumSubLevelComponent* pPlayLevelComponent1 = + findInPlay(pLevelComponent1); + FVector origin1 = + findInPlay(pGeoreference) + ->TransformLongitudeLatitudeHeightPositionToUnreal(FVector( + pPlayLevelComponent1->GetOriginLongitude(), + pPlayLevelComponent1->GetOriginLatitude(), + pPlayLevelComponent1->GetOriginHeight())); + findInPlay(pPawn)->SetActorLocation(origin1); + }); + LatentBeforeEach( + EAsyncExecution::TaskGraphMainThread, + [this](const FDoneDelegate& done) { + // Wait for the level to load. + waitFor(done, GEditor->PlayWorld, 5.0f, [this]() { + return findInPlay(pSubLevel1)->IsLoaded(); + }); + }); + It("", EAsyncExecution::TaskGraphMainThread, [this]() { + TestTrue("pSubLevel1 is loaded", findInPlay(pSubLevel1)->IsLoaded()); + TestFalse("pSubLevel2 is loaded", findInPlay(pSubLevel2)->IsLoaded()); + }); + AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() { + GEditor->RequestEndPlayMap(); + }); + }); +} + +#endif // #if WITH_EDITOR diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/UnrealAssetAccessor.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/UnrealAssetAccessor.spec.cpp new file mode 100644 index 0000000..48f9e46 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/UnrealAssetAccessor.spec.cpp @@ -0,0 +1,92 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "UnrealAssetAccessor.h" +#include "Async/Async.h" +#include "CesiumAsync/IAssetResponse.h" +#include "CesiumRuntime.h" +#include "HAL/PlatformFileManager.h" +#include "Misc/AutomationTest.h" +#include "Misc/FileHelper.h" +#include "Misc/Paths.h" + +BEGIN_DEFINE_SPEC( + FUnrealAssetAccessorSpec, + "Cesium.Unit.UnrealAssetAccessor", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) + +FString Filename; +std::string randomText = "Some random text."; +IPlatformFile* FileManager; + +void TestAccessorRequest(const FString& Uri, const std::string& expectedData) { + bool done = false; + + UnrealAssetAccessor accessor{}; + accessor.get(getAsyncSystem(), TCHAR_TO_UTF8(*Uri), {}) + .thenInMainThread( + [&](std::shared_ptr&& pRequest) { + const CesiumAsync::IAssetResponse* Response = pRequest->response(); + TestNotNull("Response", Response); + if (!Response) + return; + + std::span data = Response->data(); + TestEqual("data length", data.size(), expectedData.size()); + std::string s( + reinterpret_cast(data.data()), + data.size()); + TestEqual("data", s, expectedData); + done = true; + }); + + while (!done) { + accessor.tick(); + getAsyncSystem().dispatchMainThreadTasks(); + } +} + +END_DEFINE_SPEC(FUnrealAssetAccessorSpec) + +void FUnrealAssetAccessorSpec::Define() { + BeforeEach([this]() { + Filename = FPaths::ConvertRelativePathToFull( + FPaths::CreateTempFilename(*FPaths::ProjectSavedDir())); + + FileManager = &FPlatformFileManager::Get().GetPlatformFile(); + FFileHelper::SaveStringToFile( + UTF8_TO_TCHAR(randomText.c_str()), + *Filename, + FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM); + }); + + AfterEach([this]() { FileManager->DeleteFile(*Filename); }); + + It("Fails with non-existant file:/// URLs", [this]() { + FString Uri = TEXT("file:///") + Filename; + Uri.ReplaceCharInline('\\', '/'); + Uri.ReplaceInline(TEXT(" "), TEXT("%20")); + Uri += ".bogusExtension"; + + TestAccessorRequest(Uri, ""); + }); + + It("Can access file:/// URLs", [this]() { + FString Uri = TEXT("file:///") + Filename; + Uri.ReplaceCharInline('\\', '/'); + Uri.ReplaceInline(TEXT(" "), TEXT("%20")); + + TestAccessorRequest(Uri, randomText); + }); + + It("Can access file:/// URLs with unnecessary query params", [this]() { + FString Uri = TEXT("file:///") + Filename; + Uri.ReplaceCharInline('\\', '/'); + Uri.ReplaceInline(TEXT(" "), TEXT("%20")); + Uri.Append("?version=4.27.1"); + + TestAccessorRequest(Uri, randomText); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/UnrealMetadataConversions.spec.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/UnrealMetadataConversions.spec.cpp new file mode 100644 index 0000000..f4e81ea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/UnrealMetadataConversions.spec.cpp @@ -0,0 +1,312 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "UnrealMetadataConversions.h" +#include "CesiumTestHelpers.h" +#include "Misc/AutomationTest.h" + +#include + +BEGIN_DEFINE_SPEC( + FUnrealMetadataConversionsSpec, + "Cesium.Unit.MetadataConversions", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +END_DEFINE_SPEC(FUnrealMetadataConversionsSpec) + +void FUnrealMetadataConversionsSpec::Define() { + + Describe("FIntPoint", [this]() { + It("converts from glm::ivec2", [this]() { + TestEqual( + "value", + UnrealMetadataConversions::toIntPoint(glm::ivec2(-1, 2)), + FIntPoint(-1, 2)); + }); + + It("converts from string", [this]() { + std::string_view str("X=1 Y=2"); + TestEqual( + "value", + UnrealMetadataConversions::toIntPoint(str, FIntPoint(0)), + FIntPoint(1, 2)); + }); + + It("uses default value for invalid string", [this]() { + std::string_view str("X=1"); + TestEqual( + "partial input", + UnrealMetadataConversions::toIntPoint(str, FIntPoint(0)), + FIntPoint(0)); + + str = std::string_view("R=0.5 G=0.5"); + TestEqual( + "bad format", + UnrealMetadataConversions::toIntPoint(str, FIntPoint(0)), + FIntPoint(0)); + }); + }); + + Describe("FVector2D", [this]() { + It("converts from glm::dvec2", [this]() { + TestEqual( + "value", + UnrealMetadataConversions::toVector2D(glm::dvec2(-1.0, 2.0)), + FVector2D(-1.0, 2.0)); + }); + + It("converts from string", [this]() { + std::string_view str("X=1.5 Y=2.5"); + TestEqual( + "value", + UnrealMetadataConversions::toVector2D(str, FVector2D::Zero()), + FVector2D(1.5, 2.5)); + }); + + It("uses default value for invalid string", [this]() { + std::string_view str("X=1"); + TestEqual( + "partial input", + UnrealMetadataConversions::toVector2D(str, FVector2D::Zero()), + FVector2D::Zero()); + + str = std::string_view("R=0.5 G=0.5"); + TestEqual( + "bad format", + UnrealMetadataConversions::toVector2D(str, FVector2D::Zero()), + FVector2D::Zero()); + }); + }); + + Describe("FIntVector", [this]() { + It("converts from glm::ivec3", [this]() { + TestEqual( + "value", + UnrealMetadataConversions::toIntVector(glm::ivec3(-1, 2, 4)), + FIntVector(-1, 2, 4)); + }); + + It("converts from string", [this]() { + std::string_view str("X=1 Y=2 Z=4"); + TestEqual( + "value", + UnrealMetadataConversions::toIntVector(str, FIntVector(0)), + FIntVector(1, 2, 4)); + }); + + It("uses default value for invalid string", [this]() { + std::string_view str("X=1 Y=2"); + TestEqual( + "partial input", + UnrealMetadataConversions::toIntVector(str, FIntVector(0)), + FIntVector(0)); + + str = std::string_view("R=0.5 G=0.5 B=1"); + TestEqual( + "bad format", + UnrealMetadataConversions::toIntVector(str, FIntVector(0)), + FIntVector(0)); + }); + }); + + Describe("FVector3f", [this]() { + It("converts from glm::vec3", [this]() { + TestEqual( + "value", + UnrealMetadataConversions::toVector3f(glm::vec3(1.0f, 2.3f, 4.56f)), + FVector3f(1.0f, 2.3f, 4.56f)); + }); + + It("converts from string", [this]() { + std::string_view str("X=1 Y=2 Z=3"); + TestEqual( + "value", + UnrealMetadataConversions ::toVector3f(str, FVector3f::Zero()), + FVector3f(1.0f, 2.0f, 3.0f)); + }); + + It("uses default value for invalid string", [this]() { + std::string_view str("X=1 Y=2"); + TestEqual( + "partial input", + UnrealMetadataConversions ::toVector3f(str, FVector3f::Zero()), + FVector3f(0.0f)); + + str = std::string_view("R=0.5 G=0.5 B=0.5"); + TestEqual( + "bad format", + UnrealMetadataConversions ::toVector3f(str, FVector3f::Zero()), + FVector3f(0.0f)); + }); + }); + + Describe("FVector", [this]() { + It("converts from glm::dvec3", [this]() { + TestEqual( + "value", + UnrealMetadataConversions::toVector(glm::dvec3(1.0, 2.3, 4.56)), + FVector(1.0, 2.3, 4.56)); + }); + + It("converts from string", [this]() { + std::string_view str("X=1.5 Y=2.5 Z=3.5"); + TestEqual( + "value", + UnrealMetadataConversions::toVector(str, FVector::Zero()), + FVector(1.5f, 2.5f, 3.5f)); + }); + + It("uses default value for invalid string", [this]() { + std::string_view str("X=1 Y=2"); + TestEqual( + "partial input", + UnrealMetadataConversions::toVector(str, FVector::Zero()), + FVector::Zero()); + + str = std::string_view("R=0.5 G=0.5 B=0.5"); + TestEqual( + "bad format", + UnrealMetadataConversions::toVector(str, FVector::Zero()), + FVector::Zero()); + }); + }); + + Describe("FVector4", [this]() { + It("converts from glm::dvec4", [this]() { + TestEqual( + "value", + UnrealMetadataConversions::toVector4( + glm::dvec4(1.0, 2.3, 4.56, 7.89)), + FVector4(1.0, 2.3, 4.56, 7.89)); + }); + + It("converts from string", [this]() { + std::string_view str("X=1.5 Y=2.5 Z=3.5 W=4.5"); + TestEqual( + "with W component", + UnrealMetadataConversions::toVector4(str, FVector4::Zero()), + FVector4(1.5, 2.5, 3.5, 4.5)); + + str = std::string_view("X=1.5 Y=2.5 Z=3.5"); + TestEqual( + "without W component", + UnrealMetadataConversions::toVector4(str, FVector4::Zero()), + FVector4(1.5, 2.5, 3.5, 1.0)); + }); + + It("uses default value for invalid string", [this]() { + std::string_view str("X=1 Y=2"); + TestEqual( + "partial input", + UnrealMetadataConversions::toVector4(str, FVector4::Zero()), + FVector4::Zero()); + + str = std::string_view("R=0.5 G=0.5 B=0.5 A=1.0"); + TestEqual( + "bad format", + UnrealMetadataConversions::toVector4(str, FVector4::Zero()), + FVector4::Zero()); + }); + }); + + Describe("FMatrix", [this]() { + It("converts from glm::dmat4", [this]() { + // clang-format off + glm::dmat4 input = glm::dmat4( + 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, + 0.0, 1.0, 0.0, 1.0, + 1.0, 0.0, 0.0, 1.0); + // clang-format on + input = glm::transpose(input); + + FMatrix expected( + FPlane4d(1.0, 2.0, 3.0, 4.0), + FPlane4d(5.0, 6.0, 7.0, 8.0), + FPlane4d(0.0, 1.0, 0.0, 1.0), + FPlane4d(1.0, 0.0, 0.0, 1.0)); + TestEqual("value", UnrealMetadataConversions::toMatrix(input), expected); + }); + }); + + Describe("FString", [this]() { + It("converts from std::string_view", [this]() { + TestEqual( + "std::string_view", + UnrealMetadataConversions::toString(std::string_view("Hello")), + FString("Hello")); + }); + + It("converts from vecN", [this]() { + std::string expected("X=1 Y=2"); + TestEqual( + "vec2", + UnrealMetadataConversions::toString(glm::u8vec2(1, 2)), + FString(expected.c_str())); + + expected = "X=" + std::to_string(4.5f) + " Y=" + std::to_string(3.21f) + + " Z=" + std::to_string(123.0f); + TestEqual( + "vec3", + UnrealMetadataConversions::toString(glm::vec3(4.5f, 3.21f, 123.0f)), + FString(expected.c_str())); + + expected = "X=" + std::to_string(1.0f) + " Y=" + std::to_string(2.0f) + + " Z=" + std::to_string(3.0f) + " W=" + std::to_string(4.0f); + TestEqual( + "vec4", + UnrealMetadataConversions::toString( + glm::vec4(1.0f, 2.0f, 3.0f, 4.0f)), + FString(expected.c_str())); + }); + + It("converts from matN", [this]() { + // clang-format off + glm::mat2 mat2( + 0.0f, 1.0f, + 2.0f, 3.0f); + mat2 = glm::transpose(mat2); + + std::string expected = + "[" + std::to_string(0.0f) + " " + std::to_string(1.0f) + "] " + + "[" + std::to_string(2.0f) + " " + std::to_string(3.0f) + "]"; + // clang-format on + TestEqual( + "mat2", + UnrealMetadataConversions::toString(mat2), + FString(expected.c_str())); + + // This is written as transposed because glm::transpose only compiles for + // floating point types. + // clang-format off + glm::i8mat3x3 mat3( + -1, 4, 7, + 2, -5, 8, + 3, 6, -9); + // clang-format on + + expected = "[-1 2 3] [4 -5 6] [7 8 -9]"; + TestEqual( + "mat3", + UnrealMetadataConversions::toString(mat3), + FString(expected.c_str())); + + // This is written as transposed because glm::transpose only compiles for + // floating point types. + // clang-format off + glm::u8mat4x4 mat4( + 0, 4, 8, 12, + 1, 5, 9, 13, + 2, 6, 10, 14, + 3, 7, 11, 15); + // clang-format on + + expected = "[0 1 2 3] [4 5 6 7] [8 9 10 11] [12 13 14 15]"; + TestEqual( + "mat4", + UnrealMetadataConversions::toString(mat4), + FString(expected.c_str())); + }); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealAssetAccessor.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealAssetAccessor.cpp new file mode 100644 index 0000000..6ede3bb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealAssetAccessor.cpp @@ -0,0 +1,439 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "UnrealAssetAccessor.h" +#include "Async/Async.h" +#include "Async/AsyncWork.h" + +#include "CesiumAsync/AsyncSystem.h" +#include "CesiumAsync/IAssetRequest.h" +#include "CesiumAsync/IAssetResponse.h" +#include "CesiumCommon.h" +#include "CesiumRuntime.h" +#include "HttpManager.h" +#include "HttpModule.h" +#include "Interfaces/IHttpRequest.h" +#include "Interfaces/IHttpResponse.h" +#include "Interfaces/IPluginManager.h" +#include "Misc/App.h" +#include "Misc/EngineVersion.h" +#include "Misc/FileHelper.h" +#include +#include +#include +#include +#include + +namespace { + +CesiumAsync::HttpHeaders parseHeaders(const TArray& unrealHeaders) { + CesiumAsync::HttpHeaders result; + for (const FString& header : unrealHeaders) { + int32_t separator = -1; + if (header.FindChar(':', separator)) { + FString fstrKey = header.Left(separator); + FString fstrValue = header.Right(header.Len() - separator - 2); + std::string key = std::string(TCHAR_TO_UTF8(*fstrKey)); + std::string value = std::string(TCHAR_TO_UTF8(*fstrValue)); + result.insert({std::move(key), std::move(value)}); + } + } + + return result; +} + +class UnrealAssetResponse : public CesiumAsync::IAssetResponse { +public: + UnrealAssetResponse(FHttpResponsePtr pResponse) + : _pResponse(pResponse), + _headers(parseHeaders(pResponse->GetAllHeaders())) {} + + virtual uint16_t statusCode() const override { + return static_cast(this->_pResponse->GetResponseCode()); + } + + virtual std::string contentType() const override { + return TCHAR_TO_UTF8(*this->_pResponse->GetContentType()); + } + + virtual const CesiumAsync::HttpHeaders& headers() const override { + return this->_headers; + } + + virtual std::span data() const override { + const TArray& content = this->_pResponse->GetContent(); + return std::span( + reinterpret_cast(content.GetData()), + content.Num()); + } + +private: + FHttpResponsePtr _pResponse; + CesiumAsync::HttpHeaders _headers; +}; + +class UnrealAssetRequest : public CesiumAsync::IAssetRequest { +public: + UnrealAssetRequest(FHttpRequestPtr pRequest, FHttpResponsePtr pResponse) + : _pRequest(pRequest), + _pResponse(std::make_unique(pResponse)) { + this->_headers = parseHeaders(this->_pRequest->GetAllHeaders()); + this->_url = TCHAR_TO_UTF8(*this->_pRequest->GetURL()); + this->_method = TCHAR_TO_UTF8(*this->_pRequest->GetVerb()); + } + + virtual const std::string& method() const { return this->_method; } + + virtual const std::string& url() const { return this->_url; } + + virtual const CesiumAsync::HttpHeaders& headers() const override { + return _headers; + } + + virtual const CesiumAsync::IAssetResponse* response() const override { + return this->_pResponse.get(); + } + +private: + FHttpRequestPtr _pRequest; + std::unique_ptr _pResponse; + std::string _url; + std::string _method; + CesiumAsync::HttpHeaders _headers; +}; + +} // namespace + +UnrealAssetAccessor::UnrealAssetAccessor() + : _userAgent(), _cesiumRequestHeaders() { + FString OsVersion, OsSubVersion; + FPlatformMisc::GetOSVersions(OsVersion, OsSubVersion); + OsVersion += " " + FPlatformMisc::GetOSVersion(); + + IPluginManager& PluginManager = IPluginManager::Get(); + TSharedPtr pCesiumPlugin = + PluginManager.FindPlugin("CesiumForUnreal"); + + FString version = "unknown"; + if (pCesiumPlugin) { + version = pCesiumPlugin->GetDescriptor().VersionName; + } + + const TCHAR* projectName = FApp::GetProjectName(); + FString engine = "Unreal Engine " + FEngineVersion::Current().ToString(); + + this->_userAgent = TEXT("Mozilla/5.0 ("); + this->_userAgent += OsVersion; + this->_userAgent += TEXT(") Cesium For Unreal/"); + this->_userAgent += version; + this->_userAgent += TEXT(" (Project "); + this->_userAgent += projectName; + this->_userAgent += " Engine "; + this->_userAgent += engine; + this->_userAgent += TEXT(")"); + + this->_cesiumRequestHeaders.Add( + TEXT("X-Cesium-Client"), + TEXT("Cesium For Unreal")); + this->_cesiumRequestHeaders.Add(TEXT("X-Cesium-Client-Version"), version); + this->_cesiumRequestHeaders.Add(TEXT("X-Cesium-Client-Project"), projectName); + this->_cesiumRequestHeaders.Add(TEXT("X-Cesium-Client-Engine"), engine); + this->_cesiumRequestHeaders.Add(TEXT("X-Cesium-Client-OS"), OsVersion); +} + +namespace { + +const char fileProtocol[] = "file:///"; + +bool isFile(const std::string& url) { + return url.compare(0, sizeof(fileProtocol) - 1, fileProtocol) == 0; +} + +void rejectPromiseOnUnsuccessfulConnection( + const CesiumAsync::Promise>& + promise, + FHttpRequestPtr pRequest) { +#if ENGINE_VERSION_5_4_OR_HIGHER + if (pRequest->GetStatus() == EHttpRequestStatus::Failed) { + EHttpFailureReason failureReason = pRequest->GetFailureReason(); + promise.reject(std::runtime_error(fmt::format( + "Request failed: {}", + TCHAR_TO_UTF8(LexToString(failureReason))))); + } else { + promise.reject(std::runtime_error(fmt::format( + "Request not successful: {}", + TCHAR_TO_UTF8(ToString(pRequest->GetStatus()))))); + } +#else + if (pRequest->GetStatus() == EHttpRequestStatus::Failed_ConnectionError) { + promise.reject(std::runtime_error("Connection failed.")); + } else { + promise.reject(std::runtime_error("Request failed.")); + } +#endif +} + +} // namespace + +CesiumAsync::Future> +UnrealAssetAccessor::get( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::string& url, + const std::vector& headers) { + + CESIUM_TRACE_BEGIN_IN_TRACK("requestAsset"); + + if (isFile(url)) { + return getFromFile(asyncSystem, url, headers); + } + + const FString& userAgent = this->_userAgent; + const TMap& cesiumRequestHeaders = + this->_cesiumRequestHeaders; + + return asyncSystem.createFuture>( + [&url, &headers, &userAgent, &cesiumRequestHeaders](const auto& promise) { + FHttpModule& httpModule = FHttpModule::Get(); + TSharedRef pRequest = + httpModule.CreateRequest(); + pRequest->SetURL(UTF8_TO_TCHAR(url.c_str())); + + for (const auto& header : headers) { + pRequest->SetHeader( + UTF8_TO_TCHAR(header.first.c_str()), + UTF8_TO_TCHAR(header.second.c_str())); + } + + for (const auto& header : cesiumRequestHeaders) { + pRequest->SetHeader(header.Key, header.Value); + } + + pRequest->AppendToHeader(TEXT("User-Agent"), userAgent); + + pRequest->OnProcessRequestComplete().BindLambda( + [promise, CESIUM_TRACE_LAMBDA_CAPTURE_TRACK()]( + FHttpRequestPtr pRequest, + FHttpResponsePtr pResponse, + bool connectedSuccessfully) mutable { + CESIUM_TRACE_USE_CAPTURED_TRACK(); + CESIUM_TRACE_END_IN_TRACK("requestAsset"); + + if (connectedSuccessfully) { + promise.resolve( + std::make_unique(pRequest, pResponse)); + } else { + rejectPromiseOnUnsuccessfulConnection(promise, pRequest); + } + }); + + pRequest->ProcessRequest(); + }); +} + +CesiumAsync::Future> +UnrealAssetAccessor::request( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::string& verb, + const std::string& url, + const std::vector& headers, + const std::span& contentPayload) { + + const FString& userAgent = this->_userAgent; + const TMap& cesiumRequestHeaders = + this->_cesiumRequestHeaders; + + return asyncSystem.createFuture>( + [&verb, + &url, + &headers, + &userAgent, + &cesiumRequestHeaders, + &contentPayload](const auto& promise) { + FHttpModule& httpModule = FHttpModule::Get(); + TSharedRef pRequest = + httpModule.CreateRequest(); + pRequest->SetVerb(UTF8_TO_TCHAR(verb.c_str())); + pRequest->SetURL(UTF8_TO_TCHAR(url.c_str())); + + for (const auto& header : headers) { + pRequest->SetHeader( + UTF8_TO_TCHAR(header.first.c_str()), + UTF8_TO_TCHAR(header.second.c_str())); + } + + for (const auto& header : cesiumRequestHeaders) { + pRequest->SetHeader(header.Key, header.Value); + } + + pRequest->AppendToHeader(TEXT("User-Agent"), userAgent); + + pRequest->SetContent(TArray( + reinterpret_cast(contentPayload.data()), + contentPayload.size())); + + pRequest->OnProcessRequestComplete().BindLambda( + [promise]( + FHttpRequestPtr pRequest, + FHttpResponsePtr pResponse, + bool connectedSuccessfully) { + if (connectedSuccessfully) { + promise.resolve( + std::make_unique(pRequest, pResponse)); + } else { + rejectPromiseOnUnsuccessfulConnection(promise, pRequest); + } + }); + + pRequest->ProcessRequest(); + }); +} + +void UnrealAssetAccessor::tick() noexcept { + FHttpManager& manager = FHttpModule::Get().GetHttpManager(); + manager.Tick(0.0f); +} + +namespace { + +class UnrealFileAssetRequestResponse : public CesiumAsync::IAssetRequest, + public CesiumAsync::IAssetResponse { +public: + UnrealFileAssetRequestResponse( + std::string&& url, + uint16_t statusCode, + TArray64&& data) + : _url(std::move(url)), _statusCode(statusCode), _data(data) {} + + virtual const std::string& method() const { return getMethod; } + + virtual const std::string& url() const { return this->_url; } + + virtual const CesiumAsync::HttpHeaders& headers() const override { + return emptyHeaders; + } + + virtual const CesiumAsync::IAssetResponse* response() const override { + return this; + } + + virtual uint16_t statusCode() const override { return this->_statusCode; } + + virtual std::string contentType() const override { return std::string(); } + + virtual std::span data() const override { + return std::span( + reinterpret_cast(this->_data.GetData()), + size_t(this->_data.Num())); + } + +private: + static const std::string getMethod; + static const CesiumAsync::HttpHeaders emptyHeaders; + + std::string _url; + uint16_t _statusCode; + TArray64 _data; +}; + +const std::string UnrealFileAssetRequestResponse::getMethod = "GET"; +const CesiumAsync::HttpHeaders UnrealFileAssetRequestResponse::emptyHeaders{}; + +std::string convertFileUriToFilename(const std::string& url) { + // According to the uriparser docs, both uriUriStringToWindowsFilenameA and + // uriUriStringToUnixFilenameA require an output buffer with space for at most + // length(url)+1 characters. + // https://uriparser.github.io/doc/api/latest/Uri_8h.html#a4afbc8453c7013b9618259bc57d81a39 + std::string result(url.size() + 1, '\0'); + +#ifdef _WIN32 + int errorCode = uriUriStringToWindowsFilenameA(url.c_str(), result.data()); +#else + int errorCode = uriUriStringToUnixFilenameA(url.c_str(), result.data()); +#endif + + // Truncate the string if necessary by finding the first null character. + size_t end = result.find('\0'); + if (end != std::string::npos) { + result.resize(end); + } + + // Remove query parameters from the URL if present, as they are no longer + // ignored by Unreal. + size_t pos = result.find("?"); + if (pos != std::string::npos) { + result.erase(pos); + } + + return result; +} + +class FCesiumReadFileWorker : public FNonAbandonableTask { +public: + FCesiumReadFileWorker( + const std::string& url, + const CesiumAsync::AsyncSystem& asyncSystem) + : _url(url), + _promise( + asyncSystem + .createPromise>()) { + } + + FORCEINLINE TStatId GetStatId() const { + RETURN_QUICK_DECLARE_CYCLE_STAT( + FCesiumReadFileWorker, + STATGROUP_ThreadPoolAsyncTasks); + } + + CesiumAsync::Future> GetFuture() { + return this->_promise.getFuture(); + } + + void DoWork() { + FString filename = + UTF8_TO_TCHAR(convertFileUriToFilename(this->_url).c_str()); + TArray64 data; + if (FFileHelper::LoadFileToArray(data, *filename)) { + this->_promise.resolve(std::make_shared( + std::move(this->_url), + 200, + std::move(data))); + } else { + this->_promise.resolve(std::make_shared( + std::move(this->_url), + 404, + TArray64())); + } + } + +private: + std::string _url; + CesiumAsync::Promise> _promise; +}; + +} // namespace + +CesiumAsync::Future> +UnrealAssetAccessor::getFromFile( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::string& url, + const std::vector& headers) { + check(!url.empty()); + + auto pTaskOwner = + std::make_unique>(url, asyncSystem); + + FAsyncTask* pTask = pTaskOwner.get(); + + CesiumAsync::Future> future = + pTask->GetTask().GetFuture().thenInWorkerThread( + [pTaskOwner = std::move(pTaskOwner)]( + std::shared_ptr&& pRequest) { + // This lambda, via its capture, keeps the task instance alive until + // it is complete. + pTaskOwner->EnsureCompletion(false, false); + return pRequest; + }); + + pTask->StartBackgroundTask(GIOThreadPool); + + return future; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealMetadataConversions.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealMetadataConversions.cpp new file mode 100644 index 0000000..3b71920 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealMetadataConversions.cpp @@ -0,0 +1,286 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "UnrealMetadataConversions.h" + +ECesiumMetadataBlueprintType +CesiumMetadataValueTypeToBlueprintType(FCesiumMetadataValueType ValueType) { + if (ValueType.bIsArray) { + return ECesiumMetadataBlueprintType::Array; + } + + ECesiumMetadataType type = ValueType.Type; + ECesiumMetadataComponentType componentType = ValueType.ComponentType; + + if (type == ECesiumMetadataType::Boolean) { + return ECesiumMetadataBlueprintType::Boolean; + } + + if (type == ECesiumMetadataType::String) { + return ECesiumMetadataBlueprintType::String; + } + + if (type == ECesiumMetadataType::Scalar) { + switch (componentType) { + case ECesiumMetadataComponentType::Uint8: + return ECesiumMetadataBlueprintType::Byte; + case ECesiumMetadataComponentType::Int8: + case ECesiumMetadataComponentType::Int16: + case ECesiumMetadataComponentType::Uint16: + case ECesiumMetadataComponentType::Int32: + return ECesiumMetadataBlueprintType::Integer; + case ECesiumMetadataComponentType::Uint32: + case ECesiumMetadataComponentType::Int64: + return ECesiumMetadataBlueprintType::Integer64; + case ECesiumMetadataComponentType::Float32: + return ECesiumMetadataBlueprintType::Float; + case ECesiumMetadataComponentType::Float64: + return ECesiumMetadataBlueprintType::Float64; + case ECesiumMetadataComponentType::Uint64: + default: + return ECesiumMetadataBlueprintType::String; + } + } + + if (type == ECesiumMetadataType::Vec2) { + switch (componentType) { + case ECesiumMetadataComponentType::Uint8: + case ECesiumMetadataComponentType::Int8: + case ECesiumMetadataComponentType::Int16: + case ECesiumMetadataComponentType::Uint16: + case ECesiumMetadataComponentType::Int32: + return ECesiumMetadataBlueprintType::IntPoint; + default: + return ECesiumMetadataBlueprintType::Vector2D; + } + } + + if (type == ECesiumMetadataType::Vec3) { + switch (componentType) { + case ECesiumMetadataComponentType::Uint8: + case ECesiumMetadataComponentType::Int8: + case ECesiumMetadataComponentType::Int16: + case ECesiumMetadataComponentType::Uint16: + case ECesiumMetadataComponentType::Int32: + return ECesiumMetadataBlueprintType::IntVector; + case ECesiumMetadataComponentType::Float32: + return ECesiumMetadataBlueprintType::Vector3f; + default: + return ECesiumMetadataBlueprintType::Vector3; + } + } + + if (type == ECesiumMetadataType::Vec4) { + return ECesiumMetadataBlueprintType::Vector4; + } + + if (type == ECesiumMetadataType::Mat2 || type == ECesiumMetadataType::Mat3 || + type == ECesiumMetadataType::Mat4) { + return ECesiumMetadataBlueprintType::Matrix; + } + + return ECesiumMetadataBlueprintType::None; +} + +ECesiumMetadataBlueprintType CesiumMetadataTrueTypeToBlueprintType( + ECesiumMetadataTrueType_DEPRECATED trueType) { + switch (trueType) { + case ECesiumMetadataTrueType_DEPRECATED::Boolean_DEPRECATED: + return ECesiumMetadataBlueprintType::Boolean; + case ECesiumMetadataTrueType_DEPRECATED::Uint8_DEPRECATED: + return ECesiumMetadataBlueprintType::Byte; + case ECesiumMetadataTrueType_DEPRECATED::Int8_DEPRECATED: + case ECesiumMetadataTrueType_DEPRECATED::Int16_DEPRECATED: + case ECesiumMetadataTrueType_DEPRECATED::Uint16_DEPRECATED: + case ECesiumMetadataTrueType_DEPRECATED::Int32_DEPRECATED: + // TODO: remove this one + case ECesiumMetadataTrueType_DEPRECATED::Uint32_DEPRECATED: + return ECesiumMetadataBlueprintType::Integer; + case ECesiumMetadataTrueType_DEPRECATED::Int64_DEPRECATED: + return ECesiumMetadataBlueprintType::Integer64; + case ECesiumMetadataTrueType_DEPRECATED::Float32_DEPRECATED: + return ECesiumMetadataBlueprintType::Float; + case ECesiumMetadataTrueType_DEPRECATED::Float64_DEPRECATED: + return ECesiumMetadataBlueprintType::Float64; + case ECesiumMetadataTrueType_DEPRECATED::Uint64_DEPRECATED: + case ECesiumMetadataTrueType_DEPRECATED::String_DEPRECATED: + return ECesiumMetadataBlueprintType::String; + case ECesiumMetadataTrueType_DEPRECATED::Array_DEPRECATED: + return ECesiumMetadataBlueprintType::Array; + default: + return ECesiumMetadataBlueprintType::None; + } +} + +ECesiumMetadataTrueType_DEPRECATED +CesiumMetadataValueTypeToTrueType(FCesiumMetadataValueType ValueType) { + if (ValueType.bIsArray) { + return ECesiumMetadataTrueType_DEPRECATED::Array_DEPRECATED; + } + + CesiumGltf::PropertyType type = CesiumGltf::PropertyType(ValueType.Type); + CesiumGltf::PropertyComponentType componentType = + CesiumGltf::PropertyComponentType(ValueType.ComponentType); + + if (type == CesiumGltf::PropertyType::Boolean) { + return ECesiumMetadataTrueType_DEPRECATED::Boolean_DEPRECATED; + } + + if (type == CesiumGltf::PropertyType::Scalar) { + switch (componentType) { + case CesiumGltf::PropertyComponentType::Uint8: + return ECesiumMetadataTrueType_DEPRECATED::Uint8_DEPRECATED; + case CesiumGltf::PropertyComponentType::Int8: + return ECesiumMetadataTrueType_DEPRECATED::Int8_DEPRECATED; + case CesiumGltf::PropertyComponentType::Uint16: + return ECesiumMetadataTrueType_DEPRECATED::Uint16_DEPRECATED; + case CesiumGltf::PropertyComponentType::Int16: + return ECesiumMetadataTrueType_DEPRECATED::Int16_DEPRECATED; + case CesiumGltf::PropertyComponentType::Uint32: + return ECesiumMetadataTrueType_DEPRECATED::Uint32_DEPRECATED; + case CesiumGltf::PropertyComponentType::Int32: + return ECesiumMetadataTrueType_DEPRECATED::Int32_DEPRECATED; + case CesiumGltf::PropertyComponentType::Int64: + return ECesiumMetadataTrueType_DEPRECATED::Int64_DEPRECATED; + case CesiumGltf::PropertyComponentType::Uint64: + return ECesiumMetadataTrueType_DEPRECATED::Uint64_DEPRECATED; + case CesiumGltf::PropertyComponentType::Float32: + return ECesiumMetadataTrueType_DEPRECATED::Float32_DEPRECATED; + case CesiumGltf::PropertyComponentType::Float64: + return ECesiumMetadataTrueType_DEPRECATED::Float64_DEPRECATED; + default: + return ECesiumMetadataTrueType_DEPRECATED::None_DEPRECATED; + } + } + + if (type == CesiumGltf::PropertyType::String) { + return ECesiumMetadataTrueType_DEPRECATED::String_DEPRECATED; + } + + return ECesiumMetadataTrueType_DEPRECATED::None_DEPRECATED; +} + +/*static*/ FIntPoint +UnrealMetadataConversions::toIntPoint(const glm::ivec2& vec2) { + return FIntPoint(vec2[0], vec2[1]); +} + +/*static*/ FIntPoint UnrealMetadataConversions::toIntPoint( + const std::string_view& string, + const FIntPoint& defaultValue) { + FString unrealString = UnrealMetadataConversions::toString(string); + + // For some reason, FIntPoint doesn't have an InitFromString method, so + // copy the one from FVector. + int32 X = 0, Y = 0; + const bool bSuccessful = FParse::Value(*unrealString, TEXT("X="), X) && + FParse::Value(*unrealString, TEXT("Y="), Y); + return bSuccessful ? FIntPoint(X, Y) : defaultValue; +} + +/*static*/ FVector2D +UnrealMetadataConversions::toVector2D(const glm::dvec2& vec2) { + return FVector2D(vec2[0], vec2[1]); +} + +/*static*/ FVector2D UnrealMetadataConversions::toVector2D( + const std::string_view& string, + const FVector2D& defaultValue) { + FString unrealString = UnrealMetadataConversions::toString(string); + FVector2D result; + return result.InitFromString(unrealString) ? result : defaultValue; +} + +/*static*/ FIntVector +UnrealMetadataConversions::toIntVector(const glm::ivec3& vec3) { + return FIntVector(vec3[0], vec3[1], vec3[2]); +} + +/*static*/ FIntVector UnrealMetadataConversions::toIntVector( + const std::string_view& string, + const FIntVector& defaultValue) { + FString unrealString = UnrealMetadataConversions::toString(string); + // For some reason, FIntVector doesn't have an InitFromString method, so + // copy the one from FVector. + int32 X = 0, Y = 0, Z = 0; + const bool bSuccessful = FParse::Value(*unrealString, TEXT("X="), X) && + FParse::Value(*unrealString, TEXT("Y="), Y) && + FParse::Value(*unrealString, TEXT("Z="), Z); + return bSuccessful ? FIntVector(X, Y, Z) : defaultValue; +} + +/*static*/ FVector3f +UnrealMetadataConversions::toVector3f(const glm::vec3& vec3) { + return FVector3f(vec3[0], vec3[1], vec3[2]); +} + +/*static*/ FVector3f UnrealMetadataConversions::toVector3f( + const std::string_view& string, + const FVector3f& defaultValue) { + FString unrealString = UnrealMetadataConversions::toString(string); + FVector3f result; + return result.InitFromString(unrealString) ? result : defaultValue; +} + +/*static*/ FVector UnrealMetadataConversions::toVector(const glm::dvec3& vec3) { + return FVector(vec3[0], vec3[1], vec3[2]); +} + +/*static*/ FVector UnrealMetadataConversions::toVector( + const std::string_view& string, + const FVector& defaultValue) { + FString unrealString = UnrealMetadataConversions::toString(string); + FVector result; + return result.InitFromString(unrealString) ? result : defaultValue; +} + +/*static*/ FVector4 +UnrealMetadataConversions::toVector4(const glm::dvec4& vec4) { + return FVector4(vec4[0], vec4[1], vec4[2], vec4[3]); +} + +/*static*/ FVector4 UnrealMetadataConversions::toVector4( + const std::string_view& string, + const FVector4& defaultValue) { + FString unrealString = UnrealMetadataConversions::toString(string); + FVector4 result; + return result.InitFromString(unrealString) ? result : defaultValue; +} + +/*static*/ FMatrix UnrealMetadataConversions::toMatrix(const glm::dmat4& mat4) { + // glm is column major, but Unreal is row major. + FPlane4d row1( + static_cast(mat4[0][0]), + static_cast(mat4[1][0]), + static_cast(mat4[2][0]), + static_cast(mat4[3][0])); + + FPlane4d row2( + static_cast(mat4[0][1]), + static_cast(mat4[1][1]), + static_cast(mat4[2][1]), + static_cast(mat4[3][1])); + + FPlane4d row3( + static_cast(mat4[0][2]), + static_cast(mat4[1][2]), + static_cast(mat4[2][2]), + static_cast(mat4[3][2])); + + FPlane4d row4( + static_cast(mat4[0][3]), + static_cast(mat4[1][3]), + static_cast(mat4[2][3]), + static_cast(mat4[3][3])); + + return FMatrix(row1, row2, row3, row4); +} + +/*static*/ FString +UnrealMetadataConversions::toString(const std::string_view& from) { + return toString(std::string(from)); +} + +/*static*/ FString +UnrealMetadataConversions::toString(const std::string& from) { + return FString(UTF8_TO_TCHAR(from.data())); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealTaskProcessor.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealTaskProcessor.cpp new file mode 100644 index 0000000..0d57fa8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealTaskProcessor.cpp @@ -0,0 +1,12 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "UnrealTaskProcessor.h" +#include "Async/Async.h" +#include "Misc/QueuedThreadPool.h" + +void UnrealTaskProcessor::startTask(std::function f) { + AsyncTask(ENamedThreads::Type::AnyBackgroundThreadNormalTask, [f]() { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::AsyncTask) + f(); + }); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/VecMath.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/VecMath.cpp new file mode 100644 index 0000000..87d46a3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/VecMath.cpp @@ -0,0 +1,221 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "VecMath.h" + +#include "CesiumUtility/Math.h" +#include "Math/Quat.h" +#include "Math/RotationMatrix.h" +#include + +glm::dmat4 VecMath::createMatrix4D(const FMatrix& m) noexcept { + return glm::dmat4( + m.M[0][0], + m.M[0][1], + m.M[0][2], + m.M[0][3], + m.M[1][0], + m.M[1][1], + m.M[1][2], + m.M[1][3], + m.M[2][0], + m.M[2][1], + m.M[2][2], + m.M[2][3], + m.M[3][0], + m.M[3][1], + m.M[3][2], + m.M[3][3]); +} + +glm::dmat4 VecMath::createMatrix4D( + const FMatrix& m, + const glm::dvec3& translation) noexcept { + return VecMath::createMatrix4D( + m, + translation.x, + translation.y, + translation.z, + 1.0); +} + +glm::dmat4 VecMath::createMatrix4D( + const FMatrix& m, + const glm::dvec4& translation) noexcept { + return VecMath::createMatrix4D( + m, + translation.x, + translation.y, + translation.z, + translation.w); +} + +glm::dmat4 VecMath::createMatrix4D( + const FMatrix& m, + double tx, + double ty, + double tz, + double tw) noexcept { + return glm::dmat4( + m.M[0][0], + m.M[0][1], + m.M[0][2], + m.M[0][3], + m.M[1][0], + m.M[1][1], + m.M[1][2], + m.M[1][3], + m.M[2][0], + m.M[2][1], + m.M[2][2], + m.M[2][3], + tx, + ty, + tz, + tw); +} + +glm::dmat4 VecMath::createTranslationMatrix4D( + double tx, + double ty, + double tz, + double tw) noexcept { + return glm::dmat4( + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + tx, + ty, + tz, + tw); +} + +glm::dmat4 VecMath::createRotationMatrix4D(const FRotator& rot) noexcept { + const FMatrix& m = FRotationMatrix::Make(rot); + return createMatrix4D(m); +} + +glm::dvec3 VecMath::createVector3D(const FVector& v) noexcept { + return glm::dvec3(v.X, v.Y, v.Z); +} + +glm::dvec3 VecMath::createVector3D(const FIntVector& v) noexcept { + return glm::dvec3(v.X, v.Y, v.Z); +} + +glm::dquat VecMath::createQuaternion(const FQuat& q) noexcept { + return glm::dquat(q.W, q.X, q.Y, q.Z); +} + +FMatrix VecMath::createMatrix(const glm::dmat4& m) noexcept { + return FMatrix( + FVector(m[0].x, m[0].y, m[0].z), + FVector(m[1].x, m[1].y, m[1].z), + FVector(m[2].x, m[2].y, m[2].z), + FVector(m[3].x, m[3].y, m[3].z)); +} + +FMatrix VecMath::createMatrix(const glm::dmat3& m) noexcept { + return FMatrix( + FVector(m[0].x, m[0].y, m[0].z), + FVector(m[1].x, m[1].y, m[1].z), + FVector(m[2].x, m[2].y, m[2].z), + FVector::ZeroVector); +} + +FMatrix VecMath::createMatrix( + const glm::dvec3& column0, + const glm::dvec3& column1, + const glm::dvec3& column2) noexcept { + return FMatrix( + FVector(column0.x, column0.y, column0.z), + FVector(column1.x, column1.y, column1.z), + FVector(column2.x, column2.y, column2.z), + FVector::ZeroVector); +} + +FVector VecMath::createVector(const glm::dvec4& v) noexcept { + return FVector(v.x, v.y, v.z); +} + +FVector VecMath::createVector(const glm::dvec3& v) noexcept { + return FVector(v.x, v.y, v.z); +} + +FRotator VecMath::createRotator(const glm::dmat4& m) noexcept { + // Avoid converting to Unreal single-precision types until the very end, so + // that all intermediate conversions are performed in double-precision. + return VecMath::createRotator(quat_cast(m)); +} + +FRotator VecMath::createRotator(const glm::dmat3& m) noexcept { + return VecMath::createRotator(quat_cast(m)); +} + +FRotator VecMath::createRotator(const glm::dquat& q) noexcept { + return FRotator(FQuat(q.x, q.y, q.z, q.w)); +} + +FQuat VecMath::createQuaternion(const glm::dquat& q) noexcept { + return FQuat(q.x, q.y, q.z, q.w); +} + +glm::dvec4 VecMath::add4D(const FVector& f, const FIntVector& i) noexcept { + return glm::dvec4(VecMath::add3D(f, i), 1.0); +} + +glm::dvec4 VecMath::add4D(const FIntVector& i, const FVector& f) noexcept { + return glm::dvec4(VecMath::add3D(i, f), 1.0); +} + +glm::dvec4 VecMath::add4D(const glm::dvec4& d, const FIntVector& i) noexcept { + return glm::dvec4(VecMath::add3D(glm::dvec3(d), i), d.w); +} + +glm::dvec3 VecMath::add3D(const FIntVector& i, const FVector& f) noexcept { + return glm::dvec3( + static_cast(i.X) + f.X, + static_cast(i.Y) + f.Y, + static_cast(i.Z) + f.Z); +} + +glm::dvec3 VecMath::add3D(const FVector& f, const FIntVector& i) noexcept { + return glm::dvec3( + static_cast(f.X) + i.X, + static_cast(f.Y) + i.Y, + static_cast(f.Z) + i.Z); +} + +glm::dvec3 VecMath::add3D(const glm::dvec3& f, const FIntVector& i) noexcept { + return glm::dvec3(f.x + i.X, f.y + i.Y, f.z + i.Z); +} + +glm::dvec4 VecMath::subtract4D(const FVector& f, const FIntVector& i) noexcept { + return glm::dvec4(VecMath::subtract3D(f, i), 1.0); +} + +glm::dvec4 VecMath::subtract4D(const FIntVector& i, const FVector& f) noexcept { + return glm::dvec4(VecMath::subtract3D(i, f), 1.0); +} + +glm::dvec3 VecMath::subtract3D(const FVector& f, const FIntVector& i) noexcept { + return glm::dvec3( + static_cast(f.X) - i.X, + static_cast(f.Y) - i.Y, + static_cast(f.Z) - i.Z); +} + +glm::dvec3 VecMath::subtract3D(const FIntVector& i, const FVector& f) noexcept { + return glm::dvec3( + static_cast(i.X) - f.X, + static_cast(i.Y) - f.Y, + static_cast(i.Z) - f.Z); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/VecMath.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/VecMath.h new file mode 100644 index 0000000..d6b6ecc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/VecMath.h @@ -0,0 +1,351 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Math/Matrix.h" +#include + +#include +#include +#include +#include + +/** + * @brief Vector math utility functions. + * + * The functions in this class mainly perform conversions between + * the `glm` types and the Unreal Engine types, as well as basic, + * frequently used mathematical operations on these types. + * + * As far as possible these functions will internally perform the + * computations with `double` precision. + * + */ +class VecMath { +public: + /** + * @brief Create a `glm` 4x4 matrix from the given `FMatrix`. + * + * @param m The `FMatrix`. + * @return The `glm` matrix. + */ + static glm::dmat4 createMatrix4D(const FMatrix& m) noexcept; + + /** + * @brief Create a `glm` 4x4 matrix from the given `FMatrix`. + * + * This will use the elements of the given matrix, but replace + * the translation column with the given translation vector. + * + * @param m The `FMatrix`. + * @param translation The translation vector. + * @return The `glm` matrix. + */ + static glm::dmat4 + createMatrix4D(const FMatrix& m, const glm::dvec3& translation) noexcept; + + /** + * @brief Create a `glm` 4x4 matrix from the given `FMatrix`. + * + * This will use the elements of the given matrix, but replace + * the translation column with the given translation. + * + * @param m The `FMatrix`. + * @param tx The translation in x-direction + * @param ty The translation in y-direction + * @param tz The translation in z-direction + * @param tw The w-component of the translation, usually 1.0 + * @return The `glm` matrix. + */ + static glm::dmat4 createMatrix4D( + const FMatrix& m, + double tx, + double ty, + double tz, + double tw) noexcept; + + /** + * @brief Create a `glm` 4x4 matrix from the given `FMatrix`. + * + * This will use the elements of the given matrix, but replace + * the translation column with the given translation vector. + * + * @param m The `FMatrix`. + * @param translation The translation vector. + * @return The `glm` matrix. + */ + static glm::dmat4 + createMatrix4D(const FMatrix& m, const glm::dvec4& translation) noexcept; + + /** + * @brief Create a translation matrix from the given vector. + * + * This will return an identity matrix where the + * the translation column is set to be the given + * translation vector. + * + * @param translation The translation vector. + * @return The `glm` matrix. + */ + static glm::dmat4 createTranslationMatrix4D( + double tx, + double ty, + double tz, + double tw) noexcept; + + /** + * @brief Create a rotation matrix from the given `FRotator`. + * + * This will return an identity matrix where the + * the upper-left 3x3 matrix is set to be the matrix conversion + * of the input FRotator. + * + * @param rot The `FRotator`. + * @return The `glm` matrix. + */ + static glm::dmat4 createRotationMatrix4D(const FRotator& rot) noexcept; + + /** + * @brief Create a `glm` vector from the given `FVector`. + * + * @param v The `FVector` + * @return The `glm` vector + */ + static glm::dvec3 createVector3D(const FVector& v) noexcept; + + /** + * @brief Create a `glm` vector from the given `FIntVector`. + * + * @param v The `FIntVector` + * @return The `glm` vector + */ + static glm::dvec3 createVector3D(const FIntVector& v) noexcept; + + /** + * @brief Create a `glm` double-precision quaternion from the given `FQuat`. + * + * @param q The `FQuat` + * @return The `glm` quaternion + */ + static glm::dquat createQuaternion(const FQuat& q) noexcept; + + /** + * @brief Create a `FMatrix` from the given `glm` matrix. + * + * The result will be an identity matrix, with the upper-left 3x3 + * matrix to be set to the given input. + * + * @param m The `glm` matrix. + * @return The `FMatrix`. + */ + static FMatrix createMatrix(const glm::dmat3& m) noexcept; + + /** + * @brief Create a `FMatrix` from the given `glm` matrix. + * + * @param m The `glm` matrix. + * @return The `FMatrix`. + */ + static FMatrix createMatrix(const glm::dmat4& m) noexcept; + + /** + * @brief Create a `FMatrix` from the given `glm` columns + * + * The result will be an identity matrix, with the upper-left 3x3 + * matrix to be set to the given columns + * + * @param column0 The first column + * @param column1 The second column + * @param column2 The third column + * @return The `FMatrix`. + */ + static FMatrix createMatrix( + const glm::dvec3& column0, + const glm::dvec3& column1, + const glm::dvec3& column2) noexcept; + + /** + * @brief Create an `FVector` from the given `glm` 4D vector. + * + * @param v The `glm` vector. + * @return The `FVector`. + * + */ + static FVector createVector(const glm::dvec4& v) noexcept; + + /** + * @brief Create an `FVector` from the given `glm` 3D vector. + * + * @param v The `glm` vector. + * @return The `FVector`. + * + */ + static FVector createVector(const glm::dvec3& v) noexcept; + + /** + * @brief Create a `FRotator` from the given `glm` matrix. + * + * The result will be an `FRotator`. Note that any translation and scaling + * information will be lost. + * + * This method assumes that `m` is already associated with the left-handed UE + * coordinate system. + * + * @param m The `gl` matrix. + * @return The `FRotator`. + */ + static FRotator createRotator(const glm::dmat4& m) noexcept; + + /** + * @brief Create a `FRotator` from the given `glm` matrix. + * + * This method assumes that `m` is already associated with the left-handed UE + * coordinate system. + * + * @param m The `glm` matrix. + * @return The `FRotator`. + */ + static FRotator createRotator(const glm::dmat3& m) noexcept; + + /** + * @brief Create a `FRotator` from the given `glm` quaternion. + * + * This method assumes that `q` is already associated with the left-handed UE + * coordinate system. + * + * @param q The `glm` quaternion. + * @return The `FRotator`. + */ + static FRotator createRotator(const glm::dquat& q) noexcept; + + /** + * @brief Create a `FQuat` from the given `glm` quaternion. + * + * @param q The `glm` quaternion. + * @return The `FQuat`. + */ + static FQuat createQuaternion(const glm::dquat& q) noexcept; + + /** + * @brief Add the given `FVector` and `FIntVector`, to create a `glm` vector. + * + * This will internally perform the computation with `double` precision. + * + * @param f The `FVector` + * @param i The `FIntVector` + * @return The `glm` vector + */ + static glm::dvec4 add4D(const FVector& f, const FIntVector& i) noexcept; + + /** + * @brief Add the given `FIntVector` and `FVector`, to create a `glm` vector. + * + * This will internally perform the computation with `double` precision. + * + * @param i The `FIntVector` + * @param f The `FVector` + * @return The `glm` vector + */ + static glm::dvec4 add4D(const FIntVector& i, const FVector& f) noexcept; + + /** + * @brief Add the `glm` vector and `FIntVector`, to create a `glm` vector. + * + * @param d The `glm` vector + * @param i The `FIntVector` + * @return The `glm` vector + */ + static glm::dvec4 add4D(const glm::dvec4& d, const FIntVector& i) noexcept; + + /** + * @brief Add the given `FVector` and `FIntVector`, to create a `glm` vector. + * + * This will internally perform the computation with `double` precision. + * + * @param f The `FVector` + * @param i The `FIntVector` + * @return The `glm` vector + */ + static glm::dvec3 add3D(const FVector& f, const FIntVector& i) noexcept; + + /** + * @brief Add the given `FIntVector` and `FVector`, to create a `glm` vector. + * + * This will internally perform the computation with `double` precision. + * + * @param i The `FIntVector` + * @param f The `FVector` + * @return The `glm` vector + */ + static glm::dvec3 add3D(const FIntVector& i, const FVector& f) noexcept; + + /** + * @brief Add the `glm` vector and `FIntVector`, to create a `glm` vector. + * + * @param d The `glm` vector + * @param i The `FIntVector` + * @return The `glm` vector + */ + static glm::dvec3 add3D(const glm::dvec3& d, const FIntVector& i) noexcept; + + /** + * @brief Subtract the given `FIntVector` from the given `FVector`, to create + * a `glm` vector. + * + * This will internally perform the computation with `double` precision. + * + * @param f The `FVector` + * @param i The `FIntVector` + * @return The `glm` vector + */ + static glm::dvec4 subtract4D(const FVector& f, const FIntVector& i) noexcept; + + /** + * @brief Subtract the given `FVector` from the given `FIntVector`, to create + * a `glm` vector. + * + * This will internally perform the computation with `double` precision. + * + * @param i The `FIntVector` + * @param f The `FVector` + * @return The `glm` vector + */ + static glm::dvec4 subtract4D(const FIntVector& i, const FVector& f) noexcept; + + /** + * @brief Subtract the given `FIntVector` from the given `FVector`, to create + * a `glm` vector. + * + * This will internally perform the computation with `double` precision. + * + * @param f The `FVector` + * @param i The `FIntVector` + * @return The `glm` vector + */ + static glm::dvec3 subtract3D(const FVector& f, const FIntVector& i) noexcept; + + /** + * @brief Subtract the given `FVector` from the given `FIntVector`, to create + * a `glm` vector. + * + * This will internally perform the computation with `double` precision. + * + * @param i The `FIntVector` + * @param f The `FVector` + * @return The `glm` vector + */ + static glm::dvec3 subtract3D(const FIntVector& i, const FVector& f) noexcept; +}; + +template +std::enable_if_t, float> GltfNormalized(IntType val) { + return std::max( + static_cast(val) / std::numeric_limits::max(), + -1.0f); +} + +template +std::enable_if_t, float> +GltfNormalized(IntType val) { + return static_cast(val) / std::numeric_limits::max(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/Cesium3DTileset.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/Cesium3DTileset.h new file mode 100644 index 0000000..22f27eb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/Cesium3DTileset.h @@ -0,0 +1,1303 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Cesium3DTilesSelection/Tileset.h" +#include "Cesium3DTilesSelection/ViewState.h" +#include "Cesium3DTilesSelection/ViewUpdateResult.h" +#include "Cesium3DTilesetLoadFailureDetails.h" +#include "CesiumCreditSystem.h" +#include "CesiumEncodedMetadataComponent.h" +#include "CesiumFeaturesMetadataComponent.h" +#include "CesiumGeoreference.h" +#include "CesiumIonServer.h" +#include "CesiumPointCloudShading.h" +#include "CesiumSampleHeightResult.h" +#include "CoreMinimal.h" +#include "CustomDepthParameters.h" +#include "Engine/EngineTypes.h" +#include "GameFramework/Actor.h" +#include "Interfaces/IHttpRequest.h" +#include "PrimitiveSceneProxy.h" +#include +#include +#include +#include +#include +#include +#include "Cesium3DTileset.generated.h" + +#ifdef CESIUM_DEBUG_TILE_STATES +#include +#endif + +class UMaterialInterface; +class ACesiumCartographicSelection; +class ACesiumCameraManager; +class UCesiumBoundingVolumePoolComponent; +class CesiumViewExtension; +struct FCesiumCamera; + +namespace Cesium3DTilesSelection { +class Tileset; +class TilesetView; +class TileOcclusionRendererProxyPool; +} // namespace Cesium3DTilesSelection + +/** + * The delegate for OnCesium3DTilesetLoadFailure, which is triggered when + * the tileset encounters a load error. + */ +DECLARE_MULTICAST_DELEGATE_OneParam( + FCesium3DTilesetLoadFailure, + const FCesium3DTilesetLoadFailureDetails&); + +DECLARE_DELEGATE_ThreeParams( + FCesiumSampleHeightMostDetailedCallback, + ACesium3DTileset*, + const TArray&, + const TArray&); + +/** + * The delegate for the Acesium3DTileset::OnTilesetLoaded, + * which is triggered from UpdateLoadStatus + */ +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FCompletedLoadTrigger); + +CESIUMRUNTIME_API extern FCesium3DTilesetLoadFailure + OnCesium3DTilesetLoadFailure; + +UENUM(BlueprintType) +enum class ETilesetSource : uint8 { + /** + * The tileset will be loaded from Cesium Ion using the provided IonAssetID + * and IonAccessToken. + */ + FromCesiumIon UMETA(DisplayName = "From Cesium Ion"), + + /** + * The tileset will be loaded from the specified Url. + */ + FromUrl UMETA(DisplayName = "From Url"), + + /** + * The tileset will be loaded from the georeference ellipsoid. + */ + FromEllipsoid UMETA(DisplayName = "From Ellipsoid") +}; + +UENUM(BlueprintType) +enum class EApplyDpiScaling : uint8 { Yes, No, UseProjectDefault }; + +UCLASS() +class CESIUMRUNTIME_API ACesium3DTileset : public AActor { + GENERATED_BODY() + +public: + ACesium3DTileset(); + virtual ~ACesium3DTileset(); + +private: + UPROPERTY(VisibleAnywhere, Category = "Cesium") USceneComponent* Root; + + UPROPERTY( + Meta = + (AllowPrivateAccess, + DeprecatedProperty, + DeprecationMessage = + "Use the Mobility property on the RootComponent instead.")) + TEnumAsByte Mobility_DEPRECATED = + EComponentMobility::Static; + +public: + UFUNCTION(BlueprintCallable, meta = (DeprecatedFunction)) + EComponentMobility::Type GetMobility() const { + return this->RootComponent->Mobility; + } + UFUNCTION(BlueprintCallable, meta = (DeprecatedFunction)) + void SetMobility(EComponentMobility::Type NewMobility); + + /** + * @brief Initiates an asynchronous query for the height of this tileset at a + * list of cartographic positions, where the Longitude (X) and Latitude (Y) + * are given in degrees. The most detailed available tiles are used to + * determine each height. + * + * The height of the input positions is ignored, unless height sampling fails + * at that location. The output height is expressed in meters above the + * ellipsoid (usually WGS84), which should not be confused with a height above + * mean sea level. + * + * @param LongitudeLatitudeHeightArray The cartographic positions for which to + * sample heights. The Longitude (X) and Latitude (Y) are expressed in + * degrees, while Height (Z) is given in meters. + * @param OnHeightsSampled A callback that is invoked in the game thread when + * heights have been sampled for all positions. + */ + void SampleHeightMostDetailed( + const TArray& LongitudeLatitudeHeightArray, + FCesiumSampleHeightMostDetailedCallback OnHeightsSampled); + +private: + /** + * The designated georeference actor controlling how the actor's + * coordinate system relates to the coordinate system in this Unreal Engine + * level. + * + * If this is null, the Tileset will find and use the first Georeference + * Actor in the level, or create one if necessary. To get the active/effective + * Georeference from Blueprints or C++, use ResolvedGeoreference instead. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetGeoreference, + BlueprintSetter = SetGeoreference, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + TSoftObjectPtr Georeference; + + /** + * The resolved georeference used by this Tileset. This is not serialized + * because it may point to a Georeference in the PersistentLevel while this + * tileset is in a sublevel. If the Georeference property is specified, + * however then this property will have the same value. + * + * This property will be null before ResolveGeoreference is called. + */ + UPROPERTY( + Transient, + VisibleAnywhere, + BlueprintReadOnly, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + ACesiumGeoreference* ResolvedGeoreference = nullptr; + +public: + /** @copydoc ACesium3DTileset::Georeference */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + TSoftObjectPtr GetGeoreference() const; + + /** @copydoc ACesium3DTileset::Georeference */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetGeoreference(TSoftObjectPtr NewGeoreference); + + /** + * Resolves the Cesium Georeference to use with this Actor. Returns + * the value of the Georeference property if it is set. Otherwise, finds a + * Georeference in the World and returns it, creating it if necessary. The + * resolved Georeference is cached so subsequent calls to this function will + * return the same instance. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + ACesiumGeoreference* ResolveGeoreference(); + + /** + * Invalidates the cached resolved georeference, unsubscribing from it and + * setting it to null. The next time ResolveGeoreference is called, the + * Georeference will be re-resolved and re-subscribed. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void InvalidateResolvedGeoreference(); + +private: + /** + * The actor managing this tileset's content attributions. + * + * If this is null, the Tileset will find and use the first Credit System + * Actor in the level, or create one if necessary. To get the active/effective + * Credit System from Blueprints or C++, use ResolvedCreditSystem instead. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetCreditSystem, + BlueprintSetter = SetCreditSystem, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + TSoftObjectPtr CreditSystem; + + /** + * The resolved Credit System used by this Tileset. This is not serialized + * because it may point to a Credit System in the PersistentLevel while this + * tileset is in a sublevel. If the CreditSystem property is specified, + * however then this property will have the same value. + * + * This property will be null before ResolveCreditSystem is called. + */ + UPROPERTY( + Transient, + BlueprintReadOnly, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + ACesiumCreditSystem* ResolvedCreditSystem = nullptr; + + /** + * The actor providing custom cameras for use with this Tileset. + * + * If this is null, the Tileset will find and use the first + * CesiumCameraManager Actor in the level, or create one if necessary. To get + * the active/effective Camera Manager from Blueprints or C++, use + * ResolvedCameraManager instead. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetCameraManager, + BlueprintSetter = SetCameraManager, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + TSoftObjectPtr CameraManager; + + /** + * The resolved Camera Manager used by this Tileset. This is not serialized + * because it may point to a Camera Manager in the PersistentLevel while this + * tileset is in a sublevel. If the CameraManager property is specified, + * however then this property will have the same value. + * + * This property will be null before ResolveCameraManager is called. + */ + UPROPERTY( + Transient, + BlueprintReadOnly, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + ACesiumCameraManager* ResolvedCameraManager = nullptr; + + /** + * The bounding volume pool component that manages occlusion bounding volume + * proxies. + */ + UPROPERTY( + Transient, + BlueprintReadOnly, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + UCesiumBoundingVolumePoolComponent* BoundingVolumePoolComponent = nullptr; + + /** + * The custom view extension this tileset uses to pull renderer view + * information. + */ + TSharedPtr _cesiumViewExtension = + nullptr; + +public: + /** @copydoc ACesium3DTileset::CreditSystem */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + TSoftObjectPtr GetCreditSystem() const; + + /** @copydoc ACesium3DTileset::CreditSystem */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetCreditSystem(TSoftObjectPtr NewCreditSystem); + + /** + * Resolves the Cesium Credit System to use with this Actor. Returns + * the value of the CreditSystem property if it is set. Otherwise, finds a + * Credit System in the World and returns it, creating it if necessary. The + * resolved Credit System is cached so subsequent calls to this function will + * return the same instance. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + ACesiumCreditSystem* ResolveCreditSystem(); + + /** + * Invalidates the cached resolved Credit System, setting it to null. The next + * time ResolveCreditSystem is called, the Credit System will be re-resolved. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void InvalidateResolvedCreditSystem(); + + /** + * Whether or not to show this tileset's credits on screen. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + bool ShowCreditsOnScreen = false; + + /** @copydoc ACesium3DTileset::CameraManager */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + TSoftObjectPtr GetCameraManager() const; + + /** @copydoc ACesium3DTileset::CameraManager */ + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetCameraManager(TSoftObjectPtr NewCameraManager); + + /** + * Resolves the Cesium Camera Manager to use with this Actor. Returns + * the value of the CameraManager property if it is set. Otherwise, finds a + * Camera Manager in the World and returns it, creating it if necessary. The + * resolved Camera Manager is cached so subsequent calls to this function will + * return the same instance. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + ACesiumCameraManager* ResolveCameraManager(); + + /** + * Invalidates the cached resolved Camera Manager, setting it to null. The + * next time ResolveCameraManager is called, the Camera Manager will be + * re-resolved. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void InvalidateResolvedCameraManager(); + + /** + * The maximum number of pixels of error when rendering this tileset. + * + * This is used to select an appropriate level-of-detail: A low value + * will cause many tiles with a high level of detail to be loaded, + * causing a finer visual representation of the tiles, but with a + * higher performance cost for loading and rendering. A higher value will + * cause a coarser visual representation, with lower performance + * requirements. + * + * When a tileset uses the older layer.json / quantized-mesh format rather + * than 3D Tiles, this value is effectively divided by 8.0. So the default + * value of 16.0 corresponds to the standard value for quantized-mesh terrain + * of 2.0. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetMaximumScreenSpaceError, + BlueprintSetter = SetMaximumScreenSpaceError, + Category = "Cesium|Level of Detail", + meta = (ClampMin = 0.0)) + double MaximumScreenSpaceError = 16.0; + + /** + * Scale Level-of-Detail by Display DPI. This increases the performance for + * mobile devices and high DPI screens. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Level of Detail") + EApplyDpiScaling ApplyDpiScaling = EApplyDpiScaling::UseProjectDefault; + + /** + * Whether to preload ancestor tiles. + * + * Setting this to true optimizes the zoom-out experience and provides more + * detail in newly-exposed areas when panning. The down side is that it + * requires loading more tiles. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Loading") + bool PreloadAncestors = true; + + /** + * Whether to preload sibling tiles. + * + * Setting this to true causes tiles with the same parent as a rendered tile + * to be loaded, even if they are culled. Setting this to true may provide a + * better panning experience at the cost of loading more tiles. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Loading") + bool PreloadSiblings = true; + + /** + * Whether to unrefine back to a parent tile when a child isn't done loading. + * + * When this is set to true, the tileset will guarantee that the tileset will + * never be rendered with holes in place of tiles that are not yet loaded, + * even though the tile that is rendered instead may have low resolution. When + * false, overall loading will be faster, but newly-visible parts of the + * tileset may initially be blank. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Loading") + bool ForbidHoles = false; + + /** + * The maximum number of tiles that may be loaded at once. + * + * When new parts of the tileset become visible, the tasks to load the + * corresponding tiles are put into a queue. This value determines how + * many of these tasks are processed at the same time. A higher value + * may cause the tiles to be loaded and rendered more quickly, at the + * cost of a higher network- and processing load. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Tile Loading", + meta = (ClampMin = 0)) + int32 MaximumSimultaneousTileLoads = 20; + + /** + * @brief The maximum number of bytes that may be cached. + * + * Note that this value, even if 0, will never + * cause tiles that are needed for rendering to be unloaded. However, if the + * total number of loaded bytes is greater than this value, tiles will be + * unloaded until the total is under this number or until only required tiles + * remain, whichever comes first. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Loading") + int64 MaximumCachedBytes = 256 * 1024 * 1024; + + /** + * The number of loading descendents a tile should allow before deciding to + * render itself instead of waiting. + * + * Setting this to 0 will cause each level of detail to be loaded + * successively. This will increase the overall loading time, but cause + * additional detail to appear more gradually. Setting this to a high value + * like 1000 will decrease the overall time until the desired level of detail + * is achieved, but this high-detail representation will appear at once, as + * soon as it is loaded completely. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Tile Loading", + meta = (ClampMin = 0)) + int32 LoadingDescendantLimit = 20; + + /** + * Whether to cull tiles that are outside the frustum. + * + * By default this is true, meaning that tiles that are not visible with the + * current camera configuration will be ignored. It can be set to false, so + * that these tiles are still considered for loading, refinement and + * rendering. + * + * This will cause more tiles to be loaded, but helps to avoid holes and + * provides a more consistent mesh, which may be helpful for physics. + * + * Note that this will always be disabled if UseLodTransitions is set to true. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Tile Culling", + Meta = (EditCondition = "!UseLodTransitions", EditConditionHides)) + bool EnableFrustumCulling = true; + + /** + * Whether to cull tiles that are occluded by fog. + * + * This does not refer to the atmospheric fog of the Unreal Engine, + * but to an internal representation of fog: Depending on the height + * of the camera above the ground, tiles that are far away (close to + * the horizon) will be culled when this flag is enabled. + * + * Note that this will always be disabled if UseLodTransitions is set to true. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Tile Culling", + Meta = (EditCondition = "!UseLodTransitions", EditConditionHides)) + bool EnableFogCulling = true; + + /** + * Whether a specified screen-space error should be enforced for tiles that + * are outside the frustum or hidden in fog. + * + * When "Enable Frustum Culling" and "Enable Fog Culling" are both true, tiles + * outside the view frustum or hidden in fog are effectively ignored, and so + * their level-of-detail doesn't matter. And in this scenario, this property + * is ignored. + * + * However, when either of those flags are false, these "would-be-culled" + * tiles continue to be processed, and the question arises of how to handle + * their level-of-detail. When this property is false, refinement terminates + * at these tiles, no matter what their current screen-space error. The tiles + * are available for physics, shadows, etc., but their level-of-detail may + * be very low. + * + * When set to true, these tiles are refined until they achieve the specified + * "Culled Screen Space Error". This allows control over the minimum quality + * of these would-be-culled tiles. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Culling") + bool EnforceCulledScreenSpaceError = false; + + /** + * The screen-space error to be enforced for tiles that are outside the view + * frustum or hidden in fog. + * + * When "Enable Frustum Culling" and "Enable Fog Culling" are both true, tiles + * outside the view frustum or hidden in fog are effectively ignored, and so + * their level-of-detail doesn't matter. And in this scenario, this property + * is ignored. + * + * However, when either of those flags are false, these "would-be-culled" + * tiles continue to be processed, and the question arises of how to handle + * their level-of-detail. When "Enforce Culled Screen Space Error" is false, + * this property is ignored and refinement terminates at these tiles, no + * matter what their current screen-space error. The tiles are available for + * physics, shadows, etc., but their level-of-detail may be very low. + * + * When set to true, these tiles are refined until they achieve the + * screen-space error specified by this property. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Tile Culling", + meta = (EditCondition = "EnforceCulledScreenSpaceError", ClampMin = 0.0)) + double CulledScreenSpaceError = 64.0; + + // This mirrors + // UCesiumRuntimeSettings::EnableExperimentalOcclusionCullingFeature so that + // it can be used as an EditCondition. + UPROPERTY(Transient, VisibleDefaultsOnly, Category = "Cesium|Tile Occlusion") + bool CanEnableOcclusionCulling = false; + + /** + * Whether to cull tiles that are occluded. + * + * If this option is disabled, check that "Enable Experimental Occlusion + * Culling Feature" is enabled in the Plugins -> Cesium section of the Project + * Settings. + * + * When enabled, this feature will use Unreal's occlusion system to determine + * if tiles are actually visible on the screen. For tiles found to be + * occluded, the tile will not refine to show descendants, but it will still + * be rendered to avoid holes. This results in less tile loads and less GPU + * resource usage for dense, high-occlusion scenes like ground-level views in + * cities. + * + * This will not work for tilesets with poorly fit bounding volumes and cause + * more draw calls with very few extra culled tiles. When there is minimal + * occlusion in a scene, such as with terrain tilesets and applications + * focused on top-down views, this feature will yield minimal benefit and + * potentially cause needless overhead. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetEnableOcclusionCulling, + BlueprintSetter = SetEnableOcclusionCulling, + Category = "Cesium|Tile Occlusion", + meta = (EditCondition = "CanEnableOcclusionCulling")) + bool EnableOcclusionCulling = true; + + /** + * The number of CesiumBoundingVolumeComponents to use for querying the + * occlusion state of traversed tiles. + * + * Only applicable when EnableOcclusionCulling is enabled. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetOcclusionPoolSize, + BlueprintSetter = SetOcclusionPoolSize, + Category = "Cesium|Tile Occlusion", + meta = + (EditCondition = + "EnableOcclusionCulling && CanEnableOcclusionCulling", + ClampMin = "0", + ClampMax = "1000")) + int32 OcclusionPoolSize = 500; + + /** + * Whether to wait for valid occlusion results before refining tiles. + * + * Only applicable when EnableOcclusionCulling is enabled. When this option + * is enabled, there may be small delays before tiles are refined, but there + * may be an overall performance advantage by avoiding loads of descendants + * that will be found to be occluded. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetDelayRefinementForOcclusion, + BlueprintSetter = SetDelayRefinementForOcclusion, + Category = "Cesium|Tile Occlusion", + meta = + (EditCondition = + "EnableOcclusionCulling && CanEnableOcclusionCulling")) + bool DelayRefinementForOcclusion = true; + + /** + * Refreshes this tileset, ensuring that all materials and other settings are + * applied. It is not usually necessary to invoke this, but when + * behind-the-scenes changes are made and not reflected in the tileset, this + * function can help. + */ + UFUNCTION(CallInEditor, BlueprintCallable, Category = "Cesium") + void RefreshTileset(); + + /** + * Pauses level-of-detail and culling updates of this tileset. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Debug") + bool SuspendUpdate; + + /** + * If true, this tileset is ticked/updated in the editor. If false, is only + * ticked while playing (including Play-in-Editor). + */ + UPROPERTY(EditAnywhere, Category = "Cesium|Debug") + bool UpdateInEditor = true; + + /** + * If true, stats about tile selection are printed to the Output Log. + */ + UPROPERTY(EditAnywhere, Category = "Cesium|Debug") + bool LogSelectionStats = false; + + /** + * If true, logs stats on the assets in this tileset's shared asset system to + * the Output Log. + */ + UPROPERTY(EditAnywhere, Category = "Cesium|Debug") + bool LogSharedAssetStats = false; + + /** + * If true, draws debug text above each tile being rendered with information + * about that tile. + */ + UPROPERTY(EditAnywhere, Category = "Cesium|Debug") + bool DrawTileInfo = false; + + /** + * Define the collision profile for all the 3D tiles created inside this + * actor. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadOnly, + Category = "Collision", + meta = (ShowOnlyInnerProperties, SkipUCSModifiedProperties)) + FBodyInstance BodyInstance; + + /** + * A delegate that will be called whenever the tileset is fully loaded. + */ + UPROPERTY(BlueprintAssignable, Category = "Cesium"); + FCompletedLoadTrigger OnTilesetLoaded; + + /** + * Use a dithering effect when transitioning between tiles of different LODs. + * + * When this is set to true, Frustrum Culling and Fog Culling are always + * disabled. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetUseLodTransitions, + BlueprintSetter = SetUseLodTransitions, + Category = "Cesium|Rendering") + bool UseLodTransitions = false; + + /** + * How long dithered LOD transitions between different tiles should take, in + * seconds. + * + * Only relevant if UseLodTransitions is true. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Rendering", + meta = (EditCondition = "UseLodTransitions", EditConditionHides)) + float LodTransitionLength = 0.5f; + +private: + UPROPERTY(BlueprintGetter = GetLoadProgress, Category = "Cesium") + float LoadProgress = 0.0f; + + /** + * The type of source from which to load this tileset. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetTilesetSource, + BlueprintSetter = SetTilesetSource, + Category = "Cesium", + meta = (DisplayName = "Source")) + ETilesetSource TilesetSource = ETilesetSource::FromCesiumIon; + + /** + * The URL of this tileset's "tileset.json" file. + * + * If this property is specified, the ion asset ID and token are ignored. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetUrl, + BlueprintSetter = SetUrl, + Category = "Cesium", + meta = (EditCondition = "TilesetSource==ETilesetSource::FromUrl")) + FString Url = ""; + + /** + * The ID of the Cesium ion asset to use. + * + * This property is ignored if the Url is specified. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetIonAssetID, + BlueprintSetter = SetIonAssetID, + Category = "Cesium", + meta = + (EditCondition = "TilesetSource==ETilesetSource::FromCesiumIon", + ClampMin = 0)) + int64 IonAssetID; + + /** + * The access token to use to access the Cesium ion resource. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetIonAccessToken, + BlueprintSetter = SetIonAccessToken, + Category = "Cesium", + meta = (EditCondition = "TilesetSource==ETilesetSource::FromCesiumIon")) + FString IonAccessToken; + + UPROPERTY( + meta = + (DeprecatedProperty, + DeprecationMessage = "Use CesiumIonServer instead.")) + FString IonAssetEndpointUrl_DEPRECATED; + + /** + * The Cesium ion Server from which this tileset is loaded. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetCesiumIonServer, + BlueprintSetter = SetCesiumIonServer, + Category = "Cesium", + AdvancedDisplay, + meta = (EditCondition = "TilesetSource==ETilesetSource::FromCesiumIon")) + UCesiumIonServer* CesiumIonServer; + + /** + * Check if the Cesium ion token used to access this tileset is working + * correctly, and fix it if necessary. + */ + UFUNCTION(CallInEditor, Category = "Cesium") + void TroubleshootToken(); + + /** + * Whether to generate physics meshes for this tileset. + * + * Disabling this option will improve the performance of tile loading, but it + * will no longer be possible to collide with the tileset since the physics + * meshes will not be created. + * + * Physics meshes cannot be generated for primitives containing points. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetCreatePhysicsMeshes, + BlueprintSetter = SetCreatePhysicsMeshes, + Category = "Cesium|Physics") + bool CreatePhysicsMeshes = true; + + /** + * Whether to generate navigation collisions for this tileset. + * + * Enabling this option creates collisions for navigation when a 3D Tiles + * tileset is loaded. It is recommended to set "Runtime Generation" to + * "Static" in the navigation mesh settings in the project settings, as + * collision calculations become very slow. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetCreateNavCollision, + BlueprintSetter = SetCreateNavCollision, + Category = "Cesium|Navigation") + bool CreateNavCollision = false; + + /** + * Whether to always generate a correct tangent space basis for tiles that + * don't have them. + * + * Normally, a per-vertex tangent space basis is only required for glTF models + * with a normal map. However, a custom, user-supplied material may need a + * tangent space basis for other purposes. When this property is set to true, + * tiles lacking an explicit tangent vector will have one computed + * automatically using the MikkTSpace algorithm. When this property is false, + * load time will be improved by skipping the generation of the tangent + * vector, but the tangent space basis will be unreliable. + * + * Note that a tileset with "Enable Water Mask" set will include tangents + * for tiles containing water, regardless of the value of this property. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetAlwaysIncludeTangents, + BlueprintSetter = SetAlwaysIncludeTangents, + Category = "Cesium|Rendering") + bool AlwaysIncludeTangents = false; + + /** + * Whether to generate smooth normals when normals are missing in the glTF. + * + * According to the Gltf spec: "When normals are not specified, client + * implementations should calculate flat normals." However, calculating flat + * normals requires duplicating vertices. This option allows the gltfs to be + * sent with explicit smooth normals when the original gltf was missing + * normals. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetGenerateSmoothNormals, + BlueprintSetter = SetGenerateSmoothNormals, + Category = "Cesium|Rendering") + bool GenerateSmoothNormals = false; + + /** + * Whether to request and render the water mask. + * + * Currently only applicable for quantized-mesh tilesets that support the + * water mask extension. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetEnableWaterMask, + BlueprintSetter = SetEnableWaterMask, + Category = "Cesium|Rendering", + meta = (EditCondition = "!bIsMac")) + bool EnableWaterMask = false; + + /** + * Whether to ignore the KHR_materials_unlit extension on the glTF tiles in + * this tileset, if it exists, and instead render with standard lighting and + * shadows. This property will have no effect if the tileset does not have any + * tiles that use this extension. + * + * The KHR_materials_unlit extension is often applied to photogrammetry + * tilesets because lighting and shadows are already baked into their + * textures. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetIgnoreKhrMaterialsUnlit, + BlueprintSetter = SetIgnoreKhrMaterialsUnlit, + Category = "Cesium|Rendering", + meta = (DisplayName = "Ignore KHR_materials_unlit")) + bool IgnoreKhrMaterialsUnlit = false; + + /** + * A custom Material to use to render opaque elements in this tileset, in + * order to implement custom visual effects. + * + * The custom material should generally be created by copying the Material + * Instance "MI_CesiumThreeOverlaysAndClipping" and customizing the copy as + * desired. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetMaterial, + BlueprintSetter = SetMaterial, + Category = "Cesium|Rendering") + UMaterialInterface* Material = nullptr; + + /** + * A custom Material to use to render translucent elements of the tileset, in + * order to implement custom visual effects. + * + * The custom material should generally be created by copying the Material + * Instance "MI_CesiumThreeOverlaysAndClippingTranslucent" and customizing the + * copy as desired. Make sure that its Material Property Overrides -> Blend + * Mode is set to "Translucent". + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetTranslucentMaterial, + BlueprintSetter = SetTranslucentMaterial, + Category = "Cesium|Rendering") + UMaterialInterface* TranslucentMaterial = nullptr; + + /** + * A custom Material to use to render this tileset in areas where the + * watermask is, in order to implement custom visual effects. + * Currently only applicable for quantized-mesh tilesets that support the + * water mask extension. + * + * The custom material should generally be created by copying the Material + * Instance "MI_CesiumThreeOverlaysAndClippingAndWater" and customizing the + * copy as desired. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetWaterMaterial, + BlueprintSetter = SetWaterMaterial, + Category = "Cesium|Rendering") + UMaterialInterface* WaterMaterial = nullptr; + + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetCustomDepthParameters, + BlueprintSetter = SetCustomDepthParameters, + Category = "Rendering", + meta = (ShowOnlyInnerProperties)) + FCustomDepthParameters CustomDepthParameters; + + /** + * If this tileset contains points, their appearance can be configured with + * these point cloud shading parameters. + * + * These settings are not supported on mobile platforms. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetPointCloudShading, + BlueprintSetter = SetPointCloudShading, + Category = "Cesium|Rendering") + FCesiumPointCloudShading PointCloudShading; + +protected: + UPROPERTY() + FString PlatformName; + +#if WITH_EDITORONLY_DATA + UPROPERTY() + bool bIsMac; +#endif + +public: + UFUNCTION(BlueprintGetter, Category = "Cesium") + float GetLoadProgress() const { return LoadProgress; } + + UFUNCTION(BlueprintGetter, Category = "Cesium") + bool GetUseLodTransitions() const { return UseLodTransitions; } + + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetUseLodTransitions(bool InUseLodTransitions); + + UFUNCTION(BlueprintGetter, Category = "Cesium") + ETilesetSource GetTilesetSource() const { return TilesetSource; } + + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetTilesetSource(ETilesetSource InSource); + + UFUNCTION(BlueprintGetter, Category = "Cesium") + FString GetUrl() const { return Url; } + + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetUrl(const FString& InUrl); + + UFUNCTION(BlueprintGetter, Category = "Cesium") + int64 GetIonAssetID() const { return IonAssetID; } + + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetIonAssetID(int64 InAssetID); + + UFUNCTION(BlueprintGetter, Category = "Cesium") + FString GetIonAccessToken() const { return IonAccessToken; } + + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetIonAccessToken(const FString& InAccessToken); + + UFUNCTION(BlueprintGetter, Category = "Cesium") + UCesiumIonServer* GetCesiumIonServer() const { return CesiumIonServer; } + + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetCesiumIonServer(UCesiumIonServer* Server); + + UFUNCTION(BlueprintGetter, Category = "Cesium") + double GetMaximumScreenSpaceError() { return MaximumScreenSpaceError; } + + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetMaximumScreenSpaceError(double InMaximumScreenSpaceError); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Tile Culling|Experimental") + bool GetEnableOcclusionCulling() const; + + UFUNCTION(BlueprintSetter, Category = "Cesium|Tile Culling|Experimental") + void SetEnableOcclusionCulling(bool bEnableOcclusionCulling); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Tile Culling|Experimental") + int32 GetOcclusionPoolSize() const { return OcclusionPoolSize; } + + UFUNCTION(BlueprintSetter, Category = "Cesium|Tile Culling|Experimental") + void SetOcclusionPoolSize(int32 newOcclusionPoolSize); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Tile Culling|Experimental") + bool GetDelayRefinementForOcclusion() const { + return DelayRefinementForOcclusion; + } + + UFUNCTION(BlueprintSetter, Category = "Cesium|Tile Culling|Experimental") + void SetDelayRefinementForOcclusion(bool bDelayRefinementForOcclusion); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Physics") + bool GetCreatePhysicsMeshes() const { return CreatePhysicsMeshes; } + + UFUNCTION(BlueprintSetter, Category = "Cesium|Physics") + void SetCreatePhysicsMeshes(bool bCreatePhysicsMeshes); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Navigation") + bool GetCreateNavCollision() const { return CreateNavCollision; } + + UFUNCTION(BlueprintSetter, Category = "Cesium|Navigation") + void SetCreateNavCollision(bool bCreateNavCollision); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") + bool GetAlwaysIncludeTangents() const { return AlwaysIncludeTangents; } + + UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") + void SetAlwaysIncludeTangents(bool bAlwaysIncludeTangents); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") + bool GetGenerateSmoothNormals() const { return GenerateSmoothNormals; } + + UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") + void SetGenerateSmoothNormals(bool bGenerateSmoothNormals); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") + bool GetEnableWaterMask() const { return EnableWaterMask; } + + UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") + void SetEnableWaterMask(bool bEnableMask); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") + bool GetIgnoreKhrMaterialsUnlit() const { return IgnoreKhrMaterialsUnlit; } + UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") + void SetIgnoreKhrMaterialsUnlit(bool bIgnoreKhrMaterialsUnlit); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") + UMaterialInterface* GetMaterial() const { return Material; } + + UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") + void SetMaterial(UMaterialInterface* InMaterial); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") + UMaterialInterface* GetTranslucentMaterial() const { + return TranslucentMaterial; + } + + UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") + void SetTranslucentMaterial(UMaterialInterface* InMaterial); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") + UMaterialInterface* GetWaterMaterial() const { return WaterMaterial; } + + UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") + void SetWaterMaterial(UMaterialInterface* InMaterial); + + UFUNCTION(BlueprintGetter, Category = "Rendering") + FCustomDepthParameters GetCustomDepthParameters() const { + return CustomDepthParameters; + } + + UFUNCTION(BlueprintSetter, Category = "Rendering") + void SetCustomDepthParameters(FCustomDepthParameters InCustomDepthParameters); + + UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") + FCesiumPointCloudShading GetPointCloudShading() const { + return PointCloudShading; + } + + UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") + void SetPointCloudShading(FCesiumPointCloudShading InPointCloudShading); + + UFUNCTION(BlueprintCallable, Category = "Cesium|Rendering") + void PlayMovieSequencer(); + + UFUNCTION(BlueprintCallable, Category = "Cesium|Rendering") + void StopMovieSequencer(); + + UFUNCTION(BlueprintCallable, Category = "Cesium|Rendering") + void PauseMovieSequencer(); + + /** + * This method is not supposed to be called by clients. It is currently + * only required by the UnrealResourcePreparer. + * + * @internal + * See {@link + * UCesium3DTilesetRoot::GetCesiumTilesetToUnrealRelativeWorldTransform}. + * @endinternal + */ + const glm::dmat4& GetCesiumTilesetToUnrealRelativeWorldTransform() const; + + Cesium3DTilesSelection::Tileset* GetTileset() { + return this->_pTileset.Get(); + } + const Cesium3DTilesSelection::Tileset* GetTileset() const { + return this->_pTileset.Get(); + } + + const std::optional& + getFeaturesMetadataDescription() const { + return this->_featuresMetadataDescription; + } + + // AActor overrides (some or most of them should be protected) + virtual bool ShouldTickIfViewportsOnly() const override; + virtual void Tick(float DeltaTime) override; + virtual void BeginDestroy() override; + virtual bool IsReadyForFinishDestroy() override; + virtual void Destroyed() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + virtual void PostLoad() override; + virtual void Serialize(FArchive& Ar) override; + + void UpdateLoadStatus(); + + // UObject overrides +#if WITH_EDITOR + virtual void + PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; + virtual void PostEditChangeChainProperty( + FPropertyChangedChainEvent& PropertyChangedChainEvent) override; + virtual void PostEditUndo() override; + virtual void PostEditImport() override; +#endif + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + virtual void OnConstruction(const FTransform& Transform) override; + + /** + * Called after the C++ constructor and after the properties have + * been initialized, including those loaded from config. + */ + void PostInitProperties() override; + + virtual void NotifyHit( + class UPrimitiveComponent* MyComp, + AActor* Other, + class UPrimitiveComponent* OtherComp, + bool bSelfMoved, + FVector HitLocation, + FVector HitNormal, + FVector NormalImpulse, + const FHitResult& Hit) override; + +private: + void LoadTileset(); + void DestroyTileset(); + + static Cesium3DTilesSelection::ViewState CreateViewStateFromViewParameters( + const FCesiumCamera& camera, + const glm::dmat4& unrealWorldToTileset, + UCesiumEllipsoid* ellipsoid); + + std::vector GetCameras() const; + std::vector GetPlayerCameras() const; + std::vector GetSceneCaptures() const; + +public: + /** + * Update the transforms of the glTF components based on the + * the transform of the root component. + * + * This is supposed to be called during Tick, if the transform of + * the root component has changed since the previous Tick. + */ + void UpdateTransformFromCesium(); + +private: + /** + * The event handler for ACesiumGeoreference::OnEllipsoidChanged. + */ + UFUNCTION(CallInEditor) + void HandleOnGeoreferenceEllipsoidChanged( + UCesiumEllipsoid* OldEllipsoid, + UCesiumEllipsoid* NewEllpisoid); + + /** + * Writes the values of all properties of this actor into the + * TilesetOptions, to take them into account during the next + * traversal. + */ + void updateTilesetOptionsFromProperties(); + + /** + * Update all the "_last..." fields of this instance based + * on the given ViewUpdateResult, printing a log message + * if any value changed. + * + * @param result The ViewUpdateREsult + */ + void updateLastViewUpdateResultState( + const Cesium3DTilesSelection::ViewUpdateResult& result); + + /** + * Creates the visual representations of the given tiles to + * be rendered in the current frame. + * + * @param tiles The tiles + */ + void + showTilesToRender(const std::vector& tiles); + + /** + * Will be called after the tileset is loaded or spawned, to register + * a delegate that calls OnFocusEditorViewportOnThis when this + * tileset is double-clicked + */ + void AddFocusViewportDelegate(); + +#if WITH_EDITOR + std::vector GetEditorCameras() const; + + /** + * Will focus all viewports on this tileset. + * + * This is called when double-clicking the tileset in the World Outliner. + * It will move the tileset into the center of the view, *even if* the + * tileset was not visible before, and no geometry has been created yet + * for the tileset: It solely operates on the tile bounding volume that + * was given in the root tile. + */ + void OnFocusEditorViewportOnThis(); + + void RuntimeSettingsChanged( + UObject* pObject, + struct FPropertyChangedEvent& changed); +#endif + +private: + TUniquePtr _pTileset; + +#ifdef CESIUM_DEBUG_TILE_STATES + TUniquePtr _pStateDebug; +#endif + + std::optional + _featuresMetadataDescription; + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + std::optional _metadataDescription_DEPRECATED; + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + // For debug output + uint32_t _lastTilesRendered; + uint32_t _lastWorkerThreadTileLoadQueueLength; + uint32_t _lastMainThreadTileLoadQueueLength; + + uint32_t _lastTilesVisited; + uint32_t _lastCulledTilesVisited; + uint32_t _lastTilesCulled; + uint32_t _lastTilesOccluded; + uint32_t _lastTilesWaitingForOcclusionResults; + uint32_t _lastMaxDepthVisited; + + std::chrono::high_resolution_clock::time_point _startTime; + + bool _captureMovieMode; + bool _beforeMoviePreloadAncestors; + bool _beforeMoviePreloadSiblings; + int32_t _beforeMovieLoadingDescendantLimit; + bool _beforeMovieUseLodTransitions; + + bool _scaleUsingDPI; + + // This is used as a workaround for cesium-native#186 + // + // The tiles that are no longer supposed to be rendered in the current + // frame, according to ViewUpdateResult::tilesToHideThisFrame, + // are kept in this list, and hidden in the NEXT frame, because some + // internal occlusion culling information from Unreal might prevent + // the tiles that are supposed to be rendered instead from appearing + // immediately. + // + // If we find a way to clear the wrong occlusion information in the + // Unreal Engine, then this field may be removed, and the + // tilesToHideThisFrame may be hidden immediately. + std::vector _tilesToHideNextFrame; + + int32 _tilesetsBeingDestroyed; + + friend class UnrealResourcePreparer; + friend class UCesiumGltfPointsComponent; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/Cesium3DTilesetLoadFailureDetails.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/Cesium3DTilesetLoadFailureDetails.h new file mode 100644 index 0000000..80fbf18 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/Cesium3DTilesetLoadFailureDetails.h @@ -0,0 +1,58 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include "Cesium3DTilesetLoadFailureDetails.generated.h" + +class ACesium3DTileset; + +UENUM(BlueprintType) +enum class ECesium3DTilesetLoadType : uint8 { + /** + * An unknown load error. + */ + Unknown, + + /** + * A Cesium ion asset endpoint. + */ + CesiumIon, + + /** + * A tileset.json. + */ + TilesetJson +}; + +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesium3DTilesetLoadFailureDetails { + GENERATED_BODY() + + /** + * The tileset that encountered the load failure. + */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + TWeakObjectPtr Tileset = nullptr; + + /** + * The type of request that failed to load. + */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + ECesium3DTilesetLoadType Type = ECesium3DTilesetLoadType::Unknown; + + /** + * The HTTP status code of the response that led to the failure. + * + * If there was no response or the failure did not follow from a request, then + * the value of this property will be 0. + */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + int32 HttpStatusCode = 0; + + /** + * A human-readable explanation of what failed. + */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + FString Message; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumBingMapsRasterOverlay.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumBingMapsRasterOverlay.h new file mode 100644 index 0000000..6569547 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumBingMapsRasterOverlay.h @@ -0,0 +1,46 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumRasterOverlay.h" +#include "CoreMinimal.h" +#include "CesiumBingMapsRasterOverlay.generated.h" + +UENUM(BlueprintType) +enum class EBingMapsStyle : uint8 { + Aerial UMETA(DisplayName = "Aerial"), + AerialWithLabelsOnDemand UMETA(DisplayName = "Aerial with Labels"), + RoadOnDemand UMETA(DisplayName = "Road"), + CanvasDark UMETA(DisplayName = "Canvas Dark"), + CanvasLight UMETA(DisplayName = "Canvas Light"), + CanvasGray UMETA(DisplayName = "Canvas Gray"), + OrdnanceSurvey UMETA(DisplayName = "Ordnance Survey"), + CollinsBart UMETA(DisplayName = "Collins Bart") +}; + +/** + * A raster overlay that directly accesses Bing Maps. If you're using Bing Maps + * via Cesium ion, use the "Cesium ion Raster Overlay" component instead. + */ +UCLASS(ClassGroup = (Cesium), meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumBingMapsRasterOverlay + : public UCesiumRasterOverlay { + GENERATED_BODY() + +public: + /** + * The Bing Maps API key to use. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + FString BingMapsKey; + + /** + * The map style to use. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + EBingMapsStyle MapStyle = EBingMapsStyle::Aerial; + +protected: + virtual std::unique_ptr CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options = {}) override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCamera.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCamera.h new file mode 100644 index 0000000..2f98178 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCamera.h @@ -0,0 +1,93 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Math/Rotator.h" +#include "Math/Vector.h" +#include "Math/Vector2D.h" +#include "UObject/ObjectMacros.h" + +#include "Cesium3DTilesSelection/ViewState.h" + +#include "CesiumCamera.generated.h" + +/** + * @brief A camera description that {@link ACesium3DTileset}s can use to decide + * what tiles need to be loaded to sufficiently cover the camera view. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumCamera { + GENERATED_USTRUCT_BODY() + +public: + /** + * @brief The pixel dimensions of the viewport. + */ + UPROPERTY(BlueprintReadWrite, Category = "Cesium") + FVector2D ViewportSize; + + /** + * @brief The Unreal location of the camera. + */ + UPROPERTY(BlueprintReadWrite, Category = "Cesium") + FVector Location; + + /** + * @brief The Unreal rotation of the camera. + */ + UPROPERTY(BlueprintReadWrite, Category = "Cesium") + FRotator Rotation; + + /** + * @brief The horizontal field of view of the camera in degrees. + */ + UPROPERTY(BlueprintReadWrite, Category = "Cesium") + double FieldOfViewDegrees; + + /** + * @brief The overriden aspect ratio for this camera. + * + * When this is 0.0f, use the aspect ratio implied by ViewportSize. + * + * This may be different from the aspect ratio implied by the ViewportSize + * and black bars are added as needed in order to achieve this aspect ratio + * within a larger viewport. + */ + UPROPERTY(BlueprintReadWrite, Category = "Cesium") + double OverrideAspectRatio = 0.0; + + /** + * @brief Construct an uninitialized FCesiumCamera object. + */ + FCesiumCamera(); + + /** + * @brief Construct a new FCesiumCamera object. + * + * @param ViewportSize The viewport pixel size. + * @param Location The Unreal location. + * @param Rotation The Unreal rotation. + * @param FieldOfViewDegrees The horizontal field of view in degrees. + */ + FCesiumCamera( + const FVector2D& ViewportSize, + const FVector& Location, + const FRotator& Rotation, + double FieldOfViewDegrees); + + /** + * @brief Construct a new FCesiumCamera object. + * + * @param ViewportSize The viewport pixel size. + * @param Location The Unreal location. + * @param Rotation The Unreal rotation. + * @param FieldOfViewDegrees The horizontal field of view in degrees. + * @param OverrideAspectRatio The overriden aspect ratio. + */ + FCesiumCamera( + const FVector2D& ViewportSize, + const FVector& Location, + const FRotator& Rotation, + double FieldOfViewDegrees, + double OverrideAspectRatio); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCameraManager.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCameraManager.h new file mode 100644 index 0000000..4575a7d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCameraManager.h @@ -0,0 +1,80 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumCamera.h" +#include "Containers/Map.h" +#include "GameFramework/Actor.h" + +#include "CesiumCameraManager.generated.h" + +/** + * @brief Manages custom {@link FCesiumCamera}s for all + * {@link ACesium3DTileset}s in the world. + */ +UCLASS() +class CESIUMRUNTIME_API ACesiumCameraManager : public AActor { + GENERATED_BODY() + +public: + /** + * @brief Get the camera manager for this world. + */ + UFUNCTION( + BlueprintCallable, + Category = "CesiumCameraManager", + meta = (WorldContext = "WorldContextObject")) + static ACesiumCameraManager* + GetDefaultCameraManager(const UObject* WorldContextObject); + + ACesiumCameraManager(); + + /** + * @brief Register a new camera with the camera manager. + * + * @param Camera The current state for the new camera. + * @return The generated ID for this camera. Use this ID to refer to the + * camera in the future when calling UpdateCamera. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + int32 AddCamera(UPARAM(ref) const FCesiumCamera& Camera); + + /** + * @brief Unregister an existing camera with the camera manager. + * + * @param CameraId The ID of the camera, as returned by AddCamera during + * registration. + * @return Whether the updating was successful. If false, the CameraId was + * invalid. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + bool RemoveCamera(int32 CameraId); + + /** + * @brief Update the state of the specified camera. + * + * @param CameraId The ID of the camera, as returned by AddCamera during + * registration. + * @param Camera The new, updated state of the camera. + * @return Whether the updating was successful. If false, the CameraId was + * invalid. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + bool UpdateCamera(int32 CameraId, UPARAM(ref) const FCesiumCamera& Camera); + + /** + * @brief Get a read-only map of the current camera IDs to cameras. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + const TMap& GetCameras() const; + + virtual bool ShouldTickIfViewportsOnly() const override; + + virtual void Tick(float DeltaTime) override; + +private: + int32 _currentCameraId = 0; + TMap _cameras; + + static FName DEFAULT_CAMERAMANAGER_TAG; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCartographicPolygon.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCartographicPolygon.h new file mode 100644 index 0000000..770bdf3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCartographicPolygon.h @@ -0,0 +1,62 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGeoreference.h" +#include "CesiumGeospatial/CartographicPolygon.h" +#include "CesiumGeospatial/GlobeRectangle.h" +#include "CesiumGlobeAnchorComponent.h" +#include "Components/SplineComponent.h" +#include "CoreMinimal.h" +#include "Engine/StaticMesh.h" +#include "GameFramework/Actor.h" +#include + +#include "CesiumCartographicPolygon.generated.h" + +/** + * A spline-based polygon actor used to rasterize 2D polygons on top of + * Cesium 3D Tileset actors. + */ +UCLASS(ClassGroup = (Cesium), meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API ACesiumCartographicPolygon : public AActor { + + GENERATED_BODY() + +public: + ACesiumCartographicPolygon(); + + /** + * The polygon. + */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + USplineComponent* Polygon; + + /** + * The Globe Anchor Component that precisely ties this Polygon to the Globe. + */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + UCesiumGlobeAnchorComponent* GlobeAnchor; + + virtual void OnConstruction(const FTransform& Transform) override; + + /** + * Creates and returns a CartographicPolygon object + * created from the current spline selection. + * + * @param worldToTileset The transformation from Unreal world coordinates to + * the coordinates of the Cesium3DTileset Actor for which the cartographic + * polygon is being created. + */ + CesiumGeospatial::CartographicPolygon + CreateCartographicPolygon(const FTransform& worldToTileset) const; + + // AActor overrides + virtual void PostLoad() override; + +protected: + virtual void BeginPlay() override; + +private: + void MakeLinear(); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCommon.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCommon.h new file mode 100644 index 0000000..d988026 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCommon.h @@ -0,0 +1,10 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Runtime/Launch/Resources/Version.h" + +#define ENGINE_VERSION_5_5_OR_HIGHER \ + (ENGINE_MAJOR_VERSION > 5 || ENGINE_MINOR_VERSION >= 5) +#define ENGINE_VERSION_5_4_OR_HIGHER \ + (ENGINE_MAJOR_VERSION > 5 || ENGINE_MINOR_VERSION >= 4) diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCreditSystem.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCreditSystem.h new file mode 100644 index 0000000..3163788 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCreditSystem.h @@ -0,0 +1,97 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Components/WidgetComponent.h" +#include "Engine/Blueprint.h" +#include "GameFramework/Actor.h" +#include "UObject/Class.h" +#include "UObject/ConstructorHelpers.h" +#include +#include +#include + +#if WITH_EDITOR +#include "IAssetViewport.h" +#include "UnrealEdMisc.h" +#endif + +#include "CesiumCreditSystem.generated.h" + +namespace CesiumUtility { +class CreditSystem; +} + +/** + * Manages credits / atttribution for Cesium data sources. These credits + * are displayed by the corresponding Blueprints class + * /CesiumForUnreal/CesiumCreditSystemBP.CesiumCreditSystemBP_C. + */ +UCLASS(Abstract) +class CESIUMRUNTIME_API ACesiumCreditSystem : public AActor { + GENERATED_BODY() + +public: + static ACesiumCreditSystem* + GetDefaultCreditSystem(const UObject* WorldContextObject); + + ACesiumCreditSystem(); + + virtual void BeginPlay() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + + virtual void OnConstruction(const FTransform& Transform) override; + virtual void BeginDestroy() override; + + UPROPERTY(EditDefaultsOnly, Category = "Cesium") + TSubclassOf CreditsWidgetClass; + + /** + * Whether the credit string has changed since last frame. + */ + UPROPERTY(BlueprintReadOnly, Category = "Cesium") + bool CreditsUpdated = false; + + UPROPERTY(BlueprintReadOnly, Transient, Category = "Cesium") + class UScreenCreditsWidget* CreditsWidget; + + // Called every frame + virtual bool ShouldTickIfViewportsOnly() const override; + virtual void Tick(float DeltaTime) override; + + const std::shared_ptr& + GetExternalCreditSystem() const { + return _pCreditSystem; + } + + void updateCreditsViewport(bool recreateWidget); + void removeCreditsFromViewports(); + +#if WITH_EDITOR + void OnRedrawLevelEditingViewports(bool); + void OnPreBeginPIE(bool bIsSimulating); + void OnEndPIE(); + void OnCleanseEditor(); +#endif + +private: + static UObject* CesiumCreditSystemBP; + + /** + * A tag that is assigned to Credit Systems when they are created + * as the "default" Credit System for a certain world. + */ + static FName DEFAULT_CREDITSYSTEM_TAG; + + // the underlying cesium-native credit system that is managed by this actor. + std::shared_ptr _pCreditSystem; + + size_t _lastCreditsCount; + + FString ConvertHtmlToRtf(std::string html); + std::unordered_map _htmlToRtf; + +#if WITH_EDITOR + TWeakPtr _pLastEditorViewport; +#endif +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCustomVersion.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCustomVersion.h new file mode 100644 index 0000000..578a0f7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCustomVersion.h @@ -0,0 +1,50 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors +#pragma once + +#include "CoreMinimal.h" +#include "Misc/Guid.h" + +struct CESIUMRUNTIME_API FCesiumCustomVersion { + enum Versions { + // The version before any custom version was added to Cesium for Unreal + BeforeCustomVersionWasAdded = 0, + + // Cesium3DTileset gained the TilesetSource property. In previous versions, + // the tileset source was assumed to be the URL if one was supplied, and + // Cesium ion otherwise. + TilesetExplicitSource = 1, + + // The Georeferencing system was refactored. + GeoreferenceRefactoring = 2, + + // The explicit Mobility property on Cesium3DTileset was removed, in favor + // of the normal Mobility property on the RootComponent. + TilesetMobilityRemoved = 3, + + // The UCesiumGlobeAnchorComponent's globe transformation changed from being + // an array of doubles to being an FMatrix. + GlobeAnchorTransformationAsFMatrix = 4, + + // The origin shifting behavior became an independent component rather than + // built into the CesiumGeoreference. + OriginShiftComponent = 5, + + // Fly-to behavior became an independent component rather than built into + // the GlobeAwareDefaultPawn. + FlyToComponent = 6, + + // Added the CesiumIonServer property to Cesium3DTileset and + // CesiumIonRasterOverlay. + CesiumIonServer = 7, + + // Replaced the UseWebMercatorProjection property in + // CesiumWebMapTileServiceOverlay with the enum Projection property. + WebMapTileServiceProjectionAsEnum = 8, + + VersionPlusOne, + LatestVersion = VersionPlusOne - 1 + }; + + // The GUID for the Cesium for Unreal plugin's custom version + static const FGuid GUID; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumDebugColorizeTilesRasterOverlay.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumDebugColorizeTilesRasterOverlay.h new file mode 100644 index 0000000..f9415c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumDebugColorizeTilesRasterOverlay.h @@ -0,0 +1,25 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumRasterOverlay.h" +#include "CoreMinimal.h" +#include "CesiumDebugColorizeTilesRasterOverlay.generated.h" + +/** + * A raster overlay that can be used to debug tilesets by shading each tile with + * a random color. + */ +UCLASS( + DisplayName = "Cesium Debug Colorize Tiles Raster Overlay", + ClassGroup = (Cesium), + meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumDebugColorizeTilesRasterOverlay + : public UCesiumRasterOverlay { + GENERATED_BODY() + +public: +protected: + virtual std::unique_ptr CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options = {}) override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumEllipsoid.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumEllipsoid.h new file mode 100644 index 0000000..0931911 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumEllipsoid.h @@ -0,0 +1,148 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Engine/DataAsset.h" +#include "Misc/Optional.h" +#include +#include "CesiumEllipsoid.generated.h" + +namespace CesiumGeospatial { +class Ellipsoid; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumEllipsoid : public UDataAsset { + GENERATED_BODY() + +public: + /** + * Creates a new {@link UCesiumEllipsoid} with the given radii. + * + * This is equivalent to + * ``` + * auto ellipsoid = NewObject(); + * ellipsoid->SetRadii(Radii); + * ``` + */ + UFUNCTION(BlueprintCallable, Category = "Cesium|Ellipsoid") + static UCesiumEllipsoid* Create(const FVector& Radii); + + /** + * Gets the radii of the ellipsoid in its x-, y-, and z-directions in + * meters. + */ + UFUNCTION(BlueprintPure, Category = "Cesium|Ellipsoid") + FVector GetRadii(); + + /** + * Sets the radii of this ellipsoid in its x-, y-, and z-directions in meters. + * + * Tilesets using this ellipsoid may have to be refreshed to see the changes + * applied. + */ + void SetRadii(const FVector& NewRadii); + + /** + * Gets the maximum radius of the ellipsoid in any dimension, in meters. + */ + UFUNCTION(BlueprintPure, Category = "Cesium|Ellipsoid") + double GetMaximumRadius(); + + /** + * Gets the minimum radius of the ellipsoid in any dimension, in + * meters. + */ + UFUNCTION(BlueprintPure, Category = "Cesium|Ellipsoid") + double GetMinimumRadius(); + + /** + * Scale the given Ellipsoid-Centered, Ellipsoid-Fixed position along the + * geodetic surface normal so that it is on the surface of the ellipsoid. If + * the position is near the center of the ellipsoid, the result will have the + * value (0,0,0) because the surface position is undefined. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium|Ellipsoid", + meta = (ReturnDisplayName = "SurfacePosition")) + FVector + ScaleToGeodeticSurface(const FVector& EarthCenteredEarthFixedPosition); + + /** + * Computes the normal of the plane tangent to the surface of the ellipsoid + * at the provided Ellipsoid-Centered, Ellipsoid-Fixed position. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium|Ellipsoid", + meta = (ReturnDisplayName = "SurfaceNormalVector")) + FVector GeodeticSurfaceNormal(const FVector& EarthCenteredEarthFixedPosition); + + /** + * Convert longitude in degrees (X), latitude in degrees (Y), and height above + * the ellipsoid in meters (Z) to Ellipsoid-Centered, Ellipsoid-Fixed (ECEF) + * coordinates. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium|Ellipsoid", + meta = (ReturnDisplayName = "EarthCenteredEarthFixedPosition")) + FVector LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( + const FVector& LongitudeLatitudeHeight); + + /** + * Convert Ellipsoid-Centered, Ellipsoid-Fixed (ECEF) coordinates to longitude + * in degrees (X), latitude in degrees (Y), and height above the ellipsoid in + * meters (Z). If the position is near the center of the Ellipsoid, the result + * will have the value (0,0,0) because the longitude, latitude, and height are + * undefined. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium|Ellipsoid", + meta = (ReturnDisplayName = "LongitudeLatitudeHeight")) + FVector EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight( + const FVector& EarthCenteredEarthFixedPosition); + + /** + * Computes the transformation matrix from the local East-North-Up (ENU) frame + * to Ellipsoid-Centered, Ellipsoid-Fixed (ECEF) at the specified ECEF + * location. + */ + FMatrix EastNorthUpToEllipsoidCenteredEllipsoidFixed( + const FVector& EarthCenteredEarthFixedPosition); + + /** + * Returns a new {@link CesiumGeospatial::LocalHorizontalCoordinateSystem} + * with the given scale, center, and ellipsoid. + */ + CesiumGeospatial::LocalHorizontalCoordinateSystem + CreateCoordinateSystem(const FVector& Center, double Scale); + + /** + * Returns the underlying {@link CesiumGeospatial::Ellipsoid} + */ + const CesiumGeospatial::Ellipsoid& GetNativeEllipsoid(); + +protected: + /** + * The radii of this ellipsoid. + * + * The X coordinate of the vector should be the radius of the largest axis and + * the Z coordinate should be the radius of the smallest axis. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium|Ellipsoid", + meta = (DisplayName = "Radii")) + FVector Radii; + +private: +#if WITH_EDITOR + virtual void + PostSaveRoot(FObjectPostSaveRootContext ObjectSaveContext) override; +#endif + + TOptional NativeEllipsoid; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumEncodedMetadataComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumEncodedMetadataComponent.h new file mode 100644 index 0000000..4e4ad3b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumEncodedMetadataComponent.h @@ -0,0 +1,328 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Components/ActorComponent.h" +#include "Containers/Array.h" +#include "Containers/UnrealString.h" +#include "Misc/Guid.h" + +#if WITH_EDITOR +#include "Materials/MaterialFunctionMaterialLayer.h" +#endif + +#include "CesiumEncodedMetadataComponent.generated.h" + +PRAGMA_DISABLE_DEPRECATION_WARNINGS + +/** + * @brief The GPU component type to coerce this property to. + * + */ +UENUM() +enum class ECesiumPropertyComponentType_DEPRECATED : uint8 { + Uint8_DEPRECATED, + Float_DEPRECATED +}; + +/** + * @brief The property type. + */ +UENUM() +enum class ECesiumPropertyType_DEPRECATED : uint8 { + Scalar_DEPRECATED, + Vec2_DEPRECATED, + Vec3_DEPRECATED, + Vec4_DEPRECATED +}; + +/** + * @brief Describes how this feature table is accessed. Either through feature + * id textures, feature id attributes, mixed, or neither. + */ +UENUM() +enum class ECesiumFeatureTableAccessType_DEPRECATED : uint8 { + Unknown_DEPRECATED, + Texture_DEPRECATED, + Attribute_DEPRECATED, + Mixed_DEPRECATED +}; + +// Note that these don't exhaustively cover the possibilities of glTF metadata +// classes, they only cover the subset that can be encoded into textures. For +// example, arbitrary size arrays and enums are excluded. Other un-encoded +// types like strings will be coerced. + +struct UE_DEPRECATED( + 5.0, + "CesiumEncodedMetadataComponent and its related description properties have been deprecated. Use CesiumEncodedFeaturesMetadata instead.") + FPropertyDescription; + +/** + * @brief Description of a feature table property that should be encoded for + * access on the GPU. + */ +USTRUCT() +struct CESIUMRUNTIME_API FPropertyDescription { + GENERATED_USTRUCT_BODY() + + /** + * @brief The name of this property as it will be referenced in the + * material. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FString Name; + + /** + * @brief The GPU component type to coerce this property to. + * + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + ECesiumPropertyComponentType_DEPRECATED ComponentType = + ECesiumPropertyComponentType_DEPRECATED::Float_DEPRECATED; + + /** + * @brief The property type. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + ECesiumPropertyType_DEPRECATED Type = + ECesiumPropertyType_DEPRECATED::Scalar_DEPRECATED; + + /** + * @brief If ComponentType==Uint8, this indicates whether to normalize into a + * [0-1] range before accessing on the GPU. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = + (EditCondition = + "ComponentType==ECesiumPropertyComponentType_DEPRECATED::Uint8_DEPRECATED")) + bool Normalized = false; +}; + +struct UE_DEPRECATED( + 5.0, + "CesiumEncodedMetadataComponent and its related description properties have been deprecated. Use CesiumEncodedFeaturesMetadata instead.") + FFeatureTableDescription; + +/** + * @brief Description of a feature table containing properties to be encoded + * for access on the GPU. + */ +USTRUCT() +struct CESIUMRUNTIME_API FFeatureTableDescription { + GENERATED_USTRUCT_BODY() + + /** + * @brief The name of this feature table. + * + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FString Name; + + /** + * @brief Describes how this feature table is accessed. Either through feature + * id textures, feature id attributes, mixed, or neither. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + ECesiumFeatureTableAccessType_DEPRECATED AccessType = + ECesiumFeatureTableAccessType_DEPRECATED::Unknown_DEPRECATED; + + /** + * @brief If the AccessType==Texture, this string represents the channel of + * the feature id texture that will be used to index into this feature table. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = + (EditCondition = + "AccessType==ECesiumFeatureTableAccessType_DEPRECATED::Texture_DEPRECATED")) + FString Channel; + + /** + * @brief Descriptions of the properties to upload to the GPU. + */ + UPROPERTY(EditAnywhere, Category = "Cesium", Meta = (TitleProperty = "Name")) + TArray Properties; +}; + +struct UE_DEPRECATED( + 5.0, + "CesiumEncodedMetadataComponent and its related properties have been deprecated. Use CesiumEncodedFeaturesMetadata instead.") + FFeatureTexturePropertyDescription; + +/** + * @brief Description of a feature texture property that should be uploaded to + * the GPU. + */ +USTRUCT() +struct CESIUMRUNTIME_API FFeatureTexturePropertyDescription { + GENERATED_USTRUCT_BODY() + + /** + * @brief The name of this property as it will be referenced in the + * material. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FString Name; + + // For now, always assumes it is Uint8 + /* + UPROPERTY(EditAnywhere, Category = "Cesium") + ECesiumPropertyComponentType ComponentType = + ECesiumPropertyComponentType::Uint8;*/ + + /** + * @brief The property type. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + ECesiumPropertyType_DEPRECATED Type = + ECesiumPropertyType_DEPRECATED::Scalar_DEPRECATED; + + /** + * @brief If ComponentType==Uint8, this indicates whether to normalize into a + * [0-1] range before accessing on the GPU. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + bool Normalized = false; + + /** + * @brief This string describes the channel order of the incoming feature + * texture property (e.g., "rgb", "bgra", etc.). This helps us fix the + * channel order when accessing on the GPU. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FString Swizzle; +}; + +struct UE_DEPRECATED( + 5.0, + "CesiumEncodedMetadataComponent and its related description properties have been deprecated. Use CesiumEncodedFeaturesMetadata instead.") + FFeatureTextureDescription; + +/** + * @brief Description of a feature texture with properties that should be + * uploaded to the GPU. + */ +USTRUCT() +struct CESIUMRUNTIME_API FFeatureTextureDescription { + GENERATED_USTRUCT_BODY() + + /** + * @brief The name of this feature texture. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FString Name; + + /** + * @brief Descriptions of the properties to upload to the GPU. + */ + UPROPERTY(EditAnywhere, Category = "Cesium", Meta = (TitleProperty = "Name")) + TArray Properties; +}; + +struct UE_DEPRECATED( + 5.0, + "CesiumEncodedMetadataComponent and its related description properties have been deprecated. Use CesiumEncodedFeaturesMetadata instead.") + FMetadataDescription; + +struct UE_DEPRECATED( + 5.0, + "CesiumEncodedMetadataComponent and its related description properties have been deprecated. Use CesiumEncodedFeaturesMetadata instead.") + FMetadataDescription; + +/** + * @brief Description of metadata from a glTF that should be uploaded to the + * GPU for access in materials. + */ +USTRUCT() +struct CESIUMRUNTIME_API FMetadataDescription { + GENERATED_USTRUCT_BODY() + + /** + * @brief Descriptions of feature tables to upload to the GPU. + */ + UPROPERTY( + EditAnywhere, + Category = "EncodeMetadata", + Meta = (TitleProperty = "Name")) + TArray FeatureTables; + + /** + * @brief Descriptions of feature textures to upload to the GPU. + */ + UPROPERTY( + EditAnywhere, + Category = "EncodeMetadata", + Meta = (TitleProperty = "Name")) + TArray FeatureTextures; +}; + +/** + * @brief An actor component that can be added to Cesium3DTileset actors to + * dictate what metadata to encode for access on the GPU. The selection can be + * automatically populated based on available metadata by clicking the + * "Auto Fill" button. Once a selection of desired metadata is made, the + * boiler-plate material code to access the selected properties can be + * auto-generated using the "Generate Material" button. + */ +UCLASS(Deprecated) +class CESIUMRUNTIME_API UDEPRECATED_CesiumEncodedMetadataComponent + : public UActorComponent { + GENERATED_BODY() + +public: +#if WITH_EDITORONLY_DATA + /** + * @brief This is the target UMaterialFunctionMaterialLayer that the + * boiler-plate material generation will use. When pressing + * "Generate Material", nodes will be added to this material to enable access + * to the requested metadata. If this is left blank, a new material layer + * will be created in the /Game/ folder. + */ + UPROPERTY( + EditAnywhere, + Category = "EncodeMetadata", + Meta = + (DeprecatedProperty, + DeprecationMessage = + "CesiumEncodedMetadataComponent is deprecated. Use CesiumFeaturesMetadataComponent instead.")) + UMaterialFunctionMaterialLayer* TargetMaterialLayer = nullptr; +#endif + + // Note: Here, we avoid wrapping the feature tables and feature textures + // inside a FMetadataDescription to avoid further complicating the details + // panel UI for editing the hierarchy. + + /** + * @brief Descriptions of feature tables to upload to the GPU. + */ + UPROPERTY( + EditAnywhere, + Category = "EncodeMetadata", + Meta = + (TitleProperty = "Name", + DeprecatedProperty, + DeprecationMessage = + "CesiumEncodedMetadataComponent is deprecated. Use CesiumFeaturesMetadataComponent instead.")) + TArray FeatureTables; + + /** + * @brief Descriptions of feature textures to upload to the GPU. + */ + UPROPERTY( + EditAnywhere, + Category = "EncodeMetadata", + Meta = + (TitleProperty = "Name", + DeprecatedProperty, + DeprecationMessage = + "CesiumEncodedMetadataComponent is deprecated. Use CesiumFeaturesMetadataComponent instead.")) + TArray FeatureTextures; + + // virtual void Serialize(FArchive& Ar) override; +}; + +PRAGMA_ENABLE_DEPRECATION_WARNINGS diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdAttribute.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdAttribute.h new file mode 100644 index 0000000..7604a12 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdAttribute.h @@ -0,0 +1,165 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Kismet/BlueprintFunctionLibrary.h" +#include +#include "CesiumFeatureIdAttribute.generated.h" + +namespace CesiumGltf { +struct Model; +struct Accessor; +struct Node; +} // namespace CesiumGltf + +/** + * @brief Reports the status of a FCesiumFeatureIdAttribute. If the feature ID + * attribute cannot be accessed, this briefly indicates why. + */ +UENUM(BlueprintType) +enum class ECesiumFeatureIdAttributeStatus : uint8 { + /* The feature ID attribute is valid. */ + Valid = 0, + /* The feature ID attribute does not exist in the glTF primitive. */ + ErrorInvalidAttribute, + /* The feature ID attribute uses an invalid accessor in the glTF. */ + ErrorInvalidAccessor +}; + +/** + * @brief A blueprint-accessible wrapper for a feature ID attribute from a glTF + * model. Provides access to feature IDs which can be used with the + * corresponding {@link FCesiumPropertyTable} to access metadata. These feature + * IDs may be defined per-vertex or per-instance. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumFeatureIdAttribute { + GENERATED_USTRUCT_BODY() + +public: + /** + * @brief Constructs an empty feature ID attribute instance. Empty feature ID + * attributes can be constructed while trying to convert a FCesiumFeatureIdSet + * that is not an attribute. In this case, the status reports it is an invalid + * attribute. + */ + FCesiumFeatureIdAttribute() + : _status(ECesiumFeatureIdAttributeStatus::ErrorInvalidAttribute), + _featureIdAccessor(), + _attributeIndex(-1) {} + + /** + * @brief Constructs a feature ID attribute instance. + * + * @param Model The model. + * @param Primitive The mesh primitive containing the feature ID attribute. + * @param FeatureIDAttribute The attribute index specified by the FeatureId. + * @param PropertyTableName The name of the property table this attribute + * corresponds to, if one exists, for backwards compatibility. + */ + FCesiumFeatureIdAttribute( + const CesiumGltf::Model& Model, + const CesiumGltf::MeshPrimitive& Primitive, + const int64 FeatureIDAttribute, + const FString& PropertyTableName); + + /** + * @brief Constructs a feature ID attribute instance from + * EXT_instance_features data. + * + * @param Model The model. + * @param Node The node containing the feature ID attribute. + * @param FeatureIDAttribute The attribute index specified by the FeatureId. + * @param PropertyTableName The name of the property table this attribute + * corresponds to, if one exists, for backwards compatibility. + */ + FCesiumFeatureIdAttribute( + const CesiumGltf::Model& Model, + const CesiumGltf::Node& Node, + const int64 FeatureIDAttribute, + const FString& PropertyTableName); + + /** + * Gets the index of this feature ID attribute in the glTF primitive. + */ + int64 getAttributeIndex() const { return this->_attributeIndex; } + +private: + ECesiumFeatureIdAttributeStatus _status; + CesiumGltf::FeatureIdAccessorType _featureIdAccessor; + int64 _attributeIndex; + + // For backwards compatibility. + FString _propertyTableName; + + friend class UCesiumFeatureIdAttributeBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumFeatureIdAttributeBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Get the name of the feature table corresponding to this feature ID + * attribute. The name can be used to fetch the appropriate + * FCesiumFeatureTable from the FCesiumMetadataModel. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "Use GetPropertyTableIndex on a CesiumFeatureIdSet instead.")) + static const FString& + GetFeatureTableName(UPARAM(ref) + const FCesiumFeatureIdAttribute& FeatureIDAttribute); + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * Gets the status of the feature ID attribute. If this attribute is + * invalid in any way, this will briefly indicate why. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDAttribute") + static ECesiumFeatureIdAttributeStatus GetFeatureIDAttributeStatus( + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIDAttribute); + + /** + * Gets the number of elements in the attribute. This is distinct from the + * number of unique feature IDs within the attribute. + * + * For a feature ID attribute of a regular mesh, this is the number of + * vertices. For a per-instance feature ID, this is the number of instances. + * + * If the feature ID attribute is invalid, this returns 0. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDAttribute") + static int64 + GetCount(UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIDAttribute); + + /** + * Gets the feature ID at the given index. A feature ID can be used with a + * FCesiumPropertyTable to retrieve the metadata for that ID. If the feature + * ID attribute is invalid, this returns -1. + * + * For a feature ID attribute of a regular mesh, the provided Index is the + * index of a vertex within the mesh. For a per-instance feature ID, the + * provided Index is the index of the instance. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDAttribute") + static int64 GetFeatureID( + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIDAttribute, + int64 Index); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdSet.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdSet.h new file mode 100644 index 0000000..ee66990 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdSet.h @@ -0,0 +1,217 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumFeatureIdAttribute.h" +#include "CesiumFeatureIdTexture.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include +#include "CesiumFeatureIdSet.generated.h" + +namespace CesiumGltf { +struct Model; +struct FeatureId; +struct ExtensionExtInstanceFeaturesFeatureId; +} // namespace CesiumGltf + +/** + * @brief The type of a feature ID set. + */ +UENUM(BlueprintType) +enum class ECesiumFeatureIdSetType : uint8 { + None, + Attribute, + Texture, + Implicit, + Instance, + InstanceImplicit +}; + +/** + * @brief A blueprint-accessible wrapper for a feature ID set from a glTF + * primitive. A feature ID can be defined as a per-vertex attribute, as a + * feature texture, implicitly via vertex ID, or associated with glTF + * instances. These can be used with the corresponding {@link + * FCesiumPropertyTable} to access the metadata. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumFeatureIdSet { + GENERATED_USTRUCT_BODY() + + using FeatureIDType = std::variant< + std::monostate, + FCesiumFeatureIdAttribute, + FCesiumFeatureIdTexture>; + +public: + FCesiumFeatureIdSet() + : _featureIDSetType(ECesiumFeatureIdSetType::None), + _featureCount(0), + _nullFeatureID(-1) {} + + FCesiumFeatureIdSet( + const CesiumGltf::Model& Model, + const CesiumGltf::MeshPrimitive& Primitive, + const CesiumGltf::FeatureId& FeatureId); + + FCesiumFeatureIdSet( + const CesiumGltf::Model& Model, + const CesiumGltf::Node& Node, + const CesiumGltf::ExtensionExtInstanceFeaturesFeatureId& + InstanceFeatureId); + +private: + FeatureIDType _featureID; + ECesiumFeatureIdSetType _featureIDSetType; + int64 _featureCount; + int64 _nullFeatureID; + int64 _propertyTableIndex; + FString _label; + + friend class UCesiumFeatureIdSetBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumFeatureIdSetBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() +public: + /** + * Gets the type of this feature ID set. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDSet") + static const ECesiumFeatureIdSetType + GetFeatureIDSetType(UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet); + + /** + * Gets this feature ID set as a feature ID attribute. This can be used for + * more fine-grained interaction with the attribute itself. If this feature ID + * is not defined as an attribute, then the returned attribute will be + * invalid. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDSet") + static const FCesiumFeatureIdAttribute& + GetAsFeatureIDAttribute(UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet); + + /** + * Gets this feature ID set as a feature ID texture. This can be used for more + * fine-grained interaction with the texture itself. If this feature ID is + * not defined as a texture, then the returned texture will be invalid. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDSet") + static const FCesiumFeatureIdTexture& + GetAsFeatureIDTexture(UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet); + + /** + * Get the index of the property table corresponding to this feature + * ID set. The index can be used to fetch the appropriate + * FCesiumPropertyTable from the FCesiumModelMetadata. If the + * feature ID set does not specify a property table, this returns -1. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDSet") + static const int64 + GetPropertyTableIndex(UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet); + + /** + * Get the number of features this primitive has. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDSet") + static int64 GetFeatureCount(UPARAM(ref) + const FCesiumFeatureIdSet& FeatureIDSet); + + /** + * Gets the null feature ID, i.e., the value that indicates no feature is + * associated with the owner. In other words, if a vertex or texel returns + * this value, then it is not associated with any feature. + * + * If this value was not defined in the glTF feature ID set, this defaults to + * -1. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDSet") + static const int64 + GetNullFeatureID(UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet); + + /** + * Gets the label assigned to this feature ID set. If no label was present in + * the glTF feature ID set, this returns an empty string. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDSet") + static const FString GetLabel(UPARAM(ref) + const FCesiumFeatureIdSet& FeatureIDSet); + + /** + * Gets the feature ID associated with a given vertex. The feature ID can be + * used with a FCesiumPropertyTable to retrieve the corresponding metadata. + * + * This returns -1 if the given vertex is out-of-bounds, or if the feature ID + * set is invalid (e.g., it contains an invalid feature ID texture). + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDSet") + static int64 GetFeatureIDForVertex( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet, + int64 VertexIndex); + + /** + * Gets the feature ID associated with a given instance in glTF models using + * the EXT_mesh_gpu_instancing and EXT_instance_features extensions. The + * feature ID can be used with a FCesiumPropertyTable to retrieve the + * corresponding metadata. + * + * This returns -1 if the given instance is out-of-bounds, if the feature ID + * set is not for instances, or if the feature ID set is invalid (e.g., it + * contains an invalid feature ID attribute). + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDSet") + static int64 GetFeatureIDForInstance( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet, + int64 InstanceIndex); + + /** + * Given a trace hit result, gets the feature ID from the feature ID set on + * the hit component. This returns a more accurate value for feature ID + * textures, since they define feature IDs per-texel instead of per-vertex. + * The feature ID can be used with a FCesiumPropertyTable to retrieve the + * corresponding metadata. + * + * This can still retrieve the feature IDs for non-texture feature ID sets. + * For attribute or implicit feature IDs, the first feature ID associated + * with the first vertex of the intersected face is returned. + * + * This returns -1 if the feature ID set is invalid (e.g., it contains an + * invalid feature ID texture). + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDSet") + static int64 GetFeatureIDFromHit( + UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet, + const FHitResult& Hit); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdTexture.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdTexture.h new file mode 100644 index 0000000..465dc0d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdTexture.h @@ -0,0 +1,233 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Containers/UnrealString.h" +#include "Kismet/BlueprintFunctionLibrary.h" + +#include +#include + +#include "CesiumFeatureIdTexture.generated.h" + +namespace CesiumGltf { +struct Model; +struct FeatureIdTexture; +} // namespace CesiumGltf + +/** + * @brief Reports the status of a FCesiumFeatureIdTexture. If the feature ID + * texture cannot be accessed, this briefly indicates why. + */ +UENUM(BlueprintType) +enum ECesiumFeatureIdTextureStatus { + /* The feature ID texture is valid. */ + Valid = 0, + /* The feature ID texture cannot be found in the glTF, or the texture itself + has errors. */ + ErrorInvalidTexture, + /* The feature ID texture is being read in an invalid way -- for example, + trying to read nonexistent image channels. */ + ErrorInvalidTextureAccess, +}; + +/** + * @brief A blueprint-accessible wrapper for a feature ID texture from a glTF + * primitive. Provides access to per-pixel feature IDs, which can be used with + * the corresponding {@link FCesiumPropertyTable} to access per-pixel metadata. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumFeatureIdTexture { + GENERATED_USTRUCT_BODY() + +public: + /** + * @brief Constructs an empty feature ID texture instance. Empty feature ID + * textures can be constructed while trying to convert a FCesiumFeatureIdSet + * that is not an texture. In this case, the status reports it is an invalid + * texture. + */ + FCesiumFeatureIdTexture() + : _status(ECesiumFeatureIdTextureStatus::ErrorInvalidTexture) {} + + /** + * @brief Constructs a feature ID texture instance. + * + * @param Model The model. + * @param Primitive The mesh primitive containing the feature ID texture. + * @param FeatureIdTexture The texture specified by the FeatureId. + * @param PropertyTableName The name of the property table this texture + * corresponds to, if one exists, for backwards compatibility. + */ + FCesiumFeatureIdTexture( + const CesiumGltf::Model& Model, + const CesiumGltf::MeshPrimitive& Primitive, + const CesiumGltf::FeatureIdTexture& FeatureIdTexture, + const FString& PropertyTableName); + + /** + * @brief Gets the underlying view of this feature ID texture. + */ + constexpr const CesiumGltf::FeatureIdTextureView& + getFeatureIdTextureView() const { + return this->_featureIdTextureView; + } + +private: + ECesiumFeatureIdTextureStatus _status; + CesiumGltf::FeatureIdTextureView _featureIdTextureView; + CesiumGltf::TexCoordAccessorType _texCoordAccessor; + int64 _textureCoordinateSetIndex; + + // For backwards compatibility. + FString _propertyTableName; + + friend class UCesiumFeatureIdTextureBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumFeatureIdTextureBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Gets the name of the feature table corresponding to this feature ID + * texture. The name can be used to fetch the appropriate + * {@link FCesiumPropertyTable} from the FCesiumMetadataModel. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureIdTexture", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "Use GetPropertyTableIndex on a CesiumFeatureIdSet instead.")) + static const FString& + GetFeatureTableName(UPARAM(ref) + const FCesiumFeatureIdTexture& FeatureIDTexture); + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * Gets the status of the feature ID texture. If this texture is + * invalid in any way, this will briefly indicate why. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDTexture") + static ECesiumFeatureIdTextureStatus GetFeatureIDTextureStatus( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture); + + /** + * Gets the glTF texture coordinate set index used by the feature ID texture. + * This is the index N corresponding to the "TEXCOORD_N" attribute on the glTF + * primitive that samples this texture. + * + * If the texture contains the `KHR_texture_transform` extension, the original + * texture coordinate set index can be overridden by the one provided by the + * extension. + * + * If the feature ID texture is invalid, this returns -1. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDTexture") + static int64 GetGltfTextureCoordinateSetIndex( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture); + + /** + * Gets the UV channel containing the texture coordinate set that is used by + * the feature ID texture on the given component. This refers to the UV + * channel it uses on the primitive's static mesh, which is not necessarily + * equal to value of GetGltfTextureCoordinateSetIndex. + * + * This function may be used with FindCollisionUV to get the feature ID from a + * line trace hit. However, in order for this function to work, the feature ID + * texture should be listed under the CesiumFeaturesMetadataComponent of the + * owner Cesium3DTileset. Otherwise, its texture coordinate set may not be + * included in the Unreal mesh data. To avoid using + * CesiumFeaturesMetadataComponent, use GetFeatureIDFromHit instead. + * + * This returns -1 if the feature ID texture is invalid, or if the specified + * texture coordinate set is not present in the component's mesh data. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDTexture") + static int64 GetUnrealUVChannel( + const UPrimitiveComponent* Component, + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Gets the feature ID corresponding to the pixel specified by the texture + * coordinates. The feature ID can be used with a FCesiumPropertyTable to + * retrieve the per-pixel metadata. + * + * This assumes the given texture coordinates are from the appropriate + * texture coordinate set as indicated by GetTextureCoordinateSetIndex. If the + * feature ID texture is invalid, this returns -1. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDTexture") + static int64 GetFeatureIDForTextureCoordinates( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture, + float U, + float V); + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * Gets the feature ID corresponding to the pixel specified by the UV texture + * coordinates. The feature ID can be used with a FCesiumPropertyTable to + * retrieve the per-pixel metadata. + * + * If the feature ID texture is invalid, this returns -1. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDTexture") + static int64 GetFeatureIDForUV( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture, + const FVector2D& UV); + + /** + * Gets the feature ID associated with the given vertex. The + * feature ID can be used with a FCesiumPropertyTable to retrieve the + * per-vertex metadata. + * + * This works if the vertex contains texture coordinates for the relevant + * texture coordinate set as indicated by GetGltfTextureCoordinateSetIndex. If + * the vertex has no such coordinates, or if the feature ID texture itself is + * invalid, this returns -1. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDTexture") + static int64 GetFeatureIDForVertex( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture, + int64 VertexIndex); + + /** + * Gets the feature ID from a given line trace hit on the primitive containing + * this feature ID texture. The feature ID can be used with a + * FCesiumPropertyTable to retrieve the corresponding metadata. + * + * If the feature ID texture is invalid, this returns -1. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Features|FeatureIDTexture") + static int64 GetFeatureIDFromHit( + UPARAM(ref) const FCesiumFeatureIdTexture& FeatureIDTexture, + const FHitResult& Hit); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeaturesMetadataComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeaturesMetadataComponent.h new file mode 100644 index 0000000..114a533 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeaturesMetadataComponent.h @@ -0,0 +1,415 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumFeatureIdSet.h" +#include "CesiumMetadataEncodingDetails.h" +#include "CesiumMetadataPropertyDetails.h" +#include "Components/ActorComponent.h" +#include "Containers/Array.h" +#include "Containers/UnrealString.h" +#include "Misc/Guid.h" + +#if WITH_EDITOR +#include "Materials/MaterialFunctionMaterialLayer.h" +#endif + +#include "CesiumFeaturesMetadataComponent.generated.h" + +#pragma region Features descriptions + +/** + * @brief Description of a feature ID set from EXT_mesh_features. + */ +USTRUCT() +struct CESIUMRUNTIME_API FCesiumFeatureIdSetDescription { + GENERATED_USTRUCT_BODY() + + /** + * The display name of the feature ID set. If the feature ID set already has a + * label, this will use the label. Otherwise, if the feature ID set is + * unlabeled, a name will be generated like so: + * + * - If the feature ID set is an attribute, this will appear as + * "_FEATURE_ID_\", where \ is the set index specified in + * the attribute. + * - If the feature ID set is a texture, this will appear as + * "_FEATURE_ID_TEXTURE_\", where \ increments with the number + * of feature ID textures seen in an individual primitive. + * - If the feature ID set is an implicit set, this will appear as + * "_IMPLICIT_FEATURE_ID". Implicit feature ID sets don't vary in definition, + * so any additional implicit feature ID sets across the primitives are + * counted by this one. + * + * This name will also be used to represent the feature ID set in the + * generated material. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FString Name; + + /** + * The type of the feature ID set. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + ECesiumFeatureIdSetType Type = ECesiumFeatureIdSetType::None; + + /** + * Whether this feature ID set contains a KHR_texture_transform glTF + * extension. Only applicable if the feature ID set is a feature ID texture. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = (EditCondition = "Type == ECesiumFeatureIdSetType::Texture")) + bool bHasKhrTextureTransform = false; + + /** + * The name of the property table that this feature ID set corresponds to. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FString PropertyTableName; + + /** + * The null feature ID for the feature ID set. This value indicates that no + * feature is associated with the vertex or texel containing the value. If no + * such value is specified, this defaults to -1, which prevents it from being + * unnecessarily included in the generated material. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + bool bHasNullFeatureId = false; +}; + +/** + * @brief Description of the feature ID sets available from the + * EXT_mesh_features on a glTF's primitives. + * + * This aggregates the feature ID sets of all visible glTF primitives in the + * model. This describes the feature IDs that can be made accessible + * to Unreal Engine materials. + */ +USTRUCT() +struct CESIUMRUNTIME_API FCesiumPrimitiveFeaturesDescription { + GENERATED_USTRUCT_BODY() + + /** + * @brief The feature ID sets to make accessible to the material. Note that + * the order of feature ID sets in this array does not necessarily + * correspond to the order of these feature ID sets in a glTF + * primitive. + */ + UPROPERTY( + EditAnywhere, + Category = "Features", + Meta = (TitleProperty = "Name")) + TArray FeatureIdSets; +}; +#pragma endregion + +#pragma region Metadata descriptions + +// These don't exhaustively cover the possibilities of glTF metadata +// classes, they only cover the subset that can be encoded into textures. The +// following types are excluded: +// - enums +// - strings that cannot be parsed as numbers or colors +// - matrices +// - variable length arrays +// - arrays of non-scalar, non-boolean elements +// +// Additionally, if a property contains fixed-length arrays, only the first four +// elements can be encoded. + +/** + * @brief Description of a property table property that should be encoded for + * access on the GPU. + */ +USTRUCT() +struct CESIUMRUNTIME_API FCesiumPropertyTablePropertyDescription { + GENERATED_USTRUCT_BODY() + + /** + * The name of this property. This will be how it is referenced in the + * material. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FString Name; + + /** + * Describes the underlying type of this property and other relevant + * information from its EXT_structural_metadata definition. Not all types of + * properties can be encoded to the GPU, or coerced to GPU-compatible types. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FCesiumMetadataPropertyDetails PropertyDetails; + + /** + * Describes how the property will be encoded as data on the GPU, if possible. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FCesiumMetadataEncodingDetails EncodingDetails; +}; + +/** + * @brief Description of a property table containing properties to be encoded + * for access in Unreal materials. + */ +USTRUCT() +struct CESIUMRUNTIME_API FCesiumPropertyTableDescription { + GENERATED_USTRUCT_BODY() + + /** + * @brief The name of this property table. If this property table has no name + * in the EXT_structural_metadata extension, then its class name is used + * instead. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FString Name; + + /** + * @brief Descriptions of the properties to upload to the GPU. + */ + UPROPERTY(EditAnywhere, Category = "Cesium", Meta = (TitleProperty = "Name")) + TArray Properties; +}; + +/** + * @brief Description of a property texture property that should be made + * accessible to Unreal materials. A property texture property's data is + * already available through a texture, so no additional encoding details need + * to be specified. + */ +USTRUCT() +struct CESIUMRUNTIME_API FCesiumPropertyTexturePropertyDescription { + GENERATED_USTRUCT_BODY() + + /** + * The name of this property. This will be how it is referenced in the + * material. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FString Name; + + /** + * Describes the underlying type of this property and other relevant + * information from its EXT_structural_metadata definition. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FCesiumMetadataPropertyDetails PropertyDetails; + + /** + * Whether this property texture property contains a KHR_texture_transform + * glTF extension. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + bool bHasKhrTextureTransform = false; +}; + +/** + * @brief Description of a property texture with properties that should be + * made accessible to Unreal materials. + */ +USTRUCT() +struct CESIUMRUNTIME_API FCesiumPropertyTextureDescription { + GENERATED_USTRUCT_BODY() + + /** + * @brief The name of this property texture. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + FString Name; + + /** + * @brief Descriptions of the properties to upload to the GPU. + */ + UPROPERTY(EditAnywhere, Category = "Cesium", Meta = (TitleProperty = "Name")) + TArray Properties; +}; + +/** + * @brief Names of the metadata entities referenced by the + * EXT_structural_metadata on a glTF's primitives. + * + * This aggregates the metadata of all visible glTF primitives in the model. + * This lists the names of the property textures actually used by the glTF + * primitive, indicating it can be sampled with the primitive's texture + * coordinates in the Unreal material. + */ +USTRUCT() +struct CESIUMRUNTIME_API FCesiumPrimitiveMetadataDescription { + GENERATED_USTRUCT_BODY() + + /** + * @brief The names of the property textures used by the glTF primitives + * across the tileset. + * + * This should be a subset of the property textures listed in the model + * metadata. Property textures can be passed to the material even if they are + * not explicitly used by a glTF primitive, but the primitive may lack the + * corresponding sets of texture coordinates intended to sample them. + */ + UPROPERTY( + EditAnywhere, + Category = "Metadata", + Meta = (TitleProperty = "Name")) + TSet PropertyTextureNames; +}; + +/** + * @brief Description of metadata from a glTF's EXT_structural_metadata + * extension that should be uploaded to the GPU for access in Unreal materials. + */ +USTRUCT() +struct CESIUMRUNTIME_API FCesiumModelMetadataDescription { + GENERATED_USTRUCT_BODY() + + /** + * @brief Descriptions of property tables to encode for access in Unreal + * materials. + */ + UPROPERTY( + EditAnywhere, + Category = "Metadata", + Meta = (TitleProperty = "Name")) + TArray PropertyTables; + + /** + * @brief Descriptions of property textures to make accessible to Unreal + * materials. + */ + UPROPERTY( + EditAnywhere, + Category = "Metadata", + Meta = (TitleProperty = "Name")) + TArray PropertyTextures; +}; + +#pragma endregion + +/** + * @brief Description of both feature IDs and metadata from a glTF via the + * EXT_mesh_Features and EXT_structural_metadata extensions. Indicates what + * parts of the extension should be uploaded to the GPU for access in Unreal + * materials. + */ +USTRUCT() +struct CESIUMRUNTIME_API FCesiumFeaturesMetadataDescription { + GENERATED_USTRUCT_BODY() + +public: + /** + * @brief Description of the feature ID sets available from the + * EXT_mesh_features on a glTF's primitives. + */ + FCesiumPrimitiveFeaturesDescription Features; + + /** + * @brief Description of the metadata used by the EXT_structural_metadata on a + * glTF's primitives. + */ + FCesiumPrimitiveMetadataDescription PrimitiveMetadata; + + /** + * @brief Description of metadata from a glTF's EXT_structural_metadata + * extension. + */ + FCesiumModelMetadataDescription ModelMetadata; +}; + +/** + * @brief A component that can be added to Cesium3DTileset actors to + * dictate what metadata to encode for access on the GPU. The selection can be + * automatically populated based on available metadata by clicking the + * "Auto Fill" button. Once a selection of desired metadata is made, the + * boiler-plate material code to access the selected properties can be + * auto-generated using the "Generate Material" button. + */ +UCLASS(ClassGroup = (Cesium), Meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumFeaturesMetadataComponent + : public UActorComponent { + GENERATED_BODY() + +public: +#if WITH_EDITOR + /** + * Populate the description of metadata and feature IDs using the current view + * of the tileset. This determines what to encode to the GPU based on the + * existing metadata. + * + * Warning: Using Auto Fill may populate the description with a large amount + * of metadata. Make sure to delete the properties that aren't relevant. + */ + UFUNCTION(CallInEditor, Category = "Cesium") + void AutoFill(); + + /** + * This button can be used to create a boiler-plate material layer that + * exposes the requested metadata properties in the current description. The + * nodes to access the metadata will be added to TargetMaterialLayer if it + * exists. Otherwise a new material layer will be created in the /Content/ + * folder and TargetMaterialLayer will be set to the new material layer. + */ + UFUNCTION(CallInEditor, Category = "Cesium") + void GenerateMaterial(); +#endif + +#if WITH_EDITORONLY_DATA + /** + * This is the target UMaterialFunctionMaterialLayer that the + * boiler-plate material generation will use. When pressing + * "Generate Material", nodes will be added to this material to enable access + * to the requested metadata. If this is left blank, a new material layer + * will be created in the /Game/ folder. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + UMaterialFunctionMaterialLayer* TargetMaterialLayer = nullptr; +#endif + + // Using the FCesiumPrimitiveFeaturesDescription and + // FCesiumModelMetadataDescription structs makes the UI less readable, so the + // component uses arrays directly to help flatten the UI. + + /** + * Description of the feature ID sets in the visible glTF primitives across + * the tileset. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium|Primitive Features", + Meta = (TitleProperty = "Name")) + TArray FeatureIdSets; + + /** + * Names of the property textures used by the glTF primitives across the + * tileset. + * + * This should be a subset of the property textures listed in the model + * metadata. Property textures can be passed to the material even if they are + * not explicitly used by a glTF primitive, but the primitive may lack the + * corresponding sets of texture coordinates intended to sample them. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium|Primitive Metadata", + Meta = (TitleProperty = "Name")) + TSet PropertyTextureNames; + + /** + * Descriptions of the property tables in the visible glTF + * models across the tileset. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium|Model Metadata", + Meta = (TitleProperty = "Name")) + TArray PropertyTables; + + /** + * Descriptions of property textures in the visible glTF models across + * the tileset. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium|Model Metadata", + Meta = (TitleProperty = "Name")) + TArray PropertyTextures; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFlyToComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFlyToComponent.h new file mode 100644 index 0000000..82c274a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFlyToComponent.h @@ -0,0 +1,221 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGeospatial/SimplePlanarEllipsoidCurve.h" +#include "CesiumGlobeAnchoredActorComponent.h" +#include "CesiumFlyToComponent.generated.h" + +class UCurveFloat; +class UCesiumGlobeAnchorComponent; + +/** + * The delegate for when the Actor finishes flying. + */ +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FCesiumFlightCompleted); + +/** + * The delegate for when the Actor's flight is interrupted. + */ +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FCesiumFlightInterrupted); + +/** + * Indicates which rotation to use for orienting the object during flights. + */ +UENUM(BlueprintType) +enum class ECesiumFlyToRotation : uint8 { + /** + * Uses the relative rotation of the root component of the Actor to which the + * CesiumFlyToComponent is attached. + */ + Actor, + + /** + * Uses the ControlRotation of the Controller of the Pawn to which the + * CesiumFlyToComponent is attached. The ControlRotation is interpreted as + * being relative to the Unreal coordinate system. + * + * If the component is attached to an Actor that is not a Pawn, or if the Pawn + * does not have a Controller, this option is equivalent to the "Actor" + * option. + */ + ControlRotationInUnreal, + + /** + * Uses the ControlRotation of the Controller of the Pawn to which the + * CesiumFlyToComponent is attached. The ControlRotation is interpreted as + * being relative to the Pawn's local East-South-Up coordinate system. + * + * This is the option to use with a GlobeAwareDefaultPawn or a DynamicPawn, + * because those classes interpret the ControlRotation as being relative to + * East-South-Up. + * + * If the component is attached to an Actor that is not a Pawn, or if the Pawn + * does not have a Controller, this option is equivalent to the "Actor" + * option. + */ + ControlRotationInEastSouthUp +}; + +/** + * Smoothly animates the Actor to which it is attached on a flight to a new + * location on the globe. + */ +UCLASS(ClassGroup = "Cesium", Meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumFlyToComponent + : public UCesiumGlobeAnchoredActorComponent { + GENERATED_BODY() + +public: + UCesiumFlyToComponent(); + + /** + * A curve that is used to determine the flight progress percentage for all + * the other curves. The input is the fraction (0.0 to 1.0) of the total time + * that has passed so far, and the output is the fraction of the total curve + * that should be traversed at this time. This curve allows the Actor to + * accelerate and deaccelerate as desired throughout the flight. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + UCurveFloat* ProgressCurve; + + /** + * A curve that controls what percentage of the maximum height the Actor + * should take at a given time on the flight. This curve must be kept in the 0 + * to 1 range on both axes. The MaximumHeightByDistanceCurve controls the + * actual maximum height that is achieved during the flight. + * + * If this curve is not specified, the height will be a smooth interpolation + * between the height at the original location and the height at the + * destination location, and the MaximumHeightByDistanceCurve will be ignored. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + UCurveFloat* HeightPercentageCurve; + + /** + * A curve that controls the maximum height that will be achieved during the + * flight as a function of the straight-line distance of the flight, in + * meters. If the start and end point are on opposite sides of the globe, the + * straight-line distance goes through the Earth even though the flight itself + * will not. + * + * If HeightPercentageCurve is not specified, this property is ignored. + * If HeightPercentageCurve is specified, but this property is not, then the + * maximum height is 30,000 meters regardless of distance. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + UCurveFloat* MaximumHeightByDistanceCurve; + + /** + * The length in seconds that the flight should last. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (ClampMin = 0.0)) + float Duration = 5.0f; + + /** + * Indicates which rotation to use during flights. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + ECesiumFlyToRotation RotationToUse = ECesiumFlyToRotation::Actor; + + /** + * A delegate that will be called when the Actor finishes flying. + * + */ + UPROPERTY(BlueprintAssignable, Category = "Cesium"); + FCesiumFlightCompleted OnFlightComplete; + + /** + * A delegate that will be called when the Actor's flight is interrupted. + * + */ + UPROPERTY(BlueprintAssignable, Category = "Cesium"); + FCesiumFlightInterrupted OnFlightInterrupted; + + /** + * Begin a smooth flight to the given Earth-Centered, Earth-Fixed + * (ECEF) destination, such that the Actor ends at the specified yaw and + * pitch. The yaw and pitch are expressed relative to an East-South-Up frame + * at the destination. The characteristics of the flight can be configured + * with the properties on this component. + * + * If CanInterruptByMoving is true and the Actor moves independent of this + * component, then the flight in progress will be canceled. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void FlyToLocationEarthCenteredEarthFixed( + const FVector& EarthCenteredEarthFixedDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving); + + /** + * Begin a smooth camera flight to the given WGS84 longitude in degrees (x), + * latitude in degrees (y), and height in meters (z) such that the camera + * ends at the given yaw and pitch. The yaw and pitch are expressed relative + * to an East-South-Up frame at the destination. The characteristics of the + * flight can be configured with the properties on this component. + * + * Note that the height is measured in meters above the WGS84 ellipsoid, and + * should not be confused with a height relative to mean sea level, which may + * be tens of meters different depending on where you are on the globe. + * + * If CanInterruptByMoving is true and the Actor moves independent of this + * component, then the flight in progress will be canceled. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void FlyToLocationLongitudeLatitudeHeight( + const FVector& LongitudeLatitudeHeightDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving); + + /** + * Begin a smooth flight to the given destination in Unreal coordinates, such + * that the Actor ends at the specified yaw and pitch. The yaw and pitch are + * expressed relative to an East-South-Up frame at the destination. The + * characteristics of the flight can be configured with the properties on this + * component. + * + * If CanInterruptByMoving is true and the Actor moves independent of this + * component, then the flight in progress will be canceled. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void FlyToLocationUnreal( + const FVector& UnrealDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving); + + /** + * Interrupts the flight that is currently in progress, leaving the Actor + * wherever it is currently. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void InterruptFlight(); + +protected: + virtual void TickComponent( + float DeltaTime, + ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) override; + +private: + FQuat GetCurrentRotationEastSouthUp(); + void SetCurrentRotationEastSouthUp(const FQuat& EastSouthUpRotation); + + bool _flightInProgress = false; + bool _canInterruptByMoving; + float _currentFlyTime; + double _maxHeight; + FVector _destinationEcef; + FQuat _sourceRotation; + FQuat _destinationRotation; + FVector _previousPositionEcef; + TUniquePtr _currentCurve; + double _length; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGeoreference.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGeoreference.h new file mode 100644 index 0000000..53219a9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGeoreference.h @@ -0,0 +1,868 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumEllipsoid.h" +#include "CesiumGeospatial/LocalHorizontalCoordinateSystem.h" +#include "CesiumSubLevel.h" +#include "Delegates/Delegate.h" +#include "GameFramework/Actor.h" +#include "GeoTransforms.h" +#include "OriginPlacement.h" +#include "CesiumGeoreference.generated.h" + +class APlayerCameraManager; +class FLevelCollectionModel; +class UCesiumSubLevelSwitcherComponent; + +/** + * The delegate for the ACesiumGeoreference::OnGeoreferenceUpdated, + * which is triggered from UpdateGeoreference + */ +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGeoreferenceUpdated); + +/** + * The event that triggers when a georeference's ellipsoid is changed. + * This should be used for performing any necessary coordinate changes. + * The parameters are (OldEllipsoid, NewEllipsoid). + */ +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FGeoreferenceEllipsoidChanged, + UCesiumEllipsoid*, + OldEllipsoid, + UCesiumEllipsoid*, + NewEllipsoid); + +/** + * Controls how global geospatial coordinates are mapped to coordinates in the + * Unreal Engine level. Internally, Cesium uses a global Earth-centered, + * Earth-fixed (ECEF) ellipsoid-centered coordinate system, where the ellipsoid + * is usually the World Geodetic System 1984 (WGS84) ellipsoid. This is a + * right-handed system centered at the Earth's center of mass, where +X is in + * the direction of the intersection of the Equator and the Prime Meridian (zero + * degrees longitude), +Y is in the direction of the intersection of the Equator + * and +90 degrees longitude, and +Z is through the North Pole. This Actor is + * used by other Cesium Actors and components to control how this coordinate + * system is mapped into an Unreal Engine world and level. + */ +UCLASS() +class CESIUMRUNTIME_API ACesiumGeoreference : public AActor { + GENERATED_BODY() +public: + /** + * The minimum allowed value for the Scale property, 1e-6. + */ + static const double kMinimumScale; + + /** + * Finds and returns a CesiumGeoreference in the world. It searches in the + * following order: + * + * 1. A CesiumGeoreference that is tagged with "DEFAULT_GEOREFERENCE" and + * found in the PersistentLevel. + * 2. A CesiumGeoreference with the name "CesiumGeoreferenceDefault" and found + * in the PersistentLevel. + * 3. Any CesiumGeoreference in the PersistentLevel. + * + * If no CesiumGeoreference is found with this search, a new one is created in + * the persistent level and given the "DEFAULT_GEOREFERENCE" tag. + */ + UFUNCTION( + BlueprintCallable, + Category = "Cesium", + meta = (WorldContext = "WorldContextObject")) + static ACesiumGeoreference* + GetDefaultGeoreference(const UObject* WorldContextObject); + + /** + * Finds and returns the CesiumGeoreference suitable for use with the given + * Actor. It searches in the following order: + * + * 1. A CesiumGeoreference that is an attachment parent of the given Actor. + * 2. A CesiumGeoreference that is tagged with "DEFAULT_GEOREFERENCE" and + * found in the PersistentLevel. + * 3. A CesiumGeoreference with the name "CesiumGeoreferenceDefault" and found + * in the PersistentLevel. + * 4. Any CesiumGeoreference in the PersistentLevel. + * + * If no CesiumGeoreference is found with this search, a new one is created in + * the persistent level and given the "DEFAULT_GEOREFERENCE" tag. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + static ACesiumGeoreference* GetDefaultGeoreferenceForActor(AActor* Actor); + + /** + * A delegate that will be called whenever the Georeference is + * modified in a way that affects its computations. + */ + UPROPERTY(BlueprintAssignable, Category = "Cesium") + FGeoreferenceUpdated OnGeoreferenceUpdated; + + /** + * An event that will be called whenever the georeference's ellipsoid has + * been modified. + */ + UPROPERTY(BlueprintAssignable, Category = "Cesium") + FGeoreferenceEllipsoidChanged OnEllipsoidChanged; + +#pragma region Properties + +private: + /** + * The Ellipsoid being used by this georeference. The ellipsoid informs how + * cartographic coordinates will be interpreted and how they are transformed + * into cartesian coordinates. + */ + UPROPERTY( + Category = "Cesium", + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetEllipsoid, + BlueprintSetter = SetEllipsoid, + meta = (AllowPrivateAccess)) + UCesiumEllipsoid* Ellipsoid; + + /** + * The placement of this Actor's origin (coordinate 0,0,0) within the tileset. + * + * 3D Tiles tilesets often use Earth-centered, Earth-fixed coordinates, such + * that the tileset content is in a small bounding volume 6-7 million meters + * (the radius of the Earth) away from the coordinate system origin. This + * property allows an alternative position, other then the tileset's true + * origin, to be treated as the origin for the purpose of this Actor. Using + * this property will preserve vertex precision (and thus avoid jittering) + * much better than setting the Actor's Transform property. + */ + UPROPERTY( + Category = "Cesium", + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetOriginPlacement, + BlueprintSetter = SetOriginPlacement, + meta = (AllowPrivateAccess)) + EOriginPlacement OriginPlacement = EOriginPlacement::CartographicOrigin; + + /** + * The latitude of the custom origin placement in degrees, in the range [-90, + * 90] + */ + UPROPERTY( + Category = "Cesium", + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetOriginLatitude, + BlueprintSetter = SetOriginLatitude, + Interp, + meta = + (AllowPrivateAccess, + EditCondition = + "OriginPlacement==EOriginPlacement::CartographicOrigin", + ClampMin = -90.0, + ClampMax = 90.0)) + double OriginLatitude = 39.736401; + + /** + * The longitude of the custom origin placement in degrees, in the range + * [-180, 180] + */ + UPROPERTY( + Category = "Cesium", + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetOriginLongitude, + BlueprintSetter = SetOriginLongitude, + Interp, + meta = + (AllowPrivateAccess, + EditCondition = + "OriginPlacement==EOriginPlacement::CartographicOrigin", + ClampMin = -180.0, + ClampMax = 180.0)) + double OriginLongitude = -105.25737; + + /** + * The height of the custom origin placement in meters above the + * ellipsoid. + */ + UPROPERTY( + Category = "Cesium", + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetOriginHeight, + BlueprintSetter = SetOriginHeight, + Interp, + meta = + (AllowPrivateAccess, + EditCondition = + "OriginPlacement==EOriginPlacement::CartographicOrigin")) + double OriginHeight = 2250.0; + + /** + * The percentage scale of the globe in the Unreal world. If this value is 50, + * for example, one meter on the globe occupies half a meter in the Unreal + * world. + */ + UPROPERTY( + Category = "Cesium", + EditAnywhere, + BlueprintReadWrite, + BlueprintSetter = SetScale, + BlueprintGetter = GetScale, + Interp, + Meta = (AllowPrivateAccess, UIMin = 0.000001, UIMax = 100.0)) + double Scale = 100.0; + + /** + * The camera to use to determine which sub-level is closest, so that one can + * be activated and all others deactivated. + * @deprecated Add a CesiumOriginShiftComponent to the appropriate Actor + * instead. + */ + UPROPERTY( + meta = + (DeprecatedProperty, + DeprecationMessage = + "Add a CesiumOriginShiftComponent to the appropriate Actor instead.")) + APlayerCameraManager* SubLevelCamera_DEPRECATED = nullptr; + + /** + * The component that allows switching between the sub-levels registered with + * this georeference. + */ + UPROPERTY( + Instanced, + Category = "Cesium|Sub-levels", + BlueprintReadOnly, + BlueprintGetter = GetSubLevelSwitcher, + meta = (AllowPrivateAccess)) + UCesiumSubLevelSwitcherComponent* SubLevelSwitcher; + +#if WITH_EDITORONLY_DATA + /** + * Whether to visualize the level loading radii in the editor. Helpful for + * initially positioning the level and choosing a load radius. + */ + UPROPERTY( + Category = "Cesium|Sub-levels", + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetShowLoadRadii, + BlueprintSetter = SetShowLoadRadii, + meta = (AllowPrivateAccess)) + bool ShowLoadRadii = true; +#endif + +#pragma endregion + +#pragma region PropertyAccessors + +public: + /** + * Returns the georeference origin position as an FVector where `X` is + * longitude (degrees), `Y` is latitude (degrees), and `Z` is height above the + * ellipsoid (meters). Only valid if the placement type is Cartographic Origin + * (i.e. Longitude / Latitude / Height). + */ + UFUNCTION(BlueprintPure, Category = "Cesium") + FVector GetOriginLongitudeLatitudeHeight() const; + + /** + * This aligns the specified longitude in degrees (X), latitude in + * degrees (Y), and height above the ellipsoid in meters (Z) to the Unreal + * origin. That is, it moves the globe so that these coordinates exactly fall + * on the origin. Only valid if the placement type is Cartographic Origin + * (i.e. Longitude / Latitude / Height). + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetOriginLongitudeLatitudeHeight( + const FVector& TargetLongitudeLatitudeHeight); + + /** + * Returns the georeference origin position as an FVector in Earth-Centerd, + * Earth-Fixed (ECEF) coordinates. Only valid if the placement type is + * Cartographic Origin (i.e. Longitude / Latitude / Height). + */ + UFUNCTION(BlueprintPure, Category = "Cesium") + FVector GetOriginEarthCenteredEarthFixed() const; + + /** + * This aligns the specified Earth-Centered, Earth-Fixed (ECEF) coordinates to + * the Unreal origin. That is, it moves the globe so that these coordinates + * exactly fall on the origin. Only valid if the placement type is + * Cartographic Origin (i.e. Longitude / Latitude / Height). Note that if the + * provided ECEF coordiantes are near the center of the Earth so that + * Longitude, Latitude, and Height are undefined, this function will instead + * place the origin at 0 degrees longitude, 0 degrees latitude, and 0 meters + * height about the ellipsoid. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetOriginEarthCenteredEarthFixed( + const FVector& TargetEarthCenteredEarthFixed); + + /** + * Gets the placement of this Actor's origin (coordinate 0,0,0) within the + * tileset. + * + * 3D Tiles tilesets often use Earth-centered, Earth-fixed coordinates, such + * that the tileset content is in a small bounding volume 6-7 million meters + * (the radius of the Earth) away from the coordinate system origin. This + * property allows an alternative position, other then the tileset's true + * origin, to be treated as the origin for the purpose of this Actor. Using + * this property will preserve vertex precision (and thus avoid jittering) + * much better than setting the Actor's Transform property. + */ + UFUNCTION(BlueprintGetter) + EOriginPlacement GetOriginPlacement() const; + + /** + * Sets the placement of this Actor's origin (coordinate 0,0,0) within the + * tileset. + * + * 3D Tiles tilesets often use Earth-centered, Earth-fixed coordinates, such + * that the tileset content is in a small bounding volume 6-7 million meters + * (the radius of the Earth) away from the coordinate system origin. This + * property allows an alternative position, other then the tileset's true + * origin, to be treated as the origin for the purpose of this Actor. Using + * this property will preserve vertex precision (and thus avoid jittering) + * much better than setting the Actor's Transform property. + */ + UFUNCTION(BlueprintSetter) + void SetOriginPlacement(EOriginPlacement NewValue); + + /** + * Gets the latitude of the custom origin placement in degrees, in the range + * [-90, 90] + */ + UFUNCTION(BlueprintGetter) + double GetOriginLatitude() const; + + /** + * Sets the latitude of the custom origin placement in degrees, in the range + * [-90, 90] + */ + UFUNCTION(BlueprintSetter) + void SetOriginLatitude(double NewValue); + + /** + * Gets the longitude of the custom origin placement in degrees, in the range + * [-180, 180] + */ + UFUNCTION(BlueprintGetter) + double GetOriginLongitude() const; + + /** + * Sets the longitude of the custom origin placement in degrees, in the range + * [-180, 180] + */ + UFUNCTION(BlueprintSetter) + void SetOriginLongitude(double NewValue); + + /** + * Gets the height of the custom origin placement in meters above the + * ellipsoid. + */ + UFUNCTION(BlueprintGetter) + double GetOriginHeight() const; + + /** + * Sets the height of the custom origin placement in meters above the + * ellipsoid. + */ + UFUNCTION(BlueprintSetter) + void SetOriginHeight(double NewValue); + + /** + * Gets the percentage scale of the globe in the Unreal world. If this value + * is 50, for example, one meter on the globe occupies half a meter in the + * Unreal world. + */ + UFUNCTION(BlueprintGetter) + double GetScale() const; + + /** + * Sets the percentage scale of the globe in the Unreal world. If this value + * is 50, for example, one meter on the globe occupies half a meter in the + * Unreal world. + */ + UFUNCTION(BlueprintSetter) + void SetScale(double NewValue); + + /** + * Gets the camera to use to determine which sub-level is closest, so that one + * can be activated and all others deactivated. + */ + UE_DEPRECATED( + "Cesium For Unreal v2.0", + "Add a CesiumOriginShiftComponent to the appropriate Actor instead.") + UFUNCTION(BlueprintGetter) + APlayerCameraManager* GetSubLevelCamera() const; + + /** + * Sets the camera to use to determine which sub-level is closest, so that one + * can be activated and all others deactivated. + */ + UE_DEPRECATED( + "Cesium For Unreal v2.0", + "Add a CesiumOriginShiftComponent to the appropriate Actor instead.") + UFUNCTION(BlueprintSetter) + void SetSubLevelCamera(APlayerCameraManager* NewValue); + + /** + * Gets the component that allows switching between different sub-levels + * registered with this georeference. + */ + UFUNCTION(BlueprintGetter) + UCesiumSubLevelSwitcherComponent* GetSubLevelSwitcher() const { + return this->SubLevelSwitcher; + } + + /** + * Returns a pointer to the UCesiumEllipsoid currently being used by this + * georeference. + */ + UFUNCTION(BlueprintCallable, BlueprintGetter, Category = "Cesium") + UCesiumEllipsoid* GetEllipsoid() const; + + /** + * Sets the UCesiumEllipsoid used by this georeference. + * + * Calling this will cause all tilesets under this georeference to be + * reloaded. + */ + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetEllipsoid(UCesiumEllipsoid* NewEllipsoid); + +#if WITH_EDITOR + /** + * Gets whether to visualize the level loading radii in the editor. Helpful + * for initially positioning the level and choosing a load radius. + */ + UFUNCTION(BlueprintGetter) + bool GetShowLoadRadii() const; + + /** + * Sets whether to visualize the level loading radii in the editor. Helpful + * for initially positioning the level and choosing a load radius. + */ + UFUNCTION(BlueprintSetter) + void SetShowLoadRadii(bool NewValue); +#endif // WITH_EDITOR + +#pragma endregion + +#pragma region Transformation Functions + +public: + /** + * Transforms the given longitude in degrees (x), latitude in + * degrees (y), and height above the ellipsoid in meters (z) into Unreal + * coordinates. The resulting position should generally not be interpreted as + * an Unreal _world_ position, but rather a position expressed in some parent + * Actor's reference frame as defined by its transform. This way, the chain of + * Unreal transforms places and orients the "globe" in the Unreal world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "UnrealPosition")) + FVector TransformLongitudeLatitudeHeightPositionToUnreal( + const FVector& LongitudeLatitudeHeight) const; + + /** + * Transforms a position in Unreal coordinates into longitude in degrees (x), + * latitude in degrees (y), and height above the ellipsoid in meters (z). The + * position should generally not be an Unreal _world_ position, but rather a + * position expressed in some parent Actor's reference frame as defined by its + * transform. This way, the chain of Unreal transforms places and orients the + * "globe" in the Unreal world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "LongitudeLatitudeHeight")) + FVector TransformUnrealPositionToLongitudeLatitudeHeight( + const FVector& UnrealPosition) const; + + /** + * Transforms a position in Earth-Centered, Earth-Fixed (ECEF) coordinates + * into Unreal coordinates. The resulting position should generally not be + * interpreted as an Unreal _world_ position, but rather a position expressed + * in some parent Actor's reference frame as defined by its transform. This + * way, the chain of Unreal transforms places and orients the "globe" in the + * Unreal world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "UnrealPosition")) + FVector TransformEarthCenteredEarthFixedPositionToUnreal( + const FVector& EarthCenteredEarthFixedPosition) const; + + /** + * Transforms the given position from Unreal coordinates to Earth-Centered, + * Earth-Fixed (ECEF). The position should generally not be an Unreal _world_ + * position, but rather a position expressed in some parent Actor's reference + * frame as defined by its transform. This way, the chain of Unreal transforms + * places and orients the "globe" in the Unreal world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "EarthCenteredEarthFixedPosition")) + FVector TransformUnrealPositionToEarthCenteredEarthFixed( + const FVector& UnrealPosition) const; + + /** + * Transforms a direction vector in Earth-Centered, Earth-Fixed (ECEF) + * coordinates into Unreal coordinates. The resulting direction vector should + * generally not be interpreted as an Unreal _world_ vector, but rather a + * vector expressed in some parent Actor's reference frame as defined by its + * transform. This way, the chain of Unreal transforms places and orients the + * "globe" in the Unreal world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "UnrealDirection")) + FVector TransformEarthCenteredEarthFixedDirectionToUnreal( + const FVector& EarthCenteredEarthFixedDirection) const; + + /** + * Transforms the given direction vector from Unreal coordinates to + * Earth-Centered, Earth-Fixed (ECEF) coordinates. The direction vector should + * generally not be an Unreal _world_ vector, but rather a vector expressed in + * some parent Actor's reference frame as defined by its transform. This way, + * the chain of Unreal transforms places and orients the "globe" in the Unreal + * world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "EarthCenteredEarthFixedPosition")) + FVector TransformUnrealDirectionToEarthCenteredEarthFixed( + const FVector& UnrealDirection) const; + + /** + * Given a Rotator that transforms an object into the Unreal coordinate + * system, returns a new Rotator that transforms that object into an + * East-South-Up frame centered at a given location. + * + * In an East-South-Up frame, +X points East, +Y points South, and +Z points + * Up. However, the directions of "East", "South", and "Up" in Unreal or ECEF + * coordinates vary depending on where on the globe we are talking about. + * That is why this function takes a location, expressed in Unreal + * coordinates, that defines the origin of the East-South-Up frame of + * interest. + * + * The Unreal location and the resulting Rotator should generally not be + * relative to the Unreal _world_, but rather be expressed in some parent + * Actor's reference frame as defined by its Transform. This way, the chain of + * Unreal transforms places and orients the "globe" in the Unreal world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "EastSouthUpRotator")) + FRotator TransformUnrealRotatorToEastSouthUp( + const FRotator& UnrealRotator, + const FVector& UnrealLocation) const; + + /** + * Given a Rotator that transforms an object into the East-South-Up frame + * centered at a given location, returns a new Rotator that transforms that + * object into Unreal coordinates. + * + * In an East-South-Up frame, +X points East, +Y points South, and +Z points + * Up. However, the directions of "East", "South", and "Up" in Unreal or ECEF + * coordinates vary depending on where on the globe we are talking about. + * That is why this function takes a location, expressed in Unreal + * coordinates, that defines the origin of the East-South-Up frame of + * interest. + * + * The Unreal location and the resulting Rotator should generally not be + * relative to the Unreal _world_, but rather be expressed in some parent + * Actor's reference frame as defined by its Transform. This way, the chain of + * Unreal transforms places and orients the "globe" in the Unreal world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "UnrealRotator")) + FRotator TransformEastSouthUpRotatorToUnreal( + const FRotator& EastSouthUpRotator, + const FVector& UnrealLocation) const; + + /** + * Computes the transformation matrix from the Unreal coordinate system to the + * Earth-Centered, Earth-Fixed (ECEF) coordinate system. The Unreal + * coordinates should generally not be interpreted as Unreal _world_ + * coordinates, but rather a coordinate system based on some parent Actor's + * reference frame as defined by its transform. This way, the chain of Unreal + * transforms places and orients the "globe" in the Unreal world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "UnrealToEarthCenteredEarthFixedMatrix")) + FMatrix ComputeUnrealToEarthCenteredEarthFixedTransformation() const; + + /** + * Computes the transformation matrix from the Earth-Centered, Earth-Fixed + * (ECEF) coordinate system to the Unreal coordinate system. The Unreal + * coordinates should generally not be interpreted as Unreal _world_ + * coordinates, but rather a coordinate system based on some parent Actor's + * reference frame as defined by its transform. This way, the chain of Unreal + * transforms places and orients the "globe" in the Unreal world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "EarthCenteredEarthFixedToUnrealMatrix")) + FMatrix ComputeEarthCenteredEarthFixedToUnrealTransformation() const; + + /** + * Computes the matrix that transforms from an East-South-Up frame centered at + * a given location to the Unreal frame. + * + * In an East-South-Up frame, +X points East, +Y points South, and +Z points + * Up. However, the directions of "East", "South", and "Up" in Unreal or ECEF + * coordinates vary depending on where on the globe we are talking about. + * That is why this function takes a location, expressed in Unreal + * coordinates, that defines the origin of the East-South-Up frame of + * interest. + * + * The Unreal location and the resulting matrix should generally not be + * relative to the Unreal _world_, but rather be expressed in some parent + * Actor's reference frame as defined by its Transform. This way, the chain of + * Unreal transforms places and orients the "globe" in the Unreal world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "EastSouthUpToUnrealMatrix")) + FMatrix + ComputeEastSouthUpToUnrealTransformation(const FVector& UnrealLocation) const; + + /** + * Computes the matrix that transforms from an East-South-Up frame centered at + * a given location to the Unreal frame. The location is expressed as an + * Earth-Centered, Earth-Fixed (ECEF) position. To use an Unreal position + * instead, use ComputeUnrealToEastSouthUpTransformation. + * + * In an East-South-Up frame, +X points East, +Y points South, and +Z points + * Up. However, the directions of "East", "South", and "Up" in Unreal or ECEF + * coordinates vary depending on where on the globe we are talking about. + * That is why this function takes a location, expressed in ECEF + * coordinates, that defines the origin of the East-South-Up frame of + * interest. + * + * The resulting matrix should generally not be relative to the Unreal + * _world_, but rather be expressed in some parent Actor's reference frame as + * defined by its Transform. This way, the chain of Unreal transforms places + * and orients the "globe" in the Unreal world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "EastSouthUpToUnrealMatrix")) + FMatrix + ComputeEastSouthUpAtEarthCenteredEarthFixedPositionToUnrealTransformation( + const FVector& EarthCenteredEarthFixedPosition) const; + + /** + * Computes the matrix that transforms from the Unreal frame to an + * East-South-Up frame centered at a given location. The location is expressed + * in Unreal coordinates. To use an Earth-Centered, Earth-Fixed position + * instead, use + * ComputeEastSouthUpAtEarthCenteredEarthFixedPositionToUnrealTransformation. + * + * In an East-South-Up frame, +X points East, +Y points South, and +Z points + * Up. However, the directions of "East", "South", and "Up" in Unreal or ECEF + * coordinates vary depending on where on the globe we are talking about. + * That is why this function takes a location, expressed in Unreal + * coordinates, that defines the origin of the East-South-Up frame of + * interest. + * + * The Unreal location and the resulting matrix should generally not be + * relative to the Unreal _world_, but rather be expressed in some parent + * Actor's reference frame as defined by its Transform. This way, the chain of + * Unreal transforms places and orients the "globe" in the Unreal world. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "UnrealToEastSouthUpMatrix")) + FMatrix + ComputeUnrealToEastSouthUpTransformation(const FVector& UnrealLocation) const; + +#pragma endregion + +#pragma region Editor Support + +#if WITH_EDITOR +public: + /** + * Places the georeference origin at the camera's current location. Rotates + * the globe so the current longitude/latitude/height of the camera is at the + * Unreal origin. The camera is also teleported to the new Unreal origin and + * rotated so that the view direction is maintained. + * + * Warning: Before clicking, ensure that all non-Cesium objects in the + * persistent level are georeferenced with the "CesiumGlobeAnchorComponent" + * or attached to an actor with that component. Ensure that static actors only + * exist in georeferenced sub-levels. + */ + UFUNCTION(Category = "Cesium") + void PlaceGeoreferenceOriginHere(); + + /** + * Creates a new Level Instance Actor at the current viewport location, and + * attaches the Cesium Sub Level Component to it. You will be prompted for + * where to store the new level. + * + * Warning: Before clicking, ensure that all non-Cesium objects in the + * persistent level are georeferenced with the "CesiumGlobeAnchorComponent" + * or attached to an actor with that component. Ensure that static actors only + * exist in georeferenced sub-levels. + */ + UFUNCTION(Category = "Cesium") + void CreateSubLevelHere(); +#endif + +private: + // This property mirrors RootComponent, and exists only so that the root + // component's transform is editable in the Editor. + UPROPERTY(VisibleAnywhere, Category = "Cesium") + USceneComponent* Root; + +#if WITH_EDITOR + /** + * @brief Show the load radius of each sub-level as a sphere. + * + * If this is not called "in-game", and `ShowLoadRadii` is `true`, + * then it will show a sphere indicating the load radius of each + * sub-level. + */ + void _showSubLevelLoadRadii() const; +#endif + +#pragma endregion + +#pragma region Unreal Lifecycle + +protected: + virtual bool ShouldTickIfViewportsOnly() const override; + virtual void Tick(float DeltaTime) override; + virtual void Serialize(FArchive& Ar) override; + virtual void BeginPlay() override; + virtual void OnConstruction(const FTransform& Transform) override; + virtual void PostLoad() override; + +#if WITH_EDITOR + virtual void + PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; +#endif + +#pragma endregion + +#pragma region Obsolete + +public: + UE_DEPRECATED( + "Cesium For Unreal v2.0", + "Use transformation functions on ACesiumGeoreference and UCesiumEllipsoid instead.") + GeoTransforms GetGeoTransforms() const noexcept; + +private: + PRAGMA_DISABLE_DEPRECATION_WARNINGS + UPROPERTY( + Meta = + (DeprecatedProperty, + DeprecationMessage = + "Create sub-levels by adding a UCesiumSubLevelComponent to an ALevelInstance Actor.")) + TArray CesiumSubLevels_DEPRECATED; + PRAGMA_ENABLE_DEPRECATION_WARNINGS + +#if WITH_EDITOR + void _createSubLevelsFromWorldComposition(); +#endif + + /** + * Transforms the given longitude in degrees (x), latitude in + * degrees (y), and height above the ellipsoid in meters (z) into + * Earth-Centered, Earth-Fixed (ECEF) coordinates. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = + (DeprecatedFunction, + DeprecationMessage = + "Use LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed on UCesiumEllipsoid instead.")) + FVector TransformLongitudeLatitudeHeightToEcef( + const FVector& LongitudeLatitudeHeight) const; + + /** + * Transforms the given Earth-Centered, Earth-Fixed (ECEF) coordinates into + * Ellipsoid longitude in degrees (x), latitude in degrees (y), and height + * above the ellipsoid in meters (z). + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = + (DeprecatedFunction, + DeprecationMessage = + "Use EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight on UCesiumEllipsoid instead.")) + FVector TransformEcefToLongitudeLatitudeHeight(const FVector& Ecef) const; + + /** + * Computes the rotation matrix from the local East-North-Up to + * Earth-Centered, Earth-Fixed (ECEF) at the specified ECEF location. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = + (DeprecatedFunction, + DeprecationMessage = + "Use EastNorthUpToEllipsoidCenteredEllipsoidFixed on UCesiumEllipsoid instead.")) + FMatrix ComputeEastNorthUpToEcef(const FVector& Ecef) const; + +#pragma endregion + +private: +#pragma region Implementation Details + +public: + ACesiumGeoreference(); + + const CesiumGeospatial::LocalHorizontalCoordinateSystem& + GetCoordinateSystem() const noexcept { + return this->_coordinateSystem; + } + +private: + /** + * Recomputes all world georeference transforms. + */ + void UpdateGeoreference(); + + /** + * A tag that is assigned to Georeferences when they are created + * as the "default" Georeference for a certain world. + */ + static FName DEFAULT_GEOREFERENCE_TAG; + + CesiumGeospatial::LocalHorizontalCoordinateSystem _coordinateSystem{ + glm::dmat4(1.0)}; + + /** + * Updates _geoTransforms based on the current ellipsoid and center, and + * returns the old transforms. + */ + void _updateCoordinateSystem(); + + friend class FCesiumGeoreferenceCustomization; +#pragma endregion +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGlobeAnchorComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGlobeAnchorComponent.h new file mode 100644 index 0000000..7643eb6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGlobeAnchorComponent.h @@ -0,0 +1,601 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGeospatial/GlobeAnchor.h" +#include "Components/ActorComponent.h" +#include "Delegates/IDelegateInstance.h" +#include "CesiumGlobeAnchorComponent.generated.h" + +class ACesiumGeoreference; + +/** + * This component can be added to a movable actor to anchor it to the globe + * and maintain precise placement. When the owning actor is transformed through + * normal Unreal Engine mechanisms, the internal geospatial coordinates will be + * automatically updated. The actor position can also be set in terms of + * Earth-Centered, Earth-Fixed coordinates (ECEF) or Longitude, Latitude, and + * Height relative to the ellipsoid. + */ +UCLASS(ClassGroup = Cesium, Meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumGlobeAnchorComponent : public UActorComponent { + GENERATED_BODY() + +#pragma region Properties +private: + /** + * The designated georeference actor controlling how the owning actor's + * coordinate system relates to the coordinate system in this Unreal Engine + * level. + * + * If this is null, the Component will find and use the first Georeference + * Actor in the level, or create one if necessary. To get the active/effective + * Georeference from Blueprints or C++, use ResolvedGeoreference instead. + * + * If setting this property changes the CesiumGeoreference, the globe position + * will be maintained and the Actor's transform will be updated according to + * the new CesiumGeoreference. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetGeoreference, + BlueprintSetter = SetGeoreference, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + TSoftObjectPtr Georeference = nullptr; + + /** + * The resolved georeference used by this component. This is not serialized + * because it may point to a Georeference in the PersistentLevel while this + * component is in a sub-level. If the Georeference property is specified, + * however then this property will have the same value. + * + * This property will be null before ResolveGeoreference is called, which + * happens automatically when the component is registered. + */ + UPROPERTY( + Transient, + VisibleAnywhere, + BlueprintReadOnly, + BlueprintGetter = GetResolvedGeoreference, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + ACesiumGeoreference* ResolvedGeoreference = nullptr; + + /** + * Whether to adjust the Actor's orientation based on globe curvature as the + * Actor moves. + * + * The Earth is not flat, so as we move across its surface, the direction of + * "up" changes. If we ignore this fact and leave an object's orientation + * unchanged as it moves over the globe surface, the object will become + * increasingly tilted and eventually be completely upside-down when we arrive + * at the opposite side of the globe. + * + * When this setting is enabled, this Component will automatically apply a + * rotation to the Actor to account for globe curvature any time the Actor's + * position on the globe changes. + * + * This property should usually be enabled, but it may be useful to disable it + * when your application already accounts for globe curvature itself when it + * updates an Actor's position and orientation, because in that case the Actor + * would be over-rotated. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetAdjustOrientationForGlobeWhenMoving, + BlueprintSetter = SetAdjustOrientationForGlobeWhenMoving, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + bool AdjustOrientationForGlobeWhenMoving = true; + + /** + * Using the teleport flag will move objects to the updated transform + * immediately and without affecting their velocity. This is useful when + * working with physics actors that maintain an internal velocity which we do + * not want to change when updating location. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetTeleportWhenUpdatingTransform, + BlueprintSetter = SetTeleportWhenUpdatingTransform, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + bool TeleportWhenUpdatingTransform = true; + + /** + * The 4x4 transformation matrix from the Actors's local coordinate system to + * the Earth-Centered, Earth-Fixed (ECEF) coordinate system. + * + * The ECEF coordinate system is a right-handed system located at the center + * of the Earth. The +X axis points to the intersection of the Equator and + * Prime Meridian (zero degrees longitude). The +Y axis points to the + * intersection of the Equator and +90 degrees longitude. The +Z axis points + * up through the North Pole. + * + * If `AdjustOrientationForGlobeWhenMoving` is enabled and this property is + * set, the Actor's orientation will also be adjusted to account for globe + * curvature. + */ + UPROPERTY( + BlueprintReadWrite, + BlueprintGetter = GetActorToEarthCenteredEarthFixedMatrix, + BlueprintSetter = SetActorToEarthCenteredEarthFixedMatrix, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + FMatrix ActorToEarthCenteredEarthFixedMatrix; + +#pragma endregion + +#pragma region Property Accessors +public: + /** + * Gets the designated georeference actor controlling how the owning actor's + * coordinate system relates to the coordinate system in this Unreal Engine + * level. + * + * If this is null, the Component will find and use the first Georeference + * Actor in the level, or create one if necessary. To get the active/effective + * Georeference from Blueprints or C++, use ResolvedGeoreference instead. + */ + UFUNCTION(BlueprintGetter) + TSoftObjectPtr GetGeoreference() const; + + /** + * Sets the designated georeference actor controlling how the owning actor's + * coordinate system relates to the coordinate system in this Unreal Engine + * level. + * + * If this is null, the Component will find and use the first Georeference + * Actor in the level, or create one if necessary. To get the active/effective + * Georeference from Blueprints or C++, use ResolvedGeoreference instead. + */ + UFUNCTION(BlueprintSetter) + void SetGeoreference(TSoftObjectPtr NewGeoreference); + + /** + * Gets the resolved georeference used by this component. This is not + * serialized because it may point to a Georeference in the PersistentLevel + * while this component is in a sub-level. If the Georeference property is + * manually specified, however, then this property will have the same value. + * + * This property will be null before ResolveGeoreference is called, which + * happens automatically when the component is registered. + */ + UFUNCTION(BlueprintGetter) + ACesiumGeoreference* GetResolvedGeoreference() const; + + /** + * Resolves the Cesium Georeference to use with this Component. Returns + * the value of the Georeference property if it is set. Otherwise, finds a + * Georeference in the World and returns it, creating it if necessary. The + * resolved Georeference is cached so subsequent calls to this function will + * return the same instance, unless ForceReresolve is true. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + ACesiumGeoreference* ResolveGeoreference(bool bForceReresolve = false); + + /** + * Obtains the {@link UCesiumEllipsoid} set on the georeference used by this + * component. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + UCesiumEllipsoid* GetEllipsoid() const; + + /** + * Gets the 4x4 transformation matrix from the Actors's local coordinate + * system to the Earth-Centered, Earth-Fixed (ECEF) coordinate system. + * + * The ECEF coordinate system is a right-handed system located at the center + * of the Earth. The +X axis points to the intersection of the Equator and + * Prime Meridian (zero degrees longitude). The +Y axis points to the + * intersection of the Equator and +90 degrees longitude. The +Z axis points + * up through the North Pole. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + FMatrix GetActorToEarthCenteredEarthFixedMatrix() const; + + /** + * Sets the 4x4 transformation matrix from the Actors's local coordinate + * system to the Earth-Centered, Earth-Fixed (ECEF) coordinate system. + * + * The ECEF coordinate system is a right-handed system located at the center + * of the Earth. The +X axis points to the intersection of the Equator and + * Prime Meridian (zero degrees longitude). The +Y axis points to the + * intersection of the Equator and +90 degrees longitude. The +Z axis points + * up through the North Pole. + * + * If `AdjustOrientationForGlobeWhenMoving` is enabled, the Actor's + * orientation will also be adjusted to account for globe curvature. + */ + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetActorToEarthCenteredEarthFixedMatrix(const FMatrix& Value); + + /** + * Gets a flag indicating whether to move objects to the updated transform + * immediately and without affecting their velocity. This is useful when + * working with physics actors that maintain an internal velocity which we do + * not want to change when updating location. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + bool GetTeleportWhenUpdatingTransform() const; + + /** + * Sets a flag indicating whether to move objects to the updated transform + * immediately and without affecting their velocity. This is useful when + * working with physics actors that maintain an internal velocity which we do + * not want to change when updating location. + */ + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetTeleportWhenUpdatingTransform(bool Value); + + /** + * Gets a flag indicating whether to adjust the Actor's orientation based on + * globe curvature as the Actor moves. + * + * The Earth is not flat, so as we move across its surface, the direction of + * "up" changes. If we ignore this fact and leave an object's orientation + * unchanged as it moves over the globe surface, the object will become + * increasingly tilted and eventually be completely upside-down when we arrive + * at the opposite side of the globe. + * + * When this setting is enabled, this Component will automatically apply a + * rotation to the Actor to account for globe curvature any time the Actor's + * position on the globe changes. + * + * This property should usually be enabled, but it may be useful to disable it + * when your application already accounts for globe curvature itself when it + * updates an Actor's position and orientation, because in that case the Actor + * would be over-rotated. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + bool GetAdjustOrientationForGlobeWhenMoving() const; + + /** + * Sets a flag indicating whether to adjust the Actor's orientation based on + * globe curvature as the Actor moves. + * + * The Earth is not flat, so as we move across its surface, the direction of + * "up" changes. If we ignore this fact and leave an object's orientation + * unchanged as it moves over the globe surface, the object will become + * increasingly tilted and eventually be completely upside-down when we arrive + * at the opposite side of the globe. + * + * When this setting is enabled, this Component will automatically apply a + * rotation to the Actor to account for globe curvature any time the Actor's + * position on the globe changes. + * + * This property should usually be enabled, but it may be useful to disable it + * when your application already accounts for globe curvature itself when it + * updates an Actor's position and orientation, because in that case the Actor + * would be over-rotated. + */ + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetAdjustOrientationForGlobeWhenMoving(bool Value); + +#pragma endregion + +#pragma region Public Methods + +public: + /** + * Gets the longitude in degrees (X), latitude in degrees (Y), + * and height in meters above the ellipsoid (Z) of the actor. + * + * Do not confuse the ellipsoid height with a geoid height or height above + * mean sea level, which can be tens of meters higher or lower depending on + * where in the world the object is located. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + Meta = (ReturnDisplayName = "LongitudeLatitudeHeight")) + FVector GetLongitudeLatitudeHeight() const; + + /** + * Gets the longitude in degrees. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + Meta = (ReturnDisplayName = "Longitude")) + double GetLongitude() const { return this->GetLongitudeLatitudeHeight().X; } + + /** + * Gets the latitude in degrees. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + Meta = (ReturnDisplayName = "Latitude")) + double GetLatitude() const { return this->GetLongitudeLatitudeHeight().Y; } + + /** + * Gets the height in meters above the ellipsoid. + * + * Do not confuse the ellipsoid height with a geoid height or height above + * mean sea level, which can be tens of meters higher or lower depending on + * where in the world the object is located. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + Meta = (ReturnDisplayName = "Height")) + double GetHeight() const { return this->GetLongitudeLatitudeHeight().Z; } + + /** + * Moves the Actor to which this component is attached to a given longitude in + * degrees (X), latitude in degrees (Y), and height in meters (Z). + * + * The Height (Z) is measured in meters above the ellipsoid. Do not + * confused an ellipsoidal height with a geoid height or height above mean sea + * level, which can be tens of meters higher or lower depending on where in + * the world the object is located. + * + * If `AdjustOrientationForGlobeWhenMoving` is enabled, the Actor's + * orientation will also be adjusted to account for globe curvature. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void MoveToLongitudeLatitudeHeight(const FVector& LongitudeLatitudeHeight); + + /** + * Gets the Earth-Centered, Earth-Fixed (ECEF) coordinates of the Actor in + * meters. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "EarthCenteredEarthFixedPosition")) + FVector GetEarthCenteredEarthFixedPosition() const; + + /** + * Moves the Actor to which this component is attached to a given globe + * position in Earth-Centered, Earth-Fixed coordinates in meters. + * + * If AdjustOrientationForGlobeWhenMoving is enabled, this method will + * also update the orientation based on the globe curvature. + * + * @param EarthCenteredEarthFixedPosition The new position. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void MoveToEarthCenteredEarthFixedPosition( + const FVector& EarthCenteredEarthFixedPosition); + + /** + * Gets the rotation of the Actor relative to a local coordinate system + * centered on this object where the +X points in the local East direction, + * the +Y axis points in the local South direction, and the +Z axis points in + * the local Up direction. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "EastSouthUpRotation")) + FQuat GetEastSouthUpRotation() const; + + /** + * Sets the rotation of the Actor relative to a local coordinate system + * centered on this object where the +X points in the local East direction, + * the +Y axis points in the local South direction, and the +Z axis points in + * the local Up direction. + * + * When the rotation is set via this method, it is internally converted to + * and stored in the ActorToEarthCenteredEarthFixedMatrix property. As a + * result, getting this property will not necessarily return the exact value + * that was set. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetEastSouthUpRotation(const FQuat& EastSouthUpRotation); + + /** + * Gets the rotation of the Actor relative to the Earth-Centered, Earth-Fixed + * (ECEF) coordinate system. + * + * The ECEF coordinate system is a right-handed system located at the center + * of the Earth. The +X axis points from there to the intersection of the + * Equator and Prime Meridian (zero degrees longitude). The +Y axis points to + * the intersection of the Equator and +90 degrees longitude. The +Z axis + * points up through the North Pole. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium", + meta = (ReturnDisplayName = "EarthCenteredEarthFixedRotation")) + FQuat GetEarthCenteredEarthFixedRotation() const; + + /** + * Sets the rotation of the Actor relative to the Earth-Centered, Earth-Fixed + * (ECEF) coordinate system. + * + * The ECEF coordinate system is a right-handed system located at the center + * of the Earth. The +X axis points from there to the intersection of the + * Equator and Prime Meridian (zero degrees longitude). The +Y axis points to + * the intersection of the Equator and +90 degrees longitude. The +Z axis + * points up through the North Pole. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetEarthCenteredEarthFixedRotation( + const FQuat& EarthCenteredEarthFixedRotation); + + /** + * Rotates the Actor so that its local +Z axis is aligned with the ellipsoid + * surface normal at its current location. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SnapLocalUpToEllipsoidNormal(); + + /** + * Rotates the Actor so that its +X axis points in the local East direction, + * its +Y axis points in the local South direction, and its +Z axis points in + * the local Up direction. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SnapToEastSouthUp(); + + /** + * Synchronizes the properties of this globe anchor. + * + * It is usually not necessary to call this method because it is called + * automatically when needed. + * + * This method performs the following actions: + * + * - If the ActorToEarthCenteredEarthFixedMatrix has not yet been + * determined, it is computed from the Actor's current root transform. + * - If the Actor's root transform has changed since the last time this + * component was registered, this method updates the + * ActorToEarthCenteredEarthFixedMatrix from the current transform. + * - If the origin of the CesiumGeoreference has changed, the Actor's root + * transform is updated based on the ActorToEarthCenteredEarthFixedMatrix and + * the new georeference origin. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void Sync(); + +#pragma endregion + +#pragma region Obsolete +public: + /** + * @brief DEPRECATED + * @deprecated The resolved georeference can no longer be explicitly + * invalidated. To change the georeference, call SetGeoreference or + * ReregisterComponent. + */ + UE_DEPRECATED( + "Cesium For Unreal v2.0", + "The resolved georeference can no longer be explicitly invalidated. To change the georeference, call SetGeoreference or ReregisterComponent.") + UFUNCTION( + BlueprintCallable, + Category = "Cesium", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "The resolved georeference can no longer be explicitly invalidated. To change the georeference, call SetGeoreference or ReregisterComponent.")) + void InvalidateResolvedGeoreference(); +#pragma endregion + +#pragma region Unreal Lifecycle +protected: + /** + * Handles reading, writing, and reference collecting using FArchive. + * This implementation handles all FProperty serialization, but can be + * overridden for native variables. + * + * This class overrides this method to ensure internal variables are + * immediately synchronized with newly-loaded values. + */ + virtual void Serialize(FArchive& Ar) override; + + /** + * Called when a component is created (not loaded). This can happen in the + * editor or during gameplay. + * + * This method is invoked after this component is pasted and just prior to + * registration. We mark the globe transform invalid here because we can't + * assume the globe transform is still valid when the component is pasted into + * another Actor, or even if the Actor was changed since the Component was + * copied. + */ + virtual void OnComponentCreated() override; + +#if WITH_EDITOR + virtual void + PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; +#endif + + /** + * Called when a component is registered. This can be viewed as "enabling" + * this Component on the Actor to which it is attached. + * + * In the Editor, this is called in a many different situations, such as on + * changes to properties. + */ + virtual void OnRegister() override; + + /** + * Called when a component is unregistered. This can be viewed as + * "disabling" this Component on the Actor to which it is attached. + * + * In the Editor, this is called in a many different situations, such as on + * changes to properties. + */ + virtual void OnUnregister() override; +#pragma endregion + +#pragma region Implementation Details +private: + CesiumGeospatial::GlobeAnchor _createNativeGlobeAnchor() const; + + USceneComponent* _getRootComponent(bool warnIfNull) const; + + FTransform _getCurrentRelativeTransform() const; + + void _setCurrentRelativeTransform(const FTransform& relativeTransform); + + CesiumGeospatial::GlobeAnchor + _createOrUpdateNativeGlobeAnchorFromRelativeTransform( + const FTransform& newRelativeTransform); + + CesiumGeospatial::GlobeAnchor + _createOrUpdateNativeGlobeAnchorFromECEF(const FMatrix& newActorToECEFMatrix); + + void _updateFromNativeGlobeAnchor( + const CesiumGeospatial::GlobeAnchor& nativeAnchor); + + void _setNewActorToECEFFromRelativeTransform(); + +#if WITH_EDITORONLY_DATA + // This is used only to preserve the transformation saved by old versions of + // Cesium for Unreal. See the Serialize method. + UPROPERTY(Meta = (DeprecatedProperty)) + double _actorToECEF_Array_DEPRECATED[16]; +#endif + + /** + * True if the globe transform is a valid and correct representation of the + * position and orientation of this Actor. False if the globe transform has + * not yet been computed and so the Actor transform is the only valid + * representation of the Actor's position and orientation. + */ + UPROPERTY() + bool _actorToECEFIsValid = false; + + /** + * Whether an update of the actor transform is currently in progress, + * and further calls that are received by _onActorTransformChanged + * should be ignored + */ + bool _updatingActorTransform = false; + + bool _lastRelativeTransformIsValid = false; + FTransform _lastRelativeTransform{}; + + /** + * Called when the root transform of the Actor to which this Component is + * attached has changed. So: + * * The globe (ECEF) position and orientation are computed from the new + * transform. + * * When `AdjustOrientationForGlobeWhenMoving` is enabled, the orientation + * will also be adjusted for globe curvature. + */ + void _onActorTransformChanged( + USceneComponent* InRootComponent, + EUpdateTransformFlags UpdateTransformFlags, + ETeleportType Teleport); + + /** + * Called when the Component switches to a new Georeference Actor or the + * existing Georeference is given a new origin Longitude, Latitude, or + * Height. The Actor's position and orientation are recomputed from the + * Component's globe (ECEF) position and orientation. + */ + UFUNCTION(CallInEditor) + void _onGeoreferenceChanged(); + + friend class FCesiumGlobeAnchorCustomization; +#pragma endregion +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGlobeAnchoredActorComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGlobeAnchoredActorComponent.h new file mode 100644 index 0000000..ec238e4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGlobeAnchoredActorComponent.h @@ -0,0 +1,37 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Components/ActorComponent.h" +#include "CesiumGlobeAnchoredActorComponent.generated.h" + +class UCesiumGlobeAnchorComponent; + +UCLASS(ClassGroup = "Cesium", Abstract) +class CESIUMRUNTIME_API UCesiumGlobeAnchoredActorComponent + : public UActorComponent { + GENERATED_BODY() + +public: + UFUNCTION(BlueprintGetter) + UCesiumGlobeAnchorComponent* GetGlobeAnchor(); + +protected: + virtual void OnRegister() override; + virtual void BeginPlay() override; + +private: + void ResolveGlobeAnchor(); + + // The globe anchor attached to the same Actor as this component. Don't + // save/load or copy this. It is set in BeginPlay and OnRegister. + UPROPERTY( + Category = "Cesium", + BlueprintReadOnly, + BlueprintGetter = GetGlobeAnchor, + Transient, + DuplicateTransient, + TextExportTransient, + Meta = (AllowPrivateAccess)) + UCesiumGlobeAnchorComponent* GlobeAnchor; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumIonRasterOverlay.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumIonRasterOverlay.h new file mode 100644 index 0000000..eac3353 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumIonRasterOverlay.h @@ -0,0 +1,70 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumRasterOverlay.h" +#include "CoreMinimal.h" +#include "CesiumIonRasterOverlay.generated.h" + +class UCesiumIonServer; + +/** + * A raster overlay that uses an IMAGERY asset from Cesium ion. + */ +UCLASS( + DisplayName = "Cesium ion Raster Overlay", + ClassGroup = (Cesium), + meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumIonRasterOverlay : public UCesiumRasterOverlay { + GENERATED_BODY() + +public: + /** + * The ID of the Cesium ion asset to use. + * + * If this property is non-zero, the Bing Maps Key and Map Style properties + * are ignored. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + int64 IonAssetID; + + /** + * The access token to use to access the Cesium ion resource. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + FString IonAccessToken; + + /** + * The URL of the ion asset endpoint. Defaults to Cesium ion but a custom + * endpoint can be specified. + */ + UPROPERTY( + meta = + (DeprecatedProperty, + DeprecationMessage = "Use CesiumIonServer instead.")) + FString IonAssetEndpointUrl_DEPRECATED; + + /** + * The Cesium ion Server from which this raster overlay is loaded. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + AdvancedDisplay) + UCesiumIonServer* CesiumIonServer; + + /** + * Check if the Cesium ion token used to access this raster overlay is working + * correctly, and fix it if necessary. + */ + UFUNCTION(CallInEditor, Category = "Cesium") + void TroubleshootToken(); + + // UActorComponent overrides + virtual void PostLoad() override; + +protected: + virtual std::unique_ptr CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options = {}) override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumIonServer.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumIonServer.h new file mode 100644 index 0000000..051803a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumIonServer.h @@ -0,0 +1,135 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Engine/DataAsset.h" +#include "UObject/Object.h" +#include "CesiumIonServer.generated.h" + +namespace CesiumAsync { +template class Future; +} + +/** + * Defines a Cesium ion Server. This may be the public (SaaS) Cesium ion server + * at ion.cesium.com, or it may be a self-hosted instance. + */ +UCLASS() +class CESIUMRUNTIME_API UCesiumIonServer : public UDataAsset { + GENERATED_BODY() + +public: + /** + * Gets the default Cesium ion Server (ion.cesium.com). + * + * It is expected to be found at + * `/Game/CesiumSettings/CesiumIonServers/CesiumIonSaaS`. In the Editor, it + * will be created if it does not already exist, so this method always returns + * a valid instance. At runtime, this method returns nullptr if the object + * does not exist. + */ + static UCesiumIonServer* GetDefaultServer(); + + /** + * Gets the current server to be assigned to new objects. In the Editor, this + * is the server that is currently selected on the Cesium panel. At runtime, + * this returns `GetDefault`, unless `SetCurrentForNewObjects` has been called + * to set it to something different. + */ + static UCesiumIonServer* GetServerForNewObjects(); + + /** + * Sets the current server to be assigned to new objects. If set to nullptr, + * the value of `GetDefault` will be returned from `GetCurrentForNewObjects`. + */ + static void SetServerForNewObjects(UCesiumIonServer* Server); + +#if WITH_EDITOR + /** + * Gets or creates a server from a given API URL. This is used for backward + * compatibility with the old `IonAssetEndpointUrl` property. The new server, + * if needed, is created in `/Game/CesiumSettings/CesiumIonServers`. + */ + static UCesiumIonServer* GetBackwardCompatibleServer(const FString& apiUrl); +#endif + + /** + * The name to display for this server. + */ + UPROPERTY( + EditAnywhere, + AssetRegistrySearchable, + Category = "Cesium", + meta = (DisplayName = "Display Name")) + FString DisplayName = "ion.cesium.com"; + + /** + * The main URL of the Cesium ion server. For example, the server URL for the + * public Cesium ion is https://ion.cesium.com. + */ + UPROPERTY( + EditAnywhere, + AssetRegistrySearchable, + Category = "Cesium", + meta = (DisplayName = "Server URL")) + FString ServerUrl = "https://ion.cesium.com"; + + /** + * The URL of the main API endpoint of the Cesium ion server. For example, for + * the default, public Cesium ion server, this is `https://api.cesium.com`. If + * left blank, the API URL is automatically inferred from the Server URL. + */ + UPROPERTY( + EditAnywhere, + AssetRegistrySearchable, + Category = "Cesium", + meta = (DisplayName = "API URL")) + FString ApiUrl = "https://api.cesium.com"; + + /** + * The application ID to use to log in to this server using OAuth2. This + * OAuth2 application must be configured on the server with the exact URL + * `http://127.0.0.1/cesium-for-unreal/oauth2/callback`. + */ + UPROPERTY( + EditAnywhere, + AssetRegistrySearchable, + Category = "Cesium", + meta = (DisplayName = "OAuth Application ID")) + int64 OAuth2ApplicationID = 190; + + /** + * The ID of the default access token to use to access Cesium ion assets at + * runtime. This property may be an empty string, in which case the ID is + * found by searching the logged-in Cesium ion account for the + * DefaultIonAccessToken. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + meta = (DisplayName = "Default Cesium ion Access Token ID")) + FString DefaultIonAccessTokenId; + + /** + * The default token used to access Cesium ion assets at runtime. This token + * is embedded in packaged games for use at runtime. + */ + UPROPERTY( + EditAnywhere, + AssetRegistrySearchable, + Category = "Cesium", + meta = (DisplayName = "Default Cesium ion Access Token")) + FString DefaultIonAccessToken; + +#if WITH_EDITOR + /** + * If the `ApiUrl` property is blank, this method asynchronously resolves it + * by consulting with the `ServerUrl`. If the `ApiUrl` is not blank, this + * method returns an already-resolved future. + */ + CesiumAsync::Future ResolveApiUrl(); +#endif + +private: + static UCesiumIonServer* _pDefaultForNewObjects; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataEncodingDetails.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataEncodingDetails.h new file mode 100644 index 0000000..f4ceb12 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataEncodingDetails.h @@ -0,0 +1,114 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumMetadataValueType.h" +#include +#include + +#include "CesiumMetadataEncodingDetails.generated.h" + +/** + * @brief The component type that a metadata property's values will be encoded + * as. These correspond to the pixel component types that are supported in + * Unreal textures. + */ +UENUM() +enum class ECesiumEncodedMetadataComponentType : uint8 { None, Uint8, Float }; + +/** + * @brief The type that a metadata property's values will be encoded as. + */ +UENUM() +enum class ECesiumEncodedMetadataType : uint8 { + None, + Scalar, + Vec2, + Vec3, + Vec4 +}; + +/** + * @brief Indicates how a property value from EXT_structural_metadata should be + * converted to a GPU-accessible type, if possible. + */ +UENUM() +enum class ECesiumEncodedMetadataConversion : uint8 { + /** + * Do nothing. This is typically used for property types that are + * completely unable to be coerced. + */ + None, + /** + * Coerce the components of a property value to the specified component type. + * If the property contains string values, this attempts to parse numbers from + * the strings as uint8s. + */ + Coerce, + /** + * Attempt to parse a color from a string property value. This supports + * the following formats: + * - `rgb(R, G, B)`, where R, G, and B are values in the range [0, 255] + * - hexcode colors, e.g. `#ff0000` + */ + ParseColorFromString +}; + +/** + * Describes how a property from EXT_structural_metadata will be encoded for + * access in Unreal materials. + */ +USTRUCT() +struct FCesiumMetadataEncodingDetails { + GENERATED_USTRUCT_BODY() + + FCesiumMetadataEncodingDetails() + : Type(ECesiumEncodedMetadataType::None), + ComponentType(ECesiumEncodedMetadataComponentType::None), + Conversion(ECesiumEncodedMetadataConversion::None) {} + + FCesiumMetadataEncodingDetails( + ECesiumEncodedMetadataType InType, + ECesiumEncodedMetadataComponentType InComponentType, + ECesiumEncodedMetadataConversion InConversion) + : Type(InType), + ComponentType(InComponentType), + Conversion(InConversion) {} + + /** + * The GPU-compatible type that this property's values will be encoded as. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + ECesiumEncodedMetadataType Type; + + /** + * The GPU-compatible component type that this property's values will be + * encoded as. These correspond to the pixel component types that are + * supported in Unreal textures. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + ECesiumEncodedMetadataComponentType ComponentType; + + /** + * The method of conversion used for this property. This describes how the + * values will be converted for access in Unreal materials. Note that not all + * property types are compatible with the methods of conversion. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + ECesiumEncodedMetadataConversion Conversion; + + inline bool operator==(const FCesiumMetadataEncodingDetails& Info) const { + return Type == Info.Type && ComponentType == Info.ComponentType && + Conversion == Info.Conversion; + } + + inline bool operator!=(const FCesiumMetadataEncodingDetails& Info) const { + return Type != Info.Type || ComponentType != Info.ComponentType || + Conversion != Info.Conversion; + } + + bool HasValidType() const { + return Type != ECesiumEncodedMetadataType::None && + ComponentType != ECesiumEncodedMetadataComponentType::None; + } +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataPickingBlueprintLibrary.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataPickingBlueprintLibrary.h new file mode 100644 index 0000000..af2e059 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataPickingBlueprintLibrary.h @@ -0,0 +1,181 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumMetadataValue.h" +#include "Containers/UnrealString.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include "CesiumMetadataPickingBlueprintLibrary.generated.h" + +struct FHitResult; + +UCLASS() +class CESIUMRUNTIME_API UCesiumMetadataPickingBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Compute the UV coordinates from the given line trace hit, assuming it has + * hit a glTF primitive component that contains the specified texture + * coordinate set. The texture coordinate set is specified relative to the + * glTF itself, where the set index N resolves to the "TEXCOORD_N" attribute + * in the glTF primitive. + * + * This function can be used to sample feature ID textures or property + * textures in the primitive. This works similarly to the FindCollisionUV + * Blueprint, except it does not require the texture coordinate sets to be + * present in the model's physics mesh. + * + * Returns false if the given texture coordinate set index does not exist for + * the primitive, or if its accessor is invalid. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Picking") + static bool FindUVFromHit( + const FHitResult& Hit, + int64 GltfTexCoordSetIndex, + FVector2D& UV); + + /** + * Gets the property table values from a given line trace hit, assuming + * that it has hit a feature of a glTF primitive component. + * + * A primitive may have multiple feature ID sets, so this allows a feature ID + * set to be specified by index. This value should index into the array of + * CesiumFeatureIdSets in the component's CesiumPrimitiveFeatures. If the + * feature ID set is associated with a property table, it will return that + * property table's data. + * + * For feature ID textures and implicit feature IDs, the feature ID can vary + * across the face of a primitive. If the specified CesiumFeatureIdSet is one + * of those types, the feature ID of the first vertex on the face will be + * used. + * + * The returned result may be empty for several reasons: + * - if the component is not a Cesium glTF primitive component + * - if the hit's face index is somehow out-of-bounds + * - if the specified feature ID set does not exist on the primitive + * - if the specified feature ID set is not associated with a valid property + * table + * + * Additionally, if any of the property table's properties are invalid, they + * will not be included in the result. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Picking") + static TMap GetPropertyTableValuesFromHit( + const FHitResult& Hit, + int64 FeatureIDSetIndex = 0); + + /** + * Gets the property texture values from a given line trace hit, assuming it + * has hit a glTF primitive component. + * + * A primitive may use multiple property textures, as indicated by its indices + * in CesiumPrimitiveMetadata. This function allows for selection of which + * property texture to use from those available in CesiumPrimitiveMetadata. + * + * In other words, the "Primitive Property Texture Index" should index into + * the array property texture indices in the CesiumPrimitiveMetadata. The + * primitive metadata will not necessarily contain all of the available + * property textures in the CesiumModelMetadata, nor will it necessarily be + * listed in the same order. + * + * The returned result may be empty for several reasons: + * - if the component is not a Cesium glTF primitive component + * - if the given primitive property texture index is out-of-bounds + * - if the property texture index derived from CesiumPrimitiveMetadata + * is out-of-bounds + * + * Additionally, if any of the property texture's properties are invalid, they + * will not be included in the result. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Picking") + static TMap GetPropertyTextureValuesFromHit( + const FHitResult& Hit, + int64 PrimitivePropertyTextureIndex = 0); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Gets the metadata values for a face on a glTF primitive component. + * + * A primitive may have multiple feature ID sets, so this allows a feature ID + * set to be specified by index. This value should index into the array of + * CesiumFeatureIdSets in the component's CesiumPrimitiveFeatures. If the + * feature ID set is associated with a property table, it will return that + * property table's data. + * + * For feature ID textures and implicit feature IDs, the feature ID can vary + * across the face of a primitive. If the specified CesiumFeatureIdSet is one + * of those types, the feature ID of the first vertex on the face will be + * used. + * + * The returned result may be empty for several reasons: + * - if the component is not a Cesium glTF primitive component + * - if the given face index is out-of-bounds + * - if the specified feature ID set does not exist on the primitive + * - if the specified feature ID set is not associated with a valid property + * table + * + * Additionally, if any of the property table's properties are invalid, they + * will not be included in the result. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = "Use GetPropertyTableValuesFromHit instead.")) + static TMap GetMetadataValuesForFace( + const UPrimitiveComponent* Component, + int64 FaceIndex, + int64 FeatureIDSetIndex = 0); + + /** + * Gets the metadata values for a face on a glTF primitive component, as + * strings. + * + * A primitive may have multiple feature ID sets, so this allows a feature ID + * set to be specified by index. This value should index into the array of + * CesiumFeatureIdSets in the component's CesiumPrimitiveFeatures. If the + * feature ID set is associated with a property table, it will return that + * property table's data. + * + * For feature ID textures and implicit feature IDs, the feature ID can vary + * across the face of a primitive. If the specified CesiumFeatureIdSet is one + * of those types, the feature ID of the first vertex on the face will be + * used. + * + * The returned result may be empty for several reasons: + * - if the component is not a Cesium glTF primitive component + * - if the given face index is out-of-bounds + * - if the specified feature ID set does not exist on the primitive + * - if the specified feature ID set is not associated with a valid property + * table + * + * Additionally, if any of the property table's properties are invalid, they + * will not be included in the result. Array properties will return empty + * strings. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "Use GetValuesAsStrings to convert the output of GetPropertyTableValuesFromHit instead.")) + static TMap GetMetadataValuesForFaceAsStrings( + const UPrimitiveComponent* Component, + int64 FaceIndex, + int64 FeatureIDSetIndex = 0); + PRAGMA_ENABLE_DEPRECATION_WARNINGS +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataPrimitive.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataPrimitive.h new file mode 100644 index 0000000..d1cb6c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataPrimitive.h @@ -0,0 +1,151 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumModelMetadata.h" +#include "CesiumPrimitiveFeatures.h" +#include "CesiumPrimitiveMetadata.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" + +#include "CesiumMetadataPrimitive.generated.h" + +struct UE_DEPRECATED( + 5.0, + "FCesiumMetadataPrimitive is deprecated. Instead, use FCesiumPrimitiveFeatures and FCesiumPrimitiveMetadata to retrieve feature IDs and metadata from a glTF primitive.") + FCesiumMetadataPrimitive; + +/** + * A Blueprint-accessible wrapper for a glTF Primitive's EXT_feature_metadata + * extension. This class is deprecated and only exists for backwards + * compatibility. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumMetadataPrimitive { + GENERATED_USTRUCT_BODY() + +public: + /** + * Construct an empty primitive metadata instance. + */ + FCesiumMetadataPrimitive() + : _pPrimitiveFeatures(nullptr), + _pPrimitiveMetadata(nullptr), + _pModelMetadata(nullptr) {} + + /** + * Constructs a primitive metadata instance from the new features / metadata + * implementations for backwards compatibility. + * + * This class exists for backwards compatibility, so it requires a + * FCesiumPrimitiveFeatures to have been constructed beforehand. It assumes + * the given FCesiumPrimitiveFeatures will have the same lifetime as this + * instance. + * + * @param PrimitiveFeatures The FCesiumPrimitiveFeatures denoting the feature + * IDs in the glTF mesh primitive. + * @param PrimitiveMetadata The FCesiumPrimitiveMetadata containing references + * to the metadata for the glTF mesh primitive. + * @param ModelMetadata The FCesiumModelMetadata containing the property + * tables and textures contained in a glTF model. + */ + FCesiumMetadataPrimitive( + const FCesiumPrimitiveFeatures& PrimitiveFeatures, + const FCesiumPrimitiveMetadata& PrimitiveMetadata, + const FCesiumModelMetadata& ModelMetadata); + +private: + const FCesiumPrimitiveFeatures* _pPrimitiveFeatures; + const FCesiumPrimitiveMetadata* _pPrimitiveMetadata; + const FCesiumModelMetadata* _pModelMetadata; + + friend class UCesiumMetadataPrimitiveBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumMetadataPrimitiveBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + PRAGMA_DISABLE_DEPRECATION_WARNINGS + + /** + * Get all the feature ID attributes that are associated with the + * primitive. + * + * @param MetadataPrimitive The {@link FCesiumMetadataPrimitive} to obtain the + * feature ID attributes from. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Primitive", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "CesiumMetadataPrimitive is deprecated. Get feature IDs from CesiumPrimitiveFeatures instead.")) + static const TArray + GetFeatureIdAttributes(UPARAM(ref) + const FCesiumMetadataPrimitive& MetadataPrimitive); + + /** + * Get all the feature ID textures that are associated with the + * primitive. + * + * @param MetadataPrimitive The {@link FCesiumMetadataPrimitive} to obtain the + * feature ID textures from. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Primitive", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "CesiumMetadataPrimitive is deprecated. Get feature IDs from CesiumPrimitiveFeatures instead.")) + static const TArray + GetFeatureIdTextures(UPARAM(ref) + const FCesiumMetadataPrimitive& MetadataPrimitive); + + /** + * @brief Get all the feature textures that are associated with the + * primitive. + * + * @param MetadataPrimitive The {@link FCesiumMetadataPrimitive} to obtain the + * feature texture names from. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Primitive", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "CesiumMetadataPrimitive is deprecated. Get the associated property texture indices from CesiumPrimitiveMetadata instead.")) + static const TArray + GetFeatureTextureNames(UPARAM(ref) + const FCesiumMetadataPrimitive& MetadataPrimitive); + + /** + * Gets the ID of the first vertex that makes up a given face of this + * primitive. + * + * @param MetadataPrimitive The {@link FCesiumMetadataPrimitive} to obtain the + * vertex ID from. + * @param FaceID The ID of the face. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Primitive", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "CesiumMetadataPrimitive is deprecated. Use GetFirstVertexFromFace with CesiumPrimitiveFeatures instead.")) + static int64 GetFirstVertexIDFromFaceID( + UPARAM(ref) const FCesiumMetadataPrimitive& MetadataPrimitive, + int64 FaceID); + + PRAGMA_ENABLE_DEPRECATION_WARNINGS +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataPropertyDetails.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataPropertyDetails.h new file mode 100644 index 0000000..8371ece --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataPropertyDetails.h @@ -0,0 +1,170 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumMetadataValueType.h" +#include "UObject/ObjectMacros.h" + +#include "CesiumMetadataPropertyDetails.generated.h" + +/** + * Represents information about a metadata property according to how the + * property is defined in EXT_structural_metadata. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumMetadataPropertyDetails { + GENERATED_USTRUCT_BODY() + + FCesiumMetadataPropertyDetails() + : Type(ECesiumMetadataType::Invalid), + ComponentType(ECesiumMetadataComponentType::None), + bIsArray(false) {} + + FCesiumMetadataPropertyDetails( + ECesiumMetadataType InType, + ECesiumMetadataComponentType InComponentType, + bool IsArray) + : Type(InType), ComponentType(InComponentType), bIsArray(IsArray) {} + + /** + * The type of the metadata property. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + ECesiumMetadataType Type = ECesiumMetadataType::Invalid; + + /** + * The component of the metadata property. Only applies when the type is a + * Scalar, VecN, or MatN type. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = + (EditCondition = + "Type != ECesiumMetadataType::Invalid && Type != ECesiumMetadataType::Boolean && Type != ECesiumMetadataType::Enum && Type != ECesiumMetadataType::String")) + ECesiumMetadataComponentType ComponentType = + ECesiumMetadataComponentType::None; + + /** + * Whether or not this represents an array containing elements of the + * specified types. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + bool bIsArray = false; + + /** + * The size of the arrays in the metadata property. If the property contains + * arrays of varying length, this will be zero even though bIsArray will be + * true> If this property does not contain arrays, this is set to zero. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = (EditCondition = "bIsArray")) + int64 ArraySize = 0; + + /** + * Whether or not the values in this property are normalized. Only applicable + * to scalar, vecN, and matN types with integer components. + * + * For unsigned integer component types, values are normalized between + * [0.0, 1.0]. For signed integer component types, values are normalized + * between [-1.0, 1.0] + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = + (EditCondition = + "Type != ECesiumMetadataType::Invalid && Type != ECesiumMetadataType::Boolean && Type != ECesiumMetadataType::Enum && Type != ECesiumMetadataType::String && ComponentType != ECesiumMetadataComponentType::None && ComponentType != ECesiumMetadataComponentType::Float32 && ComponentType != ECesiumMetadataComponentType::Float64")) + bool bIsNormalized = false; + + /** + * Whether or not the property is transformed by an offset. This value is + * defined either in the class property, or in the instance of the property + * itself. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = + (EditCondition = + "Type != ECesiumMetadataType::Invalid && Type != ECesiumMetadataType::Boolean && Type != ECesiumMetadataType::Enum && Type != ECesiumMetadataType::String")) + bool bHasOffset = false; + + /** + * Whether or not the property is transformed by a scale. This value is + * defined either in the class property, or in the instance of the property + * itself. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = + (EditCondition = + "Type != ECesiumMetadataType::Invalid && Type != ECesiumMetadataType::Boolean && Type != ECesiumMetadataType::Enum && Type != ECesiumMetadataType::String")) + bool bHasScale = false; + + /** + * Whether or not the property specifies a "no data" value. This value + * functions a sentinel value, indicating missing data wherever it appears. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = + (EditCondition = + "Type != ECesiumMetadataType::Invalid && Type != ECesiumMetadataType::Boolean && Type != ECesiumMetadataType::Enum")) + bool bHasNoDataValue = false; + + /** + * Whether or not the property specifies a default value. This default value + * is used use when encountering a "no data" value in the property, or when a + * non-required property has been omitted. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = + (EditCondition = + "Type != ECesiumMetadataType::Invalid && Type != ECesiumMetadataType::Enum")) + bool bHasDefaultValue = false; + + inline bool + operator==(const FCesiumMetadataPropertyDetails& ValueType) const { + return Type == ValueType.Type && ComponentType == ValueType.ComponentType && + bIsArray == ValueType.bIsArray; + } + + inline bool + operator!=(const FCesiumMetadataPropertyDetails& ValueType) const { + return !operator==(ValueType); + } + + /** + * Returns the internal types as a FCesiumMetadataValueType. + */ + FCesiumMetadataValueType GetValueType() const { + return FCesiumMetadataValueType(Type, ComponentType, bIsArray); + } + + /** + * Sets the internal types to the values supplied by the input + * FCesiumMetadataValueType. + */ + void SetValueType(FCesiumMetadataValueType ValueType) { + Type = ValueType.Type; + ComponentType = ValueType.ComponentType; + bIsArray = ValueType.bIsArray; + } + + /** + * Whether this property has one or more value transforms. This includes + * normalization, offset, and scale, as well as the "no data" and default + * values. + */ + bool HasValueTransforms() const { + return bIsNormalized || bHasOffset || bHasScale || bHasNoDataValue || + bHasDefaultValue; + } +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataUtilityBlueprintLibrary.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataUtilityBlueprintLibrary.h new file mode 100644 index 0000000..b8c7b84 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataUtilityBlueprintLibrary.h @@ -0,0 +1,84 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumFeatureIdAttribute.h" +#include "CesiumMetadataPrimitive.h" +#include "CesiumMetadataValue.h" +#include "CesiumPrimitiveMetadata.h" +#include "Containers/UnrealString.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include "CesiumMetadataUtilityBlueprintLibrary.generated.h" + +UCLASS() +class CESIUMRUNTIME_API UCesiumMetadataUtilityBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Gets the primitive metadata of a glTF primitive component. If component is + * not a Cesium glTF primitive component, the returned metadata is empty + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "CesiumMetadataPrimitive is deprecated. Use CesiumPrimitiveFeatures and CesiumPrimitiveMetadata instead.")) + static const FCesiumMetadataPrimitive& + GetPrimitiveMetadata(const UPrimitiveComponent* component); + + /** + * Gets the metadata of a face of a glTF primitive component. If the component + * is not a Cesium glTF primitive component, the returned metadata is empty. + * If the primitive has multiple feature tables, the metadata in the first + * table is returned. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "The CesiumMetadataUtility blueprint library is deprecated. Use GetMetadataValuesForFace in the CesiumMetadataPicking blueprint library instead.")) + static TMap + GetMetadataValuesForFace(const UPrimitiveComponent* component, int64 faceID); + + /** + * Gets the metadata as string of a face of a glTF primitive component. If the + * component is not a Cesium glTF primitive component, the returned metadata + * is empty. If the primitive has multiple feature tables, the metadata in the + * first table is returned. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "The CesiumMetadataUtility blueprint library is deprecated. Use GetMetadataValuesForFaceAsStrings in the CesiumMetadataPicking blueprint library instead.")) + static TMap GetMetadataValuesAsStringForFace( + const UPrimitiveComponent* component, + int64 faceID); + + /** + * Gets the feature ID associated with a given face for a feature id + * attribute. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "Use GetFeatureIDFromFace with CesiumPrimitiveFeatures instead.")) + static int64 GetFeatureIDFromFaceID( + UPARAM(ref) const FCesiumMetadataPrimitive& Primitive, + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIDAttribute, + int64 FaceID); + PRAGMA_ENABLE_DEPRECATION_WARNINGS +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataValue.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataValue.h new file mode 100644 index 0000000..3374070 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataValue.h @@ -0,0 +1,846 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumMetadataValueType.h" +#include "CesiumPropertyArray.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include +#include +#include + +#include "CesiumMetadataValue.generated.h" + +/** + * A Blueprint-accessible wrapper for a glTF metadata value. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumMetadataValue { + GENERATED_USTRUCT_BODY() + +private: +#pragma region ValueType declaration + template using ArrayView = CesiumGltf::PropertyArrayView; + using ValueType = swl::variant< + swl::monostate, + int8_t, + uint8_t, + int16_t, + uint16_t, + int32_t, + uint32_t, + int64_t, + uint64_t, + float, + double, + bool, + std::string_view, + glm::vec<2, int8_t>, + glm::vec<2, uint8_t>, + glm::vec<2, int16_t>, + glm::vec<2, uint16_t>, + glm::vec<2, int32_t>, + glm::vec<2, uint32_t>, + glm::vec<2, int64_t>, + glm::vec<2, uint64_t>, + glm::vec<2, float>, + glm::vec<2, double>, + glm::vec<3, int8_t>, + glm::vec<3, uint8_t>, + glm::vec<3, int16_t>, + glm::vec<3, uint16_t>, + glm::vec<3, int32_t>, + glm::vec<3, uint32_t>, + glm::vec<3, int64_t>, + glm::vec<3, uint64_t>, + glm::vec<3, float>, + glm::vec<3, double>, + glm::vec<4, int8_t>, + glm::vec<4, uint8_t>, + glm::vec<4, int16_t>, + glm::vec<4, uint16_t>, + glm::vec<4, int32_t>, + glm::vec<4, uint32_t>, + glm::vec<4, int64_t>, + glm::vec<4, uint64_t>, + glm::vec<4, float>, + glm::vec<4, double>, + glm::mat<2, 2, int8_t>, + glm::mat<2, 2, uint8_t>, + glm::mat<2, 2, int16_t>, + glm::mat<2, 2, uint16_t>, + glm::mat<2, 2, int32_t>, + glm::mat<2, 2, uint32_t>, + glm::mat<2, 2, int64_t>, + glm::mat<2, 2, uint64_t>, + glm::mat<2, 2, float>, + glm::mat<2, 2, double>, + glm::mat<3, 3, int8_t>, + glm::mat<3, 3, uint8_t>, + glm::mat<3, 3, int16_t>, + glm::mat<3, 3, uint16_t>, + glm::mat<3, 3, int32_t>, + glm::mat<3, 3, uint32_t>, + glm::mat<3, 3, int64_t>, + glm::mat<3, 3, uint64_t>, + glm::mat<3, 3, float>, + glm::mat<3, 3, double>, + glm::mat<4, 4, int8_t>, + glm::mat<4, 4, uint8_t>, + glm::mat<4, 4, int16_t>, + glm::mat<4, 4, uint16_t>, + glm::mat<4, 4, int32_t>, + glm::mat<4, 4, uint32_t>, + glm::mat<4, 4, int64_t>, + glm::mat<4, 4, uint64_t>, + glm::mat<4, 4, float>, + glm::mat<4, 4, double>, + ArrayView, + ArrayView, + ArrayView, + ArrayView, + ArrayView, + ArrayView, + ArrayView, + ArrayView, + ArrayView, + ArrayView, + ArrayView, + ArrayView, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>, + ArrayView>>; +#pragma endregion + +public: + /** + * Constructs an empty metadata value with unknown type. + */ + FCesiumMetadataValue() : _value(swl::monostate{}), _valueType(), _storage() {} + + /** + * Constructs a metadata value with the given input. + * + * @param Value The value to be stored in this struct. + */ + template + explicit FCesiumMetadataValue(const T& Value) + : _value(Value), _valueType(), _storage() { + ECesiumMetadataType type; + ECesiumMetadataComponentType componentType; + bool isArray; + if constexpr (CesiumGltf::IsMetadataArray::value) { + using ArrayType = typename CesiumGltf::MetadataArrayType::type; + type = + ECesiumMetadataType(CesiumGltf::TypeToPropertyType::value); + componentType = ECesiumMetadataComponentType( + CesiumGltf::TypeToPropertyType::component); + isArray = true; + } else { + type = ECesiumMetadataType(CesiumGltf::TypeToPropertyType::value); + componentType = ECesiumMetadataComponentType( + CesiumGltf::TypeToPropertyType::component); + isArray = false; + } + _valueType = {type, componentType, isArray}; + } + + template + explicit FCesiumMetadataValue( + const CesiumGltf::PropertyArrayCopy& Copy) + : FCesiumMetadataValue(CesiumGltf::PropertyArrayCopy(Copy)) {} + + template + explicit FCesiumMetadataValue(CesiumGltf::PropertyArrayCopy&& Copy) + : _value(), _valueType(), _storage() { + this->_value = std::move(Copy).toViewAndExternalBuffer(this->_storage); + + ECesiumMetadataType type = + ECesiumMetadataType(CesiumGltf::TypeToPropertyType::value); + ECesiumMetadataComponentType componentType = ECesiumMetadataComponentType( + CesiumGltf::TypeToPropertyType::component); + bool isArray = true; + this->_valueType = {type, componentType, isArray}; + } + + /** + * Constructs a metadata value with the given optional input. + * + * @param MaybeValue The optional value to be stored in this struct. + */ + template + explicit FCesiumMetadataValue(const std::optional& MaybeValue) + : _value(), _valueType(), _storage() { + if (!MaybeValue) { + return; + } + + FCesiumMetadataValue temp(*MaybeValue); + this->_value = std::move(temp._value); + this->_valueType = std::move(temp._valueType); + this->_storage = std::move(temp._storage); + } + + FCesiumMetadataValue(FCesiumMetadataValue&& rhs); + FCesiumMetadataValue& operator=(FCesiumMetadataValue&& rhs); + FCesiumMetadataValue(const FCesiumMetadataValue& rhs); + FCesiumMetadataValue& operator=(const FCesiumMetadataValue& rhs); + +private: + ValueType _value; + FCesiumMetadataValueType _valueType; + std::vector _storage; + + friend class UCesiumMetadataValueBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumMetadataValueBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the best-fitting Blueprints type for this value. For the most precise + * representation of the value possible from Blueprints, you should retrieve + * it using this type. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static ECesiumMetadataBlueprintType + GetBlueprintType(UPARAM(ref) const FCesiumMetadataValue& Value); + + /** + * Gets the best-fitting Blueprints type for the elements of this array value. + * If the given value is not of an array type, this returns None. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static ECesiumMetadataBlueprintType + GetArrayElementBlueprintType(UPARAM(ref) const FCesiumMetadataValue& Value); + + /** + * Gets the type of the metadata value as defined in the + * EXT_structural_metadata extension. Many of these types are not accessible + * from Blueprints, but can be converted to a Blueprint-accessible type. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static FCesiumMetadataValueType + GetValueType(UPARAM(ref) const FCesiumMetadataValue& Value); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Gets true type of the value. Many of these types are not accessible + * from Blueprints, but can be converted to a Blueprint-accessible type. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "CesiumMetadataTrueType is deprecated. Use GetValueType to get the CesiumMetadataValueType instead.")) + static ECesiumMetadataTrueType_DEPRECATED + GetTrueType(UPARAM(ref) const FCesiumMetadataValue& Value); + + /** + * Gets true type of the elements in the array. If this value is not an array, + * the component type will be None. Many of these types are not accessible + * from Blueprints, but can be converted to a Blueprint-accessible type. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "CesiumMetadataTrueType is deprecated. Use GetValueType to get the CesiumMetadataValueType instead.")) + static ECesiumMetadataTrueType_DEPRECATED + GetTrueComponentType(UPARAM(ref) const FCesiumMetadataValue& Value); + + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * Attempts to retrieve the value as a boolean. + * + * If the value is a boolean, it is returned as-is. + * + * If the value is a scalar, zero is converted to false, while any other + * value is converted to true. + * + * If the value is a string, "0", "false", and "no" (case-insensitive) are + * converted to false, while "1", "true", and "yes" are converted to true. + * All other strings, including strings that can be converted to numbers, + * will return the default value. + * + * All other types return the default value. + * + * @param value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to a Boolean. + * @return The value as a Boolean. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static bool + GetBoolean(UPARAM(ref) const FCesiumMetadataValue& value, bool DefaultValue); + + /** + * Attempts to retrieve the value as an unsigned 8-bit integer. + * + * If the value is an integer between 0 and 255, it is returned + * as-is. + * + * If the value is a floating-point number in the aforementioned range, it is + * truncated (rounded toward zero) and returned. + * + * If the value is a boolean, 1 is returned for true and 0 for false. + * + * If the value is a string and the entire string can be parsed as an + * integer between 0 and 255, the parsed value is returned. The string is + * parsed in a locale-independent way and does not support the use of commas + * or other delimiters to group digits together. + * + * In all other cases, the default value is returned. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to a Byte. + * @return The value as a Byte. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static uint8 + GetByte(UPARAM(ref) const FCesiumMetadataValue& Value, uint8 DefaultValue); + + /** + * Attempts to retrieve the value as a signed 32-bit integer. + * + * If the value is an integer between -2,147,483,648 and 2,147,483,647, + * it is returned as-is. + * + * If the value is a floating-point number in the aforementioned range, it is + * truncated (rounded toward zero) and returned; + * + * If the value is a boolean, 1 is returned for true and 0 for false. + * + * If the value is a string and the entire string can be parsed as an + * integer in the valid range, the parsed value is returned. If it can be + * parsed as a floating-point number, the parsed value is truncated (rounded + * toward zero). In either case, the string is parsed in a locale-independent + * way and does not support the use of commas or other delimiters to group + * digits together. + * + * In all other cases, the default value is returned. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to an Integer. + * @return The value as an Integer. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static int32 + GetInteger(UPARAM(ref) const FCesiumMetadataValue& Value, int32 DefaultValue); + + /** + * Attempts to retrieve the value as a signed 64-bit integer. + * + * If the value is an integer and between -2^63 and (2^63 - 1), + * it is returned as-is. + * + * If the value is a floating-point number in the aforementioned range, it + * is truncated (rounded toward zero) and returned; + * + * If the value is a boolean, 1 is returned for true and 0 for false. + * + * If the value is a string and the entire string can be parsed as an + * integer in the valid range, the parsed value is returned. If it can be + * parsed as a floating-point number, the parsed value is truncated (rounded + * toward zero). In either case, the string is parsed in a locale-independent + * way and does not support the use of commas or other delimiters to group + * digits together. + * + * In all other cases, the default value is returned. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to an Integer64. + * @return The value as an Integer64. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static int64 GetInteger64( + UPARAM(ref) const FCesiumMetadataValue& Value, + int64 DefaultValue); + + /** + * Attempts to retrieve the value as a single-precision floating-point number. + * + * If the value is already a single-precision floating-point number, it is + * returned as-is. + * + * If the value is a scalar of any other type within the range of values that + * a single-precision float can represent, it is converted to its closest + * representation as a single-precision float and returned. + * + * If the value is a boolean, 1.0f is returned for true and 0.0f for false. + * + * If the value is a string, and the entire string can be parsed as a + * number, the parsed value is returned. The string is parsed in a + * locale-independent way and does not support the use of a comma or other + * delimiter to group digits togther. + * + * In all other cases, the default value is returned. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to a Float. + * @return The value as a Float. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static float + GetFloat(UPARAM(ref) const FCesiumMetadataValue& Value, float DefaultValue); + + /** + * Attempts to retrieve the value as a double-precision floating-point number. + * + * If the value is a single- or double-precision floating-point number, it is + * returned as-is. + * + * If the value is an integer, it is converted to the closest representable + * double-precision floating-point number. + * + * If the value is a boolean, 1.0 is returned for true and 0.0 for false. + * + * If the value is a string and the entire string can be parsed as a + * number, the parsed value is returned. The string is parsed in a + * locale-independent way and does not support the use of commas or other + * delimiters to group digits together. + * + * In all other cases, the default value is returned. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to a Float64. + * @return The value as a Float64. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static double GetFloat64( + UPARAM(ref) const FCesiumMetadataValue& Value, + double DefaultValue); + + /** + * Attempts to retrieve the value as a FIntPoint. + * + * If the value is a 2-dimensional vector, its components will be converted to + * 32-bit signed integers if possible. + * + * If the value is a 3- or 4-dimensional vector, it will use the first two + * components to construct the FIntPoint. + * + * If the value is a scalar that can be converted to a 32-bit signed integer, + * the resulting FIntPoint will have this value in both of its components. + * + * If the value is a boolean, (1, 1) is returned for true, while (0, 0) is + * returned for false. + * + * If the value is a string that can be parsed as a FIntPoint, the parsed + * value is returned. The string must be formatted as "X=... Y=...". + * + * In all other cases, the default value is returned. In all vector cases, if + * any of the relevant components cannot be represented as a 32-bit signed, + * the default value is returned. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to a FIntPoint. + * @return The value as a FIntPoint. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static FIntPoint GetIntPoint( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FIntPoint& DefaultValue); + + /** + * Attempts to retrieve the value as a FVector2D. + * + * If the value is a 2-dimensional vector, its components will be converted to + * double-precision floating-point numbers. + * + * If the value is a 3- or 4-dimensional vector, it will use the first two + * components to construct the FVector2D. + * + * If the value is a scalar, the resulting FVector2D will have this value in + * both of its components. + * + * If the value is a boolean, (1.0, 1.0) is returned for true, while (0.0, + * 0.0) is returned for false. + * + * If the value is a string that can be parsed as a FVector2D, the parsed + * value is returned. The string must be formatted as "X=... Y=...". + * + * In all other cases, the default value is returned. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to a FIntPoint. + * @return The value as a FIntPoint. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static FVector2D GetVector2D( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FVector2D& DefaultValue); + + /** + * Attempts to retrieve the value as a FIntVector. + * + * If the value is a 3-dimensional vector, its components will be converted to + * 32-bit signed integers if possible. + * + * If the value is a 4-dimensional vector, it will use the first three + * components to construct the FIntVector. + * + * If the value is a 2-dimensional vector, it will become the XY-components of + * the FIntVector. The Z component will be set to zero. + * + * If the value is a scalar that can be converted to a 32-bit signed integer, + * the resulting FIntVector will have this value in all of its components. + * + * If the value is a boolean, (1, 1, 1) is returned for true, while (0, 0, 0) + * is returned for false. + * + * If the value is a string that can be parsed as a FIntVector, the parsed + * value is returned. The string must be formatted as "X=... Y=... Z=". + * + * In all other cases, the default value is returned. In all vector cases, if + * any of the relevant components cannot be represented as a 32-bit signed + * integer, the default value is returned. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to a FIntVector. + * @return The value as a FIntVector. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static FIntVector GetIntVector( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FIntVector& DefaultValue); + + /** + * Attempts to retrieve the value as a FVector3f. + * + * If the value is a 3-dimensional vector, its components will be converted to + * the closest representable single-precision floats, if possible. + * + * If the value is a 4-dimensional vector, a FVector3f containing the first + * three components will be returned. + * + * If the value is a 2-dimensional vector, it will become the XY-components of + * the FVector3f. The Z-component will be set to zero. + * + * If the value is a scalar that can be converted to a single-precision + * floating-point number, then the resulting FVector3f will have this value in + * all of its components. + * + * If the value is a boolean, (1.0f, 1.0f, 1.0f) is returned for true, while + * (0.0f, 0.0f, 0.0f) is returned for false. + * + * If the value is a string that can be parsed as a FVector3f, the parsed + * value is returned. The string must be formatted as "X=... Y=... Z=". + * + * In all other cases, the default value is returned. In all vector cases, if + * any of the relevant components cannot be represented as a single-precision + * float, the default value is returned. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to a FVector3f. + * @return The value as a FVector3f. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static FVector3f GetVector3f( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FVector3f& DefaultValue); + + /** + * Attempts to retrieve the value as a FVector. + * + * If the value is a 3-dimensional vector, its components will be converted to + * double-precision floating-point numbers. + * + * If the value is a 4-dimensional vector, a FVector containing the first + * three components will be returned. + * + * If the value is a 2-dimensional vector, it will become the XY-components of + * the FVector. The Z-component will be set to zero. + * + * If the value is a scalar, then the resulting FVector will have this value + * as a double-precision floating-point number in all of its components. + * + * If the value is a boolean, (1.0, 1.0, 1.0) is returned for true, while + * (0.0, 0.0, 0.0) is returned for false. + * + * If the value is a string that can be parsed as a FVector, the parsed + * value is returned. The string must be formatted as "X=... Y=... Z=". + * + * In all other cases, the default value is returned. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to a FVector. + * @return The value as a FVector. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static FVector GetVector( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FVector& DefaultValue); + + /** + * Attempts to retrieve the value as a FVector4. + * + * If the value is a 4-dimensional vector, its components will be converted to + * double-precision floating-point numbers. + * + * If the value is a 3-dimensional vector, it will become the XYZ-components + * of the FVector4. The W-component will be set to zero. + * + * If the value is a 2-dimensional vector, it will become the XY-components of + * the FVector4. The Z- and W-components will be set to zero. + * + * If the value is a scalar, then the resulting FVector4 will have this value + * as a double-precision floating-point number in all of its components. + * + * If the value is a boolean, (1.0, 1.0, 1.0, 1.0) is returned for true, while + * (0.0, 0.0, 0.0, 0.0) is returned for false. + * + * If the value is a string that can be parsed as a FVector4, the parsed + * value is returned. This follows the rules of FVector4::InitFromString. The + * string must be formatted as "X=... Y=... Z=... W=...". The W-component is + * optional; if absent, it will be set to 1.0. + * + * In all other cases, the default value is returned. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to a FVector4. + * @return The value as a FVector4. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static FVector4 GetVector4( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FVector4& DefaultValue); + + /** + * Attempts to retrieve the value as a FMatrix. + * + * If the value is a 4-by-4 matrix, its components will be converted to + * double-precision floating-point numbers. + * + * If the value is a 3-by-3 matrix, it will initialize the corresponding + * entries of the FMatrix, while all other entries are set to zero. In other + * words, the 3-by-3 matrix is returned in an FMatrix where the fourth row and + * column are filled with zeroes. + * + * If the value is a 2-by-2 matrix, it will initialize the corresponding + * entries of the FMatrix, while all other entries are set to zero. In other + * words, the 2-by-2 matrix is returned in an FMatrix where the third and + * fourth rows / columns are filled with zeroes. + * + * If the value is a scalar, then the resulting FMatrix will have this value + * along its diagonal, including the very last component. All other entries + * will be zero. + * + * If the value is a boolean, it is converted to 1.0 for true and 0.0 for + * false. Then, the resulting FMatrix will have this value along its diagonal, + * including the very last component. All other entries will be zero. + * + * In all other cases, the default value is returned. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to a FMatrix. + * @return The value as a FMatrix. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static FMatrix GetMatrix( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FMatrix& DefaultValue); + + /** + * Attempts to retrieve the value as a FString. + * + * String properties are returned as-is. + * + * Scalar values are converted to a string with `std::to_string`. + * + * Boolean properties are converted to "true" or "false". + * + * Vector properties are returned as strings in the format "X=... Y=... Z=... + * W=..." depending on how many components they have. + * + * Matrix properties are returned as strings row-by-row, where each row's + * values are printed between square brackets. For example, a 2-by-2 matrix + * will be printed out as "[A B] [C D]". + * + * Array properties return the default value. + * + * @param Value The metadata value to retrieve. + * @param DefaultValue The default value to use if the given value cannot + * be converted to a FString. + * @return The value as a FString. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static FString GetString( + UPARAM(ref) const FCesiumMetadataValue& Value, + const FString& DefaultValue); + + /** + * Attempts to retrieve the value as a FCesiumPropertyArray. If the property + * is not an array type, this returns an empty array. + * + * @param Value The metadata value to retrieve. + * @return The value as a FCesiumPropertyArray. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static FCesiumPropertyArray GetArray(UPARAM(ref) + const FCesiumMetadataValue& Value); + + /** + * Whether the value is empty, i.e., whether it does not actually represent + * any data. An empty value functions as a null value, and can be compared to + * a std::nullopt in C++. For example, when the raw value of a property + * matches the property's specified "no data" value, it will return an empty + * FCesiumMetadataValue. + * + * @param Value The metadata value to retrieve. + * @return Whether the value is empty. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static bool IsEmpty(UPARAM(ref) const FCesiumMetadataValue& Value); + + /** + * Gets the given map of metadata values as a new map of strings, mapped by + * name. This is useful for displaying the values from a property table or + * property texture as strings in a user interface. + * + * Array properties cannot be converted to strings, so empty strings + * will be returned for their values. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Value") + static TMap + GetValuesAsStrings(const TMap& Values); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataValueType.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataValueType.h new file mode 100644 index 0000000..ce6c3dd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataValueType.h @@ -0,0 +1,253 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/PropertyArrayView.h" +#include "CesiumGltf/PropertyType.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumMetadataValueType.generated.h" + +/** + * The Blueprint type that can losslessly represent values of a given property. + */ +UENUM(BlueprintType) +enum class ECesiumMetadataBlueprintType : uint8 { + /* Indicates a value cannot be represented in Blueprints. */ + None, + /* Indicates a value is best represented as a Boolean. */ + Boolean, + /* Indicates a value is best represented as a Byte (8-bit unsigned integer). + */ + Byte, + /* Indicates a value is best represented as a Integer (32-bit signed). */ + Integer, + /* Indicates a value is best represented as a Integer64 (64-bit signed). */ + Integer64, + /* Indicates a value is best represented as a Float (32-bit). */ + Float, + /* Indicates a value is best represented as a Float64 (64-bit). */ + Float64, + /* Indicates a value is best represented as a FVector2D (2-dimensional + integer vector). */ + IntPoint, + /* Indicates a value is best represented as a FVector2D (2-dimensional + double-precision vector). */ + Vector2D, + /* Indicates a value is best represented as a FIntVector (3-dimensional + integer vector). */ + IntVector, + /* Indicates a value is best represented as a FVector3f (3-dimensional + single-precision vector). */ + Vector3f, + /* Indicates a value is best represented as a FVector3 (3-dimensional + double-precision vector). */ + Vector3, + /* Indicates a value is best represented as a FVector4 (4-dimensional + double-precision vector). */ + Vector4, + /* Indicates a value is best represented as a FMatrix (4-by-4 double-precision + matrix). */ + Matrix, + /* Indicates a value is best represented as a FString. This can be used as a + fallback for types with no proper Blueprints representation. */ + String, + /* Indicates a value is best represented as a CesiumPropertyArray. */ + Array +}; + +// UE requires us to have an enum with the value 0. +// Invalid / None should have that value, but just make sure. +static_assert(int(CesiumGltf::PropertyType::Invalid) == 0); +static_assert(int(CesiumGltf::PropertyComponentType::None) == 0); + +/** + * The type of a metadata property in EXT_feature_metadata. This has been + * deprecated; use FCesiumMetadataValueType to get the complete type information + * of a metadata property instead. + */ +UENUM(BlueprintType) +enum class ECesiumMetadataTrueType_DEPRECATED : uint8 { + None_DEPRECATED = 0, + Int8_DEPRECATED, + Uint8_DEPRECATED, + Int16_DEPRECATED, + Uint16_DEPRECATED, + Int32_DEPRECATED, + Uint32_DEPRECATED, + Int64_DEPRECATED, + Uint64_DEPRECATED, + Float32_DEPRECATED, + Float64_DEPRECATED, + Boolean_DEPRECATED, + Enum_DEPRECATED, + String_DEPRECATED, + Array_DEPRECATED +}; + +// True types are cast, reintepreted, or parsed before being packed into gpu +// types when encoding into a texture. +enum class ECesiumMetadataPackedGpuType_DEPRECATED : uint8 { + None_DEPRECATED, + Uint8_DEPRECATED, + Float_DEPRECATED +}; + +/** + * The type of a metadata property in EXT_structural_metadata. + */ +UENUM(BlueprintType) +enum class ECesiumMetadataType : uint8 { + Invalid = 0, + Scalar = int(CesiumGltf::PropertyType::Scalar), + Vec2 = int(CesiumGltf::PropertyType::Vec2), + Vec3 = int(CesiumGltf::PropertyType::Vec3), + Vec4 = int(CesiumGltf::PropertyType::Vec4), + Mat2 = int(CesiumGltf::PropertyType::Mat2), + Mat3 = int(CesiumGltf::PropertyType::Mat3), + Mat4 = int(CesiumGltf::PropertyType::Mat4), + Boolean = int(CesiumGltf::PropertyType::Boolean), + Enum = int(CesiumGltf::PropertyType::Enum), + String = int(CesiumGltf::PropertyType::String), +}; + +/** + * The component type of a metadata property in EXT_structural_metadata. Only + * applicable if the property has a Scalar, VecN, or MatN type. + */ +UENUM(BlueprintType) +enum class ECesiumMetadataComponentType : uint8 { + None = 0, + Int8 = int(CesiumGltf::PropertyComponentType::Int8), + Uint8 = int(CesiumGltf::PropertyComponentType::Uint8), + Int16 = int(CesiumGltf::PropertyComponentType::Int16), + Uint16 = int(CesiumGltf::PropertyComponentType::Uint16), + Int32 = int(CesiumGltf::PropertyComponentType::Int32), + Uint32 = int(CesiumGltf::PropertyComponentType::Uint32), + Int64 = int(CesiumGltf::PropertyComponentType::Int64), + Uint64 = int(CesiumGltf::PropertyComponentType::Uint64), + Float32 = int(CesiumGltf::PropertyComponentType::Float32), + Float64 = int(CesiumGltf::PropertyComponentType::Float64), +}; + +/** + * Represents the true value type of a metadata value, akin to the property + * types in EXT_structural_metadata. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumMetadataValueType { + GENERATED_USTRUCT_BODY() + + FCesiumMetadataValueType() + : Type(ECesiumMetadataType::Invalid), + ComponentType(ECesiumMetadataComponentType::None), + bIsArray(false) {} + + FCesiumMetadataValueType( + ECesiumMetadataType InType, + ECesiumMetadataComponentType InComponentType, + bool IsArray = false) + : Type(InType), ComponentType(InComponentType), bIsArray(IsArray) {} + + /** + * The type of the metadata property or value. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + ECesiumMetadataType Type; + + /** + * The component of the metadata property or value. Only applies when the type + * is a Scalar, VecN, or MatN type. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + Meta = + (EditCondition = + "Type != ECesiumMetadataType::Invalid && Type != ECesiumMetadataType::Boolean && Type != ECesiumMetadataType::Enum && Type != ECesiumMetadataType::String")) + ECesiumMetadataComponentType ComponentType; + + /** + * Whether or not this represents an array containing elements of the + * specified types. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + bool bIsArray; + + inline bool operator==(const FCesiumMetadataValueType& ValueType) const { + return Type == ValueType.Type && ComponentType == ValueType.ComponentType && + bIsArray == ValueType.bIsArray; + } + + inline bool operator!=(const FCesiumMetadataValueType& ValueType) const { + return Type != ValueType.Type || ComponentType != ValueType.ComponentType || + bIsArray != ValueType.bIsArray; + } +}; + +template +static FCesiumMetadataValueType TypeToMetadataValueType() { + ECesiumMetadataType type; + ECesiumMetadataComponentType componentType; + bool isArray; + + if constexpr (CesiumGltf::IsMetadataArray::value) { + using ArrayType = typename CesiumGltf::MetadataArrayType::type; + type = + ECesiumMetadataType(CesiumGltf::TypeToPropertyType::value); + componentType = ECesiumMetadataComponentType( + CesiumGltf::TypeToPropertyType::component); + isArray = true; + } else { + type = ECesiumMetadataType(CesiumGltf::TypeToPropertyType::value); + componentType = ECesiumMetadataComponentType( + CesiumGltf::TypeToPropertyType::component); + isArray = false; + } + + return {type, componentType, isArray}; +} + +/** + * Gets the size in bytes of the represented metadata type. Returns 0 for enums + * and strings. + */ +static size_t GetMetadataTypeByteSize( + ECesiumMetadataType Type, + ECesiumMetadataComponentType ComponentType) { + size_t componentByteSize = 0; + if (ComponentType != ECesiumMetadataComponentType::None) + componentByteSize = CesiumGltf::getSizeOfComponentType( + CesiumGltf::PropertyComponentType(ComponentType)); + + size_t byteSize = componentByteSize; + switch (Type) { + case ECesiumMetadataType::Boolean: + byteSize = sizeof(bool); + break; + case ECesiumMetadataType::Scalar: + break; + case ECesiumMetadataType::Vec2: + byteSize *= 2; + break; + case ECesiumMetadataType::Vec3: + byteSize *= 3; + break; + case ECesiumMetadataType::Vec4: + byteSize *= 4; + break; + case ECesiumMetadataType::Mat2: + byteSize *= 4; + break; + case ECesiumMetadataType::Mat3: + byteSize *= 9; + break; + case ECesiumMetadataType::Mat4: + byteSize *= 16; + break; + default: + return 0; + } + + return byteSize; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumModelMetadata.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumModelMetadata.h new file mode 100644 index 0000000..b78cd66 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumModelMetadata.h @@ -0,0 +1,158 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumPropertyTable.h" +#include "CesiumPropertyTexture.h" + +#include "Containers/Array.h" +#include "Containers/Map.h" +#include "Containers/UnrealString.h" + +#include "CesiumModelMetadata.generated.h" + +namespace CesiumGltf { +struct ExtensionModelExtStructuralMetadata; +struct Model; +} // namespace CesiumGltf + +/** + * @brief A blueprint-accessible wrapper for metadata contained in a glTF model. + * Provides access to views of property tables, property textures, and property + * attributes available on the glTF. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumModelMetadata { + GENERATED_USTRUCT_BODY() + +public: + FCesiumModelMetadata() {} + + FCesiumModelMetadata( + const CesiumGltf::Model& InModel, + const CesiumGltf::ExtensionModelExtStructuralMetadata& Metadata); + +private: + TArray _propertyTables; + TArray _propertyTextures; + // TODO: property attributes + + friend class UCesiumModelMetadataBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumModelMetadataBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the model metadata of a glTF primitive component. If component is + * not a Cesium glTF primitive component, the returned metadata is empty. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Model|Metadata") + static const FCesiumModelMetadata& + GetModelMetadata(const UPrimitiveComponent* component); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * @brief Get all the feature tables for this model metadata. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Model", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "Use GetPropertyTables to get an array of property tables instead.")) + static const TMap + GetFeatureTables(UPARAM(ref) const FCesiumModelMetadata& ModelMetadata); + + /** + * @brief Get all the feature textures for this model metadata. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Model", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "Use GetPropertyTextures to get an array of property textures instead.")) + static const TMap + GetFeatureTextures(UPARAM(ref) const FCesiumModelMetadata& ModelMetadata); + + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * Gets an array of all the property tables for this model metadata. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Model|Metadata") + static const TArray& + GetPropertyTables(UPARAM(ref) const FCesiumModelMetadata& ModelMetadata); + + /** + * Gets the property table at the specified index for this model metadata. If + * the index is out-of-bounds, this returns an invalid property table. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Model|Metadata") + static const FCesiumPropertyTable& GetPropertyTable( + UPARAM(ref) const FCesiumModelMetadata& ModelMetadata, + const int64 Index); + + /** + * Gets the property table at the specified indices for this model metadata. + * An invalid property table will be returned for any out-of-bounds index. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Model|Metadata") + static const TArray GetPropertyTablesAtIndices( + UPARAM(ref) const FCesiumModelMetadata& ModelMetadata, + const TArray& Indices); + + /** + * Gets an array of all the property textures for this model metadata. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Model|Metadata") + static const TArray& + GetPropertyTextures(UPARAM(ref) const FCesiumModelMetadata& ModelMetadata); + + /** + * Gets the property table at the specified index for this model metadata. If + * the index is out-of-bounds, this returns an invalid property table. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Model|Metadata") + static const FCesiumPropertyTexture& GetPropertyTexture( + UPARAM(ref) const FCesiumModelMetadata& ModelMetadata, + const int64 Index); + + /** + * Gets an array of the property textures at the specified indices for this + * model metadata. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Model|Metadata") + static const TArray GetPropertyTexturesAtIndices( + UPARAM(ref) const FCesiumModelMetadata& ModelMetadata, + const TArray& Indices); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumOriginShiftComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumOriginShiftComponent.h new file mode 100644 index 0000000..cce1fc7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumOriginShiftComponent.h @@ -0,0 +1,151 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGlobeAnchoredActorComponent.h" +#include "CoreMinimal.h" +#include "CesiumOriginShiftComponent.generated.h" + +class UCesiumGlobeAnchorComponent; + +/** + * Indicates how to shift the origin as the Actor to which a + * CesiumOriginShiftComponent is attached moves. + */ +UENUM(BlueprintType) +enum class ECesiumOriginShiftMode : uint8 { + /** + * This component is disabled and will have no effect. + */ + Disabled, + + /** + * The origin of the CesiumGeoreference will be changed when the Actor enters + * a new sub-level, but it will otherwise not be modified as the Actor moves. + * Any objects that are not anchored to the globe with a + * CesiumGlobeAnchorComponent will appear to move when the Actor enters a + * sub-level. + */ + SwitchSubLevelsOnly, + + /** + * The origin of the CesiumGeoreference will change as the Actor moves in + * order to maintain small, precise coordinate values near the Actor, as well + * as to keep the globe's local "up" direction aligned with the +Z axis. Any + * objects that are not anchored to the globe with a + * CesiumGlobeAnchorComponent will appear to move whenever the origin changes. + * + * When using this mode, all Cesium3DTileset instances as well as any Actors + * with a CesiumGlobeAnchorComponent need to be marked Movable, because these + * objects _will_ be moved when the origin is shifted. + */ + ChangeCesiumGeoreference, +}; + +/** + * Automatically shifts the origin of the Unreal world coordinate system as the + * object to which this component is attached moves. This improves rendering + * precision by keeping coordinate values small, and can also help world + * building by keeping the globe's local up direction aligned with the +Z axis. + * + * This component is typically attached to a camera or Pawn. By default, it only + * shifts the origin when entering a new sub-level (a Level Instance Actor with + * a CesiumSubLevelComponent attached to it). By changing the Mode and Distance + * properties, it can also shift the origin continually when in between + * sub-levels (or when not using sub-levels at all). + * + * It is essential to add a CesiumGlobeAnchorComponent to all other non-globe + * aware objects in the level; otherwise, they will appear to move when the + * origin is shifted. It is not necessary to anchor objects that are in + * sub-levels, because the origin remains constant for the entire time that a + * sub-level is active. + */ +UCLASS(ClassGroup = "Cesium", Meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumOriginShiftComponent + : public UCesiumGlobeAnchoredActorComponent { + GENERATED_BODY() + +#pragma region Properties +private: + /** + * Indicates how to shift the origin as the Actor to which this component is + * attached moves. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetMode, + BlueprintSetter = SetMode, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + ECesiumOriginShiftMode Mode = ECesiumOriginShiftMode::SwitchSubLevelsOnly; + + /** + * The maximum distance between the origin of the Unreal coordinate system and + * the Actor to which this component is attached. When this distance is + * exceeded, the origin is shifted to bring it close to the Actor. This + * property is ignored if the Mode property is set to "Disabled" or "Switch + * Sub Levels Only". + * + * When the value of this property is 0.0, the origin is shifted continuously. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetDistance, + BlueprintSetter = SetDistance, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + double Distance = 0.0; +#pragma endregion + +#pragma region Property Accessors +public: + /** + * Gets a value indicating how to shift the origin as the Actor to which this + * component is attached moves. + */ + UFUNCTION(BlueprintGetter) + ECesiumOriginShiftMode GetMode() const; + + /** + * Sets a value indicating how to shift the origin as the Actor to which this + * component is attached moves. + */ + UFUNCTION(BlueprintSetter) + void SetMode(ECesiumOriginShiftMode NewMode); + + /** + * Gets the maximum distance between the origin of the Unreal coordinate + * system and the Actor to which this component is attached. When this + * distance is exceeded, the origin is shifted to bring it close to the Actor. + * This property is ignored if the Mode property is set to "Disabled" or + * "Switch Sub Levels Only". + * + * When the value of this property is 0.0, the origin is shifted continuously. + */ + UFUNCTION(BlueprintGetter) + double GetDistance() const; + + /** + * Sets the maximum distance between the origin of the Unreal coordinate + * system and the Actor to which this component is attached. When this + * distance is exceeded, the origin is shifted to bring it close to the Actor. + * This property is ignored if the Mode property is set to "Disabled" or + * "Switch Sub Levels Only". + * + * When the value of this property is 0.0, the origin is shifted continuously. + */ + UFUNCTION(BlueprintSetter) + void SetDistance(double NewDistance); +#pragma endregion + +public: + UCesiumOriginShiftComponent(); + +protected: + virtual void TickComponent( + float DeltaTime, + ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPointCloudShading.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPointCloudShading.h new file mode 100644 index 0000000..a7a1689 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPointCloudShading.h @@ -0,0 +1,74 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" + +#include "CesiumPointCloudShading.generated.h" + +/** + * Options for adjusting how point clouds are rendered using 3D Tiles. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumPointCloudShading { + GENERATED_USTRUCT_BODY() + + /** + * Whether or not to perform point attenuation. Attenuation controls the size + * of the points rendered based on the geometric error of their tile. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + bool Attenuation = false; + + /** + * The scale to be applied to the tile's geometric error before it is used + * to compute attenuation. Larger values will result in larger points. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (ClampMin = 0.0)) + float GeometricErrorScale = 1.0f; + + /** + * The maximum point attenuation in pixels. If this is zero, the + * Cesium3DTileset's maximumScreenSpaceError will be used as the maximum point + * attenuation. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (ClampMin = 0.0)) + float MaximumAttenuation = 0.0f; + + /** + * The average base resolution for the dataset in meters. For example, + * a base resolution of 0.05 assumes an original capture resolution of + * 5 centimeters between neighboring points. + * + * This is used in place of geometric error when the tile's geometric error is + * 0. If this value is zero, each tile with a geometric error of 0 will have + * its geometric error approximated instead. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (ClampMin = 0.0)) + float BaseResolution = 0.0f; + + bool + operator==(const FCesiumPointCloudShading& OtherPointCloudShading) const { + return Attenuation == OtherPointCloudShading.Attenuation && + GeometricErrorScale == OtherPointCloudShading.GeometricErrorScale && + MaximumAttenuation == OtherPointCloudShading.MaximumAttenuation && + BaseResolution == OtherPointCloudShading.BaseResolution; + } + + bool + operator!=(const FCesiumPointCloudShading& OtherPointCloudShading) const { + return !(*this == OtherPointCloudShading); + } +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPolygonRasterOverlay.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPolygonRasterOverlay.h new file mode 100644 index 0000000..728ecc2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPolygonRasterOverlay.h @@ -0,0 +1,71 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumRasterOverlay.h" +#include "CoreMinimal.h" +#include "CesiumPolygonRasterOverlay.generated.h" + +class ACesiumCartographicPolygon; + +namespace Cesium3DTilesSelection { +class RasterizedPolygonsTileExcluder; +} + +/** + * A raster overlay that rasterizes polygons and drapes them over the tileset. + * This is useful for clipping out parts of a tileset, for adding a water effect + * in an area, and for many other purposes. + */ +UCLASS(ClassGroup = (Cesium), meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumPolygonRasterOverlay + : public UCesiumRasterOverlay { + GENERATED_BODY() + +public: + UCesiumPolygonRasterOverlay(); + + /** + * The polygons to rasterize for this overlay. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + TArray> Polygons; + + /** + * Whether to invert the selection specified by the polygons. + * + * If this is true, only the areas outside of all the polygons will be + * rasterized. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + bool InvertSelection = false; + + /** + * Whether tiles that fall entirely within the rasterized selection should be + * excluded from loading and rendering. For better performance, this should be + * enabled when this overlay will be used for clipping. But when this overlay + * is used for other effects, this option should be disabled to avoid missing + * tiles. + * + * Note that if InvertSelection is true, this will cull tiles that are + * outside of all the polygons. If it is false, this will cull tiles that are + * completely inside at least one polygon. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + bool ExcludeSelectedTiles = true; + +protected: + virtual std::unique_ptr CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options = {}) override; + + virtual void OnAdd( + Cesium3DTilesSelection::Tileset* pTileset, + CesiumRasterOverlays::RasterOverlay* pOverlay) override; + virtual void OnRemove( + Cesium3DTilesSelection::Tileset* pTileset, + CesiumRasterOverlays::RasterOverlay* pOverlay) override; + +private: + std::shared_ptr + _pExcluder; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPrimitiveFeatures.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPrimitiveFeatures.h new file mode 100644 index 0000000..9b079cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPrimitiveFeatures.h @@ -0,0 +1,196 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumFeatureIdSet.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include + +#include "CesiumPrimitiveFeatures.generated.h" + +namespace CesiumGltf { +struct ExtensionExtMeshFeatures; +struct ExtensionExtInstanceFeatures; +} // namespace CesiumGltf + +/** + * A Blueprint-accessible wrapper for a glTF Primitive's mesh features. It holds + * views of the feature ID sets associated with this primitive. The collection + * of features in the EXT_instance_features is very similar to that in + * EXT_mesh_features, so FCesiumPrimitiveFeatures can be used to handle those + * features too. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumPrimitiveFeatures { + GENERATED_USTRUCT_BODY() + +public: + /** + * Constructs an empty primitive features instance. + */ + FCesiumPrimitiveFeatures() : _vertexCount(0) {} + + /** + * Constructs a primitive features instance. + * + * @param Model The model that contains the EXT_mesh_features extension + * @param Primitive The mesh primitive that stores EXT_mesh_features + * extension + * @param Features The EXT_mesh_features of the glTF mesh primitive + */ + FCesiumPrimitiveFeatures( + const CesiumGltf::Model& Model, + const CesiumGltf::MeshPrimitive& Primitive, + const CesiumGltf::ExtensionExtMeshFeatures& Features); + + /** + * Constructs an instance feature object. + * + * @param Model The model that contains the EXT_instance_features extension + * @param Node The node that stores EXT_instance_features + * extension + * @param InstanceFeatures The EXT_Instance_features of the glTF mesh + * primitive + */ + FCesiumPrimitiveFeatures( + const CesiumGltf::Model& Model, + const CesiumGltf::Node& Node, + const CesiumGltf::ExtensionExtInstanceFeatures& InstanceFeatures); + +private: + TArray _featureIdSets; + CesiumGltf::IndexAccessorType _indexAccessor; + // Vertex count = 0 and _primitiveMode = -1 indicates instance features + int64_t _vertexCount; + int32_t _primitiveMode; + + friend class UCesiumPrimitiveFeaturesBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumPrimitiveFeaturesBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the primitive features of a glTF primitive component. If `component` + * is not a Cesium glTF primitive component, the returned features are empty. + * + * @param component The component to get the features of. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Primitive|Features") + static const FCesiumPrimitiveFeatures& + GetPrimitiveFeatures(const UPrimitiveComponent* component); + + /** + * Gets all the feature ID sets that are associated with the + * primitive. + * + * @param PrimitiveFeatures The primitive. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Primitive|Features") + static const TArray& + GetFeatureIDSets(UPARAM(ref) + const FCesiumPrimitiveFeatures& PrimitiveFeatures); + + /** + * Gets all the feature ID sets of the given type. + * + * @param PrimitiveFeatures The primitive. + * @param Type The type of feature ID set to obtain. If the primitive has no + * sets of that type, the returned array will be empty. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Primitive|Features") + static const TArray GetFeatureIDSetsOfType( + UPARAM(ref) const FCesiumPrimitiveFeatures& PrimitiveFeatures, + ECesiumFeatureIdSetType Type); + + /** + * Get the number of vertices in the primitive. + * + * @param PrimitiveFeatures The primitive. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Primitive|Features") + static int64 + GetVertexCount(UPARAM(ref) const FCesiumPrimitiveFeatures& PrimitiveFeatures); + + /** + * Gets the index of the first vertex that makes up a given face of this + * primitive. + * + * @param PrimitiveFeatures The primitive. + * @param FaceIndex The index of the face. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Primitive|Features") + static int64 GetFirstVertexFromFace( + UPARAM(ref) const FCesiumPrimitiveFeatures& PrimitiveFeatures, + int64 FaceIndex); + + /** + * Gets the feature ID associated with the given face. + * + * @param PrimitiveFeatures The primitive. + * @param FaceIndex The index of the face to obtain the feature ID of. + * @param FeatureIDSetIndex A primitive may have multiple feature ID sets, so + * this allows a feature ID set to be specified by index. This value should + * index into the array of CesiumFeatureIdSets in the CesiumPrimitiveFeatures. + * If the specified feature ID set index is invalid, this returns -1. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Primitive|Features") + static int64 GetFeatureIDFromFace( + UPARAM(ref) const FCesiumPrimitiveFeatures& PrimitiveFeatures, + int64 FaceIndex, + int64 FeatureIDSetIndex = 0); + + /** + * Gets the feature ID associated with the instance at the given index. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Primitive|Features") + static int64 GetFeatureIDFromInstance( + UPARAM(ref) const FCesiumPrimitiveFeatures& InstanceFeatures, + int64 InstanceIndex, + int64 FeatureIDSetIndex = 0); + + /** + * Gets the feature ID from the given line trace hit, assuming it + * has hit a glTF primitive component containing this CesiumPrimitiveFeatures. + * + * @param PrimitiveFeatures The primitive. + * @param Hit The line trace hit to try to obtain a feature ID from. + * @param FeatureIDSetIndex A primitive may have multiple feature ID sets, so + * this allows a feature ID set to be specified by index. This value should + * index into the array of CesiumFeatureIdSets in the CesiumPrimitiveFeatures. + * If the specified feature ID set index is invalid, this returns -1. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Primitive|Features") + static int64 GetFeatureIDFromHit( + UPARAM(ref) const FCesiumPrimitiveFeatures& PrimitiveFeatures, + const FHitResult& Hit, + int64 FeatureIDSetIndex = 0); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPrimitiveMetadata.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPrimitiveMetadata.h new file mode 100644 index 0000000..b8b76af --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPrimitiveMetadata.h @@ -0,0 +1,91 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" + +#include "CesiumPrimitiveMetadata.generated.h" + +namespace CesiumGltf { +struct Model; +struct MeshPrimitive; +struct ExtensionModelExtStructuralMetadata; +struct ExtensionMeshPrimitiveExtStructuralMetadata; +} // namespace CesiumGltf + +/** + * A Blueprint-accessible wrapper for a glTF Primitive's EXT_structural_metadata + * extension. It holds the indices of the property textures / attributes + * associated with this primitive, which index into the respective arrays in the + * model's EXT_structural_metadata extension. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumPrimitiveMetadata { + GENERATED_USTRUCT_BODY() + +public: + /** + * Construct an empty primitive metadata. + */ + FCesiumPrimitiveMetadata() {} + + /** + * Constructs a primitive metadata instance. + * + * @param Primitive The mesh primitive containing the EXT_structural_metadata + * extension + * @param Metadata The EXT_structural_metadata of the glTF mesh primitive. + */ + FCesiumPrimitiveMetadata( + const CesiumGltf::MeshPrimitive& Primitive, + const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata& Metadata); + +private: + TArray _propertyTextureIndices; + TArray _propertyAttributeIndices; + + friend class UCesiumPrimitiveMetadataBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumPrimitiveMetadataBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the primitive metadata of a glTF primitive component. If component is + * not a Cesium glTF primitive component, the returned metadata is empty. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Primitive|Metadata") + static const FCesiumPrimitiveMetadata& + GetPrimitiveMetadata(const UPrimitiveComponent* component); + + /** + * Get the indices of the property textures that are associated with the + * primitive. This can be used to retrieve the actual property textures from + * the model's FCesiumModelMetadata. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Primitive|Metadata") + static const TArray& GetPropertyTextureIndices( + UPARAM(ref) const FCesiumPrimitiveMetadata& PrimitiveMetadata); + + /** + * Get the indices of the property attributes that are associated with the + * primitive. This can be used to retrieve the actual property attributes from + * the model's FCesiumModelMetadata. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Primitive|Metadata") + static const TArray& GetPropertyAttributeIndices( + UPARAM(ref) const FCesiumPrimitiveMetadata& PrimitiveMetadata); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyArray.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyArray.h new file mode 100644 index 0000000..dab0d63 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyArray.h @@ -0,0 +1,155 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/PropertyArrayView.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumMetadataValueType.h" +#include "UObject/ObjectMacros.h" +#include +#include "CesiumPropertyArray.generated.h" + +/** + * A Blueprint-accessible wrapper for an array property in glTF metadata. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumPropertyArray { + GENERATED_USTRUCT_BODY() + +private: +#pragma region ArrayType + template + using ArrayPropertyView = CesiumGltf::PropertyArrayView; + + using ArrayType = swl::variant< + ArrayPropertyView, + ArrayPropertyView, + ArrayPropertyView, + ArrayPropertyView, + ArrayPropertyView, + ArrayPropertyView, + ArrayPropertyView, + ArrayPropertyView, + ArrayPropertyView, + ArrayPropertyView, + ArrayPropertyView, + ArrayPropertyView, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>, + ArrayPropertyView>>; +#pragma endregion + +public: + /** + * Constructs an empty array instance with an unknown element type. + */ + FCesiumPropertyArray() : _value(), _elementType() {} + + /** + * Constructs an array instance. + * @param value The property array view that will be stored in this struct + */ + template + FCesiumPropertyArray(CesiumGltf::PropertyArrayCopy&& value) + : _value(), _elementType(), _storage() { + this->_value = std::move(value).toViewAndExternalBuffer(this->_storage); + ECesiumMetadataType type = + ECesiumMetadataType(CesiumGltf::TypeToPropertyType::value); + ECesiumMetadataComponentType componentType = ECesiumMetadataComponentType( + CesiumGltf::TypeToPropertyType::component); + bool isArray = false; + + _elementType = {type, componentType, isArray}; + } + + template + FCesiumPropertyArray(const CesiumGltf::PropertyArrayCopy& value) + : FCesiumPropertyArray(CesiumGltf::PropertyArrayCopy(value)) {} + + template + FCesiumPropertyArray(const CesiumGltf::PropertyArrayView& value) + : _value(value), _elementType() { + ECesiumMetadataType type = + ECesiumMetadataType(CesiumGltf::TypeToPropertyType::value); + ECesiumMetadataComponentType componentType = ECesiumMetadataComponentType( + CesiumGltf::TypeToPropertyType::component); + bool isArray = false; + + _elementType = {type, componentType, isArray}; + } + + FCesiumPropertyArray(FCesiumPropertyArray&& rhs); + FCesiumPropertyArray& operator=(FCesiumPropertyArray&& rhs); + FCesiumPropertyArray(const FCesiumPropertyArray& rhs); + FCesiumPropertyArray& operator=(const FCesiumPropertyArray& rhs); + +private: + template + static bool + holdsArrayAlternative(const swl::variant& variant) { + return swl::holds_alternative>(variant); + } + + ArrayType _value; + FCesiumMetadataValueType _elementType; + std::vector _storage; + + friend class UCesiumPropertyArrayBlueprintLibrary; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyArrayBlueprintLibrary.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyArrayBlueprintLibrary.h new file mode 100644 index 0000000..1612fcd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyArrayBlueprintLibrary.h @@ -0,0 +1,377 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumMetadataValue.h" +#include "CesiumPropertyArray.h" +#include "CesiumPropertyArrayBlueprintLibrary.generated.h" + +/** + * Blueprint library functions for acting on an array property in + * EXT_structural_metadata. + */ +UCLASS() +class CESIUMRUNTIME_API UCesiumPropertyArrayBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the best-fitting Blueprints type for the elements of this array. + * + * @param array The array. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyArray") + static ECesiumMetadataBlueprintType + GetElementBlueprintType(UPARAM(ref) const FCesiumPropertyArray& array); + + /** + * Gets the true value type of the elements in the array. Many of these types + * are not accessible from Blueprints, but can be converted to a + * Blueprint-accessible type. + * + * @param array The array. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyArray") + static FCesiumMetadataValueType + GetElementValueType(UPARAM(ref) const FCesiumPropertyArray& array); + + /** + * Gets the number of elements in the array. Returns 0 if the elements have + * an unknown type. + * + * @param Array The array. + * @return The number of elements in the array. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyArray") + static int64 GetArraySize(UPARAM(ref) const FCesiumPropertyArray& Array); + + /** + * Retrieves an element from the array as a FCesiumMetadataValue. The value + * can then be retrieved as a specific Blueprints type. + * + * If the index is out-of-bounds, this returns a bogus FCesiumMetadataValue of + * an unknown type. + * + * @param Array The array. + * @param Index The index of the array element to retrieve. + * @return The element as a FCesiumMetadataValue. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyArray") + static FCesiumMetadataValue + GetValue(UPARAM(ref) const FCesiumPropertyArray& Array, int64 Index); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Gets the best-fitting Blueprints type for the elements of this array. + * + * @param array The array. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = "Use GetElementBlueprintType instead.")) + static ECesiumMetadataBlueprintType + GetBlueprintComponentType(UPARAM(ref) const FCesiumPropertyArray& array); + + /** + * Gets true type of the elements in the array. Many of these types are not + * accessible from Blueprints, but can be converted to a Blueprint-accessible + * type. + * + * @param array The array. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "CesiumMetadataTrueType is deprecated. Use GetElementValueType instead.")) + static ECesiumMetadataTrueType_DEPRECATED + GetTrueComponentType(UPARAM(ref) const FCesiumPropertyArray& array); + + /** + * Gets the number of elements in the array. Returns 0 if the elements have + * an unknown type. + * + * @param Array The array. + * @return The number of elements in the array. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = "Use GetArraySize instead.")) + static int64 GetSize(UPARAM(ref) const FCesiumPropertyArray& Array); + + /** + * Retrieves an element from the array and attempts to convert it to a Boolean + * value. + * + * If the element is boolean, it is returned directly. + * + * If the element is numeric, zero is converted to false, while any other + * value is converted to true. + * + * If the element is a string, "0", "false", and "no" (case-insensitive) are + * converted to false, while "1", "true", and "yes" are converted to true. + * All other strings, including strings that can be converted to numbers, + * will return the default value. + * + * Other types of elements will return the default value. + * + * @param Array The array. + * @param Index The index of the array element to retrieve. + * @param DefaultValue The default value to use if the index is invalid + * or the element's value cannot be converted. + * @return The element value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "GetBoolean is deprecated for metadata arrays. Use GetValue instead.")) + static bool GetBoolean( + UPARAM(ref) const FCesiumPropertyArray& Array, + int64 Index, + bool DefaultValue = false); + + /** + * Retrieves an element from the array and attempts to convert it to an + * unsigned 8-bit integer value. + * + * If the element is an integer and between 0 and 255, it is returned + * directly. + * + * If the element is a floating-point number, it is truncated (rounded + * toward zero). + * + * If the element is a boolean, 0 is returned for false and 1 for true. + * + * If the element is a string and the entire string can be parsed as an + * integer between 0 and 255, the parsed value is returned. The string is + * parsed in a locale-independent way and does not support use of a comma or + * other character to group digits. + * + * Otherwise, the default value is returned. + * + * @param Array The array. + * @param Index The index of the array element to retrieve. + * @param DefaultValue The default value to use if the index is invalid + * or the element's value cannot be converted. + * @return The element value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "GetByte is deprecated on arrays. Use GetValue instead.")) + static uint8 GetByte( + UPARAM(ref) const FCesiumPropertyArray& Array, + int64 Index, + uint8 DefaultValue = 0); + + /** + * Retrieves an element from the array and attempts to convert it to a signed + * 32-bit integer value. + * + * If the element is an integer and between -2,147,483,647 and 2,147,483,647, + * it is returned directly. + * + * If the element is a floating-point number, it is truncated (rounded + * toward zero). + * + * If the element is a boolean, 0 is returned for false and 1 for true. + * + * If the element is a string and the entire string can be parsed as an + * integer in the valid range, the parsed value is returned. If it can be + * parsed as a floating-point number, the parsed value is truncated (rounded + * toward zero). In either case, the string is parsed in a locale-independent + * way and does not support use of a comma or other character to group digits. + * + * Otherwise, the default value is returned. + * + * @param Array The array. + * @param Index The index of the array element to retrieve. + * @param DefaultValue The default value to use if the index is invalid + * or the element's value cannot be converted. + * @return The element value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "GetInteger is deprecated for metadata arrays. Use GetValue instead.")) + static int32 GetInteger( + UPARAM(ref) const FCesiumPropertyArray& Array, + int64 Index, + int32 DefaultValue = 0); + + /** + * This function is deprecated. Use Cesium > Metadata > Property Array > + * GetValue instead. + * + * Retrieves an element from the array and attempts to convert it to a signed + * 64-bit integer value. + * + * If the element is an integer and between -2^63-1 and 2^63-1, it is returned + * directly. + * + * If the element is a floating-point number, it is truncated (rounded + * toward zero). + * + * If the element is a boolean, 0 is returned for false and 1 for true. + * + * If the element is a string and the entire string can be parsed as an + * integer in the valid range, the parsed value is returned. If it can be + * parsed as a floating-point number, the parsed value is truncated (rounded + * toward zero). In either case, the string is parsed in a locale-independent + * way and does not support use of a comma or other character to group digits. + * + * Otherwise, the default value is returned. + * + * @param Array The array. + * @param Index The index of the array element to retrieve. + * @param DefaultValue The default value to use if the index is invalid + * or the element's value cannot be converted. + * @return The element value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "GetInteger64 is deprecated for metadata arrays. Use GetValue instead.")) + static int64 GetInteger64( + UPARAM(ref) const FCesiumPropertyArray& Array, + int64 Index, + int64 DefaultValue = 0); + + /** + * Retrieves an element from the array and attempts to convert it to a 32-bit + * floating-point value. + * + * If the element is a single-precision floating-point number, is is returned. + * + * If the element is an integer or double-precision floating-point number, + * it is converted to the closest representable single-precision + * floating-point number. + * + * If the element is a boolean, 0.0 is returned for false and 1.0 for true. + * + * If the element is a string and the entire string can be parsed as a + * number, the parsed value is returned. The string is parsed in a + * locale-independent way and does not support use of a comma or other + * character to group digits. + * + * Otherwise, the default value is returned. + * + * @param array The array. + * @param index The index of the array element to retrieve. + * @param DefaultValue The default value to use if the index is invalid + * or the element's value cannot be converted. + * @return The element value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "GetFloat is deprecated for metadata arrays. Use GetValue instead.")) + static float GetFloat( + UPARAM(ref) const FCesiumPropertyArray& array, + int64 index, + float DefaultValue = 0.0f); + + /** + * Retrieves an element from the array and attempts to convert it to a 64-bit + * floating-point value. + * + * If the element is a single- or double-precision floating-point number, is + * is returned. + * + * If the element is an integer, it is converted to the closest representable + * double-precision floating-point number. + * + * If the element is a boolean, 0.0 is returned for false and 1.0 for true. + * + * If the element is a string and the entire string can be parsed as a + * number, the parsed value is returned. The string is parsed in a + * locale-independent way and does not support use of a comma or other + * character to group digits. + * + * Otherwise, the default value is returned. + * + * @param array The array. + * @param index The index of the array element to retrieve. + * @param DefaultValue The default value to use if the index is invalid + * or the element's value cannot be converted. + * @return The element value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "GetFloat64 is deprecated for metadata arrays. Use GetValue instead.")) + static double GetFloat64( + UPARAM(ref) const FCesiumPropertyArray& array, + int64 index, + double DefaultValue); + + /** + * Retrieves an element from the array and attempts to convert it to a string + * value. + * + * Numeric elements are converted to a string with `FString::Format`, which + * uses the current locale. + * + * Boolean elements are converted to "true" or "false". + * + * String elements are returned directly. + * + * @param Array The array. + * @param Index The index of the array element to retrieve. + * @param DefaultValue The default value to use if the index is invalid + * or the element's value cannot be converted. + * @return The element value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "GetString is deprecated for metadata arrays. Use GetValue instead.")) + static FString GetString( + UPARAM(ref) const FCesiumPropertyArray& Array, + int64 Index, + const FString& DefaultValue = ""); + + PRAGMA_ENABLE_DEPRECATION_WARNINGS +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyTable.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyTable.h new file mode 100644 index 0000000..9cd0255 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyTable.h @@ -0,0 +1,204 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumMetadataValue.h" +#include "CesiumPropertyTableProperty.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include "CesiumPropertyTable.generated.h" + +namespace CesiumGltf { +struct Model; +struct PropertyTable; +} // namespace CesiumGltf + +/** + * @brief Reports the status of a FCesiumPropertyTable. If the property table + * cannot be accessed, this briefly indicates why. + */ +UENUM(BlueprintType) +enum class ECesiumPropertyTableStatus : uint8 { + /* The property table is valid. */ + Valid = 0, + /* The property table instance was not initialized from an actual glTF + property table. */ + ErrorInvalidPropertyTable, + /* The property table's class could be found in the schema of the metadata + extension. */ + ErrorInvalidPropertyTableClass +}; + +/** + * A Blueprint-accessible wrapper for a glTF property table. A property table is + * a collection of properties for the features in a mesh. It knows how to + * look up the metadata values associated with a given feature ID. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumPropertyTable { + GENERATED_USTRUCT_BODY() + +public: + /** + * Construct an empty property table instance. + */ + FCesiumPropertyTable() + : _status(ECesiumPropertyTableStatus::ErrorInvalidPropertyTable){}; + + /** + * Constructs a property table from a glTF Property Table. + * + * @param Model The model that stores EXT_structural_metadata. + * @param PropertyTable The target property table. + */ + FCesiumPropertyTable( + const CesiumGltf::Model& Model, + const CesiumGltf::PropertyTable& PropertyTable); + + /** + * Gets the name of the metadata class that this property table conforms to. + */ + FString getClassName() const { return _className; } + +private: + ECesiumPropertyTableStatus _status; + FString _name; + FString _className; + + int64 _count; + TMap _properties; + + friend class UCesiumPropertyTableBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumPropertyTableBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the status of the property table. If an error occurred while parsing + * the property table from the glTF extension, this briefly conveys why. + * + * @param PropertyTable The property table. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTable") + static ECesiumPropertyTableStatus + GetPropertyTableStatus(UPARAM(ref) const FCesiumPropertyTable& PropertyTable); + + /** + * Gets the name of the property table. If no name was specified in the glTF + * extension, this returns an empty string. + * + * @param PropertyTable The property table. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTable") + static const FString& + GetPropertyTableName(UPARAM(ref) const FCesiumPropertyTable& PropertyTable); + + /** + * Gets the number of values each property in the table is expected to have. + * If an error occurred while parsing the property table, this returns zero. + * + * @param PropertyTable The property table. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTable") + static int64 + GetPropertyTableCount(UPARAM(ref) const FCesiumPropertyTable& PropertyTable); + + /** + * Gets all the properties of the property table, mapped by property name. + * + * @param PropertyTable The property table. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTable") + static const TMap& + GetProperties(UPARAM(ref) const FCesiumPropertyTable& PropertyTable); + + /** + * Gets the names of the properties in this property table. + * + * @param PropertyTable The property table. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTable") + static const TArray + GetPropertyNames(UPARAM(ref) const FCesiumPropertyTable& PropertyTable); + + /** + * Retrieve a FCesiumPropertyTableProperty by name. If the property table + * does not contain a property with that name, this returns an invalid + * FCesiumPropertyTableProperty. + * + * @param PropertyTable The property table. + * @param PropertyName The name of the property to find. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTable") + static const FCesiumPropertyTableProperty& FindProperty( + UPARAM(ref) const FCesiumPropertyTable& PropertyTable, + const FString& PropertyName); + + /** + * Gets all of the property values for a given feature, mapped by property + * name. This will only include values from valid property table properties. + * + * If the feature ID is out-of-bounds, the returned map will be empty. + * + * @param PropertyTable The property table. + * @param FeatureID The ID of the feature. + * @return The property values mapped by property name. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTable") + static TMap GetMetadataValuesForFeature( + UPARAM(ref) const FCesiumPropertyTable& PropertyTable, + int64 FeatureID); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Gets all of the property values for a given feature as strings, mapped by + * property name. This will only include values from valid property table + * properties. + * + * Array properties cannot be converted to strings, so empty strings + * will be returned for their values. + * + * If the feature ID is out-of-bounds, the returned map will be empty. + * + * @param PropertyTable The property table. + * @param FeatureID The ID of the feature. + * @return The property values as strings mapped by property name. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTable", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "Use GetValuesAsStrings to convert the output of GetMetadataValuesForFeature instead.")) + static TMap GetMetadataValuesForFeatureAsStrings( + UPARAM(ref) const FCesiumPropertyTable& PropertyTable, + int64 FeatureID); + PRAGMA_ENABLE_DEPRECATION_WARNINGS +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyTableProperty.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyTableProperty.h new file mode 100644 index 0000000..d9e91b3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyTableProperty.h @@ -0,0 +1,1152 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/PropertyTablePropertyView.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumMetadataValue.h" +#include "CesiumMetadataValueType.h" +#include "CesiumPropertyArray.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include +#include +#include +#include +#include "CesiumPropertyTableProperty.generated.h" + +/** + * @brief Reports the status of a FCesiumPropertyTableProperty. If the property + * table property cannot be accessed, this briefly indicates why. + */ +UENUM(BlueprintType) +enum class ECesiumPropertyTablePropertyStatus : uint8 { + /* The property table property is valid. */ + Valid = 0, + /* The property table property is empty but has a specified default value. */ + EmptyPropertyWithDefault, + /* The property table property does not exist in the glTF, or the property + definition itself contains errors. */ + ErrorInvalidProperty, + /* The data associated with the property table property is malformed and + cannot be retrieved. */ + ErrorInvalidPropertyData +}; + +/** + * A Blueprint-accessible wrapper for a glTF property table property in + * EXT_structural_metadata. A property has a specific type, such as int64 scalar + * or string, and values of that type that can be accessed with primitive + * feature IDs from EXT_mesh_features. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumPropertyTableProperty { + GENERATED_USTRUCT_BODY() + +private: +public: + /** + * Construct an invalid property with an unknown type. + */ + FCesiumPropertyTableProperty() + : _status(ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty), + _property(), + _valueType(), + _normalized(false) {} + + /** + * Construct a wrapper for the property table property view. + * + * @param Property The PropertyTablePropertyView to be stored in this struct. + */ + template + FCesiumPropertyTableProperty( + const CesiumGltf::PropertyTablePropertyView& Property) + : _status(ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty), + _property(Property), + _valueType(), + _normalized(Normalized) { + switch (Property.status()) { + case CesiumGltf::PropertyTablePropertyViewStatus::Valid: + _status = ECesiumPropertyTablePropertyStatus::Valid; + break; + case CesiumGltf::PropertyTablePropertyViewStatus::EmptyPropertyWithDefault: + _status = ECesiumPropertyTablePropertyStatus::EmptyPropertyWithDefault; + break; + case CesiumGltf::PropertyTablePropertyViewStatus::ErrorInvalidPropertyTable: + case CesiumGltf::PropertyTablePropertyViewStatus::ErrorNonexistentProperty: + case CesiumGltf::PropertyTablePropertyViewStatus::ErrorTypeMismatch: + case CesiumGltf::PropertyTablePropertyViewStatus:: + ErrorComponentTypeMismatch: + case CesiumGltf::PropertyTablePropertyViewStatus::ErrorArrayTypeMismatch: + case CesiumGltf::PropertyTablePropertyViewStatus::ErrorInvalidNormalization: + case CesiumGltf::PropertyTablePropertyViewStatus:: + ErrorNormalizationMismatch: + case CesiumGltf::PropertyTablePropertyViewStatus::ErrorInvalidOffset: + case CesiumGltf::PropertyTablePropertyViewStatus::ErrorInvalidScale: + case CesiumGltf::PropertyTablePropertyViewStatus::ErrorInvalidMax: + case CesiumGltf::PropertyTablePropertyViewStatus::ErrorInvalidMin: + case CesiumGltf::PropertyTablePropertyViewStatus::ErrorInvalidNoDataValue: + case CesiumGltf::PropertyTablePropertyViewStatus::ErrorInvalidDefaultValue: + // The status was already set in the initializer list. + return; + default: + _status = ECesiumPropertyTablePropertyStatus::ErrorInvalidPropertyData; + return; + } + + _valueType = TypeToMetadataValueType(); + _normalized = Normalized; + } + +private: + ECesiumPropertyTablePropertyStatus _status; + + std::any _property; + + FCesiumMetadataValueType _valueType; + bool _normalized; + + friend class UCesiumPropertyTablePropertyBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumPropertyTablePropertyBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the status of the property table property. If this property table + * property is invalid in any way, this will briefly indicate why. + * + * @param Property The property table property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static ECesiumPropertyTablePropertyStatus GetPropertyTablePropertyStatus( + UPARAM(ref) const FCesiumPropertyTableProperty& Property); + + /** + * Gets the best-fitting type for the property that is accessible from + * Blueprints. For the most precise representation of the values possible in + * Blueprints, you should retrieve it using this type. + * + * @param Property The property table property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static ECesiumMetadataBlueprintType + GetBlueprintType(UPARAM(ref) const FCesiumPropertyTableProperty& Property); + + /** + * Gets the best-fitting Blueprints type for the elements in this property's + * array values. If the given property does not contain array values, this + * returns None. + * + * @param Property The property table property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static ECesiumMetadataBlueprintType GetArrayElementBlueprintType( + UPARAM(ref) const FCesiumPropertyTableProperty& Property); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Gets the best-fitting Blueprints type for the elements in this property's + * array values. If the given property does not contain array values, this + * returns None. + * + * @param Property The property table property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = "Use GetArrayElementBlueprintType instead.")) + static ECesiumMetadataBlueprintType + GetBlueprintComponentType(UPARAM(ref) + const FCesiumPropertyTableProperty& Property); + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * Gets the type of the metadata value as defined in the + * EXT_structural_metadata extension. Many of these types are not accessible + * from Blueprints, but can be converted to a Blueprint-accessible type. + * + * @param Property The property table property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FCesiumMetadataValueType + GetValueType(UPARAM(ref) const FCesiumPropertyTableProperty& Property); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Gets true type of the value. Many of these types are not accessible + * from Blueprints, but can be converted to a Blueprint-accessible type. + * + * @param Value The property table property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "CesiumMetadataTrueType is deprecated. Use GetValueType to get the CesiumMetadataValueType instead.")) + static ECesiumMetadataTrueType_DEPRECATED + GetTrueType(UPARAM(ref) const FCesiumPropertyTableProperty& Value); + + /** + * Gets true type of the elements in this array property. If this is not an + * array property, the component type will be None. Many of these types are + * not accessible from Blueprints, but can be converted to a + * Blueprint-accessible type. + * + * @param Value The property table property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "CesiumMetadataTrueType is deprecated. Use GetValueType to get the CesiumMetadataValueType instead.")) + static ECesiumMetadataTrueType_DEPRECATED + GetTrueComponentType(UPARAM(ref) const FCesiumPropertyTableProperty& Value); + + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * Gets the number of values in the property. + * + * @param Property The property table property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static int64 + GetPropertySize(UPARAM(ref) const FCesiumPropertyTableProperty& Property); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Gets the number of values in this property. + * + * @param Property The property table property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = "Use GetPropertySize instead.")) + static int64 + GetNumberOfFeatures(UPARAM(ref) const FCesiumPropertyTableProperty& Property); + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * Gets the number of elements in an array of this property. Only + * applicable when the property is a fixed-length array type. + * + * @param Property The property table property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static int64 GetArraySize(UPARAM(ref) + const FCesiumPropertyTableProperty& Property); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Gets the number of elements in an array of this property. Only + * applicable when the property is a fixed-length array type. + * + * @param Property The property table property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = "Use GetArraySize instead.")) + static int64 + GetComponentCount(UPARAM(ref) const FCesiumPropertyTableProperty& Property); + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * Attempts to retrieve the value for the given feature as a boolean. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a boolean, it is returned as-is. + * + * - If the value is a scalar, zero is converted to false, while any other + * value is converted to true. + * + * - If the value is a string, "0", "false", and "no" (case-insensitive) are + * converted to false, while "1", "true", and "yes" are converted to true. + * All other strings, including strings that can be converted to numbers, + * will return the user-defined default value. + * + * All other types return the user-defined default value. If the feature ID is + * out-of-range, or if the property table property is somehow invalid, the + * user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as a Boolean. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static bool GetBoolean( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + bool DefaultValue = false); + + /** + * Attempts to retrieve the value for the given feature as an unsigned + * 8-bit integer. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is an integer between 0 and 255, it is returned as-is. + * Otherwise, if the value is a floating-point number in the aforementioned + * range, it is truncated (rounded toward zero) and returned. + * + * - If the value is a boolean, 1 is returned for true and 0 for false. + * + * - If the value is a string and the entire string can be parsed as an + * integer between 0 and 255, the parsed value is returned. The string is + * parsed in a locale-independent way and does not support the use of commas + * or other delimiters to group digits together. + * + * In all other cases, the user-defined default value is returned. If the + * feature ID is out-of-range, or if the property table property is somehow + * invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as a Byte. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static uint8 GetByte( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + uint8 DefaultValue = 0); + + /** + * Attempts to retrieve the value for the given feature as a signed 32-bit + * integer. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is an integer between -2,147,483,648 and 2,147,483,647, it + * is returned as-is. Otherwise, if the value is a floating-point number in + * the aforementioned range, it is truncated (rounded toward zero) and + * returned. + * + * - If the value is a boolean, 1 is returned for true and 0 for false. + * + * - If the value is a string and the entire string can be parsed as an + * integer in the valid range, the parsed value is returned. If it can be + * parsed as a floating-point number, the parsed value is truncated (rounded + * toward zero). In either case, the string is parsed in a locale-independent + * way and does not support the use of commas or other delimiters to group + * digits together. + * + * In all other cases, the user-defined default value is returned. If the + * feature ID is out-of-range, or if the property table property is somehow + * invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as an Integer. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static int32 GetInteger( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + int32 DefaultValue = 0); + + /** + * Attempts to retrieve the value for the given feature as a signed 64-bit + * integer. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is an integer and between -2^63 and (2^63 - 1), it is + * returned as-is. Otherwise, if the value is a floating-point number in the + * aforementioned range, it is truncated (rounded toward zero) and returned. + * + * - If the value is a boolean, 1 is returned for true and 0 for false. + * + * - If the value is a string and the entire string can be parsed as an + * integer in the valid range, the parsed value is returned. If it can be + * parsed as a floating-point number, the parsed value is truncated (rounded + * toward zero). In either case, the string is parsed in a locale-independent + * way and does not support the use of commas or other delimiters to group + * digits together. + * + * In all other cases, the user-defined default value is returned. If the + * feature ID is out-of-range, or if the property table property is somehow + * invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as an Integer64. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static int64 GetInteger64( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + int64 DefaultValue = 0); + + /** + * Attempts to retrieve the value for the given feature as a single-precision + * floating-point number. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is already a single-precision floating-point + * number, it is returned as-is. + * + * - If the value is a scalar of any other type within the range of values + * that a single-precision float can represent, it is converted to its closest + * representation as a single-precision float and returned. + * + * - If the value is a boolean, 1.0f is returned for true and 0.0f for false. + * + * - If the value is a string, and the entire string can be parsed as a + * number, the parsed value is returned. The string is parsed in a + * locale-independent way and does not support the use of a comma or other + * delimiter to group digits together. + * + * In all other cases, the user-defined default value is returned. If the + * feature ID is out-of-range, or if the property table property is somehow + * invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as a Float. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static float GetFloat( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + float DefaultValue = 0.0f); + + /** + * Attempts to retrieve the value for the given feature as a double-precision + * floating-point number. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a single- or double-precision floating-point number, it + * is returned as-is. + * + * - If the value is an integer, it is converted to the closest representable + * double-precision floating-point number. + * + * - If the value is a boolean, 1.0 is returned for true and 0.0 for false. + * + * - If the value is a string and the entire string can be parsed as a + * number, the parsed value is returned. The string is parsed in a + * locale-independent way and does not support the use of commas or other + * delimiters to group digits together. + * + * In all other cases, the user-defined default value is returned. If the + * feature ID is out-of-range, or if the property table property is somehow + * invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as a Float64. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static double GetFloat64( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + double DefaultValue = 0.0); + + /** + * Attempts to retrieve the value for the given feature as a FIntPoint. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 2-dimensional vector, its components will be converted + * to 32-bit signed integers if possible. + * + * - If the value is a 3- or 4-dimensional vector, it will use the first two + * components to construct the FIntPoint. + * + * - If the value is a scalar that can be converted to a 32-bit signed + * integer, the resulting FIntPoint will have this value in both of its + * components. + * + * - If the value is a boolean, (1, 1) is returned for true, while (0, 0) is + * returned for false. + * + * - If the value is a string that can be parsed as a FIntPoint, the parsed + * value is returned. The string must be formatted as "X=... Y=...". + * + * In all other cases, the user-defined default value is returned. In all + * vector cases, if any of the relevant components cannot be represented as a + * 32-bit signed, the default value is returned. + * + * If the feature ID is out-of-range, or if the property table property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FIntPoint. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FIntPoint GetIntPoint( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FIntPoint& DefaultValue); + + /** + * Attempts to retrieve the value for the given feature as a FVector2D. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 2-dimensional vector, its components will be converted + * to double-precision floating-point numbers. + * + * - If the value is a 3- or 4-dimensional vector, it will use the first two + * components to construct the FVector2D. + * + * - If the value is a scalar, the resulting FVector2D will have this value in + * both of its components. + * + * - If the value is a boolean, (1.0, 1.0) is returned for true, while (0.0, + * 0.0) is returned for false. + * + * - If the value is a string that can be parsed as a FVector2D, the parsed + * value is returned. The string must be formatted as "X=... Y=...". + * + * In all other cases, the user-defined default value is returned. If the + * feature ID is out-of-range, or if the property table property is somehow + * invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FVector2D. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FVector2D GetVector2D( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FVector2D& DefaultValue); + + /** + * Attempts to retrieve the value for the given feature as a FIntVector. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 3-dimensional vector, its components will be converted + * to 32-bit signed integers if possible. + * + * - If the value is a 4-dimensional vector, it will use the first three + * components to construct the FIntVector. + * + * - If the value is a 2-dimensional vector, it will become the XY-components + * of the FIntVector. The Z component will be set to zero. + * + * - If the value is a scalar that can be converted to a 32-bit signed + * integer, the resulting FIntVector will have this value in all of its + * components. + * + * - If the value is a boolean, (1, 1, 1) is returned for true, while (0, 0, + * 0) is returned for false. + * + * - If the value is a string that can be parsed as a FIntVector, the parsed + * value is returned. The string must be formatted as "X=... Y=... Z=". + * + * In all other cases, the user-defined default value is returned. In all + * vector cases, if any of the relevant components cannot be represented as a + * 32-bit signed integer, the default value is returned. + * + * If the feature ID is out-of-range, or if the property table property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FIntVector. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FIntVector GetIntVector( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FIntVector& DefaultValue); + + /** + * Attempts to retrieve the value for the given feature as a FVector3f. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 3-dimensional vector, its components will be converted + * to the closest representable single-precision floats, if possible. + * + * - If the value is a 4-dimensional vector, a FVector3f containing the first + * three components will be returned. + * + * - If the value is a 2-dimensional vector, it will become the XY-components + * of the FVector3f. The Z-component will be set to zero. + * + * - If the value is a scalar that can be converted to a single-precision + * floating-point number, then the resulting FVector3f will have this value in + * all of its components. + * + * - If the value is a boolean, (1.0f, 1.0f, 1.0f) is returned for true, while + * (0.0f, 0.0f, 0.0f) is returned for false. + * + * - If the value is a string that can be parsed as a FVector3f, the parsed + * value is returned. The string must be formatted as "X=... Y=... Z=". + * + * In all other cases, the user-defined default value is returned. In all + * vector cases, if any of the relevant components cannot be represented as a + * single-precision float, the user-defined default value is returned. + * + * If the feature ID is out-of-range, or if the property table property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FVector3f. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FVector3f GetVector3f( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FVector3f& DefaultValue); + + /** + * Attempts to retrieve the value for the given feature as a FVector. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 3-dimensional vector, its components will be converted + * to double-precision floating-point numbers. + * + * - If the value is a 4-dimensional vector, a FVector containing the first + * three components will be returned. + * + * - If the value is a 2-dimensional vector, it will become the XY-components + * of the FVector. The Z-component will be set to zero. + * + * - If the value is a scalar, then the resulting FVector will have this value + * as a double-precision floating-point number in all of its components. + * + * - If the value is a boolean, (1.0, 1.0, 1.0) is returned for true, while + * (0.0, 0.0, 0.0) is returned for false. + * + * - If the value is a string that can be parsed as a FVector, the parsed + * value is returned. The string must be formatted as "X=... Y=... Z=". + * + * In all other cases, the user-defined default value is returned. If the + * feature ID is out-of-range, or if the property table property is somehow + * invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FVector. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FVector GetVector( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FVector& DefaultValue); + + /** + * Attempts to retrieve the value for the given feature as a FVector4. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 4-dimensional vector, its components will be converted + * to double-precision floating-point numbers. + * + * - If the value is a 3-dimensional vector, it will become the XYZ-components + * of the FVector4. The W-component will be set to zero. + * + * - If the value is a 2-dimensional vector, it will become the XY-components + * of the FVector4. The Z- and W-components will be set to zero. + * + * - If the value is a scalar, then the resulting FVector4 will have this + * value as a double-precision floating-point number in all of its components. + * + * - If the value is a boolean, (1.0, 1.0, 1.0, 1.0) is returned for true, + * while (0.0, 0.0, 0.0, 0.0) is returned for false. + * + * - If the value is a string that can be parsed as a FVector4, the parsed + * value is returned. This follows the rules of FVector4::InitFromString. The + * string must be formatted as "X=... Y=... Z=... W=...". The W-component is + * optional; if absent, it will be set to 1.0. + * + * In all other cases, the user-defined default value is returned. If the + * feature ID is out-of-range, or if the property table property is somehow + * invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FVector4. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FVector4 GetVector4( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FVector4& DefaultValue); + + /** + * Attempts to retrieve the value for the given feature as a FMatrix. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 4-by-4 matrix, its components will be converted to + * double-precision floating-point numbers. + * + * - If the value is a 3-by-3 matrix, it will initialize the corresponding + * entries of the FMatrix, while all other entries are set to zero. In other + * words, the 3-by-3 matrix is returned in an FMatrix where the fourth row and + * column are filled with zeroes. + * + * - If the value is a 2-by-2 matrix, it will initialize the corresponding + * entries of the FMatrix, while all other entries are set to zero. In other + * words, the 2-by-2 matrix is returned in an FMatrix where the third and + * fourth rows / columns are filled with zeroes. + * + * - If the value is a scalar, then the resulting FMatrix will have this value + * along its diagonal, including the very last component. All other entries + * will be zero. + * + * - If the value is a boolean, it is converted to 1.0 for true and 0.0 for + * false. Then, the resulting FMatrix will have this value along its diagonal, + * including the very last component. All other entries will be zero. + * + * In all other cases, the user-defined default value is returned. If the + * feature ID is out-of-range, or if the property table property is somehow + * invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FMatrix. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FMatrix GetMatrix( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FMatrix& DefaultValue); + + /** + * Attempts to retrieve the value for the given feature as a FString. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - String properties are returned as-is. + * + * - Scalar values are converted to a string with `std::to_string`. + * + * - Boolean properties are converted to "true" or "false". + * + * - Vector properties are returned as strings in the format "X=... Y=... + * Z=... W=..." depending on how many components they have. + * + * - Matrix properties are returned as strings row-by-row, where each row's + * values are printed between square brackets. For example, a 2-by-2 matrix + * will be printed out as "[A B] [C D]". + * + * - Array properties return the user-defined default value. + * + * If the feature ID is out-of-range, or if the property table property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FString. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FString GetString( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID, + const FString& DefaultValue = ""); + + /** + * Attempts to retrieve the value for the given feature as a + * FCesiumPropertyArray. If the property is not an array type, this returns an + * empty array. + * + * For numeric array properties, the raw array value for a given feature will + * be transformed by the property's normalization, scale, and offset before it + * is further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @return The property value as a FCesiumPropertyArray. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FCesiumPropertyArray GetArray( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID); + + /** + * Retrieves the value of the property for the given feature. This allows the + * value to be acted on more generically; its true value can be retrieved + * later as a specific Blueprints type. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * returned. If the raw value is equal to the property's "no data" value, an + * empty value will be returned. However, if the property itself specifies a + * default value, then the property-defined default value will be returned. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FCesiumMetadataValue GetValue( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Retrieves the value of the property for the given feature. This allows the + * value to be acted on more generically; its true value can be retrieved + * later as a specific Blueprints type. + * + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = (DeprecatedFunction, DeprecatedMessage = "Use GetValue instead.")) + static FCesiumMetadataValue GetGenericValue( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID); + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * Retrieves the raw value of the property for the given feature. This is the + * value of the property without normalization, offset, or scale applied. + * + * If this property specifies a "no data" value, and the raw value is equal to + * this "no data" value, the value is returned as-is. + * + * If this property is an empty property with a specified default value, it + * will not have any raw data to retrieve. The returned value will be empty. + + * @param Property The property table property. + * @param FeatureID The ID of the feature. + * @return The raw property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FCesiumMetadataValue GetRawValue( + UPARAM(ref) const FCesiumPropertyTableProperty& Property, + int64 FeatureID); + + /** + * Whether this property is normalized. Only applicable when this property has + * an integer component type. + * + * @param Property The property table property. + * @return Whether this property is normalized. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static bool IsNormalized(UPARAM(ref) + const FCesiumPropertyTableProperty& Property); + + /** + * Gets the offset of this property. This can be defined by the class property + * that it implements, or overridden by the instance of the property itself. + * + * This is only applicable to properties with floating-point or normalized + * integer component types. If an offset is not defined or applicable, this + * returns an empty value. + * + * @param Property The property table property. + * @return The offset of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FCesiumMetadataValue + GetOffset(UPARAM(ref) const FCesiumPropertyTableProperty& Property); + + /** + * Gets the scale of this property. This can be defined by the class property + * that it implements, or overridden by the instance of the property itself. + * + * This is only applicable to properties with floating-point or normalized + * integer component types. If a scale is not defined or applicable, this + * returns an empty value. + * + * @param Property The property table property. + * @return The scale of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FCesiumMetadataValue + GetScale(UPARAM(ref) const FCesiumPropertyTableProperty& Property); + + /** + * Gets the minimum value of this property. This can be defined by the class + * property that it implements, or overridden by the instance of the property + * itself. + * + * This is only applicable to scalar, vecN and matN properties. It represents + * the component-wise minimum of all property values with normalization, + * offset, and scale applied. If a minimum value is not defined or + * applicable, this returns an empty value. + * + * @param Property The property table property. + * @return The minimum value of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FCesiumMetadataValue + GetMinimumValue(UPARAM(ref) const FCesiumPropertyTableProperty& Property); + + /** + * Gets the maximum value of this property. This can be defined by the class + * property that it implements, or overridden by the instance of the property + * itself. + * + * This is only applicable to scalar, vecN and matN properties. It represents + * the component-wise maximum of all property values with normalization, + * offset, and scale applied. If a maximum value is not defined or applicable, + * this returns an empty value. + * + * @param Property The property table property. + * @return The maximum value of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FCesiumMetadataValue + GetMaximumValue(UPARAM(ref) const FCesiumPropertyTableProperty& Property); + + /** + * Gets the "no data" value of this property, as defined by its class + * property. This value functions a sentinel value, indicating missing data + * wherever it appears. The value is compared against the property's raw data, + * without normalization, offset, or scale applied. + * + * This is not applicable to boolean properties. If a "no data" value is + * not defined or applicable, this returns an empty value. + * + * @param Property The property table property. + * @return The "no data" value of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FCesiumMetadataValue + GetNoDataValue(UPARAM(ref) const FCesiumPropertyTableProperty& Property); + + /** + * Gets the default value of this property, as defined by its class + * property. This default value is used use when encountering a "no data" + * value in the property. + * + * If a default value is not defined, this returns an empty value. + * + * @param Property The property table property. + * @return The default value of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTableProperty") + static FCesiumMetadataValue + GetDefaultValue(UPARAM(ref) const FCesiumPropertyTableProperty& Property); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyTexture.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyTexture.h new file mode 100644 index 0000000..e32bbc9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyTexture.h @@ -0,0 +1,178 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/PropertyTextureView.h" +#include "CesiumPropertyTextureProperty.h" +#include "Containers/Array.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Kismet/GameplayStatics.h" +#include "CesiumPropertyTexture.generated.h" + +namespace CesiumGltf { +struct Model; +struct PropertyTexture; +}; // namespace CesiumGltf + +UENUM(BlueprintType) +enum class ECesiumPropertyTextureStatus : uint8 { + /* The property texture is valid. */ + Valid = 0, + /* The property texture instance was not initialized from an actual glTF + property texture. */ + ErrorInvalidPropertyTexture, + /* The property texture's class could be found in the schema of the metadata + extension. */ + ErrorInvalidPropertyTextureClass +}; + +/** + * @brief A blueprint-accessible wrapper of a property texture from a glTF. + * Provides access to {@link FCesiumPropertyTextureProperty} views of texture + * metadata. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumPropertyTexture { + GENERATED_USTRUCT_BODY() + +public: + FCesiumPropertyTexture() + : _status(ECesiumPropertyTextureStatus::ErrorInvalidPropertyTexture) {} + + FCesiumPropertyTexture( + const CesiumGltf::Model& model, + const CesiumGltf::PropertyTexture& PropertyTexture); + + /** + * Gets the name of the metadata class that this property table conforms to. + */ + FString getClassName() const { return _className; } + +private: + ECesiumPropertyTextureStatus _status; + FString _name; + FString _className; + + TMap _properties; + + friend class UCesiumPropertyTextureBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumPropertyTextureBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the status of the property texture. If the property texture is invalid + * in any way, this briefly indicates why. + * + * @param PropertyTexture The property texture. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTexture") + static const ECesiumPropertyTextureStatus + GetPropertyTextureStatus(UPARAM(ref) + const FCesiumPropertyTexture& PropertyTexture); + + /** + * Gets the name of the property texture. + * + * @param PropertyTexture The property texture. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTexture") + static const FString& + GetPropertyTextureName(UPARAM(ref) + const FCesiumPropertyTexture& PropertyTexture); + + /** + * Gets all the properties of the property texture, mapped by property name. + * + * @param PropertyTexture The property texture. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTexture") + static const TMap + GetProperties(UPARAM(ref) const FCesiumPropertyTexture& PropertyTexture); + + /** + * Gets the names of the properties in this property texture. If the property + * texture is invalid, this returns an empty array. + * + * @param PropertyTexture The property texture. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTexture") + static const TArray + GetPropertyNames(UPARAM(ref) const FCesiumPropertyTexture& PropertyTexture); + + /** + * Retrieve a FCesiumPropertyTextureProperty by name. If the property texture + * does not contain a property with that name, this returns an invalid + * FCesiumPropertyTextureProperty. + * + * @param PropertyTexture The property texture. + * @param PropertyName The name of the property to find. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTexture") + static const FCesiumPropertyTextureProperty& FindProperty( + UPARAM(ref) const FCesiumPropertyTexture& PropertyTexture, + const FString& PropertyName); + + /** + * Gets all of the property values at the given texture coordinates, mapped by + * property name. This will only include values from valid property texture + * properties. + * + * In EXT_structural_metadata, individual properties can specify different + * texture coordinate sets to be sampled from. This method uses the same + * coordinates to sample each property, regardless of its intended texture + * coordinate set. Use GetMetadataValuesForHit instead to sample the property + * texture's properties with their respective texture coordinate sets. + * + * @param PropertyTexture The property texture. + * @param UV The texture coordinates. + * @return The property values mapped by property name. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTexture") + static TMap GetMetadataValuesForUV( + UPARAM(ref) const FCesiumPropertyTexture& PropertyTexture, + const FVector2D& UV); + + /** + * Given a trace hit result, gets all of the property values from property + * texture on the hit component, mapped by property name. This will only + * include values from valid property texture properties. + * + * In EXT_structural_metadata, individual properties can specify different + * texture coordinate sets to be sampled from. This method uses the + * corresponding texture coordinate sets to sample each property. + * + * @param PropertyTexture The property texture. + * @param Hit The trace hit result + * @return The property values mapped by property name. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTexture") + static TMap GetMetadataValuesFromHit( + UPARAM(ref) const FCesiumPropertyTexture& PropertyTexture, + const FHitResult& Hit); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyTextureProperty.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyTextureProperty.h new file mode 100644 index 0000000..c9a7c00 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPropertyTextureProperty.h @@ -0,0 +1,842 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumMetadataValue.h" +#include "GenericPlatform/GenericPlatform.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include +#include +#include +#include +#include "CesiumPropertyTextureProperty.generated.h" + +/** + * @brief Reports the status of a FCesiumPropertyTextureProperty. If the + * property texture property cannot be accessed, this briefly indicates why. + */ +UENUM(BlueprintType) +enum class ECesiumPropertyTexturePropertyStatus : uint8 { + /* The property texture property is valid. */ + Valid = 0, + /* The property texture property is empty but has a specified default value. + */ + EmptyPropertyWithDefault, + /* The property texture property does not exist in the glTF, or the property + definition itself contains errors. */ + ErrorInvalidProperty, + /* The data associated with the property texture property is malformed and + cannot be retrieved. */ + ErrorInvalidPropertyData, + /* The type of this property texture property is not supported. */ + ErrorUnsupportedProperty +}; + +/** + * @brief A blueprint-accessible wrapper for a property texture property from a + * glTF. Provides per-pixel access to metadata encoded in a property texture. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumPropertyTextureProperty { + GENERATED_USTRUCT_BODY() + +public: + FCesiumPropertyTextureProperty() + : _status(ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty), + _property(), + _valueType(), + _normalized(false) {} + + template + FCesiumPropertyTextureProperty( + const CesiumGltf::PropertyTexturePropertyView& Property) + : _status(ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty), + _property(Property), + _valueType(), + _normalized(Normalized) { + switch (Property.status()) { + case CesiumGltf::PropertyTexturePropertyViewStatus::Valid: + _status = ECesiumPropertyTexturePropertyStatus::Valid; + break; + case CesiumGltf::PropertyTexturePropertyViewStatus:: + EmptyPropertyWithDefault: + _status = ECesiumPropertyTexturePropertyStatus::EmptyPropertyWithDefault; + break; + case CesiumGltf::PropertyTexturePropertyViewStatus:: + ErrorUnsupportedProperty: + _status = ECesiumPropertyTexturePropertyStatus::ErrorUnsupportedProperty; + return; + case CesiumGltf::PropertyTexturePropertyViewStatus:: + ErrorInvalidPropertyTexture: + case CesiumGltf::PropertyTexturePropertyViewStatus:: + ErrorNonexistentProperty: + case CesiumGltf::PropertyTexturePropertyViewStatus::ErrorTypeMismatch: + case CesiumGltf::PropertyTexturePropertyViewStatus:: + ErrorComponentTypeMismatch: + case CesiumGltf::PropertyTexturePropertyViewStatus::ErrorArrayTypeMismatch: + case CesiumGltf::PropertyTexturePropertyViewStatus:: + ErrorInvalidNormalization: + case CesiumGltf::PropertyTexturePropertyViewStatus:: + ErrorNormalizationMismatch: + case CesiumGltf::PropertyTexturePropertyViewStatus::ErrorInvalidOffset: + case CesiumGltf::PropertyTexturePropertyViewStatus::ErrorInvalidScale: + case CesiumGltf::PropertyTexturePropertyViewStatus::ErrorInvalidMax: + case CesiumGltf::PropertyTexturePropertyViewStatus::ErrorInvalidMin: + case CesiumGltf::PropertyTexturePropertyViewStatus::ErrorInvalidNoDataValue: + case CesiumGltf::PropertyTexturePropertyViewStatus:: + ErrorInvalidDefaultValue: + // The status was already set in the initializer list. + return; + default: + _status = ECesiumPropertyTexturePropertyStatus::ErrorInvalidPropertyData; + return; + } + + _valueType = TypeToMetadataValueType(); + _normalized = Normalized; + } + + const int64 getTexCoordSetIndex() const; + const CesiumGltf::Sampler* getSampler() const; + const CesiumGltf::ImageAsset* getImage() const; + const std::optional + getTextureTransform() const; + +private: + ECesiumPropertyTexturePropertyStatus _status; + + std::any _property; + + FCesiumMetadataValueType _valueType; + bool _normalized; + + friend class UCesiumPropertyTexturePropertyBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumPropertyTexturePropertyBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the status of the property texture property. If this property texture + * property is invalid in any way, this will briefly indicate why. + * + * @param Property The property texture property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static ECesiumPropertyTexturePropertyStatus GetPropertyTexturePropertyStatus( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + /** + * Gets the best-fitting type for the property that is accessible from + * Blueprints. For the most precise representation of the values possible in + * Blueprints, you should retrieve it using this type. + * + * @param Property The property texture property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static ECesiumMetadataBlueprintType + GetBlueprintType(UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + /** + * Gets the best-fitting Blueprints type for the elements in this property's + * array values. If the given property does not contain array values, this + * returns None. + * + * @param Property The property texture property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static ECesiumMetadataBlueprintType GetArrayElementBlueprintType( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + /** + * Gets the type of the metadata value as defined in the + * EXT_structural_metadata extension. Many of these types are not accessible + * from Blueprints, but can be converted to a Blueprint-accessible type. + * + * @param Property The property texture property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FCesiumMetadataValueType + GetValueType(UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + /** + * Gets the number of elements in an array of this property. Only + * applicable when the property is a fixed-length array type. + * + * @param Property The property texture property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static int64 GetArraySize(UPARAM(ref) + const FCesiumPropertyTextureProperty& Property); + + /** + * Gets the glTF texture coordinate set index used by the property texture + * property. This is the index N corresponding to the "TEXCOORD_N" attribute + * on the glTF primitive that samples this texture. + * + * If the property texture property is invalid, this returns -1. + * + * @param Property The property texture property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static int64 GetGltfTextureCoordinateSetIndex( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + /** + * Gets the UV channel containing the texture coordinate set that is used by + * the property texture property on the given component. This refers to the UV + * channel it uses on the primitive's static mesh, which is not necessarily + * equal to value of GetGltfTextureCoordinateSetIndex. + * + * This function may be used with FindCollisionUV to get the feature ID from a + * line trace hit. However, in order for this function to work, the feature ID + * texture should be listed under the CesiumFeaturesMetadataComponent of the + * owner Cesium3DTileset. Otherwise, its texture coordinate set may not be + * included in the Unreal mesh data. To avoid using + * CesiumFeaturesMetadataComponent, use GetFeatureIDFromHit instead. + * + * This returns -1 if the property texture property is invalid, or if the + * specified texture coordinate set is not present in the component's mesh + * data. + * + * @param Component The component to get the texture coordinate set from. + * @param Property The property texture property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static int64 GetUnrealUVChannel( + const UPrimitiveComponent* Component, + UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + /** + * @brief Get the channels array of this property. This contains the indices + * of the meaningful texel channels that will be used when sampling the + * property texture. + * + * @param Property The property texture property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static TArray + GetChannels(UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + /** + * Attempts to retrieve the value at the given texture coordinates as an + * unsigned 8-bit integer. + * + * For numeric properties, the raw value for the given coordinates will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is an integer between 0 and 255, it is returned as-is. + * - If the value is a floating-point number in the aforementioned range, it + * is truncated (rounded toward zero) and returned. + * + * In all other cases, the user-defined default value is returned. If the + * property texture property is somehow invalid, the user-defined default + * value is returned. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @param DefaultValue The default value to fall back on. + * @return The property value as a Byte. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static uint8 GetByte( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + uint8 DefaultValue = 0); + + /** + * Attempts to retrieve the value at the given texture coordinates as a signed + * 32-bit integer. + * + * For numeric properties, the raw value for the given coordinates will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if + * possible. If the property-defined default value cannot be converted, or + * does not exist, then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is an integer between -2,147,483,648 and 2,147,483,647, it + * is returned as-is. + * - If the value is a floating-point number in the aforementioned range, it + * is truncated (rounded toward zero) and returned. + * + * In all other cases, the user-defined default value is returned. If the + * property texture property is somehow invalid, the user-defined default + * value is returned. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @param DefaultValue The default value to fall back on. + * @return The property value as an Integer. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static int32 GetInteger( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + int32 DefaultValue = 0); + + /** + * Attempts to retrieve the value at the given texture coordinates as a + * single-precision floating-point number. + * + * For numeric properties, the raw value for the given coordinates will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is already a single-precision floating-point + * number, it is returned as-is. + * + * - If the value is a scalar of any other type within the range of values + * that a single-precision float can represent, it is converted to its closest + * representation as a single-precision float and returned. + * + * In all other cases, the user-defined default value is returned. If the + * property texture property is somehow invalid, the user-defined default + * value is returned. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @param DefaultValue The default value to fall back on. + * @return The property value as a Float. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static float GetFloat( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + float DefaultValue = 0.0f); + + /** + * Attempts to retrieve the value at the given texture coordinates as a + * double-precision floating-point number. + * + * For numeric properties, the raw value for the given coordinates will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a single- or double-precision floating-point number, it + * is returned as-is. + * + * - If the value is an integer, it is converted to the closest representable + * double-precision floating-point number. + * + * In all other cases, the user-defined default value is returned. If the + * property texture property is somehow invalid, the user-defined default + * value is returned. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @param DefaultValue The default value to fall back on. + * @return The property value as a Float. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static double GetFloat64( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + double DefaultValue = 0.0); + + /** + * Attempts to retrieve the value at the given texture coordinates as a + * FIntPoint. + * + * For numeric properties, the raw value for the given coordinates will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 2-dimensional vector, its components will be converted + * to 32-bit signed integers if possible. + * + * - If the value is a 3- or 4-dimensional vector, it will use the first two + * components to construct the FIntPoint. + * + * - If the value is a scalar that can be converted to a 32-bit signed + * integer, the resulting FIntPoint will have this value in both of its + * components. + * + * In all other cases, the user-defined default value is returned. In all + * vector cases, if any of the relevant components cannot be represented as a + * 32-bit signed, the default value is returned. + * + * If the property texture property is somehow invalid, the user-defined + * default value is returned. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FIntPoint. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FIntPoint GetIntPoint( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + const FIntPoint& DefaultValue); + + /** + * Attempts to retrieve the value at the given texture coordinates as a + * FVector2D. + * + * For numeric properties, the raw value for the given coordinates will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 2-dimensional vector, its components will be converted + * to double-precision floating-point numbers. + * + * - If the value is a 3- or 4-dimensional vector, it will use the first two + * components to construct the FVector2D. + * + * - If the value is a scalar that can be converted to a 32-bit signed + * integer, the resulting FVector2D will have this value in both of its + * components. + * + * In all other cases, the user-defined default value is returned. If the + * property texture property is somehow invalid, the user-defined default + * value is returned. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FVector2D. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FVector2D GetVector2D( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + const FVector2D& DefaultValue); + + /** + * Attempts to retrieve the value at the given texture coordinates as a + * FIntVector. + * + * For numeric properties, the raw value for the given coordinates will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 3-dimensional vector, its components will be converted + * to 32-bit signed integers if possible. + * + * - If the value is a 4-dimensional vector, it will use the first three + * components to construct the FIntVector. + * + * - If the value is a 2-dimensional vector, it will become the XY-components + * of the FIntVector. The Z component will be set to zero. + * + * - If the value is a scalar that can be converted to a 32-bit signed + * integer, the resulting FIntVector will have this value in all of its + * components. + * + * In all other cases, the user-defined default value is returned. In all + * vector cases, if any of the relevant components cannot be represented as a + * 32-bit signed integer, the default value is returned. + * + * If the property texture property is somehow invalid, the user-defined + * default value is returned. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FIntVector. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FIntVector GetIntVector( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + const FIntVector& DefaultValue); + + /** + * Attempts to retrieve the value at the given texture coordinates as a + * FVector. + * + * For numeric properties, the raw value for the given coordinates will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 3-dimensional vector, its components will be converted + * to double-precision floating-point numbers. + * + * - If the value is a 4-dimensional vector, a FVector containing the first + * three components will be returned. + * + * - If the value is a 2-dimensional vector, it will become the XY-components + * of the FVector. The Z-component will be set to zero. + * + * - If the value is a scalar, then the resulting FVector will have this value + * as a double-precision floating-point number in all of its components. + * + * In all other cases, the user-defined default value is returned. In all + * vector cases, if any of the relevant components cannot be represented as a + * single-precision float, the default value is returned. + * + * If the property texture property is somehow invalid, the user-defined + * default value is returned. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FVector. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FVector GetVector( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + const FVector& DefaultValue); + + /** + * Attempts to retrieve the value at the given texture coordinates as a + * FVector4. + * + * For numeric properties, the raw value for the given coordinates will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 4-dimensional vector, its components will be converted + * to double-precision floating-point numbers. + * + * - If the value is a 3-dimensional vector, it will become the XYZ-components + * of the FVector4. The W-component will be set to zero. + * + * - If the value is a 2-dimensional vector, it will become the XY-components + * of the FVector4. The Z- and W-components will be set to zero. + * + * - If the value is a scalar, then the resulting FVector4 will have this + * value as a double-precision floating-point number in all of its components. + * + * In all other cases, the user-defined default value is returned. If the + * property texture property is somehow invalid, the user-defined default + * value is returned. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FVector4. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FVector4 GetVector4( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + const FVector4& DefaultValue); + + /** + * Attempts to retrieve the value for the given texture coordinates as a + * FCesiumPropertyArray. If the property is not an array type, this returns an + * empty array. + * + * For numeric array properties, the raw array value for a given coordinates + * will be transformed by the property's normalization, scale, and offset + * before it is further converted. If the raw value is equal to the property's + * "no data" value, then the property's default value will be converted if + * possible. If the property-defined default value cannot be converted, or + * does not exist, then the user-defined default value is returned. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @return The property value as a FCesiumPropertyArray. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FCesiumPropertyArray GetArray( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV); + + /** + * Retrieves the value of the property for the given texture coordinates. This + * allows the value to be acted on more generically; its true value can be + * retrieved later as a specific Blueprints type. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * returned. If the raw value is equal to the property's "no data" value, an + * empty value will be returned. However, if the property itself specifies a + * default value, then the property-defined default value will be returned. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FCesiumMetadataValue GetValue( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV); + + /** + * Retrieves the raw value of the property for the given feature. This is the + * value of the property without normalization, offset, or scale applied. + * + * If this property specifies a "no data" value, and the raw value is equal to + * this "no data" value, the value is returned as-is. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @return The raw property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FCesiumMetadataValue GetRawValue( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV); + + /** + * Whether this property is normalized. Only applicable when this property + * has an integer component type. + * + * @param Property The property texture property. + * @return Whether this property is normalized. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static bool IsNormalized(UPARAM(ref) + const FCesiumPropertyTextureProperty& Property); + + /** + * Gets the offset of this property. This can be defined by the class property + * that it implements, or overridden by the instance of the property itself. + * + * This is only applicable to properties with floating-point or normalized + * integer component types. If an offset is not defined or applicable, this + * returns an empty value. + * + * @param Property The property texture property. + * @return The offset of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FCesiumMetadataValue + GetOffset(UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + /** + * Gets the scale of this property. This can be defined by the class property + * that it implements, or overridden by the instance of the property itself. + * + * This is only applicable to properties with floating-point or normalized + * integer component types. If a scale is not defined or applicable, this + * returns an empty value. + * + * @param Property The property texture property. + * @return The scale of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FCesiumMetadataValue + GetScale(UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + /** + * Gets the minimum value of this property. This can be defined by the class + * property that it implements, or overridden by the instance of the property + * itself. + * + * This is only applicable to scalar, vecN and matN properties. It represents + * the component-wise minimum of all property values with normalization, + * offset, and scale applied. If a minimum value is not defined or + * applicable, this returns an empty value. + * + * @param Property The property texture property. + * @return The minimum value of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FCesiumMetadataValue + GetMinimumValue(UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + /** + * Gets the maximum value of this property. This can be defined by the class + * property that it implements, or overridden by the instance of the property + * itself. + * + * This is only applicable to scalar, vecN and matN properties. It represents + * the component-wise maximum of all property values with normalization, + * offset, and scale applied. If a maximum value is not defined or applicable, + * this returns an empty value. + * + * @param Property The property texture property. + * @return The maximum value of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FCesiumMetadataValue + GetMaximumValue(UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + /** + * Gets the "no data" value of this property, as defined by its class + * property. This value functions a sentinel value, indicating missing data + * wherever it appears. The value is compared against the property's raw data, + * without normalization, offset, or scale applied. + * + * This is not applicable to boolean properties. If a "no data" value is + * not defined or applicable, this returns an empty value. + * + * @param Property The property texture property. + * @return The "no data" value of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FCesiumMetadataValue + GetNoDataValue(UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + /** + * Gets the default value of this property, as defined by its class + * property. This default value is used use when encountering a "no data" + * value in the property. + * + * If a default value is not defined, this returns an empty value. + * + * @param Property The property texture property. + * @return The default value of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static FCesiumMetadataValue + GetDefaultValue(UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * @brief Get the string representing how the metadata is encoded into a + * pixel color. This is useful to unpack the correct order of the metadata + * components from the pixel color. + * + * @param Property The property texture property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "Swizzles are no longer hardcoded in Unreal materials. To see what channels the property uses, use GetChannels instead.")) + static FString GetSwizzle(UPARAM(ref) + const FCesiumPropertyTextureProperty& Property); + + /** + * @brief Get the component count of this property. Since the metadata is + * encoded as pixel color, this is also the number of meaningful channels + * it will use. + * + * @param Property The property texture property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Meta = + (DeprecatedFunction, + DeprecationMessage = + "Use GetChannels to get the channels array of a property texture property instead.")) + static int64 + GetComponentCount(UPARAM(ref) const FCesiumPropertyTextureProperty& Property); + PRAGMA_ENABLE_DEPRECATION_WARNINGS +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRasterOverlay.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRasterOverlay.h new file mode 100644 index 0000000..41d1fdd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRasterOverlay.h @@ -0,0 +1,260 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumRasterOverlayLoadFailureDetails.h" +#include "CesiumRasterOverlays/RasterOverlay.h" +#include "Components/ActorComponent.h" +#include "CoreMinimal.h" +#include "Engine/Texture.h" +#include "Engine/TextureDefines.h" +#include +#include "CesiumRasterOverlay.generated.h" + +namespace Cesium3DTilesSelection { +class Tileset; +} + +/** + * The delegate for OnCesiumRasterOverlayLoadFailure, which is triggered when + * the raster overlay encounters a load error. + */ +DECLARE_MULTICAST_DELEGATE_OneParam( + FCesiumRasterOverlayLoadFailure, + const FCesiumRasterOverlayLoadFailureDetails&); + +CESIUMRUNTIME_API extern FCesiumRasterOverlayLoadFailure + OnCesiumRasterOverlayLoadFailure; + +/** + * This struct is passed through the raster overlay options and is used when + * `prepareRasterInLoadThread` is called. + */ +USTRUCT(BlueprintType) +struct FRasterOverlayRendererOptions { + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + TEnumAsByte filter = TextureFilter::TF_Default; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + TEnumAsByte group = TextureGroup::TEXTUREGROUP_World; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + bool useMipmaps = true; +}; + +/** + * A quadtree pyramid of 2D raster images meant to be draped over a Cesium 3D + * Tileset. Raster overlays are commonly used for satellite imagery, street + * maps, and more. + */ +UCLASS(Abstract) +class CESIUMRUNTIME_API UCesiumRasterOverlay : public UActorComponent { + GENERATED_BODY() + +public: + /** + * The key to use to match this overlay to a material layer. + * + * When using Material Layers, any material layers inside a "Cesium" layer + * stack with a name that matches this name will have their Texture, + * TranslationScale, and TextureCoordinateIndex properties set automatically + * so that a ML_CesiumOverlay layer function (or similar) will correctly + * sample from this overlay. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + FString MaterialLayerKey = "Overlay0"; + + /** + * Sets the texture filter and texture group of raster tile images. Depending + * on the project settings, the default texture filter, TF_Default, should + * have the best quality. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + FRasterOverlayRendererOptions rendererOptions; + + // Sets default values for this component's properties + UCesiumRasterOverlay(); + + /** + * Displays this raster overlay on its owning Cesium 3D Tileset Actor, without + * changing its activation state. It is usually better to call Activate + * rather than this function, in order to ensure that the component is also + * activated. Otherwise, if the Cesium3DTileset is reloaded for any reason, + * this overlay will no longer be shown. + * + * If the overlay is already added or if this component's Owner is not a + * Cesium 3D Tileset, this method does nothing. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void AddToTileset(); + + /** + * Stops displaying this raster overlay on its owning Cesium 3D Tileset Actor. + * It is usually better to call Deactivate rather than this function, in order + * to ensure that the component is also deactivated. Otherwise, if the + * component remains active and the Cesium3DTileset is reloaded for any + * reason, this overlay will reappear. + * + * If the overlay is not yet added or if this component's Owner is not a + * Cesium 3D Tileset, this method does nothing. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void RemoveFromTileset(); + + /** + * Refreshes this overlay by removing from its owning Cesium 3D Tileset Actor + * and re-adding it. If this component's Owner is not a Cesium 3D Tileset + * Actor, this method does nothing. If this component is not active, the + * overlay will be removed from the Cesium3DTileset if already present but not + * re-added. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void Refresh(); + + UFUNCTION(BlueprintCallable, Category = "Cesium") + double GetMaximumScreenSpaceError() const; + + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetMaximumScreenSpaceError(double Value); + + UFUNCTION(BlueprintCallable, Category = "Cesium") + int32 GetMaximumTextureSize() const; + + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetMaximumTextureSize(int32 Value); + + UFUNCTION(BlueprintCallable, Category = "Cesium") + int32 GetMaximumSimultaneousTileLoads() const; + + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetMaximumSimultaneousTileLoads(int32 Value); + + UFUNCTION(BlueprintCallable, Category = "Cesium") + int64 GetSubTileCacheBytes() const; + + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetSubTileCacheBytes(int64 Value); + + /** + * Activates this raster overlay, which will display it on the Cesium3DTileset + * to which the component is attached, if it isn't already displayed. The + * overlay will continue to be shown on the tileset until it is deactivated. + * + * If the overlay is already displayed on the Cesium3DTileset, calling this + * function will not cause it to pick up any new values for properties that + * have been modified since it was added. To do that, call Refresh. + * + * If you created this overlay component via Blueprints, consider setting the + * "Auto Activate" property to false on the "Add Component" node and calling + * Activate after setting all the desired properties. This will avoid the need + * to call Refresh, and will ensure the overlay is not loaded multiple times. + * + * @param bReset Whether the activation should happen even if ShouldActivate + * returns false. + */ + virtual void Activate(bool bReset) override; + + /** + * Deactivates this raster overlay. This will stop displaying it on the + * Cesium3DTileset to which the component is attached. The overlay will not be + * shown again until the component is re-activated. + */ + virtual void Deactivate() override; + + virtual void OnComponentDestroyed(bool bDestroyingHierarchy) override; + virtual bool IsReadyForFinishDestroy() override; + +protected: + /** + * The maximum number of pixels of error when rendering this overlay. + * This is used to select an appropriate level-of-detail. + * + * When this property has its default value, 2.0, it means that raster overlay + * images will be sized so that, when zoomed in closest, a single pixel in + * the raster overlay maps to approximately 2x2 pixels on the screen. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetMaximumScreenSpaceError, + BlueprintSetter = SetMaximumScreenSpaceError, + Category = "Cesium") + double MaximumScreenSpaceError = 2.0; + + /** + * The maximum texel size of raster overlay textures, in either + * direction. + * + * Images created by this overlay will be no more than this number of texels + * in either direction. This may result in reduced raster overlay detail in + * some cases. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetMaximumTextureSize, + BlueprintSetter = SetMaximumTextureSize, + Category = "Cesium") + int32 MaximumTextureSize = 2048; + + /** + * The maximum number of overlay tiles that may simultaneously be in + * the process of loading. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetMaximumSimultaneousTileLoads, + BlueprintSetter = SetMaximumSimultaneousTileLoads, + Category = "Cesium") + int32 MaximumSimultaneousTileLoads = 20; + + /** + * The maximum number of bytes to use to cache sub-tiles in memory. + * + * This is used by provider types that have an underlying tiling scheme that + * may not align with the tiling scheme of the geometry tiles on which the + * raster overlay tiles are draped. Because a single sub-tile may overlap + * multiple geometry tiles, it is useful to cache loaded sub-tiles in memory + * in case they're needed again soon. This property controls the maximum size + * of that cache. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetSubTileCacheBytes, + BlueprintSetter = SetSubTileCacheBytes, + Category = "Cesium") + int64 SubTileCacheBytes = 16 * 1024 * 1024; + + /** + * Whether or not to show credits of this raster overlay on screen. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + bool ShowCreditsOnScreen; + +#if WITH_EDITOR + // Called when properties are changed in the editor + virtual void + PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; +#endif + + Cesium3DTilesSelection::Tileset* FindTileset() const; + + virtual std::unique_ptr + CreateOverlay(const CesiumRasterOverlays::RasterOverlayOptions& options = {}) + PURE_VIRTUAL(UCesiumRasterOverlay::CreateOverlay, return nullptr;); + + virtual void OnAdd( + Cesium3DTilesSelection::Tileset* pTileset, + CesiumRasterOverlays::RasterOverlay* pOverlay) {} + virtual void OnRemove( + Cesium3DTilesSelection::Tileset* pTileset, + CesiumRasterOverlays::RasterOverlay* pOverlay) {} + +private: + CesiumRasterOverlays::RasterOverlay* _pOverlay; + int32 _overlaysBeingDestroyed; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRasterOverlayLoadFailureDetails.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRasterOverlayLoadFailureDetails.h new file mode 100644 index 0000000..5e27b8c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRasterOverlayLoadFailureDetails.h @@ -0,0 +1,58 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include "CesiumRasterOverlayLoadFailureDetails.generated.h" + +class UCesiumRasterOverlay; + +UENUM(BlueprintType) +enum class ECesiumRasterOverlayLoadType : uint8 { + /** + * An unknown load error. + */ + Unknown, + + /** + * A Cesium ion asset endpoint. + */ + CesiumIon, + + /** + * @brief An initial load needed to create the overlay's tile provider. + */ + TileProvider +}; + +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumRasterOverlayLoadFailureDetails { + GENERATED_BODY() + + /** + * The overlay that encountered the load failure. + */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + TWeakObjectPtr Overlay = nullptr; + + /** + * The type of request that failed to load. + */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + ECesiumRasterOverlayLoadType Type = ECesiumRasterOverlayLoadType::Unknown; + + /** + * The HTTP status code of the response that led to the failure. + * + * If there was no response or the failure did not follow from a request, then + * the value of this property will be 0. + */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + int32 HttpStatusCode = 0; + + /** + * A human-readable explanation of what failed. + */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + FString Message; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRuntime.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRuntime.h new file mode 100644 index 0000000..cecfa9e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRuntime.h @@ -0,0 +1,54 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" +#include + +class ACesium3DTileset; +class UCesiumRasterOverlay; + +namespace CesiumAsync { +class AsyncSystem; +class IAssetAccessor; +class ICacheDatabase; +} // namespace CesiumAsync + +DECLARE_LOG_CATEGORY_EXTERN(LogCesium, Log, All); + +class FCesiumRuntimeModule : public IModuleInterface { +public: + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; + +/** + * The delegate for the OnCesium3DTilesetIonTroubleshooting, which is triggered + * when the tileset encounters a load error. + */ +DECLARE_MULTICAST_DELEGATE_OneParam( + FCesium3DTilesetIonTroubleshooting, + ACesium3DTileset*); + +CESIUMRUNTIME_API extern FCesium3DTilesetIonTroubleshooting + OnCesium3DTilesetIonTroubleshooting; + +/** + * The delegate for the OnCesiumRasterOverlayIonTroubleshooting, which is + * triggered when the tileset encounters a load error. + */ +DECLARE_MULTICAST_DELEGATE_OneParam( + FCesiumRasterOverlayIonTroubleshooting, + UCesiumRasterOverlay*); + +CESIUMRUNTIME_API extern FCesiumRasterOverlayIonTroubleshooting + OnCesiumRasterOverlayIonTroubleshooting; + +CESIUMRUNTIME_API CesiumAsync::AsyncSystem& getAsyncSystem() noexcept; +CESIUMRUNTIME_API const std::shared_ptr& +getAssetAccessor(); + +CESIUMRUNTIME_API std::shared_ptr& +getCacheDatabase(); diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRuntimeSettings.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRuntimeSettings.h new file mode 100644 index 0000000..83e430a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRuntimeSettings.h @@ -0,0 +1,69 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DeveloperSettings.h" +#include "CesiumRuntimeSettings.generated.h" + +/** + * Stores runtime settings for the Cesium plugin. + */ +UCLASS(Config = Engine, DefaultConfig, meta = (DisplayName = "Cesium")) +class CESIUMRUNTIME_API UCesiumRuntimeSettings : public UDeveloperSettings { + GENERATED_UCLASS_BODY() + +public: + UPROPERTY( + Config, + meta = + (DeprecatedProperty, + DeprecationMessage = + "Tokens are now configured on CesiumIonServer data assets.")) + FString DefaultIonAccessTokenId_DEPRECATED; + + UPROPERTY( + Config, + meta = + (DeprecatedProperty, + DeprecationMessage = + "Tokens are now configured on CesiumIonServer data assets.")) + FString DefaultIonAccessToken_DEPRECATED; + + UPROPERTY( + Config, + EditAnywhere, + Category = "Level of Detail", + meta = (DisplayName = "Scale Level-of-Detail by Display DPI")) + bool ScaleLevelOfDetailByDPI = true; + + /** + * Uses Unreal's occlusion culling engine to drive Cesium 3D Tiles selection, + * reducing the detail of tiles that are occluded by other objects in the + * scene so that less data overall needs to be loaded and rendered. + */ + UPROPERTY(Config, EditAnywhere, Category = "Experimental Feature Flags") + bool EnableExperimentalOcclusionCullingFeature = false; + + /** + * The number of requests to handle before each prune of old cached results + * from the database. + */ + UPROPERTY( + Config, + EditAnywhere, + Category = "Cache", + meta = (ConfigRestartRequired = true)) + int RequestsPerCachePrune = 10000; + + /** + * The maximum number of items that should be kept in the Sqlite database + * after pruning. + */ + UPROPERTY( + Config, + EditAnywhere, + Category = "Cache", + meta = (ConfigRestartRequired = true)) + int MaxCacheItems = 4096; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSampleHeightMostDetailedAsyncAction.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSampleHeightMostDetailedAsyncAction.h new file mode 100644 index 0000000..769182f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSampleHeightMostDetailedAsyncAction.h @@ -0,0 +1,71 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors +#pragma once + +#include "CesiumSampleHeightResult.h" +#include "Kismet/BlueprintAsyncActionBase.h" +#include "CesiumSampleHeightMostDetailedAsyncAction.generated.h" + +class ACesium3DTileset; + +/** + * The delegate used to asynchronously return sampled heights. + * @param Result The result of the height sampling. This array contains the + * outputs for each input cartographic position. Each result has a HeightSampled + * property indicating whether the height was successfully sampled at that + * position, and a LongitudeLatitudeHeight property with the complete position, + * including the sampled height. If the sample was unsuccessful, the original + * position is returned. + * @param Warnings Provides information about problems, if any, that were + * encountered while sampling heights. + */ +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams( + FCesiumSampleHeightMostDetailedComplete, + const TArray&, + Result, + const TArray&, + Warnings); + +UCLASS() +class CESIUMRUNTIME_API UCesiumSampleHeightMostDetailedAsyncAction + : public UBlueprintAsyncActionBase { + GENERATED_BODY() + +public: + /** + * Asynchronously samples the height of the tileset at a list of cartographic + * positions, each expressed as a Longitude (X) and Latitude (Y) in degrees. + * The Height (Z) provided on input is ignored unless the sampling fails at + * that position, in which case it is passed through to the output. + * @param Tileset The tileset from which to query heights. + * @param LongitudeLatitudeHeightArray The array of cartographic positions at + * which to query heights, with Longitude in the X component and Latitude in + * the Y component. + */ + UFUNCTION( + BlueprintCallable, + Category = "Cesium", + meta = (BlueprintInternalUseOnly = true)) + static UCesiumSampleHeightMostDetailedAsyncAction* SampleHeightMostDetailed( + ACesium3DTileset* Tileset, + const TArray& LongitudeLatitudeHeightArray); + + /** + * Called when height has been sampled at all of the given positions. The + * Result property contains an element for each input position and in the same + * order. The Warnings property provides information about problems that were + * encountered while sampling heights. + */ + UPROPERTY(BlueprintAssignable) + FCesiumSampleHeightMostDetailedComplete OnHeightsSampled; + + virtual void Activate() override; + +private: + void RaiseOnHeightsSampled( + ACesium3DTileset* Tileset, + const TArray& Result, + const TArray& Warnings); + + ACesium3DTileset* _pTileset; + TArray _longitudeLatitudeHeightArray; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSampleHeightResult.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSampleHeightResult.h new file mode 100644 index 0000000..27b0265 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSampleHeightResult.h @@ -0,0 +1,32 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumSampleHeightResult.generated.h" + +/** + * The result of sampling the height on a tileset at the given cartographic + * position. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumSampleHeightResult { + GENERATED_BODY() + + /** + * The Longitude (X) and Latitude (Y) are the same values provided on input. + * The Height (Z) is the height sampled from the tileset if the SampleSuccess + * property is true, or the original height provided on input if SampleSuccess + * is false. + */ + UPROPERTY(BlueprintReadWrite, Category = "Cesium") + FVector LongitudeLatitudeHeight = {0.0, 0.0, 0.0}; + + /** + * True if the height as sampled from the tileset successfully. False if the + * tileset doesn't have any height at that position, or if something went + * wrong. If something went wrong, the Warnings pin of the sampling function + * will have more information about the problem. + */ + UPROPERTY(BlueprintReadWrite, Category = "Cesium") + bool SampleSuccess = false; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSubLevel.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSubLevel.h new file mode 100644 index 0000000..9d66973 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSubLevel.h @@ -0,0 +1,87 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "CesiumSubLevel.generated.h" + +class ULevelStreaming; + +struct UE_DEPRECATED( + 5.0, + "The FCesiumSubLevel struct has been deprecated. Use Level Instance Actors and UCesiumSubLevelComponent instead.") + FCesiumSubLevel; + +/* + * Sublevels can be georeferenced to the globe by filling out this struct. + */ +USTRUCT() +struct FCesiumSubLevel { + GENERATED_BODY() + + /** + * The plain name of the sub level, without any prefixes. + */ + UPROPERTY(VisibleAnywhere, Category = "Cesium") + FString LevelName; + + /** + * Whether this sub-level is enabled. An enabled sub-level will be + * automatically loaded when the camera moves within its LoadRadius and + * no other levels are closer, and the Georeference will be updated so that + * this level's Longitude, Latitude, and Height bcome (0, 0, 0) in the Unreal + * World. A sub-level that is not enabled will be ignored by Cesium. + * + * If this option is greyed out, check that World Composition is enabled + * in the World Settings and that this sub-level is in a Layer that has + * Distance-based streaming DISABLED. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + Meta = (EditCondition = "CanBeEnabled")) + bool Enabled = true; + + /** + * The WGS84 latitude in degrees of where this level should sit on the globe, + * in the range [-90, 90] + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + meta = (ClampMin = -90.0, ClampMax = 90.0, EditCondition = "Enabled")) + double LevelLatitude = 0.0; + + /** + * The WGS84 longitude in degrees of where this level should sit on the + * globe, in the range [-180, 180] + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + meta = (ClampMin = -180.0, ClampMax = 180.0, EditCondition = "Enabled")) + double LevelLongitude = 0.0; + + /** + * The height in meters above the WGS84 globe this level should sit. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + meta = (EditCondition = "Enabled")) + double LevelHeight = 0.0; + + /** + * How far in meters from the sublevel local origin the camera needs to be to + * load the level. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + meta = (ClampMin = 0.0, EditCondition = "Enabled")) + double LoadRadius = 0.0; + + UPROPERTY(VisibleDefaultsOnly, Category = "Cesium") + bool CanBeEnabled = false; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSubLevelComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSubLevelComponent.h new file mode 100644 index 0000000..c781b91 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSubLevelComponent.h @@ -0,0 +1,408 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Components/ActorComponent.h" +#include "UObject/ObjectMacros.h" +#include "CesiumSubLevelComponent.generated.h" + +class ACesiumGeoreference; +class ALevelInstance; +class UCesiumSubLevelSwitcherComponent; + +/** + * A component intended to be attached to a Level Instance Actor that turns that + * Level Instance into a Cesium sub-level. Only a single Cesium sub-level can be + * active (visible) at any given time. + * + * A globe (like the planet Earth) is an unusual sort of level in Unreal in that + * it has truly massive coordinate values and the "up" direction depends on + * where exactly on the globe you're located. Many things in the Unreal + * ecosystem, such as the gravity system, don't expect this situation and will + * have incorrect and surprising behavior when used on a globe. + * + * Cesium sub-levels help to mitigate this. Only one sub-level can be active at + * any given time, and when it is, that sub-level's origin becomes the origin of + * the Unreal world. Furthermore, at the origin location, Unreal's +X axis + * points East, its +Y axis points South, and its +Z axis points Up. Thus, + * within a sub-level, gravity works in the normal way that Unreal objects + * expect, and coordinate values stay relatively small. This allows you to use + * just about any Unreal object within a sub-level without worrying about + * surprising behavior. + * + * Globe-aware objects, particularly those with a "Cesium Globe Anchor" + * component attached to them, are allowed to exist outside sub-levels and even + * move between them. If all your objects are globe aware, there's no need to + * use sub-levels at all. + * + * In the Editor, the currently-active sub-level is selected by clicking the + * "Eye" icon next to the Level Instance in the Outliner. + * + * At runtime, the currently-active sub-level is selected by the Actor with a + * CesiumOriginShiftComponent attached to it. If this Actor is inside a + * sub-level's "Load Radius" that sub-level will be activated. If multiple + * sub-levels are in range, only the closest one will be activated. + */ +UCLASS(ClassGroup = (Cesium), meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumSubLevelComponent : public UActorComponent { + GENERATED_BODY() + +public: + /** + * Gets whether this sub-level is enabled. An enabled sub-level will be + * automatically loaded when the camera moves within its LoadRadius and + * no other levels are closer, and the Georeference will be updated so that + * this level's Longitude, Latitude, and Height become (0, 0, 0) in the Unreal + * World. A sub-level that is not enabled will be ignored by Cesium at + * runtime. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + bool GetEnabled() const; + + /** + * Sets whether this sub-level is enabled. An enabled sub-level will be + * automatically loaded when the camera moves within its LoadRadius and + * no other levels are closer, and the Georeference will be updated so that + * this level's Longitude, Latitude, and Height become (0, 0, 0) in the Unreal + * World. A sub-level that is not enabled will be ignored by Cesium at + * runtime. + */ + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetEnabled(bool value); + + /** + * Gets the longitude of the georeference origin for this sub-level in + * degrees, in the range [-180, 180]. When this sub-level is active, the + * CesiumGeoreference will adopt this origin. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + double GetOriginLongitude() const; + + /** + * Sets the longitude of the georeference origin for this sub-level in + * degrees, in the range [-180, 180]. When this sub-level is active, the + * CesiumGeoreference will adopt this origin. + */ + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetOriginLongitude(double value); + + /** + * Gets the latitude of the georeference origin for this sub-level in degrees, + * in the range [-90, 90]. When this sub-level is active, the + * CesiumGeoreference will adopt this origin. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + double GetOriginLatitude() const; + + /** + * Sets the latitude of the georeference origin for this sub-level in degrees, + * in the range [-90, 90]. When this sub-level is active, the + * CesiumGeoreference will adopt this origin. + */ + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetOriginLatitude(double value); + + /** + * Gets the height of the georeference origin for this sub-level in meters + * above the ellipsoid. This height should not be confused with a height + * above Mean Sea Level. When this sub-level is active, the CesiumGeoreference + * will adopt this origin. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + double GetOriginHeight() const; + + /** + * Sets the height of the georeference origin for this sub-level in meters + * above the ellipsoid. This height should not be confused with a height + * above Mean Sea Level. When this sub-level is active, the CesiumGeoreference + * will adopt this origin. + */ + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetOriginHeight(double value); + + /** + * Gets how close to the sub-level local origin, in meters, the camera needs + * to be to load the level. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + double GetLoadRadius() const; + + /** + * Sets how close to the sub-level local origin, in meters, the camera needs + * to be to load the level. + */ + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetLoadRadius(double value); + + /** + * Gets the designated georeference actor controlling how the actor's + * coordinate system relates to the coordinate system in this Unreal Engine + * level. + * + * If this is null, the sub-level will find and use the first Georeference + * Actor in the level, or create one if necessary. To get the active/effective + * Georeference from Blueprints or C++, use ResolvedGeoreference instead. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + TSoftObjectPtr GetGeoreference() const; + + /** + * Sets the designated georeference actor controlling how the actor's + * coordinate system relates to the coordinate system in this Unreal Engine + * level. + * + * If this is null, the sub-level will find and use the first Georeference + * Actor in the level, or create one if necessary. To get the active/effective + * Georeference from Blueprints or C++, use ResolvedGeoreference instead. + */ + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetGeoreference(TSoftObjectPtr NewGeoreference); + + /** + * Gets the resolved georeference, just like calling the ResolveGeoreference + * property, except that it will return null if a georeference has not yet + * been resolved. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + ACesiumGeoreference* GetResolvedGeoreference() const; + + /** + * Resolves the Cesium Georeference to use with this components. Returns + * the value of the Georeference property if it is set. Otherwise, finds a + * Georeference in the World and returns it, creating it if necessary. The + * resolved Georeference is cached so subsequent calls to this function will + * return the same instance, unless ForceReresolve is true. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + ACesiumGeoreference* ResolveGeoreference(bool bForceReresolve = false); + + /** + * Sets the longitude (X), latitude (Y), and height (Z) of this sub-level's + * georeference origin. When this sub-level is active, the CesiumGeoreference + * will adopt this origin. Longitude and latitude are in degrees. Height is in + * meters above the ellipsoid, which should not be confused with meters + * above Mean Sea Level. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetOriginLongitudeLatitudeHeight(const FVector& longitudeLatitudeHeight); + +#if WITH_EDITOR + /** + * Places the georeference origin at the origin of the sub-level and sets the + * Level Instance's Location to (0,0,0). This improves the precision of the + * objects in the sub-level as well as makes the Load Radius more sensible. + * + * If your sub-level has any Cesium3DTilesets, Cesium for Unreal will enter + * Edit mode for the sub-level and the Cesium3DTilesets' transformations will + * be updated based on the new georeference origin. You should Commit this + * change. + * + * Warning: Before clicking, ensure that all non-Cesium objects in the + * persistent level are georeferenced with the "CesiumGeoreferenceComponent" + * or attached to an actor with that component. Ensure that static actors only + * exist in georeferenced sub-levels. + */ + UFUNCTION(CallInEditor, Category = "Cesium") + void PlaceGeoreferenceOriginAtSubLevelOrigin(); + + /** + * Places the sub-level's origin at the camera's current location. Rotates + * the globe so the current longitude/latitude/height of the camera is at the + * Unreal origin of this sub-level. The camera is also teleported to the new + * Unreal origin and rotated so that the view direction is maintained. + * + * This function is similar to "Place Georeference Origin Here" on the + * CesiumGeoreference, except that this moves the georeference origin while + * also ensuring that the sub-level content stays in the same place on the + * globe by adjusting the Level Instance's transform. + * + * If your sub-level has any Cesium3DTilesets, Cesium for Unreal will enter + * Edit mode for the sub-level and the Cesium3DTilesets' transformations will + * be updated based on the new georeference origin. You should Commit this + * change. + * + * Warning: Before clicking, ensure that all non-Cesium objects in the + * persistent level are georeferenced with the "CesiumGlobeAnchorComponent" + * or attached to an actor with that component. Ensure that static actors only + * exist in georeferenced sub-levels. + */ + UFUNCTION(CallInEditor, Category = "Cesium") + void PlaceGeoreferenceOriginHere(); +#endif + + /** + * If this sub-level is currently the active one, this method will copy its + * origin to the georeference's origin. Otherwise, it does nothing. + */ + void UpdateGeoreferenceIfSubLevelIsActive(); + + virtual void BeginDestroy() override; + virtual void OnComponentCreated() override; + +#if WITH_EDITOR + virtual void + PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; +#endif + +protected: + virtual void BeginPlay() override; + + /** + * Called when a component is registered. This can be viewed as "enabling" + * this Component on the Actor to which it is attached. + * + * In the Editor, this is called in a many different situations, such as on + * changes to properties. + */ + virtual void OnRegister() override; + + /** + * Called when a component is unregistered. This can be viewed as + * "disabling" this Component on the Actor to which it is attached. + * + * In the Editor, this is called in a many different situations, such as on + * changes to properties. + */ + virtual void OnUnregister() override; + +#if WITH_EDITOR + /** + * Called by the Editor to check if it's ok to edit a property on this object. + * Used to disable all fields on this component when editing the sub-level + * instance that this component is attached to. + */ + virtual bool CanEditChange(const FProperty* InProperty) const override; +#endif + +private: + /** + * Whether this sub-level is enabled. An enabled sub-level will be + * automatically loaded when the camera moves within its LoadRadius and + * no other levels are closer, and the Georeference will be updated so that + * this level's Longitude, Latitude, and Height become (0, 0, 0) in the Unreal + * World. A sub-level that is not enabled will be ignored by Cesium at + * runtime. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + BlueprintGetter = GetEnabled, + BlueprintSetter = SetEnabled, + meta = (AllowPrivateAccess = true)) + bool Enabled = true; + + /** + * The latitude of the georeference origin for this sub-level in degrees, in + * the range [-90, 90]. When this sub-level is active, the CesiumGeoreference + * will adopt this origin. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + BlueprintGetter = GetOriginLatitude, + BlueprintSetter = SetOriginLatitude, + meta = (ClampMin = -90.0, ClampMax = 90.0, AllowPrivateAccess = true)) + double OriginLatitude = 39.736401; + + /** + * The longitude of the georeference origin for this sub-level in degrees, in + * the range [-180, 180]. When this sub-level is active, the + * CesiumGeoreference will adopt this origin. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + BlueprintGetter = GetOriginLongitude, + BlueprintSetter = SetOriginLongitude, + meta = (ClampMin = -180.0, ClampMax = 180.0, AllowPrivateAccess = true)) + double OriginLongitude = -105.25737; + + /** + * The height of the georeference origin for this sub-level in meters above + * the ellipsoid. This height should not be confused with a height above + * Mean Sea Level. When this sub-level is active, the CesiumGeoreference will + * adopt this origin. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + BlueprintGetter = GetOriginHeight, + BlueprintSetter = SetOriginHeight, + meta = (AllowPrivateAccess = true)) + double OriginHeight = 2250.0; + + /** + * How close to the sub-level local origin, in meters, the camera needs to be + * to load the level. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + BlueprintGetter = GetLoadRadius, + BlueprintSetter = SetLoadRadius, + meta = (ClampMin = 0.0, AllowPrivateAccess = true)) + double LoadRadius = 1000.0; + + /** + * The designated georeference actor controlling how the actor's + * coordinate system relates to the coordinate system in this Unreal Engine + * level. + * + * If this is null, the sub-level will find and use the first Georeference + * Actor in the level, or create one if necessary. To get the active/effective + * Georeference from Blueprints or C++, use ResolvedGeoreference instead. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetGeoreference, + BlueprintSetter = SetGeoreference, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + TSoftObjectPtr Georeference; + + /** + * The resolved georeference used by this sub-level. This is not serialized + * because it may point to a Georeference in the PersistentLevel while this + * Actor is in a sub-level. If the Georeference property is specified, + * however then this property will have the same value. + * + * This property will be null before ResolveGeoreference is called. + */ + UPROPERTY( + Transient, + VisibleAnywhere, + BlueprintReadOnly, + BlueprintGetter = GetResolvedGeoreference, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + ACesiumGeoreference* ResolvedGeoreference = nullptr; + + /** + * Gets the sub-level switch component with which this sub-level is + * associated. Calling this method will call ResolveGeoreference to resolve + * the georeference, if it's not already resolved. + */ + UCesiumSubLevelSwitcherComponent* _getSwitcher() noexcept; + + /** + * Gets the Level Instance Actor to which this component is attached. If this + * component is not attached to a Level Instance Actor, this method logs a + * warning and returns nullptr. + */ + ALevelInstance* _getLevelInstance() const noexcept; + + /** + * Invalidates the cached resolved georeference, unsubscribing from it and + * setting it to null. The next time ResolveGeoreference is called, the + * Georeference will be re-resolved and re-subscribed. + */ + void _invalidateResolvedGeoreference(); + + void PlaceOriginAtEcef(const FVector& NewOriginEcef); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSubLevelSwitcherComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSubLevelSwitcherComponent.h new file mode 100644 index 0000000..a1ccb20 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSubLevelSwitcherComponent.h @@ -0,0 +1,112 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Components/ActorComponent.h" +#include "CesiumSubLevelSwitcherComponent.generated.h" + +class ACesiumGeoreference; +class ALevelInstance; +class ULevelStreaming; +class UWorld; + +/** + * Manages the asynchronous switching between sub-levels, making sure that a + * previous sub-level is hidden before the CesiumGeoreference is switched to a + * new location and the next sub-level is loaded. + */ +UCLASS(ClassGroup = "Cesium") +class CESIUMRUNTIME_API UCesiumSubLevelSwitcherComponent + : public UActorComponent { + GENERATED_BODY() + +public: + UCesiumSubLevelSwitcherComponent(); + + /** + * Gets the list of sub-levels that are currently registered with this + * switcher. + */ + UFUNCTION(BlueprintPure, Category = "Cesium|Sub-levels") + TArray GetRegisteredSubLevels() const noexcept; + + /** + * Gets the list of sub-levels that are currently registered with this + * switcher. This is slightly more efficient than GetRegisteredSubLevels but + * is not accessible from Blueprints. + */ + const TArray>& + GetRegisteredSubLevelsWeak() const noexcept { + return this->_sublevels; + } + + /** + * Gets the sub-level that is currently active, or nullptr if none are active. + */ + UFUNCTION(BlueprintPure, Category = "Cesium|Sub-levels") + ALevelInstance* GetCurrentSubLevel() const noexcept; + + /** + * Gets the sub-level that is in the process of becoming active. If nullptr, + * the target is a state where no sub-levels are active. + */ + UFUNCTION(BlueprintPure, Category = "Cesium|Sub-levels") + ALevelInstance* GetTargetSubLevel() const noexcept; + + /** + * Sets the sub-level that should be active. The switcher will asynchronously + * load and show this sub-level. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium|Sub-levels") + void SetTargetSubLevel(ALevelInstance* LevelInstance) noexcept; + +private: + // To allow the sub-level to register/unregister itself with the functions + // below. + friend class UCesiumSubLevelComponent; + friend class CesiumEditorSubLevelMutex; + + /** + * Registers a sub-level with this switcher. The switcher will ensure that + * no more than one of the registered sub-levels is active at any time. + */ + void RegisterSubLevel(ALevelInstance* pSubLevel) noexcept; + + /** + * Unregisters a sub-level from this switcher. This is primarily used if the + * sub-level is being destroyed or reparented. + */ + void UnregisterSubLevel(ALevelInstance* pSubLevel) noexcept; + + virtual void TickComponent( + float DeltaTime, + enum ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) override; + + void _updateSubLevelStateGame(); +#if WITH_EDITOR + void _updateSubLevelStateEditor(); +#endif + + /** + * Finds the ULevelStreaming instance, if any, associated with a given + * sub-level. + */ + ULevelStreaming* + _getLevelStreamingForSubLevel(ALevelInstance* SubLevel) const; + + // Don't save/load or copy this. + UPROPERTY(Transient, DuplicateTransient, TextExportTransient) + TArray> _sublevels; + + // Don't save/load or copy this. + UPROPERTY(Transient, DuplicateTransient, TextExportTransient) + TWeakObjectPtr _pCurrent = nullptr; + + // Save/load this, but don't copy it. + UPROPERTY(DuplicateTransient, TextExportTransient) + TWeakObjectPtr _pTarget = nullptr; + + bool _doExtraChecksOnNextTick = false; + bool _isTransitioningSubLevels = false; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSunSky.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSunSky.h new file mode 100644 index 0000000..e49fd67 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSunSky.h @@ -0,0 +1,530 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" + +#include "CesiumGeoreference.h" +#include "Components/DirectionalLightComponent.h" +#include "Components/SkyAtmosphereComponent.h" +#include "Components/SkyLightComponent.h" +#include "Components/StaticMeshComponent.h" +#include "Engine/DirectionalLight.h" +#include "GameFramework/Actor.h" +#include "CesiumSunSky.generated.h" + +class UCesiumGlobeAnchorComponent; + +/** + * A globe-aware sun sky actor. If the georeference is set to CartographicOrigin + * (aka Longitude/Latitude/Height) mode, then this actor will automatically + * sync its longitude and latitude properties with the georeference's, and + * recalculate the sun position whenever those properties change. + * + * Note: because we use `Planet Center at Component Transform` + * for the SkyAtmosphere transform mode, this actor's location will be forced + * to the Earth's center if the georeference is set to CartographicOrigin. + */ +UCLASS() +class CESIUMRUNTIME_API ACesiumSunSky : public AActor { + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + ACesiumSunSky(); + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Components) + USceneComponent* Scene; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Components) + USkyLightComponent* SkyLight; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Components) + UDirectionalLightComponent* DirectionalLight; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Components) + USkyAtmosphereComponent* SkyAtmosphere; + + /** + * The Globe Anchor Component that precisely ties this Actor to the Globe. + */ + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Components) + UCesiumGlobeAnchorComponent* GlobeAnchor; + + /** + * Gets the time zone, represented as hours offset from GMT. + * + * After changing this value from Blueprints or C++, you must call UpdateSun + * for it to take effect. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Date and Time", + meta = (ClampMin = -12, ClampMax = 14)) + double TimeZone = -5.0; + + /** + * The current solar time represented as hours from midnight. + * + * After changing this value from Blueprints or C++, you must call UpdateSun + * for it to take effect. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Date and Time", + meta = (UIMin = 4, UIMax = 22, ClampMin = 0, ClampMax = 23.9999)) + double SolarTime = 13.0; + + /** + * The day of the month. + * + * After changing this value from Blueprints or C++, you must call UpdateSun + * for it to take effect. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Date and Time", + meta = (ClampMin = 1, ClampMax = 31)) + int32 Day = 21; + + /** + * The month of the year, where 1 is January and 12 is December. + * + * After changing this value from Blueprints or C++, you must call UpdateSun + * for it to take effect. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Date and Time", + meta = (ClampMin = 1, ClampMax = 12)) + int32 Month = 9; + + /** + * The year. + * + * After changing this value from Blueprints or C++, you must call UpdateSun + * for it to take effect. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Date and Time", + meta = (UIMin = 1800, UIMax = 2200, ClampMin = 0, ClampMax = 4000)) + int32 Year = 2019; + + /** + * Offset in the sun's position. Should be set to -90 for the sun's position + * to be accurate in the Unreal reference frame. + * + * After changing this value from Blueprints or C++, you must call UpdateSun + * for it to take effect. + */ + UPROPERTY( + BlueprintReadWrite, + Category = "Cesium|Date and Time", + meta = (ClampMin = -360, ClampMax = 360)) + double NorthOffset = -90.0; + + /** + * Enables adjustment of the Solar Time for Daylight Saving Time (DST). + * + * After changing this value from Blueprints or C++, you must call UpdateSun + * for it to take effect. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Date and Time|Daylight Savings") + bool UseDaylightSavingTime = true; + +protected: + /** + * THIS PROPERTY IS DEPRECATED. + * + * Get the Georeference instance from the Globe Anchor Component instead. + */ + UPROPERTY( + BlueprintReadOnly, + Category = "Cesium", + BlueprintGetter = GetGeoreference, + Meta = + (DeprecatedProperty, + DeprecationMessage = + "Get the Georeference instance from the Globe Anchor Component instead.")) + ACesiumGeoreference* Georeference_DEPRECATED; + + /** + * Gets the Georeference Actor associated with this instance. It is obtained + * from the Globe Anchor Component. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + ACesiumGeoreference* GetGeoreference() const; + + /** + * Set the Date at which DST starts in the current year. + * + * After changing this value from Blueprints or C++, you must call UpdateSun + * for it to take effect. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Date and Time|Daylight Savings", + meta = (ClampMin = 1, ClampMax = 12), + meta = (EditCondition = "UseDaylightSavingTime")) + int32 DSTStartMonth = 3; + + /** + * Set the Date at which DST starts in the current year. + * + * After changing this value from Blueprints or C++, you must call UpdateSun + * for it to take effect. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Date and Time|Daylight Savings", + meta = (ClampMin = 1, ClampMax = 31), + meta = (EditCondition = "UseDaylightSavingTime")) + int32 DSTStartDay = 10; + + /** + * Set the Date at which DST ends in the current year. + * + * After changing this value from Blueprints or C++, you must call UpdateSun + * for it to take effect. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Date and Time|Daylight Savings", + meta = (ClampMin = 1, ClampMax = 12), + meta = (EditCondition = "UseDaylightSavingTime")) + int32 DSTEndMonth = 11; + + /** + * Set the Date at which DST ends in the current year. + * + * After changing this value from Blueprints or C++, you must call UpdateSun + * for it to take effect. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Date and Time|Daylight Savings", + meta = (ClampMin = 1, ClampMax = 31), + meta = (EditCondition = "UseDaylightSavingTime")) + int32 DSTEndDay = 3; + + /** + * Hour of the DST Switch for both beginning and end. + * + * After changing this value from Blueprints or C++, you must call UpdateSun + * for it to take effect. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium|Date and Time|Daylight Savings", + meta = (ClampMin = 0, ClampMax = 23), + meta = (EditCondition = "UseDaylightSavingTime")) + int32 DSTSwitchHour = 2; + + /** + * Updates the atmosphere automatically given current player pawn's longitude, + * latitude, and height. Fixes artifacts seen with the atmosphere rendering + * when flying high above the surface, or low to the ground in high latitudes. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Atmosphere") + bool UpdateAtmosphereAtRuntime = true; + + /** + * When the player pawn is below this height, which is expressed in kilometers + * above the ellipsoid, this Actor will use an atmosphere ground radius that + * is calculated to be at or below the terrain surface at the player pawn's + * current location. This avoids a gap between the bottom of the atmosphere + * and the top of the terrain when zoomed in close to the terrain surface. + * + * Above CircumscribedGroundThreshold, this Actor will use an atmosphere + * ground radius that is guaranteed to be above the terrain surface anywhere + * on Earth. This avoids artifacts caused by terrain poking through the + * atmosphere when viewing the Earth from far away. + * + * At player pawn heights in between InscribedGroundThreshold and + * CircumscribedGroundThreshold, this Actor uses a linear interpolation + * between the two ground radii. + * + * This value is automatically scaled according to the CesiumGeoreference + * Scale and the Actor scale. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + meta = (EditCondition = "UpdateAtmosphereAtRuntime"), + Category = "Cesium|Atmosphere") + double InscribedGroundThreshold = 30.0; + + /** + * When the player pawn is above this height, which is expressed in kilometers + * above the ellipsoid, this Actor will use an atmosphere ground radius that + * is guaranteed to be above the terrain surface anywhere on Earth. This + * avoids artifacts caused by terrain poking through the atmosphere when + * viewing the Earth from far away. + * + * Below InscribedGroundThreshold, this Actor will use an atmosphere + * ground radius that is calculated to be at or below the terrain surface at + * the player pawn's current location. This avoids a gap between the bottom of + * the atmosphere and the top of the terrain when zoomed in close to the + * terrain surface. + * + * At heights in between InscribedGroundThreshold and + * CircumscribedGroundThreshold, this Actor uses a linear interpolation + * between the two ground radii. + * + * This value is automatically scaled according to the CesiumGeoreference + * Scale and the Actor scale. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + meta = (EditCondition = "UpdateAtmosphereAtRuntime"), + Category = "Cesium|Atmosphere") + double CircumscribedGroundThreshold = 100.0; + + /** + * The height at which to place the bottom of the atmosphere when the player + * pawn is above the CircumscribedGroundThreshold. This is expressed as a + * height in kilometers above the maximum radius of the ellipsoid (usually + * WGS84). To avoid dark splotchy artifacts in the atmosphere when zoomed out + * far from the globe, this value must be above the greatest height achieved + * by any part of the tileset. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + meta = (EditCondition = "UpdateAtmosphereAtRuntime"), + Category = "Cesium|Atmosphere") + double CircumscribedGroundHeight = 0.0; + + /** + * The height of the atmosphere layer above the ground, in kilometers. This + * value is automatically scaled according to the CesiumGeoreference Scale and + * the Actor scale. However, Unreal Engine's SkyAtmosphere has a hard-coded + * minimum effective value of 0.1, so the atmosphere will look too thick when + * the globe is scaled down drastically. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadOnly, + interp, + Category = "Cesium|Atmosphere", + meta = (UIMin = 1.0, UIMax = 200.0, ClampMin = 0.1, SliderExponent = 2.0)) + float AtmosphereHeight = 60.0f; + + /** + * Makes the aerial perspective look thicker by scaling distances from view + * to surfaces (opaque and translucent). This value is automatically scaled + * according to the CesiumGeoreference Scale and the Actor scale. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadOnly, + interp, + Category = "Cesium|Atmosphere", + meta = + (DisplayName = "Aerial Perspective View Distance Scale", + UIMin = 0.0, + UIMax = 3.0, + ClampMin = 0.0, + SliderExponent = 2.0)) + float AerialPerspectiveViewDistanceScale = 1.0f; + + /** + * The altitude in kilometers at which Rayleigh scattering effect is reduced + * to 40%. This value is automatically scaled according to the + * CesiumGeoreference Scale and the Actor scale. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadOnly, + interp, + Category = "Cesium|Atmosphere", + meta = + (UIMin = 0.01, UIMax = 20.0, ClampMin = 0.001, SliderExponent = 5.0)) + float RayleighExponentialDistribution = 8.0f; + + /** + * The altitude in kilometers at which Mie effects are reduced to 40%. This + * value is automatically scaled according to the CesiumGeoreference Scale and + * the Actor scale. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadOnly, + interp, + Category = "Cesium|Atmosphere", + meta = + (UIMin = 0.01, UIMax = 10.0, ClampMin = 0.001, SliderExponent = 5.0)) + float MieExponentialDistribution = 1.2f; + + /** + * False: Use Directional Light component inside CesiumSunSky. + * True: Use the assigned Directional Light in the level. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Sun") + bool UseLevelDirectionalLight = false; + + /** + * Reference to a manually assigned Directional Light in the level. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Sun") + ADirectionalLight* LevelDirectionalLight; + + /** + * The current sun elevation in degrees above the horizontal, as viewed from + * the Georeference origin. + */ + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Sun") + double Elevation = 0.f; + + /** + * The current sun elevation, corrected for atmospheric diffraction, in + * degrees above the horizontal, as viewed from the Georeference origin. + */ + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Sun") + double CorrectedElevation = 0.f; + + /** + * The current sun azimuth in degrees clockwise from North toward East, as + * viewed from the Georeference origin. + */ + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Sun") + double Azimuth = 0.f; + + /** + * A switch to toggle between desktop and mobile rendering code paths. + * This will NOT be automatically set when running on mobile, so make sure + * to check this setting before building on mobile platforms. + */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cesium|Mobile") + bool UseMobileRendering; + + /** + * Mobile platforms currently do not support the SkyAtmosphereComponent. + * In lieu of that, use the engine BP_Sky_Sphere class, or a derived class. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Mobile") + TSubclassOf SkySphereClass; + + /** + * Reference to BP_Sky_Sphere or similar actor (mobile only) + */ + UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Cesium|Mobile") + AActor* SkySphereActor; + + /** + * Default intensity of directional light that's spawned for mobile rendering. + */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cesium|Mobile") + double MobileDirectionalLightIntensity = 6.f; + +public: + UFUNCTION( + CallInEditor, + BlueprintCallable, + BlueprintNativeEvent, + Category = "Cesium") + void UpdateSun(); + void UpdateSun_Implementation(); + + UFUNCTION(CallInEditor, BlueprintCallable, Category = "Cesium") + void UpdateAtmosphereRadius(); + + /** + * Convert solar time to Hours:Minutes:Seconds. Copied the implementation + * from the engine SunSkyBP class. + */ + UFUNCTION(BlueprintCallable, BlueprintPure, Category = Sun) + static void GetHMSFromSolarTime( + double InSolarTime, + int32& Hour, + int32& Minute, + int32& Second); + + /** + * Check whether the current time and date (based on this class instance's + * properties) falls within Daylight Savings Time. Copied the implementation + * from the engine SunSkyBP class. + */ + UFUNCTION(BlueprintCallable, BlueprintPure, Category = Sun) + bool IsDST( + bool DSTEnable, + int32 InDSTStartMonth, + int32 InDSTStartDay, + int32 InDSTEndMonth, + int32 InDSTEndDay, + int32 InDSTSwitchHour) const; + + // Begin AActor Interface + /** + * Gets called when the actor is first created, and when properties are + * changed at edit-time. Refreshes the actor's position w/r/t the georeference + * and handles mobile-specific setup if needed. + */ + virtual void OnConstruction(const FTransform& Transform) override; + // End AActor Interface + +protected: + /** + * Modifies the sky atmosphere's ground radius, which represents the Earth's + * radius in the SkyAtmosphere rendering model. Only changes if there's a >0.1 + * difference, to reduce redraws. + * + * @param Sky A pointer to the SkyAtmosphereComponent + * @param Radius The radius in kilometers. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void + SetSkyAtmosphereGroundRadius(USkyAtmosphereComponent* Sky, double Radius); + + /** + * Update MobileSkySphere by calling its RefreshMaterial function + */ + UFUNCTION(BlueprintCallable, Category = "Mobile") + void UpdateSkySphere(); + + virtual void BeginPlay() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + virtual void Serialize(FArchive& Ar) override; + virtual void Tick(float DeltaSeconds) override; + virtual void PostLoad() override; + virtual bool ShouldTickIfViewportsOnly() const override; + +#if WITH_EDITOR + virtual void + PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; +#endif + +private: + void _spawnSkySphere(); + double _computeScale() const; + + // Sets Directional Light Component in Sky Sphere actor + void _setSkySphereDirectionalLight(); + + void _setSkyAtmosphereVisibility(bool bVisible); + + // Determines whether mobile sky sphere will be spawned during OnConstruction. + bool _wantsSpawnMobileSkySphere; + + void _handleTransformUpdated( + USceneComponent* InRootComponent, + EUpdateTransformFlags UpdateTransformFlags, + ETeleportType Teleport); + + FDelegateHandle _transformUpdatedSubscription; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumTile.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumTile.h new file mode 100644 index 0000000..9a3d4f9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumTile.h @@ -0,0 +1,47 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include +#include "CesiumTile.generated.h" + +/** + * A UObject representation of a Cesium Tile. + * This class provides an interface for accessing properties of a Cesium Tile + * from within Unreal Engine. It exposes the Bounds property, which can be + * accessed from Blueprints, and provides a helper function for testing + * intersection with a primitive component. + */ +UCLASS() +class CESIUMRUNTIME_API UCesiumTile : public UPrimitiveComponent { + GENERATED_BODY() + + glm::dmat4 _tileTransform; + + Cesium3DTilesSelection::BoundingVolume _tileBounds = + CesiumGeometry::OrientedBoundingBox(glm::dvec3(0.0), glm::dmat3(1.0)); + +public: + /** + * Tests whether a primitive component overlaps with this tile using a sphere + * and box comparison. This function provides a convenient way to test for + * intersection between a primitive component and this tile. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + bool TileBoundsOverlapsPrimitive(const UPrimitiveComponent* Other) const; + + /** + * Checks if this tile is fully inside the given primitive component using a + * sphere and box comparison. It uses the FBox::IsInside function to compare + * the FBox of the component and the tile's bounds. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + bool + PrimitiveBoxFullyContainsTileBounds(const UPrimitiveComponent* Other) const; + + virtual FBoxSphereBounds + CalcBounds(const FTransform& LocalToWorld) const override; + + friend class CesiumTileExcluderAdapter; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumTileExcluder.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumTileExcluder.h new file mode 100644 index 0000000..93e09aa --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumTileExcluder.h @@ -0,0 +1,76 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once +#include "CesiumTile.h" +#include "CoreMinimal.h" +#include "CesiumTileExcluder.generated.h" + +class CesiumTileExcluderAdapter; + +/** + * An actor component for excluding Cesium Tiles. + * This class provides an interface for excluding Cesium Tiles from a tileset. + * You can create a blueprint that derives from this class and override the + * `ShouldExclude` function to implement custom logic for determining whether a + * tile should be excluded. This function can be implemented in either C++ or + * Blueprints. + */ +UCLASS( + ClassGroup = (Cesium), + meta = (BlueprintSpawnableComponent), + Blueprintable, + Abstract) +class CESIUMRUNTIME_API UCesiumTileExcluder : public UActorComponent { + GENERATED_BODY() +private: + CesiumTileExcluderAdapter* pExcluderAdapter; + + UPROPERTY() + UCesiumTile* CesiumTile; + +public: + UCesiumTileExcluder(const FObjectInitializer& ObjectInitializer); + + virtual void Activate(bool bReset) override; + virtual void Deactivate() override; + virtual void OnComponentDestroyed(bool bDestroyingHierarchy) override; + +#if WITH_EDITOR + // Called when properties are changed in the editor + virtual void + PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; +#endif + + /** + * Adds this tile excluder to its owning Cesium 3D Tileset Actor. If the + * excluder is already added or if this component's Owner is not a Cesium 3D + * Tileset, this method does nothing. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void AddToTileset(); + + /** + * Removes this tile excluder from its owning Cesium 3D Tileset Actor. If the + * excluder is not yet added or if this component's Owner is not a Cesium 3D + * Tileset, this method does nothing. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void RemoveFromTileset(); + + /** + * Refreshes this tile excluderby removing from its owning Cesium 3D Tileset + * Actor and re-adding it. If this component's Owner is not a Cesium 3D + * Tileset Actor, this method does nothing. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void Refresh(); + + /** + * Determines whether a tile should be excluded. + * This function is called to determine whether a tile should be excluded from + * the tileset. You can override this function in a derived class or blueprint + * to implement custom exclusion logic. + */ + UFUNCTION(BlueprintNativeEvent) + bool ShouldExclude(const UCesiumTile* TileObject); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumTileMapServiceRasterOverlay.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumTileMapServiceRasterOverlay.h new file mode 100644 index 0000000..db64a15 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumTileMapServiceRasterOverlay.h @@ -0,0 +1,58 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumRasterOverlay.h" +#include "Components/ActorComponent.h" +#include "CoreMinimal.h" +#include "CesiumTileMapServiceRasterOverlay.generated.h" + +/** + * A raster overlay that directly accesses a Tile Map Service (TMS) server. If + * you're using a Tile Map Service via Cesium ion, use the "Cesium ion Raster + * Overlay" component instead. + */ +UCLASS(ClassGroup = (Cesium), meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumTileMapServiceRasterOverlay + : public UCesiumRasterOverlay { + GENERATED_BODY() + +public: + /** + * The base URL of the Tile Map Service (TMS). + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + FString Url; + + /** + * True to directly specify minum and maximum zoom levels available from the + * server, or false to automatically determine the minimum and maximum zoom + * levels from the server's tilemapresource.xml file. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + bool bSpecifyZoomLevels = false; + + /** + * Minimum zoom level. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (EditCondition = "bSpecifyZoomLevels", ClampMin = 0)) + int32 MinimumLevel = 0; + + /** + * Maximum zoom level. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (EditCondition = "bSpecifyZoomLevels", ClampMin = 0)) + int32 MaximumLevel = 10; + +protected: + virtual std::unique_ptr CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options = {}) override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumWebMapServiceRasterOverlay.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumWebMapServiceRasterOverlay.h new file mode 100644 index 0000000..1b2f284 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumWebMapServiceRasterOverlay.h @@ -0,0 +1,81 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumRasterOverlay.h" +#include "Components/ActorComponent.h" +#include "CoreMinimal.h" +#include "CesiumWebMapServiceRasterOverlay.generated.h" + +/** + * A raster overlay that directly accesses a Web Map Service (WMS) server. + * https://www.ogc.org/standards/wms + */ +UCLASS(ClassGroup = (Cesium), meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumWebMapServiceRasterOverlay + : public UCesiumRasterOverlay { + GENERATED_BODY() + +public: + /** + * The base url of the Web Map Service (WMS). + * e.g. + * https://services.ga.gov.au/gis/services/NM_Culture_and_Infrastructure/MapServer/WMSServer + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + FString BaseUrl; + + /** + * Comma-separated layer names to request from the server. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + FString Layers; + + /** + * Image width + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (ClampMin = 64, ClampMax = 2048)) + int32 TileWidth = 256; + + /** + * Image height + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (ClampMin = 64, ClampMax = 2048)) + int32 TileHeight = 256; + + /** + * Minimum zoom level. + * + * Take care when specifying this that the number of tiles at the minimum + * level is small, such as four or less. A larger number is likely to + * result in rendering problems. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (ClampMin = 0)) + int32 MinimumLevel = 0; + + /** + * Maximum zoom level. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (ClampMin = 0)) + int32 MaximumLevel = 14; + +protected: + virtual std::unique_ptr CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options = {}) override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumWebMapTileServiceRasterOverlay.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumWebMapTileServiceRasterOverlay.h new file mode 100644 index 0000000..0a305df --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumWebMapTileServiceRasterOverlay.h @@ -0,0 +1,275 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumRasterOverlay.h" +#include "Components/ActorComponent.h" +#include "CoreMinimal.h" +#include "CesiumWebMapTileServiceRasterOverlay.generated.h" + +/** + * Specifies the type of projection used for projecting a Web Map Tile Service + * raster overlay. + */ +UENUM(BlueprintType) +enum class ECesiumWebMapTileServiceRasterOverlayProjection : uint8 { + /** + * The raster overlay is projected using Web Mercator. + */ + WebMercator, + + /** + * The raster overlay is projected using a geographic projection. + */ + Geographic +}; + +/** + * A raster overlay that directly accesses a Web Map Tile Service (WMTS) server. + * If you're using a Web Map Tile Service via Cesium ion, use the "Cesium ion + * Raster Overlay" component instead. + */ +UCLASS(ClassGroup = (Cesium), meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumWebMapTileServiceRasterOverlay + : public UCesiumRasterOverlay { + GENERATED_BODY() + +public: + /** + * The base URL of the Web Map Tile Service (WMTS). + * This URL should not include query parameters. For example: + * https://tile.openstreetmap.org/{TileMatrix}/{TileCol}/{TileRow}.png + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + FString BaseUrl; + + /** + * The layer name for WMTS requests. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + FString Layer; + + /** + * The style name for WMTS requests. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + FString Style; + + /** + * The MIME type for images to retrieve from the server. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + FString Format = "image/jpeg"; + + /** + * The tile matrix set identifier for WMTS requests. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + FString TileMatrixSetID; + + /** + * The prefix to use for the tile matrix set labels. For instance, setting + * "EPSG:4326:" as prefix generates label list ["EPSG:4326:0", "EPSG:4326:1", + * "EPSG:4326:2", ...] + * Only applicable when "Specify Tile Matrix Set Labels" is false. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (EditCondition = "!bSpecifyTileMatrixSetLabels")) + FString TileMatrixSetLabelPrefix; + + /** + * Set this to true to specify tile matrix set labels manually. If false, the + * labels will be constructed from the specified levels and prefix (if one is + * specified). + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + bool bSpecifyTileMatrixSetLabels = false; + + /** + * The manually specified tile matrix set labels. + * + * Only applicable when "Specify Tile Matrix Set Labels" is true. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (EditCondition = "bSpecifyTileMatrixSetLabels")) + TArray TileMatrixSetLabels; + + UPROPERTY( + meta = + (DeprecatedProperty, DeprecationMessage = "Use Projection instead.")) + bool UseWebMercatorProjection_DEPRECATED; + + /** + * The type of projection used to project the WMTS imagery onto the globe. + * For instance, EPSG:4326 uses geographic projection and EPSG:3857 uses Web + * Mercator. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + ECesiumWebMapTileServiceRasterOverlayProjection Projection = + ECesiumWebMapTileServiceRasterOverlayProjection::WebMercator; + + /** + * Set this to true to specify the quadtree tiling scheme according to the + * specified root tile numbers and projected bounding rectangle. If false, the + * tiling scheme will be deduced from the projection. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + bool bSpecifyTilingScheme = false; + + /** + * The number of tiles corresponding to TileCol, also known as + * TileMatrixWidth. If specified, this determines the number of tiles at the + * root of the quadtree tiling scheme in the X direction. + * + * Only applicable if "Specify Tiling Scheme" is set to true. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (EditCondition = "bSpecifyTilingScheme", ClampMin = 1)) + int32 RootTilesX = 1; + + /** + * The number of tiles corresponding to TileRow, also known as + * TileMatrixHeight. If specified, this determines the number of tiles at the + * root of the quadtree tiling scheme in the Y direction. + * + * Only applicable if "Specify Tiling Scheme" is set to true. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (EditCondition = "bSpecifyTilingScheme", ClampMin = 1)) + int32 RootTilesY = 1; + + /** + * The west boundary of the bounding rectangle used for the quadtree tiling + * scheme. Specified in longitude degrees in the range [-180, 180]. + * + * Only applicable if "Specify Tiling Scheme" is set to true. + */ + UPROPERTY( + Category = "Cesium", + EditAnywhere, + BlueprintReadWrite, + meta = + (EditCondition = "bSpecifyTilingScheme", + ClampMin = -180.0, + ClampMax = 180.0)) + double RectangleWest = -180; + + /** + * The south boundary of the bounding rectangle used for the quadtree tiling + * scheme. Specified in latitude degrees in the range [-90, 90]. + * + * Only applicable if "Specify Tiling Scheme" is set to true. + */ + UPROPERTY( + Category = "Cesium", + Category = "Cesium", + EditAnywhere, + BlueprintReadWrite, + meta = + (EditCondition = "bSpecifyTilingScheme", + ClampMin = -90.0, + ClampMax = 90.0)) + double RectangleSouth = -90; + + /** + * The east boundary of the bounding rectangle used for the quadtree tiling + * scheme. Specified in longitude degrees in the range [-180, 180]. + * + * Only applicable if "Specify Tiling Scheme" is set to true. + */ + UPROPERTY( + Category = "Cesium", + EditAnywhere, + BlueprintReadWrite, + meta = + (EditCondition = "bSpecifyTilingScheme", + ClampMin = -180.0, + ClampMax = 180.0)) + double RectangleEast = 180; + + /** + * The north boundary of the bounding rectangle used for the quadtree tiling + * scheme. Specified in latitude degrees in the range [-90, 90]. + * + * Only applicable if "Specify Tiling Scheme" is set to true. + */ + UPROPERTY( + Category = "Cesium", + EditAnywhere, + BlueprintReadWrite, + meta = + (EditCondition = "bSpecifyTilingScheme", + ClampMin = -90.0, + ClampMax = 90.0)) + double RectangleNorth = 90; + + /** + * Set this to true to directly specify the minimum and maximum zoom levels + * available from the server. If false, the minimum and maximum zoom levels + * will be retrieved from the server's tilemapresource.xml file. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + bool bSpecifyZoomLevels = false; + + /** + * Minimum zoom level. + * + * Take care when specifying this that the number of tiles at the minimum + * level is small, such as four or less. A larger number is likely to result + * in rendering problems. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (EditCondition = "bSpecifyZoomLevels", ClampMin = 0)) + int32 MinimumLevel = 0; + + /** + * Maximum zoom level. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (EditCondition = "bSpecifyZoomLevels", ClampMin = 0)) + int32 MaximumLevel = 25; + + /** + * The pixel width of the image tiles. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (ClampMin = 64, ClampMax = 2048)) + int32 TileWidth = 256; + + /** + * The pixel height of the image tiles. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + Category = "Cesium", + meta = (ClampMin = 64, ClampMax = 2048)) + int32 TileHeight = 256; + + virtual void Serialize(FArchive& Ar) override; + +protected: + virtual std::unique_ptr CreateOverlay( + const CesiumRasterOverlays::RasterOverlayOptions& options = {}) override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumWgs84Ellipsoid.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumWgs84Ellipsoid.h new file mode 100644 index 0000000..a2cc3e4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumWgs84Ellipsoid.h @@ -0,0 +1,92 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumRuntime.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Misc/Optional.h" +#include "CesiumWgs84Ellipsoid.generated.h" + +UCLASS() +class CESIUMRUNTIME_API UCesiumWgs84Ellipsoid + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the radii of the WGS84 ellipsoid in its x-, y-, and z-directions in + * meters. + */ + UFUNCTION(BlueprintPure, Category = "Cesium|Ellipsoid|WGS84") + static FVector GetRadii(); + + /** + * Gets the maximum radius of the WGS84 ellipsoid in any dimension, in meters. + */ + UFUNCTION(BlueprintPure, Category = "Cesium|Ellipsoid|WGS84") + static double GetMaximumRadius(); + + /** + * Gets the minimum radius of the WGS854 ellipsoid in any dimension, in + * meters. + */ + UFUNCTION(BlueprintPure, Category = "Cesium|Ellipsoid|WGS84") + static double GetMinimumRadius(); + + /** + * Scale the given Earth-Centered, Earth-Fixed position along the geodetic + * surface normal so that it is on the surface of the ellipsoid. If the + * position is near the center of the ellipsoid, the result will have the + * value (0,0,0) because the surface position is undefined. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium|Ellipsoid|WGS84", + meta = (ReturnDisplayName = "SurfacePosition")) + static FVector + ScaleToGeodeticSurface(const FVector& EarthCenteredEarthFixedPosition); + + /** + * Computes the normal of the plane tangent to the surface of the ellipsoid + * at the provided Earth-Centered, Earth-Fixed position. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium|Ellipsoid|WGS84", + meta = (ReturnDisplayName = "SurfaceNormalVector")) + static FVector + GeodeticSurfaceNormal(const FVector& EarthCenteredEarthFixedPosition); + + /** + * Convert longitude in degrees (X), latitude in degrees (Y), and height above + * the WGS84 ellipsoid in meters (Z) to Earth-Centered, Earth-Fixed (ECEF) + * coordinates. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium|Ellipsoid|WGS84", + meta = (ReturnDisplayName = "EarthCenteredEarthFixedPosition")) + static FVector LongitudeLatitudeHeightToEarthCenteredEarthFixed( + const FVector& LongitudeLatitudeHeight); + + /** + * Convert Earth-Centered, Earth-Fixed (ECEF) coordinates to longitude in + * degrees (X), latitude in degrees (Y), and height above the WGS84 ellipsoid + * in meters (Z). If the position is near the center of the Earth, the result + * will have the value (0,0,0) because the longitude, latitude, and height are + * undefined. + */ + UFUNCTION( + BlueprintPure, + Category = "Cesium|Ellipsoid|WGS84", + meta = (ReturnDisplayName = "LongitudeLatitudeHeight")) + static FVector EarthCenteredEarthFixedToLongitudeLatitudeHeight( + const FVector& EarthCenteredEarthFixedPosition); + + /** + * Computes the transformation matrix from the local East-North-Up (ENU) frame + * to Earth-Centered, Earth-Fixed (ECEF) at the specified ECEF location. + */ + static FMatrix EastNorthUpToEarthCenteredEarthFixed( + const FVector& EarthCenteredEarthFixedPosition); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CustomDepthParameters.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CustomDepthParameters.h new file mode 100644 index 0000000..753a4ad --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CustomDepthParameters.h @@ -0,0 +1,54 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include +#include + +#include "CustomDepthParameters.generated.h" + +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCustomDepthParameters { + GENERATED_USTRUCT_BODY() + +public: + /** If true, this component will be rendered in the CustomDepth pass (usually + * used for outlines) */ + UPROPERTY( + EditAnywhere, + AdvancedDisplay, + BlueprintReadOnly, + Category = Rendering, + meta = (DisplayName = "Render CustomDepth Pass")) + bool RenderCustomDepth = false; + + /** Mask used for stencil buffer writes. */ + UPROPERTY( + EditAnywhere, + AdvancedDisplay, + BlueprintReadOnly, + Category = "Rendering", + meta = (EditCondition = "RenderCustomDepth")) + ERendererStencilMask CustomDepthStencilWriteMask = + ERendererStencilMask::ERSM_Default; + + /** Optionally write this 0-255 value to the stencil buffer in CustomDepth + * pass (Requires project setting or r.CustomDepth == 3) */ + UPROPERTY( + EditAnywhere, + AdvancedDisplay, + BlueprintReadOnly, + Category = Rendering, + meta = (UIMin = "0", UIMax = "255", EditCondition = "RenderCustomDepth")) + int32 CustomDepthStencilValue = 0; + + bool operator==(const FCustomDepthParameters& other) const { + return RenderCustomDepth == other.RenderCustomDepth && + CustomDepthStencilWriteMask == other.CustomDepthStencilWriteMask && + CustomDepthStencilValue == other.CustomDepthStencilValue; + } + + bool operator!=(const FCustomDepthParameters& other) const { + return !(*this == other); + } +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/GeoTransforms.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/GeoTransforms.h new file mode 100644 index 0000000..6ab5ad8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/GeoTransforms.h @@ -0,0 +1,241 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGeospatial/Ellipsoid.h" +#include "CesiumGeospatial/LocalHorizontalCoordinateSystem.h" +#include "HAL/Platform.h" +#include "Math/Matrix.h" +#include +#include + +/** + * @brief A lightweight structure to encapsulate coordinate transforms. + * + * It encapsulates the conversions between... + * - Earth-Centered, Earth-Fixed (ECEF) coordinates + * - Georeferenced coordinates (Latitude/Longitude/Height) + * - Unreal coordinates (relative to the unreal world origin) + * + */ +class CESIUMRUNTIME_API GeoTransforms { + +public: + /** + * @brief Creates a new instance. + */ + GeoTransforms(); + + /** + * @brief Creates a new instance. + * + * The center position is the position of the origin of the + * local coordinate system that is established by this instance. + * + * @param ellipsoid The ellipsoid to use for the georeferenced coordinates + * @param center The center position. + * @param scale The scale factor of the globe in the Unreal world. + */ + GeoTransforms( + const CesiumGeospatial::Ellipsoid& ellipsoid, + const glm::dvec3& center, + double scale); + + /** + * @brief Set the center position of this instance + * + * The center position is the position of the origin of the + * local coordinate system that is established by this instance. + * + * @param center The center position. + */ + void setCenter(const glm::dvec3& center) noexcept; + + /** + * @brief Set the ellipsoid of this instance + * + * @param ellipsoid The ellipsoid + */ + void setEllipsoid(const CesiumGeospatial::Ellipsoid& ellipsoid) noexcept; + + /** + * Transforms the given longitude in degrees (x), latitude in + * degrees (y), and height in meters (z) into Earth-Centered, Earth-Fixed + * (ECEF) coordinates. + */ + glm::dvec3 TransformLongitudeLatitudeHeightToEcef( + const glm::dvec3& LongitudeLatitudeHeight) const noexcept; + + /** + * Transforms the given Earth-Centered, Earth-Fixed (ECEF) coordinates into + * longitude in degrees (x), latitude in degrees (y), and height in + * meters (z). + */ + glm::dvec3 + TransformEcefToLongitudeLatitudeHeight(const glm::dvec3& Ecef) const noexcept; + + /** + * Transforms the given longitude in degrees (x), latitude in + * degrees (y), and height in meters (z) into Unreal world coordinates + * (relative to the floating origin). + */ + glm::dvec3 TransformLongitudeLatitudeHeightToUnreal( + const glm::dvec3& origin, + const glm::dvec3& LongitudeLatitudeHeight) const noexcept; + + /** + * Transforms Unreal world coordinates (relative to the floating origin) into + * longitude in degrees (x), latitude in degrees (y), and height in + * meters (z). + */ + glm::dvec3 TransformUnrealToLongitudeLatitudeHeight( + const glm::dvec3& origin, + const glm::dvec3& Ue) const noexcept; + + /** + * Transforms the given point from Earth-Centered, Earth-Fixed (ECEF) into + * Unreal world coordinates (relative to the floating origin). + */ + glm::dvec3 TransformEcefToUnreal( + const glm::dvec3& origin, + const glm::dvec3& Ecef) const noexcept; + + /** + * Transforms the given point from Unreal world coordinates (relative to the + * floating origin) to Earth-Centered, Earth-Fixed (ECEF). + */ + glm::dvec3 TransformUnrealToEcef( + const glm::dvec3& origin, + const glm::dvec3& Ue) const noexcept; + + /** + * Transforms a rotator from Unreal world to East-South-Up at the given + * Unreal relative world location (relative to the floating origin). + */ + glm::dquat TransformRotatorUnrealToEastSouthUp( + const glm::dvec3& origin, + const glm::dquat& UeRotator, + const glm::dvec3& UeLocation) const noexcept; + + /** + * Transforms a rotator from East-South-Up to Unreal world at the given + * Unreal world location (relative to the floating origin). + */ + glm::dquat TransformRotatorEastSouthUpToUnreal( + const glm::dvec3& origin, + const glm::dquat& EnuRotator, + const glm::dvec3& UeLocation) const noexcept; + + /** + * Computes the rotation matrix from the local East-South-Up to Unreal at the + * specified Unreal world location (relative to the floating + * origin). The returned transformation works in Unreal's left-handed + * coordinate system. + */ + glm::dmat4 ComputeEastSouthUpToUnreal( + const glm::dvec3& origin, + const glm::dvec3& Ue) const noexcept; + + /** + * Computes the rotation matrix from the local East-North-Up to + * Earth-Centered, Earth-Fixed (ECEF) at the specified ECEF location. + */ + glm::dmat3 ComputeEastNorthUpToEcef(const glm::dvec3& Ecef) const noexcept; + + /* + * GEOREFERENCE TRANSFORMS + */ + + /** + * @brief Gets the transformation from the _absolute_ "Unreal World" reference + * frame to the "Ellipsoid-centered" reference frame (i.e. ECEF). + * + * Gets a matrix that transforms coordinates from the absolute "Unreal World" + * reference frame (with respect to the absolute world origin, not the + * floating origin) to the "Ellipsoid-centered" reference frame (which is + * usually Earth-centered, Earth-fixed). See {@link reference-frames.md}. + */ + const glm::dmat4& + GetAbsoluteUnrealWorldToEllipsoidCenteredTransform() const noexcept { + return this->_coordinateSystem.getLocalToEcefTransformation(); + } + + /** + * @brief Gets the transformation from the "Ellipsoid-centered" reference + * frame (i.e. ECEF) to the absolute "Unreal World" reference frame. + * + * Gets a matrix that transforms coordinates from the "Ellipsoid-centered" + * reference frame (which is usually Earth-centered, Earth-fixed) to the + * absolute "Unreal world" reference frame (with respect to the absolute world + * origin, not the floating origin). See {@link reference-frames.md}. + */ + const glm::dmat4& + GetEllipsoidCenteredToAbsoluteUnrealWorldTransform() const noexcept { + return this->_coordinateSystem.getEcefToLocalTransformation(); + } + + /** + * @brief Computes the normal of the plane tangent to the surface of the + * ellipsoid that is used by this instance, at the provided position. + * + * @param position The cartesian position for which to to determine the + * surface normal. + * @return The normal. + */ + glm::dvec3 ComputeGeodeticSurfaceNormal(const glm::dvec3& position) const { + return _ellipsoid.geodeticSurfaceNormal(position); + } + + /** + * Computes the rotation in ellipsoid surface normal between an old position + * and a new position. This rotation is expressed in terms of Unreal world + * coordinates, and can be used to maintain an object's orientation relative + * to the local horizontal as it moves over the globe. + * + * @param oldPosition The old ECEF position that the object moved from. + * @param newPosition The new ECEF position that the object moved to. + * @return The rotation from the ellipsoid surface normal at the old position + * to the ellipsoid surface normal at the new position. + */ + glm::dquat ComputeSurfaceNormalRotation( + const glm::dvec3& oldPosition, + const glm::dvec3& newPosition) const; + + /** + * Computes the rotation in ellipsoid surface normal between an old position + * and a new position. This rotation is expressed in terms of Unreal world + * coordinates, and can be used to maintain an object's orientation relative + * to the local horizontal as it moves over the globe. + * + * @param oldPosition The old ECEF position that the object moved from. + * @param newPosition The new ECEF position that the object moved to. + * @return The rotation from the ellipsoid surface normal at the old position + * to the ellipsoid surface normal at the new position. + */ + glm::dquat ComputeSurfaceNormalRotationUnreal( + const glm::dvec3& oldPosition, + const glm::dvec3& newPosition) const; + + const FMatrix& GetEllipsoidCenteredToAbsoluteUnrealWorldMatrix() const { + return this->_ecefToUnreal; + } + const FMatrix& GetAbsoluteUnrealWorldToEllipsoidCenteredMatrix() const { + return this->_unrealToEcef; + } + +private: + /** + * Update the derived state (i.e. the local horizontal coordinate system) when + * either the center or the ellipsoid has changed. + */ + void updateTransforms() noexcept; + + CesiumGeospatial::LocalHorizontalCoordinateSystem _coordinateSystem; + + // Modifiable state + CesiumGeospatial::Ellipsoid _ellipsoid; + glm::dvec3 _center; + double _scale; + FMatrix _ecefToUnreal; + FMatrix _unrealToEcef; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/GlobeAwareDefaultPawn.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/GlobeAwareDefaultPawn.h new file mode 100644 index 0000000..d4153c0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/GlobeAwareDefaultPawn.h @@ -0,0 +1,249 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGeospatial/Ellipsoid.h" +#include "CoreMinimal.h" +#include "GameFramework/DefaultPawn.h" +#include +#include +#include +#include "GlobeAwareDefaultPawn.generated.h" + +class ACesiumGeoreference; +class UCesiumGlobeAnchorComponent; +class UCurveFloat; +class UCesiumFlyToComponent; + +/** + * The delegate for when the pawn finishes flying + * which is triggered from _handleFlightStep + */ +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FCompletedFlight); + +/** + * The delegate for when the pawn's flying is interrupted + * which is triggered from _interruptFlight + */ +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FInterruptedFlight); + +/** + * This pawn can be used to easily move around the globe while maintaining a + * sensible orientation. As the pawn moves across the horizon, it automatically + * changes its own up direction such that the world always looks right-side up. + */ +UCLASS() +class CESIUMRUNTIME_API AGlobeAwareDefaultPawn : public ADefaultPawn { + GENERATED_BODY() + +public: + AGlobeAwareDefaultPawn(); + + /** + * Input callback to move forward in local space (or backward if Val is + * negative). + * @param Val Amount of movement in the forward direction (or backward if + * negative). + * @see APawn::AddMovementInput() + */ + virtual void MoveForward(float Val) override; + + /** + * Input callback to strafe right in local space (or left if Val is negative). + * @param Val Amount of movement in the right direction (or left if negative). + * @see APawn::AddMovementInput() + */ + virtual void MoveRight(float Val) override; + + /** + * Input callback to move up in world space (or down if Val is negative). + * @param Val Amount of movement in the world up direction (or down if + * negative). + * @see APawn::AddMovementInput() + */ + virtual void MoveUp_World(float Val) override; + + /** + * Gets the absolute rotation of the camera view from the Unreal world. + */ + virtual FRotator GetViewRotation() const override; + + /** + * Gets the rotation of the aim direction, which is the same as the View + * Rotation. + */ + virtual FRotator GetBaseAimRotation() const override; + + UPROPERTY( + meta = + (DeprecatedProperty, + DeprecationMessage = + "FlyToGranularityDegrees has been deprecated. This property no longer needs to be set.")) + float FlyToGranularityDegrees_DEPRECATED = 0.01f; + + UPROPERTY( + BlueprintAssignable, + meta = + (DeprecatedProperty, + DeprecationMessage = + "Use OnFlightComplete on CesiumFlyToComponent instead.")) + FCompletedFlight OnFlightComplete_DEPRECATED; + + UPROPERTY( + BlueprintAssignable, + meta = + (DeprecatedProperty, + DeprecationMessage = + "Use OnFlightInterrupted on CesiumFlyToComponent instead.")) + FInterruptedFlight OnFlightInterrupt_DEPRECATED; + + /** + * Gets the transformation from globe's reference frame to the Unreal world + * (relative to the floating origin). This is equivalent to calling + * GetActorTransform on this pawn's attach parent, if it has one. If this pawn + * does not have an attach parent, an identity transformation is returned. + */ + UFUNCTION(BlueprintPure, Category = "Cesium") + const FTransform& GetGlobeToUnrealWorldTransform() const; + + /** + * Begin a smooth camera flight to the given Earth-Centered, Earth-Fixed + * (ECEF) destination such that the camera ends at the specified yaw and + * pitch. The characteristics of the flight can be configured with + * {@see FlyToAltitudeProfileCurve}, {@see FlyToProgressCurve}, + * {@see FlyToMaximumAltitudeCurve}, and {@see FlyToDuration} + */ + UFUNCTION( + BlueprintCallable, + meta = + (DeprecatedFunction, + DeprecationMessage = + "Use FlyToEarthCenteredEarthFixed on CesiumFlyToComponent instead.")) + void FlyToLocationECEF( + const FVector& ECEFDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving); + + /** + * Begin a smooth camera flight to the given WGS84 longitude in degrees (x), + * latitude in degrees (y), and height in meters (z) such that the camera + * ends at the given yaw and pitch. The characteristics of the flight can be + * configured with {@see FlyToAltitudeProfileCurve}, + * {@see FlyToProgressCurve}, {@see FlyToMaximumAltitudeCurve}, + * {@see FlyToDuration}, and {@see FlyToGranularityDegrees}. + */ + UFUNCTION( + BlueprintCallable, + meta = + (DeprecatedFunction, + DeprecationMessage = + "Use FlyToLocationLongitudeLatitudeHeight on CesiumFlyToComponent instead.")) + void FlyToLocationLongitudeLatitudeHeight( + const FVector& LongitudeLatitudeHeightDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving); + +protected: + virtual void Serialize(FArchive& Ar) override; + virtual void PostLoad() override; + + /** + * THIS PROPERTY IS DEPRECATED. + * + * Get the Georeference instance from the Globe Anchor Component instead. + */ + UPROPERTY( + Category = "Cesium", + BlueprintReadOnly, + BlueprintGetter = GetGeoreference, + Meta = + (DeprecatedProperty, + DeprecationMessage = + "Get the Georeference instance from the Globe Anchor Component instead.")) + ACesiumGeoreference* Georeference_DEPRECATED; + + /** + * Gets the Georeference Actor associated with this instance. It is obtained + * from the Globe Anchor Component. + */ + UFUNCTION(BlueprintGetter, Category = "Cesium") + ACesiumGeoreference* GetGeoreference() const; + + /** + * The Globe Anchor Component that precisely ties this Pawn to the Globe. + */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + UCesiumGlobeAnchorComponent* GlobeAnchor; + +private: + UPROPERTY( + Category = "Cesium", + BlueprintGetter = GetFlyToProgressCurve_DEPRECATED, + BlueprintSetter = SetFlyToProgressCurve_DEPRECATED, + meta = + (AllowPrivateAccess, + DeprecatedProperty, + DeprecationMessage = + "Use ProgressCurve on CesiumFlyToComponent instead.")) + UCurveFloat* FlyToProgressCurve_DEPRECATED; + UFUNCTION(BlueprintGetter) + UCurveFloat* GetFlyToProgressCurve_DEPRECATED() const; + UFUNCTION(BlueprintSetter) + void SetFlyToProgressCurve_DEPRECATED(UCurveFloat* NewValue); + + UPROPERTY( + Category = "Cesium", + BlueprintGetter = GetFlyToAltitudeProfileCurve_DEPRECATED, + BlueprintSetter = SetFlyToAltitudeProfileCurve_DEPRECATED, + meta = + (AllowPrivateAccess, + DeprecatedProperty, + DeprecationMessage = + "Use HeightPercentageCurve on CesiumFlyToComponent instead.")) + UCurveFloat* FlyToAltitudeProfileCurve_DEPRECATED; + UFUNCTION(BlueprintGetter) + UCurveFloat* GetFlyToAltitudeProfileCurve_DEPRECATED() const; + UFUNCTION(BlueprintSetter) + void SetFlyToAltitudeProfileCurve_DEPRECATED(UCurveFloat* NewValue); + + UPROPERTY( + Category = "Cesium", + BlueprintGetter = GetFlyToMaximumAltitudeCurve_DEPRECATED, + BlueprintSetter = SetFlyToMaximumAltitudeCurve_DEPRECATED, + meta = + (AllowPrivateAccess, + DeprecatedProperty, + DeprecationMessage = + "Use MaximumHeightByDistanceCurve on CesiumFlyToComponent instead.")) + UCurveFloat* FlyToMaximumAltitudeCurve_DEPRECATED; + UFUNCTION(BlueprintGetter) + UCurveFloat* GetFlyToMaximumAltitudeCurve_DEPRECATED() const; + UFUNCTION(BlueprintSetter) + void SetFlyToMaximumAltitudeCurve_DEPRECATED(UCurveFloat* NewValue); + + UPROPERTY( + Category = "Cesium", + BlueprintGetter = GetFlyToDuration_DEPRECATED, + BlueprintSetter = SetFlyToDuration_DEPRECATED, + meta = + (AllowPrivateAccess, + DeprecatedProperty, + DeprecationMessage = + "Use Duration on CesiumFlyToComponent instead.")) + float FlyToDuration_DEPRECATED = 5.0f; + UFUNCTION(BlueprintGetter) + float GetFlyToDuration_DEPRECATED() const; + UFUNCTION(BlueprintSetter) + void SetFlyToDuration_DEPRECATED(float NewValue); + + void _moveAlongViewAxis(EAxis::Type axis, double Val); + void _moveAlongVector(const FVector& axis, double Val); + + UFUNCTION() + void _onFlightComplete(); + + UFUNCTION() + void _onFlightInterrupted(); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/OriginPlacement.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/OriginPlacement.h new file mode 100644 index 0000000..2126b33 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/OriginPlacement.h @@ -0,0 +1,31 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "OriginPlacement.generated.h" + +/** + * An enumeration of the possible strategies for placing the origin of + * a Georeference. + */ +UENUM(BlueprintType) +enum class EOriginPlacement : uint8 { + /** + * Use the tileset's true origin as the Actor's origin. For georeferenced + * tilesets, this usually means the Actor's origin will be at the center + * of the Earth, which is not recommended. For a non-georeferenced tileset, + * however, such as a detailed building with a local origin, putting the + * Actor's origin at the same location as the tileset's origin can be useful. + */ + TrueOrigin UMETA(DisplayName = "True origin"), + + /** + * Use a custom position within the tileset as the Actor's origin. The + * position is expressed as a longitude, latitude, and height, and that + * position within the tileset will be at coordinate (0,0,0) in the Actor's + * coordinate system. + */ + CartographicOrigin UMETA(DisplayName = "Longitude / latitude / height") +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealAssetAccessor.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealAssetAccessor.h new file mode 100644 index 0000000..01095bc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealAssetAccessor.h @@ -0,0 +1,41 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumAsync/AsyncSystem.h" +#include "CesiumAsync/IAssetAccessor.h" +#include "Containers/Map.h" +#include "Containers/UnrealString.h" +#include "HAL/Platform.h" +#include + +class CESIUMRUNTIME_API UnrealAssetAccessor + : public CesiumAsync::IAssetAccessor { +public: + UnrealAssetAccessor(); + + virtual CesiumAsync::Future> + get(const CesiumAsync::AsyncSystem& asyncSystem, + const std::string& url, + const std::vector& headers) + override; + + virtual CesiumAsync::Future> + request( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::string& verb, + const std::string& url, + const std::vector& headers, + const std::span& contentPayload) override; + + virtual void tick() noexcept override; + +private: + CesiumAsync::Future> getFromFile( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::string& url, + const std::vector& headers); + + FString _userAgent; + TMap _cesiumRequestHeaders; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealMetadataConversions.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealMetadataConversions.h new file mode 100644 index 0000000..83e04ba --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealMetadataConversions.h @@ -0,0 +1,132 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumMetadataValueType.h" +#include "CesiumUtility/JsonValue.h" +#include +#include +#include + +enum class ECesiumEncodedMetadataComponentType : uint8; + +/** + * @brief Converts a FCesiumMetadataValueType to the best-fitting Blueprints + * type. + * + * @param ValueType The input metadata value type. + */ +ECesiumMetadataBlueprintType +CesiumMetadataValueTypeToBlueprintType(FCesiumMetadataValueType ValueType); + +// Deprecated. +ECesiumMetadataBlueprintType CesiumMetadataTrueTypeToBlueprintType( + ECesiumMetadataTrueType_DEPRECATED trueType); + +// For backwards compatibility. +ECesiumMetadataTrueType_DEPRECATED +CesiumMetadataValueTypeToTrueType(FCesiumMetadataValueType ValueType); + +static const std::string VectorComponents = "XYZW"; + +struct UnrealMetadataConversions { +public: + static FIntPoint toIntPoint(const glm::ivec2& vec2); + /** + * Converts a std::string_view to a FIntPoint. This expects the values to be + * written in the "X=... Y=..." format. If this function fails to parse + * a FIntPoint, the default value is returned. + */ + static FIntPoint + toIntPoint(const std::string_view& string, const FIntPoint& defaultValue); + + static FVector2D toVector2D(const glm::dvec2& vec2); + /** + * Converts a std::string_view to a FVector2D. This uses + * FVector2D::InitFromString, which expects the values to be written in the + * "X=... Y=..." format. If this function fails to parse a FVector2D, the + * default value is returned. + */ + static FVector2D + toVector2D(const std::string_view& string, const FVector2D& defaultValue); + + static FIntVector toIntVector(const glm::ivec3& vec3); + /** + * Converts a std::string_view to a FIntVector. This expects the values to be + * written in the "X=... Y=... Z=..." format. If this function fails to parse + * a FIntVector, the default value is returned. + * + * @param string The std::string_view to be parsed. + * @param defaultValue The default value to be returned if conversion fails. + */ + static FIntVector + toIntVector(const std::string_view& string, const FIntVector& defaultValue); + + static FVector3f toVector3f(const glm::vec3& vec3); + static FVector3f + toVector3f(const std::string_view& string, const FVector3f& defaultValue); + + static FVector toVector(const glm::dvec3& vec3); + static FVector + toVector(const std::string_view& string, const FVector& defaultValue); + + static FVector4 toVector4(const glm::dvec4& vec4); + static FVector4 + toVector4(const std::string_view& string, const FVector4& defaultValue); + + static FMatrix toMatrix(const glm::dmat4& mat4); + + /** + * Converts a glm::vecN to a FString. This follows the format that ToString() + * functions call on the Unreal vector equivalents. For example, a glm::vec3 + * will return a string in the format "X=... Y=... Z=...". + * + * @param from The glm::vecN to be converted. + */ + template + static FString toString(const glm::vec& from) { + std::string result; + for (glm::length_t i = 0; i < N; i++) { + if (i > 0) { + result += " "; + } + result += VectorComponents[i]; + result += "="; + result += std::to_string(from[i]); + } + return FString(result.c_str()); + } + + /** + * Converts a glm::matN to a FString. This follows the format that ToString() + * functions call on the Unreal matrix equivalents. Each row is + * returned in square brackets, e.g. "[1 2 3 4]", with spaces in-between. + * + * @param from The glm::matN to be converted. + */ + template + static FString toString(const glm::mat& from) { + std::string result; + // glm::matNs are column-major, but Unreal matrices are row-major and print + // their values by row. + for (glm::length_t r = 0; r < N; r++) { + if (r > 0) { + result += " "; + } + result += "["; + for (glm::length_t c = 0; c < N; c++) { + if (c > 0) { + result += " "; + } + result += std::to_string(from[c][r]); + } + result += "]"; + } + return FString(result.c_str()); + } + + static FString toString(const std::string_view& from); + + static FString toString(const std::string& from); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealTaskProcessor.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealTaskProcessor.h new file mode 100644 index 0000000..def1c9f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealTaskProcessor.h @@ -0,0 +1,12 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumAsync/ITaskProcessor.h" +#include "HAL/Platform.h" + +class CESIUMRUNTIME_API UnrealTaskProcessor + : public CesiumAsync::ITaskProcessor { +public: + virtual void startTask(std::function f) override; +}; diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Asset.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Asset.h new file mode 100644 index 0000000..438ab84 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Asset.h @@ -0,0 +1,51 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include + +namespace Cesium3DTiles { +/** + * @brief Metadata about the entire tileset. + */ +struct CESIUM3DTILES_API Asset final : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Asset"; + + /** + * @brief The 3D Tiles version. The version defines the JSON schema for the + * tileset JSON and the base set of tile formats. + */ + std::string version; + + /** + * @brief Application-specific version of this tileset, e.g., for when an + * existing tileset is updated. + */ + std::optional tilesetVersion; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Asset)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(this->version.capacity() * sizeof(char)); + if (this->tilesetVersion) { + accum += int64_t(this->tilesetVersion->capacity() * sizeof(char)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Availability.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Availability.h new file mode 100644 index 0000000..183f186 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Availability.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include + +namespace Cesium3DTiles { +/** + * @brief An object describing the availability of a set of elements. + */ +struct CESIUM3DTILES_API Availability final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Availability"; + + /** + * @brief Known values for Integer indicating whether all of the elements are + * available (1) or all are unavailable (0). + */ + struct Constant { + /** @brief UNAVAILABLE (`0`) */ + static constexpr int32_t UNAVAILABLE = 0; + + /** @brief AVAILABLE (`1`) */ + static constexpr int32_t AVAILABLE = 1; + }; + + /** + * @brief Index of a buffer view that indicates whether each element is + * available. The bitstream conforms to the boolean array encoding described + * in the 3D Metadata specification. If an element is available, its bit is 1, + * and if it is unavailable, its bit is 0. + */ + std::optional bitstream; + + /** + * @brief A number indicating how many 1 bits exist in the availability + * bitstream. + */ + std::optional availableCount; + + /** + * @brief Integer indicating whether all of the elements are available (1) or + * all are unavailable (0). + * + * Known values are defined in {@link Constant}. + * + */ + std::optional constant; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Availability)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BoundingVolume.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BoundingVolume.h new file mode 100644 index 0000000..ddea96e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BoundingVolume.h @@ -0,0 +1,70 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace Cesium3DTiles { +/** + * @brief A bounding volume that encloses a tile or its content. At least one + * bounding volume property is required. Bounding volumes include `box`, + * `region`, or `sphere`. + */ +struct CESIUM3DTILES_API BoundingVolume final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "BoundingVolume"; + + /** + * @brief An array of 12 numbers that define an oriented bounding box. The + * first three elements define the x, y, and z values for the center of the + * box. The next three elements (with indices 3, 4, and 5) define the x axis + * direction and half-length. The next three elements (indices 6, 7, and 8) + * define the y axis direction and half-length. The last three elements + * (indices 9, 10, and 11) define the z axis direction and half-length. + */ + std::vector box; + + /** + * @brief An array of six numbers that define a bounding geographic region in + * EPSG:4979 coordinates with the order [west, south, east, north, minimum + * height, maximum height]. Longitudes and latitudes are in radians. The range + * for latitudes is [-PI/2,PI/2]. The range for longitudes is [-PI,PI]. The + * value that is given as the 'south' of the region shall not be larger than + * the value for the 'north' of the region. The heights are in meters above + * (or below) the WGS84 ellipsoid. The 'minimum height' shall not be larger + * than the 'maximum height'. + */ + std::vector region; + + /** + * @brief An array of four numbers that define a bounding sphere. The first + * three elements define the x, y, and z values for the center of the sphere. + * The last element (with index 3) defines the radius in meters. The radius + * shall not be negative. + */ + std::vector sphere; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(BoundingVolume)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(sizeof(double) * this->box.capacity()); + accum += int64_t(sizeof(double) * this->region.capacity()); + accum += int64_t(sizeof(double) * this->sphere.capacity()); + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Buffer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Buffer.h new file mode 100644 index 0000000..a3c9d8f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Buffer.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include + +namespace Cesium3DTiles { +/** @copydoc BufferSpec */ +struct CESIUM3DTILES_API Buffer final : public BufferSpec { + Buffer() = default; + + /** + * @brief Holds properties that are specific to the 3D Tiles loader rather + * than part of the 3D Tiles spec. + */ + BufferCesium cesium; +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BufferCesium.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BufferCesium.h new file mode 100644 index 0000000..be3e8ff --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BufferCesium.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include +#include + +namespace Cesium3DTiles { +/** + * @brief Holds {@link Buffer} properties that are specific to the 3D Tiles loader + * rather than part of the 3D Tiles spec. + */ +struct CESIUM3DTILES_API BufferCesium final { + /** + * @brief The buffer's data. + */ + std::vector data; +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BufferSpec.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BufferSpec.h new file mode 100644 index 0000000..74f09db --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BufferSpec.h @@ -0,0 +1,69 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief A buffer is a binary blob. It is either the binary chunk of the + * subtree file, or an external buffer referenced by a URI. + */ +struct CESIUM3DTILES_API BufferSpec : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Buffer"; + + /** + * @brief The URI (or IRI) of the file that contains the binary buffer data. + * Relative paths are relative to the file containing the buffer JSON. `uri` + * is required when using the JSON subtree format and not required when using + * the binary subtree format - when omitted the buffer refers to the binary + * chunk of the subtree file. Data URIs are not allowed. + */ + std::optional uri; + + /** + * @brief The length of the buffer in bytes. + */ + int64_t byteLength = int64_t(); + + /** + * @brief The name of the buffer. + */ + std::optional name; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(BufferSpec)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->uri) { + accum += int64_t(this->uri->capacity() * sizeof(char)); + } + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + return accum; + } + +protected: + /** + * @brief This class is not meant to be instantiated directly. Use {@link Buffer} instead. + */ + BufferSpec() = default; + friend struct Buffer; +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BufferView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BufferView.h new file mode 100644 index 0000000..19a85c3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BufferView.h @@ -0,0 +1,60 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief A contiguous subset of a buffer + */ +struct CESIUM3DTILES_API BufferView final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "BufferView"; + + /** + * @brief The index of the buffer. + */ + int64_t buffer = int64_t(); + + /** + * @brief The offset into the buffer in bytes. + */ + int64_t byteOffset = int64_t(); + + /** + * @brief The total byte length of the buffer view. + */ + int64_t byteLength = int64_t(); + + /** + * @brief The name of the `bufferView`. + */ + std::optional name; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(BufferView)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Class.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Class.h new file mode 100644 index 0000000..0c80ad8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Class.h @@ -0,0 +1,67 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief A class containing a set of properties. + */ +struct CESIUM3DTILES_API Class final : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Class"; + + /** + * @brief The name of the class, e.g. for display purposes. + */ + std::optional name; + + /** + * @brief The description of the class. + */ + std::optional description; + + /** + * @brief A dictionary, where each key is a property ID and each value is an + * object defining the property. Property IDs shall be alphanumeric + * identifiers matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`. + */ + std::unordered_map properties; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Class)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + if (this->description) { + accum += int64_t(this->description->capacity() * sizeof(char)); + } + accum += int64_t( + this->properties.bucket_count() * + (sizeof(std::string) + sizeof(Cesium3DTiles::ClassProperty))); + for (const auto& [k, v] : this->properties) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::ClassProperty)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/ClassProperty.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/ClassProperty.h new file mode 100644 index 0000000..11e49f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/ClassProperty.h @@ -0,0 +1,241 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief A single property of a metadata class. + */ +struct CESIUM3DTILES_API ClassProperty final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ClassProperty"; + + /** + * @brief Known values for The element type. + */ + struct Type { + /** @brief `SCALAR` */ + inline static const std::string SCALAR = "SCALAR"; + + /** @brief `VEC2` */ + inline static const std::string VEC2 = "VEC2"; + + /** @brief `VEC3` */ + inline static const std::string VEC3 = "VEC3"; + + /** @brief `VEC4` */ + inline static const std::string VEC4 = "VEC4"; + + /** @brief `MAT2` */ + inline static const std::string MAT2 = "MAT2"; + + /** @brief `MAT3` */ + inline static const std::string MAT3 = "MAT3"; + + /** @brief `MAT4` */ + inline static const std::string MAT4 = "MAT4"; + + /** @brief `STRING` */ + inline static const std::string STRING = "STRING"; + + /** @brief `BOOLEAN` */ + inline static const std::string BOOLEAN = "BOOLEAN"; + + /** @brief `ENUM` */ + inline static const std::string ENUM = "ENUM"; + }; + + /** + * @brief Known values for The datatype of the element's components. Required + * for `SCALAR`, `VECN`, and `MATN` types, and disallowed for other types. + */ + struct ComponentType { + /** @brief `INT8` */ + inline static const std::string INT8 = "INT8"; + + /** @brief `UINT8` */ + inline static const std::string UINT8 = "UINT8"; + + /** @brief `INT16` */ + inline static const std::string INT16 = "INT16"; + + /** @brief `UINT16` */ + inline static const std::string UINT16 = "UINT16"; + + /** @brief `INT32` */ + inline static const std::string INT32 = "INT32"; + + /** @brief `UINT32` */ + inline static const std::string UINT32 = "UINT32"; + + /** @brief `INT64` */ + inline static const std::string INT64 = "INT64"; + + /** @brief `UINT64` */ + inline static const std::string UINT64 = "UINT64"; + + /** @brief `FLOAT32` */ + inline static const std::string FLOAT32 = "FLOAT32"; + + /** @brief `FLOAT64` */ + inline static const std::string FLOAT64 = "FLOAT64"; + }; + + /** + * @brief The name of the property, e.g. for display purposes. + */ + std::optional name; + + /** + * @brief The description of the property. + */ + std::optional description; + + /** + * @brief The element type. + * + * Known values are defined in {@link Type}. + * + */ + std::string type = Type::SCALAR; + + /** + * @brief The datatype of the element's components. Required for `SCALAR`, + * `VECN`, and `MATN` types, and disallowed for other types. + * + * Known values are defined in {@link ComponentType}. + * + */ + std::optional componentType; + + /** + * @brief Enum ID as declared in the `enums` dictionary. Required when `type` + * is `ENUM`. Disallowed when `type` is not `ENUM` + */ + std::optional enumType; + + /** + * @brief Whether the property is an array. When `count` is defined the + * property is a fixed-length array. Otherwise the property is a + * variable-length array. + */ + bool array = false; + + /** + * @brief The number of array elements. May only be defined when `array` is + * `true`. + */ + std::optional count; + + /** + * @brief Specifies whether integer values are normalized. Only applicable to + * `SCALAR`, `VECN`, and `MATN` types with integer component types. For + * unsigned integer component types, values are normalized between + * `[0.0, 1.0]`. For signed integer component types, values are normalized + * between `[-1.0, 1.0]`. For all other component types, this property shall + * be false. + */ + bool normalized = false; + + /** + * @brief An offset to apply to property values. Only applicable to `SCALAR`, + * `VECN`, and `MATN` types when the component type is `FLOAT32` or `FLOAT64`, + * or when the property is `normalized`. Not applicable to variable-length + * arrays. + */ + std::optional offset; + + /** + * @brief A scale to apply to property values. Only applicable to `SCALAR`, + * `VECN`, and `MATN` types when the component type is `FLOAT32` or `FLOAT64`, + * or when the property is `normalized`. Not applicable to variable-length + * arrays. + */ + std::optional scale; + + /** + * @brief Maximum allowed value for the property. Only applicable to `SCALAR`, + * `VECN`, and `MATN` types. This is the maximum of all property values, after + * the transforms based on the `normalized`, `offset`, and `scale` properties + * have been applied. Not applicable to variable-length arrays. + */ + std::optional max; + + /** + * @brief Minimum allowed value for the property. Only applicable to `SCALAR`, + * `VECN`, and `MATN` types. This is the minimum of all property values, after + * the transforms based on the `normalized`, `offset`, and `scale` properties + * have been applied. Not applicable to variable-length arrays. + */ + std::optional min; + + /** + * @brief If required, the property shall be present in every entity + * conforming to the class. If not required, individual entities may include + * `noData` values, or the entire property may be omitted. As a result, + * `noData` has no effect on a required property. Client implementations may + * use required properties to make performance optimizations. + */ + bool required = false; + + /** + * @brief A `noData` value represents missing data — also known as a sentinel + * value — wherever it appears. `BOOLEAN` properties may not specify `noData` + * values. This is given as the plain property value, without the transforms + * from the `normalized`, `offset`, and `scale` properties. Shall not be + * defined if `required` is true. + */ + std::optional noData; + + /** + * @brief A default value to use when encountering a `noData` value or an + * omitted property. The value is given in its final form, taking the effect + * of `normalized`, `offset`, and `scale` properties into account. Shall not + * be defined if `required` is true. + */ + std::optional defaultProperty; + + /** + * @brief An identifier that describes how this property should be + * interpreted. The semantic cannot be used by other properties in the class. + */ + std::optional semantic; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ClassProperty)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + if (this->description) { + accum += int64_t(this->description->capacity() * sizeof(char)); + } + if (this->enumType) { + accum += int64_t(this->enumType->capacity() * sizeof(char)); + } + if (this->semantic) { + accum += int64_t(this->semantic->capacity() * sizeof(char)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/ClassStatistics.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/ClassStatistics.h new file mode 100644 index 0000000..01a8d24 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/ClassStatistics.h @@ -0,0 +1,60 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief Statistics about entities that conform to a class that was defined in + * a metadata schema. + */ +struct CESIUM3DTILES_API ClassStatistics final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ClassStatistics"; + + /** + * @brief The number of entities that conform to the class. + */ + std::optional count; + + /** + * @brief A dictionary, where each key corresponds to a property ID in the + * class' `properties` dictionary and each value is an object containing + * statistics about property values. + */ + std::unordered_map properties; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ClassStatistics)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t( + this->properties.bucket_count() * + (sizeof(std::string) + sizeof(Cesium3DTiles::PropertyStatistics))); + for (const auto& [k, v] : this->properties) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += + v.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::PropertyStatistics)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Content.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Content.h new file mode 100644 index 0000000..2e2f885 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Content.h @@ -0,0 +1,73 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief Metadata about the tile's content and a link to the content. + */ +struct CESIUM3DTILES_API Content final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Content"; + + /** + * @brief An optional bounding volume that tightly encloses tile content. + * tile.boundingVolume provides spatial coherence and + * tile.content.boundingVolume enables tight view frustum culling. When this + * is omitted, tile.boundingVolume is used. + */ + std::optional boundingVolume; + + /** + * @brief A uri that points to tile content. When the uri is relative, it is + * relative to the referring tileset JSON file. + */ + std::string uri; + + /** + * @brief Metadata that is associated with this content. + */ + std::optional metadata; + + /** + * @brief The group this content belongs to. The value is an index into the + * array of `groups` that is defined for the containing tileset. + */ + std::optional group; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Content)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->boundingVolume) { + accum += this->boundingVolume->getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::BoundingVolume)); + } + accum += int64_t(this->uri.capacity() * sizeof(char)); + if (this->metadata) { + accum += this->metadata->getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::MetadataEntity)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Enum.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Enum.h new file mode 100644 index 0000000..d5021ba --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Enum.h @@ -0,0 +1,101 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief An object defining the values of an enum. + */ +struct CESIUM3DTILES_API Enum final : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Enum"; + + /** + * @brief Known values for The type of the integer enum value. + */ + struct ValueType { + /** @brief `INT8` */ + inline static const std::string INT8 = "INT8"; + + /** @brief `UINT8` */ + inline static const std::string UINT8 = "UINT8"; + + /** @brief `INT16` */ + inline static const std::string INT16 = "INT16"; + + /** @brief `UINT16` */ + inline static const std::string UINT16 = "UINT16"; + + /** @brief `INT32` */ + inline static const std::string INT32 = "INT32"; + + /** @brief `UINT32` */ + inline static const std::string UINT32 = "UINT32"; + + /** @brief `INT64` */ + inline static const std::string INT64 = "INT64"; + + /** @brief `UINT64` */ + inline static const std::string UINT64 = "UINT64"; + }; + + /** + * @brief The name of the enum, e.g. for display purposes. + */ + std::optional name; + + /** + * @brief The description of the enum. + */ + std::optional description; + + /** + * @brief The type of the integer enum value. + * + * Known values are defined in {@link ValueType}. + * + */ + std::string valueType = ValueType::UINT16; + + /** + * @brief An array of enum values. Duplicate names or duplicate integer values + * are not allowed. + */ + std::vector values; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Enum)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + if (this->description) { + accum += int64_t(this->description->capacity() * sizeof(char)); + } + accum += + int64_t(sizeof(Cesium3DTiles::EnumValue) * this->values.capacity()); + for (const Cesium3DTiles::EnumValue& value : this->values) { + accum += value.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::EnumValue)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/EnumValue.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/EnumValue.h new file mode 100644 index 0000000..cf6f5e5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/EnumValue.h @@ -0,0 +1,56 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief An enum value. + */ +struct CESIUM3DTILES_API EnumValue final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "EnumValue"; + + /** + * @brief The name of the enum value. + */ + std::string name; + + /** + * @brief The description of the enum value. + */ + std::optional description; + + /** + * @brief The integer enum value. + */ + int64_t value = int64_t(); + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(EnumValue)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(this->name.capacity() * sizeof(char)); + if (this->description) { + accum += int64_t(this->description->capacity() * sizeof(char)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Extension3dTilesBoundingVolumeS2.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Extension3dTilesBoundingVolumeS2.h new file mode 100644 index 0000000..15360c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Extension3dTilesBoundingVolumeS2.h @@ -0,0 +1,58 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace Cesium3DTiles { +/** + * @brief 3D Tiles extension for S2 bounding volumes. + */ +struct CESIUM3DTILES_API Extension3dTilesBoundingVolumeS2 final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Extension3dTilesBoundingVolumeS2"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "3DTILES_bounding_volume_S2"; + + /** + * @brief A hexadecimal representation of the S2CellId. Tokens shall be + * lower-case, shall not contain whitespace and shall have trailing zeros + * stripped. + */ + std::string token; + + /** + * @brief The minimum height of the tile, specified in meters above (or below) + * the WGS84 ellipsoid. + */ + double minimumHeight = double(); + + /** + * @brief The maximum height of the tile, specified in meters above (or below) + * the WGS84 ellipsoid. + */ + double maximumHeight = double(); + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Extension3dTilesBoundingVolumeS2)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(this->token.capacity() * sizeof(char)); + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/GroupMetadata.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/GroupMetadata.h new file mode 100644 index 0000000..bff2bb2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/GroupMetadata.h @@ -0,0 +1,32 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +namespace Cesium3DTiles { +/** + * @brief An object containing metadata about a group. + */ +struct CESIUM3DTILES_API GroupMetadata final : public MetadataEntity { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "GroupMetadata"; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(GroupMetadata)); + accum += MetadataEntity::getSizeBytes() - int64_t(sizeof(MetadataEntity)); + + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/ImplicitTiling.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/ImplicitTiling.h new file mode 100644 index 0000000..b9e2c55 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/ImplicitTiling.h @@ -0,0 +1,78 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include + +namespace Cesium3DTiles { +/** + * @brief This object allows a tile to be implicitly subdivided. Tile and + * content availability and metadata is stored in subtrees which are referenced + * externally. + */ +struct CESIUM3DTILES_API ImplicitTiling final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ImplicitTiling"; + + /** + * @brief Known values for A string describing the subdivision scheme used + * within the tileset. + */ + struct SubdivisionScheme { + /** @brief `QUADTREE` */ + inline static const std::string QUADTREE = "QUADTREE"; + + /** @brief `OCTREE` */ + inline static const std::string OCTREE = "OCTREE"; + }; + + /** + * @brief A string describing the subdivision scheme used within the tileset. + * + * Known values are defined in {@link SubdivisionScheme}. + * + */ + std::string subdivisionScheme = SubdivisionScheme::QUADTREE; + + /** + * @brief The number of distinct levels in each subtree. For example, a + * quadtree with `subtreeLevels = 2` will have subtrees with 5 nodes (one root + * and 4 children). + */ + int64_t subtreeLevels = int64_t(); + + /** + * @brief The numbers of the levels in the tree with available tiles. + */ + int64_t availableLevels = int64_t(); + + /** + * @brief An object describing the location of subtree files. + */ + Cesium3DTiles::Subtrees subtrees; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ImplicitTiling)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += this->subtrees.getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::Subtrees)); + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Library.h new file mode 100644 index 0000000..11d4a24 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes for using [3D Tiles](https://github.com/CesiumGS/3d-tiles). + * + * @mermaid-interactive{dependencies/Cesium3DTiles} + */ +namespace Cesium3DTiles {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUM3DTILES_BUILDING +#define CESIUM3DTILES_API __declspec(dllexport) +#else +#define CESIUM3DTILES_API __declspec(dllimport) +#endif +#else +#define CESIUM3DTILES_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/MetadataEntity.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/MetadataEntity.h new file mode 100644 index 0000000..71d5718 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/MetadataEntity.h @@ -0,0 +1,64 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include + +namespace Cesium3DTiles { +/** + * @brief An object containing a reference to a class from a metadata schema, + * and property values that conform to the properties of that class. + */ +struct CESIUM3DTILES_API MetadataEntity + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "MetadataEntity"; + + /** + * @brief The class that property values conform to. The value shall be a + * class ID declared in the `classes` dictionary of the metadata schema. + */ + std::string classProperty; + + /** + * @brief A dictionary, where each key corresponds to a property ID in the + * class' `properties` dictionary and each value contains the property values. + * The type of the value shall match the property definition: For `BOOLEAN` + * use `true` or `false`. For `STRING` use a JSON string. For numeric types + * use a JSON number. For `ENUM` use a valid enum `name`, not an integer + * value. For `ARRAY`, `VECN`, and `MATN` types use a JSON array containing + * values matching the `componentType`. Required properties shall be included + * in this dictionary. + */ + std::unordered_map properties; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(MetadataEntity)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(this->classProperty.capacity() * sizeof(char)); + accum += int64_t( + this->properties.bucket_count() * + (sizeof(std::string) + sizeof(CesiumUtility::JsonValue))); + for (const auto& [k, v] : this->properties) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += int64_t(sizeof(CesiumUtility::JsonValue)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/MetadataQuery.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/MetadataQuery.h new file mode 100644 index 0000000..ff65282 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/MetadataQuery.h @@ -0,0 +1,74 @@ +#pragma once + +#include +#include +#include + +#include +#include + +namespace Cesium3DTiles { + +/** + * @brief Holds the details of a found property in a {@link MetadataEntity}. + * + * Because this structure holds _references_ to the original {@link Schema} and + * {@link MetadataEntity} instances, it will be invalided if either are + * destroyed or modified. Continuing to access this result in that scenario will + * result in undefined behavior. + */ +struct CESIUM3DTILES_API FoundMetadataProperty { + /** + * @brief A reference to the identifier of the class that contains the found + * property within the {@link Schema}. + */ + const std::string& classIdentifier; + + /** + * @brief A reference to the {@link Class} that contains the found property + * within the {@link Schema}. + */ + const Class& classDefinition; + + /** + * @brief A reference to the identifier of the found property within the + * {@link Schema}. + */ + const std::string& propertyIdentifier; + + /** + * @brief A reference to the {@link ClassProperty} describing the found + * property within the {@link Schema}. + */ + const ClassProperty& propertyDefinition; + + /** + * @brief A reference to the value of the found property within the + * {@link MetadataEntity}. + */ + const CesiumUtility::JsonValue& propertyValue; +}; + +/** + * @brief Convenience functions for querying {@link MetadataEntity} instances. + */ +class CESIUM3DTILES_API MetadataQuery { +public: + /** + * @brief Gets the first property with a given + * {@link ClassProperty::semantic}. + * + * @param schema The schema to use to look up semantics. + * @param entity The metadata entity to search for a property with the + * semantic. + * @param semantic The semantic to find. + * @return The details of the found property, or `std::nullopt` if a property + * with the given semantic does not exist. + */ + static std::optional findFirstPropertyWithSemantic( + const Schema& schema, + const MetadataEntity& entity, + const std::string& semantic); +}; + +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Properties.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Properties.h new file mode 100644 index 0000000..669be0f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Properties.h @@ -0,0 +1,46 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +namespace Cesium3DTiles { +/** + * @brief A dictionary object of metadata about per-feature properties. + */ +struct CESIUM3DTILES_API Properties final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Properties"; + + /** + * @brief The maximum value of this property of all the features in the + * tileset. The maximum value shall not be smaller than the minimum value. + */ + double maximum = double(); + + /** + * @brief The minimum value of this property of all the features in the + * tileset. The maximum value shall not be smaller than the minimum value. + */ + double minimum = double(); + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Properties)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/PropertyStatistics.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/PropertyStatistics.h new file mode 100644 index 0000000..9cedf65 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/PropertyStatistics.h @@ -0,0 +1,109 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief Statistics about property values. + */ +struct CESIUM3DTILES_API PropertyStatistics final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "PropertyStatistics"; + + /** + * @brief The minimum property value occurring in the tileset. Only applicable + * to `SCALAR`, `VECN`, and `MATN` types. This is the minimum of all property + * values, after the transforms based on the `normalized`, `offset`, and + * `scale` properties have been applied. + */ + std::optional min; + + /** + * @brief The maximum property value occurring in the tileset. Only applicable + * to `SCALAR`, `VECN`, and `MATN` types. This is the maximum of all property + * values, after the transforms based on the `normalized`, `offset`, and + * `scale` properties have been applied. + */ + std::optional max; + + /** + * @brief The arithmetic mean of property values occurring in the tileset. + * Only applicable to `SCALAR`, `VECN`, and `MATN` types. This is the mean of + * all property values, after the transforms based on the `normalized`, + * `offset`, and `scale` properties have been applied. + */ + std::optional mean; + + /** + * @brief The median of property values occurring in the tileset. Only + * applicable to `SCALAR`, `VECN`, and `MATN` types. This is the median of all + * property values, after the transforms based on the `normalized`, `offset`, + * and `scale` properties have been applied. + */ + std::optional median; + + /** + * @brief The standard deviation of property values occurring in the tileset. + * Only applicable to `SCALAR`, `VECN`, and `MATN` types. This is the standard + * deviation of all property values, after the transforms based on the + * `normalized`, `offset`, and `scale` properties have been applied. + */ + std::optional standardDeviation; + + /** + * @brief The variance of property values occurring in the tileset. Only + * applicable to `SCALAR`, `VECN`, and `MATN` types. This is the variance of + * all property values, after the transforms based on the `normalized`, + * `offset`, and `scale` properties have been applied. + */ + std::optional variance; + + /** + * @brief The sum of property values occurring in the tileset. Only applicable + * to `SCALAR`, `VECN`, and `MATN` types. This is the sum of all property + * values, after the transforms based on the `normalized`, `offset`, and + * `scale` properties have been applied. + */ + std::optional sum; + + /** + * @brief A dictionary, where each key corresponds to an enum `name` and each + * value is the number of occurrences of that enum. Only applicable when + * `type` is `ENUM`. For fixed-length arrays, this is an array of + * component-wise occurrences. + */ + std::unordered_map occurrences; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(PropertyStatistics)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t( + this->occurrences.bucket_count() * + (sizeof(std::string) + sizeof(CesiumUtility::JsonValue))); + for (const auto& [k, v] : this->occurrences) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += int64_t(sizeof(CesiumUtility::JsonValue)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/PropertyTable.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/PropertyTable.h new file mode 100644 index 0000000..4b04461 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/PropertyTable.h @@ -0,0 +1,77 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief Properties conforming to a class, organized as property values stored + * in binary columnar arrays. + */ +struct CESIUM3DTILES_API PropertyTable final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "PropertyTable"; + + /** + * @brief The name of the property table, e.g. for display purposes. + */ + std::optional name; + + /** + * @brief The class that property values conform to. The value shall be a + * class ID declared in the `classes` dictionary. + */ + std::string classProperty; + + /** + * @brief The number of elements in each property array. + */ + int64_t count = int64_t(); + + /** + * @brief A dictionary, where each key corresponds to a property ID in the + * class' `properties` dictionary and each value is an object describing where + * property values are stored. Required properties shall be included in this + * dictionary. + */ + std::unordered_map + properties; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(PropertyTable)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + accum += int64_t(this->classProperty.capacity() * sizeof(char)); + accum += int64_t( + this->properties.bucket_count() * + (sizeof(std::string) + sizeof(Cesium3DTiles::PropertyTableProperty))); + for (const auto& [k, v] : this->properties) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::PropertyTableProperty)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/PropertyTableProperty.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/PropertyTableProperty.h new file mode 100644 index 0000000..a5f633d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/PropertyTableProperty.h @@ -0,0 +1,164 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief An array of binary property values. This represents one column of a + * property table, and contains one value of a certain property for each + * metadata entity. + */ +struct CESIUM3DTILES_API PropertyTableProperty final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "PropertyTableProperty"; + + /** + * @brief Known values for The type of values in `arrayOffsets`. + */ + struct ArrayOffsetType { + /** @brief `UINT8` */ + inline static const std::string UINT8 = "UINT8"; + + /** @brief `UINT16` */ + inline static const std::string UINT16 = "UINT16"; + + /** @brief `UINT32` */ + inline static const std::string UINT32 = "UINT32"; + + /** @brief `UINT64` */ + inline static const std::string UINT64 = "UINT64"; + }; + + /** + * @brief Known values for The type of values in `stringOffsets`. + */ + struct StringOffsetType { + /** @brief `UINT8` */ + inline static const std::string UINT8 = "UINT8"; + + /** @brief `UINT16` */ + inline static const std::string UINT16 = "UINT16"; + + /** @brief `UINT32` */ + inline static const std::string UINT32 = "UINT32"; + + /** @brief `UINT64` */ + inline static const std::string UINT64 = "UINT64"; + }; + + /** + * @brief The index of the buffer view containing property values. The data + * type of property values is determined by the property definition: When + * `type` is `BOOLEAN` values are packed into a bitstream. When `type` is + * `STRING` values are stored as byte sequences and decoded as UTF-8 strings. + * When `type` is `SCALAR`, `VECN`, or `MATN` the values are stored as the + * provided `componentType` and the buffer view `byteOffset` shall be aligned + * to a multiple of the `componentType` size. When `type` is `ENUM` values are + * stored as the enum's `valueType` and the buffer view `byteOffset` shall be + * aligned to a multiple of the `valueType` size. Each enum value in the array + * shall match one of the allowed values in the enum definition. + * `arrayOffsets` is required for variable-length arrays and `stringOffsets` + * is required for strings (for variable-length arrays of strings, both are + * required). + */ + int64_t values = int64_t(); + + /** + * @brief The index of the buffer view containing offsets for variable-length + * arrays. The number of offsets is equal to the property table `count` plus + * one. The offsets represent the start positions of each array, with the last + * offset representing the position after the last array. The array length is + * computed using the difference between the subsequent offset and the current + * offset. If `type` is `STRING` the offsets index into the string offsets + * array (stored in `stringOffsets`), otherwise they index into the property + * array (stored in `values`). The data type of these offsets is determined by + * `arrayOffsetType`. The buffer view `byteOffset` shall be aligned to a + * multiple of the `arrayOffsetType` size. + */ + std::optional arrayOffsets; + + /** + * @brief The index of the buffer view containing offsets for strings. The + * number of offsets is equal to the number of string elements plus one. The + * offsets represent the byte offsets of each string in the property array + * (stored in `values`), with the last offset representing the byte offset + * after the last string. The string byte length is computed using the + * difference between the subsequent offset and the current offset. The data + * type of these offsets is determined by `stringOffsetType`. The buffer view + * `byteOffset` shall be aligned to a multiple of the `stringOffsetType` size. + */ + std::optional stringOffsets; + + /** + * @brief The type of values in `arrayOffsets`. + * + * Known values are defined in {@link ArrayOffsetType}. + * + */ + std::string arrayOffsetType = ArrayOffsetType::UINT32; + + /** + * @brief The type of values in `stringOffsets`. + * + * Known values are defined in {@link StringOffsetType}. + * + */ + std::string stringOffsetType = StringOffsetType::UINT32; + + /** + * @brief An offset to apply to property values. Only applicable when the + * component type is `FLOAT32` or `FLOAT64`, or when the property is + * `normalized`. Overrides the class property's `offset` if both are defined. + */ + std::optional offset; + + /** + * @brief A scale to apply to property values. Only applicable when the + * component type is `FLOAT32` or `FLOAT64`, or when the property is + * `normalized`. Overrides the class property's `scale` if both are defined. + */ + std::optional scale; + + /** + * @brief Maximum value present in the property values. Only applicable to + * `SCALAR`, `VECN`, and `MATN` types. This is the maximum of all property + * values, after the transforms based on the `normalized`, `offset`, and + * `scale` properties have been applied. + */ + std::optional max; + + /** + * @brief Minimum value present in the property values. Only applicable to + * `SCALAR`, `VECN`, and `MATN` types. This is the minimum of all property + * values, after the transforms based on the `normalized`, `offset`, and + * `scale` properties have been applied. + */ + std::optional min; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(PropertyTableProperty)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Schema.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Schema.h new file mode 100644 index 0000000..2a65036 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Schema.h @@ -0,0 +1,97 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief An object defining classes and enums. + */ +struct CESIUM3DTILES_API Schema final : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Schema"; + + /** + * @brief Unique identifier for the schema. Schema IDs shall be alphanumeric + * identifiers matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`. + */ + std::string id; + + /** + * @brief The name of the schema, e.g. for display purposes. + */ + std::optional name; + + /** + * @brief The description of the schema. + */ + std::optional description; + + /** + * @brief Application-specific version of the schema. + */ + std::optional version; + + /** + * @brief A dictionary, where each key is a class ID and each value is an + * object defining the class. Class IDs shall be alphanumeric identifiers + * matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`. + */ + std::unordered_map classes; + + /** + * @brief A dictionary, where each key is an enum ID and each value is an + * object defining the values for the enum. Enum IDs shall be alphanumeric + * identifiers matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`. + */ + std::unordered_map enums; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Schema)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(this->id.capacity() * sizeof(char)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + if (this->description) { + accum += int64_t(this->description->capacity() * sizeof(char)); + } + if (this->version) { + accum += int64_t(this->version->capacity() * sizeof(char)); + } + accum += int64_t( + this->classes.bucket_count() * + (sizeof(std::string) + sizeof(Cesium3DTiles::Class))); + for (const auto& [k, v] : this->classes) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::Class)); + } + accum += int64_t( + this->enums.bucket_count() * + (sizeof(std::string) + sizeof(Cesium3DTiles::Enum))); + for (const auto& [k, v] : this->enums) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::Enum)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Statistics.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Statistics.h new file mode 100644 index 0000000..277bd82 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Statistics.h @@ -0,0 +1,53 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include + +namespace Cesium3DTiles { +/** + * @brief Statistics about entities. + */ +struct CESIUM3DTILES_API Statistics final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Statistics"; + + /** + * @brief A dictionary, where each key corresponds to a class ID in the + * `classes` dictionary of the metatata schema that was defined for the + * tileset that contains these statistics. Each value is an object containing + * statistics about entities that conform to the class. + */ + std::unordered_map classes; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Statistics)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t( + this->classes.bucket_count() * + (sizeof(std::string) + sizeof(Cesium3DTiles::ClassStatistics))); + for (const auto& [k, v] : this->classes) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += + v.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::ClassStatistics)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Subtree.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Subtree.h new file mode 100644 index 0000000..761fa26 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Subtree.h @@ -0,0 +1,151 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief An object describing the availability of tiles and content in a + * subtree, as well as availability of children subtrees. May also store + * metadata for available tiles and content. + */ +struct CESIUM3DTILES_API Subtree final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Subtree"; + + /** + * @brief An array of buffers. + */ + std::vector buffers; + + /** + * @brief An array of buffer views. + */ + std::vector bufferViews; + + /** + * @brief An array of property tables. + */ + std::vector propertyTables; + + /** + * @brief The availability of tiles in the subtree. The availability bitstream + * is a 1D boolean array where tiles are ordered by their level in the subtree + * and Morton index within that level. A tile's availability is determined by + * a single bit, 1 meaning a tile exists at that spatial index, and 0 meaning + * it does not. The number of elements in the array is `(N^subtreeLevels - + * 1)/(N - 1)` where N is 4 for subdivision scheme `QUADTREE` and 8 for + * `OCTREE`. Availability may be stored in a buffer view or as a constant + * value that applies to all tiles. If a non-root tile's availability is 1 its + * parent tile's availability shall also be 1. `tileAvailability.constant: 0` + * is disallowed, as subtrees shall have at least one tile. + */ + Cesium3DTiles::Availability tileAvailability; + + /** + * @brief An array of content availability objects. If the tile has a single + * content this array will have one element; if the tile has multiple contents + * - as supported by 3DTILES_multiple_contents and 3D Tiles 1.1 - this array + * will have multiple elements. + */ + std::vector contentAvailability; + + /** + * @brief The availability of children subtrees. The availability bitstream is + * a 1D boolean array where subtrees are ordered by their Morton index in the + * level of the tree immediately below the bottom row of the subtree. A child + * subtree's availability is determined by a single bit, 1 meaning a subtree + * exists at that spatial index, and 0 meaning it does not. The number of + * elements in the array is `N^subtreeLevels` where N is 4 for subdivision + * scheme `QUADTREE` and 8 for `OCTREE`. Availability may be stored in a + * buffer view or as a constant value that applies to all child subtrees. If + * availability is 0 for all child subtrees, then the tileset does not + * subdivide further. + */ + Cesium3DTiles::Availability childSubtreeAvailability; + + /** + * @brief Index of the property table containing tile metadata. Tile metadata + * only exists for available tiles and is tightly packed by increasing tile + * index. To access individual tile metadata, implementations may create a + * mapping from tile indices to tile metadata indices. + */ + std::optional tileMetadata; + + /** + * @brief An array of indexes to property tables containing content metadata. + * If the tile has a single content this array will have one element; if the + * tile has multiple contents - as supported by 3DTILES_multiple_contents and + * 3D Tiles 1.1 - this array will have multiple elements. Content metadata + * only exists for available contents and is tightly packed by increasing tile + * index. To access individual content metadata, implementations may create a + * mapping from tile indices to content metadata indices. + */ + std::vector contentMetadata; + + /** + * @brief Subtree metadata encoded in JSON. + */ + std::optional subtreeMetadata; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Subtree)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(sizeof(Cesium3DTiles::Buffer) * this->buffers.capacity()); + for (const Cesium3DTiles::Buffer& value : this->buffers) { + accum += value.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::Buffer)); + } + accum += int64_t( + sizeof(Cesium3DTiles::BufferView) * this->bufferViews.capacity()); + for (const Cesium3DTiles::BufferView& value : this->bufferViews) { + accum += + value.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::BufferView)); + } + accum += int64_t( + sizeof(Cesium3DTiles::PropertyTable) * this->propertyTables.capacity()); + for (const Cesium3DTiles::PropertyTable& value : this->propertyTables) { + accum += + value.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::PropertyTable)); + } + accum += this->tileAvailability.getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::Availability)); + accum += int64_t( + sizeof(Cesium3DTiles::Availability) * + this->contentAvailability.capacity()); + for (const Cesium3DTiles::Availability& value : this->contentAvailability) { + accum += + value.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::Availability)); + } + accum += this->childSubtreeAvailability.getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::Availability)); + accum += int64_t(sizeof(int64_t) * this->contentMetadata.capacity()); + if (this->subtreeMetadata) { + accum += this->subtreeMetadata->getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::MetadataEntity)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Subtrees.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Subtrees.h new file mode 100644 index 0000000..913373d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Subtrees.h @@ -0,0 +1,41 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace Cesium3DTiles { +/** + * @brief An object describing the location of subtree files. + */ +struct CESIUM3DTILES_API Subtrees final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Subtrees"; + + /** + * @brief A URI with embedded expressions that describes the resource that is associated with an implicit tile in an implicit tileset. Allowed expressions are `{level}`, `{x}`, `{y}`, and `{z}`. `{level}` is substituted with the level of the node, `{x}` is substituted with the x index of the node within the level, and `{y}` is substituted with the y index of the node within the level. `{z}` may only be given when the subdivision scheme is `OCTREE`, and it is substituted with the z index of the node within the level. + */ + std::string uri; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Subtrees)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(this->uri.capacity() * sizeof(char)); + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Tile.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Tile.h new file mode 100644 index 0000000..a8bcc6c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Tile.h @@ -0,0 +1,157 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief A tile in a 3D Tiles tileset. + */ +struct CESIUM3DTILES_API Tile final : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Tile"; + + /** + * @brief Known values for Specifies if additive or replacement refinement is + * used when traversing the tileset for rendering. This property is required + * for the root tile of a tileset; it is optional for all other tiles. The + * default is to inherit from the parent tile. + */ + struct Refine { + /** @brief `ADD` */ + inline static const std::string ADD = "ADD"; + + /** @brief `REPLACE` */ + inline static const std::string REPLACE = "REPLACE"; + }; + + /** + * @brief The bounding volume that encloses the tile. + */ + Cesium3DTiles::BoundingVolume boundingVolume; + + /** + * @brief Optional bounding volume that defines the volume the viewer shall be + * inside of before the tile's content will be requested and before the tile + * will be refined based on geometricError. + */ + std::optional viewerRequestVolume; + + /** + * @brief The error, in meters, introduced if this tile is rendered and its + * children are not. At runtime, the geometric error is used to compute screen + * space error (SSE), i.e., the error measured in pixels. + */ + double geometricError = double(); + + /** + * @brief Specifies if additive or replacement refinement is used when + * traversing the tileset for rendering. This property is required for the + * root tile of a tileset; it is optional for all other tiles. The default is + * to inherit from the parent tile. + * + * Known values are defined in {@link Refine}. + * + */ + std::optional refine; + + /** + * @brief A floating-point 4x4 affine transformation matrix, stored in + * column-major order, that transforms the tile's content--i.e., its features + * as well as content.boundingVolume, boundingVolume, and + * viewerRequestVolume--from the tile's local coordinate system to the parent + * tile's coordinate system, or, in the case of a root tile, from the tile's + * local coordinate system to the tileset's coordinate system. `transform` + * does not apply to any volume property when the volume is a region, defined + * in EPSG:4979 coordinates. `transform` scales the `geometricError` by the + * maximum scaling factor from the matrix. + */ + std::vector transform = + {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; + + /** + * @brief Metadata about the tile's content and a link to the content. When + * this is omitted the tile is just used for culling. When this is defined, + * then `contents` shall be undefined. + */ + std::optional content; + + /** + * @brief An array of contents. When this is defined, then `content` shall be + * undefined. + */ + std::vector contents; + + /** + * @brief A metadata entity that is associated with this tile. + */ + std::optional metadata; + + /** + * @brief An object that describes the implicit subdivision of this tile. + */ + std::optional implicitTiling; + + /** + * @brief An array of objects that define child tiles. Each child tile content + * is fully enclosed by its parent tile's bounding volume and, generally, has + * a geometricError less than its parent tile's geometricError. For leaf + * tiles, there are no children, and this property may not be defined. + */ + std::vector children; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Tile)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += this->boundingVolume.getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::BoundingVolume)); + if (this->viewerRequestVolume) { + accum += this->viewerRequestVolume->getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::BoundingVolume)); + } + accum += int64_t(sizeof(double) * this->transform.capacity()); + if (this->content) { + accum += this->content->getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::Content)); + } + accum += + int64_t(sizeof(Cesium3DTiles::Content) * this->contents.capacity()); + for (const Cesium3DTiles::Content& value : this->contents) { + accum += value.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::Content)); + } + if (this->metadata) { + accum += this->metadata->getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::MetadataEntity)); + } + if (this->implicitTiling) { + accum += this->implicitTiling->getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::ImplicitTiling)); + } + accum += int64_t(sizeof(Cesium3DTiles::Tile) * this->children.capacity()); + for (const Cesium3DTiles::Tile& value : this->children) { + accum += value.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::Tile)); + } + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Tileset.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Tileset.h new file mode 100644 index 0000000..9a65c3f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Tileset.h @@ -0,0 +1,139 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace Cesium3DTiles { +/** + * @brief A 3D Tiles tileset. + */ +struct CESIUM3DTILES_API Tileset final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Tileset"; + + /** + * @brief Metadata about the entire tileset. + */ + Cesium3DTiles::Asset asset; + + /** + * @brief A dictionary object of metadata about per-feature properties. + */ + std::unordered_map properties; + + /** + * @brief An object defining the structure of metadata classes and enums. When + * this is defined, then `schemaUri` shall be undefined. + */ + std::optional schema; + + /** + * @brief The URI (or IRI) of the external schema file. When this is defined, + * then `schema` shall be undefined. + */ + std::optional schemaUri; + + /** + * @brief An object containing statistics about metadata entities. + */ + std::optional statistics; + + /** + * @brief An array of groups that tile content may belong to. Each element of + * this array is a metadata entity that describes the group. The tile content + * `group` property is an index into this array. + */ + std::vector groups; + + /** + * @brief A metadata entity that is associated with this tileset. + */ + std::optional metadata; + + /** + * @brief The error, in meters, introduced if this tileset is not rendered. At + * runtime, the geometric error is used to compute screen space error (SSE), + * i.e., the error measured in pixels. + */ + double geometricError = double(); + + /** + * @brief The root tile. + */ + Cesium3DTiles::Tile root; + + /** + * @brief Names of 3D Tiles extensions used somewhere in this tileset. + */ + std::vector extensionsUsed; + + /** + * @brief Names of 3D Tiles extensions required to properly load this tileset. + * Each element of this array shall also be contained in `extensionsUsed`. + */ + std::vector extensionsRequired; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Tileset)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += this->asset.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::Asset)); + accum += int64_t( + this->properties.bucket_count() * + (sizeof(std::string) + sizeof(Cesium3DTiles::Properties))); + for (const auto& [k, v] : this->properties) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::Properties)); + } + if (this->schema) { + accum += + this->schema->getSizeBytes() - int64_t(sizeof(Cesium3DTiles::Schema)); + } + if (this->schemaUri) { + accum += int64_t(this->schemaUri->capacity() * sizeof(char)); + } + if (this->statistics) { + accum += this->statistics->getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::Statistics)); + } + accum += + int64_t(sizeof(Cesium3DTiles::GroupMetadata) * this->groups.capacity()); + for (const Cesium3DTiles::GroupMetadata& value : this->groups) { + accum += + value.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::GroupMetadata)); + } + if (this->metadata) { + accum += this->metadata->getSizeBytes() - + int64_t(sizeof(Cesium3DTiles::MetadataEntity)); + } + accum += this->root.getSizeBytes() - int64_t(sizeof(Cesium3DTiles::Tile)); + accum += int64_t(sizeof(std::string) * this->extensionsUsed.capacity()); + accum += int64_t(sizeof(std::string) * this->extensionsRequired.capacity()); + return accum; + } +}; +} // namespace Cesium3DTiles diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/B3dmToGltfConverter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/B3dmToGltfConverter.h new file mode 100644 index 0000000..b442cbc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/B3dmToGltfConverter.h @@ -0,0 +1,36 @@ +#pragma once + +#include "GltfConverterResult.h" + +#include +#include +#include + +#include +#include + +namespace Cesium3DTilesContent { +struct AssetFetcher; + +/** + * @brief Converts a b3dm (Batched 3D Model) file to a glTF. + * + * For more information on the b3dm format, see + * https://github.com/CesiumGS/3d-tiles/blob/main/specification/TileFormats/Batched3DModel/README.adoc + */ +struct B3dmToGltfConverter { + /** + * @brief Converts a b3dm binary file to a glTF model. + * + * @param b3dmBinary The bytes loaded for the b3dm model. + * @param options Options for how the glTF should be loaded. + * @param assetFetcher The \ref AssetFetcher containing information used by + * loaded assets. + * @returns A future that resolves to a \ref GltfConverterResult. + */ + static CesiumAsync::Future convert( + const std::span& b3dmBinary, + const CesiumGltfReader::GltfReaderOptions& options, + const AssetFetcher& assetFetcher); +}; +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/BinaryToGltfConverter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/BinaryToGltfConverter.h new file mode 100644 index 0000000..adf4b55 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/BinaryToGltfConverter.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +#include +#include + +namespace Cesium3DTilesContent { +struct AssetFetcher; + +/** + * @brief Converts a binary glTF model (glb) to a \ref CesiumGltf::Model. + */ +struct BinaryToGltfConverter { +public: + /** + * @brief Converts a glb binary file to a glTF model. + * + * @param gltfBinary The bytes loaded for the glb model. + * @param options Options for how the glTF should be loaded. + * @param assetFetcher The \ref AssetFetcher containing information used by + * loaded assets. + * @returns A future that resolves to a \ref GltfConverterResult. + */ + static CesiumAsync::Future convert( + const std::span& gltfBinary, + const CesiumGltfReader::GltfReaderOptions& options, + const AssetFetcher& assetFetcher); + +private: + static GltfConverterResult convertImmediate( + const std::span& gltfBinary, + const CesiumGltfReader::GltfReaderOptions& options, + const AssetFetcher& assetFetcher); + static CesiumGltfReader::GltfReader _gltfReader; +}; +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/CmptToGltfConverter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/CmptToGltfConverter.h new file mode 100644 index 0000000..8f4b5c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/CmptToGltfConverter.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include + +#include +#include + +namespace Cesium3DTilesContent { +struct AssetFetcher; + +/** + * @brief Converts a cmpt (Composite) file into a glTF model. + * + * For more information on the Composite format, see + * https://github.com/CesiumGS/3d-tiles/blob/main/specification/TileFormats/Composite/README.adoc + */ +struct CmptToGltfConverter { + /** + * @brief Converts a cmpt binary file to a glTF model. + * + * @param cmptBinary The bytes loaded for the cmpt model. + * @param options Options for how the glTF should be loaded. + * @param assetFetcher The \ref AssetFetcher containing information used by + * loaded assets. + * @returns A future that resolves to a \ref GltfConverterResult. + */ + static CesiumAsync::Future convert( + const std::span& cmptBinary, + const CesiumGltfReader::GltfReaderOptions& options, + const AssetFetcher& assetFetcher); +}; +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/GltfConverterResult.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/GltfConverterResult.h new file mode 100644 index 0000000..eca7947 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/GltfConverterResult.h @@ -0,0 +1,35 @@ +#pragma once + +#include "Library.h" + +#include +#include + +#include + +#include +#include +#include + +namespace Cesium3DTilesContent { +/** + * @brief The result of converting a binary content to gltf model. + * + * Instances of this structure are created internally, by the + * {@link GltfConverters}, when the response to a network request for + * loading the tile content was received. + */ +struct CESIUM3DTILESCONTENT_API GltfConverterResult { + /** + * @brief The gltf model converted from a binary content. This is empty if + * there are errors during the conversion + */ + std::optional model; + + /** + * @brief The error and warning list when converting a binary content to gltf + * model. This is empty if there are no errors during the conversion + */ + CesiumUtility::ErrorList errors; +}; +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/GltfConverterUtility.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/GltfConverterUtility.h new file mode 100644 index 0000000..ef64ade --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/GltfConverterUtility.h @@ -0,0 +1,132 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +struct Model; +struct Buffer; +} // namespace CesiumGltf + +namespace Cesium3DTilesContent { + +namespace GltfConverterUtility { +std::optional parseOffsetForSemantic( + const rapidjson::Document& document, + const char* semantic, + CesiumUtility::ErrorList& errorList); + +typedef bool (rapidjson::Value::*ValuePredicate)() const; + +template bool isValue(const rapidjson::Value& value); +template T getValue(const rapidjson::Value& value); + +template +std::optional getOptional(const rapidjson::Value& value) { + if (isValue(value)) { + return std::make_optional(getValue(value)); + } + return {}; +} + +template +std::optional +getValue(const rapidjson::Document& document, const char* semantic) { + const auto valueIt = document.FindMember(semantic); + if (valueIt == document.MemberEnd() || !isValue(valueIt->value)) { + return {}; + } + return std::make_optional(getValue(valueIt->value)); +} + +template <> inline bool isValue(const rapidjson::Value& value) { + return value.IsBool(); +} + +template <> inline bool getValue(const rapidjson::Value& value) { + return value.GetBool(); +} + +template <> inline bool isValue(const rapidjson::Value& value) { + return value.IsUint(); +} + +template <> inline uint32_t getValue(const rapidjson::Value& value) { + return value.GetUint(); +} + +bool validateJsonArrayValues( + const rapidjson::Value& arrayValue, + uint32_t expectedLength, + ValuePredicate predicate); + +std::optional +parseArrayValueDVec3(const rapidjson::Value& arrayValue); + +std::optional +parseArrayValueDVec3(const rapidjson::Document& document, const char* name); + +int32_t +createBufferInGltf(CesiumGltf::Model& gltf, std::vector buffer = {}); + +int32_t createBufferViewInGltf( + CesiumGltf::Model& gltf, + const int32_t bufferId, + const int64_t byteLength, + const int64_t byteStride); + +int32_t createAccessorInGltf( + CesiumGltf::Model& gltf, + const int32_t bufferViewId, + const int32_t componentType, + const int64_t count, + const std::string type); + +/** + * Applies the given relative-to-center (RTC) translation to the transforms of + * all nodes in the glTF. This is useful in converting i3dm files, where the RTC + * translation must be applied to the model before the i3dm instance + * transform. It's also the 3D Tiles 1.1 "way" to do away with RTC and encode it + * directly in the glTF. + */ +void applyRtcToNodes(CesiumGltf::Model& gltf, const glm::dvec3& rtc); + +template +GlmType toGlm(const GLTFType& gltfVal); + +template +GlmType toGlm(const CesiumGltf::AccessorTypes::VEC3& gltfVal) { + return GlmType(gltfVal.value[0], gltfVal.value[1], gltfVal.value[2]); +} + +template +GlmType +toGlmQuat(const CesiumGltf::AccessorTypes::VEC4& gltfVal) { + if constexpr (std::is_same()) { + return GlmType( + gltfVal.value[3], + gltfVal.value[0], + gltfVal.value[1], + gltfVal.value[2]); + } else { + return GlmType( + CesiumGltf::normalize(gltfVal.value[3]), + CesiumGltf::normalize(gltfVal.value[0]), + CesiumGltf::normalize(gltfVal.value[1]), + CesiumGltf::normalize(gltfVal.value[2])); + } +} + +} // namespace GltfConverterUtility +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/GltfConverters.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/GltfConverters.h new file mode 100644 index 0000000..986691b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/GltfConverters.h @@ -0,0 +1,267 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace Cesium3DTilesContent { + +/** + * @brief The result of an \ref AssetFetcher::get call. + */ +struct AssetFetcherResult { + /** + * @brief The byte buffer obtained from a URL. This will be empty if fetching + * the asset failed. + */ + std::vector bytes; + /** + * @brief The errors and warnings reported while fetching the asset. + */ + CesiumUtility::ErrorList errorList; +}; + +/** + * Object that makes a recursive request to fetch an asset, mostly for the + * benefit of i3dm files. + */ +struct CESIUM3DTILESCONTENT_API AssetFetcher { + /** + * @brief Creates an \ref AssetFetcher with the given base URL and settings. + * + * @param asyncSystem_ The \ref CesiumAsync::AsyncSystem used for fetching + * assets asynchronously. + * @param pAssetAccessor_ The \ref CesiumAsync::IAssetAccessor providing the + * implementation for fetching assets from a remote server. + * @param baseUrl_ The base URL that relative URLs passed to \ref get will be + * relative to. + * @param tileTransform_ A transformation matrix applied to this tile. + * @param requestHeaders_ The headers to be used for a request made with the + * \ref AssetFetcher. + * @param upAxis_ The `gltfUpAxis` property to be set on loaded glTFs. + */ + AssetFetcher( + const CesiumAsync::AsyncSystem& asyncSystem_, + const std::shared_ptr& pAssetAccessor_, + const std::string& baseUrl_, + const glm::dmat4 tileTransform_, + const std::vector& requestHeaders_, + CesiumGeometry::Axis upAxis_) + : asyncSystem(asyncSystem_), + pAssetAccessor(pAssetAccessor_), + baseUrl(baseUrl_), + tileTransform(tileTransform_), + requestHeaders(requestHeaders_), + upAxis(upAxis_) {} + + /** + * @brief Gets a buffer of bytes from the given relative URL. + * + * @param relativeUrl The URL of the asset to fetch, relative to the \ref + * baseUrl property. + * @returns A future that resolves into an \ref AssetFetcherResult. + */ + CesiumAsync::Future + get(const std::string& relativeUrl) const; + + /** + * @brief The \ref CesiumAsync::AsyncSystem used for this \ref AssetFetcher. + */ + CesiumAsync::AsyncSystem asyncSystem; + /** + * @brief The \ref CesiumAsync::IAssetAccessor used for this \ref + * AssetFetcher. + */ + std::shared_ptr pAssetAccessor; + /** + * @brief The base URL that this \ref AssetFetcher's requests will be relative + * to. + */ + std::string baseUrl; + /** + * @brief The transformation matrix applied to this tile. Used for + * East-North-Up transforms in i3dm. + */ + glm::dmat4 tileTransform; + /** + * @brief Headers that will be attached to each request made with this \ref + * AssetFetcher. + */ + std::vector requestHeaders; + /** + * @brief The `gltfUpAxis` property that will be specified for loaded assets. + */ + CesiumGeometry::Axis upAxis; +}; + +/** + * @brief Creates {@link GltfConverterResult} objects from a + * a binary content. + * + * The class offers a lookup functionality for registering + * {@link ConverterFunction} instances that can create + * {@link GltfConverterResult} instances from a binary content. + * + * The loaders are registered based on the magic header or the file extension + * of the input data. The binary data is usually received as a response to a + * network request, and the first four bytes of the raw data form the magic + * header. Based on this header or the file extension of the network response, + * the loader that will be used for processing the input can be looked up. + */ +class CESIUM3DTILESCONTENT_API GltfConverters { +public: + /** + * @brief A function pointer that can create a {@link GltfConverterResult} from a + * tile binary content. + */ + using ConverterFunction = CesiumAsync::Future (*)( + const std::span& content, + const CesiumGltfReader::GltfReaderOptions& options, + const AssetFetcher& subprocessor); + + /** + * @brief Register the given function for the given magic header. + * + * The given magic header is a 4-character string. It will be compared + * to the first 4 bytes of the raw input data, to decide whether the + * given factory function should be used to create the + * {@link GltfConverterResult} from the input data. + * + * @param magic The string describing the magic header. + * @param converter The converter that will be used to create the tile gltf + * content. + */ + static void + registerMagic(const std::string& magic, ConverterFunction converter); + + /** + * @brief Register the given function for the given file extension. + * + * The given string is a file extension including the "." (e.g. ".ext"). It + * is used for deciding whether the given factory function should be used to + * create the + * {@link GltfConverterResult} from the input data with the + * same file extension in its url. + * + * @param fileExtension The file extension. + * @param converter The converter that will be used to create the tile gltf + * content + */ + static void registerFileExtension( + const std::string& fileExtension, + ConverterFunction converter); + + /** + * @brief Retrieve the converter function that is already registered for the + * given file extension. If no such function is found, nullptr will be + * returned + * + * @param filePath The file path that contains the file extension. + * @return The {@link ConverterFunction} that is registered with the file extension. + */ + static ConverterFunction + getConverterByFileExtension(const std::string& filePath); + + /** + * @brief Retrieve the converter function that is registered for the given + * magic header. If no such function is found, nullptr will be returned + * + * The given magic header is a 4-character string. It will be compared + * to the first 4 bytes of the raw input data, to decide whether the + * given factory function should be used to create the + * {@link GltfConverterResult} from the input data. + * + * @param content The binary tile content that contains the magic header. + * @return The {@link ConverterFunction} that is registered with the magic header. + */ + static ConverterFunction + getConverterByMagic(const std::span& content); + + /** + * @brief Creates the {@link GltfConverterResult} from the given + * binary content. + * + * This will look up the {@link ConverterFunction} that can be used to + * process the given input data, based on all loaders that + * have been registered with {@link GltfConverters::registerMagic} + * or {@link GltfConverters::registerFileExtension}. + * + * It will first try to find a loader based on the magic header + * of the `content` in the given input. If no matching loader is found, then + * it will look up a loader based on the file extension of `filePath` of the + * given input. + * + * If no such loader is found then an empty `GltfConverterResult` is returned. + * + * If a matching loader is found, it will be applied to the given + * input, and the result will be returned. + * + * @param filePath The file path that contains the file extension to look up + * the converter. + * @param content The tile binary content that may contains the magic header + * to look up the converter and is used to convert to gltf model. + * @param options The {@link CesiumGltfReader::GltfReaderOptions} for how to + * read a glTF. + * @param assetFetcher An object that can perform recursive asset requests. + * @return The {@link GltfConverterResult} that stores the gltf model converted from the binary data. + */ + static CesiumAsync::Future convert( + const std::string& filePath, + const std::span& content, + const CesiumGltfReader::GltfReaderOptions& options, + const AssetFetcher& assetFetcher); + + /** + * @brief Creates the {@link GltfConverterResult} from the given + * binary content. + * + * This will look up the {@link ConverterFunction} that can be used to + * process the given input data, based on all loaders that + * have been registered with {@link GltfConverters::registerMagic}. + * + * It will try to find a loader based on the magic header + * of the `content` in the given input. If no such loader is found then an + * empty `GltfConverterResult` is returned. + * + * If a matching loader is found, it will be applied to the given + * input, and the result will be returned. + * + * @param content The tile binary content that may contains the magic header + * to look up the converter and is used to convert to gltf model. + * @param options The {@link CesiumGltfReader::GltfReaderOptions} for how to + * read a glTF. + * @param assetFetcher An object that can perform recursive asset requests. + * @return The {@link GltfConverterResult} that stores the gltf model converted from the binary data. + */ + static CesiumAsync::Future convert( + const std::span& content, + const CesiumGltfReader::GltfReaderOptions& options, + const AssetFetcher& assetFetcher); + +private: + static std::string toLowerCase(const std::string_view& str); + + static std::string getFileExtension(const std::string_view& filePath); + + static ConverterFunction getConverterByFileExtension( + const std::string& filePath, + std::string& fileExtension); + + static ConverterFunction getConverterByMagic( + const std::span& content, + std::string& magic); + + static std::unordered_map _loadersByMagic; + static std::unordered_map + _loadersByFileExtension; +}; +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/I3dmToGltfConverter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/I3dmToGltfConverter.h new file mode 100644 index 0000000..a4bbc94 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/I3dmToGltfConverter.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace Cesium3DTilesContent { +struct AssetFetcher; + +/** + * @brief Converts an i3dm (Instanced 3D Model) file to a glTF model. + * + * For more information on the i3dm format, see + * https://github.com/CesiumGS/3d-tiles/blob/main/specification/TileFormats/Instanced3DModel/README.adoc + */ +struct I3dmToGltfConverter { + /** + * @brief Converts an i3dm binary file to a glTF model. + * + * @param instancesBinary The bytes loaded for the i3dm model. + * @param options Options for how the glTF should be loaded. + * @param assetFetcher The \ref AssetFetcher containing information used by + * loaded assets. + * @returns A future that resolves to a \ref GltfConverterResult. + */ + static CesiumAsync::Future convert( + const std::span& instancesBinary, + const CesiumGltfReader::GltfReaderOptions& options, + const AssetFetcher& assetFetcher); +}; +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/ImplicitTilingUtilities.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/ImplicitTilingUtilities.h new file mode 100644 index 0000000..fa2c83b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/ImplicitTilingUtilities.h @@ -0,0 +1,523 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace CesiumGeospatial { +class BoundingRegion; +class S2CellBoundingVolume; +} // namespace CesiumGeospatial + +namespace CesiumGeometry { +class OrientedBoundingBox; +} + +namespace Cesium3DTiles { +struct BoundingVolume; +} + +namespace Cesium3DTilesContent { + +/** + * @brief A lightweight virtual container enumerating the quadtree IDs of the + * children of a given quadtree tile. + */ +class QuadtreeChildren { +public: + /** + * @brief An STL-compatible iterator over the children of a quadtree tile. + */ + class iterator { + public: + /** + * @brief The iterator category tag denoting this is a forward iterator. + */ + using iterator_category = std::forward_iterator_tag; + /** + * @brief The type of value that is being iterated over. + */ + using value_type = CesiumGeometry::QuadtreeTileID; + /** + * @brief The type used to identify distance between iterators. + * + * This is `void` as the distance between two QuadtreeTileIDs isn't + * particularly useful. + */ + using difference_type = void; + /** + * @brief A pointer to the type being iterated over. + */ + using pointer = CesiumGeometry::QuadtreeTileID*; + /** + * @brief A reference to the type being iterated over. + */ + using reference = CesiumGeometry::QuadtreeTileID&; + + /** + * @brief Creates a new iterator over the children of a quadtree tile. + * + * @param parentTileID The \ref CesiumGeometry::QuadtreeTileID of the parent + * tile whose children will be iterated over. + * @param isEnd If true, this iterator will start at the end of the data + * it's iterating over. + */ + explicit iterator( + const CesiumGeometry::QuadtreeTileID& parentTileID, + bool isEnd) noexcept; + + /** + * @brief Returns a reference to the current \ref + * CesiumGeometry::QuadtreeTileID being iterated. + */ + const CesiumGeometry::QuadtreeTileID& operator*() const { + return this->_current; + } + /** + * @brief Returns a pointer to the current \ref + * CesiumGeometry::QuadtreeTileID being iterated. + */ + const CesiumGeometry::QuadtreeTileID* operator->() const { + return &this->_current; + } + /** + * @brief Advances the iterator to the next child. + */ + iterator& operator++(); + /** + * @brief Advances the iterator to the next child. + */ + iterator operator++(int); + + /** @brief Checks if two iterators are at the same child. */ + bool operator==(const iterator& rhs) const noexcept; + /** @brief Checks if two iterators are NOT at the same child. */ + bool operator!=(const iterator& rhs) const noexcept; + + private: + CesiumGeometry::QuadtreeTileID _current; + }; + + /** @brief A const equivalent to `iterator`. */ + using const_iterator = iterator; + + /** + * @brief Creates a \ref QuadtreeChildren instance from the provided parent + * tile. + */ + QuadtreeChildren(const CesiumGeometry::QuadtreeTileID& tileID) noexcept + : _tileID(tileID) {} + + /** @brief Returns an iterator starting at the first child. */ + iterator begin() const noexcept; + /** @brief Returns an iterator starting at the last child. */ + iterator end() const noexcept; + /** + * @brief Returns the total number of \ref CesiumGeometry::QuadtreeTileID + * children for this tile, which will always be four. + */ + constexpr int64_t size() const noexcept { return 4; } + +private: + CesiumGeometry::QuadtreeTileID _tileID; +}; + +/** + * @brief A lightweight virtual container enumerating the octree IDs of the + * children of a given octree tile. + */ +class OctreeChildren { +public: + /** + * @brief An STL-compatible iterator over the children of an octree tile. + */ + class iterator { + public: + /** + * @brief The iterator category tag denoting this is a forward iterator. + */ + using iterator_category = std::forward_iterator_tag; + /** + * @brief The type of value that is being iterated over. + */ + using value_type = CesiumGeometry::OctreeTileID; + /** + * @brief The type used to identify distance between iterators. + * + * This is `void` as the distance between two OctreeTileIDs isn't + * particularly useful. + */ + using difference_type = void; + /** + * @brief A pointer to the type being iterated over. + */ + using pointer = CesiumGeometry::OctreeTileID*; + /** + * @brief A reference to the type being iterated over. + */ + using reference = CesiumGeometry::OctreeTileID&; + + /** + * @brief Creates a new iterator over the children of a octree tile. + * + * @param parentTileID The \ref CesiumGeometry::OctreeTileID of the parent + * tile whose children will be iterated over. + * @param isEnd If true, this iterator will start at the end of the data + * it's iterating over. + */ + explicit iterator( + const CesiumGeometry::OctreeTileID& parentTileID, + bool isEnd) noexcept; + + /** + * @brief Returns a reference to the current \ref + * CesiumGeometry::OctreeTileID being iterated. + */ + const CesiumGeometry::OctreeTileID& operator*() const { + return this->_current; + } + /** + * @brief Returns a pointer to the current \ref + * CesiumGeometry::OctreeTileID being iterated. + */ + const CesiumGeometry::OctreeTileID* operator->() const { + return &this->_current; + } + /** + * @brief Advances the iterator to the next child. + */ + iterator& operator++(); + /** + * @brief Advances the iterator to the next child. + */ + iterator operator++(int); + + /** @brief Checks if two iterators are at the same child. */ + bool operator==(const iterator& rhs) const noexcept; + /** @brief Checks if two iterators are NOT at the same child. */ + bool operator!=(const iterator& rhs) const noexcept; + + private: + CesiumGeometry::OctreeTileID _current; + }; + + /** @brief A const equivalent to `iterator`. */ + using const_iterator = iterator; + + /** + * @brief Creates a \ref OctreeChildren instance from the provided parent + * tile. + */ + OctreeChildren(const CesiumGeometry::OctreeTileID& tileID) noexcept + : _tileID(tileID) {} + /** @brief Returns an iterator starting at the first child. */ + iterator begin() const noexcept; + /** @brief Returns an iterator starting at the last child. */ + iterator end() const noexcept; + /** + * @brief Returns the total number of \ref CesiumGeometry::OctreeTileID + * children for this tile, which will always be eight. + */ + constexpr int64_t size() const noexcept { return 8; } + +private: + CesiumGeometry::OctreeTileID _tileID; +}; + +/** + * @brief Helper functions for working with 3D Tiles implicit tiling. + */ +class ImplicitTilingUtilities { +public: + /** + * @brief Resolves a templatized implicit tiling URL with a quadtree tile ID. + * + * @param baseUrl The base URL that is used to resolve the urlTemplate if it + * is a relative path. + * @param urlTemplate The templatized URL. + * @param quadtreeID The quadtree ID to use in resolving the parameters in the + * URL template. + * @return The resolved URL. + */ + static std::string resolveUrl( + const std::string& baseUrl, + const std::string& urlTemplate, + const CesiumGeometry::QuadtreeTileID& quadtreeID); + + /** + * @brief Resolves a templatized implicit tiling URL with an octree tile ID. + * + * @param baseUrl The base URL that is used to resolve the urlTemplate if it + * is a relative path. + * @param urlTemplate The templatized URL. + * @param octreeID The octree ID to use in resolving the parameters in the + * URL template. + * @return The resolved URL. + */ + static std::string resolveUrl( + const std::string& baseUrl, + const std::string& urlTemplate, + const CesiumGeometry::OctreeTileID& octreeID); + + /** + * @brief Computes the denominator for a given implicit tile level. + * + * Divide the root tile's geometric error by this value to get the standard + * geometric error for tiles on the level. Or divide each component of a + * bounding volume by this factor to get the size of the bounding volume along + * that axis for tiles of this level. + * + * @param level The tile level. + * @return The denominator for the level. + */ + static double computeLevelDenominator(uint32_t level) noexcept; + + /** + * @brief Computes the Morton index for a given quadtree tile within its + * level. + * + * @param tileID The ID of the tile. + * @return The Morton index. + */ + static uint64_t + computeMortonIndex(const CesiumGeometry::QuadtreeTileID& tileID); + + /** + * @brief Computes the Morton index for a given octree tile within its level. + * + * @param tileID The ID of the tile. + * @return The Morton index. + */ + static uint64_t + computeMortonIndex(const CesiumGeometry::OctreeTileID& tileID); + + /** + * @brief Computes the relative Morton index for a given quadtree tile within + * its level of a subtree root at the tile with the given quadtree ID. + * + * @param subtreeID The ID of the subtree the contains the tile. + * @param tileID The ID of the tile. + * @return The relative Morton index. + */ + static uint64_t computeRelativeMortonIndex( + const CesiumGeometry::QuadtreeTileID& subtreeID, + const CesiumGeometry::QuadtreeTileID& tileID); + + /** + * @brief Computes the relative Morton index for a given octree tile within + * its level of a subtree rooted at the tile with the given octree ID. + * + * @param subtreeRootID The ID of the subtree the contains the tile. + * @param tileID The ID of the tile. + * @return The relative Morton index. + */ + static uint64_t computeRelativeMortonIndex( + const CesiumGeometry::OctreeTileID& subtreeRootID, + const CesiumGeometry::OctreeTileID& tileID); + + /** + * @brief Gets the ID of the root tile of the subtree that contains a given + * tile. + * + * @param subtreeLevels The number of levels in each sub-tree. For example, if + * this parameter is 4, then the first subtree starts at level 0 and + * contains tiles in levels 0 through 3, and the next subtree starts at + * level 4 and contains tiles in levels 4 through 7. + * @param tileID The tile ID for each to find the subtree root. + * @return The ID of the root tile of the subtree. + */ + static CesiumGeometry::QuadtreeTileID getSubtreeRootID( + uint32_t subtreeLevels, + const CesiumGeometry::QuadtreeTileID& tileID) noexcept; + + /** + * @brief Gets the ID of the root tile of the subtree that contains a given + * tile. + * + * @param subtreeLevels The number of levels in each sub-tree. For example, if + * this parameter is 4, then the first subtree starts at level 0 and + * contains tiles in levels 0 through 3, and the next subtree starts at + * level 4 and contains tiles in levels 4 through 7. + * @param tileID The tile ID for each to find the subtree root. + * @return The ID of the root tile of the subtree. + */ + static CesiumGeometry::OctreeTileID getSubtreeRootID( + uint32_t subtreeLevels, + const CesiumGeometry::OctreeTileID& tileID) noexcept; + + /** + * @brief Converts an absolute tile ID to a tile ID relative to a given root + * tile. + * + * For example, if `rootID` and `tileID` are the same, this method returns + * `QuadtreeTileID(0, 0, 0)`. + * + * @param rootID The ID of the root tile that the returned ID should be + * relative to. + * @param tileID The absolute ID of the tile to compute a relative ID for. + * @return The relative tile ID. + */ + static CesiumGeometry::QuadtreeTileID absoluteTileIDToRelative( + const CesiumGeometry::QuadtreeTileID& rootID, + const CesiumGeometry::QuadtreeTileID& tileID) noexcept; + + /** + * @brief Converts an absolute tile ID to a tile ID relative to a given root + * tile. + * + * For example, if `rootID` and `tileID` are the same, this method returns + * `OctreeTileID(0, 0, 0, 0)`. + * + * @param rootID The ID of the root tile that the returned ID should be + * relative to. + * @param tileID The absolute ID of the tile to compute a relative ID for. + * @return The relative tile ID. + */ + static CesiumGeometry::OctreeTileID absoluteTileIDToRelative( + const CesiumGeometry::OctreeTileID& rootID, + const CesiumGeometry::OctreeTileID& tileID) noexcept; + + /** + * @brief Gets a lightweight virtual container for enumerating the quadtree + * IDs of the children of a given quadtree tile. + * + * @param tileID The tile ID of the parent tile for which to get children. + * @return The children. + */ + static QuadtreeChildren + getChildren(const CesiumGeometry::QuadtreeTileID& tileID) noexcept { + return QuadtreeChildren{tileID}; + } + + /** + * @brief Gets a lightweight virtual container for enumerating the octree + * IDs of the children of a given octree tile. + * + * @param tileID The tile ID of the parent tile for which to get children. + * @return The children. + */ + static OctreeChildren + getChildren(const CesiumGeometry::OctreeTileID& tileID) noexcept { + return OctreeChildren{tileID}; + } + + /** + * @brief Computes the bounding volume for an implicit quadtree tile with the + * given ID as a {@link Cesium3DTiles::BoundingVolume}. + * + * @param rootBoundingVolume The bounding volume of the root tile. + * @param tileID The tile ID for which to compute the bounding volume. + * @param ellipsoid The ellipsoid to use for this calculation. + * @return The bounding volume for the given implicit tile. + */ + static Cesium3DTiles::BoundingVolume computeBoundingVolume( + const Cesium3DTiles::BoundingVolume& rootBoundingVolume, + const CesiumGeometry::QuadtreeTileID& tileID, + const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) noexcept; + + /** + * @brief Computes the bounding volume for an implicit octree tile with the + * given ID as a {@link Cesium3DTiles::BoundingVolume}. + * + * @param rootBoundingVolume The bounding volume of the root tile. + * @param tileID The tile ID for which to compute the bounding volume. + * @param ellipsoid The ellipsoid to use for this calculation. + * @return The bounding volume for the given implicit tile. + */ + static Cesium3DTiles::BoundingVolume computeBoundingVolume( + const Cesium3DTiles::BoundingVolume& rootBoundingVolume, + const CesiumGeometry::OctreeTileID& tileID, + const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) noexcept; + + /** + * @brief Computes the bounding volume for an implicit quadtree tile with the + * given ID as a bounding region. + * + * @param rootBoundingVolume The bounding region of the root tile. + * @param tileID The tile ID for which to compute the bounding region. + * @param ellipsoid The ellipsoid to use for this calculation. + * @return The bounding region for the given implicit tile. + */ + static CesiumGeospatial::BoundingRegion computeBoundingVolume( + const CesiumGeospatial::BoundingRegion& rootBoundingVolume, + const CesiumGeometry::QuadtreeTileID& tileID, + const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) noexcept; + + /** + * @brief Computes the bounding volume for an implicit octree tile with the + * given ID as a bounding region. + * + * @param rootBoundingVolume The bounding region of the root tile. + * @param tileID The tile ID for which to compute the bounding region. + * @param ellipsoid The ellipsoid to use for this calculation. + * @return The bounding region for the given implicit tile. + */ + static CesiumGeospatial::BoundingRegion computeBoundingVolume( + const CesiumGeospatial::BoundingRegion& rootBoundingVolume, + const CesiumGeometry::OctreeTileID& tileID, + const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) noexcept; + + /** + * @brief Computes the bounding volume for an implicit quadtree tile + * with the given ID as an oriented bounding box. + * + * @param rootBoundingVolume The oriented bounding box of the root tile. + * @param tileID The tile ID for which to compute the oriented bounding box. + * @return The oriented bounding box for the given implicit tile. + */ + static CesiumGeometry::OrientedBoundingBox computeBoundingVolume( + const CesiumGeometry::OrientedBoundingBox& rootBoundingVolume, + const CesiumGeometry::QuadtreeTileID& tileID) noexcept; + + /** + * @brief Computes the bounding volume for an implicit octree tile with + * the given ID as an oriented bounding box. + * + * @param rootBoundingVolume The oriented bounding box of the root tile. + * @param tileID The tile ID for which to compute the oriented bounding box. + * @return The oriented bounding box for the given implicit tile. + */ + static CesiumGeometry::OrientedBoundingBox computeBoundingVolume( + const CesiumGeometry::OrientedBoundingBox& rootBoundingVolume, + const CesiumGeometry::OctreeTileID& tileID) noexcept; + + /** + * @brief Computes the bounding volume for an implicit quadtree tile + * with the given ID as an S2 cell bounding volume. + * + * @param rootBoundingVolume The S2 cell bounding volume of the root tile. + * @param tileID The tile ID for which to compute the S2 cell bounding volume. + * @param ellipsoid The ellipsoid to use for this calculation. + * @return The S2 cell bounding volume for the given implicit tile. + */ + static CesiumGeospatial::S2CellBoundingVolume computeBoundingVolume( + const CesiumGeospatial::S2CellBoundingVolume& rootBoundingVolume, + const CesiumGeometry::QuadtreeTileID& tileID, + const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) noexcept; + + /** + * @brief Computes the bounding volume for an implicit octree tile + * with the given ID as an S2 cell bounding volume. + * + * @param rootBoundingVolume The S2 cell bounding volume of the root tile. + * @param tileID The tile ID for which to compute the S2 cell bounding volume. + * @param ellipsoid The ellipsoid to use for this calculation. + * @return The S2 cell bounding volume for the given implicit tile. + */ + static CesiumGeospatial::S2CellBoundingVolume computeBoundingVolume( + const CesiumGeospatial::S2CellBoundingVolume& rootBoundingVolume, + const CesiumGeometry::OctreeTileID& tileID, + const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) noexcept; +}; + +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/Library.h new file mode 100644 index 0000000..6ebc791 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes that support loading and converting 3D Tiles tile content. + * + * @mermaid-interactive{dependencies/Cesium3DTilesContent} + */ +namespace Cesium3DTilesContent {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUM3DTILESCONTENT_BUILDING +#define CESIUM3DTILESCONTENT_API __declspec(dllexport) +#else +#define CESIUM3DTILESCONTENT_API __declspec(dllimport) +#endif +#else +#define CESIUM3DTILESCONTENT_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/PntsToGltfConverter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/PntsToGltfConverter.h new file mode 100644 index 0000000..7443940 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/PntsToGltfConverter.h @@ -0,0 +1,36 @@ +#pragma once + +#include "GltfConverterResult.h" + +#include +#include +#include + +#include +#include + +namespace Cesium3DTilesContent { +struct AssetFetcher; + +/** + * @brief Converts a pnts (Point Cloud) file to a glTF model. + * + * For more information on the pnts format, see + * https://github.com/CesiumGS/3d-tiles/blob/main/specification/TileFormats/PointCloud/README.adoc + */ +struct PntsToGltfConverter { + /** + * @brief Converts an pnts binary file to a glTF model. + * + * @param pntsBinary The bytes loaded for the pnts model. + * @param options Options for how the glTF should be loaded. + * @param assetFetcher The \ref AssetFetcher containing information used by + * loaded assets. + * @returns A future that resolves to a \ref GltfConverterResult. + */ + static CesiumAsync::Future convert( + const std::span& pntsBinary, + const CesiumGltfReader::GltfReaderOptions& options, + const AssetFetcher& assetFetcher); +}; +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/SubtreeAvailability.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/SubtreeAvailability.h new file mode 100644 index 0000000..5c42003 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/SubtreeAvailability.h @@ -0,0 +1,442 @@ +#pragma once + +#include +#include +#include + +#include + +namespace CesiumGeometry { +struct QuadtreeTileID; +struct OctreeTileID; +} // namespace CesiumGeometry + +namespace Cesium3DTiles { +struct ImplicitTiling; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesContent { + +/** + * @brief Indicates how an implicit tile is subdivided. + */ +enum class ImplicitTileSubdivisionScheme { + /** + * @brief Implicit tiles are divided into four children, forming a quadree. + */ + Quadtree, + + /** + * @brief Implicit tiles are divided into eight children, forming an octree. + */ + Octree +}; + +/** + * @brief Supports querying and modifying the various types of availablity + * information included in a {@link Cesium3DTiles::Subtree}. + */ +class SubtreeAvailability { +public: + /** + * @brief Creates an instance from a `Subtree`. + * + * @param subdivisionScheme The subdivision scheme of the subtree (quadtree or + * octree). + * @param levelsInSubtree The number of levels in this subtree. + * @param subtree The subtree. + * @return The subtree availability, or std::nullopt if the subtree definition + * is invalid. + */ + static std::optional fromSubtree( + ImplicitTileSubdivisionScheme subdivisionScheme, + uint32_t levelsInSubtree, + Cesium3DTiles::Subtree&& subtree) noexcept; + + /** + * @brief Creates an empty instance with all tiles initially available, while + * all content and subtrees are initially unavailable. + * + * @param subdivisionScheme The subdivision scheme of the subtree (quadtree or + * octree). + * @param levelsInSubtree The number of levels in this subtree. + * @return The subtree availability, or std::nullopt if the subtree definition + * is invalid. + */ + static std::optional createEmpty( + ImplicitTileSubdivisionScheme subdivisionScheme, + uint32_t levelsInSubtree) noexcept; + + /** + * @brief Asynchronously loads a subtree from a URL. The resource downloaded + * from the URL may be either a JSON or a binary subtree file. + * + * @param subdivisionScheme The subdivision scheme of the subtree (quadtree or + * octree). + * @param levelsInSubtree The number of levels in this subtree. + * @param asyncSystem The async system with which to do background work. + * @param pAssetAccessor The asset accessor to use to retrieve the subtree + * resource from the URL. + * @param pLogger The logger to which to load errors and warnings that occur + * during subtree load. + * @param subtreeUrl The URL from which to retrieve the subtree file. + * @param requestHeaders HTTP headers to include in the request for the + * subtree file. + * @return A future that resolves to a `SubtreeAvailability` instance for the + * subtree file, or std::nullopt if something goes wrong. + */ + static CesiumAsync::Future> loadSubtree( + ImplicitTileSubdivisionScheme subdivisionScheme, + uint32_t levelsInSubtree, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pLogger, + const std::string& subtreeUrl, + const std::vector& requestHeaders); + + /** + * @brief An AvailibilityView that indicates that either all tiles are + * available or all tiles are unavailable. + */ + struct SubtreeConstantAvailability { + /** + * @brief True if all tiles are availabile, false if all tiles are + * unavailable. + */ + bool constant; + }; + + /** + * @brief An AvailabilityView that accesses availability information from a + * bitstream. + */ + struct SubtreeBufferViewAvailability { + /** + * @brief The buffer from which to read and write availability information. + */ + std::span view; + }; + + /** + * @brief A mechanism for accessing availability information. It may be a + * constant value, or it may be read from a bitstream. + */ + using AvailabilityView = + std::variant; + + /** + * @brief Constructs a new instance. + * + * @param subdivisionScheme The subdivision scheme of the subtree (quadtree or + * octree). + * @param levelsInSubtree The number of levels in this subtree. + * @param tileAvailability A view on the tile availability. If backed by a + * buffer, the buffer is expected to be in `subtree`. + * @param subtreeAvailability A view on the subtree availability. If backed by + * a buffer, the buffer is expected to be in `subtree`. + * @param contentAvailability A view on the content availability. If backed by + * a buffer, the buffer is expected to be in `subtree`. + * @param subtree The subtree with which this instance queries and modifies + * availability information. + */ + SubtreeAvailability( + ImplicitTileSubdivisionScheme subdivisionScheme, + uint32_t levelsInSubtree, + AvailabilityView tileAvailability, + AvailabilityView subtreeAvailability, + std::vector&& contentAvailability, + Cesium3DTiles::Subtree&& subtree); + + /** + * @brief Determines if a given tile in the quadtree is available. + * + * @param subtreeId The ID of the root tile of the subtree. + * @param tileId The ID of the tile to query. + * @return True if the tile is available; otherwise, false. + */ + bool isTileAvailable( + const CesiumGeometry::QuadtreeTileID& subtreeId, + const CesiumGeometry::QuadtreeTileID& tileId) const noexcept; + + /** + * @brief Determines if a given tile in the octree is available. + * + * @param subtreeId The ID of the root tile of the subtree. + * @param tileId The ID of the tile to query. + * @return True if the tile is available; otherwise, false. + */ + bool isTileAvailable( + const CesiumGeometry::OctreeTileID& subtreeId, + const CesiumGeometry::OctreeTileID& tileId) const noexcept; + + /** + * @brief Determines if a given tile in the subtree is available. + * + * @param relativeTileLevel The level of the tile to query, relative to the + * root of the subtree. + * @param relativeTileMortonId The Morton ID of the tile to query. See + * {@link ImplicitTilingUtilities::computeRelativeMortonIndex}. + * @return True if the tile is available; otherwise, false. + */ + bool isTileAvailable( + uint32_t relativeTileLevel, + uint64_t relativeTileMortonId) const noexcept; + + /** + * @brief Sets the availability state of a given tile in the quadtree. + * + * @param subtreeId The ID of the root tile of the subtree. + * @param tileId The ID of the tile for which to set availability. + * @param isAvailable The new availability state for the tile. + */ + void setTileAvailable( + const CesiumGeometry::QuadtreeTileID& subtreeId, + const CesiumGeometry::QuadtreeTileID& tileId, + bool isAvailable) noexcept; + + /** + * @brief Sets the availability state of a given tile in the octree. + * + * @param subtreeId The ID of the root tile of the subtree. + * @param tileId The ID of the tile for which to set availability. + * @param isAvailable The new availability state for the tile. + */ + void setTileAvailable( + const CesiumGeometry::OctreeTileID& subtreeId, + const CesiumGeometry::OctreeTileID& tileId, + bool isAvailable) noexcept; + + /** + * @brief Sets the availability state of a given tile in the subtree. + * + * @param relativeTileLevel The level of the tile for which to set + * availability, relative to the root of the subtree. + * @param relativeTileMortonId The Morton ID of the tile for which to set + * availability. See + * {@link ImplicitTilingUtilities::computeRelativeMortonIndex}. + * @param isAvailable The new availability state of the tile. + */ + void setTileAvailable( + uint32_t relativeTileLevel, + uint64_t relativeTileMortonId, + bool isAvailable) noexcept; + + /** + * @brief Determines if content for a given tile in the quadtree is available. + * + * @param subtreeId The ID of the root tile of the subtree. + * @param tileId The ID of the tile to query. + * @param contentId The ID of the content to query. + * @return True if the tile's content is available; otherwise, false. + */ + bool isContentAvailable( + const CesiumGeometry::QuadtreeTileID& subtreeId, + const CesiumGeometry::QuadtreeTileID& tileId, + uint64_t contentId) const noexcept; + + /** + * @brief Determines if content for a given tile in the octree is available. + * + * @param subtreeId The ID of the root tile of the subtree. + * @param tileId The ID of the tile to query. + * @param contentId The ID of the content to query. + * @return True if the tile's content is available; otherwise, false. + */ + bool isContentAvailable( + const CesiumGeometry::OctreeTileID& subtreeId, + const CesiumGeometry::OctreeTileID& tileId, + uint64_t contentId) const noexcept; + + /** + * @brief Determines if content for a given tile in the subtree is available. + * + * @param relativeTileLevel The level of the tile to query, relative to the + * root of the subtree. + * @param relativeTileMortonId The Morton ID of the tile to query. See + * {@link ImplicitTilingUtilities::computeRelativeMortonIndex}. + * @param contentId The ID of the content to query. + * @return True if the tile's content is available; otherwise, false. + */ + bool isContentAvailable( + uint32_t relativeTileLevel, + uint64_t relativeTileMortonId, + uint64_t contentId) const noexcept; + + /** + * @brief Sets the availability state of the content for a given tile in the + * quadtree. + * + * @param subtreeId The ID of the root tile of the subtree. + * @param tileId The ID of the tile for which to set content availability. + * @param contentId The ID of the content to query. + * @param isAvailable The new availability state for the tile's content. + */ + void setContentAvailable( + const CesiumGeometry::QuadtreeTileID& subtreeId, + const CesiumGeometry::QuadtreeTileID& tileId, + uint64_t contentId, + bool isAvailable) noexcept; + + /** + * @brief Sets the availability state of the content for a given tile in the + * octree. + * + * @param subtreeId The ID of the root tile of the subtree. + * @param tileId The ID of the tile for which to set content availability. + * @param contentId The ID of the content to query. + * @param isAvailable The new availability state for the tile's content. + */ + void setContentAvailable( + const CesiumGeometry::OctreeTileID& subtreeId, + const CesiumGeometry::OctreeTileID& tileId, + uint64_t contentId, + bool isAvailable) noexcept; + + /** + * @brief Sets the availability state of the content for a given tile in the + * subtree. + * + * @param relativeTileLevel The level of the tile for which to set + * content availability, relative to the root of the subtree. + * @param relativeTileMortonId The Morton ID of the tile for which to set + * content availability. See + * {@link ImplicitTilingUtilities::computeRelativeMortonIndex}. + * @param contentId The ID of the content to query. + * @param isAvailable The new availability state for the tile's content. + */ + void setContentAvailable( + uint32_t relativeTileLevel, + uint64_t relativeTileMortonId, + uint64_t contentId, + bool isAvailable) noexcept; + + /** + * @brief Determines if the subtree rooted at the given tile is available. + * + * The provided `checkSubtreeID` must be a child of the leaves of this + * subtree. + * + * @param thisSubtreeID The ID of the root tile of this subtree. + * @param checkSubtreeID The ID of the tile to query to see if its subtree is + * available. + * @return True if the subtree is available; otherwise, false. + */ + bool isSubtreeAvailable( + const CesiumGeometry::QuadtreeTileID& thisSubtreeID, + const CesiumGeometry::QuadtreeTileID& checkSubtreeID) const noexcept; + + /** + * @brief Determines if the subtree rooted at the given tile is available. + * + * The provided `checkSubtreeID` must be a child of the leaves of this + * subtree. + * + * @param thisSubtreeID The ID of the root tile of this subtree. + * @param checkSubtreeID The ID of the tile to query to see if its subtree is + * available. + * @return True if the subtree is available; otherwise, false. + */ + bool isSubtreeAvailable( + const CesiumGeometry::OctreeTileID& thisSubtreeID, + const CesiumGeometry::OctreeTileID& checkSubtreeID) const noexcept; + + /** + * @brief Determines if the subtree rooted at the given tile is available. + * + * The provided `relativeSubtreeMortonId` must refer to a child of the leaves + * of this subtree. + * + * @param relativeSubtreeMortonId The Morton ID of the tile for which to check + * subtree availability. See + * {@link ImplicitTilingUtilities::computeRelativeMortonIndex}. + * @return True if the subtree is available; otherwise, false. + */ + bool isSubtreeAvailable(uint64_t relativeSubtreeMortonId) const noexcept; + + /** + * @brief Sets the availability state of the child quadtree rooted at the + * given tile. + * + * The provided `setSubtreeID` must be a child of the leaves of this + * subtree. + * + * @param thisSubtreeID The ID of the root tile of this subtree. + * @param setSubtreeID The ID of the tile to query to see if its subtree is + * available. + * @param isAvailable The new availability state for the subtree. + */ + void setSubtreeAvailable( + const CesiumGeometry::QuadtreeTileID& thisSubtreeID, + const CesiumGeometry::QuadtreeTileID& setSubtreeID, + bool isAvailable) noexcept; + + /** + * @brief Sets the availability state of the child octree rooted at the given + * tile. + * + * The provided `setSubtreeID` must be a child of the leaves of this + * subtree. + * + * @param thisSubtreeID The ID of the root tile of this subtree. + * @param setSubtreeID The ID of the tile to query to see if its subtree is + * available. + * @param isAvailable The new availability state for the subtree. + */ + void setSubtreeAvailable( + const CesiumGeometry::OctreeTileID& thisSubtreeID, + const CesiumGeometry::OctreeTileID& setSubtreeID, + bool isAvailable) noexcept; + + /** + * @brief Sets the availability state of the child subtree rooted at the given + * tile. + * + * The provided `relativeSubtreeMortonId` must refer to a child of the leaves + * of this subtree. + * + * @param relativeSubtreeMortonId The Morton ID of the tile for which to set + * subtree availability. See + * {@link ImplicitTilingUtilities::computeRelativeMortonIndex}. + * @param isAvailable The new availability state. + */ + void setSubtreeAvailable( + uint64_t relativeSubtreeMortonId, + bool isAvailable) noexcept; + + /** + * @brief Gets the subtree that this instance queries and modifies. + */ + const Cesium3DTiles::Subtree& getSubtree() const noexcept { + return this->_subtree; + } + +private: + bool isAvailable( + uint32_t relativeTileLevel, + uint64_t relativeTileMortonId, + const AvailabilityView& availabilityView) const noexcept; + void setAvailable( + uint32_t relativeTileLevel, + uint64_t relativeTileMortonId, + AvailabilityView& availabilityView, + bool isAvailable) noexcept; + + bool isAvailableUsingBufferView( + uint64_t numOfTilesFromRootToParentLevel, + uint64_t relativeTileMortonId, + const AvailabilityView& availabilityView) const noexcept; + void setAvailableUsingBufferView( + uint64_t numOfTilesFromRootToParentLevel, + uint64_t relativeTileMortonId, + AvailabilityView& availabilityView, + bool isAvailable) noexcept; + + uint32_t _powerOf2; + uint32_t _levelsInSubtree; + Cesium3DTiles::Subtree _subtree; + uint32_t _childCount; + AvailabilityView _tileAvailability; + AvailabilityView _subtreeAvailability; + std::vector _contentAvailability; +}; +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/TileBoundingVolumes.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/TileBoundingVolumes.h new file mode 100644 index 0000000..893dc21 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/TileBoundingVolumes.h @@ -0,0 +1,129 @@ +#pragma once + +#include +#include +#include +#include + +#include + +namespace Cesium3DTiles { +struct BoundingVolume; +} + +namespace Cesium3DTilesContent { + +/** + * @brief Provides functions for extracting bounding volumes types from the + * vectors stored in {@link Cesium3DTiles::BoundingVolume}. + */ +class TileBoundingVolumes { +public: + /** + * @brief Gets the bounding box defined in a + * {@link Cesium3DTiles::BoundingVolume}, if any. + * + * @param boundingVolume The bounding volume from which to get the box. + * @return The box, or `std::nullopt` if the bounding volume does not + * define a box. The box is defined in the tile's coordinate system. + */ + static std::optional + getOrientedBoundingBox(const Cesium3DTiles::BoundingVolume& boundingVolume); + + /** + * @brief Sets the `box` property in a {@link Cesium3DTiles::BoundingVolume} + * based on an {@link CesiumGeometry::OrientedBoundingBox}. + * + * Other bounding volume types, if any, are not modified. + * + * @param boundingVolume The bounding volume to set. + * @param boundingBox The bounding box with which to set the property. + */ + static void setOrientedBoundingBox( + Cesium3DTiles::BoundingVolume& boundingVolume, + const CesiumGeometry::OrientedBoundingBox& boundingBox); + + /** + * @brief Gets the bounding region defined in a + * {@link Cesium3DTiles::BoundingVolume}, if any. + * + * @param boundingVolume The bounding volume from which to get the region. + * @param ellipsoid The ellipsoid on which the region should be defined. + * @return The region, or `std::nullopt` if the bounding volume does not + * define a region. The region is defined in geographic coordinates. + */ + static std::optional getBoundingRegion( + const Cesium3DTiles::BoundingVolume& boundingVolume, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief Sets the `region` property in a {@link Cesium3DTiles::BoundingVolume} + * based on a {@link CesiumGeospatial::BoundingRegion}. + * + * Other bounding volume types, if any, are not modified. + * + * @param boundingVolume The bounding volume to set. + * @param boundingRegion The bounding region with which to set the property. + */ + static void setBoundingRegion( + Cesium3DTiles::BoundingVolume& boundingVolume, + const CesiumGeospatial::BoundingRegion& boundingRegion); + + /** + * @brief Gets the bounding sphere defined in a + * {@link Cesium3DTiles::BoundingVolume}, if any. + * + * @param boundingVolume The bounding volume from which to get the sphere. + * @return The sphere, or `std::nullopt` if the bounding volume does not + * define a sphere. The sphere is defined in the tile's coordinate system. + */ + static std::optional + getBoundingSphere(const Cesium3DTiles::BoundingVolume& boundingVolume); + + /** + * @brief Sets the `sphere` property in a {@link Cesium3DTiles::BoundingVolume} + * based on a {@link CesiumGeometry::BoundingSphere}. + * + * Other bounding volume types, if any, are not modified. + * + * @param boundingVolume The bounding volume to set. + * @param boundingSphere The bounding sphere with which to set the property. + */ + static void setBoundingSphere( + Cesium3DTiles::BoundingVolume& boundingVolume, + const CesiumGeometry::BoundingSphere& boundingSphere); + + /** + * @brief Gets the S2 cell bounding volume defined in the + * `3DTILES_bounding_volume_S2` extension of a + * {@link Cesium3DTiles::BoundingVolume}, if any. + * + * @param boundingVolume The bounding volume from which to get the S2 cell + * bounding volume. + * @param ellipsoid The ellipsoid on which the S2 cell should be defined. + * @return The S2 cell bounding volume, or `std::nullopt` if the bounding + * volume does not define an S2 cell bounding volume. The S2 cell bounding + * volume is defined in geographic coordinates. + */ + static std::optional + getS2CellBoundingVolume( + const Cesium3DTiles::BoundingVolume& boundingVolume, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief Adds the `3DTILES_bounding_volume_S2` extension to a + * {@link Cesium3DTiles::BoundingVolume} based on a + * {@link CesiumGeospatial::S2CellBoundingVolume}. + * + * Other bounding volume types, if any, are not modified. + * + * @param boundingVolume The bounding volume to set. + * @param s2BoundingVolume The S2 bounding volume with which to set the + * property. + */ + static void setS2CellBoundingVolume( + Cesium3DTiles::BoundingVolume& boundingVolume, + const CesiumGeospatial::S2CellBoundingVolume& s2BoundingVolume); +}; + +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/TileTransform.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/TileTransform.h new file mode 100644 index 0000000..19e4269 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/TileTransform.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +#include + +namespace Cesium3DTiles { +struct Tile; +} + +namespace Cesium3DTilesContent { + +/** + * @brief Convenience functions for getting and setting + * {@link Cesium3DTiles::Tile::transform} as a `glm::dmat4`. + */ +class TileTransform { +public: + /** + * @brief Gets the tile's transform as a `glm::dmat4`. + * + * If the tile's transform array has more than 16 elements, the extras are + * silently ignored. + * + * @param tile The tile from which to get the transform. + * @return The transform, or `std::nullopt` if the + * {@link Cesium3DTiles::Tile::transform} has less than 16 elements. + */ + static std::optional + getTransform(const Cesium3DTiles::Tile& tile); + + /** + * @brief Sets the tile's transform using the values of a `glm::dmat4`. + * + * The existing value of the tile's transform property, if any, is replaced. + * + * @param tile The tile on which to set the transform. + * @param newTransform The new transform. + */ + static void + setTransform(Cesium3DTiles::Tile& tile, const glm::dmat4& newTransform); +}; + +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/registerAllTileContentTypes.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/registerAllTileContentTypes.h new file mode 100644 index 0000000..c6e9a50 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesContent/registerAllTileContentTypes.h @@ -0,0 +1,15 @@ +#include "Library.h" + +namespace Cesium3DTilesContent { + +/** + * @brief Register all \ref Cesium3DTilesSelection::Tile "Tile" content types + * that can be loaded. + * + * This is supposed to be called during the initialization, before + * any \ref Cesium3DTilesSelection::Tileset "Tileset" is loaded. It will + * register loaders for the different types of tiles that can be encountered. + */ +CESIUM3DTILESCONTENT_API void registerAllTileContentTypes(); + +} // namespace Cesium3DTilesContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/AssetReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/AssetReader.h new file mode 100644 index 0000000..caa8dfc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/AssetReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Asset; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Asset "Asset" instances from JSON. + */ +class CESIUM3DTILESREADER_API AssetReader { +public: + /** + * @brief Constructs a new instance. + */ + AssetReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Asset from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Asset from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Asset from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/AvailabilityReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/AvailabilityReader.h new file mode 100644 index 0000000..032d7a7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/AvailabilityReader.h @@ -0,0 +1,73 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Availability; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Availability "Availability" instances from + * JSON. + */ +class CESIUM3DTILESREADER_API AvailabilityReader { +public: + /** + * @brief Constructs a new instance. + */ + AvailabilityReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Availability from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Availability from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Availability from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/BoundingVolumeReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/BoundingVolumeReader.h new file mode 100644 index 0000000..3fb1923 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/BoundingVolumeReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct BoundingVolume; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::BoundingVolume "BoundingVolume" instances + * from JSON. + */ +class CESIUM3DTILESREADER_API BoundingVolumeReader { +public: + /** + * @brief Constructs a new instance. + */ + BoundingVolumeReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of BoundingVolume from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of BoundingVolume from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of BoundingVolume from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/BufferReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/BufferReader.h new file mode 100644 index 0000000..191b1fd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/BufferReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Buffer; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Buffer "Buffer" instances from JSON. + */ +class CESIUM3DTILESREADER_API BufferReader { +public: + /** + * @brief Constructs a new instance. + */ + BufferReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Buffer from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Buffer from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Buffer from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/BufferViewReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/BufferViewReader.h new file mode 100644 index 0000000..3b8ab23 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/BufferViewReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct BufferView; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::BufferView "BufferView" instances from JSON. + */ +class CESIUM3DTILESREADER_API BufferViewReader { +public: + /** + * @brief Constructs a new instance. + */ + BufferViewReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of BufferView from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of BufferView from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of BufferView from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ClassPropertyReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ClassPropertyReader.h new file mode 100644 index 0000000..dcad1db --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ClassPropertyReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct ClassProperty; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::ClassProperty "ClassProperty" instances from + * JSON. + */ +class CESIUM3DTILESREADER_API ClassPropertyReader { +public: + /** + * @brief Constructs a new instance. + */ + ClassPropertyReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ClassProperty from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ClassProperty from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ClassProperty from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ClassReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ClassReader.h new file mode 100644 index 0000000..7819a15 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ClassReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Class; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Class "Class" instances from JSON. + */ +class CESIUM3DTILESREADER_API ClassReader { +public: + /** + * @brief Constructs a new instance. + */ + ClassReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Class from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Class from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Class from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ClassStatisticsReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ClassStatisticsReader.h new file mode 100644 index 0000000..003f876 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ClassStatisticsReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct ClassStatistics; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::ClassStatistics "ClassStatistics" instances + * from JSON. + */ +class CESIUM3DTILESREADER_API ClassStatisticsReader { +public: + /** + * @brief Constructs a new instance. + */ + ClassStatisticsReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ClassStatistics from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ClassStatistics from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ClassStatistics from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ContentReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ContentReader.h new file mode 100644 index 0000000..3f20ca1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ContentReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Content; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Content "Content" instances from JSON. + */ +class CESIUM3DTILESREADER_API ContentReader { +public: + /** + * @brief Constructs a new instance. + */ + ContentReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Content from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Content from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Content from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/EnumReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/EnumReader.h new file mode 100644 index 0000000..dd1a08c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/EnumReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Enum; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Enum "Enum" instances from JSON. + */ +class CESIUM3DTILESREADER_API EnumReader { +public: + /** + * @brief Constructs a new instance. + */ + EnumReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Enum from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Enum from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Enum from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/EnumValueReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/EnumValueReader.h new file mode 100644 index 0000000..fd0c8e3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/EnumValueReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct EnumValue; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::EnumValue "EnumValue" instances from JSON. + */ +class CESIUM3DTILESREADER_API EnumValueReader { +public: + /** + * @brief Constructs a new instance. + */ + EnumValueReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of EnumValue from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of EnumValue from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of EnumValue from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/Extension3dTilesBoundingVolumeS2Reader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/Extension3dTilesBoundingVolumeS2Reader.h new file mode 100644 index 0000000..c921b54 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/Extension3dTilesBoundingVolumeS2Reader.h @@ -0,0 +1,79 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Extension3dTilesBoundingVolumeS2; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Extension3dTilesBoundingVolumeS2 + * "Extension3dTilesBoundingVolumeS2" instances from JSON. + */ +class CESIUM3DTILESREADER_API Extension3dTilesBoundingVolumeS2Reader { +public: + /** + * @brief Constructs a new instance. + */ + Extension3dTilesBoundingVolumeS2Reader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Extension3dTilesBoundingVolumeS2 from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + Cesium3DTiles::Extension3dTilesBoundingVolumeS2> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Extension3dTilesBoundingVolumeS2 from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + Cesium3DTiles::Extension3dTilesBoundingVolumeS2> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Extension3dTilesBoundingVolumeS2 from + * a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/GroupMetadataReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/GroupMetadataReader.h new file mode 100644 index 0000000..e3df4ed --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/GroupMetadataReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct GroupMetadata; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::GroupMetadata "GroupMetadata" instances from + * JSON. + */ +class CESIUM3DTILESREADER_API GroupMetadataReader { +public: + /** + * @brief Constructs a new instance. + */ + GroupMetadataReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of GroupMetadata from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of GroupMetadata from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of GroupMetadata from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ImplicitTilingReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ImplicitTilingReader.h new file mode 100644 index 0000000..d0af9a3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/ImplicitTilingReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct ImplicitTiling; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::ImplicitTiling "ImplicitTiling" instances + * from JSON. + */ +class CESIUM3DTILESREADER_API ImplicitTilingReader { +public: + /** + * @brief Constructs a new instance. + */ + ImplicitTilingReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ImplicitTiling from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ImplicitTiling from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ImplicitTiling from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/Library.h new file mode 100644 index 0000000..d42b9ce --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes for reading [3D Tiles](https://github.com/CesiumGS/3d-tiles). + * + * @mermaid-interactive{dependencies/Cesium3DTilesReader} + */ +namespace Cesium3DTilesReader {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUM3DTILESREADER_BUILDING +#define CESIUM3DTILESREADER_API __declspec(dllexport) +#else +#define CESIUM3DTILESREADER_API __declspec(dllimport) +#endif +#else +#define CESIUM3DTILESREADER_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/MetadataEntityReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/MetadataEntityReader.h new file mode 100644 index 0000000..7a62214 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/MetadataEntityReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct MetadataEntity; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::MetadataEntity "MetadataEntity" instances + * from JSON. + */ +class CESIUM3DTILESREADER_API MetadataEntityReader { +public: + /** + * @brief Constructs a new instance. + */ + MetadataEntityReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of MetadataEntity from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of MetadataEntity from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of MetadataEntity from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/PropertiesReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/PropertiesReader.h new file mode 100644 index 0000000..65049a3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/PropertiesReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Properties; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Properties "Properties" instances from JSON. + */ +class CESIUM3DTILESREADER_API PropertiesReader { +public: + /** + * @brief Constructs a new instance. + */ + PropertiesReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Properties from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Properties from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Properties from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/PropertyStatisticsReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/PropertyStatisticsReader.h new file mode 100644 index 0000000..93770c7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/PropertyStatisticsReader.h @@ -0,0 +1,75 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct PropertyStatistics; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::PropertyStatistics "PropertyStatistics" + * instances from JSON. + */ +class CESIUM3DTILESREADER_API PropertyStatisticsReader { +public: + /** + * @brief Constructs a new instance. + */ + PropertyStatisticsReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of PropertyStatistics from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of PropertyStatistics from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of PropertyStatistics from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/PropertyTablePropertyReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/PropertyTablePropertyReader.h new file mode 100644 index 0000000..b94e489 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/PropertyTablePropertyReader.h @@ -0,0 +1,75 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct PropertyTableProperty; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::PropertyTableProperty + * "PropertyTableProperty" instances from JSON. + */ +class CESIUM3DTILESREADER_API PropertyTablePropertyReader { +public: + /** + * @brief Constructs a new instance. + */ + PropertyTablePropertyReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of PropertyTableProperty from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of PropertyTableProperty from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of PropertyTableProperty from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/PropertyTableReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/PropertyTableReader.h new file mode 100644 index 0000000..a389612 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/PropertyTableReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct PropertyTable; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::PropertyTable "PropertyTable" instances from + * JSON. + */ +class CESIUM3DTILESREADER_API PropertyTableReader { +public: + /** + * @brief Constructs a new instance. + */ + PropertyTableReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of PropertyTable from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of PropertyTable from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of PropertyTable from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SchemaReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SchemaReader.h new file mode 100644 index 0000000..04f6574 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SchemaReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Schema; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Schema "Schema" instances from JSON. + */ +class CESIUM3DTILESREADER_API SchemaReader { +public: + /** + * @brief Constructs a new instance. + */ + SchemaReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Schema from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Schema from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Schema from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/StatisticsReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/StatisticsReader.h new file mode 100644 index 0000000..3b949c9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/StatisticsReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Statistics; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Statistics "Statistics" instances from JSON. + */ +class CESIUM3DTILESREADER_API StatisticsReader { +public: + /** + * @brief Constructs a new instance. + */ + StatisticsReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Statistics from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Statistics from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Statistics from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SubtreeFileReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SubtreeFileReader.h new file mode 100644 index 0000000..2bf681a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SubtreeFileReader.h @@ -0,0 +1,141 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace Cesium3DTilesReader { + +/** + * @brief Reads 3D Tiles subtrees from a binary or JSON subtree file. + * + * While {@link SubtreeReader} can parse a {@link Cesium3DTiles::Subtree} from + * a binary buffer as well, `SubtreeFileReader` additionally supports: + * + * 1. Loading binary subtree files. + * 2. Loading external buffers asynchronously. + * 3. Decoding buffers from data URIs. + * + * The subtree file need not be an actual file on disk. + */ +class CESIUM3DTILESREADER_API SubtreeFileReader { +public: + /** + * @brief Constructs a new instance. + */ + SubtreeFileReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Asynchronously loads a subtree from a URL. + * + * \attention Please note that the `SubtreeFileReader` instance must remain + * valid until the returned future resolves or rejects. Destroying it earlier + * will result in undefined behavior. One easy way to achieve this is to + * construct the reader with `std::make_shared` and capture the + * `std::shared_ptr` in the continuation lambda. + * + * @param asyncSystem The AsyncSystem used to do asynchronous work. + * @param pAssetAccessor The accessor used to retrieve the URL and any other + * required resources. + * @param url The URL from which to get the subtree file. + * @param headers Headers to include in the request for the initial subtree + * file and any additional resources that are required. + * @return A future that resolves to the result of loading the subtree. + */ + CesiumAsync::Future> + load( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::string& url, + const std::vector& headers = {}) + const noexcept; + + /** + * @brief Asynchronously loads a subtree from a request. + * + * \attention Please note that the `SubtreeFileReader` instance must remain + * valid until the returned future resolves or rejects. Destroying it earlier + * will result in undefined behavior. One easy way to achieve this is to + * construct the reader with `std::make_shared` and capture the + * `std::shared_ptr` in the continuation lambda. + * + * @param asyncSystem The AsyncSystem used to do asynchronous work. + * @param pAssetAccessor The accessor used to retrieve the URL and any other + * required resources. + * @param pRequest The request to get the subtree file. + * @return A future that resolves to the result of loading the subtree. + */ + CesiumAsync::Future> + load( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pRequest) + const noexcept; + + /** + * @brief Asynchronously loads loads a subtree from data obtained from a URL. + * + * \attention Please note that the `SubtreeFileReader` instance must remain + * valid until the returned future resolves or rejects. Destroying it earlier + * will result in undefined behavior. One easy way to achieve this is to + * construct the reader with `std::make_shared` and capture the + * `std::shared_ptr` in the continuation lambda. + * + * @param asyncSystem The AsyncSystem used to do asynchronous work. + * @param pAssetAccessor The accessor used to retrieve the URL and any other + * required resources. + * @param url The URL from which the subtree file was obtained. + * @param requestHeaders Headers that were included in the request for the + * initial subtree file and should be included for any additional resources + * that are required. + * @param data The subtree file data that was obtained. + * @return A future that resolves to the result of loading the subtree. + */ + CesiumAsync::Future> + load( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::string& url, + const std::vector& requestHeaders, + const std::span& data) const noexcept; + +private: + CesiumAsync::Future> + loadBinary( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::string& url, + const std::vector& requestHeaders, + const std::span& data) const noexcept; + CesiumAsync::Future> + loadJson( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::string& url, + const std::vector& requestHeaders, + const std::span& data) const noexcept; + CesiumAsync::Future> + postprocess( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::string& url, + const std::vector& requestHeaders, + CesiumJsonReader::ReadJsonResult&& loaded) + const noexcept; + + SubtreeReader _reader; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SubtreeReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SubtreeReader.h new file mode 100644 index 0000000..7b8eb02 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SubtreeReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Subtree; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Subtree "Subtree" instances from JSON. + */ +class CESIUM3DTILESREADER_API SubtreeReader { +public: + /** + * @brief Constructs a new instance. + */ + SubtreeReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Subtree from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Subtree from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Subtree from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SubtreesReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SubtreesReader.h new file mode 100644 index 0000000..18307ab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SubtreesReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Subtrees; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Subtrees "Subtrees" instances from JSON. + */ +class CESIUM3DTILESREADER_API SubtreesReader { +public: + /** + * @brief Constructs a new instance. + */ + SubtreesReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Subtrees from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Subtrees from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Subtrees from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/TileReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/TileReader.h new file mode 100644 index 0000000..1b5d21e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/TileReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Tile; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Tile "Tile" instances from JSON. + */ +class CESIUM3DTILESREADER_API TileReader { +public: + /** + * @brief Constructs a new instance. + */ + TileReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Tile from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Tile from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Tile from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/TilesetReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/TilesetReader.h new file mode 100644 index 0000000..17886e3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/TilesetReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace Cesium3DTiles { +struct Tileset; +} // namespace Cesium3DTiles + +namespace Cesium3DTilesReader { + +/** + * @brief Reads \ref Cesium3DTiles::Tileset "Tileset" instances from JSON. + */ +class CESIUM3DTILESREADER_API TilesetReader { +public: + /** + * @brief Constructs a new instance. + */ + TilesetReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Tileset from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Tileset from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Tileset from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/BoundingVolume.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/BoundingVolume.h new file mode 100644 index 0000000..b55823b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/BoundingVolume.h @@ -0,0 +1,97 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace Cesium3DTilesSelection { + +/** + * @brief A bounding volume. + * + * This is a `std::variant` for different types of bounding volumes. + * + * @see CesiumGeometry::BoundingSphere + * @see CesiumGeometry::OrientedBoundingBox + * @see CesiumGeospatial::BoundingRegion + * @see CesiumGeospatial::BoundingRegionWithLooseFittingHeights + * @see CesiumGeospatial::S2CellBoundingVolume + */ +typedef std::variant< + CesiumGeometry::BoundingSphere, + CesiumGeometry::OrientedBoundingBox, + CesiumGeospatial::BoundingRegion, + CesiumGeospatial::BoundingRegionWithLooseFittingHeights, + CesiumGeospatial::S2CellBoundingVolume> + BoundingVolume; + +/** + * @brief Transform the given {@link BoundingVolume} with the given matrix. + * + * If the given bounding volume is a {@link CesiumGeometry::BoundingSphere} + * or {@link CesiumGeometry::OrientedBoundingBox}, then it will be transformed + * with the given matrix. Bounding regions will not be transformed. + * + * @param transform The transform matrix. + * @param boundingVolume The bounding volume. + * @return The transformed bounding volume. + */ +CESIUM3DTILESSELECTION_API BoundingVolume transformBoundingVolume( + const glm::dmat4x4& transform, + const BoundingVolume& boundingVolume); + +/** + * @brief Returns the center of the given {@link BoundingVolume}. + * + * @param boundingVolume The bounding volume. + * @return The center point. + */ +CESIUM3DTILESSELECTION_API glm::dvec3 +getBoundingVolumeCenter(const BoundingVolume& boundingVolume); + +/** + * @brief Estimates the bounding {@link CesiumGeospatial::GlobeRectangle} of the + * given {@link BoundingVolume}. + * + * @param boundingVolume The bounding volume. + * @param ellipsoid The ellipsoid to use for globe calculations. + * @return The bounding {@link CesiumGeospatial::GlobeRectangle}. + */ +CESIUM3DTILESSELECTION_API std::optional +estimateGlobeRectangle( + const BoundingVolume& boundingVolume, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + +/** + * @brief Returns the bounding region if the bounding volume is a + * {@link CesiumGeospatial::BoundingRegion} or a {@link CesiumGeospatial::BoundingRegionWithLooseFittingHeights}. + * + * @param boundingVolume The bounding volume. + * @return A pointer to the bounding region, or nullptr is the bounding volume + * is not a bounding region. + */ +CESIUM3DTILESSELECTION_API const CesiumGeospatial::BoundingRegion* +getBoundingRegionFromBoundingVolume(const BoundingVolume& boundingVolume); + +/** + * @brief Returns an oriented bounding box that contains the given {@link BoundingVolume}. + * + * @param boundingVolume The bounding volume. + * @param ellipsoid The ellipsoid used for this {@link BoundingVolume}. + * @return The oriented bounding box. + */ +CESIUM3DTILESSELECTION_API CesiumGeometry::OrientedBoundingBox +getOrientedBoundingBoxFromBoundingVolume( + const BoundingVolume& boundingVolume, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/DebugTileStateDatabase.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/DebugTileStateDatabase.h new file mode 100644 index 0000000..d6cd689 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/DebugTileStateDatabase.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +namespace Cesium3DTilesSelection { + +class Tile; +class Tileset; + +/** + * @brief Helps debug the tile selection algorithm by recording the state of + * tiles each frame to a SQLite database. + */ +class DebugTileStateDatabase { +public: + /** + * @brief Creates a new instance. + * + * @param databaseFilename The full path and filename of the output SQLite + * database. + */ + DebugTileStateDatabase(const std::string& databaseFilename); + ~DebugTileStateDatabase() noexcept; + + /** + * @brief Records the state of all tiles that are currently loaded by the + * given tileset. + * + * @param frameNumber The current frame number. + * @param tileset The tileset. + */ + void recordAllTileStates(int32_t frameNumber, const Tileset& tileset); + + /** + * @brief Records the state of a given tile. + * + * @param frameNumber The current frame number. + * @param tile The tile. + */ + void recordTileState(int32_t frameNumber, const Tile& tile); + +private: + struct Impl; + std::unique_ptr _pImpl; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/EllipsoidTilesetLoader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/EllipsoidTilesetLoader.h new file mode 100644 index 0000000..36efb21 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/EllipsoidTilesetLoader.h @@ -0,0 +1,67 @@ +#pragma once + +#include "ITilesetHeightSampler.h" + +#include +#include + +namespace Cesium3DTilesSelection { +/** + * @brief A loader that will generate a tileset by tesselating the surface of an + * ellipsoid, producing a simple globe tileset without any terrain features. + */ +class EllipsoidTilesetLoader : public TilesetContentLoader, + public ITilesetHeightSampler { +public: + /** + * @brief Constructs a new instance. + * + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + */ + EllipsoidTilesetLoader( + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief Creates a new tileset with this loader. + * + * @param externals The external interfaces to use. + * @param options Additional options for the tileset. + */ + static std::unique_ptr createTileset( + const TilesetExternals& externals, + const TilesetOptions& options = TilesetOptions{}); + + CesiumAsync::Future + loadTileContent(const TileLoadInput& input) override; + TileChildrenResult createTileChildren( + const Tile& tile, + const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) override; + + ITilesetHeightSampler* getHeightSampler() override; + + CesiumAsync::Future sampleHeights( + const CesiumAsync::AsyncSystem& asyncSystem, + std::vector&& positions) override; + +private: + struct Geometry { + std::vector indices; + std::vector vertices; + std::vector normals; + }; + + void createChildTile( + const Tile& parent, + std::vector& children, + const CesiumGeometry::QuadtreeTileID& childID) const; + + CesiumGeospatial::BoundingRegion + createBoundingRegion(const CesiumGeometry::QuadtreeTileID& quadtreeID) const; + Geometry createGeometry(const Tile& tile) const; + CesiumGltf::Model createModel(const Geometry& geometry) const; + + CesiumGeospatial::GeographicProjection _projection; + CesiumGeometry::QuadtreeTilingScheme _tilingScheme; +}; +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/IPrepareRendererResources.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/IPrepareRendererResources.h new file mode 100644 index 0000000..3236861 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/IPrepareRendererResources.h @@ -0,0 +1,177 @@ +#pragma once + +#include "Library.h" +#include "TileLoadResult.h" + +#include +#include + +#include + +#include +#include + +namespace CesiumAsync { +class AsyncSystem; +} + +namespace CesiumGeometry { +struct Rectangle; +} + +namespace CesiumGltf { +struct Model; +} // namespace CesiumGltf + +namespace CesiumRasterOverlays { +class RasterOverlayTile; +} + +namespace Cesium3DTilesSelection { + +class Tile; + +/** + * The data of a loaded tile together with a pointer to "render resources" data + * representing the result of \ref + * IPrepareRendererResources::prepareInLoadThread "prepareInLoadThread". + */ +struct TileLoadResultAndRenderResources { + /** + * @brief The \ref TileLoadResult passed to \ref + * IPrepareRendererResources::prepareInLoadThread "prepareInLoadThread" in the + * first place. + */ + TileLoadResult result; + /** + * @brief A pointer to the render resources for this tile. + + * Cesium Native doesn't know what this pointer means, and doesn't need to + * know what it means. This pointer is stored in a tile's content as a \ref + * TileRenderContent only so that it can be returned to the implementing + * application as needed and used for rendering there. + */ + void* pRenderResources{nullptr}; +}; + +/** + * @brief When implemented for a rendering engine, allows renderer resources to + * be created and destroyed under the control of a {@link Tileset}. + * + * It is not supposed to be used directly by clients. It is implemented + * for specific rendering engines to provide an infrastructure for preparing the + * data of a {@link Tile} so that it can be used for rendering. + * + * Instances of this class are associated with a {@link Tileset}, in the + * {@link TilesetExternals} structure that is passed to the constructor. + */ +class CESIUM3DTILESSELECTION_API IPrepareRendererResources + : public CesiumRasterOverlays::IPrepareRasterOverlayRendererResources { +public: + virtual ~IPrepareRendererResources() = default; + + /** + * @brief Prepares renderer resources for the given tile. This method is + * invoked in the load thread. + * + * @param asyncSystem The AsyncSystem used to do work in threads. + * @param tileLoadResult The tile data loaded so far. + * @param transform The tile's transformation. + * @param rendererOptions Renderer options associated with the tile from + * {@link TilesetOptions::rendererOptions}. + * @returns A future that resolves to the loaded tile data along with + * arbitrary "render resources" data representing the result of the load + * process. The loaded data may be the same as was originally given to this + * method, or it may be modified. The render resources are passed to + * {@link prepareInMainThread} as the `pLoadThreadResult` parameter. + */ + virtual CesiumAsync::Future + prepareInLoadThread( + const CesiumAsync::AsyncSystem& asyncSystem, + TileLoadResult&& tileLoadResult, + const glm::dmat4& transform, + const std::any& rendererOptions) = 0; + + /** + * @brief Further prepares renderer resources. + * + * This is called after {@link prepareInLoadThread}, and unlike that method, + * this one is called from the same thread that called + * {@link Tileset::updateView}. + * + * @param tile The tile to prepare. + * @param pLoadThreadResult The value returned from + * {@link prepareInLoadThread}. + * @returns Arbitrary data representing the result of the load process. + * Note that the value returned by {@link prepareInLoadThread} will _not_ be + * automatically preserved and passed to {@link free}. If you need to free + * that value, do it in this method before returning. If you need that value + * later, add it to the object returned from this method. + */ + virtual void* prepareInMainThread(Tile& tile, void* pLoadThreadResult) = 0; + + /** + * @brief Frees previously-prepared renderer resources. + * + * This method is always called from the thread that called + * {@link Tileset::updateView} or deleted the tileset. + * + * @param tile The tile for which to free renderer resources. + * @param pLoadThreadResult The result returned by + * {@link prepareInLoadThread}. If {@link prepareInMainThread} has + * already been called, this parameter will be `nullptr`. + * @param pMainThreadResult The result returned by + * {@link prepareInMainThread}. If {@link prepareInMainThread} has + * not yet been called, this parameter will be `nullptr`. + */ + virtual void free( + Tile& tile, + void* pLoadThreadResult, + void* pMainThreadResult) noexcept = 0; + + /** + * @brief Attaches a raster overlay tile to a geometry tile. + * + * @param tile The geometry tile. + * @param overlayTextureCoordinateID The ID of the overlay texture coordinate + * set to use. + * @param rasterTile The raster overlay tile to add. The raster tile will have + * been previously prepared with a call to {@link prepareRasterInLoadThread} + * followed by {@link prepareRasterInMainThread}. + * @param pMainThreadRendererResources The renderer resources for this raster + * tile, as created and returned by {@link prepareRasterInMainThread}. + * @param translation The translation to apply to the texture coordinates + * identified by `overlayTextureCoordinateID`. The texture coordinates to use + * to sample the raster image are computed as `overlayTextureCoordinates * + * scale + translation`. + * @param scale The scale to apply to the texture coordinates identified by + * `overlayTextureCoordinateID`. The texture coordinates to use to sample the + * raster image are computed as `overlayTextureCoordinates * scale + + * translation`. + */ + virtual void attachRasterInMainThread( + const Tile& tile, + int32_t overlayTextureCoordinateID, + const CesiumRasterOverlays::RasterOverlayTile& rasterTile, + void* pMainThreadRendererResources, + const glm::dvec2& translation, + const glm::dvec2& scale) = 0; + + /** + * @brief Detaches a raster overlay tile from a geometry tile. + * + * @param tile The geometry tile. + * @param overlayTextureCoordinateID The ID of the overlay texture coordinate + * set to which the raster tile was previously attached. + * @param rasterTile The raster overlay tile to remove. + * @param pMainThreadRendererResources The renderer resources for this raster + * tile, as created and returned by {@link prepareRasterInMainThread}. + */ + virtual void detachRasterInMainThread( + const Tile& tile, + int32_t overlayTextureCoordinateID, + const CesiumRasterOverlays::RasterOverlayTile& rasterTile, + void* pMainThreadRendererResources) noexcept = 0; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ITileExcluder.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ITileExcluder.h new file mode 100644 index 0000000..cd58113 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ITileExcluder.h @@ -0,0 +1,31 @@ +#pragma once + +namespace Cesium3DTilesSelection { + +class Tile; + +/** + * @brief An interface that allows tiles to be excluded from loading and + * rendering when provided in {@link TilesetOptions::excluders}. + */ +class ITileExcluder { +public: + virtual ~ITileExcluder() = default; + + /** + * @brief Indicates the start of a new frame, initiated with a call to {@link Tileset::updateView}. + */ + virtual void startNewFrame() noexcept {} + + /** + * @brief Determines whether a given tile should be excluded. + * + * @param tile The tile to test + * @return true if this tile and all of its descendants in the bounding volume + * hierarchy should be excluded from loading and rendering. + * @return false if this tile should be included. + */ + virtual bool shouldExclude(const Tile& tile) const noexcept = 0; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ITilesetHeightSampler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ITilesetHeightSampler.h new file mode 100644 index 0000000..8f9b5f9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ITilesetHeightSampler.h @@ -0,0 +1,36 @@ +#pragma once + +#include "Library.h" +#include "SampleHeightResult.h" + +#include +#include + +#include + +namespace CesiumAsync { +class AsyncSystem; +} + +namespace Cesium3DTilesSelection { + +/** + * @brief An interface to query heights from a tileset that can do so + * efficiently without necessarily downloading individual tiles. + */ +class CESIUM3DTILESSELECTION_API ITilesetHeightSampler { +public: + /** + * @brief Queries the heights at a list of locations. + * + * @param asyncSystem The async system used to do work in threads. + * @param positions The positions at which to query heights. The height field + * of each {@link CesiumGeospatial::Cartographic} is ignored. + * @return A future that will be resolved when the heights have been queried. + */ + virtual CesiumAsync::Future sampleHeights( + const CesiumAsync::AsyncSystem& asyncSystem, + std::vector&& positions) = 0; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/Library.h new file mode 100644 index 0000000..fd663fb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes that implement the 3D Tiles standard + * + * @mermaid-interactive{dependencies/Cesium3DTilesSelection} + */ +namespace Cesium3DTilesSelection {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUM3DTILESSELECTION_BUILDING +#define CESIUM3DTILESSELECTION_API __declspec(dllexport) +#else +#define CESIUM3DTILESSELECTION_API __declspec(dllimport) +#endif +#else +#define CESIUM3DTILESSELECTION_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterMappedTo3DTile.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterMappedTo3DTile.h new file mode 100644 index 0000000..d8951a6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterMappedTo3DTile.h @@ -0,0 +1,247 @@ +#pragma once + +#include "IPrepareRendererResources.h" + +#include +#include +#include +#include + +#include + +namespace Cesium3DTilesSelection { + +class Tile; + +/** + * @brief The result of applying a {@link CesiumRasterOverlays::RasterOverlayTile} to geometry. + * + * Instances of this class are used by a {@link Tile} in order to map + * imagery data that is given as {@link CesiumRasterOverlays::RasterOverlayTile} instances + * to the 2D region that is covered by the tile geometry. + */ +class RasterMappedTo3DTile final { +public: + /** + * @brief The states indicating whether the raster tile is attached to the + * geometry. + */ + enum class AttachmentState { + /** + * @brief This raster tile is not yet attached to the geometry at all. + */ + Unattached = 0, + + /** + * @brief This raster tile is attached to the geometry, but it is a + * temporary, low-res version usable while the full-res version is loading. + */ + TemporarilyAttached = 1, + + /** + * @brief This raster tile is attached to the geometry. + */ + Attached = 2 + }; + + /** + * @brief Creates a new instance. + * + * @param pRasterTile The {@link CesiumRasterOverlays::RasterOverlayTile} that is mapped to the + * geometry. + * @param textureCoordinateIndex The index of the texture coordinates to use + * with this mapped raster overlay. + */ + RasterMappedTo3DTile( + const CesiumUtility::IntrusivePointer< + CesiumRasterOverlays::RasterOverlayTile>& pRasterTile, + int32_t textureCoordinateIndex); + + /** + * @brief Returns a {@link CesiumRasterOverlays::RasterOverlayTile} that is currently loading. + * + * The caller has to check the exact state of this tile, using + * {@link Tile::getState}. + * + * @return The tile that is loading, or `nullptr`. + */ + CesiumRasterOverlays::RasterOverlayTile* getLoadingTile() noexcept { + return this->_pLoadingTile.get(); + } + + /** @copydoc getLoadingTile */ + const CesiumRasterOverlays::RasterOverlayTile* + getLoadingTile() const noexcept { + return this->_pLoadingTile.get(); + } + + /** + * @brief Returns the {@link CesiumRasterOverlays::RasterOverlayTile} that represents the imagery + * data that is ready to render. + * + * This will be `nullptr` when the tile data has not yet been loaded. + * + * @return The tile, or `nullptr`. + */ + CesiumRasterOverlays::RasterOverlayTile* getReadyTile() noexcept { + return this->_pReadyTile.get(); + } + + /** @copydoc getReadyTile */ + const CesiumRasterOverlays::RasterOverlayTile* getReadyTile() const noexcept { + return this->_pReadyTile.get(); + } + + /** + * @brief Returns an identifier for the texture coordinates of this tile. + * + * The texture coordinates for this raster are found in the glTF as an + * attribute named `_CESIUMOVERLAY_n` where `n` is this value. + * + * @return The texture coordinate ID. + */ + int32_t getTextureCoordinateID() const noexcept { + return this->_textureCoordinateID; + } + + /** + * @brief Sets the texture coordinate ID. + * + * @see getTextureCoordinateID + * + * @param textureCoordinateID The ID. + */ + void setTextureCoordinateID(int32_t textureCoordinateID) noexcept { + this->_textureCoordinateID = textureCoordinateID; + } + + /** + * @brief Returns the translation that converts between the geometry texture + * coordinates and the texture coordinates that should be used to sample this + * raster texture. + * + * `rasterCoordinates = geometryCoordinates * scale + translation` + * + * @returns The translation. + */ + const glm::dvec2& getTranslation() const noexcept { + return this->_translation; + } + + /** + * @brief Returns the scaling that converts between the geometry texture + * coordinates and the texture coordinates that should be used to sample this + * raster texture. + * + * @see getTranslation + * + * @returns The scaling. + */ + const glm::dvec2& getScale() const noexcept { return this->_scale; } + + /** + * @brief Indicates whether this overlay tile is currently attached to its + * owning geometry tile. + * + * When a raster overlay tile is attached to a geometry tile, + * {@link IPrepareRendererResources::attachRasterInMainThread} is invoked. + * When it is detached, + * {@link IPrepareRendererResources::detachRasterInMainThread} is invoked. + */ + AttachmentState getState() const noexcept { return this->_state; } + + /** + * @brief Update this tile during the update of its owner. + * + * This is only supposed to be called by + * `TilesetContentManager::updateDoneState`. It will return whether there is a + * more detailed version of the raster data available. + * + * @param prepareRendererResources The {@link IPrepareRendererResources} used to + * create render resources for raster overlay + * @param tile The owner tile. + * @return The {@link CesiumRasterOverlays::RasterOverlayTile::MoreDetailAvailable} state. + */ + CesiumRasterOverlays::RasterOverlayTile::MoreDetailAvailable + update(IPrepareRendererResources& prepareRendererResources, Tile& tile); + + /** + * @copydoc CesiumRasterOverlays::RasterOverlayTile::isMoreDetailAvailable + */ + bool isMoreDetailAvailable() const noexcept; + + /** + * @brief Detach the raster from the given tile. + * @param prepareRendererResources The IPrepareRendererResources used to + * detach raster overlay from the tile geometry + * @param tile The owner tile. + */ + void detachFromTile( + IPrepareRendererResources& prepareRendererResources, + Tile& tile) noexcept; + + /** + * @brief Does a throttled load of the mapped {@link CesiumRasterOverlays::RasterOverlayTile}. + * + * @return If the mapped tile is already in the process of loading or it has + * already finished loading, this method does nothing and returns true. If too + * many loads are already in progress, this method does nothing and returns + * false. Otherwise, it begins the asynchronous process to load the tile and + * returns true. + */ + bool loadThrottled() noexcept; + + /** + * @brief Creates a maping between a {@link CesiumRasterOverlays::RasterOverlay} and a {@link Tile}. + * + * The returned mapping will be to a placeholder {@link CesiumRasterOverlays::RasterOverlayTile} if + * the overlay's tile provider is not yet ready (i.e. it's still a + * placeholder) or if the overlap between the tile and the raster overlay + * cannot yet be determined because the projected rectangle of the tile is not + * yet known. + * + * Returns a pointer to the created `RasterMappedTo3DTile` in the Tile's + * {@link Tile::getMappedRasterTiles} collection. Note that this pointer may + * become invalid as soon as another item is added to or removed from this + * collection. + * + * @param maximumScreenSpaceError The maximum screen space error that is used + * for the current tile + * @param tileProvider The overlay tile provider to map to the tile. This may + * be a placeholder if the tile provider is not yet ready. + * @param placeholder The placeholder tile provider for this overlay. This is + * always a placeholder, even if the tile provider is already ready. + * @param tile The tile to which to map the overlay. + * @param missingProjections The list of projections for which there are not + * yet any texture coordiantes. On return, the given overlay's Projection may + * be added to this collection if the Tile does not yet have texture + * coordinates for the Projection and the Projection is not already in the + * collection. + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + * @return A pointer the created mapping, which may be to a placeholder, or + * nullptr if no mapping was created at all because the Tile does not overlap + * the raster overlay. + */ + static RasterMappedTo3DTile* mapOverlayToTile( + double maximumScreenSpaceError, + CesiumRasterOverlays::RasterOverlayTileProvider& tileProvider, + CesiumRasterOverlays::RasterOverlayTileProvider& placeholder, + Tile& tile, + std::vector& missingProjections, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + +private: + void computeTranslationAndScale(const Tile& tile); + + CesiumUtility::IntrusivePointer + _pLoadingTile; + CesiumUtility::IntrusivePointer + _pReadyTile; + int32_t _textureCoordinateID; + glm::dvec2 _translation; + glm::dvec2 _scale; + AttachmentState _state; + bool _originalFailed; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayCollection.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayCollection.h new file mode 100644 index 0000000..bd64866 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayCollection.h @@ -0,0 +1,217 @@ +#pragma once + +#include "Library.h" +#include "TilesetExternals.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace Cesium3DTilesSelection { + +/** + * @brief A collection of {@link CesiumRasterOverlays::RasterOverlay} instances that are associated + * with a {@link Tileset}. + * + * The raster overlay instances may be added to the raster overlay collection + * of a tileset that is returned with {@link Tileset::getOverlays}. When the + * tileset is loaded, one {@link CesiumRasterOverlays::RasterOverlayTileProvider} will be created + * for each raster overlay that had been added. The raster overlay tile provider + * instances will be passed to the {@link CesiumRasterOverlays::RasterOverlayTile} instances that + * they create when the tiles are updated. + */ +class CESIUM3DTILESSELECTION_API RasterOverlayCollection final { +public: + /** + * @brief Creates a new instance. + * + * @param loadedTiles The list of loaded tiles. The collection does not own + * this list, so the list needs to be kept alive as long as the collection's + * lifetime + * @param externals A collection of loading system to load a raster overlay + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + */ + RasterOverlayCollection( + Tile::LoadedLinkedList& loadedTiles, + const TilesetExternals& externals, + const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) noexcept; + + /** + * @brief Deleted Copy constructor. + * + * @param rhs The other instance. + */ + RasterOverlayCollection(const RasterOverlayCollection& rhs) = delete; + + /** + * @brief Move constructor. + * + * @param rhs The other instance. + */ + RasterOverlayCollection(RasterOverlayCollection&& rhs) noexcept = default; + + /** + * @brief Deleted copy assignment. + * + * @param rhs The other instance. + */ + RasterOverlayCollection& + operator=(const RasterOverlayCollection& rhs) = delete; + + /** + * @brief Move assignment. + * + * @param rhs The other instance. + */ + RasterOverlayCollection& + operator=(RasterOverlayCollection&& rhs) noexcept = default; + + ~RasterOverlayCollection() noexcept; + + /** + * @brief Adds the given {@link CesiumRasterOverlays::RasterOverlay} to this collection. + * + * @param pOverlay The pointer to the overlay. This may not be `nullptr`. + */ + void add(const CesiumUtility::IntrusivePointer< + CesiumRasterOverlays::RasterOverlay>& pOverlay); + + /** + * @brief Remove the given {@link CesiumRasterOverlays::RasterOverlay} from this collection. + */ + void remove(const CesiumUtility::IntrusivePointer< + CesiumRasterOverlays::RasterOverlay>& pOverlay) noexcept; + + /** + * @brief Gets the overlays in this collection. + */ + const std::vector< + CesiumUtility::IntrusivePointer>& + getOverlays() const; + + /** + * @brief Gets the tile providers in this collection. Each tile provider + * corresponds with the overlay at the same position in the collection + * returned by {@link getOverlays}. + */ + const std::vector>& + getTileProviders() const; + + /** + * @brief Gets the placeholder tile providers in this collection. Each + * placeholder tile provider corresponds with the overlay at the same position + * in the collection returned by {@link getOverlays}. + */ + const std::vector>& + getPlaceholderTileProviders() const; + + /** + * @brief Finds the tile provider for a given overlay. + * + * If the specified raster overlay is not part of this collection, this method + * will return nullptr. + * + * If the overlay's real tile provider hasn't finished being + * created yet, a placeholder will be returned. That is, its + * {@link CesiumRasterOverlays::RasterOverlayTileProvider::isPlaceholder} method will return true. + * + * @param overlay The overlay for which to obtain the tile provider. + * @return The tile provider, if any, corresponding to the raster overlay. + */ + CesiumRasterOverlays::RasterOverlayTileProvider* findTileProviderForOverlay( + CesiumRasterOverlays::RasterOverlay& overlay) noexcept; + + /** + * @copydoc findTileProviderForOverlay + */ + const CesiumRasterOverlays::RasterOverlayTileProvider* + findTileProviderForOverlay( + const CesiumRasterOverlays::RasterOverlay& overlay) const noexcept; + + /** + * @brief Finds the placeholder tile provider for a given overlay. + * + * If the specified raster overlay is not part of this collection, this method + * will return nullptr. + * + * This method will return the placeholder tile provider even if the real one + * has been created. This is useful to create placeholder tiles when the + * rectangle in the overlay's projection is not yet known. + * + * @param overlay The overlay for which to obtain the tile provider. + * @return The placeholder tile provider, if any, corresponding to the raster + * overlay. + */ + CesiumRasterOverlays::RasterOverlayTileProvider* + findPlaceholderTileProviderForOverlay( + CesiumRasterOverlays::RasterOverlay& overlay) noexcept; + + /** + * @copydoc findPlaceholderTileProviderForOverlay + */ + const CesiumRasterOverlays::RasterOverlayTileProvider* + findPlaceholderTileProviderForOverlay( + const CesiumRasterOverlays::RasterOverlay& overlay) const noexcept; + + /** + * @brief A constant iterator for {@link CesiumRasterOverlays::RasterOverlay} instances. + */ + typedef std::vector>::const_iterator const_iterator; + + /** + * @brief Returns an iterator at the beginning of this collection. + */ + const_iterator begin() const noexcept; + + /** + * @brief Returns an iterator at the end of this collection. + */ + const_iterator end() const noexcept; + + /** + * @brief Gets the number of overlays in the collection. + */ + size_t size() const noexcept; + +private: + // We store the list of overlays and tile providers in this separate class + // so that we can separate its lifetime from the lifetime of the + // RasterOverlayCollection. We need to do this because the async operations + // that create tile providers from overlays need to have somewhere to write + // the result. And we can't extend the lifetime of the entire + // RasterOverlayCollection until the async operations complete because the + // RasterOverlayCollection has a pointer to the tile LoadedLinkedList, which + // is owned externally and may become invalid before the async operations + // complete. + struct OverlayList + : public CesiumUtility::ReferenceCountedNonThreadSafe { + std::vector< + CesiumUtility::IntrusivePointer> + overlays{}; + std::vector> + tileProviders{}; + std::vector> + placeholders{}; + }; + + Tile::LoadedLinkedList* _pLoadedTiles; + TilesetExternals _externals; + CesiumGeospatial::Ellipsoid _ellipsoid; + CesiumUtility::IntrusivePointer _pOverlays; + CESIUM_TRACE_DECLARE_TRACK_SET(_loadingSlots, "Raster Overlay Loading Slot") +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterizedPolygonsTileExcluder.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterizedPolygonsTileExcluder.h new file mode 100644 index 0000000..644137d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterizedPolygonsTileExcluder.h @@ -0,0 +1,54 @@ +#pragma once + +#include "ITileExcluder.h" +#include "Library.h" + +#include + +namespace CesiumRasterOverlays { +class RasterizedPolygonsOverlay; +} + +namespace Cesium3DTilesSelection { + +/** + * @brief When provided to {@link TilesetOptions::excluders}, uses the polygons + * owned by a {@link CesiumRasterOverlays::RasterizedPolygonsOverlay} to exclude tiles that are + * entirely inside any of the polygon from loading. This is useful when the + * polygons will be used for clipping. + */ +class CESIUM3DTILESSELECTION_API RasterizedPolygonsTileExcluder + : public Cesium3DTilesSelection::ITileExcluder { +public: + /** + * @brief Constructs a new instance. + * + * @param pOverlay The overlay definining the polygons. + */ + RasterizedPolygonsTileExcluder( + const CesiumUtility::IntrusivePointer< + const CesiumRasterOverlays::RasterizedPolygonsOverlay>& + pOverlay) noexcept; + + /** + * @brief Determines whether a given tile is entirely inside a polygon and + * therefore should be excluded. + * + * @param tile The tile to check. + * @return true if the tile should be excluded because it is entirely inside a + * polygon. + */ + virtual bool shouldExclude(const Tile& tile) const noexcept override; + + /** + * @brief Gets the overlay defining the polygons. + */ + const CesiumRasterOverlays::RasterizedPolygonsOverlay& getOverlay() const; + +private: + CesiumUtility::IntrusivePointer< + const CesiumRasterOverlays::RasterizedPolygonsOverlay> + _pOverlay; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/SampleHeightResult.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/SampleHeightResult.h new file mode 100644 index 0000000..ee25eac --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/SampleHeightResult.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +#include +#include + +namespace Cesium3DTilesSelection { + +/** + * @brief The result of sampling heights with + * {@link Tileset::sampleHeightMostDetailed}. + */ +struct SampleHeightResult { + /** + * @brief The positions and their sampled heights. + * + * For each resulting position, its longitude and latitude values will match + * values from its input. Its height will either be the height sampled from + * the tileset at that position, or the original input height if the sample + * was unsuccessful. To determine which, look at the value of + * {@link SampleHeightResult::sampleSuccess} at the same index. + */ + std::vector positions; + + /** + * @brief The success of each sample. + * + * Each entry specifies whether the height for the position at the + * corresponding index was successfully sampled. If true, then + * {@link SampleHeightResult::positions} has a valid height sampled from the + * tileset at this index. If false, the height could not be sampled, leaving + * the height in {@link SampleHeightResult::positions} unchanged from the + * original input height. + */ + std::vector sampleSuccess; + + /** + * @brief Any warnings that occurred while sampling heights. + */ + std::vector warnings; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/Tile.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/Tile.h new file mode 100644 index 0000000..5dda2de --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/Tile.h @@ -0,0 +1,563 @@ +#pragma once + +#include "BoundingVolume.h" +#include "Library.h" +#include "RasterMappedTo3DTile.h" +#include "TileContent.h" +#include "TileID.h" +#include "TileRefine.h" +#include "TileSelectionState.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Cesium3DTilesSelection { +class TilesetContentLoader; + +/** + * The current state of this tile in the loading process. + */ +enum class TileLoadState { + /** + * @brief This tile is in the process of being unloaded, but could not be + * fully unloaded because an asynchronous process is using its loaded data. + */ + Unloading = -2, + + /** + * @brief Something went wrong while loading this tile, but it may be a + * temporary problem. + */ + FailedTemporarily = -1, + + /** + * @brief The tile is not yet loaded at all, beyond the metadata in + * tileset.json. + */ + Unloaded = 0, + + /** + * @brief The tile content is currently being loaded. + * + * Note that while a tile is in this state, its {@link Tile::getContent}, + * and {@link Tile::getState}, methods may be called from the load thread, + * and the state may change due to the internal loading process. + */ + ContentLoading = 1, + + /** + * @brief The tile content has finished loading. + */ + ContentLoaded = 2, + + /** + * @brief The tile is completely done loading. + */ + Done = 3, + + /** + * @brief Something went wrong while loading this tile and it will not be + * retried. + */ + Failed = 4, +}; + +/** + * @brief A tile in a {@link Tileset}. + * + * The tiles of a tileset form a hierarchy, where each tile may contain + * renderable content, and each tile has an associated bounding volume. + * + * The actual hierarchy is represented with the {@link Tile::getParent} + * and {@link Tile::getChildren} functions. + * + * The renderable content is provided as a {@link TileContent} + * from the {@link Tile::getContent} function. + * The {@link Tile::getGeometricError} function returns the geometric + * error of the representation of the renderable content of a tile. + * + * The {@link BoundingVolume} is given by the {@link Tile::getBoundingVolume} + * function. This bounding volume encloses the renderable content of the + * tile itself, as well as the renderable content of all children, yielding + * a spatially coherent hierarchy of bounding volumes. + * + * The bounding volume of the content of an individual tile is given + * by the {@link Tile::getContentBoundingVolume} function. + * + */ +class CESIUM3DTILESSELECTION_API Tile final { +public: + /** + * @brief Construct a tile with unknown content and a loader that is used to + * load the content of this tile. Tile has Unloaded status when initializing + * with this constructor. + * + * @param pLoader The {@link TilesetContentLoader} that is used to load the tile. + */ + explicit Tile(TilesetContentLoader* pLoader) noexcept; + + /** + * @brief Construct a tile with an external content and a loader that is + * associated with this tile. Tile has ContentLoaded status when initializing + * with this constructor. + * + * @param pLoader The {@link TilesetContentLoader} that is assiocated with this tile. + * @param externalContent External content that is associated with this tile. + */ + Tile( + TilesetContentLoader* pLoader, + std::unique_ptr&& externalContent) noexcept; + + /** + * @brief Construct a tile with an empty content and a loader that is + * associated with this tile. Tile has ContentLoaded status when initializing + * with this constructor. + * + * @param pLoader The {@link TilesetContentLoader} that is assiocated with this tile. + * @param emptyContent A content tag indicating that the tile has no content. + */ + Tile(TilesetContentLoader* pLoader, TileEmptyContent emptyContent) noexcept; + + /** + * @brief Default destructor, which clears all resources associated with this + * tile. + */ + ~Tile() noexcept = default; + + /** + * @brief Copy constructor. + * + * @param rhs The other instance. + */ + Tile(const Tile& rhs) = delete; + + /** + * @brief Move constructor. + * + * @param rhs The other instance. + */ + Tile(Tile&& rhs) noexcept; + + /** + * @brief Copy constructor. + * + * @param rhs The other instance. + */ + Tile& operator=(const Tile& rhs) = delete; + + /** + * @brief Move assignment operator. + * + * @param rhs The other instance. + */ + Tile& operator=(Tile&& rhs) noexcept; + + /** + * @brief Returns the parent of this tile in the tile hierarchy. + * + * This will be the `nullptr` if this is the root tile. + * + * @return The parent. + */ + Tile* getParent() noexcept { return this->_pParent; } + + /** @copydoc Tile::getParent() */ + const Tile* getParent() const noexcept { return this->_pParent; } + + /** + * @brief Returns a *view* on the children of this tile. + * + * The returned span will become invalid when this tile is destroyed. + * + * @return The children of this tile. + */ + std::span getChildren() noexcept { + return std::span(this->_children); + } + + /** @copydoc Tile::getChildren() */ + std::span getChildren() const noexcept { + return std::span(this->_children); + } + + /** + * @brief Assigns the given child tiles to this tile. + * + * This function is not supposed to be called by clients. + * + * @param children The child tiles. + * @throws `std::runtime_error` if this tile already has children. + */ + void createChildTiles(std::vector&& children); + + /** + * @brief Returns the {@link BoundingVolume} of this tile. + * + * This is a bounding volume that encloses the content of this tile, + * as well as the content of all child tiles. + * + * @see Tile::getContentBoundingVolume + * + * @return The bounding volume. + */ + const BoundingVolume& getBoundingVolume() const noexcept { + return this->_boundingVolume; + } + + /** + * @brief Set the {@link BoundingVolume} of this tile. + * + * This function is not supposed to be called by clients. + * + * @param value The bounding volume. + */ + void setBoundingVolume(const BoundingVolume& value) noexcept { + this->_boundingVolume = value; + } + + /** + * @brief Returns the viewer request volume of this tile. + * + * The viewer request volume is an optional {@link BoundingVolume} that + * may be associated with a tile. It allows controlling the rendering + * process of the tile content: If the viewer request volume is present, + * then the content of the tile will only be rendered when the viewer + * (i.e. the camera position) is inside the viewer request volume. + * + * @return The viewer request volume, or an empty optional. + */ + const std::optional& getViewerRequestVolume() const noexcept { + return this->_viewerRequestVolume; + } + + /** + * @brief Set the viewer request volume of this tile. + * + * This function is not supposed to be called by clients. + * + * @param value The viewer request volume. + */ + void + setViewerRequestVolume(const std::optional& value) noexcept { + this->_viewerRequestVolume = value; + } + + /** + * @brief Returns the geometric error of this tile. + * + * This is the error, in meters, introduced if this tile is rendered and its + * children are not. This is used to compute screen space error, i.e., the + * error measured in pixels. + * + * @return The geometric error of this tile, in meters. + */ + double getGeometricError() const noexcept { return this->_geometricError; } + + /** + * @brief Set the geometric error of the contents of this tile. + * + * This function is not supposed to be called by clients. + * + * @param value The geometric error, in meters. + */ + void setGeometricError(double value) noexcept { + this->_geometricError = value; + } + + /** + * @brief Gets the tile's geometric error as if by calling + * {@link getGeometricError}, except that if the error is smaller than + * {@link CesiumUtility::Math::Epsilon5} the returned geometric error is instead computed as + * half of the parent tile's (non-zero) geometric error. + * + * This is useful for determining when to refine what would ordinarily be a + * leaf tile, for example to attach more detailed raster overlays to it. + * + * If this tile and all of its ancestors have a geometric error less than + * {@link CesiumUtility::Math::Epsilon5}, returns {@link CesiumUtility::Math::Epsilon5}. + * + * @return The non-zero geometric error. + */ + double getNonZeroGeometricError() const noexcept; + + /** + * @brief Returns whether to unconditionally refine this tile. + * + * This is useful in cases such as with external tilesets, where instead of a + * tile having any content, it points to an external tileset's root. So the + * tile always needs to be refined otherwise the external tileset will not be + * displayed. + * + * @return Whether to uncoditionally refine this tile. + */ + bool getUnconditionallyRefine() const noexcept { + return glm::isinf(this->_geometricError); + } + + /** + * @brief Marks that this tile should be unconditionally refined. + * + * This function is not supposed to be called by clients. + */ + void setUnconditionallyRefine() noexcept { + this->_geometricError = std::numeric_limits::infinity(); + } + + /** + * @brief The refinement strategy of this tile. + * + * Returns the {@link TileRefine} value that indicates the refinement strategy + * for this tile. This is `Add` when the content of the + * child tiles is *added* to the content of this tile during refinement, and + * `Replace` when the content of the child tiles *replaces* + * the content of this tile during refinement. + * + * @return The refinement strategy. + */ + TileRefine getRefine() const noexcept { return this->_refine; } + + /** + * @brief Set the refinement strategy of this tile. + * + * This function is not supposed to be called by clients. + * + * @param value The refinement strategy. + */ + void setRefine(TileRefine value) noexcept { this->_refine = value; } + + /** + * @brief Gets the transformation matrix for this tile. + * + * This matrix does _not_ need to be multiplied with the tile's parent's + * transform as this has already been done. + * + * @return The transform matrix. + */ + const glm::dmat4x4& getTransform() const noexcept { return this->_transform; } + + /** + * @brief Set the transformation matrix for this tile. + * + * This function is not supposed to be called by clients. + * + * @param value The transform matrix. + */ + void setTransform(const glm::dmat4x4& value) noexcept { + this->_transform = value; + } + + /** + * @brief Returns the {@link TileID} of this tile. + * + * This function is not supposed to be called by clients. + * + * @return The tile ID. + */ + const TileID& getTileID() const noexcept { return this->_id; } + + /** + * @brief Set the {@link TileID} of this tile. + * + * This function is not supposed to be called by clients. + * + * @param id The tile ID. + */ + void setTileID(const TileID& id) noexcept { this->_id = id; } + + /** + * @brief Returns the {@link BoundingVolume} of the renderable content of this + * tile. + * + * The content bounding volume is a bounding volume that tightly fits only the + * renderable content of the tile. This enables tighter view frustum culling, + * making it possible to exclude from rendering any content not in the view + * frustum. + * + * @see Tile::getBoundingVolume + */ + const std::optional& + getContentBoundingVolume() const noexcept { + return this->_contentBoundingVolume; + } + + /** + * @brief Set the {@link BoundingVolume} of the renderable content of this + * tile. + * + * This function is not supposed to be called by clients. + * + * @param value The content bounding volume + */ + void setContentBoundingVolume( + const std::optional& value) noexcept { + this->_contentBoundingVolume = value; + } + + /** + * @brief Returns the {@link TileSelectionState} of this tile. + * + * This function is not supposed to be called by clients. + * + * @return The last selection state + */ + TileSelectionState& getLastSelectionState() noexcept { + return this->_lastSelectionState; + } + + /** @copydoc Tile::getLastSelectionState() */ + const TileSelectionState& getLastSelectionState() const noexcept { + return this->_lastSelectionState; + } + + /** + * @brief Set the {@link TileSelectionState} of this tile. + * + * This function is not supposed to be called by clients. + * + * @param newState The new stace + */ + void setLastSelectionState(const TileSelectionState& newState) noexcept { + this->_lastSelectionState = newState; + } + + /** + * @brief Determines the number of bytes in this tile's geometry and texture + * data. + */ + int64_t computeByteSize() const noexcept; + + /** + * @brief Returns the raster overlay tiles that have been mapped to this tile. + */ + std::vector& getMappedRasterTiles() noexcept { + return this->_rasterTiles; + } + + /** @copydoc Tile::getMappedRasterTiles() */ + const std::vector& + getMappedRasterTiles() const noexcept { + return this->_rasterTiles; + } + + /** + * @brief Get the content of the tile. + */ + const TileContent& getContent() const noexcept { return _content; } + + /** @copydoc Tile::getContent() const */ + TileContent& getContent() noexcept { return _content; } + + /** + * @brief Determines if this tile is currently renderable. + */ + bool isRenderable() const noexcept; + + /** + * @brief Determines if this tile has mesh content. + */ + bool isRenderContent() const noexcept; + + /** + * @brief Determines if this tile has external tileset content. + */ + bool isExternalContent() const noexcept; + + /** + * @brief Determines if this tile has empty content. + */ + bool isEmptyContent() const noexcept; + + /** + * @brief get the loader that is used to load the tile content. + */ + TilesetContentLoader* getLoader() const noexcept; + + /** + * @brief Returns the {@link TileLoadState} of this tile. + */ + TileLoadState getState() const noexcept; + +private: + struct TileConstructorImpl {}; + template < + typename... TileContentArgs, + typename TileContentEnable = std::enable_if_t< + std::is_constructible_v, + int>> + Tile( + TileConstructorImpl tag, + TileLoadState loadState, + TilesetContentLoader* pLoader, + TileContentArgs&&... args); + + void setParent(Tile* pParent) noexcept; + + void setState(TileLoadState state) noexcept; + + /** + * @brief Gets a flag indicating whether this tile might have latent children. + * Latent children don't exist in the `_children` property, but can be created + * by the {@link TilesetContentLoader}. + * + * When true, this tile might have children that can be created by the + * TilesetContentLoader but aren't yet reflected in the `_children` property. + * For example, in implicit tiling, we save memory by only creating explicit + * Tile instances from implicit availability as those instances are needed. + * When this flag is true, the creation of those explicit instances hasn't + * happened yet for this tile. + * + * If this flag is false, the children have already been created, if they + * exist. The tile may still have no children because it is a leaf node. + */ + bool getMightHaveLatentChildren() const noexcept; + + void setMightHaveLatentChildren(bool mightHaveLatentChildren) noexcept; + + // Position in bounding-volume hierarchy. + Tile* _pParent; + std::vector _children; + + // Properties from tileset.json. + // These are immutable after the tile leaves TileState::Unloaded. + TileID _id; + BoundingVolume _boundingVolume; + std::optional _viewerRequestVolume; + std::optional _contentBoundingVolume; + double _geometricError; + TileRefine _refine; + glm::dmat4x4 _transform; + + // Selection state + TileSelectionState _lastSelectionState; + + // tile content + CesiumUtility::DoublyLinkedListPointers _loadedTilesLinks; + TileContent _content; + TilesetContentLoader* _pLoader; + TileLoadState _loadState; + bool _mightHaveLatentChildren; + + // mapped raster overlay + std::vector _rasterTiles; + + friend class TilesetContentManager; + friend class MockTilesetContentManagerTestFixture; + +public: + /** + * @brief A {@link CesiumUtility::DoublyLinkedList} for tile objects. + */ + typedef CesiumUtility::DoublyLinkedList + LoadedLinkedList; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileContent.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileContent.h new file mode 100644 index 0000000..c92fe32 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileContent.h @@ -0,0 +1,306 @@ +#pragma once + +#include "Library.h" +#include "TilesetMetadata.h" + +#include +#include +#include +#include + +#include +#include +#include + +namespace Cesium3DTilesSelection { +/** + * @brief A content tag that indicates the {@link TilesetContentLoader} does not + * know if a tile's content will point to a mesh content or an external + * tileset. The content of the tile is only known when the loader loads the tile + * to inspect the content. + */ +struct CESIUM3DTILESSELECTION_API TileUnknownContent {}; + +/** + * @brief A content tag that indicates a tile has no content. + * + * There are two possible ways to handle a tile with no content: + * + * 1. Treat it as a placeholder used for more efficient culling, but + * never render it. Refining to this tile is equivalent to refining + * to its children. + * 2. Treat it as an indication that nothing need be rendered in this + * area at this level-of-detail. In other words, "render" it as a + * hole. To have this behavior, the tile should _not_ have content at + * all. + * + * We distinguish whether the tileset creator wanted (1) or (2) by + * comparing this tile's geometricError to the geometricError of its + * parent tile. If this tile's error is greater than or equal to its + * parent, treat it as (1). If it's less, treat it as (2). + * + * For a tile with no parent there's no difference between the + * behaviors. + */ +struct CESIUM3DTILESSELECTION_API TileEmptyContent {}; + +/** + * @brief A content tag that indicates a tile content points to an + * external tileset. When this tile is loaded, all the tiles in the + * external tileset will become children of this external content tile + */ +struct CESIUM3DTILESSELECTION_API TileExternalContent { + /** + * @brief The metadata associated with this tileset. + */ + TilesetMetadata metadata; +}; + +/** + * @brief A content tag that indicates a tile has a glTF model content and + * render resources for the model + */ +class CESIUM3DTILESSELECTION_API TileRenderContent { +public: + /** + * @brief Construct the content with a glTF model + * + * @param model A glTF model that will be owned by this content + */ + TileRenderContent(CesiumGltf::Model&& model); + + /** + * @brief Retrieve a glTF model that is owned by this content + * + * @return A glTF model that is owned by this content + */ + const CesiumGltf::Model& getModel() const noexcept; + + /** + * @brief Retrieve a glTF model that is owned by this content + * + * @return A glTF model that is owned by this content + */ + CesiumGltf::Model& getModel() noexcept; + + /** + * @brief Set the glTF model for this content + * + * @param model A glTF model that will be owned by this content + */ + void setModel(const CesiumGltf::Model& model); + + /** + * @brief Set the glTF model for this content + * + * @param model A glTF model that will be owned by this content + */ + void setModel(CesiumGltf::Model&& model); + + /** + * @brief Get the {@link CesiumRasterOverlays::RasterOverlayDetails} which is the result of generating raster overlay UVs for the glTF model + * + * @return The {@link CesiumRasterOverlays::RasterOverlayDetails} that is owned by this content + */ + const CesiumRasterOverlays::RasterOverlayDetails& + getRasterOverlayDetails() const noexcept; + + /** + * @brief Get the {@link CesiumRasterOverlays::RasterOverlayDetails} which is the result of generating raster overlay UVs for the glTF model + * + * @return The {@link CesiumRasterOverlays::RasterOverlayDetails} that is owned by this content + */ + CesiumRasterOverlays::RasterOverlayDetails& + getRasterOverlayDetails() noexcept; + + /** + * @brief Set the {@link CesiumRasterOverlays::RasterOverlayDetails} which is the result of generating raster overlay UVs for the glTF model + * + * @param rasterOverlayDetails The {@link CesiumRasterOverlays::RasterOverlayDetails} that will be owned by this content + */ + void setRasterOverlayDetails( + const CesiumRasterOverlays::RasterOverlayDetails& rasterOverlayDetails); + + /** + * @brief Set the {@link CesiumRasterOverlays::RasterOverlayDetails} which is the result of generating raster overlay UVs for the glTF model + * + * @param rasterOverlayDetails The {@link CesiumRasterOverlays::RasterOverlayDetails} that will be owned by this content + */ + void setRasterOverlayDetails( + CesiumRasterOverlays::RasterOverlayDetails&& rasterOverlayDetails); + + /** + * @brief Get the list of \ref CesiumUtility::Credit "Credit" of the content + * + * @return The list of \ref CesiumUtility::Credit "Credit" of the content + */ + const std::vector& getCredits() const noexcept; + + /** + * @brief Get the list of \ref CesiumUtility::Credit "Credit" of the content + * + * @return The list of \ref CesiumUtility::Credit "Credit" of the content + */ + std::vector& getCredits() noexcept; + + /** + * @brief Set the list of \ref CesiumUtility::Credit "Credit" for the content + * + * @param credits The list of \ref CesiumUtility::Credit "Credit" to be owned + * by the content + */ + void setCredits(std::vector&& credits); + + /** + * @brief Set the list of \ref CesiumUtility::Credit "Credit" for the content + * + * @param credits The list of \ref CesiumUtility::Credit "Credit" to be owned + * by the content + */ + void setCredits(const std::vector& credits); + + /** + * @brief Get the render resources created for the glTF model of the content + * + * @return The render resources that is created for the glTF model + */ + void* getRenderResources() const noexcept; + + /** + * @brief Set the render resources created for the glTF model of the content + * + * @param pRenderResources The render resources that is created for the glTF + * model + */ + void setRenderResources(void* pRenderResources) noexcept; + + /** + * @brief Get the fade percentage that this tile during an LOD transition. + * + * This will be used when {@link TilesetOptions::enableLodTransitionPeriod} + * is true. Tile fades can be used to make LOD transitions appear less abrupt + * and jarring. It is up to client implementations how to render the fade + * percentage, but dithered fading is recommended. + * + * @return The fade percentage. + */ + float getLodTransitionFadePercentage() const noexcept; + + /** + * @brief Set the fade percentage of this tile during an LOD transition with. + * Not to be used by clients. + * + * @param percentage The new fade percentage. + */ + void setLodTransitionFadePercentage(float percentage) noexcept; + +private: + CesiumGltf::Model _model; + void* _pRenderResources; + CesiumRasterOverlays::RasterOverlayDetails _rasterOverlayDetails; + std::vector _credits; + float _lodTransitionFadePercentage; +}; + +/** + * @brief A tile content container that can store and query the content type + * that is currently being owned by the tile + */ +class CESIUM3DTILESSELECTION_API TileContent { + using TileContentKindImpl = std::variant< + TileUnknownContent, + TileEmptyContent, + std::unique_ptr, + std::unique_ptr>; + +public: + /** + * @brief Construct an unknown content for a tile. This constructor + * is useful when the tile content is known after its content is downloaded by + * {@link TilesetContentLoader} + */ + TileContent(); + + /** + * @brief Construct an empty content for a tile + */ + TileContent(TileEmptyContent content); + + /** + * @brief Construct an external content for a tile whose content + * points to an external tileset + */ + TileContent(std::unique_ptr&& content); + + /** + * @brief Set an unknown content tag for a tile. This constructor + * is useful when the tile content is known after its content is downloaded by + * {@link TilesetContentLoader} + */ + void setContentKind(TileUnknownContent content); + + /** + * @brief Construct an empty content tag for a tile + */ + void setContentKind(TileEmptyContent content); + + /** + * @brief Set an external content for a tile whose content + * points to an external tileset + */ + void setContentKind(std::unique_ptr&& content); + + /** + * @brief Set a glTF model content for a tile + */ + void setContentKind(std::unique_ptr&& content); + + /** + * @brief Query if a tile has an unknown content + */ + bool isUnknownContent() const noexcept; + + /** + * @brief Query if a tile has an empty content + */ + bool isEmptyContent() const noexcept; + + /** + * @brief Query if a tile has an external content which points to + * an external tileset + */ + bool isExternalContent() const noexcept; + + /** + * @brief Query if a tile has an glTF model content + */ + bool isRenderContent() const noexcept; + + /** + * @brief Get the {@link TileRenderContent} which stores the glTF model + * and render resources of the tile + */ + const TileRenderContent* getRenderContent() const noexcept; + + /** + * @brief Get the {@link TileRenderContent} which stores the glTF model + * and render resources of the tile + */ + TileRenderContent* getRenderContent() noexcept; + + /** + * @brief Get the {@link TileExternalContent} which stores the details of + * the external tileset. + */ + const TileExternalContent* getExternalContent() const noexcept; + + /** + * @brief Get the {@link TileExternalContent} which stores the details of + * the external tileset. + */ + TileExternalContent* getExternalContent() noexcept; + +private: + TileContentKindImpl _contentKind; +}; +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileID.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileID.h new file mode 100644 index 0000000..b5ee683 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileID.h @@ -0,0 +1,61 @@ +#pragma once + +#include "Library.h" + +#include +#include + +#include +#include + +namespace Cesium3DTilesSelection { + +/** + * @brief An identifier for a {@link Tile} inside the tile hierarchy. + * + * This ID is stored in the tile as the {@link Tile::getTileID}. + * It is assigned to the tile at construction time, and may be + * used to identify and access the children of a given tile. + * + * Depending on the exact type of the tile and its contents, this + * identifier may have different forms: + * + * * A `std::string`: This is an explicitly-described tile and + * the ID is the URL of the tile's content. + * * A {@link CesiumGeometry::QuadtreeTileID}: This is an implicit + * tile in the quadtree. The URL of the tile's content is formed + * by instantiating the context's template URL with this ID. + * * A {@link CesiumGeometry::OctreeTileID}: This is an implicit + * tile in the octree. The URL of the tile's content is formed + * by instantiating the context's template URL with this ID. + * * A {@link CesiumGeometry::UpsampledQuadtreeNode}: This tile doesn't + * have any content, but content for it can be created by subdividing + * the parent tile's content. + */ +typedef std::variant< + std::string, + CesiumGeometry::QuadtreeTileID, + CesiumGeometry::OctreeTileID, + CesiumGeometry::UpsampledQuadtreeNode> + TileID; + +/** + * @brief Utility functions related to {@link TileID} objects. + */ +struct CESIUM3DTILESSELECTION_API TileIdUtilities { + /** + * @brief Creates an unspecified string representation of the given {@link + * TileID}. + * + * The returned string will contain information about the given tile ID, + * depending on its type. The exact format and contents of this string + * is not specified. This is mainly intended for printing informative + * log messages. + * + * @param tileId The tile ID + * @return The string + */ + static std::string createTileIdString(const TileID& tileId); +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileLoadResult.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileLoadResult.h new file mode 100644 index 0000000..8e7288b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileLoadResult.h @@ -0,0 +1,162 @@ +#pragma once + +#include "BoundingVolume.h" +#include "TileContent.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace Cesium3DTilesSelection { + +class Tile; + +/** + * @brief Store the content of the tile after finishing + * loading tile using {@link TilesetContentLoader::loadTileContent}: + * + * 1. Returning {@link TileUnknownContent} means that the loader doesn't know + * the content of the tile. This content type is useful when loader fails to + * load the tile content; or a background task is running to determine the tile + * content and the loader wants the client to retry later at some point in the + * future + * + * 2. Returning {@link TileEmptyContent} means that this tile has no content and mostly used + * for efficient culling during the traversal process + * + * 3. Returning {@link TileExternalContent} means that this tile points to an external tileset + * + * 4. Returning {@link CesiumGltf::Model} means that this tile has glTF model + */ +using TileContentKind = std::variant< + TileUnknownContent, + TileEmptyContent, + TileExternalContent, + CesiumGltf::Model>; + +/** + * @brief Indicate the status of {@link Cesium3DTilesSelection::TilesetContentLoader::loadTileContent} and + * {@link Cesium3DTilesSelection::TilesetContentLoader::createTileChildren} operations + */ +enum class TileLoadResultState { + /** + * @brief The operation is successful and all the fields in {@link TileLoadResult} + * or {@link TileChildrenResult} are applied to the tile + */ + Success, + + /** + * @brief The operation is failed and __none__ of the fields in {@link TileLoadResult} + * or {@link TileChildrenResult} are applied to the tile + */ + Failed, + + /** + * @brief The operation requires the client to retry later due to some + * background work happenning and + * __none__ of the fields in {@link TileLoadResult} or {@link TileChildrenResult} are applied to the tile + */ + RetryLater +}; + +/** + * @brief Store the result of loading a tile content after + * invoking {@link TilesetContentLoader::loadTileContent} + */ +struct CESIUM3DTILESSELECTION_API TileLoadResult { + /** + * @brief The content type of the tile. + */ + TileContentKind contentKind; + + /** + * @brief The up axis of glTF content. + */ + CesiumGeometry::Axis glTFUpAxis; + + /** + * @brief A tile can potentially store a more fit bounding volume along with + * its content. If this field is set, the tile's bounding volume will be + * updated after the loading is finished. + */ + std::optional updatedBoundingVolume; + + /** + * @brief A tile can potentially store a more fit content bounding volume + * along with its content. If this field is set, the tile's content bounding + * volume will be updated after the loading is finished. + */ + std::optional updatedContentBoundingVolume; + + /** + * @brief Holds details of the {@link TileRenderContent} that are useful + * for raster overlays. + */ + std::optional + rasterOverlayDetails; + + /** + * @brief The asset accessor that was used to retrieve this tile, and that + * should be used to retrieve further resources referenced by the tile. + */ + std::shared_ptr pAssetAccessor; + + /** + * @brief The request that is created to download the tile content. + */ + std::shared_ptr pCompletedRequest; + + /** + * @brief A callback that is invoked in the main thread immediately when the + * loading is finished. This callback is useful when the content request has + * other fields like geometric error, + * children (in the case of {@link TileExternalContent}), etc, to override the existing fields. + */ + std::function tileInitializer; + + /** + * @brief The result of loading a tile. Note that if the state is Failed or + * RetryLater, __none__ of the fields above (including {@link TileLoadResult::tileInitializer}) will be + * applied to a tile when the loading is finished + */ + TileLoadResultState state; + + /** + * @brief The ellipsoid that this tile uses. + * + * This value is only guaranteed to be accurate when {@link TileLoadResult::state} is equal to {@link TileLoadResultState::Success}. + */ + CesiumGeospatial::Ellipsoid ellipsoid = + CesiumGeospatial::Ellipsoid::UNIT_SPHERE; + + /** + * @brief Create a result with Failed state + * + * @param pAssetAccessor The \ref CesiumAsync::IAssetAccessor "IAssetAccessor" + * used to load tiles. + * @param pCompletedRequest The failed request + */ + static TileLoadResult createFailedResult( + std::shared_ptr pAssetAccessor, + std::shared_ptr pCompletedRequest); + + /** + * @brief Create a result with RetryLater state + * + * @param pAssetAccessor The \ref CesiumAsync::IAssetAccessor "IAssetAccessor" + * used to load tiles. + * @param pCompletedRequest The failed request + */ + static TileLoadResult createRetryLaterResult( + std::shared_ptr pAssetAccessor, + std::shared_ptr pCompletedRequest); +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileOcclusionRendererProxy.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileOcclusionRendererProxy.h new file mode 100644 index 0000000..b3f47b5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileOcclusionRendererProxy.h @@ -0,0 +1,147 @@ +#pragma once + +#include "Library.h" +#include "Tile.h" + +#include +#include +#include + +namespace Cesium3DTilesSelection { + +/** + * @brief The occlusion state of a tile as reported by the renderer proxy. + */ +enum class CESIUM3DTILESSELECTION_API TileOcclusionState { + /** + * @brief The renderer does not yet know if the tile's bounding volume is + * occluded or not. + * + * This can be due to the typical occlusion delay caused by buffered + * rendering or otherwise be due to postponed occlusion queries. We can + * choose to wait for the occlusion information to become available before + * commiting to load the tile. This might prevent unneeded tile loads at the + * cost of a small delay. + */ + OcclusionUnavailable, + + /** + * @brief The tile's bounding volume is known by the renderer to be visible. + */ + NotOccluded, + + /** + * @brief The tile's bounding volume is known by the renderer to be occluded. + */ + Occluded +}; + +/** + * @brief An interface for client renderers to use to represent tile bounding + * volumes that should be occlusion tested. + */ +class CESIUM3DTILESSELECTION_API TileOcclusionRendererProxy { +public: + /** + * @brief Get the occlusion state for this tile. If this is + * OcclusionUnavailable, the traversal may decide to wait for the occlusion + * result to become available in future frames. + * + * Client implementation note: Do not return OcclusionUnavailable if the + * occlusion for this tile will _never_ become available, otherwise the tile + * may not refine while waiting for occlusion. In such a case return + * NotOccluded so the traversal can assume it is _known_ to be visible. + * + * @return The occlusion state of this tile. + */ + virtual TileOcclusionState getOcclusionState() const = 0; + +protected: + friend class TileOcclusionRendererProxyPool; + /** + * @brief Reset this proxy to target a new tile. If nullptr, this proxy is + * back in the pool and will not be used for further occlusion until reset + * is called again with an actual tile. + * + * @param pTile The tile that this proxy represents or nullptr if the proxy + * is back in the pool. + */ + virtual void reset(const Tile* pTile) = 0; + +private: + bool _usedLastFrame = false; + TileOcclusionRendererProxy* _pNext = nullptr; +}; + +/** + * @brief A pool of {@link TileOcclusionRendererProxy} objects. Allows quick + * remapping of tiles to occlusion renderer proxies so new proxies do not have + * to be created for each new tile requesting occlusion results. + */ +class CESIUM3DTILESSELECTION_API TileOcclusionRendererProxyPool { +public: + /** + * @brief Constructs a new instance. + * + * @param maximumPoolSize The maximum number of + * {@link TileOcclusionRendererProxy} instances that may exist in this pool. + */ + TileOcclusionRendererProxyPool(int32_t maximumPoolSize); + + /** + * @brief Destroys this pool. + */ + virtual ~TileOcclusionRendererProxyPool(); + + /** + * @brief Destroy the pool. + */ + void destroyPool(); + + /** + * @brief Get the {@link TileOcclusionRendererProxy} mapped to the tile. + * Attempts to create a new mapping if one does not exist already by + * assigning a proxy from the free list. + * + * @param tile The tile. + * @param currentFrame The current frame number. + * @return The occlusion proxy mapped to this tile, or nullptr if one can't + * be made. + */ + const TileOcclusionRendererProxy* + fetchOcclusionProxyForTile(const Tile& tile, int32_t currentFrame); + + /** + * @brief Prunes the occlusion proxy mappings and removes any mappings that + * were unused the last frame. Any mapping corresponding to a tile that was + * not visited will have been unused. Occlusion proxies from removed mappings + * will be returned to the free list. + */ + void pruneOcclusionProxyMappings(); + +protected: + /** + * @brief Create a {@link TileOcclusionRendererProxy}. + * + * @return A new occlusion proxy. + */ + virtual TileOcclusionRendererProxy* createProxy() = 0; + + /** + * @brief Destroy a {@link TileOcclusionRendererProxy} that is done being used. + * + * @param pProxy The proxy to be destroyed. + */ + virtual void destroyProxy(TileOcclusionRendererProxy* pProxy) = 0; + +private: + // Singly linked list representing the free proxies in the pool + TileOcclusionRendererProxy* _pFreeProxiesHead; + int32_t _currentSize; + int32_t _maxSize; + // The currently used proxies in the pool + std::unordered_map + _tileToOcclusionProxyMappings; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileRefine.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileRefine.h new file mode 100644 index 0000000..8d30966 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileRefine.h @@ -0,0 +1,23 @@ +#pragma once + +namespace Cesium3DTilesSelection { + +/** + * @brief Refinement strategies for a {@link Cesium3DTilesSelection::Tile}. + */ +enum class TileRefine { + + /** + * @brief The content of the child tiles will be added to the content of the + * parent tile. + */ + Add = 0, + + /** + * @brief The content of the child tiles will replace the content of the + * parent tile. + */ + Replace = 1 +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileSelectionState.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileSelectionState.h new file mode 100644 index 0000000..dc27976 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileSelectionState.h @@ -0,0 +1,168 @@ +#pragma once + +#include "Library.h" + +#include + +namespace Cesium3DTilesSelection { + +/** + * @brief A description of the state of a {@link Tile} during the rendering + * process + * + * Instances of this class combine a frame number and a + * {@link TileSelectionState::Result} that describes the actual state of the + * tile. + * Instances of this class are stored in a {@link Tile}, and are used to track + * the state of the tile during the rendering process. The {@link Tileset} + * updates this state while traversing the tile hierarchy, tracking whether a + * tile was rendered, culled, or refined in the last frame. + */ +class TileSelectionState final { +public: + /** + * @brief Enumeration of possible results of a {@link TileSelectionState} + */ + enum class CESIUM3DTILESSELECTION_API Result { + /** + * @brief There was no selection result. + * + * This may be the case when the tile wasn't visited last frame. + */ + None = 0, + + /** + * @brief This tile was deemed not visible and culled. + */ + Culled = 1, + + /** + * @brief The tile was selected for rendering. + */ + Rendered = 2, + + /** + * @brief This tile did not meet the required screen-space error and was + * refined. + */ + Refined = 3, + + /** + * @brief This tile was rendered but then removed from the render list + * + * This tile was originally rendered, but it got kicked out of the render + * list in favor of an ancestor because it is not yet renderable. + */ + RenderedAndKicked = 4, + + /** + * @brief This tile was refined but then removed from the render list + * + * This tile was originally refined, but its rendered descendants got kicked + * out of the render list in favor of an ancestor because it is not yet + * renderable. + */ + RefinedAndKicked = 5 + }; + + /** + * @brief Initializes a new instance with + * {@link TileSelectionState::Result::None} + */ + constexpr TileSelectionState() noexcept + : _frameNumber(0), _result(Result::None) {} + + /** + * @brief Initializes a new instance with a given + * {@link TileSelectionState::Result}. + * + * @param frameNumber The frame number in which the selection took place. + * @param result The result of the selection. + */ + constexpr TileSelectionState(int32_t frameNumber, Result result) noexcept + : _frameNumber(frameNumber), _result(result) {} + + /** + * @brief Gets the frame number in which selection took place. + */ + constexpr int32_t getFrameNumber() const noexcept { + return this->_frameNumber; + } + + /** + * @brief Gets the result of selection. + * + * The given frame number must match the frame number in which selection last + * took place. Otherwise, {@link TileSelectionState::Result::None} is + * returned. + * + * @param frameNumber The previous frame number. + * @return The {@link TileSelectionState::Result} + */ + constexpr Result getResult(int32_t frameNumber) const noexcept { + if (this->_frameNumber != frameNumber) { + return Result::None; + } + return this->_result; + } + + /** + * @brief Determines if this tile or its descendents were kicked from the + * render list. + * + * In other words, if its last selection result was + * {@link TileSelectionState::Result::RenderedAndKicked} or + * {@link TileSelectionState::Result::RefinedAndKicked}. + * + * @param frameNumber The previous frame number. + * @return `true` if the tile was kicked, and `false` otherwise + */ + constexpr bool wasKicked(int32_t frameNumber) const noexcept { + const Result result = this->getResult(frameNumber); + return result == Result::RenderedAndKicked || + result == Result::RefinedAndKicked; + } + + /** + * @brief Gets the original selection result prior to being kicked. + * + * If the tile wasn't kicked, the original value is returned. + * + * @param frameNumber The previous frame number. + * @return The {@link TileSelectionState::Result} prior to being kicked. + */ + constexpr Result getOriginalResult(int32_t frameNumber) const noexcept { + const Result result = this->getResult(frameNumber); + + switch (result) { + case Result::RefinedAndKicked: + return Result::Refined; + case Result::RenderedAndKicked: + return Result::Rendered; + default: + return result; + } + } + + /** + * @brief Marks this tile as "kicked". + */ + constexpr void kick() noexcept { + switch (this->_result) { + case Result::Rendered: + this->_result = Result::RenderedAndKicked; + break; + case Result::Refined: + this->_result = Result::RefinedAndKicked; + break; + default: + break; + } + } + +private: + int32_t _frameNumber; + Result _result; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/Tileset.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/Tileset.h new file mode 100644 index 0000000..1c062ea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/Tileset.h @@ -0,0 +1,572 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlayCollection.h" +#include "SampleHeightResult.h" +#include "Tile.h" +#include "TilesetContentLoader.h" +#include "TilesetExternals.h" +#include "TilesetLoadFailureDetails.h" +#include "TilesetOptions.h" +#include "ViewState.h" +#include "ViewUpdateResult.h" + +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace Cesium3DTilesSelection { + +class TilesetContentManager; +class TilesetMetadata; +class TilesetHeightQuery; +struct TilesetHeightRequest; +class TilesetSharedAssetSystem; + +/** + * @brief A 3D + * Tiles tileset, used for streaming massive heterogeneous 3D geospatial + * datasets. + */ +class CESIUM3DTILESSELECTION_API Tileset final { +public: + /** + * @brief Constructs a new instance with a given custom tileset loader. + * @param externals The external interfaces to use. + * @param pCustomLoader The custom loader used to load the tileset and tile + * content. + * @param pRootTile The root tile that is associated with the custom loader + * @param options Additional options for the tileset. + */ + Tileset( + const TilesetExternals& externals, + std::unique_ptr&& pCustomLoader, + std::unique_ptr&& pRootTile, + const TilesetOptions& options = TilesetOptions()); + + /** + * @brief Constructs a new instance with a given `tileset.json` URL. + * @param externals The external interfaces to use. + * @param url The URL of the `tileset.json`. + * @param options Additional options for the tileset. + */ + Tileset( + const TilesetExternals& externals, + const std::string& url, + const TilesetOptions& options = TilesetOptions()); + + /** + * @brief Constructs a new instance with the given asset ID on Cesium ion. + * @param externals The external interfaces to use. + * @param ionAssetID The ID of the Cesium ion asset to use. + * @param ionAccessToken The Cesium ion access token authorizing access to the + * asset. + * @param options Additional options for the tileset. + * @param ionAssetEndpointUrl The URL of the ion asset endpoint. Defaults + * to Cesium ion but a custom endpoint can be specified. + */ + Tileset( + const TilesetExternals& externals, + int64_t ionAssetID, + const std::string& ionAccessToken, + const TilesetOptions& options = TilesetOptions(), + const std::string& ionAssetEndpointUrl = "https://api.cesium.com/"); + + /** + * @brief Destroys this tileset. + * + * Destroying the tileset will immediately (before the destructor returns) + * unload as much tile content as possible. However, tiles that are currently + * in the process of being loaded cannot be unloaded immediately. These tiles + * will be unloaded asynchronously some time after this destructor returns. To + * be notified of completion of the async portion of the tileset destruction, + * subscribe to {@link getAsyncDestructionCompleteEvent}. + */ + ~Tileset() noexcept; + + /** + * @brief A future that resolves when this Tileset has been destroyed (i.e. + * its destructor has been called) and all async operations that it was + * executing have completed. + */ + CesiumAsync::SharedFuture& getAsyncDestructionCompleteEvent(); + + /** + * @brief A future that resolves when the details of the root tile of this + * tileset are available. The root tile's content (e.g., 3D model), however, + * will not necessarily be loaded yet. + */ + CesiumAsync::SharedFuture& getRootTileAvailableEvent(); + + /** + * @brief Get tileset credits. + */ + const std::vector& getTilesetCredits() const noexcept; + + /** + * @brief Sets whether or not the tileset's credits should be shown on screen. + * @param showCreditsOnScreen Whether the credits should be shown on screen. + */ + void setShowCreditsOnScreen(bool showCreditsOnScreen) noexcept; + + /** + * @brief Gets the {@link TilesetExternals} that summarize the external + * interfaces used by this tileset. + */ + TilesetExternals& getExternals() noexcept { return this->_externals; } + + /** + * @brief Gets the {@link TilesetExternals} that summarize the external + * interfaces used by this tileset. + */ + const TilesetExternals& getExternals() const noexcept { + return this->_externals; + } + + /** + * @brief Returns the {@link CesiumAsync::AsyncSystem} that is used for + * dispatching asynchronous tasks. + */ + CesiumAsync::AsyncSystem& getAsyncSystem() noexcept { + return this->_asyncSystem; + } + + /** @copydoc Tileset::getAsyncSystem() */ + const CesiumAsync::AsyncSystem& getAsyncSystem() const noexcept { + return this->_asyncSystem; + } + + /** @copydoc Tileset::getOptions() */ + const TilesetOptions& getOptions() const noexcept { return this->_options; } + + /** + * @brief Gets the {@link TilesetOptions} of this tileset. + */ + TilesetOptions& getOptions() noexcept { return this->_options; } + + /** + * @brief Gets the {@link CesiumGeospatial::Ellipsoid} used by this tileset. + */ + const CesiumGeospatial::Ellipsoid& getEllipsoid() const { + return this->_options.ellipsoid; + } + + /** @copydoc Tileset::getEllipsoid */ + CesiumGeospatial::Ellipsoid& getEllipsoid() noexcept { + return this->_options.ellipsoid; + } + + /** + * @brief Gets the root tile of this tileset. + * + * This may be `nullptr` if there is currently no root tile. + */ + Tile* getRootTile() noexcept; + + /** @copydoc Tileset::getRootTile() */ + const Tile* getRootTile() const noexcept; + + /** + * @brief Returns the {@link RasterOverlayCollection} of this tileset. + */ + RasterOverlayCollection& getOverlays() noexcept; + + /** @copydoc Tileset::getOverlays() */ + const RasterOverlayCollection& getOverlays() const noexcept; + + /** + * @brief Returns the {@link TilesetSharedAssetSystem} of this tileset. + */ + TilesetSharedAssetSystem& getSharedAssetSystem() noexcept; + + /** @copydoc Tileset::getSharedAssetSystem() */ + const TilesetSharedAssetSystem& getSharedAssetSystem() const noexcept; + + /** + * @brief Updates this view but waits for all tiles that meet sse to finish + * loading and ready to be rendered before returning the function. This method + * is significantly slower than {@link Tileset::updateView} and should only be + * used for capturing movie or non-realtime situation. + * @param frustums The {@link ViewState}s that the view should be updated for + * @returns The set of tiles to render in the updated view. This value is only + * valid until the next call to `updateView` or until the tileset is + * destroyed, whichever comes first. + */ + const ViewUpdateResult& + updateViewOffline(const std::vector& frustums); + + /** + * @brief Updates this view, returning the set of tiles to render in this + * view. + * @param frustums The {@link ViewState}s that the view should be updated for + * @param deltaTime The amount of time that has passed since the last call to + * updateView, in seconds. + * @returns The set of tiles to render in the updated view. This value is only + * valid until the next call to `updateView` or until the tileset is + * destroyed, whichever comes first. + */ + const ViewUpdateResult& + updateView(const std::vector& frustums, float deltaTime = 0.0f); + + /** + * @brief Gets the total number of tiles that are currently loaded. + */ + int32_t getNumberOfTilesLoaded() const; + + /** + * @brief Estimate the percentage of the tiles for the current view that have + * been loaded. + */ + float computeLoadProgress() noexcept; + + /** + * @brief Invokes a function for each tile that is currently loaded. + * + * @param callback The function to invoke. + */ + void forEachLoadedTile(const std::function& callback); + + /** + * @brief Invokes a function for each tile that is currently loaded. + * + * @param callback The function to invoke. + */ + void forEachLoadedTile( + const std::function& callback) const; + + /** + * @brief Gets the total number of bytes of tile and raster overlay data that + * are currently loaded. + */ + int64_t getTotalDataBytes() const noexcept; + + /** + * @brief Gets the {@link TilesetMetadata} associated with the main or + * external tileset.json that contains a given tile. If the metadata is not + * yet loaded, this method returns nullptr. + * + * If this tileset's root tile is not yet available, this method returns + * nullptr. + * + * If the tileset has a {@link TilesetMetadata::schemaUri}, it will not + * necessarily have been loaded yet. + * + * If the provided tile is not the root tile of a tileset.json, this method + * walks up the {@link Tile::getParent} chain until it finds the closest + * root and then returns the metadata associated with the corresponding + * tileset.json. + * + * Consider calling {@link loadMetadata} instead, which will return a future + * that only resolves after the root tile is loaded and the `schemaUri`, if + * any, has been resolved. + * + * @param pTile The tile. If this parameter is nullptr, the metadata for the + * main tileset.json is returned. + * @return The found metadata, or nullptr if the root tile is not yet loaded. + */ + const TilesetMetadata* getMetadata(const Tile* pTile = nullptr) const; + + /** + * @brief Asynchronously loads the metadata associated with the main + * tileset.json. + * + * Before the returned future resolves, the root tile of this tileset will be + * loaded and the {@link TilesetMetadata::schemaUri} will be loaded if one + * has been specified. + * + * If the tileset or `schemaUri` fail to load, the returned future will + * reject. + * + * @return A shared future that resolves to the loaded metadata. Once this + * future resolves, {@link getMetadata} can be used to synchronously obtain + * the same metadata instance. + */ + CesiumAsync::Future loadMetadata(); + + /** + * @brief Initiates an asynchronous query for the height of this tileset at a + * list of cartographic positions (longitude and latitude). The most detailed + * available tiles are used to determine each height. + * + * The height of the input positions is ignored. The output height is + * expressed in meters above the ellipsoid (usually WGS84), which should not + * be confused with a height above mean sea level. + * + * Note that {@link Tileset::updateView} must be called periodically, or else + * the returned `Future` will never resolve. If you are not using this tileset + * for visualization, you can call `updateView` with an empty list of + * frustums. + * + * @param positions The positions for which to sample heights. + * @return A future that asynchronously resolves to the result of the height + * query. + */ + CesiumAsync::Future sampleHeightMostDetailed( + const std::vector& positions); + +private: + /** + * @brief The result of traversing one branch of the tile hierarchy. + * + * Instances of this structure are created by the `_visit...` functions, + * and summarize the information that was gathered during the traversal + * of the respective branch, so that this information can be used by + * the parent to decide on the further traversal process. + */ + struct TraversalDetails { + /** + * @brief Whether all selected tiles in this tile's subtree are renderable. + * + * This is `true` if all selected (i.e. not culled or refined) tiles in this + * tile's subtree are renderable. If the subtree is renderable, we'll render + * it; no drama. + */ + bool allAreRenderable = true; + + /** + * @brief Whether any tile in this tile's subtree was rendered in the last + * frame. + * + * This is `true` if any tiles in this tile's subtree were rendered last + * frame. If any were, we must render the subtree rather than this tile, + * because rendering this tile would cause detail to vanish that was visible + * last frame, and that's no good. + */ + bool anyWereRenderedLastFrame = false; + + /** + * @brief The number of selected tiles in this tile's subtree that are not + * yet renderable. + * + * Counts the number of selected tiles in this tile's subtree that are + * not yet ready to be rendered because they need more loading. Note that + * this value will _not_ necessarily be zero when + * `allAreRenderable` is `true`, for subtle reasons. + * When `allAreRenderable` and `anyWereRenderedLastFrame` are both `false`, + * we will render this tile instead of any tiles in its subtree and the + * `allAreRenderable` value for this tile will reflect only whether _this_ + * tile is renderable. The `notYetRenderableCount` value, however, will + * still reflect the total number of tiles that we are waiting on, including + * the ones that we're not rendering. `notYetRenderableCount` is only reset + * when a subtree is removed from the render queue because the + * `notYetRenderableCount` exceeds the + * {@link TilesetOptions::loadingDescendantLimit}. + */ + uint32_t notYetRenderableCount = 0; + }; + + /** + * @brief Input information that is constant throughout the traversal. + * + * An instance of this structure is created upon entry of the top-level + * `_visitTile` function, for the traversal for a certain frame, and + * passed on through the traversal. + */ + struct FrameState { + const std::vector& frustums; + std::vector fogDensities; + int32_t lastFrameNumber; + int32_t currentFrameNumber; + }; + + TraversalDetails _renderLeaf( + const FrameState& frameState, + Tile& tile, + double tilePriority, + ViewUpdateResult& result); + TraversalDetails _renderInnerTile( + const FrameState& frameState, + Tile& tile, + ViewUpdateResult& result); + bool _kickDescendantsAndRenderTile( + const FrameState& frameState, + Tile& tile, + ViewUpdateResult& result, + TraversalDetails& traversalDetails, + size_t firstRenderedDescendantIndex, + size_t workerThreadLoadQueueIndex, + size_t mainThreadLoadQueueIndex, + bool queuedForLoad, + double tilePriority); + TileOcclusionState + _checkOcclusion(const Tile& tile, const FrameState& frameState); + + TraversalDetails _visitTile( + const FrameState& frameState, + uint32_t depth, + bool meetsSse, + bool ancestorMeetsSse, + Tile& tile, + double tilePriority, + ViewUpdateResult& result); + + struct CullResult { + // whether we should visit this tile + bool shouldVisit = true; + // whether this tile was culled (Note: we might still want to visit it) + bool culled = false; + }; + + // TODO: abstract these into a composable culling interface. + void _frustumCull( + const Tile& tile, + const FrameState& frameState, + bool cullWithChildrenBounds, + CullResult& cullResult); + void _fogCull( + const FrameState& frameState, + const std::vector& distances, + CullResult& cullResult); + bool _meetsSse( + const std::vector& frustums, + const Tile& tile, + const std::vector& distances, + bool culled) const noexcept; + + TraversalDetails _visitTileIfNeeded( + const FrameState& frameState, + uint32_t depth, + bool ancestorMeetsSse, + Tile& tile, + ViewUpdateResult& result); + TraversalDetails _visitVisibleChildrenNearToFar( + const FrameState& frameState, + uint32_t depth, + bool ancestorMeetsSse, + Tile& tile, + ViewUpdateResult& result); + + /** + * @brief When called on an additive-refined tile, queues it for load and adds + * it to the render list. + * + * For replacement-refined tiles, this method does nothing and returns false. + * + * @param tile The tile to potentially load and render. + * @param result The current view update result. + * @param tilePriority The load priority of this tile. + * priority. + * @param queuedForLoad True if this tile has already been queued for loading. + * @return true The additive-refined tile was queued for load and added to the + * render list. + * @return false The non-additive-refined tile was ignored. + */ + bool _loadAndRenderAdditiveRefinedTile( + Tile& tile, + ViewUpdateResult& result, + double tilePriority, + bool queuedForLoad); + + void _processWorkerThreadLoadQueue(); + void _processMainThreadLoadQueue(); + + void _unloadCachedTiles(double timeBudget) noexcept; + void _markTileVisited(Tile& tile) noexcept; + + void _updateLodTransitions( + const FrameState& frameState, + float deltaTime, + ViewUpdateResult& result) const noexcept; + + TilesetExternals _externals; + CesiumAsync::AsyncSystem _asyncSystem; + + TilesetOptions _options; + + int32_t _previousFrameNumber; + ViewUpdateResult _updateResult; + + enum class TileLoadPriorityGroup { + /** + * @brief Low priority tiles that aren't needed right now, but + * are being preloaded for the future. + */ + Preload = 0, + + /** + * @brief Medium priority tiles that are needed to render the current view + * the appropriate level-of-detail. + */ + Normal = 1, + + /** + * @brief High priority tiles that are causing extra detail to be rendered + * in the scene, potentially creating a performance problem and aliasing + * artifacts. + */ + Urgent = 2 + }; + + struct TileLoadTask { + /** + * @brief The tile to be loaded. + */ + Tile* pTile; + + /** + * @brief The priority group (low / medium / high) in which to load this + * tile. + * + * All tiles in a higher priority group are given a chance to load before + * any tiles in a lower priority group. + */ + TileLoadPriorityGroup group; + + /** + * @brief The priority of this tile within its priority group. + * + * Tiles with a _lower_ value for this property load sooner! + */ + double priority; + + bool operator<(const TileLoadTask& rhs) const noexcept { + if (this->group == rhs.group) + return this->priority < rhs.priority; + else + return this->group > rhs.group; + } + }; + + std::vector _mainThreadLoadQueue; + std::vector _workerThreadLoadQueue; + std::vector _heightQueryLoadQueue; + + Tile::LoadedLinkedList _loadedTiles; + + // Holds computed distances, to avoid allocating them on the heap during tile + // selection. + std::vector _distances; + + // Holds the occlusion proxies of the children of a tile. Store them in this + // scratch variable so that it can allocate only when growing bigger. + std::vector _childOcclusionProxies; + + CesiumUtility::IntrusivePointer + _pTilesetContentManager; + + std::list _heightRequests; + + void addTileToLoadQueue( + Tile& tile, + TileLoadPriorityGroup priorityGroup, + double priority); + + static TraversalDetails createTraversalDetailsForSingleTile( + const FrameState& frameState, + const Tile& tile, + const TileSelectionState& lastFrameSelectionState); + + Tileset(const Tileset& rhs) = delete; + Tileset& operator=(const Tileset& rhs) = delete; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetContentLoader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetContentLoader.h new file mode 100644 index 0000000..a852f14 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetContentLoader.h @@ -0,0 +1,172 @@ +#pragma once + +#include "BoundingVolume.h" +#include "Library.h" +#include "TileContent.h" +#include "TileLoadResult.h" +#include "TilesetOptions.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace Cesium3DTilesSelection { +class Tile; +class ITilesetHeightSampler; + +/** + * @brief Store the parameters that are needed to load a tile + */ +struct CESIUM3DTILESSELECTION_API TileLoadInput { + /** + * @brief Creates a new instance + * + * @param tile The {@link Tile} that the content belongs to. + * @param contentOptions The content options the {@link TilesetContentLoader} will use to process the content of the tile. + * @param asyncSystem The async system to use for tile content loading. + * @param pAssetAccessor The asset accessor to make further requests with. + * @param pLogger The logger that will be used + * @param requestHeaders The request headers that will be attached to the + * request. + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + */ + TileLoadInput( + const Tile& tile, + const TilesetContentOptions& contentOptions, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pLogger, + const std::vector& requestHeaders, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief The tile that the {@link TilesetContentLoader} will request the server for the content. + */ + const Tile& tile; + + /** + * @brief The content options the {@link TilesetContentLoader} will use to process the content of the tile. + */ + const TilesetContentOptions& contentOptions; + + /** + * @brief The async system to run the loading in worker thread or main thread. + */ + const CesiumAsync::AsyncSystem& asyncSystem; + + /** + * @brief The asset accessor to make requests for the tile content over the + * wire. + */ + const std::shared_ptr& pAssetAccessor; + + /** + * @brief The logger that receives details of loading errors and warnings. + */ + const std::shared_ptr& pLogger; + + /** + * @brief The request headers that will be attached to the request. + */ + const std::vector& requestHeaders; + + /** + * @brief The ellipsoid that this tileset uses. + */ + const CesiumGeospatial::Ellipsoid& ellipsoid; +}; + +/** + * @brief Store the result of creating tile's children after + * invoking {@link TilesetContentLoader::createTileChildren} + */ +struct CESIUM3DTILESSELECTION_API TileChildrenResult { + /** + * @brief The children of this tile. + */ + std::vector children; + + /** + * @brief The result of creating children for + * this tile. Note that: when receiving RetryLater status, client + * needs to load this tile's content first or its parent's content. The reason + * is that some tileset formats store the tile's children along with its + * content or store a whole subtree for every n-th level tile (e.g Quantized + * Mesh format). So unless the tile's content or the root tile of the subtree + * the tile is in is loaded, the loader won't know how to create the tile's + * children. + */ + TileLoadResultState state; +}; + +/** + * @brief The loader interface to load the tile content + */ +class CESIUM3DTILESSELECTION_API TilesetContentLoader { +public: + /** + * @brief Default virtual destructor + */ + virtual ~TilesetContentLoader() = default; + + /** + * @brief Load the tile content. + * + * @param input The {@link TileLoadInput} that has the tile info and loading systems to load this tile's content + * @return The future of {@link TileLoadResult} that stores the tile's content + */ + virtual CesiumAsync::Future + loadTileContent(const TileLoadInput& input) = 0; + + /** + * @brief Create the tile's children. + * + * Note that: when receiving RetryLater status, client + * needs to load this tile's content first or its parent's content. The reason + * is that some tileset formats store the tile's children along with its + * content or store a whole subtree for every n-th level tile (e.g Quantized + * Mesh format). So unless the tile's content or the root tile of the subtree + * the tile is in is loaded, the loader won't know how to create the tile's + * children. + * + * @param tile The tile to create children for. + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + * @return The {@link TileChildrenResult} that stores the tile's children + */ + virtual TileChildrenResult createTileChildren( + const Tile& tile, + const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) = 0; + + /** + * @brief Gets an interface that can be used to efficiently query heights from + * this tileset. + * + * Some loaders may be able to query heights very efficiently by using a web + * service or by using an analytical model, e.g., when the "terrain" is a + * simple ellipsoid. + * + * For loaders that have no particular way to query heights, this method will + * return `nullptr`, signaling that heights should be computed by downloading + * and sampling individual tiles. + * + * @return The interface that can be used to efficiently query heights from + * this loader, or `nullptr` if this loader has no particular way to do that. + * The returned instance must have a lifetime that is at least as long as the + * loader itself. + */ + virtual ITilesetHeightSampler* getHeightSampler() { return nullptr; } +}; +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetExternals.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetExternals.h new file mode 100644 index 0000000..a9f8a4a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetExternals.h @@ -0,0 +1,82 @@ +#pragma once + +#include "Library.h" +#include "TileOcclusionRendererProxy.h" +#include "TilesetSharedAssetSystem.h" +#include "spdlog-cesium.h" + +#include + +#include + +namespace CesiumAsync { +class IAssetAccessor; +class ITaskProcessor; +} // namespace CesiumAsync + +namespace CesiumUtility { +class CreditSystem; +} + +namespace Cesium3DTilesSelection { +class IPrepareRendererResources; + +/** + * @brief External interfaces used by a {@link Tileset}. + * + * Not supposed to be used by clients. + */ +class CESIUM3DTILESSELECTION_API TilesetExternals final { +public: + /** + * @brief An external {@link CesiumAsync::IAssetAccessor}. + */ + std::shared_ptr pAssetAccessor; + + /** + * @brief An external {@link IPrepareRendererResources}. + */ + std::shared_ptr pPrepareRendererResources; + + /** + * @brief The async system to use to do work in threads. + * + * The tileset will automatically call + * {@link CesiumAsync::AsyncSystem::dispatchMainThreadTasks} from + * {@link Tileset::updateView}. + */ + CesiumAsync::AsyncSystem asyncSystem; + + /** + * @brief An external {@link CesiumUtility::CreditSystem} that can be used to manage credit + * strings and track which which credits to show and remove from the screen + * each frame. + */ + std::shared_ptr pCreditSystem; + + /** + * @brief A spdlog logger that will receive log messages. + * + * If not specified, defaults to `spdlog::default_logger()`. + */ + std::shared_ptr pLogger = spdlog::default_logger(); + + /** + * @brief A pool of renderer proxies to determine the occlusion state of + * tile bounding volumes. + * + * If not specified, the traversal will not attempt to leverage occlusion + * information. + */ + std::shared_ptr pTileOcclusionProxyPool = + nullptr; + + /** + * @brief The shared asset system used to facilitate sharing of common assets, + * such as images, between and within tilesets. + */ + CesiumUtility::IntrusivePointer pSharedAssetSystem = + TilesetSharedAssetSystem::getDefault(); +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetLoadFailureDetails.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetLoadFailureDetails.h new file mode 100644 index 0000000..d315955 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetLoadFailureDetails.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include + +namespace CesiumAsync { +class IAssetRequest; +} + +namespace Cesium3DTilesSelection { + +class Tileset; + +/** + * @brief The type of load that failed in `TilesetLoadFailureDetails`. + */ +enum class TilesetLoadType { + /** + * @brief An unknown load error. + */ + Unknown, + + /** + * @brief A Cesium ion asset endpoint. + */ + CesiumIon, + + /** + * @brief The root tileset.json. + */ + TilesetJson +}; + +/** + * Information on a tileset that failed to load. + */ +class TilesetLoadFailureDetails { +public: + /** + * @brief The tileset that encountered the load failure. + */ + const Tileset* pTileset = nullptr; + + /** + * @brief The type of request that failed to load. + */ + TilesetLoadType type = TilesetLoadType::Unknown; + + /** + * The status code of the HTTP response. + */ + uint16_t statusCode{200}; + + /** + * @brief A human-readable explanation of what failed. + */ + std::string message = ""; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetMetadata.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetMetadata.h new file mode 100644 index 0000000..db5b811 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetMetadata.h @@ -0,0 +1,77 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include + +#include +#include +#include + +namespace CesiumAsync { +class AsyncSystem; +class IAssetAccessor; +} // namespace CesiumAsync + +namespace Cesium3DTilesSelection { + +/** + * @brief Holds the metadata associated with a {@link Tileset} or an external + * tileset. + */ +class CESIUM3DTILESSELECTION_API TilesetMetadata { +public: + ~TilesetMetadata() noexcept; + + /** + * @brief An object defining the structure of metadata classes and enums. When + * this is defined, then `schemaUri` shall be undefined. + */ + std::optional schema; + + /** + * @brief The URI (or IRI) of the external schema file. When this is defined, + * then `schema` shall be undefined. + */ + std::optional schemaUri; + + /** + * @brief An array of groups that tile content may belong to. Each element of + * this array is a metadata entity that describes the group. The tile content + * `group` property is an index into this array. + */ + std::vector groups; + + /** + * @brief A metadata entity that is associated with this tileset. + */ + std::optional metadata; + + /** + * @brief Asynchronously loads the {@link schema} from the {@link schemaUri}. + * If the {@link schemaUri} does not contain a value, this method does + * nothing and returns an already-resolved future. + * + * Calling this method multiple times will return the same shared future each + * time, unless the {@link schemaUri} is changed. In that case, when this + * method is called, the previous load is canceled and the new one begins. + * + * @param asyncSystem The async system used to do work in threads. + * @param pAssetAccessor The asset accessor used to request the schema from + * the schemaUri. + * @return A future that resolves when the schema has been loaded from the + * schemaUri. + */ + CesiumAsync::SharedFuture& loadSchemaUri( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor); + +private: + std::optional> _loadingFuture; + std::optional _loadingSchemaUri; + std::shared_ptr _pLoadingCanceled; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetOptions.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetOptions.h new file mode 100644 index 0000000..bb09588 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetOptions.h @@ -0,0 +1,333 @@ +#pragma once + +#include "Library.h" + +#include +#include + +#include +#include +#include +#include +#include + +namespace Cesium3DTilesSelection { + +class ITileExcluder; +class TilesetLoadFailureDetails; + +/** + * @brief Options for configuring the parsing of a {@link Tileset}'s content + * and construction of Gltf models. + */ +struct CESIUM3DTILESSELECTION_API TilesetContentOptions { + /** + * @brief Whether to include a water mask within the Gltf extras. + * + * Currently only applicable for quantized-mesh tilesets that support the + * water mask extension. + */ + bool enableWaterMask = false; + + /** + * @brief Whether to generate smooth normals when normals are missing in the + * original Gltf. + * + * According to the Gltf spec: "When normals are not specified, client + * implementations should calculate flat normals." However, calculating flat + * normals requires duplicating vertices. This option allows the gltfs to be + * sent with explicit smooth normals when the original gltf was missing + * normals. + */ + bool generateMissingNormalsSmooth = false; + + /** + * @brief For each possible input transmission format, this struct names + * the ideal target gpu-compressed pixel format to transcode to. + */ + CesiumGltf::Ktx2TranscodeTargets ktx2TranscodeTargets; + + /** + * @brief Whether or not to transform texture coordinates during load when + * textures have the `KHR_texture_transform` extension. Set this to false if + * texture coordinates will be transformed another way, such as in a vertex + * shader. + */ + bool applyTextureTransform = true; +}; + +/** + * @brief Defines the fog density at a certain height. + * + * @see TilesetOptions::fogDensityTable + */ +struct CESIUM3DTILESSELECTION_API FogDensityAtHeight { + + /** @brief The height. */ + double cameraHeight; + + /** @brief The fog density. */ + double fogDensity; +}; + +/** + * @brief Additional options for configuring a {@link Tileset}. + */ +struct CESIUM3DTILESSELECTION_API TilesetOptions { + /** + * @brief A credit text for this tileset, if needed. + */ + std::optional credit; + + /** + * @brief Whether or not to display tileset's credits on the screen. + */ + bool showCreditsOnScreen = false; + + /** + * @brief The maximum number of pixels of error when rendering this tileset. + * This is used to select an appropriate level-of-detail. + * + * When a tileset uses the older layer.json / quantized-mesh format rather + * than 3D Tiles, this value is effectively divided by 8.0. So the default + * value of 16.0 corresponds to the standard value for quantized-mesh terrain + * of 2.0. + */ + double maximumScreenSpaceError = 16.0; + + /** + * @brief The maximum number of tiles that may simultaneously be in the + * process of loading. + */ + uint32_t maximumSimultaneousTileLoads = 20; + + /** + * @brief The maximum number of subtrees that may simultaneously be in the + * process of loading. + */ + uint32_t maximumSimultaneousSubtreeLoads = 20; + + /** + * @brief Indicates whether the ancestors of rendered tiles should be + * preloaded. Setting this to true optimizes the zoom-out experience and + * provides more detail in newly-exposed areas when panning. The down side is + * that it requires loading more tiles. + */ + bool preloadAncestors = true; + + /** + * @brief Indicates whether the siblings of rendered tiles should be + * preloaded. Setting this to true causes tiles with the same parent as a + * rendered tile to be loaded, even if they are culled. Setting this to true + * may provide a better panning experience at the cost of loading more tiles. + */ + bool preloadSiblings = true; + + /** + * @brief The number of loading descendant tiles that is considered "too + * many". If a tile has too many loading descendants, that tile will be loaded + * and rendered before any of its descendants are loaded and rendered. This + * means more feedback for the user that something is happening at the cost of + * a longer overall load time. Setting this to 0 will cause each tile level to + * be loaded successively, significantly increasing load time. Setting it to a + * large number (e.g. 1000) will minimize the number of tiles that are loaded + * but tend to make detail appear all at once after a long wait. + */ + uint32_t loadingDescendantLimit = 20; + + /** + * @brief Never render a tileset with missing tiles. + * + * When true, the tileset will guarantee that the tileset will never be + * rendered with holes in place of tiles that are not yet loaded. It does this + * by refusing to refine a parent tile until all of its child tiles are ready + * to render. Thus, when the camera moves, we will always have something - + * even if it's low resolution - to render any part of the tileset that + * becomes visible. When false, overall loading will be faster, but + * newly-visible parts of the tileset may initially be blank. + */ + bool forbidHoles = false; + + /** + * @brief Enable culling of tiles against the frustum. + */ + bool enableFrustumCulling = true; + + /** + * @brief Enable culling of occluded tiles, as reported by the renderer. + */ + bool enableOcclusionCulling = true; + + /** + * @brief Wait to refine until the occlusion state of a tile is known. + * + * Only applicable when enableOcclusionInfo is true. Enabling this option may + * cause a small delay between when a tile is needed according to the SSE and + * when the tile load is kicked off. On the other hand, this delay could + * allow the occlusion system to avoid loading a tile entirely if it is + * found to be unnecessary a few frames later. + */ + bool delayRefinementForOcclusion = true; + + /** + * @brief Enable culling of tiles that cannot be seen through atmospheric fog. + */ + bool enableFogCulling = true; + + /** + * @brief Whether culled tiles should be refined until they meet + * culledScreenSpaceError. + * + * When true, any culled tile from a disabled culling stage will be refined + * until it meets the specified culledScreenSpaceError. Otherwise, its + * screen-space error check will be disabled altogether and it will not bother + * to refine any futher. + */ + bool enforceCulledScreenSpaceError = true; + + /** + * @brief The screen-space error to refine until for culled tiles from + * disabled culling stages. + * + * When enforceCulledScreenSpaceError is true, culled tiles from disabled + * culling stages will be refined until they meet this screen-space error + * value. + */ + double culledScreenSpaceError = 64.0; + + /** + * @brief The maximum number of bytes that may be cached. + * + * Note that this value, even if 0, will never + * cause tiles that are needed for rendering to be unloaded. However, if the + * total number of loaded bytes is greater than this value, tiles will be + * unloaded until the total is under this number or until only required tiles + * remain, whichever comes first. + */ + int64_t maximumCachedBytes = 512 * 1024 * 1024; + + /** + * @brief A table that maps the camera height above the ellipsoid to a fog + * density. Tiles that are in full fog are culled. The density of the fog + * increases as this number approaches 1.0 and becomes less dense as it + * approaches zero. The more dense the fog is, the more aggressively the tiles + * are culled. For example, if the camera is a height of 1000.0m above the + * ellipsoid, increasing the value to 3.0e-3 will cause many tiles close to + * the viewer be culled. Decreasing the value will push the fog further from + * the viewer, but decrease performance as more of the tiles are rendered. + * Tiles are culled when `1.0 - glm::exp(-(distance * distance * fogDensity * + * fogDensity))` is >= 1.0. + */ + std::vector fogDensityTable = { + {359.393, 2.0e-5}, {800.749, 2.0e-4}, {1275.6501, 1.0e-4}, + {2151.1192, 7.0e-5}, {3141.7763, 5.0e-5}, {4777.5198, 4.0e-5}, + {6281.2493, 3.0e-5}, {12364.307, 1.9e-5}, {15900.765, 1.0e-5}, + {49889.0549, 8.5e-6}, {78026.8259, 6.2e-6}, {99260.7344, 5.8e-6}, + {120036.3873, 5.3e-6}, {151011.0158, 5.2e-6}, {156091.1953, 5.1e-6}, + {203849.3112, 4.2e-6}, {274866.9803, 4.0e-6}, {319916.3149, 3.4e-6}, + {493552.0528, 2.6e-6}, {628733.5874, 2.2e-6}, {1000000.0, 0.0}}; + + /** + * @brief Whether to render tiles directly under the camera, even if they're + * not in the view frustum. + * + * This is useful for detecting the camera's collision with terrain and other + * models. NOTE: This option currently only works with tiles that use a + * `region` as their bounding volume. It is ignored for other bounding volume + * types. + */ + bool renderTilesUnderCamera = true; + + /** + * @brief A list of interfaces that are given an opportunity to exclude tiles + * from loading and rendering. If any of the excluders indicate that a tile + * should not be loaded, it will not be loaded. + */ + std::vector> excluders; + + /** + * @brief A callback function that is invoked when a tileset resource fails to + * load. + * + * Tileset resources include a Cesium ion asset endpoint, a tileset's root + * tileset.json or layer.json, an individual tile's content, or an implicit + * tiling subtree. + */ + std::function loadErrorCallback; + + /** + * @brief Whether to keep tiles loaded during a transition period when + * switching to a different LOD tile. + * + * For each tile, {@link TileRenderContent::getLodTransitionFadePercentage} will + * indicate to the client how faded to render the tile throughout the + * transition. Tile fades can be used to mask LOD transitions and make them + * appear less abrupt and jarring. + */ + bool enableLodTransitionPeriod = false; + + /** + * @brief How long it should take to transition between tiles of different + * LODs, in seconds. + * + * When a tile refines or unrefines to a higher or lower LOD tile, a fade + * can optionally be applied to smooth the transition. This value determines + * how many seconds the whole transition should take. Note that the old tile + * doesn't start fading out until the new tile fully fades in. + */ + float lodTransitionLength = 1.0f; + + /** + * @brief Whether to kick descendants while a tile is still fading in. + * + * This does not delay loading of descendants, but it keeps them off the + * render list while the tile is fading in. If this is false, the tile + * currently fading in will pop in to full opacity if descendants are + * rendered (this counteracts the benefits of LOD transition blending). + * + */ + bool kickDescendantsWhileFadingIn = true; + + /** + * @brief A soft limit on how long (in milliseconds) to spend on the + * main-thread part of tile loading each frame (each call to + * Tileset::updateView). A value of 0.0 indicates that all pending + * main-thread loads should be completed each tick. + * + * Setting this to too low of a value will impede overall tile load progress, + * creating a discernable load latency. + */ + double mainThreadLoadingTimeLimit = 0.0; + + /** + * @brief A soft limit on how long (in milliseconds) to spend unloading + * cached tiles each frame (each call to Tileset::updateView). A value of 0.0 + * indicates that the tile cache should not throttle unloading tiles. + */ + double tileCacheUnloadTimeLimit = 0.0; + + /** + * @brief Options for configuring the parsing of a {@link Tileset}'s content + * and construction of Gltf models. + */ + TilesetContentOptions contentOptions; + + /** + * @brief Arbitrary data that will be passed to {@link IPrepareRendererResources::prepareInLoadThread}. + * + * This object is copied and given to tile preparation threads, + * so it must be inexpensive to copy. + */ + std::any rendererOptions; + + /** + * @brief The ellipsoid to use for this tileset. + * This value shouldn't be changed after the tileset is constructed. If you + * need to change a tileset's ellipsoid, please recreate the tileset. + * + * If no ellipsoid is set, Ellipsoid::WGS84 will be used by default. + */ + CesiumGeospatial::Ellipsoid ellipsoid = CesiumGeospatial::Ellipsoid::WGS84; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetSharedAssetSystem.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetSharedAssetSystem.h new file mode 100644 index 0000000..a3472fd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetSharedAssetSystem.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace Cesium3DTilesSelection { + +/** + * @brief Contains assets that are potentially shared across multiple Tilesets. + */ +class TilesetSharedAssetSystem + : public CesiumGltfReader::GltfSharedAssetSystem { +public: + /** + * @brief Obtains an `IntrusivePointer` to the `TilesetSharedAssetSystem` + * singleton. + */ + static CesiumUtility::IntrusivePointer getDefault(); + + virtual ~TilesetSharedAssetSystem() = default; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ViewState.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ViewState.h new file mode 100644 index 0000000..240f1e1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ViewState.h @@ -0,0 +1,182 @@ +#pragma once + +#include "BoundingVolume.h" +#include "Library.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace Cesium3DTilesSelection { + +/** + * @brief The state of the view that is used during the traversal of a tileset. + * + * An instance of a view state can be created with the {@link create} function. + */ +class CESIUM3DTILESSELECTION_API ViewState final { + + // TODO: Add support for orthographic and off-center perspective frustums +public: + /** + * @brief Creates a new instance of a view state. + * + * @param position The position of the eye point of the camera. + * @param direction The view direction vector of the camera. + * @param up The up vector of the camera. + * @param viewportSize The size of the viewport, in pixels. + * @param horizontalFieldOfView The horizontal field-of-view (opening) + * angle of the camera, in radians. + * @param verticalFieldOfView The vertical field-of-view (opening) + * angle of the camera, in radians. + * @param ellipsoid The ellipsoid that will be used to compute the + * {@link ViewState#getPositionCartographic cartographic position} + * from the cartesian position. + * Default value: {@link CesiumGeospatial::Ellipsoid::WGS84}. + */ + static ViewState create( + const glm::dvec3& position, + const glm::dvec3& direction, + const glm::dvec3& up, + const glm::dvec2& viewportSize, + double horizontalFieldOfView, + double verticalFieldOfView, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief Gets the position of the camera in Earth-centered, Earth-fixed + * coordinates. + */ + const glm::dvec3& getPosition() const noexcept { return this->_position; } + + /** + * @brief Gets the look direction of the camera in Earth-centered, Earth-fixed + * coordinates. + */ + const glm::dvec3& getDirection() const noexcept { return this->_direction; } + + /** + * @brief Gets the up direction of the camera in Earth-centered, Earth-fixed + * coordinates. + */ + const glm::dvec3& getUp() const noexcept { return this->_up; } + + /** + * @brief Gets the position of the camera as a longitude / latitude / height. + * + * The result may be `std::nullopt` if the Cartesian position is + * very near the center of the Ellipsoid. + */ + const std::optional& + getPositionCartographic() const noexcept { + return this->_positionCartographic; + } + + /** + * @brief Gets the size of the viewport in pixels. + */ + const glm::dvec2& getViewportSize() const noexcept { + return this->_viewportSize; + } + + /** + * @brief Gets the horizontal field-of-view angle in radians. + */ + double getHorizontalFieldOfView() const noexcept { + return this->_horizontalFieldOfView; + } + + /** + * @brief Gets the vertical field-of-view angle in radians. + */ + double getVerticalFieldOfView() const noexcept { + return this->_verticalFieldOfView; + } + + /** + * @brief Returns whether the given {@link BoundingVolume} is visible for this + * camera + * + * Returns whether the given bounding volume is visible for this camera, + * meaning that the given volume is at least partially contained in + * the frustum of this camera. + * + * @return Whether the bounding volume is visible + */ + bool + isBoundingVolumeVisible(const BoundingVolume& boundingVolume) const noexcept; + + /** + * @brief Computes the squared distance to the given {@link BoundingVolume}. + * + * Computes the squared euclidean distance from the position of this camera + * to the closest point of the given bounding volume. + * + * @param boundingVolume The bounding volume + * @returns The squared distance + */ + double computeDistanceSquaredToBoundingVolume( + const BoundingVolume& boundingVolume) const noexcept; + + /** + * @brief Computes the screen space error from a given geometric error + * + * Computes the screen space error (SSE) that results from the given + * geometric error, when it is viewed with this camera from the given + * distance. + * + * The given distance will be clamped to a small positive value if + * it is negative or too close to zero. + * + * @param geometricError The geometric error + * @param distance The viewing distance + * @return The screen space error + */ + double computeScreenSpaceError(double geometricError, double distance) + const noexcept; + +private: + /** + * @brief Creates a new instance. + * + * @param position The position of the eye point of the camera. + * @param direction The view direction vector of the camera. + * @param up The up vector of the camera. + * @param viewportSize The size of the viewport, in pixels. + * @param horizontalFieldOfView The horizontal field-of-view (opening) + * angle of the camera, in radians. + * @param verticalFieldOfView The vertical field-of-view (opening) + * angle of the camera, in radians. + */ + ViewState( + const glm::dvec3& position, + const glm::dvec3& direction, + const glm::dvec3& up, + const glm::dvec2& viewportSize, + double horizontalFieldOfView, + double verticalFieldOfView, + const std::optional& positionCartographic, + const CesiumGeospatial::Ellipsoid& ellipsoid); + + const glm::dvec3 _position; + const glm::dvec3 _direction; + const glm::dvec3 _up; + const glm::dvec2 _viewportSize; + const double _horizontalFieldOfView; + const double _verticalFieldOfView; + const CesiumGeospatial::Ellipsoid _ellipsoid; + + const double _sseDenominator; + const std::optional _positionCartographic; + + const CullingVolume _cullingVolume; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ViewUpdateResult.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ViewUpdateResult.h new file mode 100644 index 0000000..e6497fe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ViewUpdateResult.h @@ -0,0 +1,91 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include + +namespace Cesium3DTilesSelection { +class Tile; + +/** + * @brief Reports the results of {@link Tileset::updateView}. + * + * Users of a {@link Tileset} will call {@link Tileset::updateView} and receive + * this structure so that they can update the state of their rendering system + * accordingly. The tileset will internally keep track the current state of the + * tiles as their {@link Tile::getLastSelectionState} throughout the rendering + * process, and use this structure to provide information about the state + * changes of tiles to clients. + */ +class CESIUM3DTILESSELECTION_API ViewUpdateResult final { +public: + /** + * @brief The tiles that were selected by the tileset traversal this frame. + * These tiles should be rendered by the client. + * + * Tiles in this list may be fading in if + * {@link TilesetOptions::enableLodTransitionPeriod} is true. + */ + std::vector tilesToRenderThisFrame; + + /** + * @brief Tiles on this list are no longer selected for rendering. + * + * If {@link TilesetOptions::enableLodTransitionPeriod} is true they may be + * fading out. If a tile's {TileRenderContent::lodTransitionPercentage} is 0 + * or lod transitions are disabled, the tile should be hidden right away. + */ + std::unordered_set tilesFadingOut; + + /** + * @brief The number of tiles in the worker thread load queue. + */ + int32_t workerThreadTileLoadQueueLength = 0; + + /** + * @brief The number of tiles in the main thread load queue. + */ + int32_t mainThreadTileLoadQueueLength = 0; + + /** + * @brief The number of tiles visited during tileset traversal this frame. + */ + uint32_t tilesVisited = 0; + /** + * @brief The number of culled tiles visited during tileset traversal this + * frame. + */ + uint32_t culledTilesVisited = 0; + /** + * @brief The number of tiles that were skipped because they were culled + * during tileset traversal this frame. + */ + uint32_t tilesCulled = 0; + /** + * @brief The number of tiles occluded this frame. + */ + uint32_t tilesOccluded = 0; + /** + * @brief The number of tiles still waiting to obtain a \ref + * TileOcclusionState this frame. + */ + uint32_t tilesWaitingForOcclusionResults = 0; + /** + * @brief The number of tiles kicked from the render list this frame. + */ + uint32_t tilesKicked = 0; + /** + * @brief The maximum depth of the tile tree visited this frame. + */ + uint32_t maxDepthVisited = 0; + + /** + * @brief The frame number. This is incremented every time \ref + * Tileset::updateView is called. + */ + int32_t frameNumber = 0; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/spdlog-cesium.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/spdlog-cesium.h new file mode 100644 index 0000000..1ca388b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/spdlog-cesium.h @@ -0,0 +1,13 @@ +#pragma once + +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wshadow" +#endif + +#include + +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/Library.h new file mode 100644 index 0000000..e7ce939 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes for writing [3D Tiles](https://github.com/CesiumGS/3d-tiles). + * + * @mermaid-interactive{dependencies/Cesium3DTilesWriter} + */ +namespace Cesium3DTilesWriter {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUM3DTILESWRITER_BUILDING +#define CESIUM3DTILESWRITER_API __declspec(dllexport) +#else +#define CESIUM3DTILESWRITER_API __declspec(dllimport) +#endif +#else +#define CESIUM3DTILESWRITER_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/SchemaWriter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/SchemaWriter.h new file mode 100644 index 0000000..6f274ed --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/SchemaWriter.h @@ -0,0 +1,81 @@ +#pragma once + +#include "Cesium3DTilesWriter/Library.h" + +#include + +// forward declarations +namespace Cesium3DTiles { +struct Schema; +} + +namespace Cesium3DTilesWriter { + +/** + * @brief The result of writing a schema with + * {@link SchemaWriter::writeSchema}. + */ +struct CESIUM3DTILESWRITER_API SchemaWriterResult { + /** + * @brief The final generated std::vector of the schema JSON. + */ + std::vector schemaBytes; + + /** + * @brief Errors, if any, that occurred during the write process. + */ + std::vector errors; + + /** + * @brief Warnings, if any, that occurred during the write process. + */ + std::vector warnings; +}; + +/** + * @brief Options for how to write a schema. + */ +struct CESIUM3DTILESWRITER_API SchemaWriterOptions { + /** + * @brief If the schema JSON should be pretty printed. + */ + bool prettyPrint = false; +}; + +/** + * @brief Writes schemas. + */ +class CESIUM3DTILESWRITER_API SchemaWriter { +public: + /** + * @brief Constructs a new instance. + */ + SchemaWriter(); + + /** + * @brief Gets the context used to control how schema extensions are written. + */ + CesiumJsonWriter::ExtensionWriterContext& getExtensions(); + + /** + * @brief Gets the context used to control how schema extensions are written. + */ + const CesiumJsonWriter::ExtensionWriterContext& getExtensions() const; + + /** + * @brief Serializes the provided schema object into a byte vector using the + * provided flags to convert. + * + * @param schema The schema. + * @param options Options for how to write the schema. + * @return The result of writing the schema. + */ + SchemaWriterResult writeSchema( + const Cesium3DTiles::Schema& schema, + const SchemaWriterOptions& options = SchemaWriterOptions()) const; + +private: + CesiumJsonWriter::ExtensionWriterContext _context; +}; + +} // namespace Cesium3DTilesWriter diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/SubtreeWriter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/SubtreeWriter.h new file mode 100644 index 0000000..76a5603 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/SubtreeWriter.h @@ -0,0 +1,81 @@ +#pragma once + +#include "Cesium3DTilesWriter/Library.h" + +#include + +// forward declarations +namespace Cesium3DTiles { +struct Subtree; +} + +namespace Cesium3DTilesWriter { + +/** + * @brief The result of writing a subtree with + * {@link SubtreeWriter::writeSubtree}. + */ +struct CESIUM3DTILESWRITER_API SubtreeWriterResult { + /** + * @brief The final generated std::vector of the subtree JSON. + */ + std::vector subtreeBytes; + + /** + * @brief Errors, if any, that occurred during the write process. + */ + std::vector errors; + + /** + * @brief Warnings, if any, that occurred during the write process. + */ + std::vector warnings; +}; + +/** + * @brief Options for how to write a subtree. + */ +struct CESIUM3DTILESWRITER_API SubtreeWriterOptions { + /** + * @brief If the subtree JSON should be pretty printed. + */ + bool prettyPrint = false; +}; + +/** + * @brief Writes subtrees. + */ +class CESIUM3DTILESWRITER_API SubtreeWriter { +public: + /** + * @brief Constructs a new instance. + */ + SubtreeWriter(); + + /** + * @brief Gets the context used to control how subtree extensions are written. + */ + CesiumJsonWriter::ExtensionWriterContext& getExtensions(); + + /** + * @brief Gets the context used to control how subtree extensions are written. + */ + const CesiumJsonWriter::ExtensionWriterContext& getExtensions() const; + + /** + * @brief Serializes the provided subtree object into a byte vector using the + * provided flags to convert. + * + * @param subtree The subtree. + * @param options Options for how to write the subtree. + * @return The result of writing the subtree. + */ + SubtreeWriterResult writeSubtree( + const Cesium3DTiles::Subtree& subtree, + const SubtreeWriterOptions& options = SubtreeWriterOptions()) const; + +private: + CesiumJsonWriter::ExtensionWriterContext _context; +}; + +} // namespace Cesium3DTilesWriter diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/TilesetWriter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/TilesetWriter.h new file mode 100644 index 0000000..2ce548e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/TilesetWriter.h @@ -0,0 +1,81 @@ +#pragma once + +#include "Cesium3DTilesWriter/Library.h" + +#include + +// forward declarations +namespace Cesium3DTiles { +struct Tileset; +} + +namespace Cesium3DTilesWriter { + +/** + * @brief The result of writing a tileset with + * {@link TilesetWriter::writeTileset}. + */ +struct CESIUM3DTILESWRITER_API TilesetWriterResult { + /** + * @brief The final generated std::vector of the tileset. + */ + std::vector tilesetBytes; + + /** + * @brief Errors, if any, that occurred during the write process. + */ + std::vector errors; + + /** + * @brief Warnings, if any, that occurred during the write process. + */ + std::vector warnings; +}; + +/** + * @brief Options for how to write a tileset. + */ +struct CESIUM3DTILESWRITER_API TilesetWriterOptions { + /** + * @brief If the tileset JSON should be pretty printed. + */ + bool prettyPrint = false; +}; + +/** + * @brief Writes tilesets. + */ +class CESIUM3DTILESWRITER_API TilesetWriter { +public: + /** + * @brief Constructs a new instance. + */ + TilesetWriter(); + + /** + * @brief Gets the context used to control how tileset extensions are written. + */ + CesiumJsonWriter::ExtensionWriterContext& getExtensions(); + + /** + * @brief Gets the context used to control how tileset extensions are written. + */ + const CesiumJsonWriter::ExtensionWriterContext& getExtensions() const; + + /** + * @brief Serializes the provided tileset object into a byte vector using the + * provided flags to convert. + * + * @param tileset The tileset. + * @param options Options for how to write the tileset. + * @return The result of writing the tileset. + */ + TilesetWriterResult writeTileset( + const Cesium3DTiles::Tileset& tileset, + const TilesetWriterOptions& options = TilesetWriterOptions()) const; + +private: + CesiumJsonWriter::ExtensionWriterContext _context; +}; + +} // namespace Cesium3DTilesWriter diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/AsyncSystem.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/AsyncSystem.h new file mode 100644 index 0000000..23bc64f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/AsyncSystem.h @@ -0,0 +1,360 @@ +#pragma once + +#include "Future.h" +#include "Impl/ContinuationFutureType.h" +#include "Impl/RemoveFuture.h" +#include "Impl/WithTracing.h" +#include "Impl/cesium-async++.h" +#include "Library.h" +#include "Promise.h" +#include "ThreadPool.h" + +#include + +#include +#include + +namespace CesiumAsync { +class ITaskProcessor; + +class AsyncSystem; + +/** + * @brief A system for managing asynchronous requests and tasks. + * + * Instances of this class may be safely and efficiently stored and passed + * around by value. However, it is essential that the _last_ AsyncSystem + * instance be destroyed only after all continuations have run to completion. + * Otherwise, continuations may be scheduled using invalid scheduler instances, + * leading to a crash. Broadly, there are two ways to achieve this: + * + * * Wait until all Futures complete before destroying the "owner" of the + * AsyncSystem. + * * Make the AsyncSystem a global or static local in order to extend its + * lifetime all the way until program termination. + */ +class CESIUMASYNC_API AsyncSystem final { +public: + /** + * @brief Constructs a new instance. + * + * @param pTaskProcessor The interface used to run tasks in background + * threads. + */ + AsyncSystem(const std::shared_ptr& pTaskProcessor) noexcept; + + /** + * @brief Creates a new Future by immediately invoking a function and giving + * it the opportunity to resolve or reject a {@link Promise}. + * + * The {@link Promise} passed to the callback `f` may be resolved or rejected + * asynchronously, even after the function has returned. + * + * This method is very similar to {@link AsyncSystem::createPromise}, except + * that that method returns the Promise directly. The advantage of using this + * method instead is that it is more exception-safe. If the callback `f` + * throws an exception, the `Future` will be rejected automatically and the + * exception will not escape the callback. + * + * @tparam T The type that the Future resolves to. + * @tparam Func The type of the callback function. + * @param f The callback function to invoke immediately to create the Future. + * @return A Future that will resolve when the callback function resolves the + * supplied Promise. + */ + template Future createFuture(Func&& f) const { + std::shared_ptr> pEvent = + std::make_shared>(); + + Promise promise(this->_pSchedulers, pEvent); + + try { + f(promise); + } catch (...) { + promise.reject(std::current_exception()); + } + + return Future(this->_pSchedulers, pEvent->get_task()); + } + + /** + * @brief Create a Promise that can be used at a later time to resolve or + * reject a Future. + * + * Use {@link Promise::getFuture} to get the Future that is resolved + * or rejected when this Promise is resolved or rejected. + * + * Consider using {@link AsyncSystem::createFuture} instead of this method. + * + * @tparam T The type that is provided when resolving the Promise and the type + * that the associated Future resolves to. Future. + * @return The Promise. + */ + template Promise createPromise() const { + return Promise( + this->_pSchedulers, + std::make_shared>()); + } + + /** + * @brief Runs a function in a worker thread, returning a Future that + * resolves when the function completes. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * If this method is called from a designated worker thread, the + * callback will be invoked immediately and complete before this function + * returns. + * + * @tparam Func The type of the function. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template + CesiumImpl::ContinuationFutureType_t + runInWorkerThread(Func&& f) const { + static const char* tracingName = "waiting for worker thread"; + + CESIUM_TRACE_BEGIN_IN_TRACK(tracingName); + + return CesiumImpl::ContinuationFutureType_t( + this->_pSchedulers, + async::spawn( + this->_pSchedulers->workerThread.immediate, + CesiumImpl::WithTracing::end( + tracingName, + std::forward(f)))); + } + + /** + * @brief Runs a function in the main thread, returning a Future that + * resolves when the function completes. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * If this method is called from the main thread, the callback will be invoked + * immediately and complete before this function returns. + * + * @tparam Func The type of the function. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template + CesiumImpl::ContinuationFutureType_t + runInMainThread(Func&& f) const { + static const char* tracingName = "waiting for main thread"; + + CESIUM_TRACE_BEGIN_IN_TRACK(tracingName); + + return CesiumImpl::ContinuationFutureType_t( + this->_pSchedulers, + async::spawn( + this->_pSchedulers->mainThread.immediate, + CesiumImpl::WithTracing::end( + tracingName, + std::forward(f)))); + } + + /** + * @brief Runs a function in a thread pool, returning a Future that resolves + * when the function completes. + * + * @tparam Func The type of the function. + * @param threadPool The thread pool in which to run the function. + * @param f The function to run. + * @return A future that resolves after the supplied function completes. + */ + template + CesiumImpl::ContinuationFutureType_t + runInThreadPool(const ThreadPool& threadPool, Func&& f) const { + static const char* tracingName = "waiting for thread pool"; + + CESIUM_TRACE_BEGIN_IN_TRACK(tracingName); + + return CesiumImpl::ContinuationFutureType_t( + this->_pSchedulers, + async::spawn( + threadPool._pScheduler->immediate, + CesiumImpl::WithTracing::end( + tracingName, + std::forward(f)))); + } + + /** + * @brief The value type of the Future returned by {@link all}. + * + * This will be either `std::vector`, if the input Futures passed to the + * `all` function return values, or `void` if they do not. + * + * @tparam T The value type of the input Futures passed to the function. + */ + template + using AllValueType = + std::conditional_t, void, std::vector>; + + /** + * @brief Creates a Future that resolves when every Future in a vector + * resolves, and rejects when any Future in the vector rejects. + * + * If the input Futures resolve to non-void values, the returned Future + * resolves to a vector of the values, in the same order as the input Futures. + * If the input Futures resolve to void, the returned Future resolves to void + * as well. + * + * If any of the Futures rejects, the returned Future rejects as well. The + * exception included in the rejection will be from the first Future in the + * vector that rejects. + * + * To get detailed rejection information from each of the Futures, + * attach a `catchInMainThread` continuation prior to passing the + * list into `all`. + * + * @tparam T The type that each Future resolves to. + * @param futures The list of futures. + * @return A Future that resolves when all the given Futures resolve, and + * rejects when any Future in the vector rejects. + */ + template + Future> all(std::vector>&& futures) const { + return this->all>( + std::forward>>(futures)); + } + + /** + * @brief Creates a Future that resolves when every Future in a vector + * resolves, and rejects when any Future in the vector rejects. + * + * If the input SharedFutures resolve to non-void values, the returned Future + * resolves to a vector of the values, in the same order as the input + * SharedFutures. If the input SharedFutures resolve to void, the returned + * Future resolves to void as well. + * + * If any of the SharedFutures rejects, the returned Future rejects as well. + * The exception included in the rejection will be from the first SharedFuture + * in the vector that rejects. + * + * To get detailed rejection information from each of the SharedFutures, + * attach a `catchInMainThread` continuation prior to passing the + * list into `all`. + * + * @tparam T The type that each SharedFuture resolves to. + * @param futures The list of shared futures. + * @return A Future that resolves when all the given SharedFutures resolve, + * and rejects when any SharedFuture in the vector rejects. + */ + template + Future> all(std::vector>&& futures) const { + return this->all>( + std::forward>>(futures)); + } + + /** + * @brief Creates a future that is already resolved. + * + * @tparam T The type of the future. + * @param value The value for the future. + * @return The future. + */ + template Future createResolvedFuture(T&& value) const { + return Future( + this->_pSchedulers, + async::make_task(std::forward(value))); + } + + /** + * @brief Creates a future that is already resolved and resolves to no value. + * + * @return The future. + */ + Future createResolvedFuture() const { + return Future(this->_pSchedulers, async::make_task()); + } + + /** + * @brief Runs all tasks that are currently queued for the main thread. + * + * The tasks are run in the calling thread. + */ + void dispatchMainThreadTasks(); + + /** + * @brief Runs a single waiting task that is currently queued for the main + * thread. If there are no tasks waiting, it returns immediately without + * running any tasks. + * + * The task is run in the calling thread. + * + * @return true A single task was executed. + * @return false No task was executed because none are waiting. + */ + bool dispatchOneMainThreadTask(); + + /** + * @brief Creates a new thread pool that can be used to run continuations. + * + * @param numberOfThreads The number of threads in the pool. + * @return The thread pool. + */ + ThreadPool createThreadPool(int32_t numberOfThreads) const; + + /** + * Returns true if this instance and the right-hand side can be used + * interchangeably because they schedule continuations identically. Otherwise, + * returns false. + */ + bool operator==(const AsyncSystem& rhs) const noexcept; + + /** + * Returns true if this instance and the right-hand side can _not_ be used + * interchangeably because they schedule continuations differently. Otherwise, + * returns false. + */ + bool operator!=(const AsyncSystem& rhs) const noexcept; + +private: + // Common implementation of 'all' for both Future and SharedFuture. + template + Future> all(std::vector&& futures) const { + using TTaskType = decltype(TFutureType::_task); + std::vector tasks; + tasks.reserve(futures.size()); + + for (auto it = futures.begin(); it != futures.end(); ++it) { + tasks.emplace_back(std::move(it->_task)); + } + + futures.clear(); + + async::task> task = + async::when_all(tasks.begin(), tasks.end()) + .then( + async::inline_scheduler(), + [](std::vector&& tasks) { + if constexpr (std::is_void_v) { + // Tasks return void. "Get" each task so that error + // information is propagated. + for (auto it = tasks.begin(); it != tasks.end(); ++it) { + it->get(); + } + } else { + // Get all the results. If any tasks rejected, we'll bail + // with an exception. + std::vector results; + results.reserve(tasks.size()); + + for (auto it = tasks.begin(); it != tasks.end(); ++it) { + results.emplace_back(std::move(it->get())); + } + return results; + } + }); + return Future>(this->_pSchedulers, std::move(task)); + } + + std::shared_ptr _pSchedulers; + + template friend class Future; +}; +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/CacheItem.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/CacheItem.h new file mode 100644 index 0000000..ea49fe6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/CacheItem.h @@ -0,0 +1,119 @@ +#pragma once + +#include "HttpHeaders.h" +#include "Library.h" + +#include +#include +#include +#include +#include +#include + +namespace CesiumAsync { + +/** + * @brief Cache response retrieved from the cache database. + */ +class CESIUMASYNC_API CacheResponse { +public: + /** + * @brief Constructor. + * @param cacheStatusCode the status code of the response + * @param cacheHeaders the headers of the response + * @param cacheData the body of the response + */ + CacheResponse( + uint16_t cacheStatusCode, + HttpHeaders&& cacheHeaders, + std::vector&& cacheData) + : statusCode(cacheStatusCode), + headers(std::move(cacheHeaders)), + data(std::move(cacheData)) {} + + /** + * @brief The status code of the response. + */ + uint16_t statusCode; + + /** + * @brief The headers of the response. + */ + HttpHeaders headers; + + /** + * @brief The body data of the response. + */ + std::vector data; +}; + +/** + * @brief Cache request retrieved from the cache database. + */ +class CESIUMASYNC_API CacheRequest { +public: + /** + * @brief Constructor. + * @param cacheHeaders the headers of the request + * @param cacheMethod the method of the request + * @param cacheUrl the url of the request + */ + CacheRequest( + HttpHeaders&& cacheHeaders, + std::string&& cacheMethod, + std::string&& cacheUrl) + : headers(std::move(cacheHeaders)), + method(std::move(cacheMethod)), + url(std::move(cacheUrl)) {} + + /** + * @brief The headers of the request. + */ + HttpHeaders headers; + + /** + * @brief The method of the request. + */ + std::string method; + + /** + * @brief The url of the request. + */ + std::string url; +}; + +/** + * @brief Cache item retrieved from the cache database. + */ +class CESIUMASYNC_API CacheItem { +public: + /** + * @brief Constructor. + * @param cacheExpiryTime the time point this cache item will be expired + * @param request the cache request owned by this item + * @param response the cache response owned by this item + */ + CacheItem( + std::time_t cacheExpiryTime, + CacheRequest&& request, + CacheResponse&& response) + : expiryTime(cacheExpiryTime), + cacheRequest(std::move(request)), + cacheResponse(std::move(response)) {} + + /** + * @brief The time point that this cache item is expired. + */ + std::time_t expiryTime; + + /** + * @brief The cache request owned by this cache item. + */ + CacheRequest cacheRequest; + + /** + * @brief The cache response owned by this cache item. + */ + CacheResponse cacheResponse; +}; +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/CachingAssetAccessor.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/CachingAssetAccessor.h new file mode 100644 index 0000000..67aa99a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/CachingAssetAccessor.h @@ -0,0 +1,72 @@ +#pragma once + +#include "IAssetAccessor.h" +#include "IAssetRequest.h" +#include "ICacheDatabase.h" +#include "ThreadPool.h" + +#include + +#include +#include +#include +#include + +namespace CesiumAsync { +class AsyncSystem; + +/** + * @brief A decorator for an {@link IAssetAccessor} that caches requests and + * responses in an {@link ICacheDatabase}. + * + * This can be used to improve asset loading performance by caching assets + * across runs. + */ +class CachingAssetAccessor : public IAssetAccessor { +public: + /** + * @brief Constructs a new instance. + * + * @param pLogger The logger that receives messages about the status of this + * instance. + * @param pAssetAccessor The underlying {@link IAssetAccessor} used to + * retrieve assets that are not in the cache. + * @param pCacheDatabase The database in which to cache requests and + * responses. + * @param requestsPerCachePrune The number of requests to handle before each + * {@link ICacheDatabase::prune} of old cached results from the database. + */ + CachingAssetAccessor( + const std::shared_ptr& pLogger, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pCacheDatabase, + int32_t requestsPerCachePrune = 10000); + + virtual ~CachingAssetAccessor() noexcept override; + + /** @copydoc IAssetAccessor::get */ + virtual Future> + get(const AsyncSystem& asyncSystem, + const std::string& url, + const std::vector& headers) override; + + virtual Future> request( + const AsyncSystem& asyncSystem, + const std::string& verb, + const std::string& url, + const std::vector& headers, + const std::span& contentPayload) override; + + /** @copydoc IAssetAccessor::tick */ + virtual void tick() noexcept override; + +private: + int32_t _requestsPerCachePrune; + std::atomic _requestSinceLastPrune; + std::shared_ptr _pLogger; + std::shared_ptr _pAssetAccessor; + std::shared_ptr _pCacheDatabase; + ThreadPool _cacheThreadPool; + CESIUM_TRACE_DECLARE_TRACK_SET(_pruneSlots, "Prune cache database") +}; +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Future.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Future.h new file mode 100644 index 0000000..ffe4ec6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Future.h @@ -0,0 +1,351 @@ +#pragma once + +#include "Impl/AsyncSystemSchedulers.h" +#include "Impl/CatchFunction.h" +#include "Impl/ContinuationFutureType.h" +#include "Impl/WithTracing.h" +#include "SharedFuture.h" +#include "ThreadPool.h" + +#include + +#include + +namespace CesiumAsync { + +namespace CesiumImpl { + +template struct ParameterizedTaskUnwrapper; +struct TaskUnwrapper; + +} // namespace CesiumImpl + +/** + * @brief A value that will be available in the future, as produced by + * {@link AsyncSystem}. + * + * @tparam T The type of the value. + */ +template class Future final { +public: + /** + * @brief Move constructor + */ + Future(Future&& rhs) noexcept + : _pSchedulers(std::move(rhs._pSchedulers)), + _task(std::move(rhs._task)) {} + + /** + * @brief Move assignment operator. + */ + Future& operator=(Future&& rhs) noexcept { + this->_pSchedulers = std::move(rhs._pSchedulers); + this->_task = std::move(rhs._task); + return *this; + } + + Future(const Future& rhs) = delete; + Future& operator=(const Future& rhs) = delete; + + /** + * @brief Registers a continuation function to be invoked in a worker thread + * when this Future resolves, and invalidates this Future. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * If this Future is resolved from a designated worker thread, the + * continuation function will be invoked immediately rather than in a + * separate task. Similarly, if the Future is already resolved when + * `thenInWorkerThread` is called from a designated worker thread, the + * continuation function will be invoked immediately before this + * method returns. + * + * @tparam Func The type of the function. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template + CesiumImpl::ContinuationFutureType_t + thenInWorkerThread(Func&& f) && { + return std::move(*this).thenWithScheduler( + this->_pSchedulers->workerThread.immediate, + "waiting for worker thread", + std::forward(f)); + } + + /** + * @brief Registers a continuation function to be invoked in the main thread + * when this Future resolves, and invalidates this Future. + * + * If this Future is resolved from the main thread, the + * continuation function will be invoked immediately rather than queued for + * later execution in the main thread. Similarly, if the Future is already + * resolved when `thenInMainThread` is called from the main thread, the + * continuation function will be invoked immediately before this + * method returns. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * @tparam Func The type of the function. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template + CesiumImpl::ContinuationFutureType_t thenInMainThread(Func&& f) && { + return std::move(*this).thenWithScheduler( + this->_pSchedulers->mainThread.immediate, + "waiting for main thread", + std::forward(f)); + } + + /** + * @brief Registers a continuation function to be invoked immediately in + * whichever thread causes the Future to be resolved, and invalidates this + * Future. + * + * If the Future is already resolved, the supplied function will be called + * immediately in the calling thread and this method will not return until + * that function does. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * @tparam Func The type of the function. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template + CesiumImpl::ContinuationFutureType_t thenImmediately(Func&& f) && { + return CesiumImpl::ContinuationFutureType_t( + this->_pSchedulers, + _task.then( + async::inline_scheduler(), + CesiumImpl::WithTracing::end(nullptr, std::forward(f)))); + } + + /** + * @brief Registers a continuation function to be invoked in a thread pool + * when this Future resolves, and invalidates this Future. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * If this Future is resolved from a thread pool thread, the + * continuation function will be invoked immediately rather than in a + * separate task. Similarly, if the Future is already resolved when + * `thenInThreadPool` is called from a designated thread pool thread, the + * continuation function will be invoked immediately before this + * method returns. + * + * @tparam Func The type of the function. + * @param threadPool The thread pool where this function will be invoked. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template + CesiumImpl::ContinuationFutureType_t + thenInThreadPool(const ThreadPool& threadPool, Func&& f) && { + return std::move(*this).thenWithScheduler( + threadPool._pScheduler->immediate, + "waiting for thread pool thread", + std::forward(f)); + } + + /** + * @brief Registers a continuation function to be invoked in the main thread + * when this Future rejects, and invalidates this Future. + * + * If this Future is rejected from the main thread, the + * continuation function will be invoked immediately rather than queued for + * later execution in the main thread. Similarly, if the Future is already + * rejected when `catchInMainThread` is called from the main thread, the + * continuation function will be invoked immediately before this + * method returns. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * Any `then` continuations chained after this one will be invoked with the + * return value of the catch callback. + * + * @tparam Func The type of the function. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template Future catchInMainThread(Func&& f) && { + return std::move(*this).catchWithScheduler( + this->_pSchedulers->mainThread.immediate, + std::forward(f)); + } + + /** + * @brief Registers a continuation function to be invoked immediately, and + * invalidates this Future. + * + * When this Future is rejected, the continuation function will be invoked + * in whatever thread does the rejection. Similarly, if the Future is already + * rejected when `catchImmediately` is called, the continuation function will + * be invoked immediately before this method returns. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * Any `then` continuations chained after this one will be invoked with the + * return value of the catch callback. + * + * @tparam Func The type of the function. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template Future catchImmediately(Func&& f) && { + return std::move(*this).catchWithScheduler( + async::inline_scheduler(), + std::forward(f)); + } + + /** + * @brief Passes through one or more additional values to the next + * continuation. + * + * The next continuation will receive a tuple with each of the provided + * values, followed by the result of the current Future. + * + * @tparam TPassThrough The types to pass through to the next continuation. + * @param values The values to pass through to the next continuation. + * @return A new Future that resolves to a tuple with the pass-through values, + * followed by the result of the last Future. + */ + template + Future..., T>> + thenPassThrough(TPassThrough&&... values) && { + return std::move(*this).thenImmediately( + [values = std::tuple(std::forward(values)...)]( + T&& result) mutable { + return std::tuple_cat( + std::move(values), + std::make_tuple(std::move(result))); + }); + } + + /** + * @brief Waits for the future to resolve or reject and returns the result. + * + * This method must not be called from the main thread, the one that calls + * {@link AsyncSystem::dispatchMainThreadTasks}. Doing so can lead to a + * deadlock because the main thread tasks will never complete while this + * method is blocking the main thread. + * + * To wait in the main thread, use {@link waitInMainThread} instead. + * + * @return The value if the future resolves successfully. + * @throws An exception if the future rejected. + */ + T wait() { return this->_task.get(); } + + /** + * @brief Waits for this future to resolve or reject in the main thread while + * also processing main-thread tasks. + * + * This method must be called from the main thread. + * + * The function does not return until {@link Future::isReady} returns true. + * In the meantime, main-thread tasks are processed as necessary. This method + * does not spin wait; it suspends the calling thread by waiting on a + * condition variable when there is no work to do. + * + * @return The value if the future resolves successfully. + * @throws An exception if the future rejected. + */ + T waitInMainThread() { + return this->_pSchedulers->mainThread.dispatchUntilTaskCompletes( + std::move(this->_task)); + } + + /** + * @brief Determines if this future is already resolved or rejected. + * + * If this method returns true, it is guaranteed that {@link wait} will + * not block but will instead immediately return a value or throw an + * exception. + * + * @return True if the future is already resolved or rejected and {@link wait} + * will not block; otherwise, false. + */ + bool isReady() const { return this->_task.ready(); } + + /** + * @brief Creates a version of this future that can be shared, meaning that + * its value may be accessed multiple times and multiple continuations may be + * attached to it. + * + * Calling this method invalidates the original Future. + * + * @return The `SharedFuture`. + */ + SharedFuture share() && { + return SharedFuture(this->_pSchedulers, this->_task.share()); + } + +private: + Future( + const std::shared_ptr& pSchedulers, + async::task&& task) noexcept + : _pSchedulers(pSchedulers), _task(std::move(task)) {} + + template + CesiumImpl::ContinuationFutureType_t thenWithScheduler( + Scheduler& scheduler, + const char* tracingName, + Func&& f) && { + // It would be nice if tracingName were a template parameter instead of a + // function parameter, but that triggers a bug in VS2017. It was previously + // a bug in VS2019, too, but has been fixed there: + // https://developercommunity.visualstudio.com/t/internal-compiler-error-when-compiling-a-template-1/534210 +#if CESIUM_TRACING_ENABLED + // When tracing is enabled, we measure the time between scheduling and + // dispatching of the work. + auto task = this->_task.then( + async::inline_scheduler(), + CesiumImpl::WithTracing::begin(tracingName, std::forward(f))); +#else + auto& task = this->_task; +#endif + + return CesiumImpl::ContinuationFutureType_t( + this->_pSchedulers, + task.then( + scheduler, + CesiumImpl::WithTracing::end( + tracingName, + std::forward(f)))); + } + + template + CesiumImpl::ContinuationFutureType_t + catchWithScheduler(Scheduler& scheduler, Func&& f) && { + return CesiumImpl::ContinuationFutureType_t( + this->_pSchedulers, + this->_task.then( + async::inline_scheduler(), + CesiumImpl::CatchFunction{ + scheduler, + std::forward(f)})); + } + + std::shared_ptr _pSchedulers; + async::task _task; + + friend class AsyncSystem; + + template friend struct CesiumImpl::ParameterizedTaskUnwrapper; + + friend struct CesiumImpl::TaskUnwrapper; + + template friend class Future; + template friend class SharedFuture; + template friend class Promise; +}; + +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/GunzipAssetAccessor.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/GunzipAssetAccessor.h new file mode 100644 index 0000000..ca11bb0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/GunzipAssetAccessor.h @@ -0,0 +1,44 @@ +#pragma once + +#include "IAssetAccessor.h" +#include "IAssetRequest.h" + +namespace CesiumAsync { +class AsyncSystem; + +/** + * @brief A decorator for an {@link IAssetAccessor} that automatically unzips + * gzipped asset responses from the underlying Asset Accessor. + */ +class GunzipAssetAccessor : public IAssetAccessor { +public: + /** + * @brief Constructs a new instance. + * + * @param pAssetAccessor The underlying {@link IAssetAccessor} used to + * retrieve assets that may or may not be zipped. + */ + GunzipAssetAccessor(const std::shared_ptr& pAssetAccessor); + + virtual ~GunzipAssetAccessor() noexcept override; + + /** @copydoc IAssetAccessor::get */ + virtual Future> + get(const AsyncSystem& asyncSystem, + const std::string& url, + const std::vector& headers) override; + + virtual Future> request( + const AsyncSystem& asyncSystem, + const std::string& verb, + const std::string& url, + const std::vector& headers, + const std::span& contentPayload) override; + + /** @copydoc IAssetAccessor::tick */ + virtual void tick() noexcept override; + +private: + std::shared_ptr _pAssetAccessor; +}; +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/HttpHeaders.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/HttpHeaders.h new file mode 100644 index 0000000..0ed00c3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/HttpHeaders.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +namespace CesiumAsync { + +/** + * @brief A case-insensitive `less-then` string comparison. + * + * This can be used as a `Compare` function, for example for a `std::map`. + * It will compare strings case-insensitively, by converting them to + * lower-case and comparing the results (leaving the exact behavior for + * non-ASCII strings unspecified). + */ +struct CaseInsensitiveCompare { + /** @brief Performs a case-insensitive comparison of the two strings using + * `std::lexicographical_compare`. */ + bool operator()(const std::string& s1, const std::string& s2) const; +}; + +/** + * @brief Http Headers that maps case-insensitive header key with header value. + */ +using HttpHeaders = std::map; +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/IAssetAccessor.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/IAssetAccessor.h new file mode 100644 index 0000000..f1567d8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/IAssetAccessor.h @@ -0,0 +1,73 @@ +#pragma once + +#include "Future.h" +#include "IAssetRequest.h" +#include "Library.h" + +#include +#include +#include +#include +#include + +namespace CesiumAsync { + +class AsyncSystem; + +/** + * @brief Provides asynchronous access to assets, usually files downloaded via + * HTTP. + */ +class CESIUMASYNC_API IAssetAccessor { +public: + /** + * @brief An HTTP header represented as a key/value pair. + */ + typedef std::pair THeader; + + virtual ~IAssetAccessor() = default; + + /** + * @brief Starts a new request for the asset with the given URL. + * The request proceeds asynchronously without blocking the calling thread. + * + * @param asyncSystem The async system used to do work in threads. + * @param url The URL of the asset. + * @param headers The headers to include in the request. + * @return The in-progress asset request. + */ + virtual CesiumAsync::Future> + get(const AsyncSystem& asyncSystem, + const std::string& url, + const std::vector& headers = {}) = 0; + + /** + * @brief Starts a new request to the given URL, using the provided HTTP verb + * and the provided content payload. + * + * The request proceeds asynchronously without blocking the calling thread. + * + * @param asyncSystem The async system used to do work in threads. + * @param verb The HTTP verb to use, such as "POST" or "PATCH". + * @param url The URL of the asset. + * @param headers The headers to include in the request. + * @param contentPayload The payload data to include in the request. + * @return The in-progress asset request. + */ + virtual CesiumAsync::Future> request( + const AsyncSystem& asyncSystem, + const std::string& verb, + const std::string& url, + const std::vector& headers = std::vector(), + const std::span& contentPayload = {}) = 0; + + /** + * @brief Ticks the asset accessor system while the main thread is blocked. + * + * If the asset accessor is not dependent on the main thread to + * dispatch requests, this method does not need to do anything. + */ + virtual void tick() noexcept = 0; +}; + +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/IAssetRequest.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/IAssetRequest.h new file mode 100644 index 0000000..870aa1f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/IAssetRequest.h @@ -0,0 +1,45 @@ +#pragma once + +#include "HttpHeaders.h" +#include "Library.h" + +#include +#include + +namespace CesiumAsync { + +class IAssetResponse; + +/** + * @brief An asynchronous request for an asset, usually a file + * downloaded via HTTP. + */ +class CESIUMASYNC_API IAssetRequest { +public: + virtual ~IAssetRequest() = default; + + /** + * @brief Gets the request's method. This method may be called from any + * thread. + */ + virtual const std::string& method() const = 0; + + /** + * @brief Gets the requested URL. This method may be called from any thread. + */ + virtual const std::string& url() const = 0; + + /** + * @brief Gets the request's header. This method may be called from any + * thread. + */ + virtual const HttpHeaders& headers() const = 0; + + /** + * @brief Gets the response, or nullptr if the request is still in progress. + * This method may be called from any thread. + */ + virtual const IAssetResponse* response() const = 0; +}; + +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/IAssetResponse.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/IAssetResponse.h new file mode 100644 index 0000000..1260f87 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/IAssetResponse.h @@ -0,0 +1,45 @@ +#pragma once + +#include "HttpHeaders.h" +#include "Library.h" + +#include +#include +#include +#include +#include + +namespace CesiumAsync { + +/** + * @brief A completed response for a 3D Tiles asset. + */ +class CESIUMASYNC_API IAssetResponse { +public: + /** + * @brief Default destructor + */ + virtual ~IAssetResponse() = default; + + /** + * @brief Returns the HTTP response code. + */ + virtual uint16_t statusCode() const = 0; + + /** + * @brief Returns the HTTP content type + */ + virtual std::string contentType() const = 0; + + /** + * @brief Returns the HTTP headers of the response + */ + virtual const HttpHeaders& headers() const = 0; + + /** + * @brief Returns the data of this response + */ + virtual std::span data() const = 0; +}; + +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/ICacheDatabase.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/ICacheDatabase.h new file mode 100644 index 0000000..f90cb54 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/ICacheDatabase.h @@ -0,0 +1,73 @@ +#pragma once + +#include "CacheItem.h" +#include "IAssetRequest.h" +#include "Library.h" + +#include +#include + +namespace CesiumAsync { +/** + * @brief Provides database storage interface to cache completed request. + */ +class CESIUMASYNC_API ICacheDatabase { +public: + virtual ~ICacheDatabase() noexcept = default; + + /** + * @brief Gets a cache entry from the database. + * + * If an error prevents checking the database for the key, this function, + * depending on the implementation, may log the error. However, it should + * return `std::nullopt`. It should not throw an exception. + * + * @param key The unique key associated with the cache entry. + * @return The result of the cache lookup, or `std::nullopt` if the key does + * not exist in the cache or an error occurred. + */ + virtual std::optional getEntry(const std::string& key) const = 0; + + /** + * @brief Store a cache entry in the database. + * + * @param key the unique key associated with the response + * @param expiryTime the time point that this response should be expired. An + * expired response will be removed when prunning the database. + * @param url The URL being cached. + * @param requestMethod The HTTP method being cached. + * @param requestHeaders The HTTP request headers being cached. + * @param statusCode The HTTP response status code being cached. + * @param responseHeaders The HTTP response headers being cached. + * @param responseData The HTTP response being cached. + * @return `true` if the entry was successfully stored, or `false` if it could + * not be stored due to an error. + */ + virtual bool storeEntry( + const std::string& key, + std::time_t expiryTime, + const std::string& url, + const std::string& requestMethod, + const HttpHeaders& requestHeaders, + uint16_t statusCode, + const HttpHeaders& responseHeaders, + const std::span& responseData) = 0; + + /** + * @brief Remove cache entries from the database to satisfy the database + * invariant condition (.e.g exired response or LRU). + * + * @return `true` if the database was successfully pruned, or `false` if it + * could not be pruned due to an errror. + */ + virtual bool prune() = 0; + + /** + * @brief Removes all cache entries from the database. + * + * @return `true` if the database was successfully cleared, or `false` if it + * could not be pruned due to an errror. + */ + virtual bool clearAll() = 0; +}; +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/ITaskProcessor.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/ITaskProcessor.h new file mode 100644 index 0000000..916c3ab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/ITaskProcessor.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Library.h" + +#include + +namespace CesiumAsync { +/** + * @brief When implemented by a rendering engine, allows tasks to be + * asynchronously executed in background threads. + * + * Not supposed to be used by clients. + */ +class ITaskProcessor { +public: + /** + * @brief Default destructor + */ + virtual ~ITaskProcessor() = default; + + /** + * @brief Starts a task that executes the given function in a background + * thread. + * + * @param f The function to execute + */ + virtual void startTask(std::function f) = 0; +}; +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/AsyncSystemSchedulers.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/AsyncSystemSchedulers.h new file mode 100644 index 0000000..32360d8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/AsyncSystemSchedulers.h @@ -0,0 +1,27 @@ +#pragma once + +#include "QueuedScheduler.h" +#include "TaskScheduler.h" +#include "cesium-async++.h" + +namespace CesiumAsync { + +class ITaskProcessor; + +namespace CesiumImpl { +// Begin omitting doxygen warnings for Impl namespace +//! @cond Doxygen_Suppress + +class AsyncSystemSchedulers { +public: + AsyncSystemSchedulers(const std::shared_ptr& pTaskProcessor) + : mainThread(), workerThread(pTaskProcessor) {} + + QueuedScheduler mainThread; + TaskScheduler workerThread; +}; + +//! @endcond +// End omitting doxygen warnings for Impl namespace +} // namespace CesiumImpl +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/CatchFunction.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/CatchFunction.h new file mode 100644 index 0000000..bbe8426 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/CatchFunction.h @@ -0,0 +1,76 @@ +#pragma once + +#include "unwrapFuture.h" + +namespace CesiumAsync { +namespace CesiumImpl { +// Begin omitting doxgen warnings for Impl namespace +//! @cond Doxygen_Suppress + +template < + typename Func, + typename T, + typename Scheduler, + typename TaskParameter = async::task&&> +struct CatchFunction { + Scheduler& scheduler; + Func f; + + async::task operator()(TaskParameter t) { + try { + return async::make_task(t.get()); + } catch (...) { + // Make an exception_ptr task, then scheduler to a wrapper around f that + // throws it, catches it, and calls f with a reference to it. + auto ptrToException = [f = std::move(f)](std::exception_ptr&& e) mutable { + try { + std::rethrow_exception(e); + } catch (std::exception& e) { + return f(std::move(e)); + } catch (...) { + return f(std::runtime_error("Unknown exception")); + } + }; + return async::make_task(std::current_exception()) + .then( + scheduler, + unwrapFuture( + std::move(ptrToException))); + } + } +}; + +template +struct CatchFunction { + Scheduler& scheduler; + Func f; + + async::task operator()(TaskParameter t) { + try { + t.get(); + return async::make_task(); + } catch (...) { + // Make an exception_ptr task, then scheduler to a wrapper around f that + // throws it, catches it, and calls f with a reference to it. + auto ptrToException = [f = std::move(f)](std::exception_ptr&& e) mutable { + try { + std::rethrow_exception(e); + } catch (std::exception& e) { + return f(std::move(e)); + } catch (...) { + return f(std::runtime_error("Unknown exception")); + } + }; + return async::make_task(std::current_exception()) + .then( + scheduler, + unwrapFuture( + std::move(ptrToException))); + } + } +}; + +//! @endcond +// End omitting doxgen warnings for Impl namespace +} // namespace CesiumImpl +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/ContinuationFutureType.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/ContinuationFutureType.h new file mode 100644 index 0000000..b9215cb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/ContinuationFutureType.h @@ -0,0 +1,25 @@ +#pragma once + +#include "ContinuationReturnType.h" +#include "RemoveFuture.h" + +namespace CesiumAsync { + +template class Future; + +namespace CesiumImpl { +// Begin omitting doxgen warnings for Impl namespace +//! @cond Doxygen_Suppress + +template struct ContinuationFutureType { + using type = Future::type>::type>; +}; + +template +using ContinuationFutureType_t = typename ContinuationFutureType::type; + +//! @endcond +// End omitting doxgen warnings for Impl namespace +} // namespace CesiumImpl +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/ContinuationReturnType.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/ContinuationReturnType.h new file mode 100644 index 0000000..9bc9388 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/ContinuationReturnType.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace CesiumAsync { +namespace CesiumImpl { +// Begin omitting doxgen warnings for Impl namespace +//! @cond Doxygen_Suppress + +template struct ContinuationReturnType { + using type = typename std::invoke_result::type; +}; + +template struct ContinuationReturnType { + using type = typename std::invoke_result::type; +}; + +//! @endcond +// End omitting doxgen warnings for Impl namespace +} // namespace CesiumImpl +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/ImmediateScheduler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/ImmediateScheduler.h new file mode 100644 index 0000000..3663f4a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/ImmediateScheduler.h @@ -0,0 +1,97 @@ +#pragma once + +#include "cesium-async++.h" + +#include + +#include + +namespace CesiumAsync { +// Begin omitting doxygen warnings for Impl namespace +//! @cond Doxygen_Suppress +namespace CesiumImpl { + +template class ImmediateScheduler { +public: + explicit ImmediateScheduler(TScheduler* pScheduler) noexcept + : _pScheduler(pScheduler) {} + + void schedule(async::task_run_handle t) { + // Are we already in a suitable thread? + std::vector& inSuitable = + ImmediateScheduler::getSchedulersCurrentlyDispatching(); + if (std::find(inSuitable.begin(), inSuitable.end(), this->_pScheduler) != + inSuitable.end()) { + // Yes, run this task directly. + t.run(); + } else { + // No, schedule this task with the deferred scheduler. + this->_pScheduler->schedule(std::move(t)); + } + } + + class SchedulerScope { + public: + SchedulerScope(TScheduler* pScheduler = nullptr) : _pScheduler(pScheduler) { + if (this->_pScheduler) { + std::vector& inSuitable = + ImmediateScheduler::getSchedulersCurrentlyDispatching(); + inSuitable.push_back(this->_pScheduler); + } + } + + ~SchedulerScope() noexcept { this->reset(); } + + SchedulerScope(SchedulerScope&& rhs) noexcept + : _pScheduler(rhs._pScheduler) { + rhs._pScheduler = nullptr; + } + + SchedulerScope& operator=(SchedulerScope&& rhs) noexcept { + std::swap(this->_pScheduler, rhs._pScheduler); + return *this; + } + + void reset() noexcept { + if (this->_pScheduler) { + std::vector& inSuitable = + ImmediateScheduler::getSchedulersCurrentlyDispatching(); + CESIUM_ASSERT(!inSuitable.empty()); + CESIUM_ASSERT(inSuitable.back() == this->_pScheduler); + inSuitable.pop_back(); + + this->_pScheduler = nullptr; + } + } + + SchedulerScope(const SchedulerScope&) = delete; + SchedulerScope& operator=(const SchedulerScope&) = delete; + + private: + TScheduler* _pScheduler; + }; + + SchedulerScope scope() { return SchedulerScope(this->_pScheduler); } + +private: + TScheduler* _pScheduler; + + // If a TScheduler instance is found in this thread-local vector, then the + // current thread has been dispatched by this scheduler and therefore we can + // dispatch immediately. + static std::vector& + getSchedulersCurrentlyDispatching() noexcept { + // We're using a static local here rather than a static field because, on + // at least some Linux systems (mine), with Clang 12, in a Debug build, a + // thread_local static field causes a SEGFAULT on access. + // I don't understand why (despite hours trying), but making it a static + // local instead solves the problem and is arguably cleaner, anyway. + static thread_local std::vector schedulersCurrentlyDispatching; + return schedulersCurrentlyDispatching; + } +}; +//! @endcond +// End omitting doxygen warnings for Impl namespace + +} // namespace CesiumImpl +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/QueuedScheduler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/QueuedScheduler.h new file mode 100644 index 0000000..218527a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/QueuedScheduler.h @@ -0,0 +1,95 @@ +#pragma once + +#include "ImmediateScheduler.h" +#include "cesium-async++.h" + +#include + +namespace CesiumAsync { +// Begin omitting doxygen warnings for Impl namespace +//! @cond Doxygen_Suppress +namespace CesiumImpl { + +class QueuedScheduler { +public: + QueuedScheduler(); + ~QueuedScheduler(); + + void schedule(async::task_run_handle t); + void dispatchQueuedContinuations(); + bool dispatchZeroOrOneContinuation(); + + template T dispatchUntilTaskCompletes(async::task&& task) { + // Set up a continuation to unblock the blocking dispatch when this task + // completes. + // + // We use the `isDone` flag as the loop termination condition to + // avoid a race condition that can lead to a deadlock. If we used + // `unblockTask.ready()` as the termination condition instead, then it's + // possible for events to happen as follows: + // + // 1. The original `task` completes in a worker thread and the `unblockTask` + // continuation is invoked immediately in the same thread. + // 2. The unblockTask continuation calls `unblock`, which terminates the + // `wait` on the condition variable in the main thread. + // 3. The main thread resumes and the while loop in this function spins back + // around and evaluates `unblockTask.ready()`. This returns false because + // the unblockTask continuation has not actually finished running in the + // worker thread yet. The main thread starts waiting on the condition + // variable again. + // 4. The `unblockTask` continuation finally finishes, making + // `unblockTask.ready()` return true, but it's too late. The main thread is + // already waiting on the condition variable. + // + // By setting the atomic `isDone` flag before calling `unblock`, we ensure + // that the loop termination condition is satisfied before the main thread + // is awoken, avoiding the potential deadlock. + + std::atomic isDone = false; + async::task unblockTask = task.then( + async::inline_scheduler(), + [this, &isDone](async::task&& task) { + isDone = true; + this->unblock(); + return task.get(); + }); + + while (!isDone) { + this->dispatchInternal(true); + } + + return std::move(unblockTask).get(); + } + + template + T dispatchUntilTaskCompletes(const async::shared_task& task) { + // Set up a continuation to unblock the blocking dispatch when this task + // completes. This case is simpler than the one above because a SharedFuture + // supports multiple continuations. We can use readiness of the _original_ + // task to terminate the loop while unblocking in a separate continuation + // guaranteed to run only after that termination condition is satisfied. + async::task unblockTask = task.then( + async::inline_scheduler(), + [this](const async::shared_task&) { this->unblock(); }); + + while (!task.ready()) { + this->dispatchInternal(true); + } + + return task.get(); + } + + ImmediateScheduler immediate{this}; + +private: + bool dispatchInternal(bool blockIfNoTasks); + void unblock(); + + struct Impl; + std::unique_ptr _pImpl; +}; +//! @endcond +// End omitting doxygen warnings for Impl namespace + +} // namespace CesiumImpl +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/RemoveFuture.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/RemoveFuture.h new file mode 100644 index 0000000..dc93a4b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/RemoveFuture.h @@ -0,0 +1,45 @@ +#pragma once + +#include "cesium-async++.h" + +namespace CesiumAsync { + +template class Future; +template class SharedFuture; + +namespace CesiumImpl { +// Begin omitting doxgen warnings for Impl namespace +//! @cond Doxygen_Suppress + +template struct RemoveFuture { + typedef T type; +}; +template struct RemoveFuture> { + typedef T type; +}; +template struct RemoveFuture> { + typedef T type; +}; +template struct RemoveFuture> { + typedef T type; +}; +template struct RemoveFuture> { + typedef T type; +}; +template struct RemoveFuture> { + typedef T type; +}; +template struct RemoveFuture> { + typedef T type; +}; +template struct RemoveFuture> { + typedef T type; +}; +template struct RemoveFuture> { + typedef T type; +}; + +//! @endcond +// End omitting doxgen warnings for Impl namespace +} // namespace CesiumImpl +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/TaskScheduler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/TaskScheduler.h new file mode 100644 index 0000000..d12e61f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/TaskScheduler.h @@ -0,0 +1,27 @@ +#pragma once + +#include "../ITaskProcessor.h" +#include "ImmediateScheduler.h" + +#include + +namespace CesiumAsync { +namespace CesiumImpl { + +// Begin omitting doxygen warnings for Impl namespace +//! @cond Doxygen_Suppress +class TaskScheduler { +public: + TaskScheduler(const std::shared_ptr& pTaskProcessor); + void schedule(async::task_run_handle t); + + ImmediateScheduler immediate{this}; + +private: + std::shared_ptr _pTaskProcessor; +}; +//! @endcond +// End omitting doxygen warnings for Impl namespace + +} // namespace CesiumImpl +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/WithTracing.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/WithTracing.h new file mode 100644 index 0000000..3ad5036 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/WithTracing.h @@ -0,0 +1,124 @@ +#pragma once + +#include "unwrapFuture.h" + +#include + +namespace CesiumAsync { +namespace CesiumImpl { +// Begin omitting doxgen warnings for Impl namespace +//! @cond Doxygen_Suppress + +template struct WithTracing { + template + static auto + begin([[maybe_unused]] const char* tracingName, [[maybe_unused]] Func&& f) { +#if CESIUM_TRACING_ENABLED + return + [tracingName, CESIUM_TRACE_LAMBDA_CAPTURE_TRACK()](T&& result) mutable { + CESIUM_TRACE_USE_CAPTURED_TRACK(); + if (tracingName) { + CESIUM_TRACE_BEGIN_IN_TRACK(tracingName); + } + return std::move(result); + }; +#else + return CesiumImpl::unwrapFuture(std::forward(f)); +#endif + } + + template + static auto end([[maybe_unused]] const char* tracingName, Func&& f) { +#if CESIUM_TRACING_ENABLED + return [tracingName, + f = CesiumImpl::unwrapFuture(std::forward(f)), + CESIUM_TRACE_LAMBDA_CAPTURE_TRACK()](T&& result) mutable { + CESIUM_TRACE_USE_CAPTURED_TRACK(); + if (tracingName) { + CESIUM_TRACE_END_IN_TRACK(tracingName); + } + return f(std::move(result)); + }; +#else + return CesiumImpl::unwrapFuture(std::forward(f)); +#endif + } +}; + +template struct WithTracingShared { + template + static auto + begin([[maybe_unused]] const char* tracingName, [[maybe_unused]] Func&& f) { +#if CESIUM_TRACING_ENABLED + return [tracingName, + CESIUM_TRACE_LAMBDA_CAPTURE_TRACK()](const T& result) mutable { + CESIUM_TRACE_USE_CAPTURED_TRACK(); + if (tracingName) { + CESIUM_TRACE_BEGIN_IN_TRACK(tracingName); + } + return result; + }; +#else + return CesiumImpl::unwrapSharedFuture(std::forward(f)); +#endif + } + + template + static auto end([[maybe_unused]] const char* tracingName, Func&& f) { +#if CESIUM_TRACING_ENABLED + return [tracingName, + f = CesiumImpl::unwrapSharedFuture(std::forward(f)), + CESIUM_TRACE_LAMBDA_CAPTURE_TRACK()](const T& result) mutable { + CESIUM_TRACE_USE_CAPTURED_TRACK(); + if (tracingName) { + CESIUM_TRACE_END_IN_TRACK(tracingName); + } + return f(result); + }; +#else + return CesiumImpl::unwrapSharedFuture(std::forward(f)); +#endif + } +}; + +template <> struct WithTracing { + template + static auto + begin([[maybe_unused]] const char* tracingName, [[maybe_unused]] Func&& f) { +#if CESIUM_TRACING_ENABLED + return [tracingName, CESIUM_TRACE_LAMBDA_CAPTURE_TRACK()]() mutable { + CESIUM_TRACE_USE_CAPTURED_TRACK(); + if (tracingName) { + CESIUM_TRACE_END_IN_TRACK(tracingName); + } + }; +#else + return CesiumImpl::unwrapFuture(std::forward(f)); +#endif + } + + template + static auto end([[maybe_unused]] const char* tracingName, Func&& f) { +#if CESIUM_TRACING_ENABLED + return [tracingName, + f = CesiumImpl::unwrapFuture(std::forward(f)), + CESIUM_TRACE_LAMBDA_CAPTURE_TRACK()]() mutable { + CESIUM_TRACE_USE_CAPTURED_TRACK(); + if (tracingName) { + CESIUM_TRACE_END_IN_TRACK(tracingName); + } + return f(); + }; +#else + return CesiumImpl::unwrapFuture(std::forward(f)); +#endif + } +}; + +// With a void Future, shared and non-shared are identical. +template <> struct WithTracingShared : public WithTracing {}; + +//! @endcond +// End omitting doxgen warnings for Impl namespace +} // namespace CesiumImpl +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/cesium-async++.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/cesium-async++.h new file mode 100644 index 0000000..0629b71 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/cesium-async++.h @@ -0,0 +1,16 @@ +#pragma once + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4458 4324 4702) +#endif + +#ifndef _MSC_VER +#pragma GCC diagnostic ignored "-Wshadow" +#endif + +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/unwrapFuture.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/unwrapFuture.h new file mode 100644 index 0000000..b9ac5cd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/unwrapFuture.h @@ -0,0 +1,77 @@ +#pragma once + +#include "ContinuationFutureType.h" +#include "ContinuationReturnType.h" + +namespace CesiumAsync { +namespace CesiumImpl { +// Begin omitting doxgen warnings for Impl namespace +//! @cond Doxygen_Suppress + +struct IdentityUnwrapper { + template static Func unwrap(Func&& f) { + return std::forward(f); + } + + template static Func unwrapShared(Func&& f) { + return std::forward(f); + } +}; + +template struct ParameterizedTaskUnwrapper { + template static auto unwrap(Func&& f) { + return [f = std::forward(f)](T&& t) mutable { + return f(std::move(t))._task; + }; + } + + template static auto unwrapShared(Func&& f) { + return + [f = std::forward(f)](const T& t) mutable { return f(t)._task; }; + } +}; + +struct TaskUnwrapper { + template static auto unwrap(Func&& f) { + return [f = std::forward(f)]() mutable { return f()._task; }; + } +}; + +template auto unwrapFuture(Func&& f) { + return std::conditional< + std::is_same< + typename ContinuationReturnType::type, + typename RemoveFuture< + typename ContinuationFutureType::type>::type>::value, + IdentityUnwrapper, + ParameterizedTaskUnwrapper>::type::unwrap(std::forward(f)); +} + +template auto unwrapSharedFuture(Func&& f) { + return std::conditional< + std::is_same< + typename ContinuationReturnType::type, + typename RemoveFuture< + typename ContinuationFutureType::type>::type>::value, + IdentityUnwrapper, + ParameterizedTaskUnwrapper>::type::unwrapShared(std::forward(f)); +} + +template auto unwrapFuture(Func&& f) { + return std::conditional< + std::is_same< + typename ContinuationReturnType::type, + typename RemoveFuture< + typename ContinuationFutureType::type>::type>::value, + IdentityUnwrapper, + TaskUnwrapper>::type::unwrap(std::forward(f)); +} + +template auto unwrapSharedFuture(Func&& f) { + return unwrapFuture(std::forward(f)); +} + +//! @endcond +// End omitting doxgen warnings for Impl namespace +} // namespace CesiumImpl +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Library.h new file mode 100644 index 0000000..9467f2c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes that support asynchronous operations. + * + * @mermaid-interactive{dependencies/CesiumAsync} + */ +namespace CesiumAsync {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMASYNC_BUILDING +#define CESIUMASYNC_API __declspec(dllexport) +#else +#define CESIUMASYNC_API __declspec(dllimport) +#endif +#else +#define CESIUMASYNC_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/NetworkAssetDescriptor.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/NetworkAssetDescriptor.h new file mode 100644 index 0000000..69eaaff --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/NetworkAssetDescriptor.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include + +namespace CesiumAsync { + +class AsyncSystem; + +/** + * @brief A description of an asset that can be loaded from the network using an + * {@link IAssetAccessor}. This includes a URL and any headers to be included + * in the request. + */ +struct NetworkAssetDescriptor { + /** + * @brief The URL from which this network asset is downloaded. + */ + std::string url; + + /** + * @brief The HTTP headers used in requesting this asset. + */ + std::vector headers; + + /** + * @brief Determines if this descriptor is identical to another one. + */ + bool operator==(const NetworkAssetDescriptor& rhs) const noexcept; + + /** + * @brief Request this asset from the network using the provided asset + * accessor. + * + * @param asyncSystem The async system. + * @param pAssetAccessor The asset accessor. + * @return A future that resolves to the request once it is complete. + */ + Future> loadFromNetwork( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor) const; + + /** + * @brief Request this asset from the network using the provided asset + * accessor and return the downloaded bytes. + * + * @param asyncSystem The async system. + * @param pAssetAccessor The asset accessor. + * @return A future that resolves to the downloaded bytes once the request is + * complete. + */ + Future>> loadBytesFromNetwork( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor) const; +}; + +} // namespace CesiumAsync + +/** @brief Hash implementation for \ref CesiumAsync::NetworkAssetDescriptor. */ +template <> struct std::hash { + /** @brief Returns a `size_t` hash of the provided \ref + * CesiumAsync::NetworkAssetDescriptor. */ + std::size_t + operator()(const CesiumAsync::NetworkAssetDescriptor& key) const noexcept; +}; diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Promise.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Promise.h new file mode 100644 index 0000000..69b846b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Promise.h @@ -0,0 +1,124 @@ +#pragma once + +#include "Impl/AsyncSystemSchedulers.h" +#include "Impl/cesium-async++.h" + +#include +#include + +namespace CesiumAsync { + +template class Future; + +/** + * @brief A promise that can be resolved or rejected by an asynchronous task. + * + * @tparam T The type of the object that the promise will be resolved with. + */ +template class Promise { +public: + /** + * @brief Will be called when the task completed successfully. + * + * @param value The value that was computed by the asynchronous task. + */ + void resolve(T&& value) const { this->_pEvent->set(std::move(value)); } + + /** + * @brief Will be called when the task completed successfully. + * + * @param value The value that was computed by the asynchronous task. + */ + void resolve(const T& value) const { this->_pEvent->set(value); } + + /** + * @brief Will be called when the task failed. + * + * @param error The error that caused the task to fail. + */ + template void reject(TException error) const { + this->_pEvent->set_exception(std::make_exception_ptr(error)); + } + + /** + * @brief Will be called when the task failed. + * + * @param error The error, captured with `std::current_exception`, that + * caused the task to fail. + */ + void reject(const std::exception_ptr& error) const { + this->_pEvent->set_exception(error); + } + + /** + * @brief Gets the Future that resolves or rejects when this Promise is + * resolved or rejected. + * + * This method may only be called once. + * + * @return The future. + */ + Future getFuture() const { + return Future(this->_pSchedulers, this->_pEvent->get_task()); + } + +private: + Promise( + const std::shared_ptr& pSchedulers, + const std::shared_ptr>& pEvent) noexcept + : _pSchedulers(pSchedulers), _pEvent(pEvent) {} + + std::shared_ptr _pSchedulers; + std::shared_ptr> _pEvent; + + friend class AsyncSystem; +}; + +/** + * @brief Specialization for promises that resolve to no value. + */ +template <> class Promise { +public: + /** + * @brief Will be called when the task completed successfully. + */ + void resolve() const { this->_pEvent->set(); } + + /** + * @brief Will be called when the task failed. + * + * @param error The error that caused the task to fail. + */ + template void reject(TException error) const { + this->_pEvent->set_exception(std::make_exception_ptr(error)); + } + + /** + * @brief Will be called when the task failed. + * + * @param error The error, captured with `std::current_exception`, that + * caused the task to fail. + */ + void reject(const std::exception_ptr& error) const { + this->_pEvent->set_exception(error); + } + /** + * @copydoc Promise::getFuture + */ + Future getFuture() const { + return Future(this->_pSchedulers, this->_pEvent->get_task()); + } + +private: + Promise( + const std::shared_ptr& pSchedulers, + const std::shared_ptr>& pEvent) noexcept + : _pSchedulers(pSchedulers), _pEvent(pEvent) {} + + std::shared_ptr _pSchedulers; + std::shared_ptr> _pEvent; + + friend class AsyncSystem; +}; + +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SharedAssetDepot.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SharedAssetDepot.h new file mode 100644 index 0000000..793cc30 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SharedAssetDepot.h @@ -0,0 +1,562 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace CesiumUtility { +template class SharedAsset; +} + +namespace CesiumAsync { + +/** + * @brief A depot for {@link CesiumUtility::SharedAsset} instances, which are potentially shared between multiple objects. + * + * @tparam TAssetType The type of asset stored in this depot. This should + * be derived from {@link CesiumUtility::SharedAsset}. + */ +template +class CESIUMASYNC_API SharedAssetDepot + : public CesiumUtility::ReferenceCountedThreadSafe< + SharedAssetDepot>, + public CesiumUtility::IDepotOwningAsset { +public: + /** + * @brief The maximum total byte usage of assets that have been loaded but are + * no longer needed. + * + * When cached assets are no longer needed, they're marked as + * candidates for deletion. However, this deletion doesn't actually occur + * until the total byte usage of deletion candidates exceeds this threshold. + * At that point, assets are cleaned up in the order that they were marked for + * deletion until the total dips below this threshold again. + * + * Default is 16MiB. + */ + int64_t inactiveAssetSizeLimitBytes = 16 * 1024 * 1024; + + /** + * @brief Signature for the callback function that will be called to fetch and + * create a new instance of `TAssetType` if one with the given key doesn't + * already exist in the depot. + * + * @param asyncSystem The \ref AsyncSystem used by this \ref SharedAssetDepot. + * @param pAssetAccessor The \ref IAssetAccessor used by this \ref + * SharedAssetDepot. Use this to fetch the asset. + * @param key The `TAssetKey` for the asset that should be loaded by this + * factory. + * @returns A \ref CesiumAsync::Future "Future" that resolves to a \ref + * CesiumUtility::ResultPointer "ResultPointer" containing the loaded asset, + * or any error information if the asset failed to load. + */ + using FactorySignature = + CesiumAsync::Future>( + const AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const TAssetKey& key); + + /** + * @brief Creates a new `SharedAssetDepot` using the given factory callback to + * load new assets. + * + * @param factory The factory to use to fetch and create assets that don't + * already exist in the depot. See \ref FactorySignature. + */ + SharedAssetDepot(std::function factory); + + virtual ~SharedAssetDepot(); + + /** + * @brief Gets an asset from the depot if it already exists, or creates it + * using the depot's factory if it does not. + * + * @param asyncSystem The async system. + * @param pAssetAccessor The asset accessor to use to download assets, if + * necessary. + * @param assetKey The key uniquely identifying the asset to get or create. + * @return A shared future that resolves when the asset is ready or fails. + */ + SharedFuture> getOrCreate( + const AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const TAssetKey& assetKey); + + /** + * @brief Returns the total number of distinct assets contained in this depot, + * including both active and inactive assets. + */ + size_t getAssetCount() const; + + /** + * @brief Gets the number of assets owned by this depot that are active, + * meaning that they are currently being used in one or more places. + */ + size_t getActiveAssetCount() const; + + /** + * @brief Gets the number of assets owned by this depot that are inactive, + * meaning that they are not currently being used. + */ + size_t getInactiveAssetCount() const; + + /** + * @brief Gets the total bytes used by inactive (unused) assets owned by this + * depot. + */ + int64_t getInactiveAssetTotalSizeBytes() const; + +private: + struct LockHolder; + + // Disable copy + void operator=(const SharedAssetDepot& other) = delete; + + /** + * @brief Locks the shared asset depot for thread-safe access. It will remain + * locked until the returned object is destroyed or the `unlock` method is + * called on it. + */ + LockHolder lock() const; + + /** + * @brief Marks the given asset as a candidate for deletion. + * Should only be called by {@link SharedAsset}. May be called from any thread. + * + * @param asset The asset to mark for deletion. + * @param threadOwnsDepotLock True if the calling thread already owns the + * depot lock; otherwise, false. + */ + void markDeletionCandidate(const TAssetType& asset, bool threadOwnsDepotLock) + override; + + void markDeletionCandidateUnderLock(const TAssetType& asset); + + /** + * @brief Unmarks the given asset as a candidate for deletion. + * Should only be called by {@link SharedAsset}. May be called from any thread. + * + * @param asset The asset to unmark for deletion. + * @param threadOwnsDepotLock True if the calling thread already owns the + * depot lock; otherwise, false. + */ + void unmarkDeletionCandidate( + const TAssetType& asset, + bool threadOwnsDepotLock) override; + + void unmarkDeletionCandidateUnderLock(const TAssetType& asset); + + /** + * @brief An entry for an asset owned by this depot. This is reference counted + * so that we can keep it alive during async operations. + */ + struct AssetEntry + : public CesiumUtility::ReferenceCountedThreadSafe { + AssetEntry(TAssetKey&& key_) + : CesiumUtility::ReferenceCountedThreadSafe(), + key(std::move(key_)), + pAsset(), + maybePendingAsset(), + errorsAndWarnings(), + sizeInDeletionList(0), + deletionListPointers() {} + + AssetEntry(const TAssetKey& key_) : AssetEntry(TAssetKey(key_)) {} + + /** + * @brief The unique key identifying this asset. + */ + TAssetKey key; + + /** + * @brief A pointer to the asset. This may be nullptr if the asset is still + * being loaded, or if it failed to load. + */ + std::unique_ptr pAsset; + + /** + * @brief If this asset is currently loading, this field holds a shared + * future that will resolve when the asset load is complete. This field will + * be empty if the asset finished loading, including if it failed to load. + */ + std::optional>> + maybePendingAsset; + + /** + * @brief The errors and warnings that occurred while loading this asset. + * This will not contain any errors or warnings if the asset has not + * finished loading yet. + */ + CesiumUtility::ErrorList errorsAndWarnings; + + /** + * @brief The size of this asset when it was added to the + * _deletionCandidates list. This is stored so that the exact same size can + * be subtracted later. The value of this field is undefined if the asset is + * not currently in the _deletionCandidates list. + */ + int64_t sizeInDeletionList; + + /** + * @brief The next and previous pointers to entries in the + * _deletionCandidates list. + */ + CesiumUtility::DoublyLinkedListPointers deletionListPointers; + + CesiumUtility::ResultPointer toResultUnderLock() const; + }; + + // Manages the depot's mutex. Also ensures, via IntrusivePointer, that the + // depot won't be destroyed while the lock is held. + struct LockHolder { + LockHolder( + const CesiumUtility::IntrusivePointer& pDepot); + ~LockHolder(); + void unlock(); + + private: + // These two fields _must_ be declared in this order to guarantee that the + // mutex is released before the depot pointer. Releasing the depot pointer + // could destroy the depot, and that will be disastrous if the lock is still + // held. + CesiumUtility::IntrusivePointer pDepot; + std::unique_lock lock; + }; + + // Maps asset keys to AssetEntry instances. This collection owns the asset + // entries. + std::unordered_map> + _assets; + + // Maps asset pointers to AssetEntry instances. The values in this map refer + // to instances owned by the _assets map. + std::unordered_map _assetsByPointer; + + // List of assets that are being considered for deletion, in the order that + // they became unused. + CesiumUtility::DoublyLinkedList + _deletionCandidates; + + // The total amount of memory used by all assets in the _deletionCandidates + // list. + int64_t _totalDeletionCandidateMemoryUsage; + + // Mutex serializing access to _assets, _assetsByPointer, _deletionCandidates, + // and any AssetEntry owned by this depot. + mutable std::mutex _mutex; + + // The factory used to create new AssetType instances. + std::function _factory; + + // This instance keeps a reference to itself whenever it is managing active + // assets, preventing it from being destroyed even if all other references to + // it are dropped. + CesiumUtility::IntrusivePointer> + _pKeepAlive; +}; + +template +SharedAssetDepot::SharedAssetDepot( + std::function factory) + : _assets(), + _assetsByPointer(), + _deletionCandidates(), + _totalDeletionCandidateMemoryUsage(0), + _mutex(), + _factory(std::move(factory)), + _pKeepAlive(nullptr) {} + +template +SharedAssetDepot::~SharedAssetDepot() { + // Ideally, when the depot is destroyed, all the assets it owns would become + // independent assets. But this is extremely difficult to manage in a + // thread-safe manner. + + // Since we're in the destructor, we can be sure no one has a reference to + // this instance anymore. That means that no other thread can be executing + // `getOrCreate`, and no async asset creations are in progress. + + // However, if assets owned by this depot are still alive, then other + // threads can still be calling addReference / releaseReference on some of + // our assets even while we're running the depot's destructor. Which means + // that we can end up in `markDeletionCandidate` at the same time the + // destructor is running. And in fact it's possible for a `SharedAsset` with + // especially poor timing to call into a `SharedAssetDepot` just after it is + // destroyed. + + // To avoid this, we use the _pKeepAlive field to maintain an artificial + // reference to this depot whenever it owns live assets. This should keep + // this destructor from being called except when all of its assets are also + // in the _deletionCandidates list. + + CESIUM_ASSERT(this->_assets.size() == this->_deletionCandidates.size()); +} + +template +SharedFuture> +SharedAssetDepot::getOrCreate( + const AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const TAssetKey& assetKey) { + // We need to take care here to avoid two assets starting to load before the + // first asset has added an entry and set its maybePendingAsset field. + LockHolder lock = this->lock(); + + auto existingIt = this->_assets.find(assetKey); + if (existingIt != this->_assets.end()) { + // We've already loaded (or are loading) an asset with this ID - we can + // just use that. + const AssetEntry& entry = *existingIt->second; + if (entry.maybePendingAsset) { + // Asset is currently loading. + return *entry.maybePendingAsset; + } else { + return asyncSystem.createResolvedFuture(entry.toResultUnderLock()) + .share(); + } + } + + // Calling the factory function while holding the mutex unnecessarily + // limits parallelism. It can even lead to a bug in the scenario where the + // `thenInWorkerThread` continuation is invoked immediately in the current + // thread, before `thenInWorkerThread` itself returns. That would result + // in an attempt to lock the mutex recursively, which is not allowed. + + // So we jump through some hoops here to publish "this thread is working + // on it", then unlock the mutex, and _then_ actually call the factory + // function. + Promise promise = asyncSystem.createPromise(); + + // We haven't loaded or started to load this asset yet. + // Let's do that now. + CesiumUtility::IntrusivePointer> + pDepot = this; + CesiumUtility::IntrusivePointer pEntry = new AssetEntry(assetKey); + + auto future = + promise.getFuture() + .thenImmediately([pDepot, pEntry, asyncSystem, pAssetAccessor]() { + return pDepot->_factory(asyncSystem, pAssetAccessor, pEntry->key); + }) + .catchImmediately([](std::exception&& e) { + return CesiumUtility::Result< + CesiumUtility::IntrusivePointer>( + CesiumUtility::ErrorList::error( + std::string("Error creating asset: ") + e.what())); + }) + .thenInWorkerThread( + [pDepot, + pEntry](CesiumUtility::Result< + CesiumUtility::IntrusivePointer>&& result) { + LockHolder lock = pDepot->lock(); + + if (result.pValue) { + result.pValue->_pDepot = pDepot.get(); + pDepot->_assetsByPointer[result.pValue.get()] = pEntry.get(); + } + + // Now that this asset is owned by the depot, we exclusively + // control its lifetime with a std::unique_ptr. + pEntry->pAsset = + std::unique_ptr(result.pValue.get()); + pEntry->errorsAndWarnings = std::move(result.errors); + pEntry->maybePendingAsset.reset(); + + // The asset is initially live because we have an + // IntrusivePointer to it right here. So make sure the depot + // stays alive, too. + pDepot->_pKeepAlive = pDepot; + + return pEntry->toResultUnderLock(); + }); + + SharedFuture> sharedFuture = + std::move(future).share(); + + pEntry->maybePendingAsset = sharedFuture; + + [[maybe_unused]] bool added = this->_assets.emplace(assetKey, pEntry).second; + + // Should always be added successfully, because we checked above that the + // asset key doesn't exist in the map yet. + CESIUM_ASSERT(added); + + // Unlock the mutex and then call the factory function. + lock.unlock(); + promise.resolve(); + + return sharedFuture; +} + +template +size_t SharedAssetDepot::getAssetCount() const { + LockHolder lock = this->lock(); + return this->_assets.size(); +} + +template +size_t SharedAssetDepot::getActiveAssetCount() const { + LockHolder lock = this->lock(); + return this->_assets.size() - this->_deletionCandidates.size(); +} + +template +size_t SharedAssetDepot::getInactiveAssetCount() const { + LockHolder lock = this->lock(); + return this->_deletionCandidates.size(); +} + +template +int64_t +SharedAssetDepot::getInactiveAssetTotalSizeBytes() + const { + LockHolder lock = this->lock(); + return this->_totalDeletionCandidateMemoryUsage; +} + +template +typename SharedAssetDepot::LockHolder +SharedAssetDepot::lock() const { + return LockHolder{this}; +} + +template +void SharedAssetDepot::markDeletionCandidate( + const TAssetType& asset, + bool threadOwnsDepotLock) { + if (threadOwnsDepotLock) { + this->markDeletionCandidateUnderLock(asset); + } else { + LockHolder lock = this->lock(); + this->markDeletionCandidateUnderLock(asset); + } +} + +template +void SharedAssetDepot::markDeletionCandidateUnderLock( + const TAssetType& asset) { + auto it = this->_assetsByPointer.find(const_cast(&asset)); + CESIUM_ASSERT(it != this->_assetsByPointer.end()); + if (it == this->_assetsByPointer.end()) { + return; + } + + CESIUM_ASSERT(it->second != nullptr); + + AssetEntry& entry = *it->second; + entry.sizeInDeletionList = asset.getSizeBytes(); + this->_totalDeletionCandidateMemoryUsage += entry.sizeInDeletionList; + + this->_deletionCandidates.insertAtTail(entry); + + if (this->_totalDeletionCandidateMemoryUsage > + this->inactiveAssetSizeLimitBytes) { + // Delete the deletion candidates until we're below the limit. + while (this->_deletionCandidates.size() > 0 && + this->_totalDeletionCandidateMemoryUsage > + this->inactiveAssetSizeLimitBytes) { + AssetEntry* pOldEntry = this->_deletionCandidates.head(); + this->_deletionCandidates.remove(*pOldEntry); + + this->_totalDeletionCandidateMemoryUsage -= pOldEntry->sizeInDeletionList; + + CESIUM_ASSERT( + pOldEntry->pAsset == nullptr || + pOldEntry->pAsset->_referenceCount == 0); + + if (pOldEntry->pAsset) { + this->_assetsByPointer.erase(pOldEntry->pAsset.get()); + } + + // This will actually delete the asset. + this->_assets.erase(pOldEntry->key); + } + } + + // If this depot is not managing any live assets, then we no longer need to + // keep it alive. + if (this->_assets.size() == this->_deletionCandidates.size()) { + this->_pKeepAlive.reset(); + } +} + +template +void SharedAssetDepot::unmarkDeletionCandidate( + const TAssetType& asset, + bool threadOwnsDepotLock) { + if (threadOwnsDepotLock) { + this->unmarkDeletionCandidateUnderLock(asset); + } else { + LockHolder lock = this->lock(); + this->unmarkDeletionCandidateUnderLock(asset); + } +} + +template +void SharedAssetDepot::unmarkDeletionCandidateUnderLock( + const TAssetType& asset) { + auto it = this->_assetsByPointer.find(const_cast(&asset)); + CESIUM_ASSERT(it != this->_assetsByPointer.end()); + if (it == this->_assetsByPointer.end()) { + return; + } + + CESIUM_ASSERT(it->second != nullptr); + + AssetEntry& entry = *it->second; + bool isFound = this->_deletionCandidates.contains(entry); + + CESIUM_ASSERT(isFound); + + if (isFound) { + this->_totalDeletionCandidateMemoryUsage -= entry.sizeInDeletionList; + this->_deletionCandidates.remove(entry); + } + + // This depot is now managing at least one live asset, so keep it alive. + this->_pKeepAlive = this; +} + +template +CesiumUtility::ResultPointer +SharedAssetDepot::AssetEntry::toResultUnderLock() const { + // This method is called while the calling thread already owns the depot + // mutex. So we must take care not to lock it again, which could happen if + // the asset is currently unreferenced and we naively create an + // IntrusivePointer for it. + CesiumUtility::IntrusivePointer p = nullptr; + if (pAsset) { + pAsset->addReference(true); + p = pAsset.get(); + pAsset->releaseReference(true); + } + return CesiumUtility::ResultPointer(p, errorsAndWarnings); +} + +template +SharedAssetDepot::LockHolder::LockHolder( + const CesiumUtility::IntrusivePointer& pDepot_) + : pDepot(pDepot_), lock(pDepot_->_mutex) {} + +template +SharedAssetDepot::LockHolder::~LockHolder() = default; + +template +void SharedAssetDepot::LockHolder::unlock() { + this->lock.unlock(); +} + +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SharedFuture.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SharedFuture.h new file mode 100644 index 0000000..530bfe9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SharedFuture.h @@ -0,0 +1,345 @@ +#pragma once + +#include "Impl/AsyncSystemSchedulers.h" +#include "Impl/CatchFunction.h" +#include "Impl/ContinuationFutureType.h" +#include "Impl/WithTracing.h" +#include "ThreadPool.h" + +#include + +#include +#include + +namespace CesiumAsync { + +namespace CesiumImpl { + +template struct ParameterizedTaskUnwrapper; +struct TaskUnwrapper; + +} // namespace CesiumImpl + +/** + * @brief A value that will be available in the future, as produced by + * {@link AsyncSystem}. Unlike {@link Future}, a `SharedFuture` allows + * multiple continuations to be attached, and allows {@link SharedFuture::wait} + * to be called multiple times. + * + * @tparam T The type of the value. + */ +template class SharedFuture final { +public: + /** + * @brief Registers a continuation function to be invoked in a worker thread + * when this Future resolves. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * If this Future is resolved from a designated worker thread, the + * continuation function will be invoked immediately rather than in a + * separate task. Similarly, if the Future is already resolved when + * `thenInWorkerThread` is called from a designated worker thread, the + * continuation function will be invoked immediately before this + * method returns. + * + * @tparam Func The type of the function. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template + CesiumImpl::ContinuationFutureType_t thenInWorkerThread(Func&& f) { + return this->thenWithScheduler( + this->_pSchedulers->workerThread.immediate, + "waiting for worker thread", + std::forward(f)); + } + + /** + * @brief Registers a continuation function to be invoked in the main thread + * when this Future resolves. + * + * If this Future is resolved from the main thread, the + * continuation function will be invoked immediately rather than queued for + * later execution in the main thread. Similarly, if the Future is already + * resolved when `thenInMainThread` is called from the main thread, the + * continuation function will be invoked immediately before this + * method returns. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * @tparam Func The type of the function. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template + CesiumImpl::ContinuationFutureType_t thenInMainThread(Func&& f) { + return this->thenWithScheduler( + this->_pSchedulers->mainThread.immediate, + "waiting for main thread", + std::forward(f)); + } + + /** + * @brief Registers a continuation function to be invoked immediately in + * whichever thread causes the Future to be resolved. + * + * If the Future is already resolved, the supplied function will be called + * immediately in the calling thread and this method will not return until + * that function does. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * @tparam Func The type of the function. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template + CesiumImpl::ContinuationFutureType_t thenImmediately(Func&& f) { + return CesiumImpl::ContinuationFutureType_t( + this->_pSchedulers, + _task.then( + async::inline_scheduler(), + CesiumImpl::WithTracingShared::end( + nullptr, + std::forward(f)))); + } + + /** + * @brief Registers a continuation function to be invoked in a thread pool + * when this Future resolves. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * If this Future is resolved from a thread pool thread, the + * continuation function will be invoked immediately rather than in a + * separate task. Similarly, if the Future is already resolved when + * `thenInThreadPool` is called from a designated thread pool thread, the + * continuation function will be invoked immediately before this + * method returns. + * + * @tparam Func The type of the function. + * @param threadPool The thread pool where this function will be invoked. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template + CesiumImpl::ContinuationFutureType_t + thenInThreadPool(const ThreadPool& threadPool, Func&& f) { + return this->thenWithScheduler( + threadPool._pScheduler->immediate, + "waiting for thread pool thread", + std::forward(f)); + } + + /** + * @brief Registers a continuation function to be invoked in the main thread + * when this Future rejects. + * + * If this Future is rejected from the main thread, the + * continuation function will be invoked immediately rather than queued for + * later execution in the main thread. Similarly, if the Future is already + * rejected when `catchInMainThread` is called from the main thread, the + * continuation function will be invoked immediately before this + * method returns. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * Any `then` continuations chained after this one will be invoked with the + * return value of the catch callback. + * + * @tparam Func The type of the function. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template Future catchInMainThread(Func&& f) { + return this->catchWithScheduler( + this->_pSchedulers->mainThread.immediate, + std::forward(f)); + } + + /** + * @brief Registers a continuation function to be invoked immediately, and + * invalidates this Future. + * + * When this Future is rejected, the continuation function will be invoked + * in whatever thread does the rejection. Similarly, if the Future is already + * rejected when `catchImmediately` is called, the continuation function will + * be invoked immediately before this method returns. + * + * If the function itself returns a `Future`, the function will not be + * considered complete until that returned `Future` also resolves. + * + * Any `then` continuations chained after this one will be invoked with the + * return value of the catch callback. + * + * @tparam Func The type of the function. + * @param f The function. + * @return A future that resolves after the supplied function completes. + */ + template Future catchImmediately(Func&& f) { + return this->catchWithScheduler( + async::inline_scheduler(), + std::forward(f)); + } + + /** + * @brief Passes through one or more additional values to the next + * continuation. + * + * The next continuation will receive a tuple with each of the provided + * values, followed by the result of the current Future. + * + * @tparam TPassThrough The types to pass through to the next continuation. + * @param values The values to pass through to the next continuation. + * @return A new Future that resolves to a tuple with the pass-through values, + * followed by the result of the last Future. + */ + template + Future> + thenPassThrough(TPassThrough&&... values) { + return this->thenImmediately( + [values = std::tuple(std::forward(values)...)]( + const T& result) mutable { + return std::tuple_cat(std::move(values), std::make_tuple(result)); + }); + } + + /** + * @brief Waits for the future to resolve or reject and returns the result. + * + * \attention This method must not be called from the main thread, the one + * that calls {@link AsyncSystem::dispatchMainThreadTasks}. Doing so can lead to a + * deadlock because the main thread tasks will never complete while this + * method is blocking the main thread. + * + * To wait in the main thread, use {@link waitInMainThread} instead. + * + * @return The value if the future resolves successfully. + * @throws An exception if the future rejected. + */ + template < + typename U = T, + std::enable_if_t, int> = 0, + std::enable_if_t, int> = 0> + const U& wait() const { + return this->_task.get(); + } + + /** + * @brief Waits for the future to resolve or reject. + * + * \attention This method must not be called from the main thread, the one + * that calls {@link AsyncSystem::dispatchMainThreadTasks}. Doing so can lead to a + * deadlock because the main thread tasks will never complete while this + * method is blocking the main thread. + * + * To wait in the main thread, use {@link waitInMainThread} instead. + * + * @throws An exception if the future rejected. + */ + template < + typename U = T, + std::enable_if_t, int> = 0, + std::enable_if_t, int> = 0> + void wait() const { + this->_task.get(); + } + + /** + * @brief Waits for this future to resolve or reject in the main thread while + * also processing main-thread tasks. + * + * This method must be called from the main thread. + * + * The function does not return until {@link Future::isReady} returns true. + * In the meantime, main-thread tasks are processed as necessary. This method + * does not spin wait; it suspends the calling thread by waiting on a + * condition variable when there is no work to do. + * + * @return The value if the future resolves successfully. + * @throws An exception if the future rejected. + */ + T waitInMainThread() { + return this->_pSchedulers->mainThread.dispatchUntilTaskCompletes( + std::move(this->_task)); + } + + /** + * @brief Determines if this future is already resolved or rejected. + * + * If this method returns true, it is guaranteed that {@link wait} will + * not block but will instead immediately return a value or throw an + * exception. + * + * @return True if the future is already resolved or rejected and {@link wait} + * will not block; otherwise, false. + */ + bool isReady() const { return this->_task.ready(); } + +private: + SharedFuture( + const std::shared_ptr& pSchedulers, + async::shared_task&& task) noexcept + : _pSchedulers(pSchedulers), _task(std::move(task)) {} + + template + CesiumImpl::ContinuationFutureType_t + thenWithScheduler(Scheduler& scheduler, const char* tracingName, Func&& f) { + // It would be nice if tracingName were a template parameter instead of a + // function parameter, but that triggers a bug in VS2017. It was previously + // a bug in VS2019, too, but has been fixed there: + // https://developercommunity.visualstudio.com/t/internal-compiler-error-when-compiling-a-template-1/534210 +#if CESIUM_TRACING_ENABLED + // When tracing is enabled, we measure the time between scheduling and + // dispatching of the work. + auto task = this->_task.then( + async::inline_scheduler(), + CesiumImpl::WithTracingShared::begin( + tracingName, + std::forward(f))); +#else + auto& task = this->_task; +#endif + + return CesiumImpl::ContinuationFutureType_t( + this->_pSchedulers, + task.then( + scheduler, + CesiumImpl::WithTracingShared::end( + tracingName, + std::forward(f)))); + } + + template + CesiumImpl::ContinuationFutureType_t + catchWithScheduler(Scheduler& scheduler, Func&& f) { + return CesiumImpl::ContinuationFutureType_t( + this->_pSchedulers, + this->_task.then( + async::inline_scheduler(), + CesiumImpl:: + CatchFunction&>{ + scheduler, + std::forward(f)})); + } + + std::shared_ptr _pSchedulers; + async::shared_task _task; + + friend class AsyncSystem; + + template friend struct CesiumImpl::ParameterizedTaskUnwrapper; + + friend struct CesiumImpl::TaskUnwrapper; + + template friend class Future; + template friend class SharedFuture; +}; + +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SqliteCache.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SqliteCache.h new file mode 100644 index 0000000..5b31161 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SqliteCache.h @@ -0,0 +1,64 @@ +#pragma once + +#include "ICacheDatabase.h" + +#include + +#include +#include +#include +#include + +namespace CesiumAsync { + +/** + * @brief Cache storage using SQLITE to store completed response. + */ +class CESIUMASYNC_API SqliteCache : public ICacheDatabase { +public: + /** + * @brief Constructs a new instance with a given `databaseName` pointing to a + * database. + * + * The instance will connect to the existing database or create a new one if + * it doesn't exist + * + * @param pLogger The logger that receives error messages. + * @param databaseName the database path. + * @param maxItems the maximum number of items should be kept in the database + * after prunning. + */ + SqliteCache( + const std::shared_ptr& pLogger, + const std::string& databaseName, + uint64_t maxItems = 4096); + ~SqliteCache(); + + /** @copydoc ICacheDatabase::getEntry*/ + virtual std::optional + getEntry(const std::string& key) const override; + + /** @copydoc ICacheDatabase::storeEntry*/ + virtual bool storeEntry( + const std::string& key, + std::time_t expiryTime, + const std::string& url, + const std::string& requestMethod, + const HttpHeaders& requestHeaders, + uint16_t statusCode, + const HttpHeaders& responseHeaders, + const std::span& responseData) override; + + /** @copydoc ICacheDatabase::prune*/ + virtual bool prune() override; + + /** @copydoc ICacheDatabase::clearAll*/ + virtual bool clearAll() override; + +private: + struct Impl; + std::unique_ptr _pImpl; + void createConnection() const; + void destroyDatabase(); +}; +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SqliteHelper.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SqliteHelper.h new file mode 100644 index 0000000..bfc40b6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SqliteHelper.h @@ -0,0 +1,62 @@ +#pragma once + +#include "cesium-sqlite3.h" + +#include +#include + +struct CESIUM_SQLITE(sqlite3); +struct CESIUM_SQLITE(sqlite3_stmt); + +namespace CesiumAsync { + +/** + * @brief A deleter that can be used with `std::unique_ptr` to properly destroy + * a SQLite connection when it is no longer needed. + */ +struct DeleteSqliteConnection { + /** @brief Closes the provided sqlite connection when called. */ + void operator()(CESIUM_SQLITE(sqlite3*) pConnection) noexcept; +}; + +/** + * @brief A deleter that can be used with `std::unique_ptr` to properly destroy + * a SQLite prepared statement when it is no longer needed. + */ +struct DeleteSqliteStatement { + /** @brief Finalizes the provided sqlite statement when called. */ + void operator()(CESIUM_SQLITE(sqlite3_stmt*) pStatement) noexcept; +}; + +/** + * @brief A `std::unique_ptr` that will properly delete the connection + * using the SQLite API. + */ +using SqliteConnectionPtr = + std::unique_ptr; + +/** + * @brief A `std::unique_ptr` that will properly delete the + * statement using the SQLite API. + */ +using SqliteStatementPtr = + std::unique_ptr; + +/** + * @brief Helper functions for working with SQLite. + */ +struct SqliteHelper { + /** + * @brief Create a prepared statement. + * + * @param pConnection The SQLite connection in which to create the prepared + * statement. + * @param sql The SQL text for the statement. + * @return The created prepared statement. + */ + static SqliteStatementPtr prepareStatement( + const SqliteConnectionPtr& pConnection, + const std::string& sql); +}; + +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/ThreadPool.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/ThreadPool.h new file mode 100644 index 0000000..ecccbc0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/ThreadPool.h @@ -0,0 +1,56 @@ +#pragma once + +#include "Impl/ImmediateScheduler.h" +#include "Impl/cesium-async++.h" +#include "Library.h" + +#include + +namespace CesiumAsync { + +/** + * @brief A thread pool created by {@link AsyncSystem::createThreadPool}. + * + * This object has no public methods, but can be used with + * {@link AsyncSystem::runInThreadPool} and + * {@link Future::thenInThreadPool}. + */ +class CESIUMASYNC_API ThreadPool { +public: + /** + * @brief Creates a new thread pool with the given number of threads. + * + * @param numberOfThreads The number of threads to create in this ThreadPool. + */ + ThreadPool(int32_t numberOfThreads); + +private: + struct Scheduler { + Scheduler(int32_t numberOfThreads); + void schedule(async::task_run_handle t); + + CesiumImpl::ImmediateScheduler immediate{this}; + + async::threadpool_scheduler scheduler; + }; + + static auto createPreRun(ThreadPool::Scheduler* pScheduler) { + return + [pScheduler]() { ThreadPool::_scope = pScheduler->immediate.scope(); }; + } + + static auto createPostRun() noexcept { + return []() noexcept { ThreadPool::_scope.reset(); }; + } + + static thread_local CesiumImpl::ImmediateScheduler::SchedulerScope + _scope; + + std::shared_ptr _pScheduler; + + template friend class Future; + template friend class SharedFuture; + friend class AsyncSystem; +}; + +} // namespace CesiumAsync diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/cesium-sqlite3.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/cesium-sqlite3.h new file mode 100644 index 0000000..6435507 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/cesium-sqlite3.h @@ -0,0 +1,7 @@ +#pragma once + +#if PRIVATE_CESIUM_SQLITE +#define CESIUM_SQLITE(name) cesium_##name +#else +#define CESIUM_SQLITE(name) name +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Availability.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Availability.h new file mode 100644 index 0000000..2db0585 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Availability.h @@ -0,0 +1,213 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace CesiumGeometry { + +namespace AvailabilityUtilities { +uint8_t countOnesInByte(uint8_t _byte); +uint32_t countOnesInBuffer(std::span buffer); +} // namespace AvailabilityUtilities + +/** + * @brief An availability value that is a constant boolean value. + */ +struct CESIUMGEOMETRY_API ConstantAvailability { + /** + * @brief The constant value. + */ + bool constant; +}; + +/** + * @brief An availability value that needs to be obtained using an offset into a + * buffer. + */ +struct CESIUMGEOMETRY_API SubtreeBufferView { + /** + * @brief The offset into the buffer to read from. + */ + uint32_t byteOffset; + /** + * @brief The number of bytes after the offset to read until. + */ + uint32_t byteLength; + /** + * @brief The index into \ref AvailabilitySubtree::buffers that this \ref + * SubtreeBufferView corresponds to. + */ + uint8_t buffer; +}; + +/** + * @brief A view into availability information for part of the availability + * tree. This could be either a constant boolean value or a descriptor pointing + * to a buffer in an \ref AvailabilitySubtree where the information will be + * looked up. + * + * Instead of using this type directly, \ref AvailabilityAccessor can be used to + * work with it safely. + */ +typedef std::variant AvailabilityView; + +/** + * @brief The subtree data for an \ref AvailabilityNode, containing information + * on tile, content, and subtree availability. + */ +struct CESIUMGEOMETRY_API AvailabilitySubtree { + /** + * @brief The availability information corresponding to \ref + * TileAvailabilityFlags::TILE_AVAILABLE. + */ + AvailabilityView tileAvailability; + /** + * @brief The availability information corresponding to \ref + * TileAvailabilityFlags::CONTENT_AVAILABLE. + */ + AvailabilityView contentAvailability; + /** + * @brief The availability information corresponding to \ref + * TileAvailabilityFlags::SUBTREE_AVAILABLE and \ref + * TileAvailabilityFlags::SUBTREE_LOADED. + */ + AvailabilityView subtreeAvailability; + /** + * @brief Subtree buffers that may be referenced by a \ref SubtreeBufferView. + */ + std::vector> buffers; +}; + +/** + * @brief Availability nodes wrap \ref AvailabilitySubtree objects and link them + * together to form a downwardly traversable availability tree. + */ +struct CESIUMGEOMETRY_API AvailabilityNode { + /** + * @brief The subtree data for this node. + * + * If a node exists but its subtree does not exist, it indicates that the + * subtree is known to be available and is actively in the process of loading. + */ + std::optional subtree; + + /** + * @brief The child nodes for this subtree node. + */ + std::vector> childNodes; + + /** + * @brief Creates an empty instance; + */ + AvailabilityNode() noexcept; + + /** + * @brief Sets the loaded subtree for this availability node. + * + * @param subtree_ The loaded subtree to set for this node. + * @param maxChildrenSubtrees The maximum number of children this subtree + * could possible have if all of them happen to be available. + */ + void setLoadedSubtree( + AvailabilitySubtree&& subtree_, + uint32_t maxChildrenSubtrees) noexcept; +}; + +/** + * @brief A downwardly-traversable tree of \ref AvailabilityNode objects. + */ +struct CESIUMGEOMETRY_API AvailabilityTree { + /** + * @brief The root \ref AvailabilityNode of this tree. + */ + std::unique_ptr pRoot; +}; + +/** + * @brief Accessor for use with \ref AvailabilityView in order to safely obtain + * the contents of the view. + */ +class CESIUMGEOMETRY_API AvailabilityAccessor { +public: + /** + * @brief Creates a new AvailabilityAccessor. + * + * @param view The view whose contents will be accessed by this accessor. + * @param subtree The subtree that corresponds to the view. + */ + AvailabilityAccessor( + const AvailabilityView& view, + const AvailabilitySubtree& subtree) noexcept; + + /** + * @brief Is this \ref AvailabilityAccessor accessing a \ref + * SubtreeBufferView? + * + * @returns True if the \ref AvailabilityView is a \ref SubtreeBufferView with + * a valid index, offset, and length, or false otherwise. + */ + bool isBufferView() const noexcept { + return pBufferView != nullptr && bufferAccessor; + } + + /** + * @brief Is this \ref AvailabilityAccessor accessing a \ref + * ConstantAvailability? + * + * @returns True if the \ref AvailabilityView is a \ref ConstantAvailability, + * false otherwise. + */ + bool isConstant() const noexcept { return pConstant != nullptr; } + + /** + * @brief Obtains the constant value of the \ref AvailabilityView. + * + * @warning Unsafe to use if isConstant is false. + * @returns The constant value. + */ + bool getConstant() const { return pConstant->constant; } + + /** + * @brief Obtains an accessor to the buffer used by the \ref AvailabilityView. + * + * @warning Unsafe to use if isBufferView is false. + * @returns A reference to the span representing the range of the buffer + * specified by the \ref SubtreeBufferView. + */ + const std::span& getBufferAccessor() const { + return *bufferAccessor; + } + + /** + * @brief Obtains the byte at the given index from the buffer used by the \ref + * AvailabilityView. + * + * @warning Unsafe to use if isBufferView is false. + * @returns The byte at the given index of the buffer accessor. + */ + const std::byte& operator[](size_t i) const { + return bufferAccessor.value()[i]; + } + + /** + * @brief Obtains the size of the buffer used by the \ref AvailabilityView. + * + * @warning Unsafe to use if isBufferView is false. + * @returns The \ref SubtreeBufferView::byteLength "byteLength" property of + * the \ref SubtreeBufferView. + */ + size_t size() const { return pBufferView->byteLength; } + +private: + const SubtreeBufferView* pBufferView; + const ConstantAvailability* pConstant; + std::optional> bufferAccessor; +}; +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Axis.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Axis.h new file mode 100644 index 0000000..dd7cdd3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Axis.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Library.h" + +namespace CesiumGeometry { + +/** + * @brief An enum describing the x, y, and z axes + */ +enum class CESIUMGEOMETRY_API Axis { + /** + * @brief The x-axis + */ + X, + + /** + * @brief The y-axis + */ + Y, + + /** + * @brief The z-axis + */ + Z +}; +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/AxisAlignedBox.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/AxisAlignedBox.h new file mode 100644 index 0000000..54a1e1e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/AxisAlignedBox.h @@ -0,0 +1,125 @@ +#pragma once + +#include "Library.h" + +#include + +namespace CesiumGeometry { + +/** + * @brief An Axis-Aligned Bounding Box (AABB), where the axes of the box are + * aligned with the axes of the coordinate system. + */ +struct CESIUMGEOMETRY_API AxisAlignedBox final { + + /** + * @brief Creates an empty AABB with a length, width, and height of zero, + * with the center located at (0, 0, 0). + */ + constexpr AxisAlignedBox() noexcept + : minimumX(0.0), + minimumY(0.0), + minimumZ(0.0), + maximumX(0.0), + maximumY(0.0), + maximumZ(0.0), + lengthX(0.0), + lengthY(0.0), + lengthZ(0.0), + center(0.0) {} + + /** + * @brief Creates a new AABB using the range of coordinates the box covers. + * + * @param minimumX_ The minimum X coordinate within the box. + * @param minimumY_ The minimum Y coordinate within the box. + * @param minimumZ_ The minimum Z coordinate within the box. + * @param maximumX_ The maximum X coordinate within the box. + * @param maximumY_ The maximum Y coordinate within the box. + * @param maximumZ_ The maximum Z coordinate within the box. + */ + constexpr AxisAlignedBox( + double minimumX_, + double minimumY_, + double minimumZ_, + double maximumX_, + double maximumY_, + double maximumZ_) noexcept + : minimumX(minimumX_), + minimumY(minimumY_), + minimumZ(minimumZ_), + maximumX(maximumX_), + maximumY(maximumY_), + maximumZ(maximumZ_), + lengthX(maximumX - minimumX), + lengthY(maximumY - minimumY), + lengthZ(maximumZ - minimumZ), + center( + 0.5 * (maximumX + minimumX), + 0.5 * (maximumY + minimumY), + 0.5 * (maximumZ + minimumZ)) {} + + /** + * @brief The minimum x-coordinate. + */ + double minimumX; + + /** + * @brief The minimum y-coordinate. + */ + double minimumY; + + /** + * @brief The minimum z-coordinate. + */ + double minimumZ; + + /** + * @brief The maximum x-coordinate. + */ + double maximumX; + + /** + * @brief The maximum y-coordinate. + */ + double maximumY; + + /** + * @brief The maximum z-coordinate. + */ + double maximumZ; + + /** + * @brief The length of the box on the x-axis. + */ + double lengthX; + + /** + * @brief The length of the box on the y-axis. + */ + double lengthY; + + /** + * @brief The length of the box on the z-axis. + */ + double lengthZ; + + /** + * @brief The center of the box. + */ + glm::dvec3 center; + + /** + * @brief Checks if this AABB contains the given position. + * + * @param position The position to check. + * @returns True if this AABB contains the position, false otherwise. + */ + constexpr bool contains(const glm::dvec3& position) const noexcept { + return position.x >= this->minimumX && position.x <= this->maximumX && + position.y >= this->minimumY && position.y <= this->maximumY && + position.z >= this->minimumZ && position.z <= this->maximumZ; + } +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/BoundingSphere.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/BoundingSphere.h new file mode 100644 index 0000000..852f496 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/BoundingSphere.h @@ -0,0 +1,91 @@ +#pragma once + +#include "CullingResult.h" +#include "Library.h" + +#include +#include + +namespace CesiumGeometry { + +class Plane; + +/** + * @brief A bounding sphere with a center and a radius. + */ +class CESIUMGEOMETRY_API BoundingSphere final { +public: + /** + * @brief Construct a new instance. + * + * @param center The center of the bounding sphere. + * @param radius The radius of the bounding sphere. + */ + constexpr BoundingSphere(const glm::dvec3& center, double radius) noexcept + : _center(center), _radius(radius) {} + + /** + * @brief Gets the center of the bounding sphere. + */ + constexpr const glm::dvec3& getCenter() const noexcept { + return this->_center; + } + + /** + * @brief Gets the radius of the bounding sphere. + */ + constexpr double getRadius() const noexcept { return this->_radius; } + + /** + * @brief Determines on which side of a plane this boundings sphere is + * located. + * + * @param plane The plane to test against. + * @return The {@link CullingResult}: + * * `Inside` if the entire sphere is on the side of the plane the normal is + * pointing. + * * `Outside` if the entire sphere is on the opposite side. + * * `Intersecting` if the sphere intersects the plane. + */ + CullingResult intersectPlane(const Plane& plane) const noexcept; + + /** + * @brief Computes the distance squared from a position to the closest point + * on this bounding sphere. Returns 0 if the point is inside the sphere. + * + * @param position The position. + * @return The distance squared from the position to the closest point on this + * bounding sphere. + * + * @snippet TestBoundingSphere.cpp distanceSquaredTo + */ + double + computeDistanceSquaredToPosition(const glm::dvec3& position) const noexcept; + + /** + * @brief Computes whether the given position is contained within the bounding + * sphere. + * + * @param position The position. + * @return Whether the position is contained within the bounding sphere. + */ + bool contains(const glm::dvec3& position) const noexcept; + + /** + * @brief Transforms this bounding sphere to another coordinate system using a + * 4x4 matrix. + * + * If the transformation has non-uniform scale, the bounding sphere's radius + * is scaled by the largest scale value among the transformation's axes. + * + * @param transformation The transformation. + * @return The bounding sphere in the new coordinate system. + */ + BoundingSphere transform(const glm::dmat4& transformation) const noexcept; + +private: + glm::dvec3 _center; + double _radius; +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/CullingResult.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/CullingResult.h new file mode 100644 index 0000000..4def303 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/CullingResult.h @@ -0,0 +1,31 @@ +#pragma once + +#include "Library.h" + +namespace CesiumGeometry { + +/** + * @brief The result of culling an object. + */ +enum class CESIUMGEOMETRY_API CullingResult { + /** + * @brief Indicates that an object lies completely outside the culling volume. + */ + Outside = -1, + + /** + * @brief Indicates that an object intersects with the boundary of the culling + * volume. + * + * This means that the object is partially inside and partially outside the + * culling volume. + */ + Intersecting = 0, + + /** + * @brief Indicates that an object lies completely inside the culling volume. + */ + Inside = 1 +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/CullingVolume.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/CullingVolume.h new file mode 100644 index 0000000..7bf5717 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/CullingVolume.h @@ -0,0 +1,61 @@ +#pragma once + +#include "Plane.h" + +namespace Cesium3DTilesSelection { + +/** + * @brief A culling volume, defined by four planes. + * + * The planes describe the culling volume that may be created for + * the view frustum of a camera. The normals of these planes will + * point inwards. + */ +struct CullingVolume final { + + /** + * @brief The left plane of the culling volume. + * + * Defaults to (0,0,1), with a distance of 0. + */ + CesiumGeometry::Plane leftPlane{glm::dvec3(0.0, 0.0, 1.0), 0.0}; + + /** + * @brief The right plane of the culling volume. + * + * Defaults to (0,0,1), with a distance of 0. + */ + CesiumGeometry::Plane rightPlane{glm::dvec3(0.0, 0.0, 1.0), 0.0}; + + /** + * @brief The top plane of the culling volume. + * + * Defaults to (0,0,1), with a distance of 0. + */ + CesiumGeometry::Plane topPlane{glm::dvec3(0.0, 0.0, 1.0), 0.0}; + + /** + * @brief The bottom plane of the culling volume. + * + * Defaults to (0,0,1), with a distance of 0. + */ + CesiumGeometry::Plane bottomPlane{glm::dvec3(0.0, 0.0, 1.0), 0.0}; +}; + +/** + * @brief Creates a {@link CullingVolume} for a perspective frustum. + * + * @param position The eye position + * @param direction The viewing direction + * @param up The up-vector of the frustum + * @param fovx The horizontal Field-Of-View angle, in radians + * @param fovy The vertical Field-Of-View angle, in radians + * @return The {@link CullingVolume} + */ +CullingVolume createCullingVolume( + const glm::dvec3& position, + const glm::dvec3& direction, + const glm::dvec3& up, + double fovx, + double fovy) noexcept; +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/IntersectionTests.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/IntersectionTests.h new file mode 100644 index 0000000..635b7aa --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/IntersectionTests.h @@ -0,0 +1,229 @@ +#pragma once + +#include "Library.h" + +#include +#include + +#include + +namespace CesiumGeometry { +class Ray; +class Plane; +struct AxisAlignedBox; +class OrientedBoundingBox; +class BoundingSphere; + +/** + * @brief Functions for computing the intersection between geometries such as + * rays, planes, triangles, and ellipsoids. + */ +class CESIUMGEOMETRY_API IntersectionTests final { +public: + /** + * @brief Computes the intersection of a ray and a plane. + * + * @param ray The ray. + * @param plane The plane. + * @return The point of intersection, or `std::nullopt` if there is no + * intersection. + */ + static std::optional + rayPlane(const Ray& ray, const Plane& plane) noexcept; + + /** + * @brief Computes the intersection of a ray and an ellipsoid with the given + * radii, centered at the origin. + * + * Returns false if any of the radii are 0. + * + * @param ray The ray. + * @param radii The radii of ellipsoid. + * @return The distances along the ray where it intersects the ellipsoid, or + * `std::nullopt` if there are no intersections. X is the entry, and y is the + * exit. + * + */ + static std::optional + rayEllipsoid(const Ray& ray, const glm::dvec3& radii) noexcept; + + /** + * @brief Determines whether a given point is completely inside a triangle + * defined by three 2D points. + * + * This function does not check for degeneracy of the triangle. + * + * @param point The point to check. + * @param triangleVertA The first vertex of the triangle. + * @param triangleVertB The second vertex of the triangle. + * @param triangleVertC The third vertex of the triangle. + * @return Whether the point is within the triangle. + */ + static bool pointInTriangle( + const glm::dvec2& point, + const glm::dvec2& triangleVertA, + const glm::dvec2& triangleVertB, + const glm::dvec2& triangleVertC) noexcept; + + /** + * @brief Determines whether a given point is completely inside a triangle + * defined by three 3D points. + * + * Returns false for degenerate triangles. + * + * @param point The point to check. + * @param triangleVertA The first vertex of the triangle. + * @param triangleVertB The second vertex of the triangle. + * @param triangleVertC The third vertex of the triangle. + * @return Whether the point is within the triangle. + */ + static bool pointInTriangle( + const glm::dvec3& point, + const glm::dvec3& triangleVertA, + const glm::dvec3& triangleVertB, + const glm::dvec3& triangleVertC) noexcept; + + /** + * @brief Determines whether the point is completely inside a triangle defined + * by three 3D points. If the point is inside, this also outputs the + * barycentric coordinates for the point. + * + * Returns false for degenerate triangles. + * + * @param point The point to check. + * @param triangleVertA The first vertex of the triangle. + * @param triangleVertB The second vertex of the triangle. + * @param triangleVertC The third vertex of the triangle. + * @param barycentricCoordinates The barycentric coordinates for the point, if + * the point is inside the triangle. + * @return Whether the point is within the triangle. + */ + static bool pointInTriangle( + const glm::dvec3& point, + const glm::dvec3& triangleVertA, + const glm::dvec3& triangleVertB, + const glm::dvec3& triangleVertC, + glm::dvec3& barycentricCoordinates) noexcept; + + /** + * @brief Tests if a ray hits a triangle and returns the hit point. + * + * @param ray The ray. + * @param p0 The first vertex of the triangle. + * @param p1 The second vertex of the triangle. + * @param p2 The third vertex of the triangle. + * @param cullBackFaces Ignore triangles that face away from ray. Front faces + * use CCW winding order. + * @return The point of intersection, or `std::nullopt` if there is no + * intersection. + */ + static std::optional rayTriangle( + const Ray& ray, + const glm::dvec3& p0, + const glm::dvec3& p1, + const glm::dvec3& p2, + bool cullBackFaces = false); + + /** + * @brief Tests if an infinite ray hits a triangle and returns the parametric + * hit position. + * + * The return parameter is positive if the intersection point is in front of + * the ray origin, negative if it is behind it, or zero if the two points + * coincide. + * + * @param ray The ray. + * @param p0 The first vertex of the triangle. + * @param p1 The second vertex of the triangle. + * @param p2 The third vertex of the triangle. + * @param cullBackFaces Ignore triangles that face away from ray. Front faces + * use CCW winding order. + * @return optional hit parametric value, if one is detected. + */ + static std::optional rayTriangleParametric( + const Ray& ray, + const glm::dvec3& p0, + const glm::dvec3& p1, + const glm::dvec3& p2, + bool cullBackFaces = false); + + /** + * @brief Computes the intersection of a ray and an axis aligned bounding box. + * + * @param ray The ray. + * @param aabb The axis aligned bounding box. + * @return The point of intersection, or `std::nullopt` if there is no + * intersection. + */ + static std::optional + rayAABB(const Ray& ray, const AxisAlignedBox& aabb); + + /** + * @brief Computes the intersection of an infinite ray and an axis aligned + * bounding box and returns the parametric hit position. + * + * The return value is positive if the intersection point is in front of the + * ray origin, negative if it is behind it, or zero if the two points + * coincide. + * + * @param ray The ray. + * @param aabb The axis aligned bounding box. + * @return optional hit parametric value, if one is detected. + */ + static std::optional + rayAABBParametric(const Ray& ray, const AxisAlignedBox& aabb); + + /** + * @brief Computes the intersection of a ray and an oriented bounding box. + * + * @param ray The ray. + * @param obb The oriented bounding box. + * @return The point of intersection, or `std::nullopt` if there is no + * intersection. + */ + static std::optional + rayOBB(const Ray& ray, const OrientedBoundingBox& obb); + + /** + * @brief Computes the intersection of an infinite ray and an oriented + * bounding box and returns the parametric hit position. + * + * The return parameter is positive if the intersection point is in front of + * the ray origin, negative if it is behind it, or zero if the two points + * coincide. + * + * @param ray The ray. + * @param obb The oriented bounding box. + * @return optional hit parametric value, if one is detected. + */ + static std::optional + rayOBBParametric(const Ray& ray, const OrientedBoundingBox& obb); + + /** + * @brief Computes the intersection of a ray and a bounding sphere. + * + * @param ray The ray. + * @param sphere The bounding sphere. + * @return The point of intersection, or `std::nullopt` if there is no + * intersection. + */ + static std::optional + raySphere(const Ray& ray, const BoundingSphere& sphere); + + /** + * @brief Computes the intersection of an infinite ray and a bounding sphere + * and returns the parametric hit position. + * + * The return parameter is positive if the intersection point is in front of + * the ray origin, negative if it is behind it, or zero if the two points + * coincide. + * + * @param ray The ray. + * @param sphere The bounding sphere. + * @return optional hit parametric value, if one is detected. + */ + static std::optional + raySphereParametric(const Ray& ray, const BoundingSphere& sphere); +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Library.h new file mode 100644 index 0000000..b7e9cef --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Basic geometry classes for Cesium + * + * @mermaid-interactive{dependencies/CesiumGeometry} + */ +namespace CesiumGeometry {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMGEOMETRY_BUILDING +#define CESIUMGEOMETRY_API __declspec(dllexport) +#else +#define CESIUMGEOMETRY_API __declspec(dllimport) +#endif +#else +#define CESIUMGEOMETRY_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OctreeAvailability.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OctreeAvailability.h new file mode 100644 index 0000000..7f2a17b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OctreeAvailability.h @@ -0,0 +1,173 @@ +#pragma once + +#include "Availability.h" +#include "Library.h" +#include "OctreeTileID.h" +#include "TileAvailabilityFlags.h" + +#include +#include +#include +#include + +namespace CesiumGeometry { + +/** + * @brief An availability tree for an octree, where availability can be stored + * and computed based on \ref OctreeTileID. + */ +class CESIUMGEOMETRY_API OctreeAvailability final { +public: + /** + * @brief Constructs a new instance. + * + * @param subtreeLevels The number of levels in each subtree. + * @param maximumLevel The index of the maximum level in this tileset. + */ + OctreeAvailability(uint32_t subtreeLevels, uint32_t maximumLevel) noexcept; + + /** + * @brief Determines the currently known availability status of the given + * tile. + * + * @param tileID The {@link CesiumGeometry::OctreeTileID} for the tile. + * + * @return The {@link TileAvailabilityFlags} for this tile encoded into a + * uint8_t. + */ + uint8_t computeAvailability(const OctreeTileID& tileID) const noexcept; + + /** + * @brief Attempts to add an availability subtree into the existing overall + * availability tree. + * + * @param tileID The {@link CesiumGeometry::OctreeTileID} for the tile. + * @param newSubtree The {@link CesiumGeometry::AvailabilitySubtree} to add. + * + * @return Whether the insertion was successful. + */ + bool addSubtree( + const OctreeTileID& tileID, + AvailabilitySubtree&& newSubtree) noexcept; + + /** + * @brief Determines the currently known availability status of the given + * tile. + * + * Priming with a known parent subtree node avoids the need to traverse the + * entire availability tree so far. The node must have a loaded subtree + * + * @param tileID The tile ID to get the availability for. + * @param pNode The subtree node to look for the tileID in. The tileID should + * be within this subtree node. + * + * @return The {@link TileAvailabilityFlags} for this tile encoded into a + * uint8_t. + */ + uint8_t computeAvailability( + const OctreeTileID& tileID, + const AvailabilityNode* pNode) const noexcept; + + /** + * @brief Attempts to add a child subtree node onto the given parent node. + * + * Priming with a known parent subtree node avoids the need to traverse the + * entire availability tree so far. If the parent node is nullptr and the + * tile ID indicates this is the root tile, the subtree will be attached to + * the root. + * + * @param tileID The root tile's ID of the subtree we are trying to add. + * @param pParentNode The parent subtree node. The tileID should fall exactly + * at the end of this parent subtree. + * + * @return The newly created node if the insertion was successful, nullptr + * otherwise. + */ + AvailabilityNode* + addNode(const OctreeTileID& tileID, AvailabilityNode* pParentNode) noexcept; + + /** + * @brief Attempts to add a loaded subtree onto the given node. + * + * The node must have been created earlier from a call to addNode. + * + * @param pNode The node on which to add the subtree. + * @param newSubtree The new subtree to add. + * + * @return Whether the insertion was successful. + */ + bool addLoadedSubtree( + AvailabilityNode* pNode, + AvailabilitySubtree&& newSubtree) noexcept; + /** + * @brief Find the child node index corresponding to this tile ID and parent + * node. + * + * Attempts to find the child node for the tile with the given ID and parent + * node. The parent node is used to speed up the search significantly. Note + * that if the given tile ID does not correspond exactly to an immediate + * child node of the parent node, nullptr will be returned. If a tileID + * outside the given parent node's subtree is given, an incorrect child index + * may be returned. + * + * @param tileID The tile ID of the child node we are looking for. + * @param pParentNode The immediate parent to the child node we are looking + * for. + * @return The child node index if found, std::nullopt otherwise. + */ + std::optional findChildNodeIndex( + const OctreeTileID& tileID, + const AvailabilityNode* pParentNode) const; + + /** + * @brief Find the child node corresponding to this tile ID and parent node. + * + * Attempts to find the child node for the tile with the given ID and parent + * node. The parent node is used to speed up the search significantly. Note + * that if the given tile ID does not correspond exactly to an immediate + * child node of the parent node, nullptr will be returned. If a tileID + * outside the given parent node's subtree is given, an incorrect child index + * may be returned. + * + * @param tileID The tile ID of the child node we are looking for. + * @param pParentNode The immediate parent to the child node we are looking + * for. + * @return The child node if found, nullptr otherwise. + */ + AvailabilityNode* findChildNode( + const OctreeTileID& tileID, + AvailabilityNode* pParentNode) const; + + /** + * @brief Gets the number of levels in each subtree. + * + * @returns The number of levels in each subtree. + */ + constexpr inline uint32_t getSubtreeLevels() const noexcept { + return this->_subtreeLevels; + } + + /** + * @brief Gets the index of the maximum level in this implicit tileset. + * + * @returns The index of the maximum level. + */ + constexpr inline uint32_t getMaximumLevel() const noexcept { + return this->_maximumLevel; + } + + /** + * @brief Gets a pointer to the root subtree node of this implicit tileset. + * + * @returns The root node of the availability tree. + */ + AvailabilityNode* getRootNode() noexcept { return this->_pRoot.get(); } + +private: + uint32_t _subtreeLevels; + uint32_t _maximumLevel; + uint32_t _maximumChildrenSubtrees; + std::unique_ptr _pRoot; +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OctreeTileID.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OctreeTileID.h new file mode 100644 index 0000000..7d52cc9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OctreeTileID.h @@ -0,0 +1,76 @@ +#pragma once + +#include "Library.h" + +#include + +namespace CesiumGeometry { + +/** + * @brief A structure serving as a unique identifier for a node in an octree. + * + * This is one form of a {@link Cesium3DTilesSelection::TileID}. + * + * The identifier is composed of the level (with 0 being the level of the root + * tile), the x-, y-, and z-coordinate of the tile, referring to a grid + * coordinate system at the respective level. + */ +struct CESIUMGEOMETRY_API OctreeTileID { + + /** + * @brief Creates a new instance. + */ + constexpr OctreeTileID() : level(0), x(0), y(0), z(0){}; + + /** + * @brief Creates a new instance. + * + * @param level_ The level of the node, with 0 being the root. + * @param x_ The x-coordinate of the tile. + * @param y_ The y-coordinate of the tile. + * @param z_ The z-coordinate of the tile. + */ + constexpr OctreeTileID( + uint32_t level_, + uint32_t x_, + uint32_t y_, + uint32_t z_) noexcept + : level(level_), x(x_), y(y_), z(z_) {} + + /** + * @brief Returns `true` if two identifiers are equal. + */ + constexpr bool operator==(const OctreeTileID& other) const noexcept { + return this->level == other.level && this->x == other.x && + this->y == other.y && this->z == other.z; + } + + /** + * @brief Returns `true` if two identifiers are *not* equal. + */ + constexpr bool operator!=(const OctreeTileID& other) const noexcept { + return !(*this == other); + } + + /** + * @brief The level of this tile ID, with 0 being the root tile. + */ + uint32_t level; + + /** + * @brief The x-coordinate of this tile ID. + */ + uint32_t x; + + /** + * @brief The y-coordinate of this tile ID. + */ + uint32_t y; + + /** + * @brief The z-coordinate of this tile ID. + */ + uint32_t z; +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OctreeTilingScheme.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OctreeTilingScheme.h new file mode 100644 index 0000000..047498a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OctreeTilingScheme.h @@ -0,0 +1,109 @@ +#pragma once + +#include "CesiumGeometry/AxisAlignedBox.h" +#include "CesiumGeometry/Library.h" +#include "CesiumGeometry/OctreeTileID.h" + +#include + +#include + +namespace CesiumGeometry { + +/** + * @brief Defines how an {@link AxisAlignedBox} is divided into octree + * tiles. + */ +class CESIUMGEOMETRY_API OctreeTilingScheme { +public: + /** + * @brief Constructs a new instance. + * + * @param box The overall box that is tiled, expressed in projected + * coordinates. + * @param rootTilesX The number of tiles at the root of the quadtree in the X + * direction. + * @param rootTilesY The nubmer of tiles at the root of the quadtree in the Y + * direction. + * @param rootTilesZ The number of tiles at the root of the quadtree in the Z + * direction. + */ + OctreeTilingScheme( + const AxisAlignedBox& box, + uint32_t rootTilesX, + uint32_t rootTilesY, + uint32_t rootTilesZ) noexcept; + + /** + * @brief Return the overall box that is tiled. + */ + const AxisAlignedBox& getBox() const noexcept { return this->_box; } + + /** + * @brief Returns the number of root tiles, in x-direction. + */ + uint32_t getRootTilesX() const noexcept { return this->_rootTilesX; } + + /** + * @brief Returns the number of root tiles, in y-direction. + */ + uint32_t getRootTilesY() const noexcept { return this->_rootTilesY; } + + /** + * @brief Returns the number of root tiles, in z-direction. + */ + uint32_t getRootTilesZ() const noexcept { return this->_rootTilesZ; } + + /** + * @brief Returns the number of tiles, in x-direction, at the given level. + */ + uint32_t getNumberOfXTilesAtLevel(uint32_t level) const noexcept; + + /** + * @brief Returns the number of tiles, in y-direction, at the given level. + */ + uint32_t getNumberOfYTilesAtLevel(uint32_t level) const noexcept; + + /** + * @brief Returns the number of tiles, in z-direction, at the given level. + */ + uint32_t getNumberOfZTilesAtLevel(uint32_t level) const noexcept; + + /** + * @brief Computes the {@link CesiumGeometry::OctreeTileID} for a given + * position and level. + * + * If the projected position is within the {@link getBox} of this tiling + * scheme, then this will compute the octree tile ID for the tile that + * contains the given position at the given level. Otherwise, `nullopt` is + * returned. + * + * @param position The position in projected coordinates. + * @param level The level + * @return The tile ID, or `nullopt`. + */ + std::optional + positionToTile(const glm::dvec3& position, uint32_t level) const noexcept; + + /** + * @brief Returns the {@link AxisAlignedBox} that is + * covered by the specified tile. + * + * The volume that is covered by the tile that is identified with + * the given {@link CesiumGeometry::OctreeTileID} will be computed, + * based on the {@link getBox} of this tiling scheme. + * + * @param tileID The tile ID + * @return The box + */ + AxisAlignedBox + tileToBox(const CesiumGeometry::OctreeTileID& tileID) const noexcept; + +private: + AxisAlignedBox _box; + uint32_t _rootTilesX; + uint32_t _rootTilesY; + uint32_t _rootTilesZ; +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OrientedBoundingBox.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OrientedBoundingBox.h new file mode 100644 index 0000000..983d06b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OrientedBoundingBox.h @@ -0,0 +1,150 @@ +#pragma once + +#include "AxisAlignedBox.h" +#include "BoundingSphere.h" +#include "CullingResult.h" +#include "Library.h" + +#include +#include + +namespace CesiumGeometry { + +class Plane; + +/** + * @brief A bounding volume defined as a closed and convex cuboid with any + * orientation. + * + * @see BoundingSphere + * @see BoundingRegion + */ +class CESIUMGEOMETRY_API OrientedBoundingBox final { +public: + /** + * @brief Constructs a new instance. + * + * @param center The center of the box. + * @param halfAxes The three orthogonal half-axes of the bounding box. + * Equivalently, the transformation matrix to rotate and scale a 2x2x2 cube + * centered at the origin. + * + * @snippet TestOrientedBoundingBox.cpp Constructor + */ + OrientedBoundingBox( + const glm::dvec3& center, + const glm::dmat3& halfAxes) noexcept + : _center(center), + _halfAxes(halfAxes), + // TODO: what should we do if halfAxes is singular? + _inverseHalfAxes(glm::inverse(halfAxes)), + _lengths( + 2.0 * glm::length(_halfAxes[0]), + 2.0 * glm::length(_halfAxes[1]), + 2.0 * glm::length(_halfAxes[2])) {} + + /** + * @brief Gets the center of the box. + */ + constexpr const glm::dvec3& getCenter() const noexcept { + return this->_center; + } + + /** + * @brief Gets the three orthogonal half-axes of the bounding box. + * Equivalently, the transformation matrix to rotate and scale a 2x2x2 cube + * centered at the origin. + */ + constexpr const glm::dmat3& getHalfAxes() const noexcept { + return this->_halfAxes; + } + + /** + * @brief Gets the inverse transformation matrix, to rotate from world space + * to local space relative to the box. + */ + constexpr const glm::dmat3& getInverseHalfAxes() const noexcept { + return this->_inverseHalfAxes; + } + + /** + * @brief Gets the lengths of the box on each local axis respectively. + */ + constexpr const glm::dvec3& getLengths() const noexcept { + return this->_lengths; + } + + /** + * @brief Determines on which side of a plane the bounding box is located. + * + * @param plane The plane to test against. + * @return The {@link CullingResult}: + * * `Inside` if the entire box is on the side of the plane the normal is + * pointing. + * * `Outside` if the entire box is on the opposite side. + * * `Intersecting` if the box intersects the plane. + */ + CullingResult intersectPlane(const Plane& plane) const noexcept; + + /** + * @brief Computes the distance squared from a given position to the closest + * point on this bounding volume. The bounding volume and the position must be + * expressed in the same coordinate system. + * + * @param position The position + * @return The estimated distance squared from the bounding box to the point. + * + * @snippet TestOrientedBoundingBox.cpp distanceSquaredTo + */ + double + computeDistanceSquaredToPosition(const glm::dvec3& position) const noexcept; + + /** + * @brief Computes whether the given position is contained within the bounding + * box. + * + * @param position The position. + * @return Whether the position is contained within the bounding box. + */ + bool contains(const glm::dvec3& position) const noexcept; + + /** + * @brief Transforms this bounding box to another coordinate system using a + * 4x4 matrix. + * + * @param transformation The transformation. + * @return The oriented bounding box in the new coordinate system. + */ + OrientedBoundingBox + transform(const glm::dmat4& transformation) const noexcept; + + /** + * @brief Converts this oriented bounding box to an axis-aligned bounding box. + */ + AxisAlignedBox toAxisAligned() const noexcept; + + /** + * @brief Converts this oriented bounding box to a bounding sphere. + */ + BoundingSphere toSphere() const noexcept; + + /** + * @brief Creates an oriented bounding box from the given axis-aligned + * bounding box. + */ + static OrientedBoundingBox + fromAxisAligned(const AxisAlignedBox& axisAligned) noexcept; + + /** + * @brief Creates an oriented bounding box from the given bounding sphere. + */ + static OrientedBoundingBox fromSphere(const BoundingSphere& sphere) noexcept; + +private: + glm::dvec3 _center; + glm::dmat3 _halfAxes; + glm::dmat3 _inverseHalfAxes; + glm::dvec3 _lengths; +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Plane.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Plane.h new file mode 100644 index 0000000..0fef46c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Plane.h @@ -0,0 +1,111 @@ +#pragma once + +#include "Library.h" + +#include + +namespace CesiumGeometry { + +/** + * @brief A plane in Hessian Normal Format. + */ +class CESIUMGEOMETRY_API Plane final { +public: + /** + * @brief The XY plane passing through the origin, with normal in positive Z. + */ + static const Plane ORIGIN_XY_PLANE; + + /** + * @brief The YZ plane passing through the origin, with normal in positive X. + */ + static const Plane ORIGIN_YZ_PLANE; + + /** + * @brief The ZX plane passing through the origin, with normal in positive Y. + */ + static const Plane ORIGIN_ZX_PLANE; + + /** + * @brief Constructs a new plane with a +Z normal and a distance of 0.0. + */ + Plane() noexcept; + + /** + * @brief Constructs a new plane from a normal and a distance from the origin. + * + * The plane is defined by: + * ``` + * ax + by + cz + d = 0 + * ``` + * where (a, b, c) is the plane's `normal`, d is the signed + * `distance` to the plane, and (x, y, z) is any point on + * the plane. + * + * @param normal The plane's normal (normalized). + * @param distance The shortest distance from the origin to the plane. The + * sign of `distance` determines which side of the plane the origin is on. If + * `distance` is positive, the origin is in the half-space in the direction of + * the normal; if negative, the origin is in the half-space opposite to the + * normal; if zero, the plane passes through the origin. + * + * @exception std::exception `normal` must be normalized. + * + * Example: + * @snippet TestPlane.cpp constructor-normal-distance + */ + Plane(const glm::dvec3& normal, double distance); + + /** + * @brief Construct a new plane from a point in the plane and the plane's + * normal. + * + * @param point The point on the plane. + * @param normal The plane's normal (normalized). + * + * @exception std::exception `normal` must be normalized. + * + * Example: + * @snippet TestPlane.cpp constructor-point-normal + */ + Plane(const glm::dvec3& point, const glm::dvec3& normal); + + /** + * @brief Gets the plane's normal. + */ + const glm::dvec3& getNormal() const noexcept { return this->_normal; } + + /** + * @brief Gets the signed shortest distance from the origin to the plane. + * The sign of `distance` determines which side of the plane the origin + * is on. If `distance` is positive, the origin is in the half-space + * in the direction of the normal; if negative, the origin is in the + * half-space opposite to the normal; if zero, the plane passes through the + * origin. + */ + double getDistance() const noexcept { return this->_distance; } + + /** + * @brief Computes the signed shortest distance of a point to this plane. + * The sign of the distance determines which side of the plane the point + * is on. If the distance is positive, the point is in the half-space + * in the direction of the normal; if negative, the point is in the half-space + * opposite to the normal; if zero, the plane passes through the point. + * + * @param point The point. + * @returns The signed shortest distance of the point to the plane. + */ + double getPointDistance(const glm::dvec3& point) const noexcept; + + /** + * @brief Projects a point onto this plane. + * @param point The point to project onto the plane. + * @returns The projected point. + */ + glm::dvec3 projectPointOntoPlane(const glm::dvec3& point) const noexcept; + +private: + glm::dvec3 _normal; + double _distance; +}; +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeAvailability.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeAvailability.h new file mode 100644 index 0000000..f47dfde --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeAvailability.h @@ -0,0 +1,168 @@ +#pragma once + +#include "Availability.h" +#include "Library.h" +#include "QuadtreeTileID.h" +#include "TileAvailabilityFlags.h" + +#include +#include +#include +#include + +namespace CesiumGeometry { + +/** + * @brief An availability tree for a quadtree, where availability can be stored + * and computed based on \ref QuadtreeTileID. + */ +class CESIUMGEOMETRY_API QuadtreeAvailability final { +public: + /** + * @brief Constructs a new instance. + * + * @param subtreeLevels The number of levels in each subtree. + * @param maximumLevel The index of the maximum level in this tileset. + */ + QuadtreeAvailability(uint32_t subtreeLevels, uint32_t maximumLevel) noexcept; + + /** + * @brief Determines the currently known availability status of the given + * tile. + * + * @param tileID The {@link CesiumGeometry::QuadtreeTileID} for the tile. + * + * @return The {@link TileAvailabilityFlags} for this tile encoded into a + * uint8_t. + */ + uint8_t computeAvailability(const QuadtreeTileID& tileID) const noexcept; + + /** + * @brief Attempts to add an availability subtree into the existing overall + * availability tree. + * + * @param tileID The {@link CesiumGeometry::QuadtreeTileID} for the tile. + * @param newSubtree The {@link CesiumGeometry::AvailabilitySubtree} to add. + * + * @return Whether the insertion was successful. + */ + bool addSubtree( + const QuadtreeTileID& tileID, + AvailabilitySubtree&& newSubtree) noexcept; + + /** + * @brief Determines the currently known availability status of the given + * tile. + * + * Priming with a known parent subtree node avoids the need to traverse the + * entire availability tree so far. The node must have a loaded subtree + * + * @param tileID The tile ID to get the availability for. + * @param pNode The subtree node to look for the tileID in. The tileID should + * be within this subtree node. + * + * @return The {@link TileAvailabilityFlags} for this tile encoded into a + * uint8_t. + */ + uint8_t computeAvailability( + const QuadtreeTileID& tileID, + const AvailabilityNode* pNode) const noexcept; + + /** + * @brief Attempts to add a child subtree node onto the given parent node. + * + * Priming with a known parent subtree node avoids the need to traverse the + * entire availability tree so far. If the parent node is nullptr and the + * tile ID indicates this is the root tile, the subtree will be attached to + * the root. + * + * @param tileID The root tile's ID of the subtree we are trying to add. + * @param pParentNode The parent subtree node. The tileID should fall exactly + * at the end of this parent subtree. + * + * @return The newly created node if the insertion was successful, nullptr + * otherwise. + */ + AvailabilityNode* + addNode(const QuadtreeTileID& tileID, AvailabilityNode* pParentNode) noexcept; + + /** + * @brief Attempts to add a loaded subtree onto the given node. + * + * The node must have been created earlier from a call to addNode. + * + * @param pNode The node on which to add the subtree. + * @param newSubtree The new subtree to add. + * + * @return Whether the insertion was successful. + */ + bool addLoadedSubtree( + AvailabilityNode* pNode, + AvailabilitySubtree&& newSubtree) noexcept; + + /** + * @brief Find the child node index corresponding to this tile ID and parent + * node. + * + * Attempts to find the child node for the tile with the given ID and parent + * node. The parent node is used to speed up the search significantly. Note + * that if the given tile ID does not correspond exactly to an immediate + * child node of the parent node, nullptr will be returned. If a tileID + * outside the given parent node's subtree is given, an incorrect child index + * may be returned. + * + * @param tileID The tile ID of the child node we are looking for. + * @param pParentNode The immediate parent to the child node we are looking + * for. + * @return The child node index if found, std::nullopt otherwise. + */ + std::optional findChildNodeIndex( + const QuadtreeTileID& tileID, + const AvailabilityNode* pParentNode) const; + + /** + * @brief Find the child node corresponding to this tile ID and parent node. + * + * Attempts to find the child node for the tile with the given ID and parent + * node. The parent node is used to speed up the search significantly. Note + * that if the given tile ID does not correspond exactly to an immediate + * child node of the parent node, nullptr will be returned. If a tileID + * outside the given parent node's subtree is given, an incorrect child index + * may be returned. + * + * @param tileID The tile ID of the child node we are looking for. + * @param pParentNode The immediate parent to the child node we are looking + * for. + * @return The child node if found, nullptr otherwise. + */ + AvailabilityNode* findChildNode( + const QuadtreeTileID& tileID, + AvailabilityNode* pParentNode) const; + + /** + * @brief Gets the number of levels in each subtree. + */ + constexpr inline uint32_t getSubtreeLevels() const noexcept { + return this->_subtreeLevels; + } + + /** + * @brief Gets the index of the maximum level in this implicit tileset. + */ + constexpr inline uint32_t getMaximumLevel() const noexcept { + return this->_maximumLevel; + } + + /** + * @brief Gets a pointer to the root subtree node of this implicit tileset. + */ + AvailabilityNode* getRootNode() noexcept { return this->_pRoot.get(); } + +private: + uint32_t _subtreeLevels; + uint32_t _maximumLevel; + uint32_t _maximumChildrenSubtrees; + std::unique_ptr _pRoot; +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeRectangleAvailability.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeRectangleAvailability.h new file mode 100644 index 0000000..7713b56 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeRectangleAvailability.h @@ -0,0 +1,121 @@ +#pragma once + +#include "Library.h" +#include "QuadtreeTileRectangularRange.h" +#include "QuadtreeTilingScheme.h" +#include "Rectangle.h" + +#include + +#include +#include + +namespace CesiumGeometry { + +/** + * @brief Manages information about the availability of tiles in a quadtree. + */ +class CESIUMGEOMETRY_API QuadtreeRectangleAvailability final { +public: + /** + * @brief Creates a new instance. + * + * @param tilingScheme The {@link QuadtreeTilingScheme}. + * @param maximumLevel The maximum level (height of the tree) for which + * the availability should be tracked. + */ + QuadtreeRectangleAvailability( + const QuadtreeTilingScheme& tilingScheme, + uint32_t maximumLevel) noexcept; + + /** + * @brief Adds the specified range to the set of available tiles. + * + * @param range The {@link QuadtreeTileRectangularRange} that describes + * the range of available tiles. + */ + void + addAvailableTileRange(const QuadtreeTileRectangularRange& range) noexcept; + + /** + * @brief Computes the maximum level for the given 2D position. + * + * This will compute the maximum level of any available tile for + * the given position. The position refers to the 2D space that + * is covered by the nodes of the quadtree. + * + * @param position The 2D position. + * @return The maximum level at the given position. This may be 0 if + * the position is not covered by the quadtree at all. + */ + uint32_t + computeMaximumLevelAtPosition(const glm::dvec2& position) const noexcept; + + /** + * @brief Returns whether a certain tile is available. + * + * This checks the availability of the tile that is described by the + * given {@link QuadtreeTileID}, which consists of the level and + * the x- and y- coordinates of the queried tile. + * + * @param id The quadtree tile ID. + * @returns The {@link CesiumGeometry::TileAvailabilityFlags} for this tile, + * encoded into an uint8_t. + */ + uint8_t isTileAvailable(const QuadtreeTileID& id) const noexcept; + +private: + struct RectangleWithLevel { + uint32_t level; + Rectangle rectangle; + }; + + struct QuadtreeNode { + QuadtreeNode( + const QuadtreeTileID& id_, + const Rectangle& extent_, + QuadtreeNode* pParent_) noexcept + : id(id_), + extent(extent_), + pParent(pParent_), + ll(), + lr(), + ul(), + ur(), + rectangles() {} + + QuadtreeTileID id; + + CesiumGeometry::Rectangle extent; + + QuadtreeNode* pParent; + std::unique_ptr ll; + std::unique_ptr lr; + std::unique_ptr ul; + std::unique_ptr ur; + + std::vector rectangles; + }; + + QuadtreeTilingScheme _tilingScheme; + uint32_t _maximumLevel; + std::vector> _rootNodes; + + static void putRectangleInQuadtree( + const QuadtreeTilingScheme& tilingScheme, + uint32_t maximumLevel, + QuadtreeRectangleAvailability::QuadtreeNode& node, + const QuadtreeRectangleAvailability::RectangleWithLevel& + rectangle) noexcept; + static bool rectangleLevelComparator( + const QuadtreeRectangleAvailability::RectangleWithLevel& a, + const QuadtreeRectangleAvailability::RectangleWithLevel& b) noexcept; + static uint32_t findMaxLevelFromNode( + QuadtreeNode* pStopNode, + QuadtreeNode& node, + const glm::dvec2& position) noexcept; + static void createNodeChildrenIfNecessary( + QuadtreeNode& node, + const QuadtreeTilingScheme& tilingScheme) noexcept; +}; +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeTileID.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeTileID.h new file mode 100644 index 0000000..9d1ebad --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeTileID.h @@ -0,0 +1,116 @@ +#pragma once + +#include "Library.h" + +#include +#include + +namespace CesiumGeometry { +class QuadtreeTilingScheme; + +/** + * @brief Uniquely identifies a node in a quadtree. + * + * This is one form of a {@link Cesium3DTilesSelection::TileID}. + * + * The identifier is composed of the level (with 0 being the level of the root + * tile), the x- and y-coordinate of the tile, referring to a grid coordinate + * system at the respective level. + */ +struct CESIUMGEOMETRY_API QuadtreeTileID final { + + /** + * @brief Creates a new instance. + * + * @param level_ The level of the node, with 0 being the root + * @param x_ The x-coordinate of the tile + * @param y_ The y-coordinate of the tile + */ + constexpr QuadtreeTileID(uint32_t level_, uint32_t x_, uint32_t y_) noexcept + : level(level_), x(x_), y(y_) {} + + /** + * @brief Returns `true` if two identifiers are equal. + */ + constexpr bool operator==(const QuadtreeTileID& other) const noexcept { + return this->level == other.level && this->x == other.x && + this->y == other.y; + } + + /** + * @brief Returns `true` if two identifiers are *not* equal. + */ + constexpr bool operator!=(const QuadtreeTileID& other) const noexcept { + return !(*this == other); + } + + /** + * @brief Computes the inverse y-coordinate of this tile ID. + * + * This will compute the inverse y-coordinate of this tile ID, based + * on the given tiling scheme, which provides the number of tiles + * in y-direction for the level of this tile ID. + * + * @param tilingScheme The {@link QuadtreeTilingScheme}. + * @return The inverted y-coordinate. + */ + uint32_t + computeInvertedY(const QuadtreeTilingScheme& tilingScheme) const noexcept; + + /** + * @brief Gets the ID of the parent of the tile with this ID. + * + * If this method is called on a level zero tile, it returns itself. + * + * @return The ID of the parent tile. + */ + constexpr QuadtreeTileID getParent() const noexcept { + if (this->level == 0) { + return *this; + } + return QuadtreeTileID(this->level - 1, this->x >> 1, this->y >> 1); + } + + /** + * @brief The level of this tile ID, with 0 being the root tile. + */ + uint32_t level; + + /** + * @brief The x-coordinate of this tile ID. + */ + uint32_t x; + + /** + * @brief The y-coordinate of this tile ID. + */ + uint32_t y; +}; + +/** + * @brief A node of a tile hierarchy that was created by upsampling the tile + * content of a parent node. + */ +struct CESIUMGEOMETRY_API UpsampledQuadtreeNode final { + + /** + * @brief The {@link QuadtreeTileID} for this tree node. + */ + QuadtreeTileID tileID; +}; +} // namespace CesiumGeometry + +namespace std { + +/** + * @brief A hash function for {@link CesiumGeometry::QuadtreeTileID} objects. + */ +template <> struct hash { + + /** + * @brief A specialization of the `std::hash` template for + * {@link CesiumGeometry::QuadtreeTileID} objects. + */ + size_t operator()(const CesiumGeometry::QuadtreeTileID& key) const noexcept; +}; +} // namespace std diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeTileRectangularRange.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeTileRectangularRange.h new file mode 100644 index 0000000..5330a71 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeTileRectangularRange.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +namespace CesiumGeometry { + +/** + * @brief A rectangular range of tiles at a particular level of a quadtree. + */ +struct QuadtreeTileRectangularRange { + + /** + * @brief The level in the tree at which this rectangle is located, with 0 + * being the root. + */ + uint32_t level; + + /** + * @brief The minimum x-coordinate of the range, *inclusive*. + */ + uint32_t minimumX; + + /** + * @brief The minimum y-coordinate of the range, *inclusive*. + */ + uint32_t minimumY; + + /** + * @brief The maximum x-coordinate of the range, *inclusive*. + */ + uint32_t maximumX; + + /** + * @brief The maximum y-coordinate of the range, *inclusive*. + */ + uint32_t maximumY; +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeTilingScheme.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeTilingScheme.h new file mode 100644 index 0000000..545177e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeTilingScheme.h @@ -0,0 +1,98 @@ +#pragma once + +#include "Library.h" +#include "QuadtreeTileID.h" +#include "Rectangle.h" + +#include + +#include + +namespace CesiumGeometry { + +/** + * @brief Defines how a rectangular region is divided into quadtree tiles. + */ +class CESIUMGEOMETRY_API QuadtreeTilingScheme final { +public: + /** + * @brief Constructs a new instance. + * + * @param rectangle The overall rectangle that is tiled, expressed in + * projected coordinates. + * @param rootTilesX The number of tiles at the root of the quadtree in the X + * direction. + * @param rootTilesY The number of tiles at the root of the quadtree in the Y + * direction. + */ + QuadtreeTilingScheme( + const CesiumGeometry::Rectangle& rectangle, + uint32_t rootTilesX, + uint32_t rootTilesY) noexcept; + + /** + * @brief Return the overall rectangle that is tiled. + * + * The rectangle is expressed in projected coordinates. + */ + const CesiumGeometry::Rectangle& getRectangle() const noexcept { + return this->_rectangle; + } + + /** + * @brief Returns the number of root tiles, in x-direction. + */ + uint32_t getRootTilesX() const noexcept { return this->_rootTilesX; } + + /** + * @brief Returns the number of root tiles, in y-direction. + */ + uint32_t getRootTilesY() const noexcept { return this->_rootTilesY; } + + /** + * @brief Returns the number of tiles, in x-direction, at the given level. + */ + uint32_t getNumberOfXTilesAtLevel(uint32_t level) const noexcept; + + /** + * @brief Returns the number of tiles, in y-direction, at the given level. + */ + uint32_t getNumberOfYTilesAtLevel(uint32_t level) const noexcept; + + /** + * @brief Computes the {@link CesiumGeometry::QuadtreeTileID} for a given + * position and level. + * + * If the given position is within the {@link getRectangle} of this tiling + * scheme, then this will compute the quadtree tile ID for the tile that + * contains the given position at the given level. Otherwise, `nullopt` + * is returned. + * + * @param position The 2D position + * @param level The level + * @return The tile ID, or `nullopt`. + */ + std::optional + positionToTile(const glm::dvec2& position, uint32_t level) const noexcept; + + /** + * @brief Returns the {@link CesiumGeometry::Rectangle} that is covered by the + * specified tile. + * + * The rectangle that is covered by the tile that is identified with + * the given {@link CesiumGeometry::QuadtreeTileID} will be computed, + * based on the {@link getRectangle} of this tiling scheme. + * + * @param tileID The tile ID + * @return The rectangle + */ + CesiumGeometry::Rectangle + tileToRectangle(const CesiumGeometry::QuadtreeTileID& tileID) const noexcept; + +private: + CesiumGeometry::Rectangle _rectangle; + uint32_t _rootTilesX; + uint32_t _rootTilesY; +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Ray.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Ray.h new file mode 100644 index 0000000..9bcadd6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Ray.h @@ -0,0 +1,63 @@ +#pragma once + +#include "Library.h" + +#include +#include + +namespace CesiumGeometry { + +/** + * @brief A ray that extends infinitely from the provided origin in the provided + * direction. + */ +class CESIUMGEOMETRY_API Ray final { +public: + /** + * @brief Construct a new ray. + * + * @param origin The origin of the ray. + * @param direction The direction of the ray (normalized). + * + * @exception std::exception `direction` must be normalized. + */ + Ray(const glm::dvec3& origin, const glm::dvec3& direction); + + /** + * @brief Gets the origin of the ray. + */ + const glm::dvec3& getOrigin() const noexcept { return this->_origin; } + + /** + * @brief Gets the direction of the ray. + */ + const glm::dvec3& getDirection() const noexcept { return this->_direction; } + + /** + * @brief Calculates a point on the ray that corresponds to the given + * distance from origin. Can be positive, negative, or 0. + * + * @param distance Desired distance from origin + * @return The point along the ray. + */ + glm::dvec3 pointFromDistance(double distance) const noexcept; + + /** + * @brief Transforms the ray using a given 4x4 transformation matrix. + * + * @param transformation The 4x4 transformation matrix used to transform the + * ray. + * @return The transformed ray. + */ + Ray transform(const glm::dmat4x4& transformation) const noexcept; + + /** + * @brief Constructs a new ray with its direction opposite this one. + */ + Ray operator-() const noexcept; + +private: + glm::dvec3 _origin; + glm::dvec3 _direction; +}; +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Rectangle.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Rectangle.h new file mode 100644 index 0000000..7c9ef80 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Rectangle.h @@ -0,0 +1,202 @@ +#pragma once + +#include "Library.h" + +#include + +#include + +namespace CesiumGeometry { + +/** + * @brief A 2D rectangle + */ +struct CESIUMGEOMETRY_API Rectangle final { + /** + * @brief Creates a new instance with all coordinate values set to 0.0. + */ + constexpr Rectangle() noexcept + : minimumX(0.0), minimumY(0.0), maximumX(0.0), maximumY(0.0) {} + + /** + * @brief Creates a new instance. + * + * Creates a new rectangle from the given coordinates. This implicitly + * assumes that the given coordinates form a valid rectangle, meaning + * that `minimumX <= maximumX` and `minimumY <= maximumY`. + * + * @param minimumX_ The minimum x-coordinate. + * @param minimumY_ The minimum y-coordinate. + * @param maximumX_ The maximum x-coordinate. + * @param maximumY_ The maximum y-coordinate. + */ + constexpr Rectangle( + double minimumX_, + double minimumY_, + double maximumX_, + double maximumY_) noexcept + : minimumX(minimumX_), + minimumY(minimumY_), + maximumX(maximumX_), + maximumY(maximumY_) {} + + /** + * @brief The minimum x-coordinate. + */ + double minimumX; + + /** + * @brief The minimum y-coordinate. + */ + double minimumY; + + /** + * @brief The maximum x-coordinate. + */ + double maximumX; + + /** + * @brief The maximum y-coordinate. + */ + double maximumY; + + /** + * @brief Checks whether this rectangle contains the given position. + * + * This means that the `x`- and `y` coordinates of the given position + * are not smaller than the minimum and not larger than the maximum + * coordinates of this rectangle. + * + * @param position The position. + * @returns Whether this rectangle contains the given position. + */ + bool contains(const glm::dvec2& position) const noexcept; + + /** + * @brief Checks whether this rectangle overlaps the given rectangle. + * + * This means that this rectangle and the given rectangle have + * a non-empty intersection. If either of the rectangles is empty, + * then this will always return `false`. + * + * @param other The other rectangle. + * @returns Whether this rectangle overlaps the given rectangle. + */ + bool overlaps(const Rectangle& other) const noexcept; + + /** + * @brief Checks whether this rectangle fully contains the given rectangle. + * + * This means that this rectangle contains all four corner points + * of the given rectangle, as defined in {@link Rectangle::contains}. + * + * @param other The other rectangle. + * @returns Whether this rectangle fully contains the given rectangle. + */ + bool fullyContains(const Rectangle& other) const noexcept; + + /** + * @brief Computes the signed distance from a position to the edge of the + * rectangle. + * + * If the position is inside the rectangle, the distance is negative. If it is + * outside the rectangle, it is positive. + * + * @param position The position. + * @return The signed distance. + */ + double computeSignedDistance(const glm::dvec2& position) const noexcept; + + /** + * @brief Returns a point at the lower left of this rectangle. + * + * This is the point that consists of the minimum x- and y-coordinate. + * + * @returns The lower left point. + */ + constexpr glm::dvec2 getLowerLeft() const noexcept { + return glm::dvec2(this->minimumX, this->minimumY); + } + + /** + * @brief Returns a point at the lower right of this rectangle. + * + * This is the point that consists of the maximum x- and minimum y-coordinate. + * + * @returns The lower right point. + */ + constexpr glm::dvec2 getLowerRight() const noexcept { + return glm::dvec2(this->maximumX, this->minimumY); + } + + /** + * @brief Returns a point at the upper left of this rectangle. + * + * This is the point that consists of the minimum x- and maximum y-coordinate. + * + * @returns The upper left point. + */ + constexpr glm::dvec2 getUpperLeft() const noexcept { + return glm::dvec2(this->minimumX, this->maximumY); + } + + /** + * @brief Returns a point at the upper right of this rectangle. + * + * This is the point that consists of the maximum x- and y-coordinate. + * + * @returns The upper right point. + */ + constexpr glm::dvec2 getUpperRight() const noexcept { + return glm::dvec2(this->maximumX, this->maximumY); + } + + /** + * @brief Returns a point at the center of this rectangle. + * + * @returns The center point. + */ + constexpr glm::dvec2 getCenter() const noexcept { + return glm::dvec2( + (this->minimumX + this->maximumX) * 0.5, + (this->minimumY + this->maximumY) * 0.5); + } + + /** + * @brief Computes the width of this rectangle. + * + * @returns The width. + */ + constexpr double computeWidth() const noexcept { + return this->maximumX - this->minimumX; + } + + /** + * @brief Computes the height of this rectangle. + * + * @returns The height. + */ + constexpr double computeHeight() const noexcept { + return this->maximumY - this->minimumY; + } + + /** + * Computes the intersection of this rectangle with another. + * + * @param other The other rectangle to intersect with this one. + * @returns The intersection rectangle, or `std::nullopt` if there is no + * intersection. + */ + std::optional + computeIntersection(const Rectangle& other) const noexcept; + + /** + * @brief Computes the union of this rectangle with another. + * + * @param other The other rectangle to union with this one. + * @return The union rectangle, which fully contains both rectangles. + */ + Rectangle computeUnion(const Rectangle& other) const noexcept; +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/TileAvailabilityFlags.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/TileAvailabilityFlags.h new file mode 100644 index 0000000..86b1de3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/TileAvailabilityFlags.h @@ -0,0 +1,43 @@ +#pragma once + +#include "Library.h" + +#include + +namespace CesiumGeometry { + +/** + * @brief A bitmask representing the availability state of a tile. + */ +enum CESIUMGEOMETRY_API TileAvailabilityFlags { + /** + * @brief The tile is known to be available. + */ + TILE_AVAILABLE = 1U, + + /** + * @brief The tile's content is known to be available. + */ + CONTENT_AVAILABLE = 2U, + + /** + * @brief This tile has a subtree that is known to be available. + */ + SUBTREE_AVAILABLE = 4U, + + /** + * @brief This tile has a subtree that is loaded. + */ + SUBTREE_LOADED = 8U, + + // TODO: is REACHABLE needed? Reevaluate after implementation + /** + * @brief The tile is reachable through the tileset availability tree. + * + * If a tile is not reachable, the above flags being false may simply + * indicate that a subtree needed to reach this tile has not yet been loaded. + */ + REACHABLE = 16U +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Transforms.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Transforms.h new file mode 100644 index 0000000..8a7870b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Transforms.h @@ -0,0 +1,100 @@ +#pragma once + +#include "Axis.h" +#include "Library.h" + +#include + +namespace CesiumGeometry { + +/** + * @brief Coordinate system matrix constructions helpers. + */ +struct CESIUMGEOMETRY_API Transforms final { + + /** + * @brief A matrix to convert from y-up to z-up orientation, + * by rotating about PI/2 around the x-axis + */ + static const glm::dmat4 Y_UP_TO_Z_UP; + + /** + * @brief A matrix to convert from z-up to y-up orientation, + * by rotating about -PI/2 around the x-axis + */ + static const glm::dmat4 Z_UP_TO_Y_UP; + + /** + * @brief A matrix to convert from x-up to z-up orientation, + * by rotating about -PI/2 around the y-axis + */ + static const glm::dmat4 X_UP_TO_Z_UP; + + /** + * @brief A matrix to convert from z-up to x-up orientation, + * by rotating about PI/2 around the y-axis + */ + static const glm::dmat4 Z_UP_TO_X_UP; + + /** + * @brief A matrix to convert from x-up to y-up orientation, + * by rotating about PI/2 around the z-axis + */ + static const glm::dmat4 X_UP_TO_Y_UP; + + /** + * @brief A matrix to convert from y-up to x-up orientation, + * by rotating about -PI/2 around the z-axis + */ + static const glm::dmat4 Y_UP_TO_X_UP; + + /** + * @brief Creates a translation-rotation-scale matrix, equivalent to + * `translation * rotation * scale`. So if a vector is multiplied with the + * resulting matrix, it will be first scaled, then rotated, then translated. + * + * @param translation The translation. + * @param rotation The rotation. + * @param scale The scale. + */ + static glm::dmat4 createTranslationRotationScaleMatrix( + const glm::dvec3& translation, + const glm::dquat& rotation, + const glm::dvec3& scale); + + /** + * @brief Decomposes a matrix into translation, rotation, and scale + * components. This is the reverse of + * {@link createTranslationRotationScaleMatrix}. + * + * The scale may be negative (i.e. when switching from a right-handed to a + * left-handed system), but skew and other funny business will result in + * undefined behavior. + * + * @param matrix The matrix to decompose. + * @param pTranslation A pointer to the vector in which to store the + * translation, or nullptr if the translation is not needed. + * @param pRotation A pointer to the quaternion in which to store the + * rotation, or nullptr if the rotation is not needed. + * @param pScale A pointer to the vector in which to store the scale, or + * nullptr if the scale is not needed. + */ + static void computeTranslationRotationScaleFromMatrix( + const glm::dmat4& matrix, + glm::dvec3* pTranslation, + glm::dquat* pRotation, + glm::dvec3* pScale); + + /** + * @brief Gets a transform that converts from one up axis to another. + * + * @param from The up axis to convert from. + * @param to The up axis to convert to. + * + * @returns The up axis transform. + */ + static const glm::dmat4& + getUpAxisTransform(CesiumGeometry::Axis from, CesiumGeometry::Axis to); +}; + +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/clipTriangleAtAxisAlignedThreshold.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/clipTriangleAtAxisAlignedThreshold.h new file mode 100644 index 0000000..02294b3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/clipTriangleAtAxisAlignedThreshold.h @@ -0,0 +1,104 @@ +#pragma once + +#include + +#include +#include + +namespace CesiumGeometry { + +/** + * @brief A structure describing a vertex that results from interpolating two + * other vertices. + * + * The vertices to interpolate between are given via their indices. This is + * used as one representation of a vertex in a {@link TriangleClipVertex}. + */ +struct InterpolatedVertex { + /** + * @brief The index of the first vertex to interpolate between. + */ + int first; + + /** + * @brief The index of the second vertex to interpolate between. + */ + int second; + + /** + * @brief The fraction of the distance from {@link first} to {@link second} at + * which to interpolate. + */ + double t; + + /** + * @brief Compares this \ref InterpolatedVertex against another. + * + * Two \ref InterpolatedVertex instances are considered equivalent if their + * \ref first and \ref second fields are equivalent and the difference between + * their \ref t fields is less than `std::numeric_limits::epsilon()`. + */ + constexpr bool operator==(const InterpolatedVertex& other) const noexcept { + return this->first == other.first && this->second == other.second && + std::fabs(this->t - other.t) <= + std::numeric_limits::epsilon(); + } + + /** @brief The inverse of \ref InterpolatedVertex::operator== */ + constexpr bool operator!=(const InterpolatedVertex& other) const noexcept { + return !(*this == other); + } +}; + +/** + * @brief A vertex resulting from clipping a triangle against a threshold. + * + * It may either be a simple index referring to an existing vertex, + * or an interpolation between two vertices. + */ +using TriangleClipVertex = std::variant; + +/** + * @brief Splits a 2D triangle at given axis-aligned threshold value and returns + * the resulting polygon on a given side of the threshold. + * + * The resulting polygon may have 0, 1, 2, 3, or 4 vertices. + * + * @param threshold The threshold coordinate value at which to clip the + * triangle. + * @param keepAbove true to keep the portion of the triangle above the + * threshold, or false to keep the portion below. + * @param i0 The index of the first vertex in the triangle in counter-clockwise + * order, used only to construct the TriangleClipVertex result. + * @param i1 The index of the second vertex in the triangle in counter-clockwise + * order, used only to construct the TriangleClipVertex result. + * @param i2 The index of the third vertex in the triangle in counter-clockwise + * order, used only to construct the TriangleClipVertex result. + * @param u0 The coordinate of the first vertex in the triangle, in + * counter-clockwise order. + * @param u1 The coordinate of the second vertex in the triangle, in + * counter-clockwise order. + * @param u2 The coordinate of the third vertex in the triangle, in + * counter-clockwise order. + * @param result On return, contains the polygon that results after the clip, + * specified as a list of vertices. If this vector already contains elements, + * the result is pushed onto the end of the vector. + * + * ``` + * TODO port this CesiumJS example to cesium-native + * var result = Cesium.Intersections2D.clipTriangleAtAxisAlignedThreshold(0.5, + * false, 0.2, 0.6, 0.4); + * // result === [2, 0, -1, 1, 0, 0.25, -1, 1, 2, 0.5] + * ``` + */ +void clipTriangleAtAxisAlignedThreshold( + double threshold, + bool keepAbove, + int i0, + int i1, + int i2, + double u0, + double u1, + double u2, + std::vector& result) noexcept; +} // namespace CesiumGeometry diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/BoundingRegion.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/BoundingRegion.h new file mode 100644 index 0000000..bf1f21a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/BoundingRegion.h @@ -0,0 +1,156 @@ +#pragma once + +#include "Ellipsoid.h" +#include "GlobeRectangle.h" +#include "Library.h" + +#include +#include +#include + +namespace CesiumGeometry { +class Plane; +} + +namespace CesiumGeospatial { +class Cartographic; + +/** + * @brief A bounding volume specified as a longitude/latitude bounding box and a + * minimum and maximum height. + */ +class CESIUMGEOSPATIAL_API BoundingRegion final { +public: + /** + * @brief Constructs a new bounding region. + * + * @param rectangle The bounding rectangle of the region. + * @param minimumHeight The minimum height in meters. + * @param maximumHeight The maximum height in meters. + * @param ellipsoid The ellipsoid on which this region is defined. + */ + BoundingRegion( + const GlobeRectangle& rectangle, + double minimumHeight, + double maximumHeight, + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief Gets the bounding rectangle of the region. + */ + const GlobeRectangle& getRectangle() const noexcept { + return this->_rectangle; + } + + /** + * @brief Gets the minimum height of the region. + */ + double getMinimumHeight() const noexcept { return this->_minimumHeight; } + + /** + * @brief Gets the maximum height of the region. + */ + double getMaximumHeight() const noexcept { return this->_maximumHeight; } + + /** + * @brief Gets an oriented bounding box containing this region. + */ + const CesiumGeometry::OrientedBoundingBox& getBoundingBox() const noexcept { + return this->_boundingBox; + } + + /** + * @brief Determines on which side of a plane the bounding region is located. + * + * @param plane The plane to test against. + * @return The {@link CesiumGeometry::CullingResult} + * * `Inside` if the entire region is on the side of the plane the normal is + * pointing. + * * `Outside` if the entire region is on the opposite side. + * * `Intersecting` if the region intersects the plane. + */ + CesiumGeometry::CullingResult + intersectPlane(const CesiumGeometry::Plane& plane) const noexcept; + + /** + * @brief Computes the distance-squared from a position in ellipsoid-centered + * Cartesian coordinates to the closest point in this bounding region. + * + * If the position cannot be converted into cartograpic coordinates for the + * given ellipsoid (because it is close to the center of the ellipsoid), + * then this function will return the squared distance between the given + * position and the closest point of the bounding box that is enclosed in + * this region. + * + * @param position The position. + * @param ellipsoid The ellipsoid on which this region is defined. + * @return The distance-squared from the position to the closest point in the + * bounding region. + */ + double computeDistanceSquaredToPosition( + const glm::dvec3& position, + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID) const noexcept; + + /** + * @brief Computes the distance-squared from a longitude-latitude-height + * position to the closest point in this bounding region. + * + * @param position The position. + * @param ellipsoid The ellipsoid on which this region is defined. + * @return The distance-squared from the position to the closest point in the + * bounding region. + */ + double computeDistanceSquaredToPosition( + const Cartographic& position, + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID) const noexcept; + + /** + * @brief Computes the distance-squared from a position to the closest point + * in this bounding region, when the longitude-latitude-height and + * ellipsoid-centered Cartesian coordinates of the position are both already + * known. + * + * @param cartographicPosition The position as a longitude-latitude-height. + * @param cartesianPosition The position as ellipsoid-centered Cartesian + * coordinates. + * @return The distance-squared from the position to the closest point in the + * bounding region. + */ + double computeDistanceSquaredToPosition( + const Cartographic& cartographicPosition, + const glm::dvec3& cartesianPosition) const noexcept; + + /** + * @brief Computes the union of this bounding region with another. + * + * @param other The other bounding region. + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + * @return The union. + */ + BoundingRegion computeUnion( + const BoundingRegion& other, + const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) const noexcept; + +private: + static CesiumGeometry::OrientedBoundingBox _computeBoundingBox( + const GlobeRectangle& rectangle, + double minimumHeight, + double maximumHeight, + const Ellipsoid& ellipsoid); + + GlobeRectangle _rectangle; + double _minimumHeight; + double _maximumHeight; + CesiumGeometry::OrientedBoundingBox _boundingBox; + + glm::dvec3 _southwestCornerCartesian; + glm::dvec3 _northeastCornerCartesian; + glm::dvec3 _westNormal; + glm::dvec3 _eastNormal; + glm::dvec3 _southNormal; + glm::dvec3 _northNormal; + bool _planesAreInvalid; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/BoundingRegionBuilder.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/BoundingRegionBuilder.h new file mode 100644 index 0000000..4f6476f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/BoundingRegionBuilder.h @@ -0,0 +1,101 @@ +#pragma once + +#include "BoundingRegion.h" +#include "GlobeRectangle.h" +#include "Library.h" + +namespace CesiumGeospatial { + +/** + * @brief Helper class for creating a \ref BoundingRegion or \ref GlobeRectangle + * from a set of points. + */ +class CESIUMGEOSPATIAL_API BoundingRegionBuilder { +public: + /** + * @brief Constructs a new instance, starting with an empty bounding region. + */ + BoundingRegionBuilder() noexcept; + + /** + * @brief Gets the final region from this builder. + * + * If no positions are added to this builder, the returned region's rectangle + * will be {@link GlobeRectangle::EMPTY}, its minimum height will be 1.0, and + * its maximum height will be -1.0 (the minimum will be greater than the + * maximum). + */ + BoundingRegion + toRegion(const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID) const; + + /** + * @brief Gets the final globe rectangle from this builder. + * + * If no positions are added to this builder, the returned region's rectangle + * will be {@link GlobeRectangle::EMPTY}. + */ + GlobeRectangle toGlobeRectangle() const; + + /** + * @brief Sets the distance from the North or South pole, in radians, that is + * considered "too close" to rely on the longitude value. + * + * When a position given to {@link expandToIncludePosition} has a latitude closer than this value, + * the region will be updated to include the position's _latitude_, but the + * position's longitude will be ignored. + * + * @param tolerance The new tolerance. + */ + void setPoleTolerance(double tolerance) noexcept; + + /** + * @brief Gets the distance from the North or South pole, in radians, that is + * considered "too close" to rely on the longitude value. + * + * When a position given to {@link expandToIncludePosition} has a latitude closer than this value, + * the region will be updated to include the position's _latitude_, but the + * position's longitude will be ignored. + * + * @return The tolerance. + */ + double getPoleTolerance() const noexcept; + + /** + * @brief Expands the bounding region to include the given position. + * + * The region will be kept as small as possible. + * + * @param position The position to be included in the region. + * @returns True if the region was modified, or false if the region already + * contained the position. + */ + bool expandToIncludePosition(const Cartographic& position); + +private: + /** + * @brief When a position's latitude is within this distance in radians from + * the North or South pole, its longitude should be considered unreliable and + * not used to expand the bounding region in that direction. + */ + double _poleTolerance; + GlobeRectangle _rectangle; + double _minimumHeight; + double _maximumHeight; + + /** + * @brief True if the region is empty (covers no space) in the longitude + * direction. + * + * We know the rectangle is empty in the latitude direction when South + * is greater than North. But due to wrapping at the anti-meridian, the West + * longitude may very well be greater than the East longitude. So this field + * explicitly tracks whether the region is empty in the longitude direction. + * + * It's possible for the longitude range to be empty while the latitude range + * is not when all of the points used to expand the region so far have been + * too close to the poles to reliably use to compute longitude. + */ + bool _longitudeRangeIsEmpty; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/BoundingRegionWithLooseFittingHeights.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/BoundingRegionWithLooseFittingHeights.h new file mode 100644 index 0000000..bfe9cf1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/BoundingRegionWithLooseFittingHeights.h @@ -0,0 +1,110 @@ +#pragma once + +#include "BoundingRegion.h" +#include "Library.h" + +namespace CesiumGeospatial { + +/** + * @brief A {@link BoundingRegion} whose heights might be very inaccurate and so + * distances should be estimated conservatively for level-of-detail + * computations. + * + * An instance of this class serves as a marker of the imprecision of the + * heights in a {@link BoundingRegion}, and also has a + * {@link BoundingRegionWithLooseFittingHeights::computeConservativeDistanceSquaredToPosition} + * method to compute the conservative distance metric. + */ +class CESIUMGEOSPATIAL_API BoundingRegionWithLooseFittingHeights final { +public: + /** + * @brief Constructs a new bounding region. + * + * @param boundingRegion The bounding region that has imprecise heights. + */ + BoundingRegionWithLooseFittingHeights( + const BoundingRegion& boundingRegion) noexcept; + + /** + * @brief Gets the bounding region that has imprecise heights. + */ + const BoundingRegion& getBoundingRegion() const noexcept { + return this->_region; + } + + /** + * @brief Computes the conservative distance-squared from a position in + * ellipsoid-centered Cartesian coordinates to the closest point in this + * bounding region. + * + * It is conservative in that the distance is computed using whichever + * is _farther away_ of this bounding region's imprecise minimum and maximum + * heights, so the returned distance may be greater than what the distance to + * the bounding region would be if the heights were precise. When used for + * level-of-detail selection, this ensures that imprecise selection caused by + * the imprecise heights will cause _too little_ detail to be loaded rather + * than too much detail. This is important because overestimating the required + * level-of-detail can require an excessive number of tiles to be loaded. + * + * @param position The position. + * @param ellipsoid The ellipsoid on which this region is defined. + * @return The distance-squared from the position to the closest point in the + * bounding region. + */ + double computeConservativeDistanceSquaredToPosition( + const glm::dvec3& position, + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID) const noexcept; + + /** + * @brief Computes the conservative distance-squared from a + * longitude-latitude-height position to the closest point in this bounding + * region. + * + * It is conservative in that the distance is computed using whichever + * is _farther away_ of this bounding region's imprecise minimum and maximum + * heights, so the returned distance may be greater than what the distance to + * the bounding region would be if the heights were precise. When used for + * level-of-detail selection, this ensures that imprecise selection caused by + * the imprecise heights will cause _too little_ detail to be loaded rather + * than too much detail. This is important because overestimating the required + * level-of-detail can require an excessive number of tiles to be loaded. + * + * @param position The position. + * @param ellipsoid The ellipsoid on which this region is defined. + * @return The distance-squared from the position to the closest point in the + * bounding region. + */ + double computeConservativeDistanceSquaredToPosition( + const Cartographic& position, + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID) const noexcept; + + /** + * @brief Computes the conservative distance-squared from a position to the + * closest point in this bounding region, when the longitude-latitude-height + * and ellipsoid-centered Cartesian coordinates of the position are both + * already known. + * + * It is conservative in that the distance is computed using whichever + * is _farther away_ of this bounding region's imprecise minimum and maximum + * heights, so the returned distance may be greater than what the distance to + * the bounding region would be if the heights were precise. When used for + * level-of-detail selection, this ensures that imprecise selection caused by + * the imprecise heights will cause _too little_ detail to be loaded rather + * than too much detail. This is important because overestimating the required + * level-of-detail can require an excessive number of tiles to be loaded. + * + * @param cartographicPosition The position as a longitude-latitude-height. + * @param cartesianPosition The position as ellipsoid-centered Cartesian + * coordinates. + * @return The distance-squared from the position to the closest point in the + * bounding region. + */ + double computeConservativeDistanceSquaredToPosition( + const Cartographic& cartographicPosition, + const glm::dvec3& cartesianPosition) const noexcept; + +private: + BoundingRegion _region; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Cartographic.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Cartographic.h new file mode 100644 index 0000000..32cba01 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Cartographic.h @@ -0,0 +1,72 @@ +#pragma once + +#include "Library.h" + +#include + +namespace CesiumGeospatial { + +/** + * @brief A position defined by longitude, latitude, and height. + */ +class CESIUMGEOSPATIAL_API Cartographic final { +public: + /** + * @brief Creates a new instance. + * + * @param longitudeRadians The longitude, in radians. + * @param latitudeRadians The latitude, in radians. + * @param heightMeters The height, in meters. Default value: 0.0. + */ + constexpr Cartographic( + double longitudeRadians, + double latitudeRadians, + double heightMeters = 0.0) noexcept + : longitude(longitudeRadians), + latitude(latitudeRadians), + height(heightMeters) {} + + /** + * @brief Creates a new instance from a longitude and latitude specified in + * degrees, and a height given in meters. + * + * The values in the resulting object will be in radians. + * + * @param longitudeDegrees The longitude, in degrees. + * @param latitudeDegrees The latitude, in degrees. + * @param heightMeters The height, in meters. Default value: 0.0. + */ + static constexpr Cartographic fromDegrees( + double longitudeDegrees, + double latitudeDegrees, + double heightMeters = 0.0) noexcept { + return Cartographic( + CesiumUtility::Math::degreesToRadians(longitudeDegrees), + CesiumUtility::Math::degreesToRadians(latitudeDegrees), + heightMeters); + } + + /** + * @brief Returns `true` if two cartographics are equal. + */ + constexpr bool operator==(const Cartographic& rhs) const noexcept { + return this->longitude == rhs.longitude && this->latitude == rhs.latitude && + this->height == rhs.height; + }; + + /** + * @brief The longitude, in radians. + */ + double longitude; + + /** + * @brief The latitude, in radians. + */ + double latitude; + + /** + * @brief The height, in meters. + */ + double height; +}; +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/CartographicPolygon.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/CartographicPolygon.h new file mode 100644 index 0000000..e5112b4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/CartographicPolygon.h @@ -0,0 +1,101 @@ +#pragma once + +#include "GlobeRectangle.h" +#include "Library.h" + +#include + +#include +#include +#include + +namespace CesiumGeospatial { + +/** + * @brief A 2D polygon expressed as a list of longitude/latitude coordinates in + * radians. + * + * The {@link Ellipsoid} associated with the coordinates is not specified + * directly by this instance, but it is assumed that the longitude values range + * from -PI to PI radians and the latitude values range from -PI/2 to PI/2 + * radians. Longitude values outside this range are wrapped to be inside the + * range. Latitude values are clamped to the range. + */ +class CESIUMGEOSPATIAL_API CartographicPolygon final { +public: + /** + * @brief Constructs a 2D polygon that can be rasterized onto {@link Cesium3DTilesSelection::Tileset} + * objects. + * + * @param polygon An array of longitude-latitude points in radians defining + * the perimeter of the 2D polygon. + */ + CartographicPolygon(const std::vector& polygon); + + /** + * @brief Returns the longitude-latitude vertices that define the + * perimeter of the selected polygon. + * + * @return The perimeter vertices in longitude-latitude radians. + */ + constexpr const std::vector& getVertices() const { + return this->_vertices; + } + + /** + * @brief Returns the triangulated indices representing a triangle + * decomposition of the polygon. The indices are in reference to the + * polygon's perimeter vertices. + * + * @return The indices for the polygon's triangle decomposition. + */ + constexpr const std::vector& getIndices() const { + return this->_indices; + } + + /** + * @brief Returns a {@link GlobeRectangle} that represents the bounding + * rectangle of the polygon. + * + * @return The polygon's global bounding rectangle. + */ + constexpr const std::optional& + getBoundingRectangle() const { + return this->_boundingRectangle; + } + + /** + * @brief Determines whether a globe rectangle is completely inside any of the + * polygons in a list. + * + * @param rectangle The {@link CesiumGeospatial::GlobeRectangle} of the tile. + * @param cartographicPolygons The list of polygons to check. + * @return True if the rectangle is completely inside a polygon; otherwise, + * false. + */ + static bool rectangleIsWithinPolygons( + const CesiumGeospatial::GlobeRectangle& rectangle, + const std::vector& + cartographicPolygons) noexcept; + + /** + * @brief Determines whether a globe rectangle is completely outside all the + * polygons in a list. + * + * @param rectangle The {@link CesiumGeospatial::GlobeRectangle} of the tile. + * @param cartographicPolygons The list of polygons to check. + * @return True if the rectangle is completely outside all the polygons; + * otherwise, false. + */ + static bool rectangleIsOutsidePolygons( + const CesiumGeospatial::GlobeRectangle& rectangle, + const std::vector& + cartographicPolygons) noexcept; + +private: + std::vector _vertices; + std::vector _indices; + std::optional _boundingRectangle; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/EarthGravitationalModel1996Grid.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/EarthGravitationalModel1996Grid.h new file mode 100644 index 0000000..31f310a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/EarthGravitationalModel1996Grid.h @@ -0,0 +1,60 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include +#include +#include + +namespace CesiumGeospatial { + +class Cartographic; + +/** + * @brief Loads and queries heights from an Earth Gravitational Model 1996 + * (EGM96) grid. + * + * EGM96 is a standard geopotential model of the earth's surface, which can be + * used to obtain an approximation of the mean sea level (MSL) height at any + * location on Earth. + */ +class CESIUMGEOSPATIAL_API EarthGravitationalModel1996Grid final { +public: + /** + * @brief Attempts to create a {@link EarthGravitationalModel1996Grid} from the given buffer. + * + * This method expects the buffer to contain the contents of the WW15MGH.DAC + * 15-arcminute grid. It must be at least 721 * 1440 * 2 = 2,076,480 bytes. + * Any additional bytes at the end of the buffer are ignored. + * + * @returns The instance created from the buffer, or `std::nullopt` if the + * buffer cannot be interpreted as an EGM96 grid. + */ + static std::optional + fromBuffer(const std::span& buffer); + + /** + * @brief Samples the height at the given position. + * + * @param position The position to sample. The `height` is ignored. + * @returns The height (in meters) of the EGM96 surface above the WGS84 + * ellipsoid. A positive value indicates that EGM96 is above the ellipsoid's + * surface, while a negative value indicates that EGM96 is below the + * ellipsoid's surface. + */ + double sampleHeight(const Cartographic& position) const; + +private: + EarthGravitationalModel1996Grid(std::vector&& gridValues); + + /** + * Returns the height of the given grid value, in meters. + */ + double getHeightForIndices(size_t vertical, size_t horizontal) const; + + std::vector _gridValues; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Ellipsoid.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Ellipsoid.h new file mode 100644 index 0000000..71d7b6d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Ellipsoid.h @@ -0,0 +1,193 @@ +#pragma once + +#include "Cartographic.h" +#include "Library.h" + +#include + +#include + +#include + +// The comments are copied here so that the doc comment always shows up in +// Intellisense whether the default is toggled or not. +#ifndef CESIUM_DISABLE_DEFAULT_ELLIPSOID +// To keep from breaking our API, a lot of things now need default Ellipsoid +// parameters. However, we shouldn't rely on these defaults internally, so +// disabling them is a good way to get a compile-time check that they're not +// being used. This macro allows us to toggle this check. +#define CESIUM_DEFAULT_ELLIPSOID = CesiumGeospatial::Ellipsoid::WGS84 +#else +// To keep from breaking our API, a lot of things now need default Ellipsoid +// parameters. However, we shouldn't rely on these defaults internally, so +// disabling them is a good way to get a compile-time check that they're not +// being used. This macro allows us to toggle this check. +#define CESIUM_DEFAULT_ELLIPSOID +#endif + +namespace CesiumGeospatial { + +/** + * @brief A quadratic surface defined in Cartesian coordinates. + * + * The surface is defined by the equation `(x / a)^2 + (y / b)^2 + (z / c)^2 = + * 1`. This is primarily used by Cesium to represent the shape of planetary + * bodies. Rather than constructing this object directly, one of the provided + * constants is normally used. + */ +class CESIUMGEOSPATIAL_API Ellipsoid final { +public: + /** + * @brief An Ellipsoid instance initialized to the WGS84 standard. + * + * The ellipsoid is initialized to the World Geodetic System (WGS84) + * standard, as defined in + * https://earth-info.nga.mil/GandG/publications/tr8350.2/wgs84fin.pdf. + */ + static /*constexpr*/ const Ellipsoid WGS84; + + /** + * @brief An Ellipsoid with all three radii set to one meter. + */ + static const Ellipsoid UNIT_SPHERE; + + /** + * @brief Creates a new instance. + * + * @param x The radius in x-direction. + * @param y The radius in y-direction. + * @param z The radius in z-direction. + */ + constexpr Ellipsoid(double x, double y, double z) noexcept + : Ellipsoid(glm::dvec3(x, y, z)) {} + + /** + * @brief Creates a new instance. + * + * @param radii The radii in x-, y-, and z-direction. + */ + constexpr Ellipsoid(const glm::dvec3& radii) noexcept + : _radii(radii), + _radiiSquared(radii.x * radii.x, radii.y * radii.y, radii.z * radii.z), + _oneOverRadii(1.0 / radii.x, 1.0 / radii.y, 1.0 / radii.z), + _oneOverRadiiSquared( + 1.0 / (radii.x * radii.x), + 1.0 / (radii.y * radii.y), + 1.0 / (radii.z * radii.z)), + _centerToleranceSquared(CesiumUtility::Math::Epsilon1) {} + + /** + * @brief Returns the radii in x-, y-, and z-direction. + */ + constexpr const glm::dvec3& getRadii() const noexcept { return this->_radii; } + + /** + * @brief Computes the normal of the plane tangent to the surface of the + * ellipsoid at the provided position. + * + * @param position The cartesian position for which to to determine the + * surface normal. + * @return The normal. + */ + glm::dvec3 geodeticSurfaceNormal(const glm::dvec3& position) const noexcept; + + /** + * @brief Computes the normal of the plane tangent to the surface of the + * ellipsoid at the provided position. + * + * @param cartographic The {@link Cartographic} position for which to to + * determine the surface normal. + * @return The normal. + */ + glm::dvec3 + geodeticSurfaceNormal(const Cartographic& cartographic) const noexcept; + + /** + * @brief Converts the provided {@link Cartographic} to cartesian + * representation. + * + * @param cartographic The {@link Cartographic} position. + * @return The cartesian representation. + */ + glm::dvec3 + cartographicToCartesian(const Cartographic& cartographic) const noexcept; + + /** + * @brief Converts the provided cartesian to a {@link Cartographic} + * representation. + * + * The result will be the empty optional if the given cartesian is at the + * center of this ellipsoid. + * + * @param cartesian The cartesian position. + * @return The {@link Cartographic} representation, or the empty optional if + * the cartesian is at the center of this ellipsoid. + */ + std::optional + cartesianToCartographic(const glm::dvec3& cartesian) const noexcept; + + /** + * @brief Scales the given cartesian position along the geodetic surface + * normal so that it is on the surface of this ellipsoid. + * + * The result will be the empty optional if the position is at the center of + * this ellipsoid. + * + * @param cartesian The cartesian position. + * @return The scaled position, or the empty optional if + * the cartesian is at the center of this ellipsoid. + */ + std::optional + scaleToGeodeticSurface(const glm::dvec3& cartesian) const noexcept; + + /** + * @brief Scales the provided cartesian position along the geocentric + * surface normal so that it is on the surface of this ellipsoid. + * + * @param cartesian The cartesian position to scale. + * @returns The scaled position, or the empty optional if the cartesian is at + * the center of this ellipsoid. + */ + std::optional + scaleToGeocentricSurface(const glm::dvec3& cartesian) const noexcept; + + /** + * @brief The maximum radius in any dimension. + * + * @return The maximum radius. + */ + constexpr double getMaximumRadius() const noexcept { + return glm::max(this->_radii.x, glm::max(this->_radii.y, this->_radii.z)); + } + + /** + * @brief The minimum radius in any dimension. + * + * @return The minimum radius. + */ + constexpr double getMinimumRadius() const noexcept { + return glm::min(this->_radii.x, glm::min(this->_radii.y, this->_radii.z)); + } + + /** + * @brief Returns `true` if two elliposids are equal. + */ + constexpr bool operator==(const Ellipsoid& rhs) const noexcept { + return this->_radii == rhs._radii; + }; + + /** + * @brief Returns `true` if two elliposids are *not* equal. + */ + constexpr bool operator!=(const Ellipsoid& rhs) const noexcept { + return !(*this == rhs); + }; + +private: + glm::dvec3 _radii; + glm::dvec3 _radiiSquared; + glm::dvec3 _oneOverRadii; + glm::dvec3 _oneOverRadiiSquared; + double _centerToleranceSquared; +}; +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/EllipsoidTangentPlane.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/EllipsoidTangentPlane.h new file mode 100644 index 0000000..c0a730b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/EllipsoidTangentPlane.h @@ -0,0 +1,112 @@ +#pragma once + +#include "Ellipsoid.h" +#include "Library.h" + +#include + +#include +#include +#include + +namespace CesiumGeospatial { + +/** + * @brief A plane tangent to an {@link Ellipsoid} at a certain origin position. + * + * If the origin is not on the surface of the ellipsoid, its surface projection + * will be used. + */ +class CESIUMGEOSPATIAL_API EllipsoidTangentPlane final { +public: + /** + * @brief Creates a new instance. + * + * @param origin The origin, in cartesian coordinates. + * @param ellipsoid The ellipsoid. Default value: {@link Ellipsoid::WGS84}. + * @throws An `std::invalid_argument` if the given origin is at the + * center of the ellipsoid. + */ + EllipsoidTangentPlane( + const glm::dvec3& origin, + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief Creates a new instance. + * + * @param eastNorthUpToFixedFrame A transform that was computed with + * {@link GlobeTransforms::eastNorthUpToFixedFrame}. + * @param ellipsoid The ellipsoid. Default value: {@link Ellipsoid::WGS84}. + */ + EllipsoidTangentPlane( + const glm::dmat4& eastNorthUpToFixedFrame, + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief Returns the {@link Ellipsoid}. + */ + const Ellipsoid& getEllipsoid() const noexcept { return this->_ellipsoid; } + + /** + * @brief Returns the origin, in cartesian coordinates. + */ + const glm::dvec3& getOrigin() const noexcept { return this->_origin; } + + /** + * @brief Returns the x-axis of this plane. + */ + const glm::dvec3& getXAxis() const noexcept { return this->_xAxis; } + + /** + * @brief Returns the y-axis of this plane. + */ + const glm::dvec3& getYAxis() const noexcept { return this->_yAxis; } + + /** + * @brief Returns the z-axis (i.e. the normal) of this plane. + */ + const glm::dvec3& getZAxis() const noexcept { + return this->_plane.getNormal(); + } + + /** + * @brief Returns a {@link CesiumGeometry::Plane} representation of this + * plane. + */ + const CesiumGeometry::Plane& getPlane() const noexcept { + return this->_plane; + } + + /** + * @brief Computes the position of the projection of the given point on this + * plane. + * + * Projects the given point on this plane, along the normal. The result will + * be a 2D point, referring to the local coordinate system of the plane that + * is given by the x- and y-axis. + * + * @param cartesian The point in cartesian coordinates. + * @return The 2D representation of the point on the plane that is closest to + * the given position. + */ + glm::dvec2 + projectPointToNearestOnPlane(const glm::dvec3& cartesian) const noexcept; + +private: + /** + * Computes the matrix that is used for the constructor (if the origin + * and ellipsoid are given), but throws an `std::invalid_argument` if + * the origin is at the center of the ellipsoid. + */ + static glm::dmat4 computeEastNorthUpToFixedFrame( + const glm::dvec3& origin, + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + Ellipsoid _ellipsoid; + glm::dvec3 _origin; + glm::dvec3 _xAxis; + glm::dvec3 _yAxis; + CesiumGeometry::Plane _plane; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GeographicProjection.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GeographicProjection.h new file mode 100644 index 0000000..de65224 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GeographicProjection.h @@ -0,0 +1,155 @@ +#pragma once + +#include "Ellipsoid.h" +#include "GlobeRectangle.h" +#include "Library.h" + +#include + +#include +#include + +namespace CesiumGeospatial { + +class Cartographic; + +/** + * @brief A map projection where longitude and latitude are mapped using an + * {@link Ellipsoid}. + * + * The longitude and latitude are linearly mapped to X and Y by multiplying them + * (in radians) by the {@link Ellipsoid::getMaximumRadius()}. This projection is + * commonly known as geographic, equirectangular, equidistant cylindrical, or + * plate carrée. It is also known as EPSG:4326. + * + * @see WebMercatorProjection + */ +class CESIUMGEOSPATIAL_API GeographicProjection final { +public: + /** + * @brief The maximum bounding rectangle of the geographic projection, + * ranging from -PI to PI radians longitude and + * from -PI/2 to +PI/2 radians latitude. + */ + static constexpr GlobeRectangle MAXIMUM_GLOBE_RECTANGLE = GlobeRectangle( + -CesiumUtility::Math::OnePi, + -CesiumUtility::Math::PiOverTwo, + CesiumUtility::Math::OnePi, + CesiumUtility::Math::PiOverTwo); + + /** + * @brief Computes the maximum rectangle that can be covered with this + * projection + * + * @param ellipsoid The {@link Ellipsoid}. Default value: + * {@link Ellipsoid::WGS84}. + * @return The rectangle + */ + static constexpr CesiumGeometry::Rectangle computeMaximumProjectedRectangle( + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID) noexcept { + const double longitudeValue = + ellipsoid.getMaximumRadius() * CesiumUtility::Math::OnePi; + const double latitudeValue = + ellipsoid.getMaximumRadius() * CesiumUtility::Math::PiOverTwo; + return CesiumGeometry::Rectangle( + -longitudeValue, + -latitudeValue, + longitudeValue, + latitudeValue); + } + + /** + * @brief Constructs a new instance. + * + * @param ellipsoid The {@link Ellipsoid}. + */ + GeographicProjection( + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID) noexcept; + + /** + * @brief Gets the {@link Ellipsoid}. + */ + const Ellipsoid& getEllipsoid() const noexcept { return this->_ellipsoid; } + + /** + * @brief Converts geodedic ellipsoid coordinates to geographic coordinates. + * + * Converts geodetic ellipsoid coordinates, in radians, to the equivalent + * geographic X, Y, Z coordinates expressed in meters. The height is copied + * unmodified to the `z` coordinate. + * + * @param cartographic The geodetic coordinates in radians. + * @returns The equivalent geographic X, Y, Z coordinates, in meters. + */ + glm::dvec3 project(const Cartographic& cartographic) const noexcept; + + /** + * @brief Projects a globe rectangle to geographic coordinates. + * + * This is done by projecting the southwest and northeast corners. + * + * @param rectangle The globe rectangle to project. + * @return The projected rectangle. + */ + CesiumGeometry::Rectangle + project(const CesiumGeospatial::GlobeRectangle& rectangle) const noexcept; + + /** + * @brief Converts geographic coordinates to geodetic ellipsoid coordinates. + * + * Converts geographic X and Y coordinates, expressed in meters, to a + * {@link Cartographic} containing geodetic ellipsoid coordinates. + * The height is set to 0.0. + * + * @param projectedCoordinates The geographic projected coordinates to + * unproject. + * @returns The equivalent cartographic coordinates. + */ + Cartographic unproject(const glm::dvec2& projectedCoordinates) const noexcept; + + /** + * @brief Converts geographic coordinates to geodetic ellipsoid coordinates. + * + * Converts geographic X, Y coordinates, expressed in meters, to a + * {@link Cartographic} containing geodetic ellipsoid coordinates. + * The Z coordinate is copied unmodified to the height. + * + * @param projectedCoordinates The geographic projected coordinates to + * unproject, with height (z) in meters. + * @returns The equivalent cartographic coordinates. + */ + Cartographic unproject(const glm::dvec3& projectedCoordinates) const noexcept; + + /** + * @brief Unprojects a geographic rectangle to the globe. + * + * This is done by unprojecting the southwest and northeast corners. + * + * @param rectangle The rectangle to unproject. + * @returns The unprojected rectangle. + */ + CesiumGeospatial::GlobeRectangle + unproject(const CesiumGeometry::Rectangle& rectangle) const noexcept; + + /** + * @brief Returns `true` if two projections (i.e. their ellipsoids) are equal. + */ + bool operator==(const GeographicProjection& rhs) const noexcept { + return this->_ellipsoid == rhs._ellipsoid; + }; + + /** + * @brief Returns `true` if two projections (i.e. their ellipsoids) are *not* + * equal. + */ + bool operator!=(const GeographicProjection& rhs) const noexcept { + return !(*this == rhs); + }; + +private: + Ellipsoid _ellipsoid; + double _semimajorAxis; + double _oneOverSemimajorAxis; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GlobeAnchor.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GlobeAnchor.h new file mode 100644 index 0000000..0a241e8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GlobeAnchor.h @@ -0,0 +1,137 @@ +#pragma once + +#include "Library.h" + +#include + +#include + +#include + +namespace CesiumGeospatial { + +class LocalHorizontalCoordinateSystem; + +/** + * @brief Anchors an object to the globe by defining a transformation from the + * object's coordinate to the globe-fixed coordinate system (usually + * \ref glossary-ecef). + * + * This class allows the anchored coordinate system to be realized in any + * {@link LocalHorizontalCoordinateSystem}. When the object is moved, either by + * specifying a new globe-fixed transform or a new local transform, the + * orientation may optionally be updated to keep the object upright at its new + * location on the globe. + */ +class CESIUMGEOSPATIAL_API GlobeAnchor final { +public: + /** + * @brief Creates a new instance from a transformation to a local coordinate + * system. + * + * For example, in a game engine, the transformation may be the game + * object's initial transformation to the game engine's world coordinate + * system. + * + * @param localCoordinateSystem The local coordinate system that is the target + * of the transformation. + * @param anchorToLocal The matrix transforming from this object's + * coordinate system to the local coordinate system. + */ + static GlobeAnchor fromAnchorToLocalTransform( + const LocalHorizontalCoordinateSystem& localCoordinateSystem, + const glm::dmat4& anchorToLocal); + + /** + * @brief Creates a new instance from a transformation to the globe-fixed + * coordinate system. + * + * @param anchorToFixed The matrix transforming from this object's + * coordinate system to the globe-fixed coordinate system. + */ + static GlobeAnchor + fromAnchorToFixedTransform(const glm::dmat4& anchorToFixed); + + /** + * @brief Constructs a new instance with a given transformation to the + * globe-fixed coordinate system. + * + * @param anchorToFixed The matrix transforming from this object's + * coordinate system to the globe-fixed coordinate system. + */ + explicit GlobeAnchor(const glm::dmat4& anchorToFixed); + + /** + * @brief Gets the transformation from the anchor's coordinate system to the + * globe-fixed coordinate system. + */ + const glm::dmat4& getAnchorToFixedTransform() const; + + /** + * @brief Sets the new transformation from the anchor's coordinate system + * to globe-fixed coordinates. + * + * @param newAnchorToFixed The new matrix transforming from this object's + * coordinate system to the globe-fixed coordinate system. + * @param adjustOrientation Whether to adjust the anchor's orientation based + * on globe curvature as the anchor moves. The Earth is not flat, so as we + * move across its surface, the direction of "up" changes. If we ignore this + * fact and leave an object's orientation unchanged as it moves over the globe + * surface, the object will become increasingly tilted and eventually be + * completely upside-down when we arrive at the opposite side of the globe. + * When this parameter is true, this method will automatically apply a + * rotation to the anchor to account for globe curvature when the position on + * the globe changes. This parameter should usually be true, but it may be + * useful to set it to false it when the caller already accounts for globe + * curvature itself, because in that case anchor would be over-rotated. + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + */ + void setAnchorToFixedTransform( + const glm::dmat4& newAnchorToFixed, + bool adjustOrientation, + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief Gets the transformation from the anchor's coordinate system to the + * given local-horizontal coordinate system. + */ + glm::dmat4 getAnchorToLocalTransform( + const LocalHorizontalCoordinateSystem& localCoordinateSystem) const; + + /** + * @brief Sets the globe-fixed transformation based on a new transformation + * from anchor coordinates to a local-horizontal coordinate system. + * + * For example, in a game engine, the new transformation may be the game + * object's normal transformation to the game engine's world coordinate + * system. It may need to be updated because the object was just moved by the + * physics engine. + * + * @param localCoordinateSystem The local coordinate system that is the target + * of the transformation. + * @param newAnchorToLocal The new matrix transforming from this object's + * coordinate system to the local coordinate system. + * @param adjustOrientation Whether to adjust the anchor's orientation based + * on globe curvature as the anchor moves. The Earth is not flat, so as we + * move across its surface, the direction of "up" changes. If we ignore this + * fact and leave an object's orientation unchanged as it moves over the globe + * surface, the object will become increasingly tilted and eventually be + * completely upside-down when we arrive at the opposite side of the globe. + * When this parameter is true, this method will automatically apply a + * rotation to the anchor to account for globe curvature when the position on + * the globe changes. This parameter should usually be true, but it may be + * useful to set it to false it when the caller already accounts for globe + * curvature itself, because in that case anchor would be over-rotated. + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + */ + void setAnchorToLocalTransform( + const LocalHorizontalCoordinateSystem& localCoordinateSystem, + const glm::dmat4& newAnchorToLocal, + bool adjustOrientation, + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + +private: + glm::dmat4 _anchorToFixed; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GlobeRectangle.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GlobeRectangle.h new file mode 100644 index 0000000..0705b84 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GlobeRectangle.h @@ -0,0 +1,288 @@ +#pragma once + +#include "Cartographic.h" +#include "Library.h" + +#include +#include + +#include + +namespace CesiumGeospatial { + +/** + * @brief A two-dimensional, rectangular region on a globe, specified using + * longitude and latitude coordinates. The region is rectangular in terms of + * longitude-latitude coordinates, but may be far from rectangular on the actual + * globe surface. + * + * The eastern coordinate may be less than the western coordinate, which + * indicates that the rectangle crosses the anti-meridian. + * + * @see CesiumGeometry::Rectangle + */ +class CESIUMGEOSPATIAL_API GlobeRectangle final { +public: + /** + * @brief An empty rectangle. + * + * The rectangle has the following values: + * * `west`: Pi + * * `south`: Pi/2 + * * `east`: -Pi + * * `north`: -Pi/2 + */ + static const GlobeRectangle EMPTY; + + /** + * @brief The maximum rectangle. + * + * The rectangle has the following values: + * * `west`: -Pi + * * `south`: -Pi/2 + * * `east`: Pi + * * `north`: Pi/2 + */ + static const GlobeRectangle MAXIMUM; + + /** + * @brief Constructs a new instance. + * + * @param west The westernmost longitude, in radians, in the range [-Pi, Pi]. + * @param south The southernmost latitude, in radians, in the range [-Pi/2, + * Pi/2]. + * @param east The easternmost longitude, in radians, in the range [-Pi, Pi]. + * @param north The northernmost latitude, in radians, in the range [-Pi/2, + * Pi/2]. + */ + constexpr GlobeRectangle( + double west, + double south, + double east, + double north) noexcept + : _west(west), _south(south), _east(east), _north(north) {} + + /** + * Creates a rectangle given the boundary longitude and latitude in degrees. + * The angles are converted to radians. + * + * @param westDegrees The westernmost longitude in degrees in the range + * [-180.0, 180.0]. + * @param southDegrees The southernmost latitude in degrees in the range + * [-90.0, 90.0]. + * @param eastDegrees The easternmost longitude in degrees in the range + * [-180.0, 180.0]. + * @param northDegrees The northernmost latitude in degrees in the range + * [-90.0, 90.0]. + * @returns The rectangle. + * + * @snippet TestGlobeRectangle.cpp fromDegrees + */ + static constexpr GlobeRectangle fromDegrees( + double westDegrees, + double southDegrees, + double eastDegrees, + double northDegrees) noexcept { + return GlobeRectangle( + CesiumUtility::Math::degreesToRadians(westDegrees), + CesiumUtility::Math::degreesToRadians(southDegrees), + CesiumUtility::Math::degreesToRadians(eastDegrees), + CesiumUtility::Math::degreesToRadians(northDegrees)); + } + + /** + * @brief Returns the westernmost longitude, in radians. + */ + constexpr double getWest() const noexcept { return this->_west; } + + /** + * @brief Sets the westernmost longitude, in radians. + */ + void setWest(double value) noexcept { this->_west = value; } + + /** + * @brief Returns the southernmost latitude, in radians. + */ + constexpr double getSouth() const noexcept { return this->_south; } + + /** + * @brief Sets the southernmost latitude, in radians. + */ + void setSouth(double value) noexcept { this->_south = value; } + + /** + * @brief Returns the easternmost longitude, in radians. + */ + constexpr double getEast() const noexcept { return this->_east; } + + /** + * @brief Sets the easternmost longitude, in radians. + */ + void setEast(double value) noexcept { this->_east = value; } + + /** + * @brief Returns the northernmost latitude, in radians. + */ + constexpr double getNorth() const noexcept { return this->_north; } + + /** + * @brief Sets the northernmost latitude, in radians. + */ + void setNorth(double value) noexcept { this->_north = value; } + + /** + * @brief Returns the {@link Cartographic} position of the south-west corner. + */ + constexpr Cartographic getSouthwest() const noexcept { + return Cartographic(this->_west, this->_south); + } + + /** + * @brief Returns the {@link Cartographic} position of the south-east corner. + */ + constexpr Cartographic getSoutheast() const noexcept { + return Cartographic(this->_east, this->_south); + } + + /** + * @brief Returns the {@link Cartographic} position of the north-west corner. + */ + constexpr Cartographic getNorthwest() const noexcept { + return Cartographic(this->_west, this->_north); + } + + /** + * @brief Returns the {@link Cartographic} position of the north-east corner. + */ + constexpr Cartographic getNortheast() const noexcept { + return Cartographic(this->_east, this->_north); + } + + /** + * @brief Returns this rectangle as a {@link CesiumGeometry::Rectangle}. + */ + constexpr CesiumGeometry::Rectangle toSimpleRectangle() const noexcept { + return CesiumGeometry::Rectangle( + this->getWest(), + this->getSouth(), + this->getEast(), + this->getNorth()); + } + + /** + * @brief Computes the width of this rectangle. + * + * The result will be in radians, in the range [0, Pi*2]. + */ + constexpr double computeWidth() const noexcept { + double east = this->_east; + const double west = this->_west; + if (east < west) { + east += CesiumUtility::Math::TwoPi; + } + return east - west; + } + + /** + * @brief Computes the height of this rectangle. + * + * The result will be in radians, in the range [0, Pi*2]. + */ + constexpr double computeHeight() const noexcept { + return this->_north - this->_south; + } + + /** + * @brief Computes the {@link Cartographic} center position of this rectangle. + */ + Cartographic computeCenter() const noexcept; + + /** + * @brief Returns `true` if this rectangle contains the given point. + * + * The provided cartographic position must be within the longitude range [-Pi, + * Pi] and the latitude range [-Pi/2, Pi/2]. + * + * This will take into account the wrapping of the longitude at the + * anti-meridian. + */ + bool contains(const Cartographic& cartographic) const noexcept; + + /** + * @brief Determines if this rectangle is empty. + * + * An empty rectangle bounds no part of the globe, not even a single point. + */ + bool isEmpty() const noexcept; + + /** + * @brief Computes the intersection of two rectangles. + * + * This function assumes that the rectangle's coordinates are latitude and + * longitude in radians and produces a correct intersection, taking into + * account the fact that the same angle can be represented with multiple + * values as well as the wrapping of longitude at the anti-meridian. For a + * simple intersection that ignores these factors and can be used with + * projected coordinates, see + * {@link CesiumGeometry::Rectangle::computeIntersection}. + * + * @param other The other rectangle to intersect with this one. + * @returns The intersection rectangle, or `std::nullopt` if there is no + * intersection. + */ + std::optional + computeIntersection(const GlobeRectangle& other) const noexcept; + + /** + * @brief Computes the union of this globe rectangle with another. + * + * @param other The other globe rectangle. + * @return The union. + */ + GlobeRectangle computeUnion(const GlobeRectangle& other) const noexcept; + + /** + * @brief Splits this rectangle at the anti-meridian (180 degrees longitude), + * if necessary. + * + * If the rectangle does not cross the anti-meridian, the entire rectangle is + * returned in the `first` field of the pair and the `second` is std::nullopt. + * If it does cross the anti-meridian, this function returns two rectangles + * that touch but do not cross it. The larger of the two rectangles is + * returned in `first` and the smaller one is returned in `second`. + */ + std::pair> + splitAtAntiMeridian() const noexcept; + + /** + * @brief Checks whether two globe rectangles are exactly equal. + * + * @param left The first rectangle. + * @param right The second rectangle. + * @return Whether the rectangles are equal + */ + static bool + equals(const GlobeRectangle& left, const GlobeRectangle& right) noexcept; + + /** + * @brief Checks whether two globe rectangles are equal up to a given relative + * epsilon. + * + * @param left The first rectangle. + * @param right The second rectangle. + * @param relativeEpsilon The relative epsilon. + * @return Whether the rectangles are epsilon-equal + */ + static bool equalsEpsilon( + const GlobeRectangle& left, + const GlobeRectangle& right, + double relativeEpsilon) noexcept; + +private: + double _west; + double _south; + double _east; + double _north; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GlobeTransforms.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GlobeTransforms.h new file mode 100644 index 0000000..134916a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GlobeTransforms.h @@ -0,0 +1,39 @@ +#pragma once + +#include "Ellipsoid.h" +#include "Library.h" + +#include +#include + +namespace CesiumGeospatial { + +/** + * @brief Transforms between globe-related coordinate systems. + */ +class CESIUMGEOSPATIAL_API GlobeTransforms final { +public: + /** + * @brief Computes a transformation from east-north-up axes to an + * ellipsoid-fixed reference frame. + * + * Computes a 4x4 transformation matrix from a reference frame with an + * east-north-up axes centered at the provided origin to the provided + * ellipsoid's fixed reference frame. The local axes are defined as:
    + *
  • The `x` axis points in the local east direction.
  • + *
  • The `y` axis points in the local north direction.
  • + *
  • The `z` axis points in the direction of the ellipsoid surface normal + * which passes through the position.
  • + *
+ * + * @param origin The center point of the local reference frame. + * @param ellipsoid The {@link Ellipsoid} whose fixed frame is used in the + * transformation. Default value: {@link Ellipsoid::WGS84}. + * @return The transformation matrix + */ + static glm::dmat4x4 eastNorthUpToFixedFrame( + const glm::dvec3& origin, + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID) noexcept; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Library.h new file mode 100644 index 0000000..0315283 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes for geospatial computations in Cesium + * + * @mermaid-interactive{dependencies/CesiumGeospatial} + */ +namespace CesiumGeospatial {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMGEOSPATIAL_BUILDING +#define CESIUMGEOSPATIAL_API __declspec(dllexport) +#else +#define CESIUMGEOSPATIAL_API __declspec(dllimport) +#endif +#else +#define CESIUMGEOSPATIAL_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/LocalHorizontalCoordinateSystem.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/LocalHorizontalCoordinateSystem.h new file mode 100644 index 0000000..cfb6466 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/LocalHorizontalCoordinateSystem.h @@ -0,0 +1,205 @@ +#pragma once + +#include "Ellipsoid.h" +#include "Library.h" + +#include +#include + +namespace CesiumGeospatial { +class Cartographic; +} + +namespace CesiumGeospatial { + +/** + * @brief A local direction, consisting of the four cardinal directions (North, + * South, East, West) combined with Up and Down. + */ +enum class LocalDirection { East, North, West, South, Up, Down }; + +/** + * @brief A coordinate system created from a local horizontal plane at a + * particular origin point on the globe. + * + * Each principal axis in the new coordinate system can be specified to point in + * a particular compass direction, or it can point up or down. In this way, a + * right-handed or left-handed coordinate system can be created. + */ +class CESIUMGEOSPATIAL_API LocalHorizontalCoordinateSystem { +public: + /** + * @brief Create a new coordinate system centered at a given longitude, + * latitude, and ellipsoidal height. + * + * @param origin The origin of the coordinate system. + * @param xAxisDirection The local direction in which the X axis points at the + * origin. + * @param yAxisDirection The local direction in which the Y axis points at the + * origin. + * @param zAxisDirection The local direction in which the Z axis points at the + * origin. + * @param scaleToMeters Local units are converted to meters by multiplying + * them by this factor. For example, if the local units are centimeters, this + * parameter should be 1.0 / 100.0. + * @param ellipsoid The ellipsoid on which the coordinate system is based. + */ + LocalHorizontalCoordinateSystem( + const Cartographic& origin, + LocalDirection xAxisDirection = LocalDirection::East, + LocalDirection yAxisDirection = LocalDirection::North, + LocalDirection zAxisDirection = LocalDirection::Up, + double scaleToMeters = 1.0, + // Can't use CESIUM_DEFAULT_ELLIPSOID here because of the other default + // parameters + const Ellipsoid& ellipsoid = CesiumGeospatial::Ellipsoid::WGS84); + + /** + * @brief Create a new coordinate system centered at a \ref glossary-ecef + * "Earth-Centered, Earth-Fixed" position. + * + * @param originEcef The origin of the coordinate system. + * @param xAxisDirection The local direction in which the X axis points at the + * origin. + * @param yAxisDirection The local direction in which the Y axis points at the + * origin. + * @param zAxisDirection The local direction in which the Z axis points at the + * origin. + * @param scaleToMeters Local units are converted to meters by multiplying + * them by this factor. For example, if the local units are centimeters, this + * parameter should be 1.0 / 100.0. + * @param ellipsoid The ellipsoid on which the coordinate system is based. + */ + LocalHorizontalCoordinateSystem( + const glm::dvec3& originEcef, + LocalDirection xAxisDirection = LocalDirection::East, + LocalDirection yAxisDirection = LocalDirection::North, + LocalDirection zAxisDirection = LocalDirection::Up, + double scaleToMeters = 1.0, + const Ellipsoid& ellipsoid = CesiumGeospatial::Ellipsoid::WGS84); + + /** + * @brief Create a new coordinate system with a specified transformation to + * the \ref glossary-ecef "Earth-Centered, Earth-Fixed" frame. This is an + * advanced constructor and should be avoided in most cases. + * + * This constructor can be used to save/restore the state of an instance. It + * can also be used to create unusual coordinate systems that can't be created + * by the other constructors, such as coordinate systems where the axes aren't + * aligned with compass directions. + * + * @param localToEcef The transformation matrix from this coordinate system to + * the ECEF frame. + */ + explicit LocalHorizontalCoordinateSystem(const glm::dmat4& localToEcef); + + /** + * @brief Create a new coordinate system with the specified transformations + * between the local frame and the + * \ref glossary-ecef "Earth-Centered, Earth-Fixed" frame. This is an advanced + * constructor and should be avoided in most cases. + * + * This constructor can be used to save/restore the state of an instance. It + * can also be used to create unusual coordinate systems that can't be created + * by the other constructors, such as coordinate systems where the axes aren't + * aligned with compass directions. + * + * @param localToEcef The transformation matrix from this coordinate system to + * the ECEF frame. This must be the inverse of `ecefToLocal` or behavior is + * undefined, but this is not enforced. + * @param ecefToLocal The transformation matrix from the ECEF frame to this + * coordinate system. This must be the inverse of `localToEcef` or behavior is + * undefined, but this is not enforced. + */ + LocalHorizontalCoordinateSystem( + const glm::dmat4& localToEcef, + const glm::dmat4& ecefToLocal); + + /** + * @brief Gets the transformation matrix from the local horizontal coordinate + * system managed by this instance to the \ref glossary-ecef. + * + * @return The transformation. + */ + const glm::dmat4& getLocalToEcefTransformation() const noexcept { + return this->_localToEcef; + } + + /** + * @brief Gets the transformation matrix from \ref glossary-ecef to the + * local horizontal coordinate system managed by this instance. + * + * @return The transformation. + */ + const glm::dmat4& getEcefToLocalTransformation() const noexcept { + return this->_ecefToLocal; + }; + + /** + * @brief Converts a position in the local horizontal coordinate system + * managed by this instance to + * \ref glossary-ecef "Earth-Centered, Earth-Fixed (ECEF)". + * + * @param localPosition The position in the local coordinate system. + * @return The equivalent position in the ECEF coordinate system. + */ + glm::dvec3 + localPositionToEcef(const glm::dvec3& localPosition) const noexcept; + + /** + * @brief Converts a position in the + * \ref glossary-ecef "Earth-Centered, Earth-Fixed (ECEF)" coordinate system + * to the local horizontal coordinate system managed by this instance. + * + * @param ecefPosition The position in the ECEF coordinate system. + * @return The equivalent position in the local coordinate system. + */ + glm::dvec3 ecefPositionToLocal(const glm::dvec3& ecefPosition) const noexcept; + + /** + * @brief Converts a direction in the local horizontal coordinate system + * managed by this instance to + * \ref glossary-ecef "Earth-Centered, Earth-Fixed (ECEF)". + * + * Because the vector is treated as a direction only, the translation portion + * of the transformation is ignored. + * + * @param localDirection The direction in the local coordinate system. + * @return The equivalent direction in the ECEF coordinate system. + */ + glm::dvec3 + localDirectionToEcef(const glm::dvec3& localDirection) const noexcept; + + /** + * @brief Converts a direction in the + * \ref glossary-ecef "Earth-Centered, Earth-Fixed (ECEF)" coordinate system + * to the local horizontal coordinate system managed by this instance. + * + * Because the vector is treated as a direction only, the translation portion + * of the transformation is ignored. + * + * @param ecefDirection The direction in the ECEF coordinate system. + * @return The equivalent direction in the local coordinate system. + */ + glm::dvec3 + ecefDirectionToLocal(const glm::dvec3& ecefDirection) const noexcept; + + /** + * @brief Computes the transformation matrix from this local horizontal + * coordinate system to another one. For example, if the returned matrix is + * multiplied with a vector representing a position in this coordinate system, + * the result will be a new vector representing the position in the target + * coordinate system. + * + * @param target The other local horizontal coordinate system. + * @return The transformation. + */ + glm::dmat4 computeTransformationToAnotherLocal( + const LocalHorizontalCoordinateSystem& target) const noexcept; + +private: + glm::dmat4 _ecefToLocal; + glm::dmat4 _localToEcef; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Projection.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Projection.h new file mode 100644 index 0000000..aac8f3c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Projection.h @@ -0,0 +1,140 @@ +#pragma once + +#include "BoundingRegion.h" +#include "CesiumGeometry/AxisAlignedBox.h" +#include "CesiumGeometry/Rectangle.h" +#include "Ellipsoid.h" +#include "GeographicProjection.h" +#include "WebMercatorProjection.h" + +#include + +#include + +namespace CesiumGeospatial { + +/** + * @brief A projection. + * + * This is a `std::variant` of different types of map projections that + * can convert between projected map coordinates and Cartographic coordinates. + * + * @see GeographicProjection + * @see WebMercatorProjection + */ +typedef std::variant Projection; + +/** + * @brief Projects a position on the globe using the given {@link Projection}. + * + * @param projection The projection. + * @param position The {@link Cartographic} position. + * @return The coordinates of the projected point, in the coordinate system + * of the given projection. + */ +glm::dvec3 +projectPosition(const Projection& projection, const Cartographic& position); + +/** + * @brief Unprojects a position from the globe using the given + * {@link Projection}. + * + * @param projection The projection. + * @param position The coordinates of the point, in meters. + * @return The {@link Cartographic} position. + */ +Cartographic +unprojectPosition(const Projection& projection, const glm::dvec3& position); + +/** + * @brief Projects a rectangle on the globe by simply projecting its four + * corners. + * + * This is only accurate when the globe rectangle is still a rectangle after + * projecting, which is true for {@link WebMercatorProjection} but not + * necessarily true for other projections. + * + * @param projection The projection. + * @param rectangle The globe rectangle to be projected. + * @return The projected rectangle. + */ +CesiumGeometry::Rectangle projectRectangleSimple( + const Projection& projection, + const GlobeRectangle& rectangle); + +/** + * @brief Unprojects a rectangle to the globe by simply unprojecting its four + * corners. + * + * This is only accurate when the rectangle is still a rectangle after + * unprojecting, which is true for {@link WebMercatorProjection} but not + * necessarily true for other projections. + * + * @param projection The projection. + * @param rectangle The rectangle to be unprojected. + * @return The unprojected rectangle. + */ +GlobeRectangle unprojectRectangleSimple( + const Projection& projection, + const CesiumGeometry::Rectangle& rectangle); + +/** + * @brief Projects a bounding region on the globe by simply projecting its + * eight corners. + * + * This is only accurate when the globe box is still a box after + * projecting, which is true for {@link WebMercatorProjection} but not + * necessarily true for other projections. + * + * @param projection The projection. + * @param region The bounding region to be projected. + * @return The projected box. + */ +CesiumGeometry::AxisAlignedBox +projectRegionSimple(const Projection& projection, const BoundingRegion& region); + +/** + * @brief Unprojects a box to the globe by simply unprojecting its eight + * corners. + * + * This is only accurate when the box is still a box after + * unprojecting, which is true for {@link WebMercatorProjection} but not + * necessarily true for other projections. + * + * @param projection The projection. + * @param box The box to be unprojected. + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + * @return The unprojected bounding region. + */ +BoundingRegion unprojectRegionSimple( + const Projection& projection, + const CesiumGeometry::AxisAlignedBox& box, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + +/** + * @brief Computes the approximate real-world size, in meters, of a given + * projected rectangle. + * + * The returned X component corresponds to the size in the projected X + * direction, while the returned Y component corresponds to the size in the + * projected Y direction. + * + * @param projection The projection. + * @param rectangle The projected rectangle to measure. + * @param maxHeight The maximum height of the geometry inside the rectangle. + * @param ellipsoid The ellipsoid used to convert longitude and latitude to + * ellipsoid-centered coordinates. + * @return The approximate size. + */ +glm::dvec2 computeProjectedRectangleSize( + const Projection& projection, + const CesiumGeometry::Rectangle& rectangle, + double maxHeight, + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + +/** + * @brief Obtains the ellipsoid used by a Projection variant. + */ +const Ellipsoid& getProjectionEllipsoid(const Projection& projection); + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/S2CellBoundingVolume.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/S2CellBoundingVolume.h new file mode 100644 index 0000000..54456bc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/S2CellBoundingVolume.h @@ -0,0 +1,118 @@ +#pragma once + +#include "BoundingRegion.h" +#include "Ellipsoid.h" +#include "S2CellID.h" + +#include +#include + +#include + +#include +#include +#include + +namespace CesiumGeospatial { + +/** + * A tile bounding volume specified as an S2 cell token with minimum and maximum + * heights. The bounding volume is a k DOP. A k-DOP is the Boolean intersection + * of extents along k directions. + */ +class CESIUMGEOSPATIAL_API S2CellBoundingVolume final { +public: + /** @brief Creates a new \ref S2CellBoundingVolume. + * + * @param cellID The S2 cell ID. + * @param minimumHeight The minimum height of the bounding volume. + * @param maximumHeight The maximum height of the bounding volume. + * @param ellipsoid The ellipsoid. + */ + S2CellBoundingVolume( + const S2CellID& cellID, + double minimumHeight, + double maximumHeight, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief Gets this bounding volume's cell ID. + */ + const S2CellID& getCellID() const { return this->_cellID; } + + /** + * @brief Gets the minimum height of the cell. + */ + double getMinimumHeight() const noexcept { return this->_minimumHeight; } + + /** + * @brief Gets the maximum height of the cell. + */ + double getMaximumHeight() const noexcept { return this->_maximumHeight; } + + /** + * @brief Gets the center of this bounding volume in ellipsoid-fixed (ECEF) + * coordinates. + */ + glm::dvec3 getCenter() const noexcept; + + /** + * @brief Gets the either corners of the bounding volume, in ellipsoid-fixed + * (ECEF) coordinates. + * + * @return An array of positions with a `size()` of 8. + */ + std::span getVertices() const noexcept; + + /** + * @brief Determines on which side of a plane the bounding volume is located. + * + * @param plane The plane to test against. + * @return The {@link CesiumGeometry::CullingResult} + * * `Inside` if the entire region is on the side of the plane the normal is + * pointing. + * * `Outside` if the entire region is on the opposite side. + * * `Intersecting` if the region intersects the plane. + */ + CesiumGeometry::CullingResult + intersectPlane(const CesiumGeometry::Plane& plane) const noexcept; + + /** + * @brief Computes the distance squared from a given position to the closest + * point on this bounding volume. The position must be expressed in + * ellipsoid-centered (ECEF) coordinates. + * + * @param position The position + * @return The estimated distance squared from the bounding box to the point. + * + * @snippet TestOrientedBoundingBox.cpp distanceSquaredTo + */ + double + computeDistanceSquaredToPosition(const glm::dvec3& position) const noexcept; + + /** + * @brief Gets the six planes that bound the volume. + * + * @return An array of planes with a `size()` of 6. + */ + std::span getBoundingPlanes() const noexcept; + + /** + * @brief Computes the bounding begion that best fits this S2 cell volume. + * + * @return The bounding region. + */ + BoundingRegion + computeBoundingRegion(const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) const noexcept; + +private: + S2CellID _cellID; + double _minimumHeight; + double _maximumHeight; + glm::dvec3 _center; + std::array _boundingPlanes; + std::array _vertices; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/S2CellID.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/S2CellID.h new file mode 100644 index 0000000..fe63b58 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/S2CellID.h @@ -0,0 +1,173 @@ +#pragma once + +#include "Cartographic.h" +#include "GlobeRectangle.h" +#include "Library.h" + +#include +#include +#include +#include + +namespace CesiumGeometry { +struct QuadtreeTileID; +} + +namespace CesiumGeospatial { + +/** + * @brief A 64-bit unsigned integer that uniquely identifies a + * cell in the S2 cell decomposition. + * + * It has the following format: + * + * id = [face][face_pos] + * + * face: a 3-bit number (range 0..5) encoding the cube face. + * + * face_pos: a 61-bit number encoding the position of the center of this + * cell along the Hilbert curve over this face (see the Wiki + * pages for details). + * + * Sequentially increasing cell ids follow a continuous space-filling curve + * over the entire sphere. They have the following properties: + * + * - The id of a cell at level k consists of a 3-bit face number followed + * by k bit pairs that recursively select one of the four children of + * each cell. The next bit is always 1, and all other bits are 0. + * Therefore, the level of a cell is determined by the position of its + * lowest-numbered bit that is turned on (for a cell at level k, this + * position is 2 * (kMaxLevel - k).) + * + * - The id of a parent cell is at the midpoint of the range of ids spanned + * by its children (or by its descendants at any level). + * + * This class is adapted from S2CellId in https://github.com/google/s2geometry. + */ +class CESIUMGEOSPATIAL_API S2CellID { +public: + /** + * Creates a new S2Cell from a token. A token is a hexadecimal representation + * of the 64-bit S2CellID. + * + * @param token The token for the S2 Cell. + * @returns A new S2CellID. + */ + static S2CellID fromToken(const std::string_view& token); + + /** + * @brief Creates a cell given its face (range 0..5), level, and Hilbert curve + * cell index within that face and level. + * + * @param face The face index. + * @param level The level within the face. + * @param position The Hilbert-order index of the cell within the face and + * level. + * @return The cell. + */ + static S2CellID + fromFaceLevelPosition(uint8_t face, uint32_t level, uint64_t position); + + /** + * @brief Create an S2 id from a face and a quadtree tile id. + * + * @param face The S2 face (0...5) that this tile is on. + * @param quadtreeTileID The quadtree tile id for this tile, within the given + * face. + */ + static S2CellID fromQuadtreeTileID( + uint8_t face, + const CesiumGeometry::QuadtreeTileID& quadtreeTileID); + + /** + * @brief Constructs a new S2 cell ID. + * + * The cell ID value is not validated. Use {@link isValid} to check the + * validity after constructions. + * + * @param id The 64-bit cell ID value. + */ + S2CellID(uint64_t id); + + /** + * @brief Determines if this cell ID is valid. + * + * @return true if the the cell ID refers to a valid cell; otherwise, false. + */ + bool isValid() const; + + /** + * @brief Gets the ID of the cell. + * + * @return The ID. + */ + uint64_t getID() const { return this->_id; } + + /** + * @brief Converts the cell ID to a hexadecimal token. + */ + std::string toToken() const; + + /** + * @brief Gets the level of the cell from the cell ID. + * + * @return The cell ID, where 0 is the root. + */ + int32_t getLevel() const; + + /** + * @brief Gets the face id (0...5) for this S2 cell. + */ + uint8_t getFace() const; + + /** + * @brief Gets the longitude/latitude position at the center of this cell. + * + * The height is always 0.0. + * + * @return The center. + */ + Cartographic getCenter() const; + + /** + * @brief Gets the vertices at the corners of the cell. + * + * The height values are always 0.0. + * + * Note that all positions inside the S2 Cell are _not_ guaranteed to fall + * inside the rectangle formed by these vertices. + * + * @return Four vertices specifying the corners of this cell. + */ + std::array getVertices() const; + + /** + * @brief Gets the parent cell of this cell. + * + * If this is a root cell, the behavior is unspecified. + */ + S2CellID getParent() const; + + /** + * @brief Gets a child cell of this cell. + * + * If the index is less than 0 or greater than 3, or if this is a leaf cell, + * the behavior is unspecified. + * + * @param index The index in the range 0 to 3. + * @return The child cell. + */ + S2CellID getChild(size_t index) const; + + /** + * @brief Computes the globe rectangle that bounds this cell. + * + * @return The globe rectangle. + */ + GlobeRectangle computeBoundingRectangle() const; + +private: + uint64_t _id; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/SimplePlanarEllipsoidCurve.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/SimplePlanarEllipsoidCurve.h new file mode 100644 index 0000000..685536f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/SimplePlanarEllipsoidCurve.h @@ -0,0 +1,102 @@ +#pragma once + +#include "Library.h" + +#include + +#include + +#include + +namespace CesiumGeospatial { + +/** + * @brief Produces points on an ellipse that lies on a plane that intersects the + * center of the earth and each of the input coordinates. The height above the + * surface at each point along the curve will be a linear interpolation between + * the source and destination heights. + */ +class CESIUMGEOSPATIAL_API SimplePlanarEllipsoidCurve final { +public: + /** + * @brief Creates a new instance of {@link SimplePlanarEllipsoidCurve} from a + * source and destination specified in Earth-Centered, Earth-Fixed + * coordinates. + * + * @param ellipsoid The ellipsoid that the source and destination positions + * are relative to. + * @param sourceEcef The position that the path will begin at in ECEF + * coordinates. + * @param destinationEcef The position that the path will end at in ECEF + * coordinates. + * + * @returns An optional type containing a {@link SimplePlanarEllipsoidCurve} + * object representing the generated path, if possible. If it wasn't possible + * to scale the input coordinates to geodetic surface coordinates on a WGS84 + * ellipsoid, this will return `std::nullopt` instead. + */ + static std::optional + fromEarthCenteredEarthFixedCoordinates( + const Ellipsoid& ellipsoid, + const glm::dvec3& sourceEcef, + const glm::dvec3& destinationEcef); + + /** + * @brief Creates a new instance of {@link SimplePlanarEllipsoidCurve} from a + * source and destination specified in cartographic coordinates (Longitude, + * Latitude, and Height). + * + * @param ellipsoid The ellipsoid that these cartographic coordinates are + * from. + * @param source The position that the path will begin at in Longitude, + * Latitude, and Height. + * @param destination The position that the path will end at in Longitude, + * Latitude, and Height. + * + * @returns An optional type containing a {@link SimplePlanarEllipsoidCurve} + * object representing the generated path, if possible. If it wasn't possible + * to scale the input coordinates to geodetic surface coordinates on a WGS84 + * ellipsoid, this will return std::nullopt instead. + */ + static std::optional fromLongitudeLatitudeHeight( + const Ellipsoid& ellipsoid, + const Cartographic& source, + const Cartographic& destination); + + /** + * @brief Samples the curve at the given percentage of its length. + * + * @param percentage The percentage of the curve's length to sample at, + * where 0 is the beginning and 1 is the end. This value will be clamped to + * the range [0..1]. + * @param additionalHeight The height above the earth at this position will be + * calculated by interpolating between the height at the beginning and end of + * the curve based on the value of \p percentage. This parameter specifies an + * additional offset to add to the height. + * + * @returns The position of the given point on this curve in Earth-Centered + * Earth-Fixed coordinates. + */ + glm::dvec3 + getPosition(double percentage, double additionalHeight = 0.0) const; + +private: + SimplePlanarEllipsoidCurve( + const Ellipsoid& ellipsoid, + const glm::dvec3& scaledSourceEcef, + const glm::dvec3& scaledDestinationEcef, + const glm::dvec3& originalSourceEcef, + const glm::dvec3& originalDestinationEcef); + + double _totalAngle; + double _sourceHeight; + double _destinationHeight; + + Ellipsoid _ellipsoid; + glm::dvec3 _sourceDirection; + glm::dvec3 _rotationAxis; + glm::dvec3 _sourceEcef; + glm::dvec3 _destinationEcef; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/WebMercatorProjection.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/WebMercatorProjection.h new file mode 100644 index 0000000..457ba50 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/WebMercatorProjection.h @@ -0,0 +1,176 @@ +#pragma once + +#include "Ellipsoid.h" +#include "GlobeRectangle.h" +#include "Library.h" + +#include +#include + +namespace CesiumGeospatial { + +class Cartographic; + +/** + * @brief The map projection used by Google Maps, Bing Maps, and most of ArcGIS + * Online, EPSG:3857. + * + * This projection uses geodetic longitude and latitude expressed with WGS84 and + * transforms them to Mercator using the spherical (rather than ellipsoidal) + * equations. + * + * @see GeographicProjection + */ +class CESIUMGEOSPATIAL_API WebMercatorProjection final { +public: + /** + * @brief The maximum latitude (both North and South) supported by a Web + * Mercator (EPSG:3857) projection. + * + * Technically, the Mercator projection is defined for any latitude + * up to (but not including) 90 degrees, but it makes sense + * to cut it off sooner because it grows exponentially with increasing + * latitude. The logic behind this particular cutoff value, which is the one + * used by Google Maps, Bing Maps, and Esri, is that it makes the projection + * square. That is, the rectangle is equal in the X and Y directions. + * + * The constant value is computed by calling: + * `CesiumGeospatial::WebMercatorProjection::mercatorAngleToGeodeticLatitude(CesiumUtility::Math::OnePi)` + */ + static const double MAXIMUM_LATITUDE; + + /** + * @brief The maximum bounding rectangle of the Web Mercator projection, + * ranging from -PI to PI radians longitude and + * from -MAXIMUM_LATITUDE to +MAXIMUM_LATITUDE. + */ + static const GlobeRectangle MAXIMUM_GLOBE_RECTANGLE; + + /** + * @brief Computes the maximum rectangle that can be covered with this + * projection + * + * @param ellipsoid The {@link Ellipsoid}. Default value: + * {@link Ellipsoid::WGS84}. + * @return The rectangle + */ + static constexpr CesiumGeometry::Rectangle computeMaximumProjectedRectangle( + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID) noexcept { + const double value = + ellipsoid.getMaximumRadius() * CesiumUtility::Math::OnePi; + return CesiumGeometry::Rectangle(-value, -value, value, value); + } + + /** + * @brief Constructs a new instance. + * + * @param ellipsoid The {@link Ellipsoid}. + */ + WebMercatorProjection( + const Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID) noexcept; + + /** + * @brief Gets the {@link Ellipsoid}. + */ + const Ellipsoid& getEllipsoid() const noexcept { return this->_ellipsoid; } + + /** + * @brief Converts geodedic ellipsoid coordinates to Web Mercator coordinates. + * + * Converts geodetic ellipsoid coordinates, in radians, to the equivalent Web + * Mercator X, Y, Z coordinates expressed in meters. The height is copied + * unmodified to the `z` coordinate. + * + * @param cartographic The geodetic coordinates in radians. + * @returns The equivalent web mercator X, Y, Z coordinates, in meters. + */ + glm::dvec3 project(const Cartographic& cartographic) const noexcept; + + /** + * @brief Projects a globe rectangle to Web Mercator coordinates. + * + * This is done by projecting the southwest and northeast corners. + * + * @param rectangle The globe rectangle to project. + * @return The projected rectangle. + */ + CesiumGeometry::Rectangle + project(const CesiumGeospatial::GlobeRectangle& rectangle) const noexcept; + + /** + * @brief Converts Web Mercator coordinates to geodetic ellipsoid coordinates. + * + * Converts Web Mercator X and Y coordinates, expressed in meters, to a + * {@link Cartographic} containing geodetic ellipsoid coordinates. + * The height is set to 0.0. + * + * @param projectedCoordinates The web mercator projected coordinates to + * unproject. + * @returns The equivalent cartographic coordinates. + */ + Cartographic unproject(const glm::dvec2& projectedCoordinates) const noexcept; + + /** + * @brief Converts Web Mercator coordinates to geodetic ellipsoid coordinates. + * + * Converts Web Mercator X, Y coordinates, expressed in meters, to a + * {@link Cartographic} containing geodetic ellipsoid coordinates. + * The Z coordinate is copied unmodified to the height. + * + * @param projectedCoordinates The web mercator projected coordinates to + * unproject, with height (z) in meters. + * @returns The equivalent cartographic coordinates. + */ + Cartographic unproject(const glm::dvec3& projectedCoordinates) const noexcept; + + /** + * @brief Unprojects a Web Mercator rectangle to the globe. + * + * This is done by unprojecting the southwest and northeast corners. + * + * @param rectangle The rectangle to unproject. + * @returns The unprojected rectangle. + */ + CesiumGeospatial::GlobeRectangle + unproject(const CesiumGeometry::Rectangle& rectangle) const noexcept; + + /** + * @brief Converts a Mercator angle, in the range -PI to PI, to a geodetic + * latitude in the range -PI/2 to PI/2. + * + * @param mercatorAngle The angle to convert. + * @returns The geodetic latitude in radians. + */ + static double mercatorAngleToGeodeticLatitude(double mercatorAngle) noexcept; + + /** + * @brief Converts a geodetic latitude in radians, in the range -PI/2 to PI/2, + * to a Mercator angle in the range -PI to PI. + * + * @param latitude The geodetic latitude in radians. + * @returns The Mercator angle. + */ + static double geodeticLatitudeToMercatorAngle(double latitude) noexcept; + + /** + * @brief Returns `true` if two projections (i.e. their ellipsoids) are equal. + */ + bool operator==(const WebMercatorProjection& rhs) const noexcept { + return this->_ellipsoid == rhs._ellipsoid; + }; + + /** + * @brief Returns `true` if two projections (i.e. their ellipsoids) are *not* + * equal. + */ + bool operator!=(const WebMercatorProjection& rhs) const noexcept { + return !(*this == rhs); + }; + +private: + Ellipsoid _ellipsoid; + double _semimajorAxis; + double _oneOverSemimajorAxis; +}; + +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/calcQuadtreeMaxGeometricError.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/calcQuadtreeMaxGeometricError.h new file mode 100644 index 0000000..1134b26 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/calcQuadtreeMaxGeometricError.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Ellipsoid.h" + +#include + +namespace CesiumGeospatial { +/** + * @brief Computes the maximum geometric error per radian of a quadtree with + * certain assumptions. + * + * The geometric error for a tile can be computed by multiplying the value + * returned by this function by the width of the tile in radians. + * + * This function computes a suitable geometric error for a 65x65 terrain + * heightmap where the vertical error is 25% of the horizontal spacing between + * height samples at the equator. + * + * @param ellipsoid The ellipsoid. + * @return The max geometric error. + */ +double calcQuadtreeMaxGeometricError( + const CesiumGeospatial::Ellipsoid& ellipsoid) noexcept; +} // namespace CesiumGeospatial diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Accessor.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Accessor.h new file mode 100644 index 0000000..1612621 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Accessor.h @@ -0,0 +1,97 @@ +#pragma once + +#include "CesiumGltf/AccessorSpec.h" +#include "CesiumGltf/Library.h" + +#include + +namespace CesiumGltf { +struct Model; + +/** @copydoc AccessorSpec */ +struct CESIUMGLTF_API Accessor final : public AccessorSpec { + /** + * @brief Computes the number of components for a given accessor type. + * + * For example `CesiumGltf::Accessor::Type::SCALAR` has 1 component while + * `CesiumGltf::Accessor::Type::VEC4` has 4 components. + * + * @param type The accessor type. + * @return The number of components. Returns 0 if {@link Accessor::type} is + * not a valid enumeration value. + */ + static int8_t computeNumberOfComponents(const std::string& type) noexcept; + + /** + * @brief Computes the number of bytes for a given accessor component type. + * + * For example `CesiumGltf::Accessor::ComponentType::UNSIGNED_SHORT` is 2 + * bytes while `CesiumGltf::Accessor::ComponentType::FLOAT` is 4 bytes. + * + * @param componentType The accessor component type. + * @return The number of bytes for the component type. Returns 0 if + * {@link Accessor::componentType} is not a valid enumeration value. + */ + static int8_t computeByteSizeOfComponent(int32_t componentType) noexcept; + + Accessor() = default; + + /** + * @brief Computes the number of components for this accessor. + * + * For example if this accessor's {@link Accessor::type} is + * `CesiumGltf::Accessor::Type::SCALAR`, then it has 1 component, while if + * it's `CesiumGltf::Accessor::Type::VEC4` it has 4 components. + * + * @return The number of components in this accessor. Returns 0 if this + * accessor's {@link Accessor::type} does not have a valid enumeration value. + */ + int8_t computeNumberOfComponents() const noexcept; + + /** + * @brief Computes the number of bytes for this accessor's component type. + * + * For example if this accessor's {@link Accessor::componentType} is + * `CesiumGltf::Accessor::ComponentType::UNSIGNED_SHORT`, then the component + * type is 2 bytes, while if it's `CesiumGltf::Accessor::ComponentType::FLOAT` + * then it is 4 bytes. + * + * @return The number of bytes for this accessor's component type. Returns 0 + * if this accessor's {@link Accessor::componentType} does not have a valid + * enumeration value. + */ + int8_t computeByteSizeOfComponent() const noexcept; + + /** + * @brief Computes the total number of bytes for this accessor in each vertex. + * + * This is computed by multiplying + * {@link Accessor::computeByteSizeOfComponent} by + * {@link Accessor::computeNumberOfComponents}. + * + * @return The total number of bytes for this accessor in each vertex. Returns + * 0 if this accessor's {@link Accessor::type} or + * {@link Accessor::componentType} does not have a valid enumeration + * value. + */ + int64_t computeBytesPerVertex() const noexcept; + + /** + * @brief Computes this accessor's stride. + * + * The stride is the number of bytes between the same elements of successive + * vertices. The returned value will be at least as large as + * {@link Accessor::computeBytesPerVertex}, but maybe be larger if this + * accessor's data is interleaved with other accessors. + * + * The behavior is undefined if this accessor is not part of the given model. + * + * @param model The model that this accessor is a part of. + * @return The stride in bytes. Returns 0 if this accessor's + * {@link Accessor::type} or {@link Accessor::componentType} does not have + * a valid enumeration value, or if {@link Accessor::bufferView} does not + * refer to a valid {@link BufferView}. + */ + int64_t computeByteStride(const CesiumGltf::Model& model) const noexcept; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSparse.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSparse.h new file mode 100644 index 0000000..db85dfc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSparse.h @@ -0,0 +1,60 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief Sparse storage of accessor values that deviate from their + * initialization value. + */ +struct CESIUMGLTF_API AccessorSparse final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "AccessorSparse"; + + /** + * @brief Number of deviating accessor values stored in the sparse array. + */ + int64_t count = int64_t(); + + /** + * @brief An object pointing to a buffer view containing the indices of + * deviating accessor values. The number of indices is equal to `count`. + * Indices **MUST** strictly increase. + */ + CesiumGltf::AccessorSparseIndices indices; + + /** + * @brief An object pointing to a buffer view containing the deviating + * accessor values. + */ + CesiumGltf::AccessorSparseValues values; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(AccessorSparse)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += this->indices.getSizeBytes() - + int64_t(sizeof(CesiumGltf::AccessorSparseIndices)); + accum += this->values.getSizeBytes() - + int64_t(sizeof(CesiumGltf::AccessorSparseValues)); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSparseIndices.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSparseIndices.h new file mode 100644 index 0000000..3d85f0d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSparseIndices.h @@ -0,0 +1,73 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief An object pointing to a buffer view containing the indices of + * deviating accessor values. The number of indices is equal to + * `accessor.sparse.count`. Indices **MUST** strictly increase. + */ +struct CESIUMGLTF_API AccessorSparseIndices final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "AccessorSparseIndices"; + + /** + * @brief Known values for The indices data type. + */ + struct ComponentType { + /** @brief UNSIGNED_BYTE (`5121`) */ + static constexpr int32_t UNSIGNED_BYTE = 5121; + + /** @brief UNSIGNED_SHORT (`5123`) */ + static constexpr int32_t UNSIGNED_SHORT = 5123; + + /** @brief UNSIGNED_INT (`5125`) */ + static constexpr int32_t UNSIGNED_INT = 5125; + }; + + /** + * @brief The index of the buffer view with sparse indices. The referenced + * buffer view **MUST NOT** have its `target` or `byteStride` properties + * defined. The buffer view and the optional `byteOffset` **MUST** be aligned + * to the `componentType` byte length. + */ + int32_t bufferView = -1; + + /** + * @brief The offset relative to the start of the buffer view in bytes. + */ + int64_t byteOffset = 0; + + /** + * @brief The indices data type. + * + * Known values are defined in {@link ComponentType}. + * + */ + int32_t componentType = ComponentType::UNSIGNED_BYTE; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(AccessorSparseIndices)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSparseValues.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSparseValues.h new file mode 100644 index 0000000..f61c0a1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSparseValues.h @@ -0,0 +1,52 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief An object pointing to a buffer view containing the deviating accessor + * values. The number of elements is equal to `accessor.sparse.count` times + * number of components. The elements have the same component type as the base + * accessor. The elements are tightly packed. Data **MUST** be aligned following + * the same rules as the base accessor. + */ +struct CESIUMGLTF_API AccessorSparseValues final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "AccessorSparseValues"; + + /** + * @brief The index of the bufferView with sparse values. The referenced + * buffer view **MUST NOT** have its `target` or `byteStride` properties + * defined. + */ + int32_t bufferView = -1; + + /** + * @brief The offset relative to the start of the bufferView in bytes. + */ + int64_t byteOffset = 0; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(AccessorSparseValues)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSpec.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSpec.h new file mode 100644 index 0000000..ad682ae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSpec.h @@ -0,0 +1,204 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief A typed view into a buffer view that contains raw binary data. + */ +struct CESIUMGLTF_API AccessorSpec : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Accessor"; + + /** + * @brief Known values for The datatype of the accessor's components. + */ + struct ComponentType { + /** @brief BYTE (`5120`) */ + static constexpr int32_t BYTE = 5120; + + /** @brief UNSIGNED_BYTE (`5121`) */ + static constexpr int32_t UNSIGNED_BYTE = 5121; + + /** @brief SHORT (`5122`) */ + static constexpr int32_t SHORT = 5122; + + /** @brief UNSIGNED_SHORT (`5123`) */ + static constexpr int32_t UNSIGNED_SHORT = 5123; + + /** @brief INT (`5124`) */ + static constexpr int32_t INT = 5124; + + /** @brief UNSIGNED_INT (`5125`) */ + static constexpr int32_t UNSIGNED_INT = 5125; + + /** @brief INT64 (`5134`) */ + static constexpr int32_t INT64 = 5134; + + /** @brief UNSIGNED_INT64 (`5135`) */ + static constexpr int32_t UNSIGNED_INT64 = 5135; + + /** @brief FLOAT (`5126`) */ + static constexpr int32_t FLOAT = 5126; + + /** @brief DOUBLE (`5130`) */ + static constexpr int32_t DOUBLE = 5130; + }; + + /** + * @brief Known values for Specifies if the accessor's elements are scalars, + * vectors, or matrices. + */ + struct Type { + /** @brief `SCALAR` */ + inline static const std::string SCALAR = "SCALAR"; + + /** @brief `VEC2` */ + inline static const std::string VEC2 = "VEC2"; + + /** @brief `VEC3` */ + inline static const std::string VEC3 = "VEC3"; + + /** @brief `VEC4` */ + inline static const std::string VEC4 = "VEC4"; + + /** @brief `MAT2` */ + inline static const std::string MAT2 = "MAT2"; + + /** @brief `MAT3` */ + inline static const std::string MAT3 = "MAT3"; + + /** @brief `MAT4` */ + inline static const std::string MAT4 = "MAT4"; + }; + + /** + * @brief The index of the bufferView. + * + * The index of the buffer view. When undefined, the accessor **MUST** be + * initialized with zeros; `sparse` property or extensions **MAY** override + * zeros with actual values. + */ + int32_t bufferView = -1; + + /** + * @brief The offset relative to the start of the buffer view in bytes. + * + * This **MUST** be a multiple of the size of the component datatype. This + * property **MUST NOT** be defined when `bufferView` is undefined. + */ + int64_t byteOffset = 0; + + /** + * @brief The datatype of the accessor's components. + * + * Known values are defined in {@link ComponentType}. + * + * + * UNSIGNED_INT type **MUST NOT** be used for any accessor that is not + * referenced by `mesh.primitive.indices`. + */ + int32_t componentType = ComponentType::BYTE; + + /** + * @brief Specifies whether integer data values are normalized before usage. + * + * Specifies whether integer data values are normalized (`true`) to [0, 1] + * (for unsigned types) or to [-1, 1] (for signed types) when they are + * accessed. This property **MUST NOT** be set to `true` for accessors with + * `FLOAT` or `UNSIGNED_INT` component type. + */ + bool normalized = false; + + /** + * @brief The number of elements referenced by this accessor. + * + * The number of elements referenced by this accessor, not to be confused with + * the number of bytes or number of components. + */ + int64_t count = int64_t(); + + /** + * @brief Specifies if the accessor's elements are scalars, vectors, or + * matrices. + * + * Known values are defined in {@link Type}. + * + */ + std::string type = Type::SCALAR; + + /** + * @brief Maximum value of each component in this accessor. + * + * Array elements **MUST** be treated as having the same data type as + * accessor's `componentType`. Both `min` and `max` arrays have the same + * length. The length is determined by the value of the `type` property; it + * can be 1, 2, 3, 4, 9, or 16. + * + * `normalized` property has no effect on array values: they always correspond + * to the actual values stored in the buffer. When the accessor is sparse, + * this property **MUST** contain maximum values of accessor data with sparse + * substitution applied. + */ + std::vector max; + + /** + * @brief Minimum value of each component in this accessor. + * + * Array elements **MUST** be treated as having the same data type as + * accessor's `componentType`. Both `min` and `max` arrays have the same + * length. The length is determined by the value of the `type` property; it + * can be 1, 2, 3, 4, 9, or 16. + * + * `normalized` property has no effect on array values: they always correspond + * to the actual values stored in the buffer. When the accessor is sparse, + * this property **MUST** contain minimum values of accessor data with sparse + * substitution applied. + */ + std::vector min; + + /** + * @brief Sparse storage of elements that deviate from their initialization + * value. + */ + std::optional sparse; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(AccessorSpec)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + accum += int64_t(sizeof(double) * this->max.capacity()); + accum += int64_t(sizeof(double) * this->min.capacity()); + if (this->sparse) { + accum += this->sparse->getSizeBytes() - + int64_t(sizeof(CesiumGltf::AccessorSparse)); + } + return accum; + } + +protected: + /** + * @brief This class is not meant to be instantiated directly. Use {@link Accessor} instead. + */ + AccessorSpec() = default; + friend struct Accessor; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorUtility.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorUtility.h new file mode 100644 index 0000000..b2dfa40 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorUtility.h @@ -0,0 +1,399 @@ +#pragma once + +#include "AccessorView.h" + +#include + +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief Visitor that retrieves the count of elements in the given accessor + * type as an int64_t. + */ +struct CountFromAccessor { + /** @brief Attempts to obtain an element count from an empty accessor variant, + * resulting in 0. */ + int64_t operator()(std::monostate) { return 0; } + + /** @brief Attempts to obtain an element count from an \ref AccessorView. */ + template int64_t operator()(const AccessorView& value) { + return value.size(); + } +}; + +/** + * @brief Visitor that retrieves the status from the given accessor. Returns an + * invalid status for a std::monostate (interpreted as a nonexistent accessor). + */ +struct StatusFromAccessor { + /** @brief Attempts to obtain an \ref AccessorViewStatus from an empty + * accessor variant, resulting in \ref + * AccessorViewStatus::InvalidAccessorIndex. */ + AccessorViewStatus operator()(std::monostate) { + return AccessorViewStatus::InvalidAccessorIndex; + } + + /** @brief Attempts to obtain an \ref AccessorViewStatus from an \ref + * AccessorView. */ + template + AccessorViewStatus operator()(const AccessorView& value) { + return value.status(); + } +}; + +/** + * Type definition for position accessor. + */ +typedef AccessorView> PositionAccessorType; + +/** + * Retrieves an accessor view for the position attribute from the given glTF + * primitive and model. This verifies that the accessor is of a valid type. If + * not, the returned accessor view will be invalid. + */ +PositionAccessorType +getPositionAccessorView(const Model& model, const MeshPrimitive& primitive); + +/** + * Type definition for normal accessor. + */ +typedef AccessorView> NormalAccessorType; + +/** + * Retrieves an accessor view for the normal attribute from the given glTF + * primitive and model. This verifies that the accessor is of a valid type. If + * not, the returned accessor view will be invalid. + */ +NormalAccessorType +getNormalAccessorView(const Model& model, const MeshPrimitive& primitive); + +/** + * Type definition for all kinds of feature ID attribute accessors. + */ +typedef std::variant< + AccessorView, + AccessorView, + AccessorView, + AccessorView, + AccessorView, + AccessorView> + FeatureIdAccessorType; + +/** + * Retrieves an accessor view for the specified feature ID attribute from the + * given glTF primitive and model. This verifies that the accessor is of a valid + * type. If not, the returned accessor view will be invalid. + */ +FeatureIdAccessorType getFeatureIdAccessorView( + const Model& model, + const MeshPrimitive& primitive, + int32_t featureIdAttributeIndex); + +/** + * Retrieves an accessor view for the specified feature ID attribute from the + * given glTF node and model, if the node contains an EXT_mesh_gpu_instancing + * property. This verifies that the accessor is of a valid type. If not, the + * returned accessor view will be invalid. + */ +FeatureIdAccessorType getFeatureIdAccessorView( + const Model& model, + const Node& node, + int32_t featureIdAttributeIndex); + +/** + * Visitor that retrieves the feature ID from the given accessor type as an + * int64_t. This should be initialized with the index of the vertex whose + * feature ID is being queried. + * + * -1 is used to indicate errors retrieving the feature ID, e.g., if the given + * index was out-of-bounds. + */ +struct FeatureIdFromAccessor { + /** @brief Attempts to obtain a feature ID from an \ref AccessorView over + * float values, returning the float value rounded to the nearest `int64_t`. + */ + int64_t operator()(const AccessorView& value) { + if (index < 0 || index >= value.size()) { + return -1; + } + return static_cast(glm::round(value[index])); + } + + /** @brief Attempts to obtain a feature ID from an \ref AccessorView. */ + template int64_t operator()(const AccessorView& value) { + if (index < 0 || index >= value.size()) { + return -1; + } + return static_cast(value[index]); + } + + /** @brief The index of the vertex whose feature ID is being queried. */ + int64_t index; +}; + +/** + * Type definition for all kinds of index accessors. std::monostate + * indicates a nonexistent accessor, which can happen (and is valid) if the + * primitive vertices are defined without an index buffer. + */ +typedef std::variant< + std::monostate, + AccessorView, + AccessorView, + AccessorView> + IndexAccessorType; + +/** + * Retrieves an accessor view for the indices of the given glTF primitive from + * the model. The primitive may not specify any indices; if so, std::monostate + * is returned. + */ +IndexAccessorType +getIndexAccessorView(const Model& model, const MeshPrimitive& primitive); + +/** + * Visitor that retrieves the vertex indices from the given accessor type + * corresponding to a given face index. These indices are returned as an array + * of int64_ts. This should be initialized with the index of the face, the + * total number of vertices in the primitive, and the + * `CesiumGltf::MeshPrimitive::Mode` of the primitive. + * + * -1 is used to indicate errors retrieving the index, e.g., if the given + * index was out-of-bounds. + */ +struct IndicesForFaceFromAccessor { + /** @brief Attempts to obtain the indices for the given face from an empty + * accessor variant, using the \ref vertexCount property. */ + std::array operator()(std::monostate) { + int64_t firstVertex = faceIndex; + int64_t numFaces = 0; + + switch (primitiveMode) { + case MeshPrimitive::Mode::TRIANGLE_STRIP: + numFaces = vertexCount - 2; + break; + case MeshPrimitive::Mode::TRIANGLE_FAN: + numFaces = vertexCount - 2; + firstVertex++; + break; + case MeshPrimitive::Mode::TRIANGLES: + numFaces = vertexCount / 3; + firstVertex *= 3; + break; + default: + // Unsupported primitive mode. + return {-1, -1, -1}; + } + + if (faceIndex < 0 || faceIndex >= numFaces) { + return {-1, -1, -1}; + } + + std::array result; + + if (primitiveMode == MeshPrimitive::Mode::TRIANGLE_FAN) { + result[0] = 0; + result[1] = firstVertex < vertexCount ? firstVertex : -1; + result[2] = firstVertex + 1 < vertexCount ? firstVertex + 1 : -1; + } else { + for (int64_t i = 0; i < 3; i++) { + int64_t vertexIndex = firstVertex + i; + result[i] = vertexIndex < vertexCount ? vertexIndex : -1; + } + } + + return result; + } + + /** @brief Attempts to obtain the indices for the given face from an \ref + * AccessorView, using the view's size and contents rather than the \ref + * vertexCount property. */ + template + std::array operator()(const AccessorView& value) { + int64_t firstIndex = faceIndex; + int64_t numFaces = 0; + + switch (primitiveMode) { + case MeshPrimitive::Mode::TRIANGLE_STRIP: + numFaces = value.size() - 2; + break; + case MeshPrimitive::Mode::TRIANGLE_FAN: + numFaces = value.size() - 2; + firstIndex++; + break; + case MeshPrimitive::Mode::TRIANGLES: + numFaces = value.size() / 3; + firstIndex *= 3; + break; + default: + // Unsupported primitive mode. + return {-1, -1, -1}; + } + + if (faceIndex < 0 || faceIndex >= numFaces) { + return {-1, -1, -1}; + } + + std::array result; + + if (primitiveMode == MeshPrimitive::Mode::TRIANGLE_FAN) { + result[0] = value[0]; + result[1] = firstIndex < value.size() ? value[firstIndex] : -1; + result[2] = firstIndex + 1 < value.size() ? value[firstIndex + 1] : -1; + } else { + for (int64_t i = 0; i < 3; i++) { + int64_t index = firstIndex + i; + result[i] = index < value.size() ? value[index] : -1; + } + } + + return result; + } + + /** @brief The index of the face to obtain indices for. */ + int64_t faceIndex; + /** @brief The total number of vertices in the data being accessed. */ + int64_t vertexCount; + /** @brief The \ref MeshPrimitive::Mode of the data being accessed. */ + int32_t primitiveMode; +}; // namespace CesiumGltf + +/** + * Visitor that retrieves the vertex index from the given accessor type as an + * int64_t. This should be initialized with the index (within the + * accessor itself) of the vertex index. + * + * -1 is used to indicate errors retrieving the index, e.g., if the given + * index was out-of-bounds. + */ +struct IndexFromAccessor { + /** @brief Attempts to obtain a vertex index from an empty \ref + * IndexAccessorType, resulting in -1. */ + int64_t operator()(std::monostate) { return -1; } + + /** @brief Attempts to obtain a vertex index from an \ref + * CesiumGltf::AccessorView. */ + template + int64_t operator()(const CesiumGltf::AccessorView& value) { + if (index < 0 || index >= value.size()) { + return -1; + } + + return value[index]; + } + + /** @brief The index of the vertex index within the accessor itself. */ + int64_t index; +}; + +/** + * Type definition for all kinds of texture coordinate (TEXCOORD_n) accessors. + */ +typedef std::variant< + AccessorView>, + AccessorView>, + AccessorView>> + TexCoordAccessorType; + +/** + * Retrieves an accessor view for the specified texture coordinate set from + * the given glTF primitive and model. This verifies that the accessor is of a + * valid type. If not, the returned accessor view will be invalid., + */ +TexCoordAccessorType getTexCoordAccessorView( + const Model& model, + const MeshPrimitive& primitive, + int32_t textureCoordinateSetIndex); + +/** + * Visitor that retrieves the texture coordinates from the given accessor type + * as a glm::dvec2. This should be initialized with the target index. + * + * There are technically no invalid UV values because of clamp / wrap + * behavior, so we use std::nullopt to denote an erroneous value. + */ +struct TexCoordFromAccessor { + /** + * @brief Attempts to obtain a `glm::dvec2` at the given index from an + * accessor over a vec2 of floats. If the index is invalid, `std::nullopt` is + * returned instead. + */ + std::optional + operator()(const AccessorView>& value) { + if (index < 0 || index >= value.size()) { + return std::nullopt; + } + + return glm::dvec2(value[index].value[0], value[index].value[1]); + } + + /** + * @brief Attempts to obtain a `glm::dvec2` at the given index from an + * accessor over a vec2. The values will be cast to `double` and normalized + * based on `std::numeric_limits::max()`. If the index is invalid, + * `std::nullopt` is returned instead. + */ + template + std::optional + operator()(const AccessorView>& value) { + if (index < 0 || index >= value.size()) { + return std::nullopt; + } + + double u = static_cast(value[index].value[0]); + double v = static_cast(value[index].value[1]); + + // TODO: do normalization logic in accessor view? + u /= std::numeric_limits::max(); + v /= std::numeric_limits::max(); + + return glm::dvec2(u, v); + } + + /** @brief The index of texcoords to obtain. */ + int64_t index; +}; + +/** + * @brief Type definition for quaternion accessors, as used in + * ExtMeshGpuInstancing rotations and animation samplers. + */ +typedef std::variant< + AccessorView>, + AccessorView>, + AccessorView>, + AccessorView>, + AccessorView>> + QuaternionAccessorType; + +/** + * @brief Obtains a \ref QuaternionAccessorType from the given \ref Accessor on + * the given \ref Model. + * + * @param model The model containing the quaternion. + * @param accessor An accessor from which the quaternion will be obtained. + * @returns A quaternion from the data in `accessor`. If no quaternion could be + * obtained, the default value for \ref QuaternionAccessorType will be returned + * instead. + */ +QuaternionAccessorType +getQuaternionAccessorView(const Model& model, const Accessor* accessor); + +/** + * @brief Obtains a \ref QuaternionAccessorType from the given \ref Accessor on + * the given \ref Model. + * + * @param model The model containing the quaternion. + * @param accessorIndex An index to the accessor from which the quaternion will + * be obtained. + * @returns A quaternion from the data in the accessor at `accessorIndex`. If no + * quaternion could be obtained, the default value for \ref + * QuaternionAccessorType will be returned instead. + */ +QuaternionAccessorType +getQuaternionAccessorView(const Model& model, int32_t accessorIndex); +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorView.h new file mode 100644 index 0000000..b98a01b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorView.h @@ -0,0 +1,538 @@ +#pragma once + +#include "CesiumGltf/Accessor.h" +#include "CesiumGltf/Model.h" + +#include +#include + +namespace CesiumGltf { + +/** + * @brief Indicates the status of an accessor view. + * + * The {@link AccessorView} constructor always completes successfully. However, + * it may not always reflect the actual content of the {@link Accessor}, but + * instead indicate that its {@link AccessorView::size} is 0. This enumeration + * provides the reason. + */ +enum class AccessorViewStatus { + /** + * @brief This accessor is valid and ready to use. + */ + Valid, + + /** + * @brief The accessor index does not refer to a valid accessor. + */ + InvalidAccessorIndex, + + /** + * @brief The accessor's bufferView index does not refer to a valid + * bufferView. + */ + InvalidBufferViewIndex, + + /** + * @brief The accessor's bufferView's buffer index does not refer to a valid + * buffer. + */ + InvalidBufferIndex, + + /** + * @brief The accessor is too large to fit in its bufferView. + */ + BufferViewTooSmall, + + /** + * @brief The accessor's bufferView is too large to fit in its buffer. + */ + BufferTooSmall, + + /** + * @brief The `sizeof(T)` does not match the accessor's + * {@link Accessor::computeBytesPerVertex}. + */ + WrongSizeT, + + /** + * @brief The `AccessorSpec:type` is invalid. + */ + InvalidType, + + /** + * @brief The {@link AccessorSpec::componentType} is invalid. + */ + InvalidComponentType, + + /** + * @brief The {@link BufferView::byteStride} is negative, which is invalid. + * + */ + InvalidByteStride, +}; + +/** + * @brief A view on the data of one accessor of a glTF asset. + * + * It provides the actual accessor data like an array of elements. + * The type of the accessor elements is determined by the template + * parameter. Instances are usually from an {@link Accessor}, + * and the {@link operator[]()} can be used to access the elements: + * + * @snippet TestAccessorView.cpp createFromAccessorAndRead + * + * @tparam T The type of the elements in the accessor. + */ +template class AccessorView final { +private: + const std::byte* _pData; + int64_t _stride; + int64_t _offset; + int64_t _size; + AccessorViewStatus _status; + +public: + /** + * @brief The type of the elements in the accessor. + */ + typedef T value_type; + + /** + * @brief Construct a new instance not pointing to any data. + * + * The new instance will have a {@link size} of 0 and a {@link status} of + * `AccessorViewStatus::InvalidAccessorIndex`. + * + * @param status The status of the new accessor. Defaults to + * {@link AccessorViewStatus::InvalidAccessorIndex}. + */ + AccessorView( + AccessorViewStatus status = AccessorViewStatus::InvalidAccessorIndex) + : _pData(nullptr), _stride(0), _offset(0), _size(0), _status(status) {} + + /** + * @brief Creates a new instance from low-level parameters. + * + * The provided parameters are not validated in any way, and so this overload + * can easily be used to access invalid memory. + * + * @param pData The raw data buffer from which to read. + * @param stride The stride, in bytes, between successive elements. + * @param offset The offset from the start of the buffer to the first element. + * @param size The total number of elements. + */ + AccessorView( + const std::byte* pData, + int64_t stride, + int64_t offset, + int64_t size) + : _pData(pData), + _stride(stride), + _offset(offset), + _size(size), + _status(AccessorViewStatus::Valid) {} + + /** + * @brief Creates a new instance from a given model and {@link Accessor}. + * + * If the accessor cannot be viewed, the construct will still complete + * successfully without throwing an exception. However, {@link size} will + * return 0 and + * {@link status} will indicate what went wrong. + * + * @param model The model to access. + * @param accessor The accessor to view. + */ + AccessorView(const Model& model, const Accessor& accessor) noexcept + : AccessorView() { + this->create(model, accessor); + } + + /** + * @brief Creates a new instance from a given model and accessor index. + * + * If the accessor cannot be viewed, the construct will still complete + * successfully without throwing an exception. However, {@link size} will + * return 0 and + * {@link status} will indicate what went wrong. + * + * @param model The model to access. + * @param accessorIndex The index of the accessor to view in the model's + * {@link Model::accessors} list. + */ + AccessorView(const Model& model, int32_t accessorIndex) noexcept + : AccessorView() { + const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex); + if (!pAccessor) { + this->_status = AccessorViewStatus::InvalidAccessorIndex; + return; + } + + this->create(model, *pAccessor); + } + + /** + * @brief Provides the specified accessor element. + * + * @param i The index of the element. + * @returns The constant reference to the accessor element. + * @throws A `std::range_error` if the given index is negative + * or not smaller than the {@link size} of this accessor. + */ + const T& operator[](int64_t i) const { + if (i < 0 || i >= this->_size) { + throw std::range_error("index out of range"); + } + + return *reinterpret_cast( + this->_pData + i * this->_stride + this->_offset); + } + + /** + * @brief Returns the size (number of elements) of this accessor. + * + * This is the number of elements of type `T` that this accessor contains. + * + * @returns The size. + */ + int64_t size() const noexcept { return this->_size; } + + /** + * @brief Gets the status of this accessor view. + * + * Indicates whether the view accurately reflects the accessor's data, or + * whether an error occurred. + */ + AccessorViewStatus status() const noexcept { return this->_status; } + + /** + * @brief Returns the stride of this accessor, which is the number of bytes + * from the start of one element to the start of the next. + * + * @returns The stride. + */ + int64_t stride() const noexcept { return this->_stride; } + + /** + * @brief Returns the offset of this accessor, which is the number of bytes + * from the start of the buffer to the first element. + * + * @returns The offset. + */ + int64_t offset() const noexcept { return this->_offset; } + + /** + * @brief Returns a pointer to the first byte of this accessor view's data. + * The elements are stored contiguously, so the next one starts {@link stride} bytes later. + * + * @returns The start of this view. + */ + const std::byte* data() const noexcept { + return this->_pData + this->_offset; + } + +private: + void create(const Model& model, const Accessor& accessor) noexcept { + const CesiumGltf::BufferView* pBufferView = + Model::getSafe(&model.bufferViews, accessor.bufferView); + if (!pBufferView) { + this->_status = AccessorViewStatus::InvalidBufferViewIndex; + return; + } + + const CesiumGltf::Buffer* pBuffer = + Model::getSafe(&model.buffers, pBufferView->buffer); + if (!pBuffer) { + this->_status = AccessorViewStatus::InvalidBufferIndex; + return; + } + + const std::vector& data = pBuffer->cesium.data; + const int64_t bufferBytes = int64_t(data.size()); + if (pBufferView->byteOffset + pBufferView->byteLength > bufferBytes) { + this->_status = AccessorViewStatus::BufferTooSmall; + return; + } + + const int64_t accessorByteStride = accessor.computeByteStride(model); + if (accessorByteStride < 0) { + this->_status = AccessorViewStatus::InvalidByteStride; + return; + } + + const int64_t accessorComponentElements = + accessor.computeNumberOfComponents(); + const int64_t accessorComponentBytes = + accessor.computeByteSizeOfComponent(); + const int64_t accessorBytesPerStride = + accessorComponentElements * accessorComponentBytes; + + if (sizeof(T) != accessorBytesPerStride) { + this->_status = AccessorViewStatus::WrongSizeT; + return; + } + + const int64_t accessorBytes = accessorByteStride * accessor.count; + const int64_t bytesRemainingInBufferView = + pBufferView->byteLength - + (accessor.byteOffset + accessorByteStride * (accessor.count - 1) + + accessorBytesPerStride); + if (accessorBytes > pBufferView->byteLength || + bytesRemainingInBufferView < 0) { + this->_status = AccessorViewStatus::BufferViewTooSmall; + return; + } + + this->_pData = pBuffer->cesium.data.data(); + this->_stride = accessorByteStride; + this->_offset = accessor.byteOffset + pBufferView->byteOffset; + this->_size = accessor.count; + this->_status = AccessorViewStatus::Valid; + } +}; + +/** + * @brief Contains types that may optionally be used with {@link AccessorView} + * for various {@link Accessor::componentType} values. + */ +struct AccessorTypes { +#pragma pack(push, 1) + + /** + * @brief A scalar element for an {@link AccessorView}. + * + * @tparam T The component type. + */ + template struct SCALAR { + /** + * @brief The component values of this element. + */ + T value[1]; + }; + + /** + * @brief A 2D vector element for an {@link AccessorView}. + * + * @tparam T The component type. + */ + template struct VEC2 { + /** + * @brief The component values of this element. + */ + T value[2]; + }; + + /** + * @brief A 3D vector element for an {@link AccessorView}. + * + * @tparam T The component type. + */ + template struct VEC3 { + /** + * @brief The component values of this element. + */ + T value[3]; + }; + + /** + * @brief A 4D vector element for an {@link AccessorView}. + * + * @tparam T The component type. + */ + template struct VEC4 { + /** + * @brief The component values of this element. + */ + T value[4]; + }; + + /** + * @brief A 2x2 matrix element for an {@link AccessorView}. + * + * @tparam T The component type. + */ + template struct MAT2 { + /** + * @brief The component values of this element. + */ + T value[4]; + }; + + /** + * @brief A 3x3 matrix element for an {@link AccessorView}. + * + * @tparam T The component type. + */ + template struct MAT3 { + /** + * @brief The component values of this element. + */ + T value[9]; + }; + + /** + * @brief A 4x4 matrix element for an {@link AccessorView}. + * + * @tparam T The component type. + */ + template struct MAT4 { + /** + * @brief The component values of this element. + */ + T value[16]; + }; + +#pragma pack(pop) +}; + +namespace CesiumImpl { +template +std::invoke_result_t>> +createAccessorView( + const Model& model, + const Accessor& accessor, + TCallback&& callback) { + if (accessor.type == Accessor::Type::SCALAR) { + return callback( + AccessorView>(model, accessor)); + } + if (accessor.type == Accessor::Type::VEC2) { + return callback( + AccessorView>(model, accessor)); + } + if (accessor.type == Accessor::Type::VEC3) { + return callback( + AccessorView>(model, accessor)); + } + if (accessor.type == Accessor::Type::VEC4) { + return callback( + AccessorView>(model, accessor)); + } + if (accessor.type == Accessor::Type::MAT2) { + return callback( + AccessorView>(model, accessor)); + } + if (accessor.type == Accessor::Type::MAT3) { + return callback( + AccessorView>(model, accessor)); + } + if (accessor.type == Accessor::Type::MAT4) { + return callback( + AccessorView>(model, accessor)); + } + // TODO Print a warning here??? + return callback(AccessorView>( + AccessorViewStatus::InvalidType)); +} +} // namespace CesiumImpl + +/** + * @brief Creates an appropriate {@link AccessorView} for a given accessor. + * + * The created accessor is provided via a callback, which is a function that can + * be invoked with all possible {@link AccessorView} types. If an accessor + * cannot be created, the callback will be invoked with + * `AccessorView>` and the + * {@link AccessorView::status} will indicate the reason. + * + * @tparam TCallback The callback. + * @param model The model to access. + * @param accessor The accessor to view. + * @param callback The callback that receives the created accessor. + * @return The value returned by the callback. + */ +template +std::invoke_result_t>> +createAccessorView( + const Model& model, + const Accessor& accessor, + TCallback&& callback) { + switch (accessor.componentType) { + case Accessor::ComponentType::BYTE: + return ::CesiumGltf::CesiumImpl::createAccessorView( + model, + accessor, + std::forward(callback)); + case Accessor::ComponentType::UNSIGNED_BYTE: + return ::CesiumGltf::CesiumImpl::createAccessorView( + model, + accessor, + std::forward(callback)); + case Accessor::ComponentType::SHORT: + return ::CesiumGltf::CesiumImpl::createAccessorView( + model, + accessor, + std::forward(callback)); + case Accessor::ComponentType::UNSIGNED_SHORT: + return ::CesiumGltf::CesiumImpl::createAccessorView( + model, + accessor, + std::forward(callback)); + case Accessor::ComponentType::INT: + return ::CesiumGltf::CesiumImpl::createAccessorView( + model, + accessor, + std::forward(callback)); + case Accessor::ComponentType::UNSIGNED_INT: + return ::CesiumGltf::CesiumImpl::createAccessorView( + model, + accessor, + std::forward(callback)); + case Accessor::ComponentType::INT64: + return ::CesiumGltf::CesiumImpl::createAccessorView( + model, + accessor, + std::forward(callback)); + case Accessor::ComponentType::UNSIGNED_INT64: + return ::CesiumGltf::CesiumImpl::createAccessorView( + model, + accessor, + std::forward(callback)); + case Accessor::ComponentType::FLOAT: + return ::CesiumGltf::CesiumImpl::createAccessorView( + model, + accessor, + std::forward(callback)); + case Accessor::ComponentType::DOUBLE: + return ::CesiumGltf::CesiumImpl::createAccessorView( + model, + accessor, + std::forward(callback)); + default: + return callback(AccessorView>( + AccessorViewStatus::InvalidComponentType)); + } +} + +/** + * @brief Creates an appropriate {@link AccessorView} for a given accessor. + * + * The created accessor is provided via a callback, which is a function that can + * be invoked with all possible {@link AccessorView} types. If an accessor + * cannot be created, the callback will be invoked with + * `AccessorView>` and the + * {@link AccessorView::status} will indicate the reason. + * + * @tparam TCallback The callback. + * @param model The model to access. + * @param accessorIndex The index of the accessor to view in + * {@link Model::accessors}. + * @param callback The callback that receives the created accessor. + * @return The value returned by the callback. + */ +template +std::invoke_result_t>> +createAccessorView( + const Model& model, + int32_t accessorIndex, + TCallback&& callback) { + const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex); + if (!pAccessor) { + return callback(AccessorView>( + AccessorViewStatus::InvalidComponentType)); + } + + return createAccessorView(model, *pAccessor, callback); +} +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorWriter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorWriter.h new file mode 100644 index 0000000..6c55b43 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorWriter.h @@ -0,0 +1,72 @@ +#pragma once + +#include "CesiumGltf/AccessorView.h" + +namespace CesiumGltf { + +/** + * @brief Provides write access to an {@link AccessorView}. + */ +template class AccessorWriter final { +private: + AccessorView _accessor; + +public: + /** + * @brief The type of the elements in the accessor. + */ + typedef T value_type; + + AccessorWriter() : _accessor() {} + + /** + * @brief Constructs a new instance from an {@link AccessorView}. + */ + AccessorWriter(const AccessorView& accessorView) + : _accessor(accessorView) {} + + /** @copydoc AccessorView::AccessorView(const std::byte*, int64_t, int64_t, + * int64_t) */ + AccessorWriter(std::byte* pData, int64_t stride, int64_t offset, int64_t size) + : _accessor(pData, stride, offset, size) {} + + /** @copydoc AccessorView::AccessorView(const Model&,const Accessor&) */ + AccessorWriter(Model& model, const Accessor& accessor) + : _accessor(model, accessor) {} + + /** @copydoc AccessorView::AccessorView(const Model&,int32_t) */ + AccessorWriter(Model& model, int32_t accessorIndex) noexcept + : _accessor(model, accessorIndex) {} + + /** @copydoc AccessorView::operator[]() */ + const T& operator[](int64_t i) const { return this->_accessor[i]; } + + /** @copydoc AccessorView::operator[]() */ + T& operator[](int64_t i) { return const_cast(this->_accessor[i]); } + + /** @copydoc AccessorView::size */ + int64_t size() const noexcept { return this->_accessor.size(); } + + /** + * @brief Gets the status of this accessor writer. + * + * Indicates whether the writer accurately reflects the accessor's data, or + * whether an error occurred. + */ + AccessorViewStatus status() const noexcept { + return this->_accessor.status(); + } + + /** @copydoc AccessorView::stride */ + int64_t stride() const noexcept { return this->_accessor.stride(); } + + /** @copydoc AccessorView::offset */ + int64_t offset() const noexcept { return this->_accessor.offset(); } + + /** @copydoc AccessorView::data */ + std::byte* data() noexcept { + return const_cast(this->_accessor.data()); + } +}; + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Animation.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Animation.h new file mode 100644 index 0000000..d89ae93 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Animation.h @@ -0,0 +1,62 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief A keyframe animation. + */ +struct CESIUMGLTF_API Animation final : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Animation"; + + /** + * @brief An array of animation channels. An animation channel combines an + * animation sampler with a target property being animated. Different channels + * of the same animation **MUST NOT** have the same targets. + */ + std::vector channels; + + /** + * @brief An array of animation samplers. An animation sampler combines + * timestamps with a sequence of output values and defines an interpolation + * algorithm. + */ + std::vector samplers; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Animation)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + accum += int64_t( + sizeof(CesiumGltf::AnimationChannel) * this->channels.capacity()); + for (const CesiumGltf::AnimationChannel& value : this->channels) { + accum += + value.getSizeBytes() - int64_t(sizeof(CesiumGltf::AnimationChannel)); + } + accum += int64_t( + sizeof(CesiumGltf::AnimationSampler) * this->samplers.capacity()); + for (const CesiumGltf::AnimationSampler& value : this->samplers) { + accum += + value.getSizeBytes() - int64_t(sizeof(CesiumGltf::AnimationSampler)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AnimationChannel.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AnimationChannel.h new file mode 100644 index 0000000..64dad00 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AnimationChannel.h @@ -0,0 +1,53 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief An animation channel combines an animation sampler with a target + * property being animated. + */ +struct CESIUMGLTF_API AnimationChannel final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "AnimationChannel"; + + /** + * @brief The index of a sampler in this animation used to compute the value + * for the target. + * + * The index of a sampler in this animation used to compute the value for the + * target, e.g., a node's translation, rotation, or scale (TRS). + */ + int32_t sampler = -1; + + /** + * @brief The descriptor of the animated property. + */ + CesiumGltf::AnimationChannelTarget target; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(AnimationChannel)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += this->target.getSizeBytes() - + int64_t(sizeof(CesiumGltf::AnimationChannelTarget)); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AnimationChannelTarget.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AnimationChannelTarget.h new file mode 100644 index 0000000..9bdbc89 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AnimationChannelTarget.h @@ -0,0 +1,79 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief The descriptor of the animated property. + */ +struct CESIUMGLTF_API AnimationChannelTarget final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "AnimationChannelTarget"; + + /** + * @brief Known values for The name of the node's TRS property to animate, or + * the `"weights"` of the Morph Targets it instantiates. For the + * `"translation"` property, the values that are provided by the sampler are + * the translation along the X, Y, and Z axes. For the `"rotation"` property, + * the values are a quaternion in the order (x, y, z, w), where w is the + * scalar. For the `"scale"` property, the values are the scaling factors + * along the X, Y, and Z axes. + */ + struct Path { + /** @brief `translation` */ + inline static const std::string translation = "translation"; + + /** @brief `rotation` */ + inline static const std::string rotation = "rotation"; + + /** @brief `scale` */ + inline static const std::string scale = "scale"; + + /** @brief `weights` */ + inline static const std::string weights = "weights"; + }; + + /** + * @brief The index of the node to animate. When undefined, the animated + * object **MAY** be defined by an extension. + */ + int32_t node = -1; + + /** + * @brief The name of the node's TRS property to animate, or the `"weights"` + * of the Morph Targets it instantiates. For the `"translation"` property, the + * values that are provided by the sampler are the translation along the X, Y, + * and Z axes. For the `"rotation"` property, the values are a quaternion in + * the order (x, y, z, w), where w is the scalar. For the `"scale"` property, + * the values are the scaling factors along the X, Y, and Z axes. + * + * Known values are defined in {@link Path}. + * + */ + std::string path = Path::translation; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(AnimationChannelTarget)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AnimationSampler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AnimationSampler.h new file mode 100644 index 0000000..2799bad --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AnimationSampler.h @@ -0,0 +1,84 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief An animation sampler combines timestamps with a sequence of output + * values and defines an interpolation algorithm. + */ +struct CESIUMGLTF_API AnimationSampler final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "AnimationSampler"; + + /** + * @brief Known values for Interpolation algorithm. + */ + struct Interpolation { + /** @brief The animated values are linearly interpolated between keyframes. + * When targeting a rotation, spherical linear interpolation (slerp) + * **SHOULD** be used to interpolate quaternions. The number of output + * elements **MUST** equal the number of input elements. */ + inline static const std::string LINEAR = "LINEAR"; + + /** @brief The animated values remain constant to the output of the first + * keyframe, until the next keyframe. The number of output elements **MUST** + * equal the number of input elements. */ + inline static const std::string STEP = "STEP"; + + /** @brief The animation's interpolation is computed using a cubic spline + * with specified tangents. The number of output elements **MUST** equal + * three times the number of input elements. For each input element, the + * output stores three elements, an in-tangent, a spline vertex, and an + * out-tangent. There **MUST** be at least two keyframes when using this + * interpolation. */ + inline static const std::string CUBICSPLINE = "CUBICSPLINE"; + }; + + /** + * @brief The index of an accessor containing keyframe timestamps. + * + * The accessor **MUST** be of scalar type with floating-point components. The + * values represent time in seconds with `time[0] >= 0.0`, and strictly + * increasing values, i.e., `time[n + 1] > time[n]`. + */ + int32_t input = -1; + + /** + * @brief Interpolation algorithm. + * + * Known values are defined in {@link Interpolation}. + * + */ + std::string interpolation = Interpolation::LINEAR; + + /** + * @brief The index of an accessor, containing keyframe output values. + */ + int32_t output = -1; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(AnimationSampler)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Asset.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Asset.h new file mode 100644 index 0000000..73b527a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Asset.h @@ -0,0 +1,69 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief Metadata about the glTF asset. + */ +struct CESIUMGLTF_API Asset final : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Asset"; + + /** + * @brief A copyright message suitable for display to credit the content + * creator. + */ + std::optional copyright; + + /** + * @brief Tool that generated this glTF model. Useful for debugging. + */ + std::optional generator; + + /** + * @brief The glTF version in the form of `.` that this asset + * targets. + */ + std::string version; + + /** + * @brief The minimum glTF version in the form of `.` that this + * asset targets. This property **MUST NOT** be greater than the asset + * version. + */ + std::optional minVersion; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Asset)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->copyright) { + accum += int64_t(this->copyright->capacity() * sizeof(char)); + } + if (this->generator) { + accum += int64_t(this->generator->capacity() * sizeof(char)); + } + accum += int64_t(this->version.capacity() * sizeof(char)); + if (this->minVersion) { + accum += int64_t(this->minVersion->capacity() * sizeof(char)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Buffer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Buffer.h new file mode 100644 index 0000000..bf7b4e4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Buffer.h @@ -0,0 +1,18 @@ +#pragma once + +#include "CesiumGltf/BufferCesium.h" +#include "CesiumGltf/BufferSpec.h" +#include "CesiumGltf/Library.h" + +namespace CesiumGltf { +/** @copydoc BufferSpec */ +struct CESIUMGLTF_API Buffer final : public BufferSpec { + Buffer() = default; + + /** + * @brief Holds properties that are specific to the glTF loader rather than + * part of the glTF spec. + */ + BufferCesium cesium; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/BufferCesium.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/BufferCesium.h new file mode 100644 index 0000000..1aab061 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/BufferCesium.h @@ -0,0 +1,19 @@ +#pragma once + +#include "CesiumGltf/Library.h" + +#include +#include + +namespace CesiumGltf { +/** + * @brief Holds {@link Buffer} properties that are specific to the glTF loader + * rather than part of the glTF spec. + */ +struct CESIUMGLTF_API BufferCesium final { + /** + * @brief The buffer's data. + */ + std::vector data; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/BufferSpec.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/BufferSpec.h new file mode 100644 index 0000000..25f2712 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/BufferSpec.h @@ -0,0 +1,59 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief A buffer points to binary geometry, animation, or skins. + */ +struct CESIUMGLTF_API BufferSpec : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Buffer"; + + /** + * @brief The URI (or IRI) of the buffer. + * + * Relative paths are relative to the current glTF asset. Instead of + * referencing an external file, this field **MAY** contain a `data:`-URI. + */ + std::optional uri; + + /** + * @brief The length of the buffer in bytes. + */ + int64_t byteLength = int64_t(); + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(BufferSpec)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + if (this->uri) { + accum += int64_t(this->uri->capacity() * sizeof(char)); + } + return accum; + } + +protected: + /** + * @brief This class is not meant to be instantiated directly. Use {@link Buffer} instead. + */ + BufferSpec() = default; + friend struct Buffer; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/BufferView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/BufferView.h new file mode 100644 index 0000000..d50f200 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/BufferView.h @@ -0,0 +1,81 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief A view into a buffer generally representing a subset of the buffer. + */ +struct CESIUMGLTF_API BufferView final : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "BufferView"; + + /** + * @brief Known values for The hint representing the intended GPU buffer type + * to use with this buffer view. + */ + struct Target { + /** @brief ARRAY_BUFFER (`34962`) */ + static constexpr int32_t ARRAY_BUFFER = 34962; + + /** @brief ELEMENT_ARRAY_BUFFER (`34963`) */ + static constexpr int32_t ELEMENT_ARRAY_BUFFER = 34963; + }; + + /** + * @brief The index of the buffer. + */ + int32_t buffer = -1; + + /** + * @brief The offset into the buffer in bytes. + */ + int64_t byteOffset = 0; + + /** + * @brief The length of the bufferView in bytes. + */ + int64_t byteLength = int64_t(); + + /** + * @brief The stride, in bytes. + * + * The stride, in bytes, between vertex attributes. When this is not defined, + * data is tightly packed. When two or more accessors use the same buffer + * view, this field **MUST** be defined. + */ + std::optional byteStride; + + /** + * @brief The hint representing the intended GPU buffer type to use with this + * buffer view. + * + * Known values are defined in {@link Target}. + * + */ + std::optional target; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(BufferView)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Camera.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Camera.h new file mode 100644 index 0000000..6e893f5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Camera.h @@ -0,0 +1,84 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief A camera's projection. A node **MAY** reference a camera to apply a + * transform to place the camera in the scene. + */ +struct CESIUMGLTF_API Camera final : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Camera"; + + /** + * @brief Known values for Specifies if the camera uses a perspective or + * orthographic projection. + */ + struct Type { + /** @brief `perspective` */ + inline static const std::string perspective = "perspective"; + + /** @brief `orthographic` */ + inline static const std::string orthographic = "orthographic"; + }; + + /** + * @brief An orthographic camera containing properties to create an + * orthographic projection matrix. This property **MUST NOT** be defined when + * `perspective` is defined. + */ + std::optional orthographic; + + /** + * @brief A perspective camera containing properties to create a perspective + * projection matrix. This property **MUST NOT** be defined when + * `orthographic` is defined. + */ + std::optional perspective; + + /** + * @brief Specifies if the camera uses a perspective or orthographic + * projection. + * + * Known values are defined in {@link Type}. + * + * + * Based on this, either the camera's `perspective` or `orthographic` property + * **MUST** be defined. + */ + std::string type = Type::perspective; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Camera)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + if (this->orthographic) { + accum += this->orthographic->getSizeBytes() - + int64_t(sizeof(CesiumGltf::CameraOrthographic)); + } + if (this->perspective) { + accum += this->perspective->getSizeBytes() - + int64_t(sizeof(CesiumGltf::CameraPerspective)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/CameraOrthographic.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/CameraOrthographic.h new file mode 100644 index 0000000..e8b352c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/CameraOrthographic.h @@ -0,0 +1,58 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +namespace CesiumGltf { +/** + * @brief An orthographic camera containing properties to create an orthographic + * projection matrix. + */ +struct CESIUMGLTF_API CameraOrthographic final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "CameraOrthographic"; + + /** + * @brief The floating-point horizontal magnification of the view. This value + * **MUST NOT** be equal to zero. This value **SHOULD NOT** be negative. + */ + double xmag = double(); + + /** + * @brief The floating-point vertical magnification of the view. This value + * **MUST NOT** be equal to zero. This value **SHOULD NOT** be negative. + */ + double ymag = double(); + + /** + * @brief The floating-point distance to the far clipping plane. This value + * **MUST NOT** be equal to zero. `zfar` **MUST** be greater than `znear`. + */ + double zfar = double(); + + /** + * @brief The floating-point distance to the near clipping plane. + */ + double znear = double(); + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(CameraOrthographic)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/CameraPerspective.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/CameraPerspective.h new file mode 100644 index 0000000..dcd40e2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/CameraPerspective.h @@ -0,0 +1,65 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief A perspective camera containing properties to create a perspective + * projection matrix. + */ +struct CESIUMGLTF_API CameraPerspective final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "CameraPerspective"; + + /** + * @brief The floating-point aspect ratio of the field of view. + * + * When undefined, the aspect ratio of the rendering viewport **MUST** be + * used. + */ + std::optional aspectRatio; + + /** + * @brief The floating-point vertical field of view in radians. This value + * **SHOULD** be less than π. + */ + double yfov = double(); + + /** + * @brief The floating-point distance to the far clipping plane. + * + * When defined, `zfar` **MUST** be greater than `znear`. If `zfar` is + * undefined, client implementations **SHOULD** use infinite projection + * matrix. + */ + std::optional zfar; + + /** + * @brief The floating-point distance to the near clipping plane. + */ + double znear = double(); + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(CameraPerspective)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Class.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Class.h new file mode 100644 index 0000000..397b3b4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Class.h @@ -0,0 +1,67 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief A class containing a set of properties. + */ +struct CESIUMGLTF_API Class final : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Class"; + + /** + * @brief The name of the class, e.g. for display purposes. + */ + std::optional name; + + /** + * @brief The description of the class. + */ + std::optional description; + + /** + * @brief A dictionary, where each key is a property ID and each value is an + * object defining the property. Property IDs must be alphanumeric identifiers + * matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`. + */ + std::unordered_map properties; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Class)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + if (this->description) { + accum += int64_t(this->description->capacity() * sizeof(char)); + } + accum += int64_t( + this->properties.bucket_count() * + (sizeof(std::string) + sizeof(CesiumGltf::ClassProperty))); + for (const auto& [k, v] : this->properties) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - int64_t(sizeof(CesiumGltf::ClassProperty)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ClassProperty.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ClassProperty.h new file mode 100644 index 0000000..11a8d91 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ClassProperty.h @@ -0,0 +1,239 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief A class property. + */ +struct CESIUMGLTF_API ClassProperty final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ClassProperty"; + + /** + * @brief Known values for The element type. + */ + struct Type { + /** @brief `SCALAR` */ + inline static const std::string SCALAR = "SCALAR"; + + /** @brief `VEC2` */ + inline static const std::string VEC2 = "VEC2"; + + /** @brief `VEC3` */ + inline static const std::string VEC3 = "VEC3"; + + /** @brief `VEC4` */ + inline static const std::string VEC4 = "VEC4"; + + /** @brief `MAT2` */ + inline static const std::string MAT2 = "MAT2"; + + /** @brief `MAT3` */ + inline static const std::string MAT3 = "MAT3"; + + /** @brief `MAT4` */ + inline static const std::string MAT4 = "MAT4"; + + /** @brief `STRING` */ + inline static const std::string STRING = "STRING"; + + /** @brief `BOOLEAN` */ + inline static const std::string BOOLEAN = "BOOLEAN"; + + /** @brief `ENUM` */ + inline static const std::string ENUM = "ENUM"; + }; + + /** + * @brief Known values for The datatype of the element's components. Only + * applicable to `SCALAR`, `VECN`, and `MATN` types. + */ + struct ComponentType { + /** @brief `INT8` */ + inline static const std::string INT8 = "INT8"; + + /** @brief `UINT8` */ + inline static const std::string UINT8 = "UINT8"; + + /** @brief `INT16` */ + inline static const std::string INT16 = "INT16"; + + /** @brief `UINT16` */ + inline static const std::string UINT16 = "UINT16"; + + /** @brief `INT32` */ + inline static const std::string INT32 = "INT32"; + + /** @brief `UINT32` */ + inline static const std::string UINT32 = "UINT32"; + + /** @brief `INT64` */ + inline static const std::string INT64 = "INT64"; + + /** @brief `UINT64` */ + inline static const std::string UINT64 = "UINT64"; + + /** @brief `FLOAT32` */ + inline static const std::string FLOAT32 = "FLOAT32"; + + /** @brief `FLOAT64` */ + inline static const std::string FLOAT64 = "FLOAT64"; + }; + + /** + * @brief The name of the property, e.g. for display purposes. + */ + std::optional name; + + /** + * @brief The description of the property. + */ + std::optional description; + + /** + * @brief The element type. + * + * Known values are defined in {@link Type}. + * + */ + std::string type = Type::SCALAR; + + /** + * @brief The datatype of the element's components. Only applicable to + * `SCALAR`, `VECN`, and `MATN` types. + * + * Known values are defined in {@link ComponentType}. + * + */ + std::optional componentType; + + /** + * @brief Enum ID as declared in the `enums` dictionary. Required when `type` + * is `ENUM`. + */ + std::optional enumType; + + /** + * @brief Whether the property is an array. When `count` is defined the + * property is a fixed-length array. Otherwise the property is a + * variable-length array. + */ + bool array = false; + + /** + * @brief The number of array elements. May only be defined when `array` is + * true. + */ + std::optional count; + + /** + * @brief Specifies whether integer values are normalized. Only applicable to + * `SCALAR`, `VECN`, and `MATN` types with integer component types. For + * unsigned integer component types, values are normalized between + * `[0.0, 1.0]`. For signed integer component types, values are normalized + * between `[-1.0, 1.0]`. For all other component types, this property must be + * false. + */ + bool normalized = false; + + /** + * @brief An offset to apply to property values. Only applicable to `SCALAR`, + * `VECN`, and `MATN` types when the component type is `FLOAT32` or `FLOAT64`, + * or when the property is `normalized`. + */ + std::optional offset; + + /** + * @brief A scale to apply to property values. Only applicable to `SCALAR`, + * `VECN`, and `MATN` types when the component type is `FLOAT32` or `FLOAT64`, + * or when the property is `normalized`. + */ + std::optional scale; + + /** + * @brief Maximum allowed value for the property. Only applicable to `SCALAR`, + * `VECN`, and `MATN` types. This is the maximum of all property values, after + * the transforms based on the `normalized`, `offset`, and `scale` properties + * have been applied. + */ + std::optional max; + + /** + * @brief Minimum allowed value for the property. Only applicable to `SCALAR`, + * `VECN`, and `MATN` types. This is the minimum of all property values, after + * the transforms based on the `normalized`, `offset`, and `scale` properties + * have been applied. + */ + std::optional min; + + /** + * @brief If required, the property must be present in every entity conforming + * to the class. If not required, individual entities may include `noData` + * values, or the entire property may be omitted. As a result, `noData` has no + * effect on a required property. Client implementations may use required + * properties to make performance optimizations. + */ + bool required = false; + + /** + * @brief A `noData` value represents missing data — also known as a sentinel + * value — wherever it appears. `BOOLEAN` properties may not specify `noData` + * values. This is given as the plain property value, without the transforms + * from the `normalized`, `offset`, and `scale` properties. Must not be + * defined if `required` is true. + */ + std::optional noData; + + /** + * @brief A default value to use when encountering a `noData` value or an + * omitted property. The value is given in its final form, taking the effect + * of `normalized`, `offset`, and `scale` properties into account. Must not be + * defined if `required` is true. + */ + std::optional defaultProperty; + + /** + * @brief An identifier that describes how this property should be + * interpreted. The semantic cannot be used by other properties in the class. + */ + std::optional semantic; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ClassProperty)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + if (this->description) { + accum += int64_t(this->description->capacity() * sizeof(char)); + } + if (this->enumType) { + accum += int64_t(this->enumType->capacity() * sizeof(char)); + } + if (this->semantic) { + accum += int64_t(this->semantic->capacity() * sizeof(char)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Enum.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Enum.h new file mode 100644 index 0000000..f0d567f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Enum.h @@ -0,0 +1,100 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief An object defining the values of an enum. + */ +struct CESIUMGLTF_API Enum final : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Enum"; + + /** + * @brief Known values for The type of the integer enum value. + */ + struct ValueType { + /** @brief `INT8` */ + inline static const std::string INT8 = "INT8"; + + /** @brief `UINT8` */ + inline static const std::string UINT8 = "UINT8"; + + /** @brief `INT16` */ + inline static const std::string INT16 = "INT16"; + + /** @brief `UINT16` */ + inline static const std::string UINT16 = "UINT16"; + + /** @brief `INT32` */ + inline static const std::string INT32 = "INT32"; + + /** @brief `UINT32` */ + inline static const std::string UINT32 = "UINT32"; + + /** @brief `INT64` */ + inline static const std::string INT64 = "INT64"; + + /** @brief `UINT64` */ + inline static const std::string UINT64 = "UINT64"; + }; + + /** + * @brief The name of the enum, e.g. for display purposes. + */ + std::optional name; + + /** + * @brief The description of the enum. + */ + std::optional description; + + /** + * @brief The type of the integer enum value. + * + * Known values are defined in {@link ValueType}. + * + */ + std::string valueType = ValueType::UINT16; + + /** + * @brief An array of enum values. Duplicate names or duplicate integer values + * are not allowed. + */ + std::vector values; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Enum)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + if (this->description) { + accum += int64_t(this->description->capacity() * sizeof(char)); + } + accum += int64_t(sizeof(CesiumGltf::EnumValue) * this->values.capacity()); + for (const CesiumGltf::EnumValue& value : this->values) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::EnumValue)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/EnumValue.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/EnumValue.h new file mode 100644 index 0000000..158f305 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/EnumValue.h @@ -0,0 +1,55 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief An enum value. + */ +struct CESIUMGLTF_API EnumValue final : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "EnumValue"; + + /** + * @brief The name of the enum value. + */ + std::string name; + + /** + * @brief The description of the enum value. + */ + std::optional description; + + /** + * @brief The integer enum value. + */ + int64_t value = int64_t(); + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(EnumValue)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(this->name.capacity() * sizeof(char)); + if (this->description) { + accum += int64_t(this->description->capacity() * sizeof(char)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionBufferExtMeshoptCompression.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionBufferExtMeshoptCompression.h new file mode 100644 index 0000000..b1c7870 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionBufferExtMeshoptCompression.h @@ -0,0 +1,45 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +namespace CesiumGltf { +/** + * @brief Compressed data for bufferView. + */ +struct CESIUMGLTF_API ExtensionBufferExtMeshoptCompression final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = + "ExtensionBufferExtMeshoptCompression"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "EXT_meshopt_compression"; + + /** + * @brief Set to true to indicate that the buffer is only referenced by + * bufferViews that have EXT_meshopt_compression extension and as such doesn't + * need to be loaded. + */ + bool fallback = false; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionBufferExtMeshoptCompression)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionBufferViewExtMeshoptCompression.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionBufferViewExtMeshoptCompression.h new file mode 100644 index 0000000..485ad38 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionBufferViewExtMeshoptCompression.h @@ -0,0 +1,113 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief Compressed data for bufferView. + */ +struct CESIUMGLTF_API ExtensionBufferViewExtMeshoptCompression final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = + "ExtensionBufferViewExtMeshoptCompression"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "EXT_meshopt_compression"; + + /** + * @brief Known values for The compression mode. + */ + struct Mode { + /** @brief `ATTRIBUTES` */ + inline static const std::string ATTRIBUTES = "ATTRIBUTES"; + + /** @brief `TRIANGLES` */ + inline static const std::string TRIANGLES = "TRIANGLES"; + + /** @brief `INDICES` */ + inline static const std::string INDICES = "INDICES"; + }; + + /** + * @brief Known values for The compression filter. + */ + struct Filter { + /** @brief `NONE` */ + inline static const std::string NONE = "NONE"; + + /** @brief `OCTAHEDRAL` */ + inline static const std::string OCTAHEDRAL = "OCTAHEDRAL"; + + /** @brief `QUATERNION` */ + inline static const std::string QUATERNION = "QUATERNION"; + + /** @brief `EXPONENTIAL` */ + inline static const std::string EXPONENTIAL = "EXPONENTIAL"; + }; + + /** + * @brief The index of the buffer with compressed data. + */ + int32_t buffer = -1; + + /** + * @brief The offset into the buffer in bytes. + */ + int64_t byteOffset = 0; + + /** + * @brief The length of the compressed data in bytes. + */ + int64_t byteLength = int64_t(); + + /** + * @brief The stride, in bytes. + */ + int64_t byteStride = int64_t(); + + /** + * @brief The number of elements. + */ + int64_t count = int64_t(); + + /** + * @brief The compression mode. + * + * Known values are defined in {@link Mode}. + * + */ + std::string mode = Mode::ATTRIBUTES; + + /** + * @brief The compression filter. + * + * Known values are defined in {@link Filter}. + * + */ + std::string filter = Filter::NONE; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionBufferViewExtMeshoptCompression)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionCesiumPrimitiveOutline.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionCesiumPrimitiveOutline.h new file mode 100644 index 0000000..a747be3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionCesiumPrimitiveOutline.h @@ -0,0 +1,46 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief glTF extension for indicating that some edges of a primitive's + * triangles should be outlined. + */ +struct CESIUMGLTF_API ExtensionCesiumPrimitiveOutline final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionCesiumPrimitiveOutline"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "CESIUM_primitive_outline"; + + /** + * @brief The index of the accessor providing the list of highlighted lines at + * the edge of this primitive's triangles. + */ + int32_t indices = -1; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionCesiumPrimitiveOutline)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionCesiumRTC.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionCesiumRTC.h new file mode 100644 index 0000000..f67a8ea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionCesiumRTC.h @@ -0,0 +1,44 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief glTF CESIUM_RTC extension. + */ +struct CESIUMGLTF_API ExtensionCesiumRTC final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionCesiumRTC"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "CESIUM_RTC"; + + /** + * @brief Center that vertex positions are relative to. + */ + std::vector center; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionCesiumRTC)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(sizeof(double) * this->center.capacity()); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionCesiumTileEdges.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionCesiumTileEdges.h new file mode 100644 index 0000000..f339aee --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionCesiumTileEdges.h @@ -0,0 +1,63 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief `CESIUM_tile_edges` extension for a primitive in a glTF model. + */ +struct CESIUMGLTF_API ExtensionCesiumTileEdges final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionCesiumTileEdges"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "CESIUM_tile_edges"; + + /** + * @brief The index of the accessor containing indices that make up the left + * edge. + */ + int32_t left = -1; + + /** + * @brief The index of the accessor containing indices that make up the bottom + * edge. + */ + int32_t bottom = -1; + + /** + * @brief The index of the accessor containing indices that make up the right + * edge. + */ + int32_t right = -1; + + /** + * @brief The index of the accessor containing indices that make up the top + * edge. + */ + int32_t top = -1; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionCesiumTileEdges)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtInstanceFeatures.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtInstanceFeatures.h new file mode 100644 index 0000000..67a99ad --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtInstanceFeatures.h @@ -0,0 +1,53 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief An object describing per-instance feature IDs. + */ +struct CESIUMGLTF_API ExtensionExtInstanceFeatures final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionExtInstanceFeatures"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "EXT_instance_features"; + + /** + * @brief An array of feature ID sets. + */ + std::vector featureIds; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionExtInstanceFeatures)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t( + sizeof(CesiumGltf::ExtensionExtInstanceFeaturesFeatureId) * + this->featureIds.capacity()); + for (const CesiumGltf::ExtensionExtInstanceFeaturesFeatureId& value : + this->featureIds) { + accum += + value.getSizeBytes() - + int64_t(sizeof(CesiumGltf::ExtensionExtInstanceFeaturesFeatureId)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtInstanceFeaturesFeatureId.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtInstanceFeaturesFeatureId.h new file mode 100644 index 0000000..602b0fa --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtInstanceFeaturesFeatureId.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief Feature IDs stored in a GPU mesh instancing attribute + */ +struct CESIUMGLTF_API ExtensionExtInstanceFeaturesFeatureId final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = + "ExtensionExtInstanceFeaturesFeatureId"; + + /** + * @brief The number of unique features in the attribute. + */ + int64_t featureCount = int64_t(); + + /** + * @brief A value that indicates that no feature is associated with this + * instance. + */ + std::optional nullFeatureId; + + /** + * @brief A label assigned to this feature ID set. Labels must be alphanumeric + * identifiers matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`. + */ + std::optional label; + + /** + * @brief An integer value used to construct a string in the format + * `_FEATURE_ID_` which is a reference to a key in + * `EXT_mesh_gpu_instancing.attributes` dictionary (e.g. a value of `0` + * corresponds to `_FEATURE_ID_0`). + */ + std::optional attribute; + + /** + * @brief The index of the property table containing per-feature property + * values. Only applicable when using the `EXT_structural_metadata` extension. + */ + std::optional propertyTable; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionExtInstanceFeaturesFeatureId)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->label) { + accum += int64_t(this->label->capacity() * sizeof(char)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshFeatures.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshFeatures.h new file mode 100644 index 0000000..f19afcb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshFeatures.h @@ -0,0 +1,49 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief An object describing feature IDs for a mesh primitive. + */ +struct CESIUMGLTF_API ExtensionExtMeshFeatures final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionExtMeshFeatures"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "EXT_mesh_features"; + + /** + * @brief An array of feature ID sets. + */ + std::vector featureIds; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionExtMeshFeatures)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += + int64_t(sizeof(CesiumGltf::FeatureId) * this->featureIds.capacity()); + for (const CesiumGltf::FeatureId& value : this->featureIds) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::FeatureId)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshGpuInstancing.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshGpuInstancing.h new file mode 100644 index 0000000..6a46c84 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshGpuInstancing.h @@ -0,0 +1,60 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief glTF extension defines instance attributes for a node with a mesh. + */ +struct CESIUMGLTF_API ExtensionExtMeshGpuInstancing final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionExtMeshGpuInstancing"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "EXT_mesh_gpu_instancing"; + + /** + * @brief A dictionary object, where each key corresponds to instance + * attribute and each value is the index of the accessor containing + * attribute's data. Attributes TRANSLATION, ROTATION, SCALE define instance + * transformation. For "TRANSLATION" the values are FLOAT_VEC3's specifying + * translation along the x, y, and z axes. For "ROTATION" the values are + * VEC4's specifying rotation as a quaternion in the order (x, y, z, w), where + * w is the scalar, with component type `FLOAT` or normalized integer. For + * "SCALE" the values are FLOAT_VEC3's specifying scaling factors along the x, + * y, and z axes. + */ + std::unordered_map attributes; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionExtMeshGpuInstancing)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t( + this->attributes.bucket_count() * + (sizeof(std::string) + sizeof(int32_t))); + for (const auto& [k, v] : this->attributes) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += int64_t(sizeof(int32_t)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadata.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadata.h new file mode 100644 index 0000000..a61a8da --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadata.h @@ -0,0 +1,69 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief Structural metadata about a glTF element. + */ +struct CESIUMGLTF_API ExtensionExtStructuralMetadata final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionExtStructuralMetadata"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "EXT_structural_metadata"; + + /** + * @brief The class that property values conform to. The value shall be a + * class ID declared in the `classes` dictionary of the metadata schema. + */ + std::optional classProperty; + + /** + * @brief A dictionary, where each key corresponds to a property ID in the + * class' `properties` dictionary and each value contains the property values. + * The type of the value shall match the property definition: For `BOOLEAN` + * use `true` or `false`. For `STRING` use a JSON string. For numeric types + * use a JSON number. For `ENUM` use a valid enum `name`, not an integer + * value. For `ARRAY`, `VECN`, and `MATN` types use a JSON array containing + * values matching the `componentType`. Required properties shall be included + * in this dictionary. + */ + std::unordered_map properties; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionExtStructuralMetadata)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->classProperty) { + accum += int64_t(this->classProperty->capacity() * sizeof(char)); + } + accum += int64_t( + this->properties.bucket_count() * + (sizeof(std::string) + sizeof(CesiumUtility::JsonValue))); + for (const auto& [k, v] : this->properties) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += int64_t(sizeof(CesiumUtility::JsonValue)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrDracoMeshCompression.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrDracoMeshCompression.h new file mode 100644 index 0000000..e8139bd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrDracoMeshCompression.h @@ -0,0 +1,58 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief KHR_draco_mesh_compression glTF Mesh Primitive Extension + */ +struct CESIUMGLTF_API ExtensionKhrDracoMeshCompression final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionKhrDracoMeshCompression"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "KHR_draco_mesh_compression"; + + /** + * @brief The index of the bufferView. + */ + int32_t bufferView = -1; + + /** + * @brief A dictionary object, where each key corresponds to an attribute and + * its unique attribute id stored in the compressed geometry. + */ + std::unordered_map attributes; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionKhrDracoMeshCompression)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t( + this->attributes.bucket_count() * + (sizeof(std::string) + sizeof(int32_t))); + for (const auto& [k, v] : this->attributes) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += int64_t(sizeof(int32_t)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrMaterialsUnlit.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrMaterialsUnlit.h new file mode 100644 index 0000000..292d1e6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrMaterialsUnlit.h @@ -0,0 +1,37 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +namespace CesiumGltf { +/** + * @brief glTF extension that defines the unlit material model. + */ +struct CESIUMGLTF_API ExtensionKhrMaterialsUnlit final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionKhrMaterialsUnlit"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "KHR_materials_unlit"; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionKhrMaterialsUnlit)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrTextureBasisu.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrTextureBasisu.h new file mode 100644 index 0000000..cee94ad --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrTextureBasisu.h @@ -0,0 +1,46 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief glTF extension to specify textures using the KTX v2 images with Basis + * Universal supercompression. + */ +struct CESIUMGLTF_API ExtensionKhrTextureBasisu final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionKhrTextureBasisu"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "KHR_texture_basisu"; + + /** + * @brief The index of the image which points to a KTX v2 resource with Basis + * Universal supercompression. + */ + int32_t source = -1; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionKhrTextureBasisu)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrTextureTransform.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrTextureTransform.h new file mode 100644 index 0000000..fe3196d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrTextureTransform.h @@ -0,0 +1,66 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief glTF extension that enables shifting and scaling UV coordinates on a + * per-texture basis + */ +struct CESIUMGLTF_API ExtensionKhrTextureTransform final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionKhrTextureTransform"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "KHR_texture_transform"; + + /** + * @brief The offset of the UV coordinate origin as a factor of the texture + * dimensions. + */ + std::vector offset = {0, 0}; + + /** + * @brief Rotate the UVs by this many radians counter-clockwise around the + * origin. + */ + double rotation = 0; + + /** + * @brief The scale factor applied to the components of the UV coordinates. + */ + std::vector scale = {1, 1}; + + /** + * @brief Overrides the textureInfo texCoord value if supplied, and if this + * extension is supported. + */ + std::optional texCoord; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionKhrTextureTransform)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(sizeof(double) * this->offset.capacity()); + accum += int64_t(sizeof(double) * this->scale.capacity()); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveExtStructuralMetadata.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveExtStructuralMetadata.h new file mode 100644 index 0000000..462a9e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveExtStructuralMetadata.h @@ -0,0 +1,54 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief Structural metadata about a glTF primitive. + */ +struct CESIUMGLTF_API ExtensionMeshPrimitiveExtStructuralMetadata final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = + "ExtensionMeshPrimitiveExtStructuralMetadata"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "EXT_structural_metadata"; + + /** + * @brief An array of indexes of property textures in the root + * `EXT_structural_metadata` object. + */ + std::vector propertyTextures; + + /** + * @brief An array of indexes of property attributes in the root + * `EXT_structural_metadata` object. + */ + std::vector propertyAttributes; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionMeshPrimitiveExtStructuralMetadata)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(sizeof(int32_t) * this->propertyTextures.capacity()); + accum += int64_t(sizeof(int32_t) * this->propertyAttributes.capacity()); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveKhrMaterialsVariants.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveKhrMaterialsVariants.h new file mode 100644 index 0000000..2bbacbb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveKhrMaterialsVariants.h @@ -0,0 +1,63 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief KHR_materials_variants glTF Mesh Primitive Extension + */ +struct CESIUMGLTF_API ExtensionMeshPrimitiveKhrMaterialsVariants final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = + "ExtensionMeshPrimitiveKhrMaterialsVariants"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "KHR_materials_variants"; + + /** + * @brief A list of material to variant mappings + * + * An array of object values that associate an indexed material to a set of + * variants. + */ + std::vector< + CesiumGltf::ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue> + mappings; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionMeshPrimitiveKhrMaterialsVariants)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t( + sizeof(CesiumGltf:: + ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue) * + this->mappings.capacity()); + for (const CesiumGltf:: + ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue& value : + this->mappings) { + accum += + value.getSizeBytes() - + int64_t(sizeof( + CesiumGltf:: + ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue.h new file mode 100644 index 0000000..70c6430 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue.h @@ -0,0 +1,67 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief ExtensionMeshPrimitiveKhrMaterialsVariants Mappings Value + */ +struct CESIUMGLTF_API ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue + final : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = + "ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue"; + + /** + * @brief An array of variant index values. + * + * An array of index values that reference variants defined in the glTF root's + * extension object. + */ + std::vector variants; + + /** + * @brief The material associated with the set of variants. + * + * A reference to the material associated with the given array of variants. + */ + int32_t material = -1; + + /** + * @brief The user-defined name of this variant material mapping. + * + * The optional user-defined name of this variant material mapping. This is + * not necessarily unique. + */ + std::optional name; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t( + sizeof(ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(sizeof(int32_t) * this->variants.capacity()); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelExtStructuralMetadata.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelExtStructuralMetadata.h new file mode 100644 index 0000000..6ae2de7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelExtStructuralMetadata.h @@ -0,0 +1,99 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief glTF extension that provides structural metadata about vertices, + * texels, and features in a glTF asset. + */ +struct CESIUMGLTF_API ExtensionModelExtStructuralMetadata final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionModelExtStructuralMetadata"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "EXT_structural_metadata"; + + /** + * @brief An object defining classes and enums. + */ + CesiumUtility::IntrusivePointer schema; + + /** + * @brief The URI (or IRI) of the external schema file. + */ + std::optional schemaUri; + + /** + * @brief An array of property table definitions, which may be referenced by + * index. + */ + std::vector propertyTables; + + /** + * @brief An array of property texture definitions, which may be referenced by + * index. + */ + std::vector propertyTextures; + + /** + * @brief An array of property attribute definitions, which may be referenced + * by index. + */ + std::vector propertyAttributes; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionModelExtStructuralMetadata)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += this->schema->getSizeBytes(); + if (this->schemaUri) { + accum += int64_t(this->schemaUri->capacity() * sizeof(char)); + } + accum += int64_t( + sizeof(CesiumGltf::PropertyTable) * this->propertyTables.capacity()); + for (const CesiumGltf::PropertyTable& value : this->propertyTables) { + accum += + value.getSizeBytes() - int64_t(sizeof(CesiumGltf::PropertyTable)); + } + accum += int64_t( + sizeof(CesiumGltf::PropertyTexture) * + this->propertyTextures.capacity()); + for (const CesiumGltf::PropertyTexture& value : this->propertyTextures) { + accum += + value.getSizeBytes() - int64_t(sizeof(CesiumGltf::PropertyTexture)); + } + accum += int64_t( + sizeof(CesiumGltf::PropertyAttribute) * + this->propertyAttributes.capacity()); + for (const CesiumGltf::PropertyAttribute& value : + this->propertyAttributes) { + accum += + value.getSizeBytes() - int64_t(sizeof(CesiumGltf::PropertyAttribute)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelKhrMaterialsVariants.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelKhrMaterialsVariants.h new file mode 100644 index 0000000..64e7347 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelKhrMaterialsVariants.h @@ -0,0 +1,53 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief glTF extension that defines a material variations for mesh primitives + */ +struct CESIUMGLTF_API ExtensionModelKhrMaterialsVariants final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionModelKhrMaterialsVariants"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "KHR_materials_variants"; + + /** + * @brief variants + */ + std::vector variants; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionModelKhrMaterialsVariants)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t( + sizeof(CesiumGltf::ExtensionModelKhrMaterialsVariantsValue) * + this->variants.capacity()); + for (const CesiumGltf::ExtensionModelKhrMaterialsVariantsValue& value : + this->variants) { + accum += + value.getSizeBytes() - + int64_t(sizeof(CesiumGltf::ExtensionModelKhrMaterialsVariantsValue)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelKhrMaterialsVariantsValue.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelKhrMaterialsVariantsValue.h new file mode 100644 index 0000000..fd12701 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelKhrMaterialsVariantsValue.h @@ -0,0 +1,42 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief An object defining a valid material variant + */ +struct CESIUMGLTF_API ExtensionModelKhrMaterialsVariantsValue final + : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = + "ExtensionModelKhrMaterialsVariantsValue"; + + /** + * @brief The name of the material variant. + */ + std::string name; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionModelKhrMaterialsVariantsValue)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + accum += int64_t(this->name.capacity() * sizeof(char)); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelMaxarMeshVariants.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelMaxarMeshVariants.h new file mode 100644 index 0000000..0008d47 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelMaxarMeshVariants.h @@ -0,0 +1,61 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief glTF extension that defines mesh variants for nodes + */ +struct CESIUMGLTF_API ExtensionModelMaxarMeshVariants final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionModelMaxarMeshVariants"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "MAXAR_mesh_variants"; + + /** + * @brief The index of the variant to load by default. The meshes that are + * mapped to the default variant must represent the set of meshes initially + * selected by the nodes for rendering, as per vanilla glTF behavior. + */ + int32_t defaultProperty = -1; + + /** + * @brief variants + */ + std::vector variants; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionModelMaxarMeshVariants)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t( + sizeof(CesiumGltf::ExtensionModelMaxarMeshVariantsValue) * + this->variants.capacity()); + for (const CesiumGltf::ExtensionModelMaxarMeshVariantsValue& value : + this->variants) { + accum += + value.getSizeBytes() - + int64_t(sizeof(CesiumGltf::ExtensionModelMaxarMeshVariantsValue)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelMaxarMeshVariantsValue.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelMaxarMeshVariantsValue.h new file mode 100644 index 0000000..f6ced1f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelMaxarMeshVariantsValue.h @@ -0,0 +1,42 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief An object defining a valid mesh variant + */ +struct CESIUMGLTF_API ExtensionModelMaxarMeshVariantsValue final + : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = + "ExtensionModelMaxarMeshVariantsValue"; + + /** + * @brief The name of the mesh variant + */ + std::string name; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionModelMaxarMeshVariantsValue)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + accum += int64_t(this->name.capacity() * sizeof(char)); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionNodeMaxarMeshVariants.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionNodeMaxarMeshVariants.h new file mode 100644 index 0000000..49ce441 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionNodeMaxarMeshVariants.h @@ -0,0 +1,53 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief MAXAR_mesh_variants node extension + */ +struct CESIUMGLTF_API ExtensionNodeMaxarMeshVariants final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionNodeMaxarMeshVariants"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "MAXAR_mesh_variants"; + + /** + * @brief A list of mesh to variant mappings + */ + std::vector mappings; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionNodeMaxarMeshVariants)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t( + sizeof(CesiumGltf::ExtensionNodeMaxarMeshVariantsMappingsValue) * + this->mappings.capacity()); + for (const CesiumGltf::ExtensionNodeMaxarMeshVariantsMappingsValue& value : + this->mappings) { + accum += value.getSizeBytes() - + int64_t(sizeof( + CesiumGltf::ExtensionNodeMaxarMeshVariantsMappingsValue)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionNodeMaxarMeshVariantsMappingsValue.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionNodeMaxarMeshVariantsMappingsValue.h new file mode 100644 index 0000000..a31a266 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionNodeMaxarMeshVariantsMappingsValue.h @@ -0,0 +1,58 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief ExtensionNodeMaxarMeshVariants Mappings Value + */ +struct CESIUMGLTF_API ExtensionNodeMaxarMeshVariantsMappingsValue final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = + "ExtensionNodeMaxarMeshVariantsMappingsValue"; + + /** + * @brief An array of variant index values. + */ + std::vector variants; + + /** + * @brief The mesh associated with the set of variants. + */ + int32_t mesh = -1; + + /** + * @brief The user-defined name of this variant mesh mapping. + */ + std::optional name; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionNodeMaxarMeshVariantsMappingsValue)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(sizeof(int32_t) * this->variants.capacity()); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionTextureWebp.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionTextureWebp.h new file mode 100644 index 0000000..16fe5b7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionTextureWebp.h @@ -0,0 +1,44 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief glTF extension to specify textures using the WebP image format. + */ +struct CESIUMGLTF_API ExtensionTextureWebp final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "ExtensionTextureWebp"; + /** @brief The official name of the extension. This should be the same as its + * key in the `extensions` object. */ + static constexpr const char* ExtensionName = "EXT_texture_webp"; + + /** + * @brief The index of the images node which points to a WebP image. + */ + int32_t source = -1; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensionTextureWebp)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureId.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureId.h new file mode 100644 index 0000000..e6adf9e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureId.h @@ -0,0 +1,80 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief Feature IDs stored in an attribute or texture. + */ +struct CESIUMGLTF_API FeatureId final : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "FeatureId"; + + /** + * @brief The number of unique features in the attribute or texture. + */ + int64_t featureCount = int64_t(); + + /** + * @brief A value that indicates that no feature is associated with this + * vertex or texel. + */ + std::optional nullFeatureId; + + /** + * @brief A label assigned to this feature ID set. Labels must be alphanumeric + * identifiers matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`. + */ + std::optional label; + + /** + * @brief An integer value used to construct a string in the format + * `_FEATURE_ID_` which is a reference to a key in + * `mesh.primitives.attributes` (e.g. a value of `0` corresponds to + * `_FEATURE_ID_0`). + */ + std::optional attribute; + + /** + * @brief A texture containing feature IDs. + */ + std::optional texture; + + /** + * @brief The index of the property table containing per-feature property + * values. Only applicable when using the `EXT_structural_metadata` extension. + */ + int32_t propertyTable = -1; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(FeatureId)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->label) { + accum += int64_t(this->label->capacity() * sizeof(char)); + } + if (this->texture) { + accum += this->texture->getSizeBytes() - + int64_t(sizeof(CesiumGltf::FeatureIdTexture)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIdTexture.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIdTexture.h new file mode 100644 index 0000000..9a6b637 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIdTexture.h @@ -0,0 +1,43 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief A texture containing feature IDs + */ +struct CESIUMGLTF_API FeatureIdTexture final : public TextureInfo { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "FeatureIdTexture"; + + /** + * @brief Texture channels containing feature IDs, identified by index. + * Feature IDs may be packed into multiple channels if a single channel does + * not have sufficient bit depth to represent all feature ID values. The + * values are packed in little-endian order. + */ + std::vector channels = {0}; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(FeatureIdTexture)); + accum += TextureInfo::getSizeBytes() - int64_t(sizeof(TextureInfo)); + accum += int64_t(sizeof(int64_t) * this->channels.capacity()); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIdTextureView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIdTextureView.h new file mode 100644 index 0000000..609cd68 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIdTextureView.h @@ -0,0 +1,136 @@ +#pragma once + +#include "CesiumGltf/FeatureIdTexture.h" +#include "CesiumGltf/TextureView.h" + +#include + +namespace CesiumGltf { + +struct Model; + +/** + * @brief The status of a feature ID texture view. + * + * The {@link FeatureIdTextureView} constructor always completes successfully, + * but it may not always reflect the actual content of the + * {@link FeatureIdTexture}. This enumeration provides the reason. + */ +enum class FeatureIdTextureViewStatus { + /** + * @brief This view is valid and ready to use. + */ + Valid, + + /** + * @brief This view has not yet been initialized. + */ + ErrorUninitialized, + + /** + * @brief This feature ID texture has a texture index that doesn't exist in + * the glTF. + */ + ErrorInvalidTexture, + + /** + * @brief This feature ID texture has an image index that doesn't exist in + * the glTF. + */ + ErrorInvalidImage, + + /** + * @brief This feature ID texture has a sampler index that doesn't exist in + * the glTF. + */ + ErrorInvalidSampler, + + /** + * @brief This feature ID texture has an empty image. + */ + ErrorEmptyImage, + + /** + * @brief The image for this feature ID texture has channels that take up more + * than a byte. Only single-byte channels are supported. + */ + ErrorInvalidImageBytesPerChannel, + + /** + * @brief The channels of this feature ID texture property are invalid. + * Channels must be in the range 0-3, with a minimum of one channel. Although + * more than four channels can be defined for specialized texture + * formats, this view only supports a maximum of four channels. + */ + ErrorInvalidChannels +}; + +/** + * @brief A view on the image data of {@link FeatureIdTexture}. + * + * It provides the ability to sample the feature IDs from the + * {@link FeatureIdTexture} using texture coordinates. + */ +class FeatureIdTextureView : public TextureView { +public: + /** + * @brief Constructs an uninitialized and invalid view. + */ + FeatureIdTextureView() noexcept; + + /** + * @brief Construct a view of the data specified by a {@link FeatureIdTexture}. + * + * A feature ID texture may contain the `KHR_texture_transform` extension, + * which transforms the texture coordinates used to sample the texture. The + * extension may also override the TEXCOORD set index that was originally + * specified by the feature ID texture. + * + * If a view is constructed with applyKhrTextureTransformExtension set to + * true, the view will automatically apply the texture transform to any UV + * coordinates used to sample the texture. If the extension defines its own + * TEXCOORD set index, it will override the original value. + * + * Otherwise, if the flag is set to false, UVs will not be transformed and + * the original TEXCOORD set index will be preserved. The extension's values + * may still be retrieved using getTextureTransform, if desired. + * + * @param model The glTF in which to look for the feature ID texture's data. + * @param featureIdTexture The feature ID texture to create a view for. + * @param options The set of options to use for this `FeatureIdTextureView`. + */ + FeatureIdTextureView( + const Model& model, + const FeatureIdTexture& featureIdTexture, + const TextureViewOptions& options = TextureViewOptions()) noexcept; + + /** + * @brief Get the feature ID from the texture at the given texture + * coordinates. If the texture is somehow invalid, this returns -1. + * + * @param u The u-component of the texture coordinates. Must be within + * [0.0, 1.0]. + * @param v The v-component of the texture coordinates. Must be within + * [0.0, 1.0]. + * @return The feature ID at the nearest pixel to the texture coordinates. + */ + int64_t getFeatureID(double u, double v) const noexcept; + + /** + * @brief Get the status of this view. + * + * If invalid, it will not be safe to sample feature IDs from this view. + */ + FeatureIdTextureViewStatus status() const noexcept { return this->_status; } + + /** + * @brief Get the channels of this feature ID texture. The channels represent + * the bytes of the actual feature ID, in little-endian order. + */ + std::vector getChannels() const noexcept { return this->_channels; } + +private: + FeatureIdTextureViewStatus _status; + std::vector _channels; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Image.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Image.h new file mode 100644 index 0000000..5a06d12 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Image.h @@ -0,0 +1,19 @@ +#pragma once + +#include "CesiumGltf/ImageAsset.h" +#include "CesiumGltf/ImageSpec.h" +#include "CesiumGltf/Library.h" +#include "CesiumUtility/IntrusivePointer.h" + +namespace CesiumGltf { +/** @copydoc ImageSpec */ +struct CESIUMGLTF_API Image final : public ImageSpec { + Image() = default; + + /** + * @brief The loaded image asset. When an image is loaded from a URL, multiple + * `Image` instances may all point to the same `ImageAsset` instance. + */ + CesiumUtility::IntrusivePointer pAsset; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ImageAsset.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ImageAsset.h new file mode 100644 index 0000000..afa6666 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ImageAsset.h @@ -0,0 +1,132 @@ +#pragma once + +#include "CesiumGltf/Ktx2TranscodeTargets.h" +#include "CesiumGltf/Library.h" +#include "CesiumUtility/SharedAsset.h" + +#include +#include +#include +#include + +namespace CesiumGltf { + +/** + * @brief The byte range within a buffer where this mip exists. + */ +struct CESIUMGLTF_API ImageAssetMipPosition { + /** + * @brief The byte index where this mip begins. + */ + size_t byteOffset; + + /** + * @brief The size in bytes of this mip. + */ + size_t byteSize; +}; + +/** + * @brief A 2D image asset, including its pixel data. The image may have + * mipmaps, and it may be encoded in a GPU compression format. + */ +struct CESIUMGLTF_API ImageAsset final + : public CesiumUtility::SharedAsset { + /** + * @brief The width of the image in pixels. + */ + int32_t width = 0; + + /** + * @brief The height of the image in pixels. + */ + int32_t height = 0; + + /** + * @brief The number of channels per pixel. + */ + int32_t channels = 4; + + /** + * @brief The number of bytes per channel. + */ + int32_t bytesPerChannel = 1; + + /** + * @brief The gpu compressed pixel format for this image or NONE if it is not + * compressed. + */ + GpuCompressedPixelFormat compressedPixelFormat = + GpuCompressedPixelFormat::NONE; + + /** + * @brief The offset of each mip in the pixel data. + * + * A list of the positions of each mip's data within the overall pixel buffer. + * The first element will be the full image, the second will be the second + * biggest and etc. If this is empty, assume the entire buffer is a single + * image, the mip map will need to be generated on the client in this case. + */ + std::vector mipPositions; + + /** + * @brief The pixel data. + * + * This will be the raw pixel data when compressedPixelFormat is std::nullopt. + * Otherwise, this buffer will store the compressed pixel data in the + * specified format. + * + * If mipPositions is not empty, this buffer will contains multiple mips + * back-to-back. + * + * When this is an uncompressed texture: + * -The pixel data is consistent with the + * [stb](https://github.com/nothings/stb) image library. + * + * -For a correctly-formed image, the size of the array will be + * `width * height * channels * bytesPerChannel` bytes. There is no + * padding between rows or columns of the image, regardless of format. + * + * -The channels and their meaning are as follows: + * + * | Number of Channels | Channel Order and Meaning | + * |--------------------|---------------------------| + * | 1 | grey | + * | 2 | grey, alpha | + * | 3 | red, green, blue | + * | 4 | red, green, blue, alpha | + */ + std::vector pixelData; + + /** + * @brief The effective size of this image, in bytes, for estimating resource + * usage for caching purposes. + * + * When this value is less than zero (the default), the size of this image + * should be assumed to equal the size of the {@link pixelData} array. When + * it is greater than or equal to zero, the specified size should be used + * instead. For example, the overridden size may account for: + * * The `pixelData` being cleared during the load process in order to save + * memory. + * * The cost of any renderer resources (e.g., GPU textures) created for + * this image. + */ + int64_t sizeBytes = -1; + + /** + * @brief Constructs an empty image asset. + */ + ImageAsset() = default; + + /** + * @brief Gets the size of this asset, in bytes. + * + * If {@link sizeBytes} is greater than or equal to zero, it is returned. + * Otherwise, the size of the {@link pixelData} array is returned. + */ + int64_t getSizeBytes() const { + return this->sizeBytes >= 0 ? this->sizeBytes + : static_cast(this->pixelData.size()); + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ImageSpec.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ImageSpec.h new file mode 100644 index 0000000..48e0261 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ImageSpec.h @@ -0,0 +1,83 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief Image data used to create a texture. Image **MAY** be referenced by an + * URI (or IRI) or a buffer view index. + */ +struct CESIUMGLTF_API ImageSpec : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Image"; + + /** + * @brief Known values for The image's media type. This field **MUST** be + * defined when `bufferView` is defined. + */ + struct MimeType { + /** @brief `image/jpeg` */ + inline static const std::string image_jpeg = "image/jpeg"; + + /** @brief `image/png` */ + inline static const std::string image_png = "image/png"; + }; + + /** + * @brief The URI (or IRI) of the image. + * + * Relative paths are relative to the current glTF asset. Instead of + * referencing an external file, this field **MAY** contain a `data:`-URI. + * This field **MUST NOT** be defined when `bufferView` is defined. + */ + std::optional uri; + + /** + * @brief The image's media type. This field **MUST** be defined when + * `bufferView` is defined. + * + * Known values are defined in {@link MimeType}. + * + */ + std::optional mimeType; + + /** + * @brief The index of the bufferView that contains the image. This field + * **MUST NOT** be defined when `uri` is defined. + */ + int32_t bufferView = -1; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ImageSpec)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + if (this->uri) { + accum += int64_t(this->uri->capacity() * sizeof(char)); + } + return accum; + } + +protected: + /** + * @brief This class is not meant to be instantiated directly. Use {@link Image} instead. + */ + ImageSpec() = default; + friend struct Image; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/InstanceAttributeSemantics.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/InstanceAttributeSemantics.h new file mode 100644 index 0000000..6c2b922 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/InstanceAttributeSemantics.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +namespace CesiumGltf { + +/** + * @brief The standard glTF instance attribute semantics from + * `EXT_mesh_gpu_instancing` plus additional instance attribute semantics from + * extensions. + */ +struct InstanceAttributeSemantics { + /** + * @brief XYZ translation vector. + */ + static const std::string TRANSLATION; + + /** + * @brief XYZW rotation quaternion. + */ + static const std::string ROTATION; + + /** + * @brief XYZ scale vector. + */ + static const std::string SCALE; + + /** + * @brief Feature IDs used by `EXT_instance_features`. + */ + static const std::array FEATURE_ID_n; +}; + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/KhrTextureTransform.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/KhrTextureTransform.h new file mode 100644 index 0000000..4505b6d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/KhrTextureTransform.h @@ -0,0 +1,91 @@ +#pragma once + +#include "CesiumGltf/ExtensionKhrTextureTransform.h" + +#include + +namespace CesiumGltf { +/** + * @brief The status of a parsed KHR_texture_transform. + * + * The {@link KhrTextureTransform} constructor always completes successfully, + * but it may not always reflect the actual transform if errors occur. This + * enumeration provides the reason. + */ +enum class KhrTextureTransformStatus { + Valid, + ErrorInvalidOffset, + ErrorInvalidScale +}; + +/** + * @brief A utility class that parses KHR_texture_transform parameters and + * transforms input texture coordinates. + */ +class KhrTextureTransform { +public: + /** + * @brief Constructs a texture transformation with identity values. + */ + KhrTextureTransform() noexcept; + + /** + * @brief Constructs a texture transformation from the given extension. + */ + KhrTextureTransform(const ExtensionKhrTextureTransform& extension) noexcept; + + /** + * @brief The current \ref KhrTextureTransformStatus of the transform + * operation. + */ + KhrTextureTransformStatus status() const noexcept { return this->_status; } + + /** + * @brief Gets the offset of the texture transform. + */ + glm::dvec2 offset() const noexcept { return this->_offset; } + + /** + * @brief Gets the rotation (in radians) of the texture transform. + */ + double rotation() const noexcept { return this->_rotation; } + + /** + * @brief Gets the sine and cosine of the rotation in the texture transform. + * This is cached to avoid re-computing the values in the future. + */ + glm::dvec2 rotationSineCosine() const noexcept { + return this->_rotationSineCosine; + } + + /** + * @brief Gets the scale of the texture transform. + */ + glm::dvec2 scale() const noexcept { return this->_scale; } + + /** + * @brief Applies this texture transformation to the input coordinates. + */ + glm::dvec2 applyTransform(double u, double v) const noexcept; + + /** + * @brief Gets the texture coordinate set index used by this texture + * transform. If defined, this should override the set index of the texture's + * original textureInfo. + */ + std::optional getTexCoordSetIndex() const noexcept { + return this->_texCoordSetIndex; + } + +private: + KhrTextureTransformStatus _status; + glm::dvec2 _offset; + double _rotation; + glm::dvec2 _scale; + std::optional _texCoordSetIndex; + + // Cached values of sin(rotation) and cos(rotation). + glm::dvec2 _rotationSineCosine; +}; + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Ktx2TranscodeTargets.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Ktx2TranscodeTargets.h new file mode 100644 index 0000000..103e491 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Ktx2TranscodeTargets.h @@ -0,0 +1,214 @@ +#pragma once + +#include "CesiumGltf/Library.h" + +namespace CesiumGltf { + +/** + * @brief Supported GPU compressed pixel formats. + */ +enum class CESIUMGLTF_API GpuCompressedPixelFormat { + /** + * @brief The data is uncompressed. + */ + NONE, + /** + * @brief The data is an ETC1-compressed + * RGB888 texture. + */ + ETC1_RGB, + /** + * @brief The data is an ETC2-compressed RGBA8888 texture. + */ + ETC2_RGBA, + /** + * @brief The data is a BC1-compressed + * RGB565 texture. + */ + BC1_RGB, + /** + * @brief The data is a BC3-compressed + * RGBA5658 texture. + */ + BC3_RGBA, + /** + * @brief The data is a BC4-compressed + * R8 texture. + */ + BC4_R, + /** + * @brief The data is a BC5-compressed + * RG88 texture. + */ + BC5_RG, + /** + * @brief The data is a BC7-compressed + * RGBA8888 texture. + */ + BC7_RGBA, + /** + * @brief The data is a PVRTC1-compressed + * RGB444 texture. + */ + PVRTC1_4_RGB, + /** + * @brief The data is a PVRTC1-compressed + * RGBA4444 texture. + */ + PVRTC1_4_RGBA, + /** + * @brief The data is a ASTC-compressed + * RGBA texture with a 4x4 block footprint. + */ + ASTC_4x4_RGBA, + /** + * @brief The data is a PVRTC2-compressed + * RGB444 texture. + */ + PVRTC2_4_RGB, + /** + * @brief The data is a PVRTC2-compressed + * RGBA4444 texture. + */ + PVRTC2_4_RGBA, + /** + * @brief The data is a ETC2 + * R11 EAC-compressed texture with a single channel. + */ + ETC2_EAC_R11, + /** + * @brief The data is a ETC2 + * RG11 EAC-compressed texture with two channels. + */ + ETC2_EAC_RG11 +}; + +/** + * @brief Represents the status of support for all + * {@link GpuCompressedPixelFormat}s on a client platform. + * + * Clients can use this struct to convey which gpu compressed pixel formats are + * supported. This can be used to construct a {@link Ktx2TranscodeTargets}. + * + * Each entry in the struct is a bool that represents whether the gpu + * compressed pixel format with the corresponding name is supported. + */ +struct CESIUMGLTF_API SupportedGpuCompressedPixelFormats { + /** @copydoc GpuCompressedPixelFormat::ETC1_RGB */ + bool ETC1_RGB{}; + /** @copydoc GpuCompressedPixelFormat::ETC2_RGBA */ + bool ETC2_RGBA{}; + /** @copydoc GpuCompressedPixelFormat::BC1_RGB */ + bool BC1_RGB{}; + /** @copydoc GpuCompressedPixelFormat::BC3_RGBA */ + bool BC3_RGBA{}; + /** @copydoc GpuCompressedPixelFormat::BC4_R */ + bool BC4_R{}; + /** @copydoc GpuCompressedPixelFormat::BC5_RG */ + bool BC5_RG{}; + /** @copydoc GpuCompressedPixelFormat::BC7_RGBA */ + bool BC7_RGBA{}; + /** @copydoc GpuCompressedPixelFormat::PVRTC1_4_RGB */ + bool PVRTC1_4_RGB{}; + /** @copydoc GpuCompressedPixelFormat::PVRTC1_4_RGBA */ + bool PVRTC1_4_RGBA{}; + /** @copydoc GpuCompressedPixelFormat::ASTC_4x4_RGBA */ + bool ASTC_4x4_RGBA{}; + /** @copydoc GpuCompressedPixelFormat::PVRTC2_4_RGB */ + bool PVRTC2_4_RGB{}; + /** @copydoc GpuCompressedPixelFormat::PVRTC2_4_RGBA */ + bool PVRTC2_4_RGBA{}; + /** @copydoc GpuCompressedPixelFormat::ETC2_EAC_R11 */ + bool ETC2_EAC_R11{}; + /** @copydoc GpuCompressedPixelFormat::ETC2_EAC_RG11 */ + bool ETC2_EAC_RG11{}; +}; + +/** + * @brief For each possible input transmission format, this struct names + * the ideal target gpu-compressed pixel format to transcode to. + * + * When built with the constructor, these targets can take into account + * platform-specific support for target formats as reported by the client. + */ +struct CESIUMGLTF_API Ktx2TranscodeTargets { + + /** + * @brief The gpu pixel compression format to transcode Red ETC1S textures + * into. If NONE, it will be decompressed into raw pixels. + */ + GpuCompressedPixelFormat ETC1S_R = GpuCompressedPixelFormat::NONE; + + /** + * @brief The gpu pixel compression format to transcode Red-Green ETC1S + * textures into, if one exists. Otherwise it will be decompressed into raw + * pixels. + */ + GpuCompressedPixelFormat ETC1S_RG = GpuCompressedPixelFormat::NONE; + + /** + * @brief The gpu pixel compression format to transcode RGB ETC1S textures + * into. If NONE, it will be decompressed into raw pixels. + */ + GpuCompressedPixelFormat ETC1S_RGB = GpuCompressedPixelFormat::NONE; + + /** + * @brief The gpu pixel compression format to transcode RGBA ETC1S textures + * into. If NONE, it will be decompressed into raw pixels. + */ + GpuCompressedPixelFormat ETC1S_RGBA = GpuCompressedPixelFormat::NONE; + + /** + * @brief The gpu pixel compression format to transcode Red UASTC textures + * into. If NONE, it will be decompressed into raw pixels. + */ + GpuCompressedPixelFormat UASTC_R = GpuCompressedPixelFormat::NONE; + + /** + * @brief The gpu pixel compression format to transcode Red-Green UASTC + * textures into. If NONE, it will be decompressed into raw pixels. + */ + GpuCompressedPixelFormat UASTC_RG = GpuCompressedPixelFormat::NONE; + + /** + * @brief The gpu pixel compression format to transcode RGB UASTC textures + * into. If NONE, it will be decompressed into raw pixels. + */ + GpuCompressedPixelFormat UASTC_RGB = GpuCompressedPixelFormat::NONE; + + /** + * @brief The gpu pixel compression format to transcode RGBA UASTC textures + * into. If NONE, it will be decompressed into raw pixels. + */ + GpuCompressedPixelFormat UASTC_RGBA = GpuCompressedPixelFormat::NONE; + + Ktx2TranscodeTargets() = default; + + /** + * @brief Determine ideal transcode targets based on a list of supported gpu + * compressed formats. + * + * @param supportedFormats The supported gpu compressed pixel formats. + * @param preserveHighQuality Whether to preserve texture quality when + * transcoding KTXv2 textures. If this is true, the texture may be fully + * decompressed instead of picking a lossy target gpu compressed pixel format. + */ + Ktx2TranscodeTargets( + const SupportedGpuCompressedPixelFormats& supportedFormats, + bool preserveHighQuality); +}; + +} // namespace CesiumGltf \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Library.h new file mode 100644 index 0000000..8a4fc2b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes for working with [glTF](https://www.khronos.org/gltf/) models. + * + * @mermaid-interactive{dependencies/CesiumGltf} + */ +namespace CesiumGltf {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMGLTF_BUILDING +#define CESIUMGLTF_API __declspec(dllexport) +#else +#define CESIUMGLTF_API __declspec(dllimport) +#endif +#else +#define CESIUMGLTF_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Material.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Material.h new file mode 100644 index 0000000..c64c9a1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Material.h @@ -0,0 +1,160 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief The material appearance of a primitive. + */ +struct CESIUMGLTF_API Material final : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Material"; + + /** + * @brief Known values for The alpha rendering mode of the material. + */ + struct AlphaMode { + /** @brief The alpha value is ignored, and the rendered output is fully + * opaque. */ + inline static const std::string OPAQUE = "OPAQUE"; + + /** @brief The rendered output is either fully opaque or fully transparent + * depending on the alpha value and the specified `alphaCutoff` value; the + * exact appearance of the edges **MAY** be subject to + * implementation-specific techniques such as "`Alpha-to-Coverage`". */ + inline static const std::string MASK = "MASK"; + + /** @brief The alpha value is used to composite the source and destination + * areas. The rendered output is combined with the background using the + * normal painting operation (i.e. the Porter and Duff over operator). */ + inline static const std::string BLEND = "BLEND"; + }; + + /** + * @brief A set of parameter values that are used to define the + * metallic-roughness material model from Physically Based Rendering (PBR) + * methodology. When undefined, all the default values of + * `pbrMetallicRoughness` **MUST** apply. + */ + std::optional pbrMetallicRoughness; + + /** + * @brief The tangent space normal texture. + * + * The texture encodes RGB components with linear transfer function. Each + * texel represents the XYZ components of a normal vector in tangent space. + * The normal vectors use the convention +X is right and +Y is up. +Z points + * toward the viewer. If a fourth component (A) is present, it **MUST** be + * ignored. When undefined, the material does not have a tangent space normal + * texture. + */ + std::optional normalTexture; + + /** + * @brief The occlusion texture. + * + * The occlusion values are linearly sampled from the R channel. Higher values + * indicate areas that receive full indirect lighting and lower values + * indicate no indirect lighting. If other channels are present (GBA), they + * **MUST** be ignored for occlusion calculations. When undefined, the + * material does not have an occlusion texture. + */ + std::optional occlusionTexture; + + /** + * @brief The emissive texture. + * + * It controls the color and intensity of the light being emitted by the + * material. This texture contains RGB components encoded with the sRGB + * transfer function. If a fourth component (A) is present, it **MUST** be + * ignored. When undefined, the texture **MUST** be sampled as having `1.0` in + * RGB components. + */ + std::optional emissiveTexture; + + /** + * @brief The factors for the emissive color of the material. + * + * This value defines linear multipliers for the sampled texels of the + * emissive texture. + */ + std::vector emissiveFactor = {0, 0, 0}; + + /** + * @brief The alpha rendering mode of the material. + * + * Known values are defined in {@link AlphaMode}. + * + * + * The material's alpha rendering mode enumeration specifying the + * interpretation of the alpha value of the base color. + */ + std::string alphaMode = AlphaMode::OPAQUE; + + /** + * @brief The alpha cutoff value of the material. + * + * Specifies the cutoff threshold when in `MASK` alpha mode. If the alpha + * value is greater than or equal to this value then it is rendered as fully + * opaque, otherwise, it is rendered as fully transparent. A value greater + * than `1.0` will render the entire material as fully transparent. This value + * **MUST** be ignored for other alpha modes. When `alphaMode` is not defined, + * this value **MUST NOT** be defined. + */ + double alphaCutoff = 0.5; + + /** + * @brief Specifies whether the material is double sided. + * + * When this value is false, back-face culling is enabled. When this value is + * true, back-face culling is disabled and double-sided lighting is enabled. + * The back-face **MUST** have its normals reversed before the lighting + * equation is evaluated. + */ + bool doubleSided = false; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Material)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + if (this->pbrMetallicRoughness) { + accum += this->pbrMetallicRoughness->getSizeBytes() - + int64_t(sizeof(CesiumGltf::MaterialPBRMetallicRoughness)); + } + if (this->normalTexture) { + accum += this->normalTexture->getSizeBytes() - + int64_t(sizeof(CesiumGltf::MaterialNormalTextureInfo)); + } + if (this->occlusionTexture) { + accum += this->occlusionTexture->getSizeBytes() - + int64_t(sizeof(CesiumGltf::MaterialOcclusionTextureInfo)); + } + if (this->emissiveTexture) { + accum += this->emissiveTexture->getSizeBytes() - + int64_t(sizeof(CesiumGltf::TextureInfo)); + } + accum += int64_t(sizeof(double) * this->emissiveFactor.capacity()); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MaterialNormalTextureInfo.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MaterialNormalTextureInfo.h new file mode 100644 index 0000000..f7e3256 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MaterialNormalTextureInfo.h @@ -0,0 +1,43 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +namespace CesiumGltf { +/** + * @brief Material Normal Texture Info + */ +struct CESIUMGLTF_API MaterialNormalTextureInfo final : public TextureInfo { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "MaterialNormalTextureInfo"; + + /** + * @brief The scalar parameter applied to each normal vector of the normal + * texture. + * + * The scalar parameter applied to each normal vector of the texture. This + * value scales the normal vector in X and Y directions using the formula: + * `scaledNormal = normalize(( * 2.0 - 1.0) * + * vec3(, , 1.0))`. + */ + double scale = 1; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(MaterialNormalTextureInfo)); + accum += TextureInfo::getSizeBytes() - int64_t(sizeof(TextureInfo)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MaterialOcclusionTextureInfo.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MaterialOcclusionTextureInfo.h new file mode 100644 index 0000000..704067a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MaterialOcclusionTextureInfo.h @@ -0,0 +1,42 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +namespace CesiumGltf { +/** + * @brief Material Occlusion Texture Info + */ +struct CESIUMGLTF_API MaterialOcclusionTextureInfo final : public TextureInfo { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "MaterialOcclusionTextureInfo"; + + /** + * @brief A scalar multiplier controlling the amount of occlusion applied. + * + * A scalar parameter controlling the amount of occlusion applied. A value of + * `0.0` means no occlusion. A value of `1.0` means full occlusion. This value + * affects the final occlusion value as: `1.0 + strength * ( - 1.0)`. + */ + double strength = 1; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(MaterialOcclusionTextureInfo)); + accum += TextureInfo::getSizeBytes() - int64_t(sizeof(TextureInfo)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MaterialPBRMetallicRoughness.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MaterialPBRMetallicRoughness.h new file mode 100644 index 0000000..bc6b160 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MaterialPBRMetallicRoughness.h @@ -0,0 +1,96 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief A set of parameter values that are used to define the + * metallic-roughness material model from Physically-Based Rendering (PBR) + * methodology. + */ +struct CESIUMGLTF_API MaterialPBRMetallicRoughness final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "MaterialPBRMetallicRoughness"; + + /** + * @brief The factors for the base color of the material. + * + * This value defines linear multipliers for the sampled texels of the base + * color texture. + */ + std::vector baseColorFactor = {1, 1, 1, 1}; + + /** + * @brief The base color texture. + * + * The first three components (RGB) **MUST** be encoded with the sRGB transfer + * function. They specify the base color of the material. If the fourth + * component (A) is present, it represents the linear alpha coverage of the + * material. Otherwise, the alpha coverage is equal to `1.0`. The + * `material.alphaMode` property specifies how alpha is interpreted. The + * stored texels **MUST NOT** be premultiplied. When undefined, the texture + * **MUST** be sampled as having `1.0` in all components. + */ + std::optional baseColorTexture; + + /** + * @brief The factor for the metalness of the material. + * + * This value defines a linear multiplier for the sampled metalness values of + * the metallic-roughness texture. + */ + double metallicFactor = 1; + + /** + * @brief The factor for the roughness of the material. + * + * This value defines a linear multiplier for the sampled roughness values of + * the metallic-roughness texture. + */ + double roughnessFactor = 1; + + /** + * @brief The metallic-roughness texture. + * + * The metalness values are sampled from the B channel. The roughness values + * are sampled from the G channel. These values **MUST** be encoded with a + * linear transfer function. If other channels are present (R or A), they + * **MUST** be ignored for metallic-roughness calculations. When undefined, + * the texture **MUST** be sampled as having `1.0` in G and B components. + */ + std::optional metallicRoughnessTexture; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(MaterialPBRMetallicRoughness)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(sizeof(double) * this->baseColorFactor.capacity()); + if (this->baseColorTexture) { + accum += this->baseColorTexture->getSizeBytes() - + int64_t(sizeof(CesiumGltf::TextureInfo)); + } + if (this->metallicRoughnessTexture) { + accum += this->metallicRoughnessTexture->getSizeBytes() - + int64_t(sizeof(CesiumGltf::TextureInfo)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Mesh.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Mesh.h new file mode 100644 index 0000000..e867f94 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Mesh.h @@ -0,0 +1,54 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief A set of primitives to be rendered. Its global transform is defined + * by a node that references it. + */ +struct CESIUMGLTF_API Mesh final : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Mesh"; + + /** + * @brief An array of primitives, each defining geometry to be rendered. + */ + std::vector primitives; + + /** + * @brief Array of weights to be applied to the morph targets. The number of + * array elements **MUST** match the number of morph targets. + */ + std::vector weights; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Mesh)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + accum += int64_t( + sizeof(CesiumGltf::MeshPrimitive) * this->primitives.capacity()); + for (const CesiumGltf::MeshPrimitive& value : this->primitives) { + accum += + value.getSizeBytes() - int64_t(sizeof(CesiumGltf::MeshPrimitive)); + } + accum += int64_t(sizeof(double) * this->weights.capacity()); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MeshPrimitive.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MeshPrimitive.h new file mode 100644 index 0000000..1dd714a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MeshPrimitive.h @@ -0,0 +1,108 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief Geometry to be rendered with the given material. + */ +struct CESIUMGLTF_API MeshPrimitive final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "MeshPrimitive"; + + /** + * @brief Known values for The topology type of primitives to render. + */ + struct Mode { + /** @brief POINTS (`0`) */ + static constexpr int32_t POINTS = 0; + + /** @brief LINES (`1`) */ + static constexpr int32_t LINES = 1; + + /** @brief LINE_LOOP (`2`) */ + static constexpr int32_t LINE_LOOP = 2; + + /** @brief LINE_STRIP (`3`) */ + static constexpr int32_t LINE_STRIP = 3; + + /** @brief TRIANGLES (`4`) */ + static constexpr int32_t TRIANGLES = 4; + + /** @brief TRIANGLE_STRIP (`5`) */ + static constexpr int32_t TRIANGLE_STRIP = 5; + + /** @brief TRIANGLE_FAN (`6`) */ + static constexpr int32_t TRIANGLE_FAN = 6; + }; + + /** + * @brief A plain JSON object, where each key corresponds to a mesh attribute + * semantic and each value is the index of the accessor containing attribute's + * data. + */ + std::unordered_map attributes; + + /** + * @brief The index of the accessor that contains the vertex indices. + * + * When this is undefined, the primitive defines non-indexed geometry. When + * defined, the accessor **MUST** have `SCALAR` type and an unsigned integer + * component type. + */ + int32_t indices = -1; + + /** + * @brief The index of the material to apply to this primitive when rendering. + */ + int32_t material = -1; + + /** + * @brief The topology type of primitives to render. + * + * Known values are defined in {@link Mode}. + * + */ + int32_t mode = Mode::TRIANGLES; + + /** + * @brief An array of morph targets. + */ + std::vector> targets; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(MeshPrimitive)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t( + this->attributes.bucket_count() * + (sizeof(std::string) + sizeof(int32_t))); + for (const auto& [k, v] : this->attributes) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += int64_t(sizeof(int32_t)); + } + accum += int64_t( + sizeof(std::unordered_map) * + this->targets.capacity()); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MetadataConversions.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MetadataConversions.h new file mode 100644 index 0000000..8c5b5d7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MetadataConversions.h @@ -0,0 +1,865 @@ +#pragma once + +#include "PropertyTypeTraits.h" + +#include + +#include + +#include +#include +#include +#include +#include + +#ifndef GLM_ENABLE_EXPERIMENTAL +// If we define GLM_ENABLE_EXPERIMENTAL here, we undefine it at the end of this +// header file. +#define GLM_ENABLE_EXPERIMENTAL +#define GLM_ENABLE_EXPERIMENTAL_defined_locally +#endif +#include + +namespace CesiumGltf { +/** + * @brief Default conversion between two types. No actual conversion is defined. + * This returns std::nullopt to indicate the conversion was not successful. + */ +template +struct MetadataConversions { + /** + * @brief Converts between `TFrom` and `TTo` where no actual conversion is + * defined, returning `std::nullopt`. + */ + static std::optional convert(TFrom /*from*/) { return std::nullopt; } +}; + +/** + * @brief Trivially converts any type to itself. + */ +template struct MetadataConversions { + /** + * @brief Converts an instance of `T` to an instance of `T`, always returning + * the same value that was passed in. + */ + static std::optional convert(T from) { return from; } +}; + +#pragma region Conversions to boolean +/** + * @brief Converts from a scalar to a bool. + */ +template +struct MetadataConversions< + bool, + TFrom, + std::enable_if_t::value>> { + /** + * @brief Converts a scalar to a boolean. Zero is converted to false, while + * nonzero values are converted to true. + * + * @param from The scalar to convert from. + */ + static std::optional convert(TFrom from) { + return from != static_cast(0); + } +}; + +/** + * @brief Converts from std::string_view to a bool. + */ +template <> struct MetadataConversions { +private: + static bool + isEqualCaseInsensitive(const std::string_view& a, const std::string_view& b) { + if (a.size() != b.size()) { + return false; + } + + for (size_t i = 0; i < a.size(); i++) { + if (std::tolower(a[i]) != std::tolower(b[i])) { + return false; + } + } + return true; + } + +public: + /** + * @brief Converts the contents of a std::string_view to a boolean. + * + * "0", "false", and "no" (case-insensitive) are converted to false, while + * "1", "true", and "yes" are converted to true. All other strings will return + * std::nullopt. + * + * @param from The std::string_view to convert from. + */ + static std::optional convert(const std::string_view& from) { + if (isEqualCaseInsensitive(from, "1") || + isEqualCaseInsensitive(from, "true") || + isEqualCaseInsensitive(from, "yes")) { + return true; + } + + if (isEqualCaseInsensitive(from, "0") || + isEqualCaseInsensitive(from, "false") || + isEqualCaseInsensitive(from, "no")) { + return false; + } + + return std::nullopt; + } +}; + +/** + * @brief Converts from std::string to a bool. + */ +template <> struct MetadataConversions { +public: + /** + * @brief Converts the contents of a std::string to a boolean. + * + * "0", "false", and "no" (case-insensitive) are converted to false, while + * "1", "true", and "yes" are converted to true. All other strings will return + * std::nullopt. + * + * @param from The std::string to convert from. + */ + static std::optional convert(const std::string& from) { + return MetadataConversions::convert( + std::string_view(from.data(), from.size())); + } +}; + +#pragma endregion + +#pragma region Conversions to integer +/** + * @brief Converts from one integer type to another. + */ +template +struct MetadataConversions< + TTo, + TFrom, + std::enable_if_t< + CesiumGltf::IsMetadataInteger::value && + CesiumGltf::IsMetadataInteger::value && + !std::is_same_v>> { + /** + * @brief Converts a value of the given integer to another integer type. If + * the integer cannot be losslessly converted to the desired type, + * std::nullopt is returned. + * + * @param from The integer value to convert from. + */ + static std::optional convert(TFrom from) { + return CesiumUtility::losslessNarrow(from); + } +}; + +/** + * @brief Converts from a floating-point type to an integer. + */ +template +struct MetadataConversions< + TTo, + TFrom, + std::enable_if_t< + CesiumGltf::IsMetadataInteger::value && + CesiumGltf::IsMetadataFloating::value>> { + /** + * @brief Converts a floating-point value to an integer type. This truncates + * the floating-point value, rounding it towards zero. + * + * If the value is outside the range of the integer type, std::nullopt is + * returned. + * + * @param from The floating-point value to convert from. + */ + static std::optional convert(TFrom from) { + if (double(std::numeric_limits::max()) < from || + double(std::numeric_limits::lowest()) > from) { + // Floating-point number is outside the range of this integer type. + return std::nullopt; + } + + return static_cast(from); + } +}; + +/** + * @brief Converts from std::string to a signed integer. + */ +template +struct MetadataConversions< + TTo, + std::string, + std::enable_if_t< + CesiumGltf::IsMetadataInteger::value && std::is_signed_v>> { + /** + * @brief Converts the contents of a std::string to a signed integer. + * This assumes that the entire std::string represents the number, not + * just a part of it. + * + * This returns std::nullopt if no number is parsed from the string. + * + * @param from The std::string to parse from. + */ + static std::optional convert(const std::string& from) { + if (from.size() == 0) { + // Return early. Otherwise, empty strings will be parsed as 0, which is + // misleading. + return std::nullopt; + } + + errno = 0; + + char* pLastUsed; + int64_t parsedValue = std::strtoll(from.c_str(), &pLastUsed, 10); + if (errno == 0 && pLastUsed == from.c_str() + from.size()) { + // Successfully parsed the entire string as an integer of this type. + return CesiumUtility::losslessNarrow(parsedValue); + } + + errno = 0; + + // Failed to parse as an integer. Maybe we can parse as a double and + // truncate it? + double parsedDouble = std::strtod(from.c_str(), &pLastUsed); + if (errno == 0 && pLastUsed == from.c_str() + from.size()) { + // Successfully parsed the entire string as a double. + // Convert it to an integer if we can. + double truncated = glm::trunc(parsedDouble); + + int64_t asInteger = static_cast(truncated); + double roundTrip = static_cast(asInteger); + if (roundTrip == truncated) { + return CesiumUtility::losslessNarrow(asInteger); + } + } + + return std::nullopt; + } +}; // namespace CesiumGltf + +/** + * @brief Converts from std::string to an unsigned integer. + */ +template +struct MetadataConversions< + TTo, + std::string, + std::enable_if_t< + CesiumGltf::IsMetadataInteger::value && !std::is_signed_v>> { + /** + * @brief Converts the contents of a std::string to an unsigned integer. + * This assumes that the entire std::string represents the number, not + * just a part of it. + * + * This returns std::nullopt if no number is parsed from the string. + * + * @param from The std::string to parse from. + */ + static std::optional convert(const std::string& from) { + if (from.size() == 0) { + // Return early. Otherwise, empty strings will be parsed as 0, which is + // misleading. + return std::nullopt; + } + + if (from.find('-') != std::string::npos) { + // The string must be manually checked for a negative sign because for + // std::strtoull accepts negative numbers and bitcasts them, which is not + // desired! + return std::nullopt; + } + + errno = 0; + + char* pLastUsed; + uint64_t parsedValue = std::strtoull(from.c_str(), &pLastUsed, 10); + if (errno == 0 && pLastUsed == from.c_str() + from.size()) { + // Successfully parsed the entire string as an integer of this type. + return CesiumUtility::losslessNarrow(parsedValue); + } + + // Failed to parse as an integer. Maybe we can parse as a double and + // truncate it? + errno = 0; + + double parsedDouble = std::strtod(from.c_str(), &pLastUsed); + if (errno == 0 && pLastUsed == from.c_str() + from.size()) { + // Successfully parsed the entire string as a double. + // Convert it to an integer if we can. + double truncated = glm::trunc(parsedDouble); + + uint64_t asInteger = static_cast(truncated); + double roundTrip = static_cast(asInteger); + if (roundTrip == truncated) { + return CesiumUtility::losslessNarrow(asInteger); + } + } + + return std::nullopt; + } +}; + +/** + * @brief Converts from std::string_view to an integer. + */ +template +struct MetadataConversions< + TTo, + std::string_view, + std::enable_if_t::value>> { + /** + * @brief Converts the contents of a std::string_view to an integer. + * This assumes that the entire std::string_view represents the number, not + * just a part of it. + * + * This returns std::nullopt if no number is parsed from the string. + * + * @param from The std::string_view to parse from. + */ + static std::optional convert(const std::string_view& from) { + if (from.size() == 0) { + // Return early. Otherwise, empty strings will be parsed as 0, which is + // misleading. + return std::nullopt; + } + + // Amazingly, C++ has no* string parsing functions that work with strings + // that might not be null-terminated. So we have to copy to a std::string + // (which _is_ guaranteed to be null terminated) before parsing. + // * except std::from_chars, but compiler/library support for the + // floating-point version of that method is spotty at best. + return MetadataConversions::convert(std::string(from)); + } +}; + +/** + * @brief Converts from a boolean to an integer type. + */ +template +struct MetadataConversions< + TTo, + bool, + std::enable_if_t::value>> { + /** + * @brief Converts a boolean to an integer. This returns 1 for true, 0 for + * false. + * + * @param from The boolean value to be converted. + */ + static std::optional convert(bool from) { return from ? 1 : 0; } +}; +#pragma endregion + +#pragma region Conversions to float +/** + * @brief Converts from a boolean to a float. + */ +template <> struct MetadataConversions { + /** + * @brief Converts a boolean to a float. This returns 1.0f for true, 0.0f for + * false. + * + * @param from The boolean value to be converted. + */ + static std::optional convert(bool from) { return from ? 1.0f : 0.0f; } +}; + +/** + * @brief Converts from an integer type to a float. + */ +template +struct MetadataConversions< + float, + TFrom, + std::enable_if_t::value>> { + /** + * @brief Converts an integer to a float. The value may lose precision during + * conversion. + * + * @param from The integer value to be converted. + */ + static std::optional convert(TFrom from) { + return static_cast(from); + } +}; + +/** + * @brief Converts from a double to a float. + */ +template <> struct MetadataConversions { + /** + * @brief Converts a double to a float. The value may lose precision during + * conversion. + * + * If the value is outside the range of a float, std::nullopt is returned. + * + * @param from The double value to be converted. + */ + static std::optional convert(double from) { + if (from > std::numeric_limits::max() || + from < std::numeric_limits::lowest()) { + return std::nullopt; + } + return static_cast(from); + } +}; + +/** + * @brief Converts from a std::string to a float. + */ +template <> struct MetadataConversions { + /** + * @brief Converts a std::string to a float. This assumes that the entire + * std::string represents the number, not just a part of it. + * + * This returns std::nullopt if no number is parsed from the string. + * + * @param from The std::string to parse from. + */ + static std::optional convert(const std::string& from) { + if (from.size() == 0) { + // Return early. Otherwise, empty strings will be parsed as 0, which is + // misleading. + return std::nullopt; + } + + errno = 0; + + char* pLastUsed; + float parsedValue = std::strtof(from.c_str(), &pLastUsed); + if (errno == 0 && pLastUsed == from.c_str() + from.size() && + !std::isinf(parsedValue)) { + // Successfully parsed the entire string as a float. + return parsedValue; + } + return std::nullopt; + } +}; + +/** + * @brief Converts from a std::string_view to a float. + */ +template <> struct MetadataConversions { + /** + * @brief Converts a std::string_view to a float. This assumes that the entire + * std::string_view represents the number, not just a part of it. + * + * This returns std::nullopt if no number is parsed from the string. + * + * @param from The std::string_view to parse from. + */ + static std::optional convert(const std::string_view& from) { + if (from.size() == 0) { + // Return early. Otherwise, empty strings will be parsed as 0, which is + // misleading. + return std::nullopt; + } + // Amazingly, C++ has no* string parsing functions that work with strings + // that might not be null-terminated. So we have to copy to a std::string + // (which _is_ guaranteed to be null terminated) before parsing. + // * except std::from_chars, but compiler/library support for the + // floating-point version of that method is spotty at best. + return MetadataConversions::convert( + std::string(from.data(), from.size())); + } +}; +#pragma endregion + +#pragma region Conversions to double +/** + * @brief Converts from a boolean to a double. + */ +template <> struct MetadataConversions { + /** + * @brief Converts a boolean to a double. This returns 1.0 for true, 0.0 for + * false. + * + * @param from The boolean value to be converted. + */ + static std::optional convert(bool from) { return from ? 1.0 : 0.0; } +}; + +/** + * @brief Converts from any integer type to a double. + */ +template +struct MetadataConversions< + double, + TFrom, + std::enable_if_t::value>> { + /** + * @brief Converts any integer type to a double. The value may lose precision + * during conversion. + * + * @param from The boolean value to be converted. + */ + static std::optional convert(TFrom from) { + return static_cast(from); + } +}; + +/** + * @brief Converts from a float to a double. + */ +template <> struct MetadataConversions { + /** + * @brief Converts from a float to a double. + * + * @param from The float value to be converted. + */ + static std::optional convert(float from) { + return static_cast(from); + } +}; + +/** + * @brief Converts from std::string to a double. + */ +template <> struct MetadataConversions { + /** + * Converts a std::string to a double. This assumes that the entire + * std::string represents the number, not just a part of it. + * + * This returns std::nullopt if no number is parsed from the string. + * + * @param from The std::string to parse from. + */ + static std::optional convert(const std::string& from) { + if (from.size() == 0) { + // Return early. Otherwise, empty strings will be parsed as 0, which is + // misleading. + return std::nullopt; + } + + errno = 0; + + char* pLastUsed; + double parsedValue = std::strtod(from.c_str(), &pLastUsed); + if (errno == 0 && pLastUsed == from.c_str() + from.size() && + !std::isinf(parsedValue)) { + // Successfully parsed the entire string as a double. + return parsedValue; + } + return std::nullopt; + } +}; + +/** + * @brief Converts from std::string_view to a double. + */ +template <> struct MetadataConversions { + /** + * Converts a std::string_view to a double. This assumes that the entire + * std::string_view represents the number, not just a part of it. + * + * This returns std::nullopt if no number is parsed from the string. + * + * @param from The std::string_view to parse from. + */ + static std::optional convert(const std::string_view& from) { + if (from.size() == 0) { + // Return early. Otherwise, empty strings will be parsed as 0, which is + // misleading. + return std::nullopt; + } + + // Amazingly, C++ has no* string parsing functions that work with strings + // that might not be null-terminated. So we have to copy to a std::string + // (which _is_ guaranteed to be null terminated) before parsing. + // * except std::from_chars, but compiler/library support for the + // floating-point version of that method is spotty at best. + return MetadataConversions::convert(std::string(from)); + } +}; +#pragma endregion + +#pragma region Conversions to string +/** + * @brief Converts from a boolean to a string. + */ +template <> struct MetadataConversions { + /** + * @brief Converts a boolean to a std::string. Returns "true" for true and + * "false" for false. + * + * @param from The boolean to be converted. + */ + static std::optional convert(bool from) { + return from ? "true" : "false"; + } +}; + +/** + * @brief Converts from a scalar to a string. + */ +template +struct MetadataConversions< + std::string, + TFrom, + std::enable_if_t::value>> { + /** + * @brief Converts a scalar to a std::string. + * + * @param from The scalar to be converted. + */ + static std::optional convert(TFrom from) { + return std::to_string(from); + } +}; + +/** + * @brief Converts from a glm::vecN or glm::matN to a string. + */ +template +struct MetadataConversions< + std::string, + TFrom, + std::enable_if_t< + IsMetadataVecN::value || IsMetadataMatN::value>> { + /** + * @brief Converts a glm::vecN or glm::matN to a std::string. This uses the + * format that glm::to_string() outputs for vecNs or matNs respectively. + * + * @param from The glm::vecN or glm::matN to be converted. + */ + static std::optional convert(const TFrom& from) { + return glm::to_string(from); + } +}; + +/** + * @brief Converts from a std::string_view to a std::string. + */ +template <> struct MetadataConversions { + /** + * @brief Converts from a std::string_view to a std::string. + */ + static std::optional convert(const std::string_view& from) { + return std::string(from.data(), from.size()); + } +}; + +#pragma endregion + +#pragma region Conversions to glm::vecN +/** + * @brief Converts from a boolean to a vecN. + */ +template +struct MetadataConversions< + TTo, + bool, + std::enable_if_t::value>> { + /** + * @brief Converts a boolean to a vecN. The boolean is converted to an integer + * value of 1 for true or 0 for false. The returned vector is initialized with + * this value in both of its components. + * + * @param from The boolean to be converted. + */ + static std::optional convert(bool from) { + return from ? TTo(1) : TTo(0); + } +}; + +/** + * @brief Converts from a scalar type to a vecN. + */ +template +struct MetadataConversions< + TTo, + TFrom, + std::enable_if_t< + CesiumGltf::IsMetadataVecN::value && + CesiumGltf::IsMetadataScalar::value>> { + /** + * @brief Converts a scalar to a vecN. The returned vector is initialized + * with the value in all of its components. The value may lose precision + * during conversion depending on the type of the scalar and the component + * type of the matrix. + * + * If the scalar cannot be reasonably converted to the component type of the + * vecN, std::nullopt is returned. + * + * @param from The scalar value to be converted. + */ + static std::optional convert(TFrom from) { + using ToValueType = typename TTo::value_type; + + std::optional maybeValue = + MetadataConversions::convert(from); + if (maybeValue) { + ToValueType value = *maybeValue; + return TTo(value); + } + + return std::nullopt; + } +}; + +/** + * @brief Converts from a vecN type to another vecN type. + */ +template +struct MetadataConversions< + TTo, + TFrom, + std::enable_if_t< + CesiumGltf::IsMetadataVecN::value && + CesiumGltf::IsMetadataVecN::value && + !std::is_same_v>> { + /** + * @brief Converts a value of the given vecN to another vecN type. + * + * If the given vector has more components than the target vecN type, then + * only its first N components will be used, where N is the dimension of the + * target vecN type. Otherwise, if the target vecN type has more components, + * its extra components will be initialized to zero. + * + * If any of the relevant components cannot be converted to the target vecN + * component type, std::nullopt is returned. + * + * @param from The vecN value to convert from. + */ + static std::optional convert(TFrom from) { + TTo result = TTo(0); + + constexpr glm::length_t validLength = + glm::min(TTo::length(), TFrom::length()); + + using ToValueType = typename TTo::value_type; + using FromValueType = typename TFrom::value_type; + + for (glm::length_t i = 0; i < validLength; i++) { + auto maybeValue = + MetadataConversions::convert(from[i]); + if (!maybeValue) { + return std::nullopt; + } + + result[i] = *maybeValue; + } + + return result; + } +}; +#pragma endregion + +#pragma region Conversions to glm::matN +/** + * @brief Converts from a boolean to a matN. + */ +template +struct MetadataConversions< + TTo, + bool, + std::enable_if_t::value>> { + /** + * @brief Converts a boolean to a matN. The boolean is converted to an integer + * value of 1 for true or 0 for false. The returned matrix is initialized with + * this value in all of its components. + * + * @param from The boolean to be converted. + */ + static std::optional convert(bool from) { + return from ? TTo(1) : TTo(0); + } +}; + +/** + * Converts from a scalar type to a matN. + */ +template +struct MetadataConversions< + TTo, + TFrom, + std::enable_if_t< + CesiumGltf::IsMetadataMatN::value && + CesiumGltf::IsMetadataScalar::value>> { + /** + * Converts a scalar to a matN. The returned vector is initialized + * with the value in all components. The value may lose precision during + * conversion depending on the type of the scalar and the component type of + * the matrix. + * + * If the scalar cannot be reasonably converted to the component type of the + * matN, std::nullopt is returned. + * + * @param from The scalar value to be converted. + */ + static std::optional convert(TFrom from) { + using ToValueType = typename TTo::value_type; + + std::optional maybeValue = + MetadataConversions::convert(from); + if (!maybeValue) { + return std::nullopt; + } + + ToValueType value = *maybeValue; + return TTo(value); + } +}; + +/** + * @brief Converts from a matN type to another matN type. + */ +template +struct MetadataConversions< + TTo, + TFrom, + std::enable_if_t< + CesiumGltf::IsMetadataMatN::value && + CesiumGltf::IsMetadataMatN::value && + !std::is_same_v>> { + /** + * @brief Converts a value of the given matN to another matN type. + * + * Let M be the length of the given matN, and N be the length of the target + * matN. If M > N, then only the first N components of the first N columns + * will be used. Otherwise, if M < N, all other elements in the N x N matrix + * will be initialized to zero. + * + * If any of the relevant components cannot be converted to the target matN + * component type, std::nullopt is returned. + * + * @param from The matN value to convert from. + */ + static std::optional convert(TFrom from) { + TTo result = TTo(0); + + constexpr glm::length_t validLength = + glm::min(TTo::length(), TFrom::length()); + + using ToValueType = typename TTo::value_type; + using FromValueType = typename TFrom::value_type; + + for (glm::length_t c = 0; c < validLength; c++) { + for (glm::length_t r = 0; r < validLength; r++) { + auto maybeValue = + MetadataConversions::convert( + from[c][r]); + if (!maybeValue) { + return std::nullopt; + } + + result[c][r] = *maybeValue; + } + } + + return result; + } +}; +#pragma endregion + +} // namespace CesiumGltf + +#ifdef GLM_ENABLE_EXPERIMENTAL_defined_locally +#undef GLM_ENABLE_EXPERIMENTAL +#undef GLM_ENABLE_EXPERIMENTAL_defined_locally +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Model.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Model.h new file mode 100644 index 0000000..6253416 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Model.h @@ -0,0 +1,287 @@ +#pragma once + +#include +#include +#include + +#include + +#include + +namespace CesiumGltf { + +/** @copydoc ModelSpec */ +struct CESIUMGLTF_API Model : public ModelSpec { + Model() = default; + + /** + * @brief Merges another model into this one. + * + * After this method returns, this `Model` contains all of the + * elements that were originally in it _plus_ all of the elements + * that were in `rhs`. Element indices are updated accordingly. + * However, element indices in {@link CesiumUtility::ExtensibleObject::extras}, if any, + * are _not_ updated. + * + * @param rhs The model to merge into this one. + */ + CesiumUtility::ErrorList merge(Model&& rhs); + + /** + * @brief A callback function for {@link forEachRootNodeInScene}. + */ + typedef void ForEachRootNodeInSceneCallback(Model& gltf, Node& node); + + /** + * @brief A callback function for {@link forEachRootNodeInScene}. + */ + typedef void + ForEachRootNodeInSceneConstCallback(const Model& gltf, const Node& node); + + /** + * @brief Apply the given callback to the root nodes of the scene. + * + * If the given `sceneID` is non-negative and exists in the given glTF, + * then the given callback will be applied to all root nodes of this scene. + * + * If the given `sceneId` is negative, then the nodes that the callback + * will be applied to depends on the structure of the glTF model: + * + * * If the glTF model has a default scene, then it will + * be applied to all root nodes of the default scene. + * * Otherwise, it will be applied to all root nodes of the first scene. + * * Otherwise (if the glTF model does not contain any scenes), it will + * be applied to the first node. + * * Otherwise (if there are no scenes and no nodes), then this method will do + * nothing. + * + * @param sceneID The scene ID (index) + * @param callback The callback to apply + */ + void forEachRootNodeInScene( + int32_t sceneID, + std::function&& callback); + + /** @copydoc Model::forEachRootNodeInScene */ + void forEachRootNodeInScene( + int32_t sceneID, + std::function&& callback) const; + + /** + * @brief A callback function for {@link forEachNodeInScene}. + */ + typedef void ForEachNodeInSceneCallback( + Model& gltf, + Node& node, + const glm::dmat4& transform); + + /** + * @brief Apply the given callback to all nodes in the scene. + * + * If the given `sceneID` is non-negative and exists in the given glTF, + * then the given callback will be applied to all nodes in this scene. + * + * If the given `sceneId` is negative, then the nodes that the callback + * will be applied to depends on the structure of the glTF model: + * + * * If the glTF model has a default scene, then it will + * be applied to all nodes in the default scene. + * * Otherwise, it will be applied to all nodes in the first scene. + * * Otherwise (if the glTF model does not contain any scenes), it will + * be applied to the first node. + * * Otherwise (if there are no scenes and no nodes), then this method will do + * nothing. + * + * @param sceneID The scene ID (index) + * @param callback The callback to apply + */ + void forEachNodeInScene( + int32_t sceneID, + std::function&& callback); + + /** + * @brief A callback function for {@link forEachNodeInScene}. + */ + typedef void ForEachNodeInSceneConstCallback( + const Model& gltf, + const Node& node, + const glm::dmat4& transform); + + /** @copydoc Model::forEachNodeInScene */ + void forEachNodeInScene( + int32_t sceneID, + std::function&& callback) const; + + /** + * @brief A callback function for {@link forEachPrimitiveInScene}. + */ + typedef void ForEachPrimitiveInSceneCallback( + Model& gltf, + Node& node, + Mesh& mesh, + MeshPrimitive& primitive, + const glm::dmat4& transform); + + /** + * @brief Apply the given callback to all relevant primitives. + * + * If the given `sceneID` is non-negative and exists in the given glTF, + * then the given callback will be applied to all meshes of this scene. + * + * If the given `sceneId` is negative, then the meshes that the callback + * will be applied to depends on the structure of the glTF model: + * + * * If the glTF model has a default scene, then it will + * be applied to all meshes of the default scene. + * * Otherwise, it will be applied to all meshes of the the first scene. + * * Otherwise (if the glTF model does not contain any scenes), it will + * be applied to all meshes that can be found by starting a traversal + * at the root node. + * * Otherwise (if there are no scenes and no nodes), then all meshes + * will be traversed. + * + * @param sceneID The scene ID (index) + * @param callback The callback to apply + */ + void forEachPrimitiveInScene( + int32_t sceneID, + std::function&& callback); + + /** + * @brief A callback function for {@link forEachPrimitiveInScene}. + */ + typedef void ForEachPrimitiveInSceneConstCallback( + const Model& gltf, + const Node& node, + const Mesh& mesh, + const MeshPrimitive& primitive, + const glm::dmat4& transform); + + /** @copydoc Model::forEachPrimitiveInScene */ + void forEachPrimitiveInScene( + int32_t sceneID, + std::function&& callback) const; + + /** + * @brief Fills in smooth normals for any primitives with missing normals. + */ + void generateMissingNormalsSmooth(); + + /** + * @brief Safely gets the element with a given index, returning a default + * instance if the index is outside the range. + * + * @tparam T The type of the array. + * @param items The array. + * @param index The index of the array element to retrieve. + * @return The requested element, or a default instance if the index is + * invalid. + */ + template + static const T& getSafe(const std::vector& items, int32_t index) { + static T defaultObject; + if (index < 0 || size_t(index) >= items.size()) { + return defaultObject; + } else { + return items[size_t(index)]; + } + } + + /** + * @brief Safely gets a pointer to the element with a given index, returning + * `nullptr` if the index is outside the range. + * + * @tparam T The type of the array. + * @param pItems The array. + * @param index The index of the array element to retrieve. + * @return A pointer to the requested element, or `nullptr` if the index is + * invalid. + */ + template + static const T* + getSafe(const std::vector* pItems, int32_t index) noexcept { + if (index < 0 || size_t(index) >= pItems->size()) { + return nullptr; + } else { + return &(*pItems)[size_t(index)]; + } + } + + /** + * @brief Safely gets a pointer to the element with a given index, returning + * `nullptr` if the index is outside the range. + * + * @tparam T The type of the array. + * @param pItems The array. + * @param index The index of the array element to retrieve. + * @return A pointer to the requested element, or `nullptr` if the index is + * invalid. + */ + template + static T* getSafe(std::vector* pItems, int32_t index) noexcept { + if (index < 0 || size_t(index) >= pItems->size()) { + return nullptr; + } else { + return &(*pItems)[size_t(index)]; + } + } + + /** + * @brief Adds an extension to the {@link ModelSpec::extensionsUsed} + * property, if it is not already present. + * + * @param extensionName The name of the used extension. + */ + void addExtensionUsed(const std::string& extensionName); + + /** + * @brief Adds an extension to the {@link ModelSpec::extensionsRequired} + * property, if it is not already present. + * + * Calling this function also adds the extension to `extensionsUsed`, if it's + * not already present. + * + * @param extensionName The name of the required extension. + */ + void addExtensionRequired(const std::string& extensionName); + + /** + * @brief Removes an extension from the {@link ModelSpec::extensionsUsed} + * property. + * + * @param extensionName The name of the used extension. + */ + void removeExtensionUsed(const std::string& extensionName); + + /** + * @brief Removes an extension from the {@link ModelSpec::extensionsRequired} + * property. + * + * Calling this function also removes the extension from `extensionsUsed`. + * + * @param extensionName The name of the required extension. + */ + void removeExtensionRequired(const std::string& extensionName); + + /** + * @brief Determines whether a given extension name is listed in the model's + * {@link ModelSpec::extensionsUsed} property. + * + * @param extensionName The extension name to check. + * @returns True if the extension is found in `extensionsUsed`; otherwise, + * false. + */ + bool isExtensionUsed(const std::string& extensionName) const noexcept; + + /** + * @brief Determines whether a given extension name is listed in the model's + * {@link ModelSpec::extensionsRequired} property. + * + * @param extensionName The extension name to check. + * @returns True if the extension is found in `extensionsRequired`; otherwise, + * false. + */ + bool isExtensionRequired(const std::string& extensionName) const noexcept; +}; + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ModelSpec.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ModelSpec.h new file mode 100644 index 0000000..86ec085 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ModelSpec.h @@ -0,0 +1,220 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief The root object for a glTF asset. + */ +struct CESIUMGLTF_API ModelSpec : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Model"; + + /** + * @brief Names of glTF extensions used in this asset. + */ + std::vector extensionsUsed; + + /** + * @brief Names of glTF extensions required to properly load this asset. + */ + std::vector extensionsRequired; + + /** + * @brief An array of accessors. + * + * An accessor is a typed view into a bufferView. + */ + std::vector accessors; + + /** + * @brief An array of keyframe animations. + */ + std::vector animations; + + /** + * @brief Metadata about the glTF asset. + */ + CesiumGltf::Asset asset; + + /** + * @brief An array of buffers. + * + * A buffer points to binary geometry, animation, or skins. + */ + std::vector buffers; + + /** + * @brief An array of bufferViews. + * + * A bufferView is a view into a buffer generally representing a subset of the + * buffer. + */ + std::vector bufferViews; + + /** + * @brief An array of cameras. + * + * A camera defines a projection matrix. + */ + std::vector cameras; + + /** + * @brief An array of images. + * + * An image defines data used to create a texture. + */ + std::vector images; + + /** + * @brief An array of materials. + * + * A material defines the appearance of a primitive. + */ + std::vector materials; + + /** + * @brief An array of meshes. + * + * A mesh is a set of primitives to be rendered. + */ + std::vector meshes; + + /** + * @brief An array of nodes. + */ + std::vector nodes; + + /** + * @brief An array of samplers. + * + * A sampler contains properties for texture filtering and wrapping modes. + */ + std::vector samplers; + + /** + * @brief The index of the default scene. + * + * This property **MUST NOT** be defined, when `scenes` is undefined. + */ + int32_t scene = -1; + + /** + * @brief An array of scenes. + */ + std::vector scenes; + + /** + * @brief An array of skins. + * + * A skin is defined by joints and matrices. + */ + std::vector skins; + + /** + * @brief An array of textures. + */ + std::vector textures; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ModelSpec)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(sizeof(std::string) * this->extensionsUsed.capacity()); + accum += int64_t(sizeof(std::string) * this->extensionsRequired.capacity()); + accum += int64_t(sizeof(CesiumGltf::Accessor) * this->accessors.capacity()); + for (const CesiumGltf::Accessor& value : this->accessors) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Accessor)); + } + accum += + int64_t(sizeof(CesiumGltf::Animation) * this->animations.capacity()); + for (const CesiumGltf::Animation& value : this->animations) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Animation)); + } + accum += this->asset.getSizeBytes() - int64_t(sizeof(CesiumGltf::Asset)); + accum += int64_t(sizeof(CesiumGltf::Buffer) * this->buffers.capacity()); + for (const CesiumGltf::Buffer& value : this->buffers) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Buffer)); + } + accum += + int64_t(sizeof(CesiumGltf::BufferView) * this->bufferViews.capacity()); + for (const CesiumGltf::BufferView& value : this->bufferViews) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::BufferView)); + } + accum += int64_t(sizeof(CesiumGltf::Camera) * this->cameras.capacity()); + for (const CesiumGltf::Camera& value : this->cameras) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Camera)); + } + accum += int64_t(sizeof(CesiumGltf::Image) * this->images.capacity()); + for (const CesiumGltf::Image& value : this->images) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Image)); + } + accum += int64_t(sizeof(CesiumGltf::Material) * this->materials.capacity()); + for (const CesiumGltf::Material& value : this->materials) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Material)); + } + accum += int64_t(sizeof(CesiumGltf::Mesh) * this->meshes.capacity()); + for (const CesiumGltf::Mesh& value : this->meshes) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Mesh)); + } + accum += int64_t(sizeof(CesiumGltf::Node) * this->nodes.capacity()); + for (const CesiumGltf::Node& value : this->nodes) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Node)); + } + accum += int64_t(sizeof(CesiumGltf::Sampler) * this->samplers.capacity()); + for (const CesiumGltf::Sampler& value : this->samplers) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Sampler)); + } + accum += int64_t(sizeof(CesiumGltf::Scene) * this->scenes.capacity()); + for (const CesiumGltf::Scene& value : this->scenes) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Scene)); + } + accum += int64_t(sizeof(CesiumGltf::Skin) * this->skins.capacity()); + for (const CesiumGltf::Skin& value : this->skins) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Skin)); + } + accum += int64_t(sizeof(CesiumGltf::Texture) * this->textures.capacity()); + for (const CesiumGltf::Texture& value : this->textures) { + accum += value.getSizeBytes() - int64_t(sizeof(CesiumGltf::Texture)); + } + return accum; + } + +protected: + /** + * @brief This class is not meant to be instantiated directly. Use {@link Model} instead. + */ + ModelSpec() = default; + friend struct Model; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/NamedObject.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/NamedObject.h new file mode 100644 index 0000000..fcb41a8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/NamedObject.h @@ -0,0 +1,38 @@ +#pragma once + +#include "CesiumGltf/Library.h" + +#include + +#include + +namespace CesiumGltf { +/** + * @brief The base class for objects in a glTF that have a name. + * + * A named object is also an {@link CesiumUtility::ExtensibleObject}. + */ +struct CESIUMGLTF_API NamedObject : public CesiumUtility::ExtensibleObject { + /** + * @brief The user-defined name of this object. + * + * This is not necessarily unique, e.g., an accessor and a buffer could have + * the same name, or two accessors could even have the same name. + */ + std::string name; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += sizeof(NamedObject); + accum += + ExtensibleObject::getSizeBytes() - int64_t(sizeof(ExtensibleObject)); + accum += this->name.capacity() * sizeof(char); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Node.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Node.h new file mode 100644 index 0000000..bb88f70 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Node.h @@ -0,0 +1,103 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief A node in the node hierarchy. When the node contains `skin`, all + * `mesh.primitives` **MUST** contain `JOINTS_0` and `WEIGHTS_0` attributes. A + * node **MAY** have either a `matrix` or any combination of + * `translation`/`rotation`/`scale` (TRS) properties. TRS properties are + * converted to matrices and postmultiplied in the `T * R * S` order to compose + * the transformation matrix; first the scale is applied to the vertices, then + * the rotation, and then the translation. If none are provided, the transform + * is the identity. When a node is targeted for animation (referenced by an + * animation.channel.target), `matrix` **MUST NOT** be present. + */ +struct CESIUMGLTF_API Node final : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Node"; + + /** + * @brief The index of the camera referenced by this node. + */ + int32_t camera = -1; + + /** + * @brief The indices of this node's children. + */ + std::vector children; + + /** + * @brief The index of the skin referenced by this node. + * + * When a skin is referenced by a node within a scene, all joints used by the + * skin **MUST** belong to the same scene. When defined, `mesh` **MUST** also + * be defined. + */ + int32_t skin = -1; + + /** + * @brief A floating-point 4x4 transformation matrix stored in column-major + * order. + */ + std::vector matrix = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; + + /** + * @brief The index of the mesh in this node. + */ + int32_t mesh = -1; + + /** + * @brief The node's unit quaternion rotation in the order (x, y, z, w), where + * w is the scalar. + */ + std::vector rotation = {0, 0, 0, 1}; + + /** + * @brief The node's non-uniform scale, given as the scaling factors along the + * x, y, and z axes. + */ + std::vector scale = {1, 1, 1}; + + /** + * @brief The node's translation along the x, y, and z axes. + */ + std::vector translation = {0, 0, 0}; + + /** + * @brief The weights of the instantiated morph target. The number of array + * elements **MUST** match the number of morph targets of the referenced mesh. + * When defined, `mesh` **MUST** also be defined. + */ + std::vector weights; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Node)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + accum += int64_t(sizeof(int32_t) * this->children.capacity()); + accum += int64_t(sizeof(double) * this->matrix.capacity()); + accum += int64_t(sizeof(double) * this->rotation.capacity()); + accum += int64_t(sizeof(double) * this->scale.capacity()); + accum += int64_t(sizeof(double) * this->translation.capacity()); + accum += int64_t(sizeof(double) * this->weights.capacity()); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyArrayView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyArrayView.h new file mode 100644 index 0000000..fcfb8e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyArrayView.h @@ -0,0 +1,370 @@ +#pragma once + +#include "CesiumGltf/PropertyType.h" +#include "getOffsetFromOffsetsBuffer.h" + +#include + +#include +#include +#include +#include +#include + +namespace CesiumGltf { + +/** + * @brief A view on an array element of a {@link PropertyTableProperty} + * or {@link PropertyTextureProperty}. + * + * Provides utility to retrieve the data stored in the array of + * elements via the array index operator. + */ +template class PropertyArrayView { +public: + /** + * @brief Constructs an empty array view. + */ + PropertyArrayView() : _values{} {} + + /** + * @brief Constructs an array view from a buffer. + * + * @param buffer The buffer containing the values. + */ + PropertyArrayView(const std::span& buffer) noexcept + : _values{CesiumUtility::reintepretCastSpan(buffer)} {} + + /** + * @brief Accesses the element of this array at the given index. + */ + const ElementType& operator[](int64_t index) const noexcept { + return this->_values[index]; + } + + /** + * @brief The number of elements in this array. + */ + int64_t size() const noexcept { return this->_values.size(); } + + /** + * @brief The `begin` iterator. + */ + auto begin() { return this->_values.begin(); } + /** + * @brief The `end` iterator. + */ + auto end() { return this->_values.end(); } + /** @copydoc begin */ + auto begin() const { return this->_values.begin(); } + /** @copydoc end */ + auto end() const { return this->_values.end(); } + +private: + std::span _values; +}; + +/** + * @brief A copy of an array element of a {@link PropertyTableProperty} or + * {@link PropertyTextureProperty}. + * + * Whereas {@link PropertyArrayView} is a pointer to data stored in a separate + * place, a PropertyArrayCopy owns the data that it's viewing. + * + * Provides utility to retrieve the data stored in the array of elements via the + * array index operator. + */ +template class PropertyArrayCopy { +public: + /** + * @brief Constructs an empty array view. + */ + PropertyArrayCopy() : _storage{}, _view() {} + + /** + * @brief Constructs an array view from a buffer. + * + * @param values The buffer containing the values. + */ + PropertyArrayCopy(const std::vector& values) noexcept + : _storage(), _view() { + size_t numberOfElements = values.size(); + size_t sizeInBytes = numberOfElements * sizeof(ElementType); + this->_storage.resize(sizeInBytes); + std::memcpy( + this->_storage.data(), + reinterpret_cast(values.data()), + sizeInBytes); + this->_view = PropertyArrayView(this->_storage); + } + + /** @brief Default move constructor */ + PropertyArrayCopy(PropertyArrayCopy&&) = default; + /** @brief Default move assignment operator */ + PropertyArrayCopy& operator=(PropertyArrayCopy&&) = default; + + /** @brief Creates a new \ref PropertyArrayCopy directly from a buffer of + * bytes, which will be moved into this copy. */ + PropertyArrayCopy(std::vector&& buffer) noexcept + : _storage(std::move(buffer)), _view(this->_storage) {} + + /** @brief Copy constructor */ + PropertyArrayCopy(const PropertyArrayCopy& rhs) + : _storage(rhs._storage), _view(this->_storage) {} + + /** @brief Copy assignment operator */ + PropertyArrayCopy& operator=(const PropertyArrayCopy& rhs) { + this->_storage = rhs._storage; + this->_view = PropertyArrayView(this->_storage); + return *this; + } + + /** + * @brief Returns the `ElementType` at the given index from this copy. + * + * @param index The index to obtain. + * @returns The `ElementType` at that index from the internal view. + */ + const ElementType& operator[](int64_t index) const noexcept { + return this->_view[index]; + } + + /** @copydoc PropertyArrayView::size */ + int64_t size() const noexcept { return this->_view.size(); } + + /** @copydoc PropertyArrayView::begin */ + auto begin() { return this->_view.begin(); } + /** @copydoc PropertyArrayView::end */ + auto end() { return this->_view.end(); } + /** @copydoc PropertyArrayView::begin */ + auto begin() const { return this->_view.begin(); } + /** @copydoc PropertyArrayView::end */ + auto end() const { return this->_view.end(); } + + /** + * @brief Obtains a \ref PropertyArrayView over the contents of this copy. + */ + const PropertyArrayView& view() const { return this->_view; } + + /** + * @brief Obtains a buffer and view from the copied data, leaving this \ref + * PropertyArrayCopy empty. + * + * @param outBuffer The destination where this copy's internal buffer will be + * moved to. + */ + PropertyArrayView + toViewAndExternalBuffer(std::vector& outBuffer) && { + outBuffer = std::move(this->_storage); + PropertyArrayView result = std::move(this->_view); + this->_view = PropertyArrayView(); + return result; + } + +private: + std::vector _storage; + PropertyArrayView _view; +}; + +/** + * @brief A view on a bool array element of a {@link PropertyTableProperty} + * or {@link PropertyTextureProperty}. + * + * Provides utility to retrieve the data stored in the array of + * elements via the array index operator. + */ +template <> class PropertyArrayView { +public: + /** + * @brief Constructs an empty array view. + */ + PropertyArrayView() : _values{}, _bitOffset{0}, _size{0} {} + + /** + * @brief Constructs an array view from a buffer. + * + * @param buffer The buffer containing the values. + * @param bitOffset The offset into the buffer where the values actually + * begin. + * @param size The number of values in the array. + */ + PropertyArrayView( + const std::span& buffer, + int64_t bitOffset, + int64_t size) noexcept + : _values{buffer}, _bitOffset{bitOffset}, _size{size} {} + + /** + * @brief Obtains the element in the array at the given index. + */ + bool operator[](int64_t index) const noexcept { + index += _bitOffset; + const int64_t byteIndex = index / 8; + const int64_t bitIndex = index % 8; + const int bitValue = static_cast(_values[byteIndex] >> bitIndex) & 1; + return bitValue == 1; + } + + /** + * @brief The number of entries in the array. + */ + int64_t size() const noexcept { return _size; } + +private: + std::span _values; + int64_t _bitOffset; + int64_t _size; +}; + +/** + * @brief A view on a string array element of a {@link PropertyTableProperty} + * or {@link PropertyTextureProperty}. + * + * Provides utility to retrieve the data stored in the array of + * elements via the array index operator. + */ +template <> class PropertyArrayView { +public: + /** + * @brief Constructs an empty array view. + */ + PropertyArrayView() + : _values{}, + _stringOffsets{}, + _stringOffsetType{PropertyComponentType::None}, + _size{0} {} + + /** + * @brief Constructs an array view from buffers and their information. + * + * @param values The buffer containing the values. + * @param stringOffsets The buffer containing the string offsets. + * @param stringOffsetType The component type of the string offsets. + * @param size The number of values in the array. + */ + PropertyArrayView( + const std::span& values, + const std::span& stringOffsets, + PropertyComponentType stringOffsetType, + int64_t size) noexcept + : _values{values}, + _stringOffsets{stringOffsets}, + _stringOffsetType{stringOffsetType}, + _size{size} {} + + /** + * @brief Obtains an `std::string_view` for the element at the given index. + */ + std::string_view operator[](int64_t index) const noexcept { + const size_t currentOffset = + getOffsetFromOffsetsBuffer(index, _stringOffsets, _stringOffsetType); + const size_t nextOffset = getOffsetFromOffsetsBuffer( + index + 1, + _stringOffsets, + _stringOffsetType); + return std::string_view( + reinterpret_cast(_values.data() + currentOffset), + (nextOffset - currentOffset)); + } + + /** + * @brief The number of elements in this array. + */ + int64_t size() const noexcept { return _size; } + +private: + std::span _values; + std::span _stringOffsets; + PropertyComponentType _stringOffsetType; + int64_t _size; +}; + +/** @brief Compares two \ref PropertyArrayView instances by comparing their + * values. If the two arrays aren't the same size, this comparison will return + * false. */ +template +bool operator==( + const PropertyArrayView& lhs, + const PropertyArrayView& rhs) { + int64_t size = lhs.size(); + if (size != rhs.size()) { + return false; + } + + for (int64_t i = 0; i < size; ++i) { + if (lhs[i] != rhs[i]) { + return false; + } + } + + return true; +} + +/** @brief Compares a \ref PropertyArrayView with a \ref + * PropertyArrayCopy by creating a view from the copy and comparing the two. */ +template +bool operator==( + const PropertyArrayView& lhs, + const PropertyArrayCopy& rhs) { + return lhs == PropertyArrayView(rhs); +} + +/** @brief Compares a \ref PropertyArrayView with a \ref + * PropertyArrayCopy by creating a view from the copy and comparing the two. */ +template +bool operator==( + const PropertyArrayCopy& lhs, + const PropertyArrayView& rhs) { + return lhs.view() == rhs; +} + +/** @brief Compares two \ref PropertyArrayCopy instances by creating + * views from each instance and comparing the two. */ +template +bool operator==( + const PropertyArrayCopy& lhs, + const PropertyArrayCopy& rhs) { + return lhs.view() == rhs.view(); +} + +/** + * @brief Compares two \ref PropertyArrayView instances and returns the inverse. + */ +template +bool operator!=( + const PropertyArrayView& lhs, + const PropertyArrayView& rhs) { + return !(lhs == rhs); +} + +/** @brief Compares a \ref PropertyArrayView with a \ref + * PropertyArrayCopy by creating a view from the copy and returning the inverse + * of comparing the two. */ +template +bool operator!=( + const PropertyArrayView& lhs, + const PropertyArrayCopy& rhs) { + return !(lhs == rhs); +} + +/** @brief Compares a \ref PropertyArrayView with a \ref + * PropertyArrayCopy by creating a view from the copy and returning the inverse + * of comparing the two. */ +template +bool operator!=( + const PropertyArrayCopy& lhs, + const PropertyArrayView& rhs) { + return !(lhs == rhs); +} + +/** @brief Compares two \ref + * PropertyArrayCopy instances by creating views from both instances and + * returning the inverse of comparing the two. */ +template +bool operator!=( + const PropertyArrayCopy& lhs, + const PropertyArrayCopy& rhs) { + return !(lhs == rhs); +} + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyAttribute.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyAttribute.h new file mode 100644 index 0000000..29774f7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyAttribute.h @@ -0,0 +1,71 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief Properties conforming to a class, organized as property values stored + * in attributes. + */ +struct CESIUMGLTF_API PropertyAttribute final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "PropertyAttribute"; + + /** + * @brief The name of the property attribute, e.g. for display purposes. + */ + std::optional name; + + /** + * @brief The class that property values conform to. The value must be a class + * ID declared in the `classes` dictionary. + */ + std::string classProperty; + + /** + * @brief A dictionary, where each key corresponds to a property ID in the + * class' `properties` dictionary and each value is an object describing where + * property values are stored. Required properties must be included in this + * dictionary. + */ + std::unordered_map + properties; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(PropertyAttribute)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + accum += int64_t(this->classProperty.capacity() * sizeof(char)); + accum += int64_t( + this->properties.bucket_count() * + (sizeof(std::string) + sizeof(CesiumGltf::PropertyAttributeProperty))); + for (const auto& [k, v] : this->properties) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - + int64_t(sizeof(CesiumGltf::PropertyAttributeProperty)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyAttributeProperty.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyAttributeProperty.h new file mode 100644 index 0000000..0884da0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyAttributeProperty.h @@ -0,0 +1,73 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief An attribute containing property values. + */ +struct CESIUMGLTF_API PropertyAttributeProperty final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "PropertyAttributeProperty"; + + /** + * @brief The name of the attribute containing property values. + */ + std::string attribute; + + /** + * @brief An offset to apply to property values. Only applicable when the + * component type is `FLOAT32` or `FLOAT64`, or when the property is + * `normalized`. Overrides the class property's `offset` if both are defined. + */ + std::optional offset; + + /** + * @brief A scale to apply to property values. Only applicable when the + * component type is `FLOAT32` or `FLOAT64`, or when the property is + * `normalized`. Overrides the class property's `scale` if both are defined. + */ + std::optional scale; + + /** + * @brief Maximum value present in the property values. Only applicable to + * `SCALAR`, `VECN`, and `MATN` types. This is the maximum of all property + * values, after the transforms based on the `normalized`, `offset`, and + * `scale` properties have been applied. + */ + std::optional max; + + /** + * @brief Minimum value present in the property values. Only applicable to + * `SCALAR`, `VECN`, and `MATN` types. This is the minimum of all property + * values, after the transforms based on the `normalized`, `offset`, and + * `scale` properties have been applied. + */ + std::optional min; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(PropertyAttributeProperty)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(this->attribute.capacity() * sizeof(char)); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyAttributePropertyView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyAttributePropertyView.h new file mode 100644 index 0000000..a30b38c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyAttributePropertyView.h @@ -0,0 +1,440 @@ +#pragma once + +#include "CesiumGltf/AccessorView.h" +#include "CesiumGltf/PropertyAttributeProperty.h" +#include "CesiumGltf/PropertyTransformations.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumGltf/PropertyView.h" + +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief Indicates the status of a property attribute property view. + * + * The {@link PropertyAttributePropertyView} constructor always completes + * successfully. However it may not always reflect the actual content of the + * corresponding property attribute property. This enumeration provides the + * reason. + */ +class PropertyAttributePropertyViewStatus : public PropertyViewStatus { +public: + /** + * @brief This property view was initialized from an invalid + * {@link PropertyAttribute}. + */ + static const int ErrorInvalidPropertyAttribute = 14; + + /** + * @brief This property view is associated with a {@link ClassProperty} of an + * unsupported type. + */ + static const int ErrorUnsupportedProperty = 15; + + /** + * @brief This property view was initialized with a primitive that does not + * contain the specified attribute. + */ + static const int ErrorMissingAttribute = 16; + + /** + * @brief This property view's attribute does not have a valid accessor index. + */ + static const int ErrorInvalidAccessor = 17; + + /** + * @brief This property view's type does not match the type of the accessor it + * uses. + */ + static const int ErrorAccessorTypeMismatch = 18; + + /** + * @brief This property view's component type does not match the type of the + * accessor it uses. + */ + static const int ErrorAccessorComponentTypeMismatch = 19; + + /** + * @brief This property view's normalization does not match the normalization + * of the accessor it uses. + */ + static const int ErrorAccessorNormalizationMismatch = 20; + + /** + * @brief This property view uses an accessor that does not have a valid + * buffer view index. + */ + static const int ErrorInvalidBufferView = 21; + + /** + * @brief This property view uses a buffer view that does not have a valid + * buffer index. + */ + static const int ErrorInvalidBuffer = 22; + + /** + * @brief This property view uses an accessor that points outside the bounds + * of its target buffer view. + */ + static const PropertyViewStatusType ErrorAccessorOutOfBounds = 23; + + /** + * @brief This property view uses a buffer view that points outside the bounds + * of its target buffer. + */ + static const PropertyViewStatusType ErrorBufferViewOutOfBounds = 24; +}; + +/** + * @brief A view of the data specified by a {@link PropertyAttributeProperty}. + * + * Ideally, property attribute properties can be initialized as vertex + * attributes in the target rendering context. However, some runtime engines do + * not allow custom vertex attributes. To compensate, this view can be used to + * sample the property attributes property via vertex index. + * + * @tparam ElementType The type of the elements represented in the property view + * @tparam Normalized Whether or not the property is normalized. If normalized, + * the elements can be retrieved as normalized floating-point numbers, as + * opposed to their integer values. + */ +template +class PropertyAttributePropertyView; + +/** + * @brief A view of the non-normalized data specified by a + * {@link PropertyAttributeProperty}. + * + * Ideally, property attribute properties can be initialized as vertex + * attributes in the target rendering context. However, some runtime engines do + * not allow custom vertex attributes. This view can be used instead to sample + * the property attributes property via vertex index. + * + * @tparam ElementType The type of the elements represented in the property view + */ +template +class PropertyAttributePropertyView + : public PropertyView { +public: + /** + * @brief Constructs an invalid instance for a non-existent property. + */ + PropertyAttributePropertyView() noexcept + : PropertyView(), _accessor{}, _size{0} {} + + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The code from {@link PropertyAttributePropertyViewStatus} indicating the error with the property. + */ + PropertyAttributePropertyView(PropertyViewStatusType status) noexcept + : PropertyView(status), _accessor{}, _size{0} { + CESIUM_ASSERT( + this->_status != PropertyAttributePropertyViewStatus::Valid && + "An empty property view should not be constructed with a valid status"); + } + + /** + * @brief Constructs an instance of an empty property that specifies a default + * value. Although this property has no data, it can return the default value + * when {@link PropertyAttributePropertyView::get} is called. However, + * {@link PropertyAttributePropertyView::getRaw} cannot be used. + * + * @param classProperty The {@link ClassProperty} this property conforms to. + * @param size The number of elements in the primitive's POSITION accessor. + * Used as a substitute since no actual accessor is defined. + */ + PropertyAttributePropertyView( + const ClassProperty& classProperty, + int64_t size) noexcept + : PropertyView(classProperty), _accessor{}, _size{0} { + if (this->_status != PropertyAttributePropertyViewStatus::Valid) { + // Don't override the status / size if something is wrong with the class + // property's definition. + return; + } + + if (!classProperty.defaultProperty) { + // This constructor should only be called if the class property *has* a + // default value. But in the case that it does not, this property view + // becomes invalid. + this->_status = + PropertyAttributePropertyViewStatus::ErrorNonexistentProperty; + return; + } + + this->_status = + PropertyAttributePropertyViewStatus::EmptyPropertyWithDefault; + this->_size = size; + } + + /** + * @brief Construct a view of the data specified by a {@link PropertyAttributeProperty}. + * + * @param property The {@link PropertyAttributeProperty} + * @param classProperty The {@link ClassProperty} this property conforms to. + * @param accessorView The {@link AccessorView} for the data that this property is + * associated with. + */ + PropertyAttributePropertyView( + const PropertyAttributeProperty& property, + const ClassProperty& classProperty, + const AccessorView& accessorView) noexcept + : PropertyView(classProperty, property), + _accessor{accessorView}, + _size{ + this->_status == PropertyAttributePropertyViewStatus::Valid + ? accessorView.size() + : 0} {} + + /** + * @brief Gets the value of the property for the given vertex index + * with all value transforms applied. That is, if the property specifies an + * offset and scale, they will be applied to the value before the value is + * returned. + * + * If this property has a specified "no data" value, this will return the + * property's default value for any elements that equal this "no data" value. + * If the property did not specify a default value, this returns std::nullopt. + * + * @param index The vertex index. + * + * @return The value of the property for the given vertex, or std::nullopt if + * it matches the "no data" value + */ + std::optional get(int64_t index) const noexcept { + if (this->_status == + PropertyAttributePropertyViewStatus::EmptyPropertyWithDefault) { + return this->defaultValue(); + } + + ElementType value = getRaw(index); + + if (value == this->noData()) { + return this->defaultValue(); + } + + return transformValue(value, this->offset(), this->scale()); + } + + /** + * @brief Gets the raw value of the property for the given vertex index. + * + * If this property has a specified "no data" value, the raw value will still + * be returned, even if it equals the "no data" value. + * + * @param index The vertex index. + * + * @return The value of the property for the given vertex. + */ + ElementType getRaw(int64_t index) const noexcept { + CESIUM_ASSERT( + this->_status == PropertyAttributePropertyViewStatus::Valid && + "Check the status() first to make sure view is valid"); + CESIUM_ASSERT( + size() > 0 && + "Check the size() of the view to make sure it's not empty"); + CESIUM_ASSERT(index >= 0 && "index must be non-negative"); + CESIUM_ASSERT(index < size() && "index must be less than size"); + + return _accessor[index]; + } + + /** + * @brief Get the number of elements in this PropertyAttributePropertyView. + * If the view is valid, this returns the count of the elements in the + * attribute's accessor. Otherwise, this returns 0. + * + * @return The number of elements in this PropertyAttributePropertyView. + */ + int64_t size() const noexcept { return _size; } + +private: + AccessorView _accessor; + int64_t _size; +}; + +/** + * @brief A view of the normalized data specified by a + * {@link PropertyAttributeProperty}. + * + * Ideally, property attribute properties can be initialized as vertex + * attributes in the target rendering context. However, some runtime engines do + * not allow custom vertex attributes. This view can be used instead to sample + * the property attributes property via vertex index. + * + * @tparam ElementType The type of the elements represented in the property view + */ +template +class PropertyAttributePropertyView + : public PropertyView { +private: + using NormalizedType = typename TypeToNormalizedType::type; + +public: + /** + * @brief Constructs an invalid instance for a non-existent property. + */ + PropertyAttributePropertyView() noexcept + : PropertyView(), _accessor{}, _size{0} {} + + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The code from {@link PropertyAttributePropertyViewStatus} indicating the error with the property. + */ + PropertyAttributePropertyView(PropertyViewStatusType status) noexcept + : PropertyView(status), _accessor{}, _size{0} { + CESIUM_ASSERT( + this->_status != PropertyAttributePropertyViewStatus::Valid && + "An empty property view should not be constructed with a valid status"); + } + + /** + * @brief Constructs an instance of an empty property that specifies a default + * value. Although this property has no data, it can return the default value + * when \ref get is called. However, \ref getRaw cannot be used. + * + * @param classProperty The {@link ClassProperty} this property conforms to. + * @param size The number of elements in the primitive's POSITION accessor. + * Used as a substitute since no actual accessor is defined. + */ + PropertyAttributePropertyView( + const ClassProperty& classProperty, + int64_t size) noexcept + : PropertyView(classProperty), _accessor{}, _size{0} { + if (this->_status != PropertyAttributePropertyViewStatus::Valid) { + // Don't override the status / size if something is wrong with the class + // property's definition. + return; + } + + if (!classProperty.defaultProperty) { + // This constructor should only be called if the class property *has* a + // default value. But in the case that it does not, this property view + // becomes invalid. + this->_status = + PropertyAttributePropertyViewStatus::ErrorNonexistentProperty; + return; + } + + this->_status = + PropertyAttributePropertyViewStatus::EmptyPropertyWithDefault; + this->_size = size; + } + + /** + * @brief Construct a view of the data specified by a {@link PropertyAttributeProperty}. + * + * @param property The {@link PropertyAttributeProperty} + * @param classProperty The {@link ClassProperty} this property conforms to. + * @param accessorView The {@link AccessorView} for the data that this property is + * associated with. + */ + PropertyAttributePropertyView( + const PropertyAttributeProperty& property, + const ClassProperty& classProperty, + const AccessorView& accessorView) noexcept + : PropertyView(classProperty, property), + _accessor{accessorView}, + _size{ + this->_status == PropertyAttributePropertyViewStatus::Valid + ? accessorView.size() + : 0} {} + + /** + * @brief Gets the value of the property for the given vertex index + * with all value transforms applied. That is, if the property specifies an + * offset and scale, they will be applied to the value before the value is + * returned. + * + * If this property has a specified "no data" value, this will return the + * property's default value for any elements that equal this "no data" value. + * If the property did not specify a default value, this returns std::nullopt. + * + * @param index The vertex index. + * + * @return The value of the property for the given vertex, or std::nullopt if + * it matches the "no data" value + */ + std::optional get(int64_t index) const noexcept { + if (this->_status == + PropertyAttributePropertyViewStatus::EmptyPropertyWithDefault) { + return this->defaultValue(); + } + + ElementType value = getRaw(index); + + if (value == this->noData()) { + return this->defaultValue(); + } + + if constexpr (IsMetadataScalar::value) { + return transformValue( + normalize(value), + this->offset(), + this->scale()); + } + + if constexpr (IsMetadataVecN::value) { + constexpr glm::length_t N = ElementType::length(); + using T = typename ElementType::value_type; + using NormalizedT = typename NormalizedType::value_type; + return transformValue>( + normalize(value), + this->offset(), + this->scale()); + } + + if constexpr (IsMetadataMatN::value) { + constexpr glm::length_t N = ElementType::length(); + using T = typename ElementType::value_type; + using NormalizedT = typename NormalizedType::value_type; + return transformValue>( + normalize(value), + this->offset(), + this->scale()); + } + } + + /** + * @brief Gets the raw value of the property for the given vertex index. + * + * If this property has a specified "no data" value, the raw value will still + * be returned, even if it equals the "no data" value. + * + * @param index The vertex index. + * + * @return The value of the property for the given vertex. + */ + ElementType getRaw(int64_t index) const noexcept { + CESIUM_ASSERT( + this->_status == PropertyAttributePropertyViewStatus::Valid && + "Check the status() first to make sure view is valid"); + CESIUM_ASSERT( + size() > 0 && + "Check the size() of the view to make sure it's not empty"); + CESIUM_ASSERT(index >= 0 && "index must be non-negative"); + CESIUM_ASSERT(index < size() && "index must be less than size"); + + return _accessor[index]; + } + + /** + * @brief Get the number of elements in this PropertyAttributePropertyView. + * If the view is valid, this returns the count of the elements in the + * attribute's accessor. Otherwise, this returns 0. + * + * @return The number of elements in this PropertyAttributePropertyView. + */ + int64_t size() const noexcept { return _size; } + +private: + AccessorView _accessor; + int64_t _size; +}; + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyAttributeView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyAttributeView.h new file mode 100644 index 0000000..478169b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyAttributeView.h @@ -0,0 +1,742 @@ +#pragma once + +#include "CesiumGltf/Class.h" +#include "CesiumGltf/ClassProperty.h" +#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" +#include "CesiumGltf/PropertyAttribute.h" +#include "CesiumGltf/PropertyAttributePropertyView.h" +#include "Model.h" + +namespace CesiumGltf { +/** + * @brief Indicates the status of a property attribute view. + * + * The {@link PropertyAttributeView} constructor always completes successfully. + * However it may not always reflect the actual content of the + * {@link PropertyAttribute}. This enumeration provides the reason. + */ +enum class PropertyAttributeViewStatus { + /** + * @brief This property attribute view is valid and ready to use. + */ + Valid, + + /** + * @brief The glTF is missing the EXT_structural_metadata extension. + */ + ErrorMissingMetadataExtension, + + /** + * @brief The glTF EXT_structural_metadata extension doesn't contain a schema. + */ + ErrorMissingSchema, + + /** + * @brief The property attribute's specified class could not be found in the + * extension. + */ + ErrorClassNotFound +}; + +/** + * @brief Attempts to obtain a \ref PropertyType from the \ref Accessor::type + * "type" field of the accessor. + * + * @param accessor The accessor whose type will be obtained. + * @returns A \ref PropertyType equivalent to the accessor's \ref + * AccessorSpec::type, or \ref PropertyType::Invalid if no conversion could be + * made. + */ +PropertyType getAccessorTypeAsPropertyType(const Accessor& accessor); + +/** + * @brief Attempts to obtain a \ref PropertyComponentType from the \ref + * Accessor::componentType "componentType" field of the accessor. + * + * @param accessor The accessor whose componentType will be obtained. + * @returns A \ref PropertyComponentType equivalent to the accessor's \ref + * AccessorSpec::componentType, or \ref PropertyComponentType::None if no + * conversion could be made. + */ +PropertyComponentType +getAccessorComponentTypeAsPropertyComponentType(const Accessor& accessor); + +/** + * @brief A view on a {@link PropertyAttribute}. + * + * This should be used to get a {@link PropertyAttributePropertyView} of a property + * in the property attribute. It will validate the EXT_structural_metadata + * format and ensure {@link PropertyAttributePropertyView} does not access data out + * of bounds. + */ +class PropertyAttributeView { +public: + /** + * @brief Construct a PropertyAttributeView. + * + * @param model The glTF that contains the property attribute's data. + * @param propertyAttribute The {@link PropertyAttribute} from which + * the view will retrieve data. + */ + PropertyAttributeView( + const Model& model, + const PropertyAttribute& propertyAttribute) noexcept; + + /** + * @brief Gets the status of this property attribute view. + * + * Indicates whether the view accurately reflects the property attribute's + * data, or whether an error occurred. + */ + PropertyAttributeViewStatus status() const noexcept { return this->_status; } + + /** + * @brief Gets the name of the property attribute being viewed. Returns + * std::nullopt if no name was specified. + */ + const std::optional& name() const noexcept { + return _pPropertyAttribute->name; + } + + /** + * @brief Gets the {@link Class} that this property attribute conforms to. + * + * @return A pointer to the {@link Class}. Returns nullptr if the + * PropertyAttribute did not specify a valid class. + */ + const Class* getClass() const noexcept { return _pClass; } + + /** + * @brief Finds the {@link ClassProperty} that + * describes the type information of the property with the specified id. + * @param propertyId The id of the property to retrieve the class for. + * @return A pointer to the {@link ClassProperty}. + * Return nullptr if the PropertyAttributeView is invalid or if no class + * property was found. + */ + const ClassProperty* getClassProperty(const std::string& propertyId) const; + + /** + * @brief Gets a {@link PropertyAttributePropertyView} that views the data of a + * property stored in the {@link PropertyAttribute}. + * + * This method will validate the EXT_structural_metadata format to ensure + * {@link PropertyAttributePropertyView} retrieves the correct data. T must + * be a scalar with a supported component type (int8_t, uint8_t, int16_t, + * uint16_t, float), a glm vecN composed of one of the scalar types, + * or a glm matN containing one of the scalar types. + * + * If T does not match the type specified by the class property, this returns + * an invalid PropertyAttributePropertyView. Likewise, if the value of + * Normalized does not match the value of {@link ClassProperty::normalized} for that + * class property, this returns an invalid property view. Only types with + * integer components may be normalized. + * + * @tparam T The C++ type corresponding to the type of the data retrieved. + * @tparam Normalized Whether the property is normalized. Only applicable to + * types with integer components. + * @param primitive The target primitive + * @param propertyId The id of the property to retrieve data from + * @return A {@link PropertyAttributePropertyView} of the property. If no valid + * property is found, the property view will be invalid. + */ + template + PropertyAttributePropertyView getPropertyView( + const MeshPrimitive& primitive, + const std::string& propertyId) const { + if (this->_status != PropertyAttributeViewStatus::Valid) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorInvalidPropertyAttribute); + } + const ClassProperty* pClassProperty = getClassProperty(propertyId); + if (!pClassProperty) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorNonexistentProperty); + } + + if constexpr ( + IsMetadataArray::value || IsMetadataBoolean::value || + IsMetadataString::value) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorUnsupportedProperty); + } + + return getPropertyViewImpl( + primitive, + propertyId, + *pClassProperty); + } + + /** + * @brief Gets a {@link PropertyAttributePropertyView} through a callback that accepts a + * property id and a {@link PropertyAttributePropertyView} that views the data + * of the property with the specified id. + * + * This method will validate the EXT_structural_metadata format to ensure + * {@link PropertyAttributePropertyView} retrieves the correct data. T must + * be a scalar with a supported component type (int8_t, uint8_t, int16_t, + * uint16_t, float), a glm vecN composed of one of the scalar types, + * or a glm matN containing one of the scalar types. + * + * If the property is somehow invalid, an empty {@link PropertyAttributePropertyView} + * with an error status will be passed to the callback. Otherwise, a valid + * property view will be passed to the callback. + * + * @param primitive The target primitive + * @param propertyId The id of the property to retrieve data from + * @param callback A callback function that accepts a property id and a + * {@link PropertyAttributePropertyView} + * @tparam Callback The type of the callback function. + */ + template + void getPropertyView( + const MeshPrimitive& primitive, + const std::string& propertyId, + Callback&& callback) const { + if (this->_status != PropertyAttributeViewStatus::Valid) { + callback( + propertyId, + PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus:: + ErrorInvalidPropertyAttribute)); + return; + } + + const ClassProperty* pClassProperty = getClassProperty(propertyId); + if (!pClassProperty) { + callback( + propertyId, + PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorNonexistentProperty)); + return; + } + + if (pClassProperty->array) { + callback( + propertyId, + PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorUnsupportedProperty)); + return; + } + + PropertyType type = convertStringToPropertyType(pClassProperty->type); + PropertyComponentType componentType = PropertyComponentType::None; + if (pClassProperty->componentType) { + componentType = + convertStringToPropertyComponentType(*pClassProperty->componentType); + } + + bool normalized = pClassProperty->normalized; + if (normalized && !isPropertyComponentTypeInteger(componentType)) { + callback( + propertyId, + PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorInvalidNormalization)); + return; + } + + if (type == PropertyType::Scalar) { + if (normalized) { + getScalarPropertyViewImpl( + primitive, + propertyId, + *pClassProperty, + componentType, + std::forward(callback)); + } else { + getScalarPropertyViewImpl( + primitive, + propertyId, + *pClassProperty, + componentType, + std::forward(callback)); + } + return; + } + + if (isPropertyTypeVecN(type)) { + if (normalized) { + getVecNPropertyViewImpl( + primitive, + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback)); + } else { + getVecNPropertyViewImpl( + primitive, + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback)); + } + return; + } + + if (isPropertyTypeMatN(type)) { + if (normalized) { + getMatNPropertyViewImpl( + primitive, + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback)); + } else { + getMatNPropertyViewImpl( + primitive, + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback)); + } + return; + } + + callback( + propertyId, + PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorUnsupportedProperty)); + return; + } + + /** + * @brief Iterates over each property in the {@link PropertyAttribute} with a callback + * that accepts a property id and a {@link PropertyAttributePropertyView} to view + * the data stored in the {@link PropertyAttributeProperty}. + * + * This method will validate the EXT_structural_metadata format to ensure + * {@link PropertyAttributePropertyView} retrieves the correct data. T must be + * a scalar with a supported component type (int8_t, uint8_t, int16_t, + * uint16_t, float), a glm vecN composed of one of the scalar types, + * or a PropertyArrayView containing one of the scalar types. + * + * If the property is invalid, an empty {@link PropertyAttributePropertyView} with an + * error status will be passed to the callback. Otherwise, a valid property + * view will be passed to the callback. + * + * @param primitive The id of the property to retrieve data from + * @param callback A callback function that accepts property id and + * {@link PropertyAttributePropertyView} + * @tparam Callback The type of the callback function. + */ + template + void + forEachProperty(const MeshPrimitive& primitive, Callback&& callback) const { + for (const auto& property : this->_pClass->properties) { + getPropertyView( + primitive, + property.first, + std::forward(callback)); + } + } + +private: + template + PropertyAttributePropertyView getEmptyPropertyViewWithDefault( + const MeshPrimitive& primitive, + const ClassProperty& classProperty) const { + // To make the view have a nonzero size, find the POSITION attribute and get + // its accessor count. If it doesn't exist or is somehow erroneous, just + // mark the property as nonexistent. + if (primitive.attributes.find("POSITION") == primitive.attributes.end()) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorNonexistentProperty); + } + + const Accessor* pAccessor = _pModel->getSafe( + &_pModel->accessors, + primitive.attributes.at("POSITION")); + if (!pAccessor) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorNonexistentProperty); + } + + return PropertyAttributePropertyView( + classProperty, + pAccessor->count); + } + + template + PropertyAttributePropertyView getPropertyViewImpl( + const MeshPrimitive& primitive, + const std::string& propertyId, + const ClassProperty& classProperty) const { + auto propertyAttributePropertyIter = + _pPropertyAttribute->properties.find(propertyId); + if (propertyAttributePropertyIter == + _pPropertyAttribute->properties.end()) { + if (!classProperty.required && classProperty.defaultProperty) { + // If the property was omitted from the property attribute, it is still + // technically valid if it specifies a default value. Try to create a + // view that just returns the default value. + return getEmptyPropertyViewWithDefault( + primitive, + classProperty); + } + + // Otherwise, the property is erroneously nonexistent. + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorNonexistentProperty); + } + + const PropertyAttributeProperty& propertyAttributeProperty = + propertyAttributePropertyIter->second; + + return createPropertyView( + primitive, + classProperty, + propertyAttributeProperty); + } + + template + void getScalarPropertyViewImpl( + const MeshPrimitive& primitive, + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyComponentType componentType, + Callback&& callback) const { + switch (componentType) { + case PropertyComponentType::Int8: + callback( + propertyId, + getPropertyViewImpl( + primitive, + propertyId, + classProperty)); + return; + case PropertyComponentType::Uint8: + callback( + propertyId, + getPropertyViewImpl( + primitive, + propertyId, + classProperty)); + return; + case PropertyComponentType::Int16: + callback( + propertyId, + getPropertyViewImpl( + primitive, + propertyId, + classProperty)); + return; + case PropertyComponentType::Uint16: + callback( + propertyId, + getPropertyViewImpl( + primitive, + propertyId, + classProperty)); + break; + case PropertyComponentType::Float32: + callback( + propertyId, + getPropertyViewImpl( + primitive, + propertyId, + classProperty)); + break; + default: + callback( + propertyId, + PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorUnsupportedProperty)); + break; + } + } + + template + void getVecNPropertyViewImpl( + const MeshPrimitive& primitive, + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyComponentType componentType, + Callback&& callback) const { + switch (componentType) { + case PropertyComponentType::Int8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + primitive, + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + primitive, + propertyId, + classProperty)); + break; + case PropertyComponentType::Int16: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + primitive, + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint16: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + primitive, + propertyId, + classProperty)); + break; + case PropertyComponentType::Float32: + callback( + propertyId, + getPropertyViewImpl, false>( + primitive, + propertyId, + classProperty)); + break; + default: + callback( + propertyId, + PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorUnsupportedProperty)); + break; + } + } + + template + void getVecNPropertyViewImpl( + const MeshPrimitive& primitive, + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyType type, + PropertyComponentType componentType, + Callback&& callback) const { + const glm::length_t N = getDimensionsFromPropertyType(type); + switch (N) { + case 2: + getVecNPropertyViewImpl( + primitive, + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + case 3: + getVecNPropertyViewImpl( + primitive, + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + case 4: + getVecNPropertyViewImpl( + primitive, + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + default: + callback( + propertyId, + PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorTypeMismatch)); + break; + } + } + + template + void getMatNPropertyViewImpl( + const MeshPrimitive& primitive, + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyComponentType componentType, + Callback&& callback) const { + switch (componentType) { + case PropertyComponentType::Int8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + primitive, + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + primitive, + propertyId, + classProperty)); + break; + case PropertyComponentType::Int16: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + primitive, + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint16: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + primitive, + propertyId, + classProperty)); + break; + case PropertyComponentType::Float32: + callback( + propertyId, + getPropertyViewImpl, false>( + primitive, + propertyId, + classProperty)); + break; + default: + callback( + propertyId, + PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorUnsupportedProperty)); + break; + } + } + + template + void getMatNPropertyViewImpl( + const MeshPrimitive& primitive, + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyType type, + PropertyComponentType componentType, + Callback&& callback) const { + glm::length_t N = getDimensionsFromPropertyType(type); + switch (N) { + case 2: + getMatNPropertyViewImpl( + primitive, + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + case 3: + getMatNPropertyViewImpl( + primitive, + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + case 4: + getMatNPropertyViewImpl( + primitive, + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + default: + callback( + propertyId, + PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorTypeMismatch)); + break; + } + } + + template + PropertyAttributePropertyView createPropertyView( + const MeshPrimitive& primitive, + const ClassProperty& classProperty, + const PropertyAttributeProperty& propertyAttributeProperty) const { + const PropertyType type = convertStringToPropertyType(classProperty.type); + if (TypeToPropertyType::value != type) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorTypeMismatch); + } + + const PropertyComponentType componentType = + convertStringToPropertyComponentType( + classProperty.componentType.value_or("")); + if (TypeToPropertyType::component != componentType) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorComponentTypeMismatch); + } + + if (classProperty.normalized != Normalized) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorNormalizationMismatch); + } + + if (primitive.attributes.find(propertyAttributeProperty.attribute) == + primitive.attributes.end()) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorMissingAttribute); + } + + const Accessor* pAccessor = _pModel->getSafe( + &_pModel->accessors, + primitive.attributes.at(propertyAttributeProperty.attribute)); + if (!pAccessor) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorInvalidAccessor); + } + + if (getAccessorTypeAsPropertyType(*pAccessor) != type) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorAccessorTypeMismatch); + } + + if (getAccessorComponentTypeAsPropertyComponentType(*pAccessor) != + componentType) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus:: + ErrorAccessorComponentTypeMismatch); + } + + if (pAccessor->normalized != Normalized) { + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus:: + ErrorAccessorNormalizationMismatch); + } + + AccessorView accessorView = AccessorView(*_pModel, *pAccessor); + if (accessorView.status() != AccessorViewStatus::Valid) { + switch (accessorView.status()) { + case AccessorViewStatus::InvalidBufferViewIndex: + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorInvalidBufferView); + case AccessorViewStatus::InvalidBufferIndex: + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorInvalidBuffer); + case AccessorViewStatus::BufferViewTooSmall: + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorAccessorOutOfBounds); + case AccessorViewStatus::BufferTooSmall: + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorBufferViewOutOfBounds); + default: + return PropertyAttributePropertyView( + PropertyAttributePropertyViewStatus::ErrorInvalidAccessor); + } + } + + return PropertyAttributePropertyView( + propertyAttributeProperty, + classProperty, + accessorView); + } + + const Model* _pModel; + const PropertyAttribute* _pPropertyAttribute; + const Class* _pClass; + + PropertyAttributeViewStatus _status; +}; + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTable.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTable.h new file mode 100644 index 0000000..f32eba8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTable.h @@ -0,0 +1,76 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief Properties conforming to a class, organized as property values stored + * in binary columnar arrays. + */ +struct CESIUMGLTF_API PropertyTable final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "PropertyTable"; + + /** + * @brief The name of the property table, e.g. for display purposes. + */ + std::optional name; + + /** + * @brief The class that property values conform to. The value must be a class + * ID declared in the `classes` dictionary. + */ + std::string classProperty; + + /** + * @brief The number of elements in each property array. + */ + int64_t count = int64_t(); + + /** + * @brief A dictionary, where each key corresponds to a property ID in the + * class' `properties` dictionary and each value is an object describing where + * property values are stored. Required properties must be included in this + * dictionary. + */ + std::unordered_map properties; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(PropertyTable)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + accum += int64_t(this->classProperty.capacity() * sizeof(char)); + accum += int64_t( + this->properties.bucket_count() * + (sizeof(std::string) + sizeof(CesiumGltf::PropertyTableProperty))); + for (const auto& [k, v] : this->properties) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += + v.getSizeBytes() - int64_t(sizeof(CesiumGltf::PropertyTableProperty)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTableProperty.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTableProperty.h new file mode 100644 index 0000000..d378abd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTableProperty.h @@ -0,0 +1,161 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief An array of binary property values. + */ +struct CESIUMGLTF_API PropertyTableProperty final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "PropertyTableProperty"; + + /** + * @brief Known values for The type of values in `arrayOffsets`. + */ + struct ArrayOffsetType { + /** @brief `UINT8` */ + inline static const std::string UINT8 = "UINT8"; + + /** @brief `UINT16` */ + inline static const std::string UINT16 = "UINT16"; + + /** @brief `UINT32` */ + inline static const std::string UINT32 = "UINT32"; + + /** @brief `UINT64` */ + inline static const std::string UINT64 = "UINT64"; + }; + + /** + * @brief Known values for The type of values in `stringOffsets`. + */ + struct StringOffsetType { + /** @brief `UINT8` */ + inline static const std::string UINT8 = "UINT8"; + + /** @brief `UINT16` */ + inline static const std::string UINT16 = "UINT16"; + + /** @brief `UINT32` */ + inline static const std::string UINT32 = "UINT32"; + + /** @brief `UINT64` */ + inline static const std::string UINT64 = "UINT64"; + }; + + /** + * @brief The index of the buffer view containing property values. The data + * type of property values is determined by the property definition: When + * `type` is `BOOLEAN` values are packed into a bitstream. When `type` is + * `STRING` values are stored as byte sequences and decoded as UTF-8 strings. + * When `type` is `SCALAR`, `VECN`, or `MATN` the values are stored as the + * provided `componentType` and the buffer view `byteOffset` must be aligned + * to a multiple of the `componentType` size. When `type` is `ENUM` values are + * stored as the enum's `valueType` and the buffer view `byteOffset` must be + * aligned to a multiple of the `valueType` size. Each enum value in the array + * must match one of the allowed values in the enum definition. `arrayOffsets` + * is required for variable-length arrays and `stringOffsets` is required for + * strings (for variable-length arrays of strings, both are required). + */ + int32_t values = -1; + + /** + * @brief The index of the buffer view containing offsets for variable-length + * arrays. The number of offsets is equal to the property table `count` plus + * one. The offsets represent the start positions of each array, with the last + * offset representing the position after the last array. The array length is + * computed using the difference between the subsequent offset and the current + * offset. If `type` is `STRING` the offsets index into the string offsets + * array (stored in `stringOffsets`), otherwise they index into the property + * array (stored in `values`). The data type of these offsets is determined by + * `arrayOffsetType`. The buffer view `byteOffset` must be aligned to a + * multiple of the `arrayOffsetType` size. + */ + int32_t arrayOffsets = -1; + + /** + * @brief The index of the buffer view containing offsets for strings. The + * number of offsets is equal to the number of string elements plus one. The + * offsets represent the byte offsets of each string in the property array + * (stored in `values`), with the last offset representing the byte offset + * after the last string. The string byte length is computed using the + * difference between the subsequent offset and the current offset. The data + * type of these offsets is determined by `stringOffsetType`. The buffer view + * `byteOffset` must be aligned to a multiple of the `stringOffsetType` size. + */ + int32_t stringOffsets = -1; + + /** + * @brief The type of values in `arrayOffsets`. + * + * Known values are defined in {@link ArrayOffsetType}. + * + */ + std::string arrayOffsetType = ArrayOffsetType::UINT32; + + /** + * @brief The type of values in `stringOffsets`. + * + * Known values are defined in {@link StringOffsetType}. + * + */ + std::string stringOffsetType = StringOffsetType::UINT32; + + /** + * @brief An offset to apply to property values. Only applicable when the + * component type is `FLOAT32` or `FLOAT64`, or when the property is + * `normalized`. Overrides the class property's `offset` if both are defined. + */ + std::optional offset; + + /** + * @brief A scale to apply to property values. Only applicable when the + * component type is `FLOAT32` or `FLOAT64`, or when the property is + * `normalized`. Overrides the class property's `scale` if both are defined. + */ + std::optional scale; + + /** + * @brief Maximum value present in the property values. Only applicable to + * `SCALAR`, `VECN`, and `MATN` types. This is the maximum of all property + * values, after the transforms based on the `normalized`, `offset`, and + * `scale` properties have been applied. + */ + std::optional max; + + /** + * @brief Minimum value present in the property values. Only applicable to + * `SCALAR`, `VECN`, and `MATN` types. This is the minimum of all property + * values, after the transforms based on the `normalized`, `offset`, and + * `scale` properties have been applied. + */ + std::optional min; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(PropertyTableProperty)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTablePropertyView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTablePropertyView.h new file mode 100644 index 0000000..f37d064 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTablePropertyView.h @@ -0,0 +1,791 @@ +#pragma once + +#include "CesiumGltf/PropertyArrayView.h" +#include "CesiumGltf/PropertyTransformations.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumGltf/PropertyView.h" + +#include + +#include +#include +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief Indicates the status of a property table property view. + * + * The {@link PropertyTablePropertyView} constructor always completes successfully. + * However, it may not always reflect the actual content of the + * {@link PropertyTableProperty}, but instead indicate that its `size` is 0. + * This enumeration provides the reason. + */ +class PropertyTablePropertyViewStatus : public PropertyViewStatus { +public: + /** + * @brief This property view was initialized from an invalid + * {@link PropertyTable}. + */ + static const PropertyViewStatusType ErrorInvalidPropertyTable = 14; + + /** + * @brief This property view does not have a valid value buffer view index. + */ + static const PropertyViewStatusType ErrorInvalidValueBufferView = 15; + + /** + * @brief This array property view does not have a valid array offset buffer + * view index. + */ + static const PropertyViewStatusType ErrorInvalidArrayOffsetBufferView = 16; + + /** + * @brief This string property view does not have a valid string offset buffer + * view index. + */ + static const PropertyViewStatusType ErrorInvalidStringOffsetBufferView = 17; + + /** + * @brief This property view has a valid value buffer view, but the buffer + * view specifies an invalid buffer index. + */ + static const PropertyViewStatusType ErrorInvalidValueBuffer = 18; + + /** + * @brief This property view has a valid array string buffer view, but the + * buffer view specifies an invalid buffer index. + */ + static const PropertyViewStatusType ErrorInvalidArrayOffsetBuffer = 19; + + /** + * @brief This property view has a valid string offset buffer view, but the + * buffer view specifies an invalid buffer index. + */ + static const PropertyViewStatusType ErrorInvalidStringOffsetBuffer = 20; + + /** + * @brief This property view has a buffer view that points outside the bounds + * of its target buffer. + */ + static const PropertyViewStatusType ErrorBufferViewOutOfBounds = 21; + + /** + * @brief This property view has an invalid buffer view; its length is not + * a multiple of the size of its type / offset type. + */ + static const PropertyViewStatusType + ErrorBufferViewSizeNotDivisibleByTypeSize = 22; + + /** + * @brief This property view has an invalid buffer view; its length does not + * match the size of the property table. + */ + static const PropertyViewStatusType + ErrorBufferViewSizeDoesNotMatchPropertyTableCount = 23; + + /** + * @brief This array property view has both a fixed length and an offset + * buffer view defined. + */ + static const PropertyViewStatusType ErrorArrayCountAndOffsetBufferCoexist = + 24; + + /** + * @brief This array property view has neither a fixed length nor an offset + * buffer view defined. + */ + static const PropertyViewStatusType ErrorArrayCountAndOffsetBufferDontExist = + 25; + + /** + * @brief This property view has an unknown array offset type. + */ + static const PropertyViewStatusType ErrorInvalidArrayOffsetType = 26; + + /** + * @brief This property view has an unknown string offset type. + */ + static const PropertyViewStatusType ErrorInvalidStringOffsetType = 27; + + /** + * @brief This property view's array offset values are not sorted in ascending + * order. + */ + static const PropertyViewStatusType ErrorArrayOffsetsNotSorted = 28; + + /** + * @brief This property view's string offset values are not sorted in + * ascending order. + */ + static const PropertyViewStatusType ErrorStringOffsetsNotSorted = 29; + + /** + * @brief This property view has an array offset that is out of bounds. + */ + static const PropertyViewStatusType ErrorArrayOffsetOutOfBounds = 30; + + /** + * @brief This property view has a string offset that is out of bounds. + */ + static const PropertyViewStatusType ErrorStringOffsetOutOfBounds = 31; +}; + +/** + * @brief Returns the size in bytes of a \ref PropertyComponentType used as the + * `arrayOffsetType` in the constructor of \ref PropertyTablePropertyView. + */ +int64_t getOffsetTypeSize(PropertyComponentType offsetType) noexcept; + +/** + * @brief A view on the data of the {@link PropertyTableProperty} that is created + * by a {@link PropertyTableView}. + */ +template +class PropertyTablePropertyView; + +/** + * @brief A view on the data of the {@link PropertyTableProperty} that is created + * by a {@link PropertyTableView}. + * + * It provides utility to retrieve the actual data stored in the + * {@link PropertyTableProperty::values} like an array of elements. Data of each + * instance can be accessed through the {@link PropertyTablePropertyView::get} method. + * + * @param ElementType must be one of the following: a scalar (uint8_t, int8_t, + * uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double), a + * glm vecN composed of one of the scalar types, a glm matN composed of one of + * the scalar types, bool, std::string_view, or PropertyArrayView with T as + * one of the aforementioned types. + */ +template +class PropertyTablePropertyView + : public PropertyView { +public: + /** + * @brief Constructs an invalid instance for a non-existent property. + */ + PropertyTablePropertyView() + : PropertyView(), + _values{}, + _size{0}, + _arrayOffsets{}, + _arrayOffsetType{PropertyComponentType::None}, + _arrayOffsetTypeSize{0}, + _stringOffsets{}, + _stringOffsetType{PropertyComponentType::None}, + _stringOffsetTypeSize{0} {} + + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The code from {@link PropertyTablePropertyViewStatus} indicating the error with the property. + */ + PropertyTablePropertyView(PropertyViewStatusType status) + : PropertyView(status), + _values{}, + _size{0}, + _arrayOffsets{}, + _arrayOffsetType{PropertyComponentType::None}, + _arrayOffsetTypeSize{0}, + _stringOffsets{}, + _stringOffsetType{PropertyComponentType::None}, + _stringOffsetTypeSize{0} { + CESIUM_ASSERT( + this->_status != PropertyTablePropertyViewStatus::Valid && + "An empty property view should not be constructed with a valid status"); + } + + /** + * @brief Constructs an instance of an empty property that specifies a default + * value. Although this property has no data, it can return the default value + * when {@link PropertyTablePropertyView::get} is called. However, + * {@link PropertyTablePropertyView::getRaw} cannot be used. + * + * @param classProperty The {@link ClassProperty} this property conforms to. + * @param size The number of elements in the property table specified by {@link PropertyTable::count} + */ + PropertyTablePropertyView(const ClassProperty& classProperty, int64_t size) + : PropertyView(classProperty), + _values{}, + _size{0}, + _arrayOffsets{}, + _arrayOffsetType{PropertyComponentType::None}, + _arrayOffsetTypeSize{0}, + _stringOffsets{}, + _stringOffsetType{PropertyComponentType::None}, + _stringOffsetTypeSize{0} { + if (this->_status != PropertyTablePropertyViewStatus::Valid) { + // Don't override the status / size if something is wrong with the class + // property's definition. + return; + } + + if (!classProperty.defaultProperty) { + // This constructor should only be called if the class property *has* a + // default value. But in the case that it does not, this property view + // becomes invalid. + this->_status = PropertyTablePropertyViewStatus::ErrorNonexistentProperty; + return; + } + + this->_status = PropertyTablePropertyViewStatus::EmptyPropertyWithDefault; + this->_size = size; + } + + /** + * @brief Construct an instance pointing to data specified by a {@link PropertyTableProperty}. + * Used for non-array or fixed-length array data. + * + * @param property The {@link PropertyTableProperty} + * @param classProperty The {@link ClassProperty} this property conforms to. + * @param size The number of elements in the property table specified by {@link PropertyTable::count} + * @param values The raw buffer specified by {@link PropertyTableProperty::values} + */ + PropertyTablePropertyView( + const PropertyTableProperty& property, + const ClassProperty& classProperty, + int64_t size, + std::span values) noexcept + : PropertyView(classProperty, property), + _values{values}, + _size{ + this->_status == PropertyTablePropertyViewStatus::Valid ? size : 0}, + _arrayOffsets{}, + _arrayOffsetType{PropertyComponentType::None}, + _arrayOffsetTypeSize{0}, + _stringOffsets{}, + _stringOffsetType{PropertyComponentType::None}, + _stringOffsetTypeSize{0} {} + + /** + * @brief Construct an instance pointing to the data specified by a {@link PropertyTableProperty}. + * + * @param property The {@link PropertyTableProperty} + * @param classProperty The {@link ClassProperty} this property conforms to. + * @param size The number of elements in the property table specified by {@link PropertyTable::count} + * @param values The raw buffer specified by {@link PropertyTableProperty::values} + * @param arrayOffsets The raw buffer specified by {@link PropertyTableProperty::arrayOffsets} + * @param stringOffsets The raw buffer specified by {@link PropertyTableProperty::stringOffsets} + * @param arrayOffsetType The offset type of arrayOffsets specified by {@link PropertyTableProperty::arrayOffsetType} + * @param stringOffsetType The offset type of stringOffsets specified by {@link PropertyTableProperty::stringOffsetType} + */ + PropertyTablePropertyView( + const PropertyTableProperty& property, + const ClassProperty& classProperty, + int64_t size, + std::span values, + std::span arrayOffsets, + std::span stringOffsets, + PropertyComponentType arrayOffsetType, + PropertyComponentType stringOffsetType) noexcept + : PropertyView(classProperty, property), + _values{values}, + _size{ + this->_status == PropertyTablePropertyViewStatus::Valid ? size : 0}, + _arrayOffsets{arrayOffsets}, + _arrayOffsetType{arrayOffsetType}, + _arrayOffsetTypeSize{getOffsetTypeSize(arrayOffsetType)}, + _stringOffsets{stringOffsets}, + _stringOffsetType{stringOffsetType}, + _stringOffsetTypeSize{getOffsetTypeSize(stringOffsetType)} {} + + /** + * @brief Get the value of an element in the {@link PropertyTable}, + * with all value transforms applied. That is, if the property specifies an + * offset and scale, they will be applied to the value before the value is + * returned. + * + * If this property has a specified "no data" value, and the retrieved element + * is equal to that value, then this will return the property's specified + * default value. If the property did not provide a default value, this + * returns std::nullopt. + * + * @param index The element index + * @return The value of the element, or std::nullopt if it matches the "no + * data" value + */ + std::optional> + get(int64_t index) const noexcept { + if (this->_status == + PropertyTablePropertyViewStatus::EmptyPropertyWithDefault) { + CESIUM_ASSERT(index >= 0 && "index must be non-negative"); + CESIUM_ASSERT(index < size() && "index must be less than size"); + + return propertyValueViewToCopy(this->defaultValue()); + } + + ElementType value = getRaw(index); + + if (value == this->noData()) { + return propertyValueViewToCopy(this->defaultValue()); + } else if constexpr (IsMetadataNumeric::value) { + return transformValue(value, this->offset(), this->scale()); + } else if constexpr (IsMetadataNumericArray::value) { + return transformArray(value, this->offset(), this->scale()); + } else { + return value; + } + } + + /** + * @brief Get the raw value of an element of the {@link PropertyTable}, + * without offset or scale applied. + * + * If this property has a specified "no data" value, the raw value will still + * be returned, even if it equals the "no data" value. + * + * @param index The element index + * @return The value of the element + */ + ElementType getRaw(int64_t index) const noexcept { + CESIUM_ASSERT( + this->_status == PropertyTablePropertyViewStatus::Valid && + "Check the status() first to make sure view is valid"); + CESIUM_ASSERT( + size() > 0 && + "Check the size() of the view to make sure it's not empty"); + CESIUM_ASSERT(index >= 0 && "index must be non-negative"); + CESIUM_ASSERT(index < size() && "index must be less than size"); + + if constexpr (IsMetadataNumeric::value) { + return getNumericValue(index); + } + + if constexpr (IsMetadataBoolean::value) { + return getBooleanValue(index); + } + + if constexpr (IsMetadataString::value) { + return getStringValue(index); + } + + if constexpr (IsMetadataNumericArray::value) { + return getNumericArrayValues< + typename MetadataArrayType::type>(index); + } + + if constexpr (IsMetadataBooleanArray::value) { + return getBooleanArrayValues(index); + } + + if constexpr (IsMetadataStringArray::value) { + return getStringArrayValues(index); + } + } + + /** + * @brief Get the number of elements in this + * PropertyTablePropertyView. If the view is valid, this returns + * {@link PropertyTable::count}. Otherwise, this returns 0. + * + * @return The number of elements in this PropertyTablePropertyView. + */ + int64_t size() const noexcept { return _size; } + +private: + ElementType getNumericValue(int64_t index) const noexcept { + return reinterpret_cast(_values.data())[index]; + } + + bool getBooleanValue(int64_t index) const noexcept { + const int64_t byteIndex = index / 8; + const int64_t bitIndex = index % 8; + const int bitValue = static_cast(_values[byteIndex] >> bitIndex) & 1; + return bitValue == 1; + } + + std::string_view getStringValue(int64_t index) const noexcept { + const size_t currentOffset = + getOffsetFromOffsetsBuffer(index, _stringOffsets, _stringOffsetType); + const size_t nextOffset = getOffsetFromOffsetsBuffer( + index + 1, + _stringOffsets, + _stringOffsetType); + return std::string_view( + reinterpret_cast(_values.data() + currentOffset), + nextOffset - currentOffset); + } + + template + PropertyArrayView getNumericArrayValues(int64_t index) const noexcept { + size_t count = static_cast(this->arrayCount()); + // Handle fixed-length arrays + if (count > 0) { + size_t arraySize = count * sizeof(T); + const std::span values( + _values.data() + index * arraySize, + arraySize); + return PropertyArrayView{values}; + } + + // Handle variable-length arrays. The offsets are interpreted as array + // indices, not byte offsets, so they must be multiplied by sizeof(T) + const size_t currentOffset = + getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType) * + sizeof(T); + const size_t nextOffset = + getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType) * + sizeof(T); + const std::span values( + _values.data() + currentOffset, + nextOffset - currentOffset); + return PropertyArrayView{values}; + } + + PropertyArrayView + getStringArrayValues(int64_t index) const noexcept { + size_t count = static_cast(this->arrayCount()); + // Handle fixed-length arrays + if (count > 0) { + // Copy the corresponding string offsets to pass to the PropertyArrayView. + const size_t arraySize = count * _stringOffsetTypeSize; + const std::span stringOffsetValues( + _stringOffsets.data() + index * arraySize, + arraySize + _stringOffsetTypeSize); + return PropertyArrayView( + _values, + stringOffsetValues, + _stringOffsetType, + count); + } + + // Handle variable-length arrays + const size_t currentArrayOffset = + getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType); + const size_t nextArrayOffset = + getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType); + const size_t arraySize = nextArrayOffset - currentArrayOffset; + const std::span stringOffsetValues( + _stringOffsets.data() + currentArrayOffset, + arraySize + _arrayOffsetTypeSize); + return PropertyArrayView( + _values, + stringOffsetValues, + _stringOffsetType, + arraySize / _arrayOffsetTypeSize); + } + + PropertyArrayView getBooleanArrayValues(int64_t index) const noexcept { + size_t count = static_cast(this->arrayCount()); + // Handle fixed-length arrays + if (count > 0) { + const size_t offsetBits = count * index; + const size_t nextOffsetBits = count * (index + 1); + const std::span buffer( + _values.data() + offsetBits / 8, + (nextOffsetBits / 8 - offsetBits / 8 + 1)); + return PropertyArrayView(buffer, offsetBits % 8, count); + } + + // Handle variable-length arrays + const size_t currentOffset = + getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType); + const size_t nextOffset = + getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType); + const size_t totalBits = nextOffset - currentOffset; + const std::span buffer( + _values.data() + currentOffset / 8, + (nextOffset / 8 - currentOffset / 8 + 1)); + return PropertyArrayView(buffer, currentOffset % 8, totalBits); + } + + std::span _values; + int64_t _size; + + std::span _arrayOffsets; + PropertyComponentType _arrayOffsetType; + int64_t _arrayOffsetTypeSize; + + std::span _stringOffsets; + PropertyComponentType _stringOffsetType; + int64_t _stringOffsetTypeSize; +}; + +/** + * @brief A view on the normalized data of the {@link PropertyTableProperty} + * that is created by a {@link PropertyTableView}. + * + * It provides utility to retrieve the actual data stored in the + * {@link PropertyTableProperty::values} like an array of elements. Data of each + * instance can be accessed through the \ref get method. + * + * @param ElementType must be one of the following: an integer scalar (uint8_t, + * int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t), a glm vecN + * composed of one of the integer scalar types, a glm matN composed of one of + * the integer scalar types, or PropertyArrayView with T as one of the + * aforementioned types. + */ +template +class PropertyTablePropertyView + : public PropertyView { +private: + using NormalizedType = typename TypeToNormalizedType::type; + +public: + /** + * @brief Constructs an invalid instance for a non-existent property. + */ + PropertyTablePropertyView() + : PropertyView(), + _values{}, + _size{0}, + _arrayOffsets{}, + _arrayOffsetType{PropertyComponentType::None}, + _arrayOffsetTypeSize{0} {} + + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The value of {@link PropertyTablePropertyViewStatus} indicating the error with the property. + */ + PropertyTablePropertyView(PropertyViewStatusType status) + : PropertyView(status), + _values{}, + _size{0}, + _arrayOffsets{}, + _arrayOffsetType{PropertyComponentType::None}, + _arrayOffsetTypeSize{0} { + CESIUM_ASSERT( + this->_status != PropertyTablePropertyViewStatus::Valid && + "An empty property view should not be constructed with a valid status"); + } + + /** + * @brief Constructs an instance of an empty property that specifies a default + * value. Although this property has no data, it can return the default value + * when {@link PropertyTablePropertyView::get} is called. However, + * {@link PropertyTablePropertyView::getRaw} cannot be used. + * + * @param classProperty The {@link ClassProperty} this property conforms to. + * @param size The number of elements in the property table specified by {@link PropertyTable::count} + */ + PropertyTablePropertyView(const ClassProperty& classProperty, int64_t size) + : PropertyView(classProperty), + _values{}, + _size{0}, + _arrayOffsets{}, + _arrayOffsetType{PropertyComponentType::None}, + _arrayOffsetTypeSize{0} { + if (this->_status != PropertyTablePropertyViewStatus::Valid) { + // Don't override the status / size if something is wrong with the class + // property's definition. + return; + } + + if (!classProperty.defaultProperty) { + // This constructor should only be called if the class property *has* a + // default value. But in the case that it does not, this property view + // becomes invalid. + this->_status = PropertyTablePropertyViewStatus::ErrorNonexistentProperty; + return; + } + + this->_status = PropertyTablePropertyViewStatus::EmptyPropertyWithDefault; + this->_size = size; + } + + /** + * @brief Construct an instance pointing to data specified by a {@link PropertyTableProperty}. + * Used for non-array or fixed-length array data. + * + * @param property The {@link PropertyTableProperty} + * @param classProperty The {@link ClassProperty} this property conforms to. + * @param size The number of elements in the property table specified by {@link PropertyTable::count} + * @param values The raw buffer specified by {@link PropertyTableProperty::values} + */ + PropertyTablePropertyView( + const PropertyTableProperty& property, + const ClassProperty& classProperty, + int64_t size, + std::span values) noexcept + : PropertyView(classProperty, property), + _values{values}, + _size{ + this->_status == PropertyTablePropertyViewStatus::Valid ? size : 0}, + _arrayOffsets{}, + _arrayOffsetType{PropertyComponentType::None}, + _arrayOffsetTypeSize{0} {} + + /** + * @brief Construct an instance pointing to the data specified by a {@link PropertyTableProperty}. + * + * + * @param property The {@link PropertyTableProperty} + * @param classProperty The {@link ClassProperty} this property conforms to. + * @param size The number of elements in the property table specified by {@link PropertyTable::count} + * @param values The raw buffer specified by {@link PropertyTableProperty::values} + * @param arrayOffsets The raw buffer specified by {@link PropertyTableProperty::arrayOffsets} + * @param arrayOffsetType The offset type of arrayOffsets specified by {@link PropertyTableProperty::arrayOffsetType} + */ + PropertyTablePropertyView( + const PropertyTableProperty& property, + const ClassProperty& classProperty, + int64_t size, + std::span values, + std::span arrayOffsets, + PropertyComponentType arrayOffsetType) noexcept + : PropertyView(classProperty, property), + _values{values}, + _size{ + this->_status == PropertyTablePropertyViewStatus::Valid ? size : 0}, + _arrayOffsets{arrayOffsets}, + _arrayOffsetType{arrayOffsetType}, + _arrayOffsetTypeSize{getOffsetTypeSize(arrayOffsetType)} {} + + /** + * @brief Get the value of an element of the {@link PropertyTable}, + * with normalization and other value transforms applied. In other words, the + * value will be normalized, then transformed by the property's offset + * and scale, if they are defined. + * + * If this property has a specified "no data" value, and the retrieved element + * is equal to that value, then this will return the property's specified + * default value. If the property did not provide a default value, this + * returns std::nullopt. + * + * @param index The element index + * @return The value of the element, or std::nullopt if it matches the "no + * data" value + */ + std::optional> + get(int64_t index) const noexcept { + if (this->_status == + PropertyTablePropertyViewStatus::EmptyPropertyWithDefault) { + CESIUM_ASSERT(index >= 0 && "index must be non-negative"); + CESIUM_ASSERT(index < size() && "index must be less than size"); + + return propertyValueViewToCopy(this->defaultValue()); + } + + ElementType value = getRaw(index); + if (this->noData() && value == *(this->noData())) { + return propertyValueViewToCopy(this->defaultValue()); + } else if constexpr (IsMetadataScalar::value) { + return transformValue( + normalize(value), + this->offset(), + this->scale()); + } else if constexpr (IsMetadataVecN::value) { + constexpr glm::length_t N = ElementType::length(); + using T = typename ElementType::value_type; + using NormalizedT = typename NormalizedType::value_type; + return transformValue>( + normalize(value), + this->offset(), + this->scale()); + } else if constexpr (IsMetadataMatN::value) { + constexpr glm::length_t N = ElementType::length(); + using T = typename ElementType::value_type; + using NormalizedT = typename NormalizedType::value_type; + return transformValue>( + normalize(value), + this->offset(), + this->scale()); + } else if constexpr (IsMetadataArray::value) { + using ArrayElementType = typename MetadataArrayType::type; + if constexpr (IsMetadataScalar::value) { + return transformNormalizedArray( + value, + this->offset(), + this->scale()); + } else if constexpr (IsMetadataVecN::value) { + constexpr glm::length_t N = ArrayElementType::length(); + using T = typename ArrayElementType::value_type; + return transformNormalizedVecNArray( + value, + this->offset(), + this->scale()); + } else if constexpr (IsMetadataMatN::value) { + constexpr glm::length_t N = ArrayElementType::length(); + using T = typename ArrayElementType::value_type; + return transformNormalizedMatNArray( + value, + this->offset(), + this->scale()); + } + } + } + + /** + * @brief Get the raw value of an element of the {@link PropertyTable}, + * without offset, scale, or normalization applied. + * + * If this property has a specified "no data" value, the raw value will still + * be returned, even if it equals the "no data" value. + * + * @param index The element index + * @return The value of the element + */ + ElementType getRaw(int64_t index) const noexcept { + CESIUM_ASSERT( + this->_status == PropertyTablePropertyViewStatus::Valid && + "Check the status() first to make sure view is valid"); + CESIUM_ASSERT( + size() > 0 && + "Check the size() of the view to make sure it's not empty"); + CESIUM_ASSERT(index >= 0 && "index must be non-negative"); + CESIUM_ASSERT(index < size() && "index must be less than size"); + + if constexpr (IsMetadataNumeric::value) { + return getValue(index); + } + + if constexpr (IsMetadataNumericArray::value) { + return getArrayValues::type>( + index); + } + } + + /** + * @brief Get the number of elements in this + * PropertyTablePropertyView. If the view is valid, this returns + * {@link PropertyTable::count}. Otherwise, this returns 0. + * + * @return The number of elements in this PropertyTablePropertyView. + */ + int64_t size() const noexcept { + return this->_status == PropertyTablePropertyViewStatus::Valid ? _size : 0; + } + +private: + ElementType getValue(int64_t index) const noexcept { + return reinterpret_cast(_values.data())[index]; + } + + template + PropertyArrayView getArrayValues(int64_t index) const noexcept { + size_t count = static_cast(this->arrayCount()); + // Handle fixed-length arrays + if (count > 0) { + size_t arraySize = count * sizeof(T); + const std::span values( + _values.data() + index * arraySize, + arraySize); + return PropertyArrayView{values}; + } + + // Handle variable-length arrays. The offsets are interpreted as array + // indices, not byte offsets, so they must be multiplied by sizeof(T) + const size_t currentOffset = + getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType) * + sizeof(T); + const size_t nextOffset = + getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType) * + sizeof(T); + const std::span values( + _values.data() + currentOffset, + nextOffset - currentOffset); + return PropertyArrayView{values}; + } + + std::span _values; + int64_t _size; + + std::span _arrayOffsets; + PropertyComponentType _arrayOffsetType; + int64_t _arrayOffsetTypeSize; +}; + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTableView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTableView.h new file mode 100644 index 0000000..f5bfaac --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTableView.h @@ -0,0 +1,1303 @@ +#pragma once + +#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltf/PropertyTablePropertyView.h" +#include "CesiumGltf/PropertyType.h" + +#include + +#include + +namespace CesiumGltf { + +/** + * @brief Indicates the status of a property table view. + * + * The {@link PropertyTableView} constructor always completes successfully. + * However, it may not always reflect the actual content of the {@link PropertyTable}, + * but instead indicate that its {@link PropertyTableView::size} is 0. + * This enumeration provides the reason. + */ +enum class PropertyTableViewStatus { + /** + * @brief This property table view is valid and ready to use. + */ + Valid, + + /** + * @brief The property table view's model does not contain an + * EXT_structural_metadata extension. + */ + ErrorMissingMetadataExtension, + + /** + * @brief The property table view's model does not have a schema in its + * EXT_structural_metadata extension. + */ + ErrorMissingSchema, + + /** + * @brief The property table's specified class could not be found in the + * extension. + */ + ErrorClassNotFound +}; + +/** + * @brief Utility to retrieve the data of {@link PropertyTable}. + * + * This should be used to get a {@link PropertyTablePropertyView} of a property in the property table. + * It will validate the EXT_structural_metadata format and ensure {@link PropertyTablePropertyView} + * does not access out of bounds. + */ +class PropertyTableView { +public: + /** + * @brief Creates an instance of PropertyTableView. + * @param model The glTF Model that contains the property table data. + * @param propertyTable The {@link PropertyTable} + * from which the view will retrieve data. + */ + PropertyTableView(const Model& model, const PropertyTable& propertyTable); + + /** + * @brief Gets the status of this property table view. + * + * Indicates whether the view accurately reflects the property table's data, + * or whether an error occurred. + * + * @return The status of this property table view. + */ + PropertyTableViewStatus status() const noexcept { return _status; } + + /** + * @brief Gets the name of the property table being viewed. Returns + * std::nullopt if no name was specified. + */ + const std::optional& name() const noexcept { + return _pPropertyTable->name; + } + + /** + * @brief Get the number of elements in this PropertyTableView. If the + * view is valid, this returns {@link PropertyTable::count}. Otherwise, this returns 0. + * + * @return The number of elements in this PropertyTableView. + */ + int64_t size() const noexcept { + return _status == PropertyTableViewStatus::Valid ? _pPropertyTable->count + : 0; + } + + /** + * @brief Gets the {@link Class} that this property table conforms to. + * + * @return A pointer to the {@link Class}. Returns nullptr if the PropertyTable + * did not specify a valid class. + */ + const Class* getClass() const noexcept { return _pClass; } + + /** + * @brief Finds the {@link ClassProperty} that + * describes the type information of the property with the specified id. + * @param propertyId The id of the property to retrieve the class for. + * @return A pointer to the {@link ClassProperty}. Returns nullptr if the + * PropertyTableView is invalid or if no class property was found. + */ + const ClassProperty* getClassProperty(const std::string& propertyId) const; + + /** + * @brief Gets a {@link PropertyTablePropertyView} that views the data of a property stored + * in the {@link PropertyTable}. + * + * This method will validate the EXT_structural_metadata format to ensure + * {@link PropertyTablePropertyView} retrieves the correct data. T must be one of the + * following: a scalar (uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, + * uint64_t, int64_t, float, double), a glm vecN composed of one of the scalar + * types, a glm matN composed of one of the scalar types, bool, + * std::string_view, or \ref PropertyArrayView with T as one of the + * aforementioned types. + * + * If T does not match the type specified by the class property, this returns + * an invalid PropertyTablePropertyView. Likewise, if the value of + * Normalized + * does not match the value of {@link ClassProperty::normalized} for that class property, + * this returns an invalid property view. Only types with integer components + * may be normalized. + * + * @tparam T The C++ type corresponding to the type of the data retrieved. + * @tparam Normalized Whether the property is normalized. Only applicable to + * types with integer components. + * @param propertyId The id of the property to retrieve data from + * @return A \ref PropertyTablePropertyView of the property. If no valid + * property is found, the property view will be invalid. + */ + template + PropertyTablePropertyView + getPropertyView(const std::string& propertyId) const { + if (this->size() <= 0) { + return PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorInvalidPropertyTable); + } + + const ClassProperty* pClassProperty = getClassProperty(propertyId); + if (!pClassProperty) { + return PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorNonexistentProperty); + } + + return getPropertyViewImpl(propertyId, *pClassProperty); + } + + /** + * @brief Gets a \ref PropertyTablePropertyView through a callback that + * accepts a property id and a \ref PropertyTablePropertyView that views the + * data of the property with the specified id. + * + * This method will validate the EXT_structural_metadata format to ensure + * \ref PropertyTablePropertyView retrieves the correct data. T must be one of + * the following: a scalar (uint8_t, int8_t, uint16_t, int16_t, uint32_t, + * int32_t, uint64_t, int64_t, float, double), a glm vecN composed of one of + * the scalar types, a glm matN composed of one of the scalar types, bool, + * std::string_view, or \ref PropertyArrayView with T as one of the + * aforementioned types. + * + * If the property is invalid, an empty \ref PropertyTablePropertyView with an + * error status will be passed to the callback. Otherwise, a valid property + * view will be passed to the callback. + * + * @param propertyId The id of the property to retrieve data from + * @param callback A callback function that accepts a property id and a + * \ref PropertyTablePropertyView + * @tparam Callback The type of the callback function. + */ + template + void + getPropertyView(const std::string& propertyId, Callback&& callback) const { + if (this->size() <= 0) { + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorInvalidPropertyTable)); + return; + } + + const ClassProperty* pClassProperty = getClassProperty(propertyId); + if (!pClassProperty) { + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorNonexistentProperty)); + return; + } + + PropertyType type = convertStringToPropertyType(pClassProperty->type); + PropertyComponentType componentType = PropertyComponentType::None; + if (pClassProperty->componentType) { + componentType = + convertStringToPropertyComponentType(*pClassProperty->componentType); + } + + bool normalized = pClassProperty->normalized; + if (normalized && !isPropertyComponentTypeInteger(componentType)) { + // Only integer components may be normalized. + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorInvalidNormalization)); + return; + } + + if (pClassProperty->array) { + if (normalized) { + getArrayPropertyViewImpl( + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback)); + } else { + getArrayPropertyViewImpl( + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback)); + } + return; + } + + if (type == PropertyType::Scalar) { + if (normalized) { + getScalarPropertyViewImpl( + propertyId, + *pClassProperty, + componentType, + std::forward(callback)); + } else { + getScalarPropertyViewImpl( + propertyId, + *pClassProperty, + componentType, + std::forward(callback)); + } + return; + } + + if (isPropertyTypeVecN(type)) { + if (normalized) { + getVecNPropertyViewImpl( + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback)); + } else { + getVecNPropertyViewImpl( + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback)); + } + return; + } + + if (isPropertyTypeMatN(type)) { + if (normalized) { + getMatNPropertyViewImpl( + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback)); + } else { + getMatNPropertyViewImpl( + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback)); + } + return; + } + + if (type == PropertyType::String) { + callback( + propertyId, + getPropertyViewImpl( + propertyId, + *pClassProperty)); + return; + } + + if (type == PropertyType::Boolean) { + callback( + propertyId, + getPropertyViewImpl(propertyId, *pClassProperty)); + return; + } + + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorTypeMismatch)); + } + + /** + * @brief Iterates over each property in the \ref PropertyTable with a + * callback that accepts a property id and a \ref PropertyTablePropertyView to + * view the data stored in the \ref PropertyTableProperty. + * + * This method will validate the EXT_structural_metadata format to ensure + * \ref PropertyTablePropertyView retrieves the correct data. T must be one of + * the following: a scalar (uint8_t, int8_t, uint16_t, int16_t, uint32_t, + * int32_t, uint64_t, int64_t, float, double), a glm vecN composed of one of + * the scalar types, a glm matN composed of one of the scalar types, bool, + * std::string_view, or \ref PropertyArrayView with T as one of the + * aforementioned types. + * + * If the property is invalid, an empty \ref PropertyTablePropertyView with + * an error status code will be passed to the callback. Otherwise, a valid + * property view will be passed to the callback. + * + * @param callback A callback function that accepts property id and + * \ref PropertyTablePropertyView + * @tparam Callback The type of the callback function. + */ + template void forEachProperty(Callback&& callback) const { + for (const auto& property : this->_pClass->properties) { + getPropertyView(property.first, std::forward(callback)); + } + } + +private: + template + void getScalarArrayPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyComponentType componentType, + Callback&& callback) const { + switch (componentType) { + case PropertyComponentType::Int8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Int16: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint16: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Int32: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint32: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Int64: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint64: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Float32: + callback( + propertyId, + getPropertyViewImpl, false>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Float64: + callback( + propertyId, + getPropertyViewImpl, false>( + propertyId, + classProperty)); + break; + default: + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorComponentTypeMismatch)); + break; + } + } + + template + void getVecNArrayPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyComponentType componentType, + Callback&& callback) const { + switch (componentType) { + case PropertyComponentType::Int8: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Uint8: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Int16: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Uint16: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Int32: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Uint32: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Int64: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Uint64: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Float32: + callback( + propertyId, + getPropertyViewImpl>, false>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Float64: + callback( + propertyId, + getPropertyViewImpl>, false>( + propertyId, + classProperty)); + break; + default: + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorComponentTypeMismatch)); + break; + } + } + + template + void getVecNArrayPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyType type, + PropertyComponentType componentType, + Callback&& callback) const { + glm::length_t N = getDimensionsFromPropertyType(type); + switch (N) { + case 2: + getVecNArrayPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + case 3: + getVecNArrayPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + case 4: + getVecNArrayPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + default: + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorTypeMismatch)); + break; + } + } + + template + void getMatNArrayPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyComponentType componentType, + Callback&& callback) const { + switch (componentType) { + case PropertyComponentType::Int8: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Uint8: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Int16: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Uint16: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Int32: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Uint32: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Int64: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Uint64: + callback( + propertyId, + getPropertyViewImpl< + PropertyArrayView>, + Normalized>(propertyId, classProperty)); + break; + case PropertyComponentType::Float32: + callback( + propertyId, + getPropertyViewImpl>, false>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Float64: + callback( + propertyId, + getPropertyViewImpl>, false>( + propertyId, + classProperty)); + break; + default: + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorComponentTypeMismatch)); + break; + } + } + + template + void getMatNArrayPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyType type, + PropertyComponentType componentType, + Callback&& callback) const { + const glm::length_t N = getDimensionsFromPropertyType(type); + switch (N) { + case 2: + getMatNArrayPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + case 3: + getMatNArrayPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + case 4: + getMatNArrayPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + default: + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorTypeMismatch)); + break; + } + } + + template + void getArrayPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyType type, + PropertyComponentType componentType, + Callback&& callback) const { + if (type == PropertyType::Scalar) { + getScalarArrayPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + } else if (isPropertyTypeVecN(type)) { + getVecNArrayPropertyViewImpl( + propertyId, + classProperty, + type, + componentType, + std::forward(callback)); + } else if (isPropertyTypeMatN(type)) { + getMatNArrayPropertyViewImpl( + propertyId, + classProperty, + type, + componentType, + std::forward(callback)); + } else if (type == PropertyType::Boolean) { + callback( + propertyId, + getPropertyViewImpl, false>( + propertyId, + classProperty)); + + } else if (type == PropertyType::String) { + callback( + propertyId, + getPropertyViewImpl, false>( + propertyId, + classProperty)); + } else { + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorTypeMismatch)); + } + } + + template + void getVecNPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyComponentType componentType, + Callback&& callback) const { + + switch (componentType) { + case PropertyComponentType::Int8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Int16: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint16: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Int32: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint32: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Int64: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint64: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Float32: + callback( + propertyId, + getPropertyViewImpl, false>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Float64: + callback( + propertyId, + getPropertyViewImpl, false>( + propertyId, + classProperty)); + break; + default: + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorComponentTypeMismatch)); + break; + } + } + + template + void getVecNPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyType type, + PropertyComponentType componentType, + Callback&& callback) const { + const glm::length_t N = getDimensionsFromPropertyType(type); + switch (N) { + case 2: + getVecNPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + case 3: + getVecNPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + case 4: + getVecNPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + default: + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorTypeMismatch)); + break; + } + } + + template + void getMatNPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyComponentType componentType, + Callback&& callback) const { + switch (componentType) { + case PropertyComponentType::Int8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Int16: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint16: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Int32: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint32: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Int64: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Uint64: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Float32: + callback( + propertyId, + getPropertyViewImpl, false>( + propertyId, + classProperty)); + break; + case PropertyComponentType::Float64: + callback( + propertyId, + getPropertyViewImpl, false>( + propertyId, + classProperty)); + break; + default: + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorComponentTypeMismatch)); + break; + } + } + + template + void getMatNPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyType type, + PropertyComponentType componentType, + Callback&& callback) const { + glm::length_t N = getDimensionsFromPropertyType(type); + switch (N) { + case 2: + getMatNPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + case 3: + getMatNPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + case 4: + getMatNPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback)); + break; + default: + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorTypeMismatch)); + break; + } + } + + template + void getScalarPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyComponentType componentType, + Callback&& callback) const { + switch (componentType) { + case PropertyComponentType::Int8: + callback( + propertyId, + getPropertyViewImpl(propertyId, classProperty)); + return; + case PropertyComponentType::Uint8: + callback( + propertyId, + getPropertyViewImpl(propertyId, classProperty)); + return; + case PropertyComponentType::Int16: + callback( + propertyId, + getPropertyViewImpl(propertyId, classProperty)); + return; + case PropertyComponentType::Uint16: + callback( + propertyId, + getPropertyViewImpl(propertyId, classProperty)); + break; + case PropertyComponentType::Int32: + callback( + propertyId, + getPropertyViewImpl(propertyId, classProperty)); + break; + case PropertyComponentType::Uint32: + callback( + propertyId, + getPropertyViewImpl(propertyId, classProperty)); + break; + case PropertyComponentType::Int64: + callback( + propertyId, + getPropertyViewImpl(propertyId, classProperty)); + break; + case PropertyComponentType::Uint64: + callback( + propertyId, + getPropertyViewImpl(propertyId, classProperty)); + break; + case PropertyComponentType::Float32: + callback( + propertyId, + getPropertyViewImpl(propertyId, classProperty)); + break; + case PropertyComponentType::Float64: + callback( + propertyId, + getPropertyViewImpl(propertyId, classProperty)); + break; + default: + callback( + propertyId, + PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorComponentTypeMismatch)); + break; + } + } + + template + PropertyTablePropertyView getPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty) const { + auto propertyTablePropertyIter = + _pPropertyTable->properties.find(propertyId); + if (propertyTablePropertyIter == _pPropertyTable->properties.end()) { + if (!classProperty.required && classProperty.defaultProperty) { + // If the property was omitted from the property table, it is still + // technically valid if it specifies a default value. Create a view that + // just returns the default value. + return PropertyTablePropertyView( + classProperty, + _pPropertyTable->count); + } + + // Otherwise, the property is erroneously nonexistent. + return PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorNonexistentProperty); + } + + const PropertyTableProperty& propertyTableProperty = + propertyTablePropertyIter->second; + + if constexpr (IsMetadataNumeric::value || IsMetadataBoolean::value) { + return getNumericOrBooleanPropertyValues( + classProperty, + propertyTableProperty); + } + + if constexpr (IsMetadataString::value) { + return getStringPropertyValues(classProperty, propertyTableProperty); + } + + if constexpr (IsMetadataBooleanArray::value) { + return getBooleanArrayPropertyValues( + classProperty, + propertyTableProperty); + } + + if constexpr (IsMetadataNumericArray::value) { + return getNumericArrayPropertyValues< + typename MetadataArrayType::type, + Normalized>(classProperty, propertyTableProperty); + } + + if constexpr (IsMetadataStringArray::value) { + return getStringArrayPropertyValues(classProperty, propertyTableProperty); + } + } + + template + PropertyTablePropertyView getNumericOrBooleanPropertyValues( + const ClassProperty& classProperty, + const PropertyTableProperty& propertyTableProperty) const { + if (classProperty.array) { + return PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorArrayTypeMismatch); + } + + const PropertyType type = convertStringToPropertyType(classProperty.type); + if (TypeToPropertyType::value != type) { + return PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorTypeMismatch); + } + const PropertyComponentType componentType = + convertStringToPropertyComponentType( + classProperty.componentType.value_or("")); + if (TypeToPropertyType::component != componentType) { + return PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorComponentTypeMismatch); + } + + if (classProperty.normalized != Normalized) { + return PropertyTablePropertyView( + PropertyTablePropertyViewStatus::ErrorNormalizationMismatch); + } + + std::span values; + const auto status = getBufferSafe(propertyTableProperty.values, values); + if (status != PropertyTablePropertyViewStatus::Valid) { + return PropertyTablePropertyView(status); + } + + if (values.size() % sizeof(T) != 0) { + return PropertyTablePropertyView( + PropertyTablePropertyViewStatus:: + ErrorBufferViewSizeNotDivisibleByTypeSize); + } + + size_t maxRequiredBytes = 0; + if (IsMetadataBoolean::value) { + maxRequiredBytes = static_cast( + glm::ceil(static_cast(_pPropertyTable->count) / 8.0)); + } else { + maxRequiredBytes = _pPropertyTable->count * sizeof(T); + } + + if (values.size() < maxRequiredBytes) { + return PropertyTablePropertyView( + PropertyTablePropertyViewStatus:: + ErrorBufferViewSizeDoesNotMatchPropertyTableCount); + } + + return PropertyTablePropertyView( + propertyTableProperty, + classProperty, + _pPropertyTable->count, + values); + } + + PropertyTablePropertyView getStringPropertyValues( + const ClassProperty& classProperty, + const PropertyTableProperty& propertyTableProperty) const; + + PropertyTablePropertyView> + getBooleanArrayPropertyValues( + const ClassProperty& classProperty, + const PropertyTableProperty& propertyTableProperty) const; + + template + PropertyTablePropertyView, Normalized> + getNumericArrayPropertyValues( + const ClassProperty& classProperty, + const PropertyTableProperty& propertyTableProperty) const { + if (!classProperty.array) { + return PropertyTablePropertyView, Normalized>( + PropertyTablePropertyViewStatus::ErrorArrayTypeMismatch); + } + + const PropertyType type = convertStringToPropertyType(classProperty.type); + if (TypeToPropertyType::value != type) { + return PropertyTablePropertyView, Normalized>( + PropertyTablePropertyViewStatus::ErrorTypeMismatch); + } + + const PropertyComponentType componentType = + convertStringToPropertyComponentType( + classProperty.componentType.value_or("")); + if (TypeToPropertyType::component != componentType) { + return PropertyTablePropertyView, Normalized>( + PropertyTablePropertyViewStatus::ErrorComponentTypeMismatch); + } + + if (classProperty.normalized != Normalized) { + return PropertyTablePropertyView, Normalized>( + PropertyTablePropertyViewStatus::ErrorNormalizationMismatch); + } + + std::span values; + auto status = getBufferSafe(propertyTableProperty.values, values); + if (status != PropertyTablePropertyViewStatus::Valid) { + return PropertyTablePropertyView, Normalized>( + status); + } + + if (values.size() % sizeof(T) != 0) { + return PropertyTablePropertyView, Normalized>( + PropertyTablePropertyViewStatus:: + ErrorBufferViewSizeNotDivisibleByTypeSize); + } + + const int64_t fixedLengthArrayCount = classProperty.count.value_or(0); + if (fixedLengthArrayCount > 0 && propertyTableProperty.arrayOffsets >= 0) { + return PropertyTablePropertyView, Normalized>( + PropertyTablePropertyViewStatus:: + ErrorArrayCountAndOffsetBufferCoexist); + } + + if (fixedLengthArrayCount <= 0 && propertyTableProperty.arrayOffsets < 0) { + return PropertyTablePropertyView, Normalized>( + PropertyTablePropertyViewStatus:: + ErrorArrayCountAndOffsetBufferDontExist); + } + + // Handle fixed-length arrays + if (fixedLengthArrayCount > 0) { + size_t maxRequiredBytes = maxRequiredBytes = static_cast( + _pPropertyTable->count * fixedLengthArrayCount * sizeof(T)); + + if (values.size() < maxRequiredBytes) { + return PropertyTablePropertyView, Normalized>( + PropertyTablePropertyViewStatus:: + ErrorBufferViewSizeDoesNotMatchPropertyTableCount); + } + + return PropertyTablePropertyView, Normalized>( + propertyTableProperty, + classProperty, + _pPropertyTable->count, + values); + } + + // Handle variable-length arrays + const PropertyComponentType arrayOffsetType = + convertArrayOffsetTypeStringToPropertyComponentType( + propertyTableProperty.arrayOffsetType); + if (arrayOffsetType == PropertyComponentType::None) { + return PropertyTablePropertyView, Normalized>( + PropertyTablePropertyViewStatus::ErrorInvalidArrayOffsetType); + } + + constexpr bool checkBitsSize = false; + std::span arrayOffsets; + status = getArrayOffsetsBufferSafe( + propertyTableProperty.arrayOffsets, + arrayOffsetType, + values.size(), + static_cast(_pPropertyTable->count), + checkBitsSize, + arrayOffsets); + if (status != PropertyTablePropertyViewStatus::Valid) { + return PropertyTablePropertyView, Normalized>( + status); + } + + if constexpr (Normalized) { + return PropertyTablePropertyView, true>( + propertyTableProperty, + classProperty, + _pPropertyTable->count, + values, + arrayOffsets, + arrayOffsetType); + } else { + return PropertyTablePropertyView, false>( + propertyTableProperty, + classProperty, + _pPropertyTable->count, + values, + arrayOffsets, + std::span(), + arrayOffsetType, + PropertyComponentType::None); + } + } + + PropertyTablePropertyView> + getStringArrayPropertyValues( + const ClassProperty& classProperty, + const PropertyTableProperty& propertyTableProperty) const; + + PropertyViewStatusType getBufferSafe( + int32_t bufferView, + std::span& buffer) const noexcept; + + PropertyViewStatusType getArrayOffsetsBufferSafe( + int32_t arrayOffsetsBufferView, + PropertyComponentType arrayOffsetType, + size_t valuesBufferSize, + size_t propertyTableCount, + bool checkBitsSize, + std::span& arrayOffsetsBuffer) const noexcept; + + PropertyViewStatusType getStringOffsetsBufferSafe( + int32_t stringOffsetsBufferView, + PropertyComponentType stringOffsetType, + size_t valuesBufferSize, + size_t propertyTableCount, + std::span& stringOffsetsBuffer) const noexcept; + + const Model* _pModel; + const PropertyTable* _pPropertyTable; + const Class* _pClass; + PropertyTableViewStatus _status; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTexture.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTexture.h new file mode 100644 index 0000000..31a6215 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTexture.h @@ -0,0 +1,71 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief Properties conforming to a class, organized as property values stored + * in textures. + */ +struct CESIUMGLTF_API PropertyTexture final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "PropertyTexture"; + + /** + * @brief The name of the property texture, e.g. for display purposes. + */ + std::optional name; + + /** + * @brief The class that property values conform to. The value must be a class + * ID declared in the `classes` dictionary. + */ + std::string classProperty; + + /** + * @brief A dictionary, where each key corresponds to a property ID in the + * class' `properties` dictionary and each value is an object describing where + * property values are stored. Required properties must be included in this + * dictionary. + */ + std::unordered_map + properties; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(PropertyTexture)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + accum += int64_t(this->classProperty.capacity() * sizeof(char)); + accum += int64_t( + this->properties.bucket_count() * + (sizeof(std::string) + sizeof(CesiumGltf::PropertyTextureProperty))); + for (const auto& [k, v] : this->properties) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - + int64_t(sizeof(CesiumGltf::PropertyTextureProperty)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTextureProperty.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTextureProperty.h new file mode 100644 index 0000000..3c74274 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTextureProperty.h @@ -0,0 +1,75 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief A texture containing property values. + */ +struct CESIUMGLTF_API PropertyTextureProperty final : public TextureInfo { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "PropertyTextureProperty"; + + /** + * @brief Texture channels containing property values, identified by index. + * The values may be packed into multiple channels if a single channel does + * not have sufficient bit depth. The values are packed in little-endian + * order. + */ + std::vector channels = {0}; + + /** + * @brief An offset to apply to property values. Only applicable when the + * component type is `FLOAT32` or `FLOAT64`, or when the property is + * `normalized`. Overrides the class property's `offset` if both are defined. + */ + std::optional offset; + + /** + * @brief A scale to apply to property values. Only applicable when the + * component type is `FLOAT32` or `FLOAT64`, or when the property is + * `normalized`. Overrides the class property's `scale` if both are defined. + */ + std::optional scale; + + /** + * @brief Maximum value present in the property values. Only applicable to + * `SCALAR`, `VECN`, and `MATN` types. This is the maximum of all property + * values, after the transforms based on the `normalized`, `offset`, and + * `scale` properties have been applied. + */ + std::optional max; + + /** + * @brief Minimum value present in the property values. Only applicable to + * `SCALAR`, `VECN`, and `MATN` types. This is the minimum of all property + * values, after the transforms based on the `normalized`, `offset`, and + * `scale` properties have been applied. + */ + std::optional min; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(PropertyTextureProperty)); + accum += TextureInfo::getSizeBytes() - int64_t(sizeof(TextureInfo)); + accum += int64_t(sizeof(int64_t) * this->channels.capacity()); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTexturePropertyView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTexturePropertyView.h new file mode 100644 index 0000000..52583ab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTexturePropertyView.h @@ -0,0 +1,726 @@ +#pragma once + +#include "CesiumGltf/ImageAsset.h" +#include "CesiumGltf/KhrTextureTransform.h" +#include "CesiumGltf/PropertyTextureProperty.h" +#include "CesiumGltf/PropertyTransformations.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumGltf/PropertyView.h" +#include "CesiumGltf/Sampler.h" +#include "CesiumGltf/TextureView.h" + +#include + +#include +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief Indicates the status of a property texture property view. + * + * The {@link PropertyTexturePropertyView} constructor always completes + * successfully. However it may not always reflect the actual content of the + * corresponding property texture property. This enumeration provides the + * reason. + */ +class PropertyTexturePropertyViewStatus : public PropertyViewStatus { +public: + /** + * @brief This property view was initialized from an invalid + * {@link PropertyTexture}. + */ + static const int ErrorInvalidPropertyTexture = 14; + + /** + * @brief This property view is associated with a {@link ClassProperty} of an + * unsupported type. + */ + static const int ErrorUnsupportedProperty = 15; + + /** + * @brief This property view does not have a valid texture index. + */ + static const int ErrorInvalidTexture = 16; + + /** + * @brief This property view does not have a valid sampler index. + */ + static const int ErrorInvalidSampler = 17; + + /** + * @brief This property view does not have a valid image index. + */ + static const int ErrorInvalidImage = 18; + + /** + * @brief This property is viewing an empty image. + */ + static const int ErrorEmptyImage = 19; + + /** + * @brief This property uses an image with multi-byte channels. Only + * single-byte channels are supported. + */ + static const int ErrorInvalidBytesPerChannel = 20; + + /** + * @brief The channels of this property texture property are invalid. + * Channels must be in the range 0-N, where N is the number of available + * channels in the image. There must be a minimum of one channel. Although + * more than four channels can be defined for specialized texture + * formats, this implementation only supports four channels max. + */ + static const int ErrorInvalidChannels = 21; + + /** + * @brief The channels of this property texture property do not provide + * the exact number of bytes required by the property type. This may be + * because an incorrect number of channels was provided, or because the + * image itself has a different channel count / byte size than expected. + */ + static const int ErrorChannelsAndTypeMismatch = 22; +}; + +/** + * @brief Attempts to obtain a scalar value from the given span of bytes. + * + * @tparam ElementType The scalar value type to read from `bytes`. + * @param bytes A span of bytes to convert into a scalar value. + * @returns A value of `ElementType`. + */ +template +ElementType assembleScalarValue(const std::span bytes) noexcept { + if constexpr (std::is_same_v) { + CESIUM_ASSERT( + bytes.size() == sizeof(float) && + "Not enough channel inputs to construct a float."); + uint32_t resultAsUint = 0; + for (size_t i = 0; i < bytes.size(); i++) { + resultAsUint |= static_cast(bytes[i]) << i * 8; + } + + // Reinterpret the bits as a float. + return *reinterpret_cast(&resultAsUint); + } + + if constexpr (IsMetadataInteger::value) { + using UintType = std::make_unsigned_t; + UintType resultAsUint = 0; + for (size_t i = 0; i < bytes.size(); i++) { + resultAsUint |= static_cast(bytes[i]) << i * 8; + } + + // Reinterpret the bits with the correct signedness. + return *reinterpret_cast(&resultAsUint); + } +} + +/** + * @brief Attempts to obtain a vector value from the given span of bytes. + * + * @tparam ElementType The vector value type to read from `bytes`. + * @param bytes A span of bytes to convert into a vector value. + * @returns A value of `ElementType`. + */ +template +ElementType assembleVecNValue(const std::span bytes) noexcept { + ElementType result = ElementType(); + + const glm::length_t N = + getDimensionsFromPropertyType(TypeToPropertyType::value); + using T = typename ElementType::value_type; + + CESIUM_ASSERT( + sizeof(T) <= 2 && "Components cannot be larger than two bytes in size."); + + if constexpr (std::is_same_v) { + CESIUM_ASSERT( + N == 2 && "Only vec2s can contain two-byte integer components."); + uint16_t x = static_cast(bytes[0]) | + (static_cast(bytes[1]) << 8); + uint16_t y = static_cast(bytes[2]) | + (static_cast(bytes[3]) << 8); + + result[0] = *reinterpret_cast(&x); + result[1] = *reinterpret_cast(&y); + } + + if constexpr (std::is_same_v) { + CESIUM_ASSERT( + N == 2 && "Only vec2s can contain two-byte integer components."); + result[0] = static_cast(bytes[0]) | + (static_cast(bytes[1]) << 8); + result[1] = static_cast(bytes[2]) | + (static_cast(bytes[3]) << 8); + } + + if constexpr (std::is_same_v) { + for (size_t i = 0; i < bytes.size(); i++) { + result[i] = *reinterpret_cast(&bytes[i]); + } + } + + if constexpr (std::is_same_v) { + for (size_t i = 0; i < bytes.size(); i++) { + result[i] = bytes[i]; + } + } + + return result; +} + +/** + * @brief Attempts to obtain an array value from the given span of bytes. + * + * @tparam T The element type to read from `bytes`. + * @param bytes A span of bytes to convert into an array value. + * @returns A \ref PropertyArrayCopy containing the elements read. + */ +template +PropertyArrayCopy +assembleArrayValue(const std::span bytes) noexcept { + std::vector result(bytes.size() / sizeof(T)); + + if constexpr (sizeof(T) == 2) { + for (int i = 0, b = 0; i < result.size(); i++, b += 2) { + using UintType = std::make_unsigned_t; + UintType resultAsUint = static_cast(bytes[b]) | + (static_cast(bytes[b + 1]) << 8); + result[i] = *reinterpret_cast(&resultAsUint); + } + } else { + for (size_t i = 0; i < bytes.size(); i++) { + result[i] = *reinterpret_cast(&bytes[i]); + } + } + + return PropertyArrayCopy(std::move(result)); +} + +/** + * @brief Assembles the given type from the provided channel values of sampling + * a texture. + * + * @tparam ElementType The type of element to assemble. + * @param bytes The byte values of the sampled channels of the texture. + * @returns The result of \ref assembleScalarValue, \ref assembleVecNValue, or + * \ref assembleArrayValue depending on `ElementType`. + */ +template +PropertyValueViewToCopy +assembleValueFromChannels(const std::span bytes) noexcept { + CESIUM_ASSERT( + bytes.size() > 0 && "Channel input must have at least one value."); + + if constexpr (IsMetadataScalar::value) { + return assembleScalarValue(bytes); + } + + if constexpr (IsMetadataVecN::value) { + return assembleVecNValue(bytes); + } + + if constexpr (IsMetadataArray::value) { + return assembleArrayValue::type>( + bytes); + } +} + +#pragma region Non - normalized property + +/** + * @brief A view of the data specified by a {@link PropertyTextureProperty}. + * + * Provides utilities to sample the property texture property using texture + * coordinates. Property values are retrieved from the NEAREST texel without + * additional filtering applied. + * + * @tparam ElementType The type of the elements represented in the property + * view + * @tparam Normalized Whether or not the property is normalized. If + * normalized, the elements can be retrieved as normalized floating-point + * numbers, as opposed to their integer values. + */ +template +class PropertyTexturePropertyView; + +/** + * @brief A view of the non-normalized data specified by a + * {@link PropertyTextureProperty}. + * + * Provides utilities to sample the property texture property using texture + * coordinates. + * + * @tparam ElementType The type of the elements represented in the property view + */ +template +class PropertyTexturePropertyView + : public PropertyView, public TextureView { +public: + /** + * @brief Constructs an invalid instance for a non-existent property. + */ + PropertyTexturePropertyView() noexcept + : PropertyView(), + TextureView(), + _channels(), + _swizzle() {} + + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The code from {@link PropertyTexturePropertyViewStatus} indicating the error with the property. + */ + PropertyTexturePropertyView(PropertyViewStatusType status) noexcept + : PropertyView(status), + TextureView(), + _channels(), + _swizzle() { + CESIUM_ASSERT( + this->_status != PropertyTexturePropertyViewStatus::Valid && + "An empty property view should not be constructed with a valid status"); + } + + /** + * @brief Constructs an instance of an empty property that specifies a default + * value. Although this property has no data, it can return the default value + * when \ref get is called. However, \ref getRaw cannot be used. + * + * @param classProperty The {@link ClassProperty} this property conforms to. + */ + PropertyTexturePropertyView(const ClassProperty& classProperty) noexcept + : PropertyView(classProperty), + TextureView(), + _channels(), + _swizzle() { + if (this->_status != PropertyTexturePropertyViewStatus::Valid) { + // Don't override the status / size if something is wrong with the class + // property's definition. + return; + } + + if (!classProperty.defaultProperty) { + // This constructor should only be called if the class property *has* a + // default value. But in the case that it does not, this property view + // becomes invalid. + this->_status = + PropertyTexturePropertyViewStatus::ErrorNonexistentProperty; + return; + } + + this->_status = PropertyTexturePropertyViewStatus::EmptyPropertyWithDefault; + } + + /** + * @brief Construct a view of the data specified by a {@link PropertyTextureProperty}. + * + * @param property The {@link PropertyTextureProperty} + * @param classProperty The {@link ClassProperty} this property conforms to. + * @param sampler The {@link Sampler} used by the property. + * @param image The {@link ImageAsset} used by the property. + * @param options The options for constructing the view. + */ + PropertyTexturePropertyView( + const PropertyTextureProperty& property, + const ClassProperty& classProperty, + const Sampler& sampler, + const ImageAsset& image, + const TextureViewOptions& options = TextureViewOptions()) noexcept + : PropertyView(classProperty, property), + TextureView( + sampler, + image, + property.texCoord, + property.getExtension(), + options), + _channels(property.channels), + _swizzle() { + if (this->_status != PropertyTexturePropertyViewStatus::Valid) { + return; + } + + switch (this->getTextureViewStatus()) { + case TextureViewStatus::Valid: + break; + case TextureViewStatus::ErrorInvalidSampler: + this->_status = PropertyTexturePropertyViewStatus::ErrorInvalidSampler; + return; + case TextureViewStatus::ErrorInvalidImage: + this->_status = PropertyTexturePropertyViewStatus::ErrorInvalidImage; + return; + case TextureViewStatus::ErrorEmptyImage: + this->_status = PropertyTexturePropertyViewStatus::ErrorEmptyImage; + return; + case TextureViewStatus::ErrorInvalidBytesPerChannel: + this->_status = + PropertyTexturePropertyViewStatus::ErrorInvalidBytesPerChannel; + return; + case TextureViewStatus::ErrorUninitialized: + case TextureViewStatus::ErrorInvalidTexture: + default: + this->_status = PropertyTexturePropertyViewStatus::ErrorInvalidTexture; + return; + } + + _swizzle.reserve(_channels.size()); + + for (size_t i = 0; i < _channels.size(); ++i) { + switch (_channels[i]) { + case 0: + _swizzle += "r"; + break; + case 1: + _swizzle += "g"; + break; + case 2: + _swizzle += "b"; + break; + case 3: + _swizzle += "a"; + break; + default: + CESIUM_ASSERT( + false && "A valid channels vector must be passed to the view."); + } + } + } + + /** + * @brief Gets the value of the property for the given texture coordinates + * with all value transforms applied. That is, if the property specifies an + * offset and scale, they will be applied to the value before the value is + * returned. The sampler's wrapping mode will be used when sampling the + * texture. + * + * If this property has a specified "no data" value, this will return the + * property's default value for any elements that equal this "no data" value. + * If the property did not specify a default value, this returns std::nullopt. + * + * @param u The u-component of the texture coordinates. + * @param v The v-component of the texture coordinates. + * + * @return The value of the element, or std::nullopt if it matches the "no + * data" value + */ + std::optional> + get(double u, double v) const noexcept { + if (this->_status == + PropertyTexturePropertyViewStatus::EmptyPropertyWithDefault) { + return propertyValueViewToCopy(this->defaultValue()); + } + + PropertyValueViewToCopy value = getRaw(u, v); + + if (value == this->noData()) { + return propertyValueViewToCopy(this->defaultValue()); + } else if constexpr (IsMetadataNumeric::value) { + return transformValue(value, this->offset(), this->scale()); + } else if constexpr (IsMetadataNumericArray::value) { + return transformArray( + propertyValueCopyToView(value), + this->offset(), + this->scale()); + } else { + return value; + } + } + + /** + * @brief Gets the raw value of the property for the given texture + * coordinates. The sampler's wrapping mode will be used when sampling the + * texture. + * + * If this property has a specified "no data" value, the raw value will still + * be returned, even if it equals the "no data" value. + * + * @param u The u-component of the texture coordinates. + * @param v The v-component of the texture coordinates. + * + * @return The value at the nearest pixel to the texture coordinates. + */ + + PropertyValueViewToCopy + getRaw(double u, double v) const noexcept { + CESIUM_ASSERT( + this->_status == PropertyTexturePropertyViewStatus::Valid && + "Check the status() first to make sure view is valid"); + + std::vector sample = + this->sampleNearestPixel(u, v, this->_channels); + + return assembleValueFromChannels( + std::span(sample.data(), this->_channels.size())); + } + + /** + * @brief Gets the channels of this property texture property. + */ + const std::vector& getChannels() const noexcept { + return this->_channels; + } + + /** + * @brief Gets this property's channels as a swizzle string. + */ + const std::string& getSwizzle() const noexcept { return this->_swizzle; } + +private: + std::vector _channels; + std::string _swizzle; +}; + +#pragma endregion + +#pragma region Normalized property + +/** + * @brief A view of the normalized data specified by a + * {@link PropertyTextureProperty}. + * + * Provides utilities to sample the property texture property using texture + * coordinates. + */ +template +class PropertyTexturePropertyView + : public PropertyView, public TextureView { +private: + using NormalizedType = typename TypeToNormalizedType::type; + +public: + /** + * @brief Constructs an invalid instance for a non-existent property. + */ + PropertyTexturePropertyView() noexcept + : PropertyView(), + TextureView(), + _channels(), + _swizzle() {} + + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The code from {@link PropertyTexturePropertyViewStatus} indicating the error with the property. + */ + PropertyTexturePropertyView(PropertyViewStatusType status) noexcept + : PropertyView(status), + TextureView(), + _channels(), + _swizzle() { + CESIUM_ASSERT( + this->_status != PropertyTexturePropertyViewStatus::Valid && + "An empty property view should not be constructed with a valid " + "status"); + } + + /** + * @brief Constructs an instance of an empty property that specifies a + * default value. Although this property has no data, it can return the + * default value when {@link PropertyTexturePropertyView::get} is called. + * However, {@link PropertyTexturePropertyView::getRaw} cannot be used. + * + * @param classProperty The {@link ClassProperty} this property conforms to. + */ + PropertyTexturePropertyView(const ClassProperty& classProperty) noexcept + : PropertyView(classProperty), + TextureView(), + _channels(), + _swizzle() { + if (this->_status != PropertyTexturePropertyViewStatus::Valid) { + // Don't override the status / size if something is wrong with the class + // property's definition. + return; + } + + if (!classProperty.defaultProperty) { + // This constructor should only be called if the class property *has* a + // default value. But in the case that it does not, this property view + // becomes invalid. + this->_status = + PropertyTexturePropertyViewStatus::ErrorNonexistentProperty; + return; + } + + this->_status = PropertyTexturePropertyViewStatus::EmptyPropertyWithDefault; + } + + /** + * @brief Construct a view of the data specified by a {@link PropertyTextureProperty}. + * + * @param property The {@link PropertyTextureProperty} + * @param classProperty The {@link ClassProperty} this property conforms to. + * @param sampler The {@link Sampler} used by the property. + * @param image The {@link ImageAsset} used by the property. + * @param options The options for constructing the view. + */ + PropertyTexturePropertyView( + const PropertyTextureProperty& property, + const ClassProperty& classProperty, + const Sampler& sampler, + const ImageAsset& image, + const TextureViewOptions& options = TextureViewOptions()) noexcept + : PropertyView(classProperty, property), + TextureView( + sampler, + image, + property.texCoord, + property.getExtension(), + options), + _channels(property.channels), + _swizzle() { + if (this->_status != PropertyTexturePropertyViewStatus::Valid) { + return; + } + + switch (this->getTextureViewStatus()) { + case TextureViewStatus::Valid: + break; + case TextureViewStatus::ErrorInvalidSampler: + this->_status = PropertyTexturePropertyViewStatus::ErrorInvalidSampler; + return; + case TextureViewStatus::ErrorInvalidImage: + this->_status = PropertyTexturePropertyViewStatus::ErrorInvalidImage; + return; + case TextureViewStatus::ErrorEmptyImage: + this->_status = PropertyTexturePropertyViewStatus::ErrorEmptyImage; + return; + case TextureViewStatus::ErrorInvalidBytesPerChannel: + this->_status = + PropertyTexturePropertyViewStatus::ErrorInvalidBytesPerChannel; + return; + case TextureViewStatus::ErrorUninitialized: + case TextureViewStatus::ErrorInvalidTexture: + default: + this->_status = PropertyTexturePropertyViewStatus::ErrorInvalidTexture; + return; + } + + _swizzle.reserve(_channels.size()); + for (size_t i = 0; i < _channels.size(); ++i) { + switch (_channels[i]) { + case 0: + _swizzle += "r"; + break; + case 1: + _swizzle += "g"; + break; + case 2: + _swizzle += "b"; + break; + case 3: + _swizzle += "a"; + break; + default: + CESIUM_ASSERT( + false && "A valid channels vector must be passed to the view."); + } + } + } + + /** + * @brief Gets the value of the property for the given texture coordinates + * with all value transforms applied. That is, if the property specifies an + * offset and scale, they will be applied to the value before the value is + * returned. The sampler's wrapping mode will be used when sampling the + * texture. + * + * If this property has a specified "no data" value, and the retrieved + * element is equal to that value, then this will return the property's + * specified default value. If the property did not provide a default value, + * this returns std::nullopt. + * + * @param u The u-component of the texture coordinates. + * @param v The v-component of the texture coordinates. + * + * @return The value of the element, or std::nullopt if it matches the "no + * data" value + */ + std::optional> + get(double u, double v) const noexcept { + if (this->_status == + PropertyTexturePropertyViewStatus::EmptyPropertyWithDefault) { + return propertyValueViewToCopy(this->defaultValue()); + } + + PropertyValueViewToCopy value = getRaw(u, v); + + if (value == this->noData()) { + return propertyValueViewToCopy(this->defaultValue()); + } else if constexpr (IsMetadataScalar::value) { + return transformValue( + normalize(value), + this->offset(), + this->scale()); + } else if constexpr (IsMetadataVecN::value) { + constexpr glm::length_t N = ElementType::length(); + using T = typename ElementType::value_type; + using NormalizedT = typename NormalizedType::value_type; + return transformValue>( + normalize(value), + this->offset(), + this->scale()); + } else if constexpr (IsMetadataArray::value) { + using ArrayElementType = typename MetadataArrayType::type; + if constexpr (IsMetadataScalar::value) { + return transformNormalizedArray( + propertyValueCopyToView(value), + this->offset(), + this->scale()); + } else if constexpr (IsMetadataVecN::value) { + constexpr glm::length_t N = ArrayElementType::length(); + using T = typename ArrayElementType::value_type; + return transformNormalizedVecNArray( + propertyValueCopyToView(value), + this->offset(), + this->scale()); + } + } + } + + /** + * @brief Gets the raw value of the property for the given texture + * coordinates. The sampler's wrapping mode will be used when sampling the + * texture. + * + * If this property has a specified "no data" value, the raw value will + * still be returned, even if it equals the "no data" value. + * + * @param u The u-component of the texture coordinates. + * @param v The v-component of the texture coordinates. + * + * @return The value at the nearest pixel to the texture coordinates. + */ + + PropertyValueViewToCopy + getRaw(double u, double v) const noexcept { + CESIUM_ASSERT( + this->_status == PropertyTexturePropertyViewStatus::Valid && + "Check the status() first to make sure view is valid"); + + std::vector sample = + this->sampleNearestPixel(u, v, this->_channels); + + return assembleValueFromChannels( + std::span(sample.data(), this->_channels.size())); + } + + /** + * @brief Gets the channels of this property texture property. + */ + const std::vector& getChannels() const noexcept { + return this->_channels; + } + + /** + * @brief Gets this property's channels as a swizzle string. + */ + const std::string& getSwizzle() const noexcept { return this->_swizzle; } + +private: + std::vector _channels; + std::string _swizzle; +}; +#pragma endregion + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTextureView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTextureView.h new file mode 100644 index 0000000..d5d35c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTextureView.h @@ -0,0 +1,794 @@ +#pragma once + +#include "CesiumGltf/Class.h" +#include "CesiumGltf/ClassProperty.h" +#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltf/PropertyTexture.h" +#include "CesiumGltf/PropertyTexturePropertyView.h" +#include "CesiumGltf/TextureView.h" + +namespace CesiumGltf { +/** + * @brief Indicates the status of a property texture view. + * + * The {@link PropertyTextureView} constructor always completes successfully. + * However it may not always reflect the actual content of the + * {@link PropertyTexture}. This enumeration provides the reason. + */ +enum class PropertyTextureViewStatus { + /** + * @brief This property texture view is valid and ready to use. + */ + Valid, + + /** + * @brief The glTF is missing the EXT_structural_metadata extension. + */ + ErrorMissingMetadataExtension, + + /** + * @brief The glTF EXT_structural_metadata extension doesn't contain a schema. + */ + ErrorMissingSchema, + + /** + * @brief The property texture's specified class could not be found in the + * extension. + */ + ErrorClassNotFound +}; + +/** + * @brief A view on a {@link PropertyTexture}. + * + * This should be used to get a {@link PropertyTexturePropertyView} of a property + * in the property texture. It will validate the EXT_structural_metadata format + * and + * ensure {@link PropertyTexturePropertyView} does not access data out of bounds. + */ +class PropertyTextureView { +public: + /** + * @brief Construct a PropertyTextureView. + * + * @param model The glTF that contains the property texture's data. + * @param propertyTexture The {@link PropertyTexture} + * from which the view will retrieve data. + */ + PropertyTextureView( + const Model& model, + const PropertyTexture& propertyTexture) noexcept; + + /** + * @brief Gets the status of this property texture view. + * + * Indicates whether the view accurately reflects the property texture's data, + * or whether an error occurred. + */ + PropertyTextureViewStatus status() const noexcept { return this->_status; } + + /** + * @brief Gets the name of the property texture being viewed. Returns + * std::nullopt if no name was specified. + */ + const std::optional& name() const noexcept { + return _pPropertyTexture->name; + } + + /** + * @brief Gets the {@link Class} that this property texture conforms to. + * + * @return A pointer to the {@link Class}. Returns nullptr if the PropertyTexture + * did not specify a valid class. + */ + const Class* getClass() const noexcept { return _pClass; } + + /** + * @brief Finds the {@link ClassProperty} that + * describes the type information of the property with the specified id. + * @param propertyId The id of the property to retrieve the class for. + * @return A pointer to the {@link ClassProperty}. + * Return nullptr if the PropertyTextureView is invalid or if no class + * property was found. + */ + const ClassProperty* getClassProperty(const std::string& propertyId) const; + + /** + * @brief Gets a {@link PropertyTexturePropertyView} that views the data of a + * property stored in the {@link PropertyTexture}. + * + * This method will validate the EXT_structural_metadata format to ensure + * {@link PropertyTexturePropertyView} retrieves the correct data. T must + * be a scalar with a supported component type (int8_t, uint8_t, int16_t, + * uint16_t, int32_t, uint32_t, float), a glm vecN composed of one of the + * scalar types, or a PropertyArrayView containing one of the scalar types. + * + * If T does not match the type specified by the class property, this returns + * an invalid PropertyTexturePropertyView. Likewise, if the value of + * Normalized does not match the value of {@link ClassProperty::normalized} for that + * class property, this returns an invalid property view. Only types with + * integer components may be normalized. + * + * @tparam T The C++ type corresponding to the type of the data retrieved. + * @tparam Normalized Whether the property is normalized. Only applicable to + * types with integer components. + * @param propertyId The ID of the property to retrieve data from + * @param propertyOptions The options to apply to the property. + * @return A {@link PropertyTexturePropertyView} of the property. If no valid + * property is found, the property view will be invalid. + */ + template + PropertyTexturePropertyView getPropertyView( + const std::string& propertyId, + const TextureViewOptions& propertyOptions = TextureViewOptions()) const { + if (this->_status != PropertyTextureViewStatus::Valid) { + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorInvalidPropertyTexture); + } + + const ClassProperty* pClassProperty = getClassProperty(propertyId); + if (!pClassProperty) { + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorNonexistentProperty); + } + + return getPropertyViewImpl( + propertyId, + *pClassProperty, + propertyOptions); + } + + /** + * @brief Gets a {@link PropertyTexturePropertyView} through a callback that accepts a + * property id and a {@link PropertyTexturePropertyView} that views the data + * of the property with the specified id. + * + * This method will validate the EXT_structural_metadata format to ensure + * {@link PropertyTexturePropertyView} retrieves the correct data. T must + * be a scalar with a supported component type (int8_t, uint8_t, int16_t, + * uint16_t, int32_t, uint32_t, float), a glm vecN composed of one of the + * scalar types, or a PropertyArrayView containing one of the scalar types. + * + * If the property is somehow invalid, an empty {@link PropertyTexturePropertyView} + * with an error status will be passed to the callback. Otherwise, a valid + * property view will be passed to the callback. + * + * @param propertyId The id of the property to retrieve data from + * @param callback A callback function that accepts a property id and a + * {@link PropertyTexturePropertyView} + * @param propertyOptions The options to apply to the property. + * @tparam Callback The type of the callback function. + */ + template + void getPropertyView( + const std::string& propertyId, + Callback&& callback, + const TextureViewOptions& propertyOptions = TextureViewOptions()) const { + if (this->_status != PropertyTextureViewStatus::Valid) { + callback( + propertyId, + PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorInvalidPropertyTexture)); + return; + } + + const ClassProperty* pClassProperty = getClassProperty(propertyId); + if (!pClassProperty) { + callback( + propertyId, + PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorNonexistentProperty)); + return; + } + + PropertyType type = convertStringToPropertyType(pClassProperty->type); + PropertyComponentType componentType = PropertyComponentType::None; + if (pClassProperty->componentType) { + componentType = + convertStringToPropertyComponentType(*pClassProperty->componentType); + } + + bool normalized = pClassProperty->normalized; + if (normalized && !isPropertyComponentTypeInteger(componentType)) { + // Only integer components may be normalized. + callback( + propertyId, + PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorInvalidNormalization)); + return; + } + + if (pClassProperty->array) { + if (normalized) { + getArrayPropertyViewImpl( + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback), + propertyOptions); + } else { + getArrayPropertyViewImpl( + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback), + propertyOptions); + } + return; + } + + if (type == PropertyType::Scalar) { + if (normalized) { + getScalarPropertyViewImpl( + propertyId, + *pClassProperty, + componentType, + std::forward(callback), + propertyOptions); + } else { + getScalarPropertyViewImpl( + propertyId, + *pClassProperty, + componentType, + std::forward(callback), + propertyOptions); + } + return; + } + + if (isPropertyTypeVecN(type)) { + if (normalized) { + getVecNPropertyViewImpl( + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback), + propertyOptions); + } else { + getVecNPropertyViewImpl( + propertyId, + *pClassProperty, + type, + componentType, + std::forward(callback), + propertyOptions); + } + return; + } + + callback( + propertyId, + PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty)); + return; + } + + /** + * @brief Iterates over each property in the {@link PropertyTexture} with a callback + * that accepts a property id and a {@link PropertyTexturePropertyView} to view + * the data stored in the {@link PropertyTextureProperty}. + * + * This method will validate the EXT_structural_metadata format to ensure + * {@link PropertyTexturePropertyView} retrieves the correct data. T must be + * a scalar with a supported component type (int8_t, uint8_t, int16_t, + * uint16_t, int32_t, uint32_t, float), a glm vecN composed of one of the + * scalar types, or a PropertyArrayView containing one of the scalar types. + * + * If the property is invalid, an empty {@link PropertyTexturePropertyView} with an + * error status will be passed to the callback. Otherwise, a valid property + * view will be passed to the callback. + * + * @param callback A callback function that accepts property id and + * {@link PropertyTexturePropertyView} + * @param propertyOptions The options to apply to each property in the + * property texture. + * @tparam Callback The type of the callback function. + */ + + template + void forEachProperty( + Callback&& callback, + const TextureViewOptions& propertyOptions = TextureViewOptions()) const { + for (const auto& property : this->_pClass->properties) { + getPropertyView( + property.first, + std::forward(callback), + propertyOptions); + } + } + +private: + template + PropertyTexturePropertyView getPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + const TextureViewOptions& propertyOptions) const { + auto propertyTexturePropertyIter = + _pPropertyTexture->properties.find(propertyId); + if (propertyTexturePropertyIter == _pPropertyTexture->properties.end()) { + if (!classProperty.required && classProperty.defaultProperty) { + // If the property was omitted from the property texture, it is still + // technically valid if it specifies a default value. Create a view that + // just returns the default value. + return PropertyTexturePropertyView(classProperty); + } + + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorNonexistentProperty); + } + + const PropertyTextureProperty& propertyTextureProperty = + propertyTexturePropertyIter->second; + + if constexpr (IsMetadataScalar::value) { + return createScalarPropertyView( + classProperty, + propertyTextureProperty, + propertyOptions); + } + + if constexpr (IsMetadataVecN::value) { + return createVecNPropertyView( + classProperty, + propertyTextureProperty, + propertyOptions); + } + + if constexpr (IsMetadataArray::value) { + return createArrayPropertyView< + typename MetadataArrayType::type, + Normalized>(classProperty, propertyTextureProperty, propertyOptions); + } + } + + template + void getArrayPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyType type, + PropertyComponentType componentType, + Callback&& callback, + const TextureViewOptions& propertyOptions) const { + // Only scalar arrays are supported. + if (type != PropertyType::Scalar) { + callback( + propertyId, + PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty)); + return; + } + + int64_t count = classProperty.count.value_or(0); + if (count <= 0 || count > 4) { + callback( + propertyId, + PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty)); + return; + } + + switch (componentType) { + case PropertyComponentType::Int8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty, + propertyOptions)); + break; + case PropertyComponentType::Uint8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty, + propertyOptions)); + break; + case PropertyComponentType::Int16: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty, + propertyOptions)); + break; + case PropertyComponentType::Uint16: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty, + propertyOptions)); + break; + default: + callback( + propertyId, + PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty)); + break; + } + } + + template + void getScalarPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyComponentType componentType, + Callback&& callback, + const TextureViewOptions& propertyOptions) const { + switch (componentType) { + case PropertyComponentType::Int8: + callback( + propertyId, + getPropertyViewImpl( + propertyId, + classProperty, + propertyOptions)); + return; + case PropertyComponentType::Uint8: + callback( + propertyId, + getPropertyViewImpl( + propertyId, + classProperty, + propertyOptions)); + return; + case PropertyComponentType::Int16: + callback( + propertyId, + getPropertyViewImpl( + propertyId, + classProperty, + propertyOptions)); + return; + case PropertyComponentType::Uint16: + callback( + propertyId, + getPropertyViewImpl( + propertyId, + classProperty, + propertyOptions)); + break; + case PropertyComponentType::Int32: + callback( + propertyId, + getPropertyViewImpl( + propertyId, + classProperty, + propertyOptions)); + break; + case PropertyComponentType::Uint32: + callback( + propertyId, + getPropertyViewImpl( + propertyId, + classProperty, + propertyOptions)); + break; + case PropertyComponentType::Float32: + callback( + propertyId, + getPropertyViewImpl( + propertyId, + classProperty, + propertyOptions)); + break; + default: + callback( + propertyId, + PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty)); + break; + } + } + + template + void getVecNPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyComponentType componentType, + Callback&& callback, + const TextureViewOptions& propertyOptions) const { + switch (componentType) { + case PropertyComponentType::Int8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty, + propertyOptions)); + break; + case PropertyComponentType::Uint8: + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty, + propertyOptions)); + break; + case PropertyComponentType::Int16: + if constexpr (N == 2) { + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty, + propertyOptions)); + break; + } + [[fallthrough]]; + case PropertyComponentType::Uint16: + if constexpr (N == 2) { + callback( + propertyId, + getPropertyViewImpl, Normalized>( + propertyId, + classProperty, + propertyOptions)); + break; + } + [[fallthrough]]; + default: + callback( + propertyId, + PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty)); + break; + } + } + + template + void getVecNPropertyViewImpl( + const std::string& propertyId, + const ClassProperty& classProperty, + PropertyType type, + PropertyComponentType componentType, + Callback&& callback, + const TextureViewOptions& propertyOptions) const { + const glm::length_t N = getDimensionsFromPropertyType(type); + switch (N) { + case 2: + getVecNPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback), + propertyOptions); + break; + case 3: + getVecNPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback), + propertyOptions); + break; + case 4: + getVecNPropertyViewImpl( + propertyId, + classProperty, + componentType, + std::forward(callback), + propertyOptions); + break; + default: + callback( + propertyId, + PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorTypeMismatch)); + break; + } + } + + template + PropertyTexturePropertyView createScalarPropertyView( + const ClassProperty& classProperty, + [[maybe_unused]] const PropertyTextureProperty& propertyTextureProperty, + const TextureViewOptions& propertyOptions) const { + if (classProperty.array) { + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorArrayTypeMismatch); + } + + const PropertyType type = convertStringToPropertyType(classProperty.type); + if (TypeToPropertyType::value != type) { + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorTypeMismatch); + } + + const PropertyComponentType componentType = + convertStringToPropertyComponentType( + classProperty.componentType.value_or("")); + if (TypeToPropertyType::component != componentType) { + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorComponentTypeMismatch); + } + + if (classProperty.normalized != Normalized) { + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorNormalizationMismatch); + } + + // Only up to four bytes of image data are supported. + if constexpr (sizeof(T) <= 4) { + return createPropertyViewImpl( + classProperty, + propertyTextureProperty, + sizeof(T), + propertyOptions); + } else { + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty); + } + } + + template + PropertyTexturePropertyView createVecNPropertyView( + const ClassProperty& classProperty, + [[maybe_unused]] const PropertyTextureProperty& propertyTextureProperty, + [[maybe_unused]] const TextureViewOptions& propertyOptions) const { + if (classProperty.array) { + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorArrayTypeMismatch); + } + + const PropertyType type = convertStringToPropertyType(classProperty.type); + if (TypeToPropertyType::value != type) { + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorTypeMismatch); + } + + const PropertyComponentType componentType = + convertStringToPropertyComponentType( + classProperty.componentType.value_or("")); + if (TypeToPropertyType::component != componentType) { + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorComponentTypeMismatch); + } + + if (classProperty.normalized != Normalized) { + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorNormalizationMismatch); + } + + // Only up to four bytes of image data are supported. + if constexpr (sizeof(T) <= 4) { + return createPropertyViewImpl( + classProperty, + propertyTextureProperty, + sizeof(T), + propertyOptions); + } else { + return PropertyTexturePropertyView( + PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty); + } + } + + template + PropertyTexturePropertyView, Normalized> + createArrayPropertyView( + const ClassProperty& classProperty, + [[maybe_unused]] const PropertyTextureProperty& propertyTextureProperty, + [[maybe_unused]] const TextureViewOptions& propertyOptions) const { + if (!classProperty.array) { + return PropertyTexturePropertyView, Normalized>( + PropertyTexturePropertyViewStatus::ErrorArrayTypeMismatch); + } + + const PropertyType type = convertStringToPropertyType(classProperty.type); + if (TypeToPropertyType::value != type) { + return PropertyTexturePropertyView, Normalized>( + PropertyTexturePropertyViewStatus::ErrorTypeMismatch); + } + + const PropertyComponentType componentType = + convertStringToPropertyComponentType( + classProperty.componentType.value_or("")); + if (TypeToPropertyType::component != componentType) { + return PropertyTexturePropertyView, Normalized>( + PropertyTexturePropertyViewStatus::ErrorComponentTypeMismatch); + } + + if (classProperty.normalized != Normalized) { + return PropertyTexturePropertyView, Normalized>( + PropertyTexturePropertyViewStatus::ErrorNormalizationMismatch); + } + + // Only scalar arrays are supported. The scalar component type must not + // exceed two bytes. + if constexpr (IsMetadataScalar::value && sizeof(T) <= 4) { + // Only up to four elements are supported. + int64_t count = classProperty.count.value_or(0); + if (count <= 0 || count > 4) { + return PropertyTexturePropertyView, Normalized>( + PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty); + } + + if (count * sizeof(T) > 4) { + return PropertyTexturePropertyView, Normalized>( + PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty); + } + + return createPropertyViewImpl, Normalized>( + classProperty, + propertyTextureProperty, + count * sizeof(T), + propertyOptions); + } else { + return PropertyTexturePropertyView, Normalized>( + PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty); + } + } + + template + PropertyTexturePropertyView createPropertyViewImpl( + const ClassProperty& classProperty, + const PropertyTextureProperty& propertyTextureProperty, + size_t elementSize, + const TextureViewOptions& propertyOptions) const { + int32_t samplerIndex; + int32_t imageIndex; + + auto status = + getTextureSafe(propertyTextureProperty.index, samplerIndex, imageIndex); + + if (status != PropertyTexturePropertyViewStatus::Valid) { + return PropertyTexturePropertyView(status); + } + + status = checkSampler(samplerIndex); + if (status != PropertyTexturePropertyViewStatus::Valid) { + return PropertyTexturePropertyView(status); + } + + status = checkImage(imageIndex); + if (status != PropertyTexturePropertyViewStatus::Valid) { + return PropertyTexturePropertyView(status); + } + + const CesiumUtility::IntrusivePointer& pImage = + _pModel->images[imageIndex].pAsset; + const std::vector& channels = propertyTextureProperty.channels; + + status = checkChannels(channels, *pImage); + if (status != PropertyTexturePropertyViewStatus::Valid) { + return PropertyTexturePropertyView(status); + } + + if (channels.size() * pImage->bytesPerChannel != elementSize) { + return PropertyTexturePropertyViewStatus::ErrorChannelsAndTypeMismatch; + } + + return PropertyTexturePropertyView( + propertyTextureProperty, + classProperty, + _pModel->samplers[samplerIndex], + *pImage, + propertyOptions); + } + + PropertyViewStatusType getTextureSafe( + const int32_t textureIndex, + int32_t& samplerIndex, + int32_t& imageIndex) const noexcept; + + PropertyViewStatusType + checkSampler(const int32_t samplerIndex) const noexcept; + + PropertyViewStatusType checkImage(const int32_t imageIndex) const noexcept; + + PropertyViewStatusType checkChannels( + const std::vector& channels, + const ImageAsset& image) const noexcept; + + const Model* _pModel; + const PropertyTexture* _pPropertyTexture; + const Class* _pClass; + + PropertyTextureViewStatus _status; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTransformations.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTransformations.h new file mode 100644 index 0000000..d097c88 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTransformations.h @@ -0,0 +1,244 @@ +#pragma once + +#include "CesiumGltf/PropertyArrayView.h" +#include "CesiumGltf/PropertyTypeTraits.h" + +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief Normalizes the given value between [0, 1] if unsigned or [-1, 1] if + * signed, based on the type's maximum value. + * + * @param value The value to normalize. + */ +template double normalize(T value) { + constexpr double max = static_cast(std::numeric_limits::max()); + if constexpr (std::is_signed_v) { + return std::max(static_cast(value) / max, -1.0); + } else { + return static_cast(value) / max; + } +} + +/** + * @brief Normalizes the given vector's components between [0, 1] if unsigned or + * [-1, 1] if signed, based on the type's maximum value. + * + * @param value The value to normalize. + */ +template +glm::vec normalize(glm::vec value) { + constexpr double max = static_cast(std::numeric_limits::max()); + if constexpr (std::is_signed_v) { + return glm::max(static_cast>(value) / max, -1.0); + } else { + return static_cast>(value) / max; + } +} + +/** + * @brief Normalizes the given matrix's components between [0, 1] if unsigned or + * [-1, 1] if signed, based on the type's maximum value. + * + * @param value The value to normalize. + */ +template +glm::mat normalize(glm::mat value) { + constexpr double max = static_cast(std::numeric_limits::max()); + // No max() implementation for matrices, so we have to write our own. + glm::mat result; + for (glm::length_t i = 0; i < N; i++) { + for (glm::length_t j = 0; j < N; j++) { + if constexpr (std::is_signed_v) { + result[i][j] = glm::max(static_cast(value[i][j]) / max, -1.0); + } else { + result[i][j] = static_cast(value[i][j]) / max; + } + } + } + return result; +} + +/** + * @brief Multiplies each component of the value by the given scale factor. + * + * @param value The value to scale. + * @param scale The scale factor to apply to the value. + */ +template T applyScale(const T& value, const T& scale) { + if constexpr (IsMetadataMatN::value) { + // Do component-wise multiplication instead of actual matrix + // multiplication. + T matN; + constexpr glm::length_t N = T::length(); + for (glm::length_t i = 0; i < N; i++) { + matN[i] = value[i] * scale[i]; + } + return matN; + } else { + return value * scale; + } +} + +/** + * @brief Transforms the value by optional offset and scale factors. + * + * @param value The value to transform. + * @param offset The amount to offset the value by, or `std::nullopt` to apply + * no offset. + * @param scale The amount to scale the value by, or `std::nullopt` to apply no + * scale. See \ref applyScale. + */ +template +T transformValue( + const T& value, + const std::optional& offset, + const std::optional& scale) { + T result = value; + if (scale) { + result = applyScale(result, *scale); + } + + if (offset) { + result += *offset; + } + + return result; +} + +/** + * @brief Transforms each element of an array of values by optional offset and + * scale factors. See \ref transformValue. + * + * @param value The array whose elements will be transformed. + * @param offset The amount to offset each element by, or `std::nullopt` to + * apply no offset. + * @param scale The amount to scale each element by, or `std::nullopt` to apply + * no scale factor. + * @returns A transformed copy of the input array. + */ +template +PropertyArrayCopy transformArray( + const PropertyArrayView& value, + const std::optional>& offset, + const std::optional>& scale) { + std::vector result(static_cast(value.size())); + for (int64_t i = 0; i < value.size(); i++) { + result[i] = value[i]; + + if (scale) { + result[i] = applyScale(result[i], (*scale)[i]); + } + + if (offset) { + result[i] = result[i] + (*offset)[i]; + } + } + + return PropertyArrayCopy(std::move(result)); +} + +/** + * @brief Normalizes each element of an array of values and transforms them by + * optional offset and scale factors. See \ref transformValue and \ref + * transformArray. + * + * @param value The array whose elements will be transformed. + * @param offset The amount to offset each element by, or `std::nullopt` to + * apply no offset. The offset will be applied after normalization. + * @param scale The amount to scale each element by, or `std::nullopt` to apply + * no scale factor. The scale will be applied after normalization. + * @returns A normalized and transformed copy of the input array. + */ +template < + typename T, + typename NormalizedType = typename TypeToNormalizedType::type> +PropertyArrayCopy transformNormalizedArray( + const PropertyArrayView& value, + const std::optional>& offset, + const std::optional>& scale) { + std::vector result(static_cast(value.size())); + for (int64_t i = 0; i < value.size(); i++) { + result[i] = normalize(value[i]); + + if (scale) { + result[i] = result[i] * (*scale)[i]; + } + + if (offset) { + result[i] = result[i] + (*offset)[i]; + } + } + + return PropertyArrayCopy(std::move(result)); +} + +/** + * @brief Normalizes each element of an array of vectors and transforms them by + * optional offset and scale factors. See \ref transformNormalizedArray. + * + * @param value The array whose elements will be transformed. + * @param offset The amount to offset each element by, or `std::nullopt` to + * apply no offset. The offset will be applied after normalization. + * @param scale The amount to scale each element by, or `std::nullopt` to apply + * no scale factor. The scale will be applied after normalization. + * @returns A normalized and transformed copy of the input array. + */ +template +PropertyArrayCopy> transformNormalizedVecNArray( + const PropertyArrayView>& value, + const std::optional>>& offset, + const std::optional>>& scale) { + std::vector> result(static_cast(value.size())); + for (int64_t i = 0; i < value.size(); i++) { + result[i] = normalize(value[i]); + + if (scale) { + result[i] = result[i] * (*scale)[i]; + } + + if (offset) { + result[i] = result[i] + (*offset)[i]; + } + } + + return PropertyArrayCopy(std::move(result)); +} + +/** + * @brief Normalizes each element of an array of matrices and transforms them by + * optional offset and scale factors. See \ref transformNormalizedArray. + * + * @param value The array whose elements will be transformed. + * @param offset The amount to offset each element by, or `std::nullopt` to + * apply no offset. The offset will be applied after normalization. + * @param scale The amount to scale each element by, or `std::nullopt` to apply + * no scale factor. The scale will be applied after normalization. + * @returns A normalized and transformed copy of the input array. + */ +template +PropertyArrayCopy> transformNormalizedMatNArray( + const PropertyArrayView>& value, + const std::optional>>& offset, + const std::optional>>& scale) { + std::vector> result(static_cast(value.size())); + for (int64_t i = 0; i < value.size(); i++) { + result[i] = normalize(value[i]); + + if (scale) { + result[i] = applyScale>(result[i], (*scale)[i]); + } + + if (offset) { + result[i] = result[i] + (*offset)[i]; + } + } + + return PropertyArrayCopy(std::move(result)); +} +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyType.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyType.h new file mode 100644 index 0000000..f3bff90 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyType.h @@ -0,0 +1,255 @@ +#pragma once + +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief The possible types of a property in a PropertyTableView. + */ +enum class PropertyType { + /** + * @brief An invalid property type. + */ + Invalid, + /** + * @brief A scalar property, i.e. an integer or floating point value. + */ + Scalar, + /** + * @brief A vector with two components. + */ + Vec2, + /** + * @brief A vector with three components. + */ + Vec3, + /** + * @brief A vector with four components. + */ + Vec4, + /** + * @brief A 2x2 matrix. + */ + Mat2, + /** + * @brief A 3x3 matrix. + */ + Mat3, + /** + * @brief A 4x4 matrix. + */ + Mat4, + /** + * @brief A string. + */ + String, + /** + * @brief A boolean. + */ + Boolean, + /** + * @brief An enum. + */ + Enum +}; + +/** + * @brief The possible types of a property component. + */ +enum class PropertyComponentType { + /** + * @brief No type. + */ + None, + /** + * @brief A property component equivalent to an `int8_t`. + */ + Int8, + /** + * @brief A property component equivalent to a `uint8_t`. + */ + Uint8, + /** + * @brief A property component equivalent to an `int16_t`. + */ + Int16, + /** + * @brief A property component equivalent to a `uint16_t`. + */ + Uint16, + /** + * @brief A property component equivalent to an `int32_t`. + */ + Int32, + /** + * @brief A property component equivalent to a `uint32_t`. + */ + Uint32, + /** + * @brief A property component equivalent to an `int64_t`. + */ + Int64, + /** + * @brief A property component equivalent to a `uint32_t`. + */ + Uint64, + /** + * @brief A property component equivalent to a `float`. + */ + Float32, + /** + * @brief A property component equivalent to a `double`. + */ + Float64, +}; + +/** + * @brief Converts a \ref PropertyType value to a string. + * + * For example, \ref PropertyType::Mat3 will become `"MAT3"`. + * + * @param type The type to convert to a string. + * @returns The type as a string, or `"INVALID"` if no conversion is possible. + */ +std::string convertPropertyTypeToString(PropertyType type); + +/** + * @brief Converts a string into a \ref PropertyType. + * + * For example, `"MAT3"` will become a \ref PropertyType::Mat3. + * + * @param str The string to convert to a \ref PropertyType. + * @returns The string as a \ref PropertyType, or \ref PropertyType::Invalid if + * no conversion is possible. + */ +PropertyType convertStringToPropertyType(const std::string& str); + +/** + * @brief Converts a \ref PropertyComponentType value to a string. + * + * For example, \ref PropertyComponentType::Uint8 will become `"UINT8"`. + * + * @param componentType The type to convert to a string. + * @returns The type as a string, or `"NONE"` if no conversion is possible. + */ +std::string +convertPropertyComponentTypeToString(PropertyComponentType componentType); + +/** + * @brief Converts a string into a \ref PropertyComponentType. + * + * For example, `"UINT8"` will become a \ref PropertyComponentType::Uint8. + * + * @param str The string to convert to a \ref PropertyComponentType. + * @returns The string as a \ref PropertyComponentType, or \ref + * PropertyComponentType::None if no conversion is possible. + */ +PropertyComponentType +convertStringToPropertyComponentType(const std::string& str); + +/** + * @brief Converts a string listed in \ref + * PropertyTableProperty::ArrayOffsetType to its corresponding \ref + * PropertyComponentType. + * + * @param str The string to convert to a \ref PropertyComponentType. + * @returns The string as a \ref PropertyComponentType, or \ref + * PropertyComponentType::None if no conversion is possible. + */ +PropertyComponentType +convertArrayOffsetTypeStringToPropertyComponentType(const std::string& str); + +/** + * @brief Converts a string listed in \ref + * PropertyTableProperty::StringOffsetType to its corresponding \ref + * PropertyComponentType. + * + * @param str The string to convert to a \ref PropertyComponentType. + * @returns The string as a \ref PropertyComponentType, or \ref + * PropertyComponentType::None if no conversion is possible. + */ +PropertyComponentType +convertStringOffsetTypeStringToPropertyComponentType(const std::string& str); + +/** + * @brief Converts a integer type ID listed in \ref + * AccessorSpec::ComponentType to its corresponding \ref + * PropertyComponentType. + * + * @param componentType The integer ID to convert to a \ref + * PropertyComponentType. + * @returns The ID as a \ref PropertyComponentType, or \ref + * PropertyComponentType::None if no conversion is possible. + */ +PropertyComponentType +convertAccessorComponentTypeToPropertyComponentType(int componentType); + +/** + * @brief Checks if the given \ref PropertyType represents a vector with any + * number of components. + * + * @param type The \ref PropertyType to check. + * @returns True if \ref PropertyType is \ref PropertyType::Vec2, \ref + * PropertyType::Vec3, or \ref PropertyType::Vec4, or false otherwise. + */ +bool isPropertyTypeVecN(PropertyType type); + +/** + * @brief Checks if the given \ref PropertyType represents a matrix with any + * number of components. + * + * @param type The \ref PropertyType to check. + * @returns True if \ref PropertyType is \ref PropertyType::Mat2, \ref + * PropertyType::Mat3, or \ref PropertyType::Mat4, or false otherwise. + */ +bool isPropertyTypeMatN(PropertyType type); + +/** + * @brief Checks if the given \ref PropertyComponentType represents an integer + * value. + * + * @param componentType The \ref PropertyComponentType to check. + * @returns True if the \ref PropertyComponentType is \b not \ref + * PropertyComponentType::Float32 or \ref PropertyComponentType::Float64, false + * otherwise. + */ +bool isPropertyComponentTypeInteger(PropertyComponentType componentType); + +/** + * @brief Obtains the number of dimensions in the given \ref PropertyType. + * + * @param type The type of the property to get the dimensions of. + * @returns The number of dimensions in a value of the given \ref PropertyType. + * For example, a value of \ref PropertyType::Scalar has one dimension. A value + * of \ref PropertyType::Mat4 and a value of \ref PropertyType::Vec4 both have + * four dimensions. + */ +glm::length_t getDimensionsFromPropertyType(PropertyType type); + +/** + * @brief Obtains the number of components in the given \ref PropertyType. + * + * @param type The type of the property to get the component count of. + * @returns The number of components in a value of the given \ref PropertyType. + * For example, a value of \ref PropertyType::Scalar has one component. A value + * of \ref PropertyType::Vec4 has four components. A value of \ref + * PropertyType::Mat4 has 16 components. + */ +glm::length_t getComponentCountFromPropertyType(PropertyType type); + +/** + * @brief Obtains the size in bytes of a value of this \ref + * PropertyComponentType. + * + * @param componentType The component type to get the size of. + * @returns The size in bytes that a value matching this \ref + * PropertyComponentType. For example, a value of \ref + * PropertyComponentType::Uint32 would take up four bytes. + */ +size_t getSizeOfComponentType(PropertyComponentType componentType); + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTypeTraits.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTypeTraits.h new file mode 100644 index 0000000..df357f6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTypeTraits.h @@ -0,0 +1,648 @@ +#pragma once + +#include "CesiumGltf/PropertyArrayView.h" +#include "CesiumGltf/PropertyType.h" + +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief Check if a C++ type can be represented as a scalar property type + */ +template struct IsMetadataScalar; +/** @copydoc IsMetadataScalar */ +template struct IsMetadataScalar : std::false_type {}; +/** @copydoc IsMetadataScalar */ +template <> struct IsMetadataScalar : std::true_type {}; +/** @copydoc IsMetadataScalar */ +template <> struct IsMetadataScalar : std::true_type {}; +/** @copydoc IsMetadataScalar */ +template <> struct IsMetadataScalar : std::true_type {}; +/** @copydoc IsMetadataScalar */ +template <> struct IsMetadataScalar : std::true_type {}; +/** @copydoc IsMetadataScalar */ +template <> struct IsMetadataScalar : std::true_type {}; +/** @copydoc IsMetadataScalar */ +template <> struct IsMetadataScalar : std::true_type {}; +/** @copydoc IsMetadataScalar */ +template <> struct IsMetadataScalar : std::true_type {}; +/** @copydoc IsMetadataScalar */ +template <> struct IsMetadataScalar : std::true_type {}; +/** @copydoc IsMetadataScalar */ +template <> struct IsMetadataScalar : std::true_type {}; +/** @copydoc IsMetadataScalar */ +template <> struct IsMetadataScalar : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as an integer property type + */ +template struct IsMetadataInteger; +/** @copydoc IsMetadataInteger */ +template struct IsMetadataInteger : std::false_type {}; +/** @copydoc IsMetadataInteger */ +template <> struct IsMetadataInteger : std::true_type {}; +/** @copydoc IsMetadataInteger */ +template <> struct IsMetadataInteger : std::true_type {}; +/** @copydoc IsMetadataInteger */ +template <> struct IsMetadataInteger : std::true_type {}; +/** @copydoc IsMetadataInteger */ +template <> struct IsMetadataInteger : std::true_type {}; +/** @copydoc IsMetadataInteger */ +template <> struct IsMetadataInteger : std::true_type {}; +/** @copydoc IsMetadataInteger */ +template <> struct IsMetadataInteger : std::true_type {}; +/** @copydoc IsMetadataInteger */ +template <> struct IsMetadataInteger : std::true_type {}; +/** @copydoc IsMetadataInteger */ +template <> struct IsMetadataInteger : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as a floating-point property + * type. + */ +template struct IsMetadataFloating; +/** @copydoc IsMetadataFloating */ +template struct IsMetadataFloating : std::false_type {}; +/** @copydoc IsMetadataFloating */ +template <> struct IsMetadataFloating : std::true_type {}; +/** @copydoc IsMetadataFloating */ +template <> struct IsMetadataFloating : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as a vecN type. + */ +template struct IsMetadataVecN; +/** @copydoc IsMetadataVecN */ +template struct IsMetadataVecN : std::false_type {}; +/** @copydoc IsMetadataVecN */ +template +struct IsMetadataVecN> : IsMetadataScalar {}; + +/** + * @brief Check if a C++ type can be represented as a matN type. + */ +template struct IsMetadataMatN; +/** @copydoc IsMetadataMatN */ +template struct IsMetadataMatN : std::false_type {}; +/** @copydoc IsMetadataMatN */ +template +struct IsMetadataMatN> : IsMetadataScalar {}; + +/** + * @brief Check if a C++ type can be represented as a numeric property, i.e. + * a scalar / vecN / matN type. + */ +template struct IsMetadataNumeric; +/** + * @copydoc IsMetadataNumeric + */ +template struct IsMetadataNumeric { + /** + * @brief Whether the given metadata type is a scalar, a vector, or a matrix. + */ + static constexpr bool value = IsMetadataScalar::value || + IsMetadataVecN::value || + IsMetadataMatN::value; +}; + +/** + * @brief Check if a C++ type can be represented as a boolean property type + */ +template struct IsMetadataBoolean; +/** @copydoc IsMetadataBoolean */ +template struct IsMetadataBoolean : std::false_type {}; +/** @copydoc IsMetadataBoolean */ +template <> struct IsMetadataBoolean : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as a string property type + */ +template struct IsMetadataString; +/** @copydoc IsMetadataString */ +template struct IsMetadataString : std::false_type {}; +/** @copydoc IsMetadataString */ +template <> struct IsMetadataString : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as an array. + */ +template struct IsMetadataArray; +/** @copydoc IsMetadataArray */ +template struct IsMetadataArray : std::false_type {}; +/** @copydoc IsMetadataArray */ +template +struct IsMetadataArray> : std::true_type {}; +/** @copydoc IsMetadataArray */ +template +struct IsMetadataArray> : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as an array of numeric elements + * property type + */ +template struct IsMetadataNumericArray; +/** @copydoc IsMetadataNumericArray */ +template struct IsMetadataNumericArray : std::false_type {}; +/** @copydoc IsMetadataNumericArray */ +template struct IsMetadataNumericArray> { + /** @brief Whether the component of this \ref PropertyArrayView is numeric. */ + static constexpr bool value = IsMetadataNumeric::value; +}; +/** @copydoc IsMetadataNumericArray */ +template struct IsMetadataNumericArray> { + /** @brief Whether the component of this \ref PropertyArrayCopy is numeric. */ + static constexpr bool value = IsMetadataNumeric::value; +}; + +/** + * @brief Check if a C++ type can be represented as an array of booleans + * property type + */ +template struct IsMetadataBooleanArray; +/** @copydoc IsMetadataBooleanArray */ +template struct IsMetadataBooleanArray : std::false_type {}; +/** @copydoc IsMetadataBooleanArray */ +template <> +struct IsMetadataBooleanArray> : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as an array of strings property + * type + */ +template struct IsMetadataStringArray; +/** @copydoc IsMetadataStringArray */ +template struct IsMetadataStringArray : std::false_type {}; +/** @copydoc IsMetadataStringArray */ +template <> +struct IsMetadataStringArray> + : std::true_type {}; + +/** + * @brief Retrieve the component type of a metadata array + */ +template struct MetadataArrayType { + /** @brief The component type of this metadata array. */ + using type = void; +}; +/** @copydoc MetadataArrayType */ +template +struct MetadataArrayType> { + /** @brief The component type of this metadata array. */ + using type = T; +}; +/** @copydoc MetadataArrayType */ +template +struct MetadataArrayType> { + /** @brief The component type of this metadata array. */ + using type = T; +}; + +/** + * @brief Convert a C++ type to PropertyType and PropertyComponentType + */ +template struct TypeToPropertyType; + +#pragma region Scalar Property Types + +/** @copydoc TypeToPropertyType */ +template <> struct TypeToPropertyType { + /** @brief The \ref PropertyComponentType corresponding to a `uint8_t`. */ + static constexpr PropertyComponentType component = + PropertyComponentType::Uint8; + /** @brief The \ref PropertyType corresponding to a `uint8_t`. */ + static constexpr PropertyType value = PropertyType::Scalar; +}; + +/** @copydoc TypeToPropertyType */ +template <> struct TypeToPropertyType { + /** @brief The \ref PropertyComponentType corresponding to an `int8_t`. */ + static constexpr PropertyComponentType component = + PropertyComponentType::Int8; + /** @brief The \ref PropertyType corresponding to an `int8_t`. */ + static constexpr PropertyType value = PropertyType::Scalar; +}; + +/** @copydoc TypeToPropertyType */ +template <> struct TypeToPropertyType { + /** @brief The \ref PropertyComponentType corresponding to a `uint16_t`. */ + static constexpr PropertyComponentType component = + PropertyComponentType::Uint16; + /** @brief The \ref PropertyType corresponding to a `uint16_t`. */ + static constexpr PropertyType value = PropertyType::Scalar; +}; + +/** @copydoc TypeToPropertyType */ +template <> struct TypeToPropertyType { + /** @brief The \ref PropertyComponentType corresponding to an `int16_t`. */ + static constexpr PropertyComponentType component = + PropertyComponentType::Int16; + /** @brief The \ref PropertyType corresponding to an `int16_t`. */ + static constexpr PropertyType value = PropertyType::Scalar; +}; + +/** @copydoc TypeToPropertyType */ +template <> struct TypeToPropertyType { + /** @brief The \ref PropertyComponentType corresponding to a `uint32_t`. */ + static constexpr PropertyComponentType component = + PropertyComponentType::Uint32; + /** @brief The \ref PropertyType corresponding to a `uint32_t`. */ + static constexpr PropertyType value = PropertyType::Scalar; +}; + +/** @copydoc TypeToPropertyType */ +template <> struct TypeToPropertyType { + /** @brief The \ref PropertyComponentType corresponding to an `int32_t`. */ + static constexpr PropertyComponentType component = + PropertyComponentType::Int32; + /** @brief The \ref PropertyType corresponding to an `int32_t`. */ + static constexpr PropertyType value = PropertyType::Scalar; +}; + +/** @copydoc TypeToPropertyType */ +template <> struct TypeToPropertyType { + /** @brief The \ref PropertyComponentType corresponding to a `uint64_t`. */ + static constexpr PropertyComponentType component = + PropertyComponentType::Uint64; + /** @brief The \ref PropertyType corresponding to a `uint64_t`. */ + static constexpr PropertyType value = PropertyType::Scalar; +}; + +/** @copydoc TypeToPropertyType */ +template <> struct TypeToPropertyType { + /** @brief The \ref PropertyComponentType corresponding to an `int64_t`. */ + static constexpr PropertyComponentType component = + PropertyComponentType::Int64; + /** @brief The \ref PropertyType corresponding to an `int64_t`. */ + static constexpr PropertyType value = PropertyType::Scalar; +}; + +/** @copydoc TypeToPropertyType */ +template <> struct TypeToPropertyType { + /** @brief The \ref PropertyComponentType corresponding to a `float`. */ + static constexpr PropertyComponentType component = + PropertyComponentType::Float32; + /** @brief The \ref PropertyType corresponding to a `float`. */ + static constexpr PropertyType value = PropertyType::Scalar; +}; + +/** @copydoc TypeToPropertyType */ +template <> struct TypeToPropertyType { + /** @brief The \ref PropertyComponentType corresponding to a `double`. */ + static constexpr PropertyComponentType component = + PropertyComponentType::Float64; + /** @brief The \ref PropertyType corresponding to a `float`. */ + static constexpr PropertyType value = PropertyType::Scalar; +}; +#pragma endregion + +#pragma region Vector Property Types + +/** @copydoc TypeToPropertyType */ +template +struct TypeToPropertyType> { + /** @brief The \ref PropertyComponentType corresponding to a `glm::vec<2, + * ...>`. */ + static constexpr PropertyComponentType component = + TypeToPropertyType::component; + /** @brief The \ref PropertyType corresponding to a `glm::vec<2, ...>`. */ + static constexpr PropertyType value = PropertyType::Vec2; +}; + +/** @copydoc TypeToPropertyType */ +template +struct TypeToPropertyType> { + /** @brief The \ref PropertyComponentType corresponding to a `glm::vec<3, + * ...>`. */ + static constexpr PropertyComponentType component = + TypeToPropertyType::component; + /** @brief The \ref PropertyType corresponding to a `glm::vec<3, ...>`. */ + static constexpr PropertyType value = PropertyType::Vec3; +}; + +/** @copydoc TypeToPropertyType */ +template +struct TypeToPropertyType> { + /** @brief The \ref PropertyComponentType corresponding to a `glm::vec<4, + * ...>`. */ + static constexpr PropertyComponentType component = + TypeToPropertyType::component; + /** @brief The \ref PropertyType corresponding to a `glm::vec<4, ...>`. */ + static constexpr PropertyType value = PropertyType::Vec4; +}; + +#pragma endregion + +#pragma region Matrix Property Types + +/** @copydoc TypeToPropertyType */ +template +struct TypeToPropertyType> { + /** @brief The \ref PropertyComponentType corresponding to a `glm::mat<2, 2, + * ...>`. */ + static constexpr PropertyComponentType component = + TypeToPropertyType::component; + /** @brief The \ref PropertyType corresponding to a `glm::mat<2, 2, ...>`. */ + static constexpr PropertyType value = PropertyType::Mat2; +}; + +/** @copydoc TypeToPropertyType */ +template +struct TypeToPropertyType> { + /** @brief The \ref PropertyComponentType corresponding to a `glm::mat<3, 3, + * ...>`. */ + static constexpr PropertyComponentType component = + TypeToPropertyType::component; + /** @brief The \ref PropertyType corresponding to a `glm::mat<3, 3, ...>`. */ + static constexpr PropertyType value = PropertyType::Mat3; +}; + +/** @copydoc TypeToPropertyType */ +template +struct TypeToPropertyType> { + /** @brief The \ref PropertyComponentType corresponding to a `glm::mat<4, 4, + * ...>`. */ + static constexpr PropertyComponentType component = + TypeToPropertyType::component; + /** @brief The \ref PropertyType corresponding to a `glm::mat<4, 4, ...>`. */ + static constexpr PropertyType value = PropertyType::Mat4; +}; + +#pragma endregion + +/** @copydoc TypeToPropertyType */ +template <> struct TypeToPropertyType { + /** @brief The \ref PropertyComponentType corresponding to a `bool`. */ + static constexpr PropertyComponentType component = + PropertyComponentType::None; + /** @brief The \ref PropertyType corresponding to a `bool`. */ + static constexpr PropertyType value = PropertyType::Boolean; +}; + +/** @copydoc TypeToPropertyType */ +template <> struct TypeToPropertyType { + /** @brief The \ref PropertyComponentType corresponding to a + * `std::string_view`. */ + static constexpr PropertyComponentType component = + PropertyComponentType::None; + /** @brief The \ref PropertyType corresponding to a `std::string_view`. */ + static constexpr PropertyType value = PropertyType::String; +}; + +/** + * @brief Check if a C++ type can be normalized. + */ +template struct CanBeNormalized; +/** @copydoc CanBeNormalized */ +template struct CanBeNormalized : std::false_type {}; +/** @copydoc CanBeNormalized */ +template <> struct CanBeNormalized : std::true_type {}; +/** @copydoc CanBeNormalized */ +template <> struct CanBeNormalized : std::true_type {}; +/** @copydoc CanBeNormalized */ +template <> struct CanBeNormalized : std::true_type {}; +/** @copydoc CanBeNormalized */ +template <> struct CanBeNormalized : std::true_type {}; +/** @copydoc CanBeNormalized */ +template <> struct CanBeNormalized : std::true_type {}; +/** @copydoc CanBeNormalized */ +template <> struct CanBeNormalized : std::true_type {}; +/** @copydoc CanBeNormalized */ +template <> struct CanBeNormalized : std::true_type {}; +/** @copydoc CanBeNormalized */ +template <> struct CanBeNormalized : std::true_type {}; + +/** @copydoc CanBeNormalized */ +template +struct CanBeNormalized> : CanBeNormalized {}; + +/** @copydoc CanBeNormalized */ +template +struct CanBeNormalized> : CanBeNormalized {}; + +/** @copydoc CanBeNormalized */ +template +struct CanBeNormalized> : CanBeNormalized {}; +/** + * @brief Convert an integer numeric type to the corresponding representation as + * a double type. Doubles are preferred over floats to maintain more precision. + */ +template struct TypeToNormalizedType; + +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType { + /** @brief The representation of an `int8_t` as a double type. */ + using type = double; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType { + /** @brief The representation of a `uint8_t` as a double type. */ + using type = double; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType { + /** @brief The representation of an `int16_t` as a double type. */ + using type = double; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType { + /** @brief The representation of a `uint16_t` as a double type. */ + using type = double; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType { + /** @brief The representation of an `int32_t` as a double type. */ + using type = double; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType { + /** @brief The representation of a `uint32_t` as a double type. */ + using type = double; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType { + /** @brief The representation of an `int64_t` as a double type. */ + using type = double; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType { + /** @brief The representation of a `uint64_t` as a double type. */ + using type = double; +}; + +/** @copydoc TypeToNormalizedType */ +template +struct TypeToNormalizedType> { + /** @brief The representation of a `glm::vec` as a double type. */ + using type = glm::vec; +}; + +/** @copydoc TypeToNormalizedType */ +template +struct TypeToNormalizedType> { + /** @brief The representation of a `glm::mat` as a double type. */ + using type = glm::mat; +}; + +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType> { + /** @brief The representation of an array of `int8_t` types as an array of its + * double type equivalents. */ + using type = PropertyArrayView; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType> { + /** @brief The representation of an array of `uint8_t` types as an array of + * its double type equivalents. */ + using type = PropertyArrayView; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType> { + /** @brief The representation of an array of `int16_t` types as an array of + * its double type equivalents. */ + using type = PropertyArrayView; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType> { + /** @brief The representation of an array of `uint16_t` types as an array of + * its double type equivalents. */ + using type = PropertyArrayView; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType> { + /** @brief The representation of an array of `int32_t` types as an array of + * its double type equivalents. */ + using type = PropertyArrayView; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType> { + /** @brief The representation of an array of `uint32_t` types as an array of + * its double type equivalents. */ + using type = PropertyArrayView; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType> { + /** @brief The representation of an array of `int64_t` types as an array of + * its double type equivalents. */ + using type = PropertyArrayView; +}; +/** @copydoc TypeToNormalizedType */ +template <> struct TypeToNormalizedType> { + /** @brief The representation of an array of `uint64_t` types as an array of + * its double type equivalents. */ + using type = PropertyArrayView; +}; + +/** @copydoc TypeToNormalizedType */ +template +struct TypeToNormalizedType>> { + /** @brief The representation of an array of `glm::vec` types as an + * array of its double type equivalents. */ + using type = PropertyArrayView>; +}; + +/** @copydoc TypeToNormalizedType */ +template +struct TypeToNormalizedType>> { + /** @brief The representation of an array of `glm::mat` types as + * an array of its double type equivalents. */ + using type = PropertyArrayView>; +}; + +/** + * @brief Transforms a property value type from a view to an equivalent type + * that owns the data it is viewing. For most property types this is an identity + * transformation, because most property types are held by value. However, it + * transforms numeric `PropertyArrayView` to `PropertyArrayCopy` because a + * `PropertyArrayView` only has a pointer to the value it is viewing. + * + * See `propertyValueViewToCopy`. + * + * @remarks This is the inverse of \ref PropertyValueCopyToView + * @tparam T The type of the property value view. + */ +template +using PropertyValueViewToCopy = std::conditional_t< + IsMetadataNumericArray::value, + PropertyArrayCopy::type>, + T>; + +/** + * @brief Transforms a property value type from a copy that owns the data it is + * viewing to a view into that data. For most property types this is an identity + * transformation, because most property types are held by value. However, it + * transforms numeric `PropertyArrayCopy` to `PropertyArrayView`. + * + * See `propertyValueCopyToView`. + * + * @remarks This is the inverse of \ref PropertyValueViewToCopy + * @tparam T The type of the property value copy. + */ +template +using PropertyValueCopyToView = std::conditional_t< + IsMetadataNumericArray::value, + PropertyArrayView::type>, + T>; + +/** + * @brief Creates an optional instance of a type that can be used to own a + * property value from an optional instance that is only a view on that value. + * See {@link PropertyValueViewToCopy}. + * + * @tparam T The type of the view to copy. + * @param view An optional instance of a view on the value that will be copied. + * @return std::optional> + */ +template +static std::optional> +propertyValueViewToCopy(const std::optional& view) { + if constexpr (IsMetadataNumericArray::value) { + if (view) { + return std::make_optional>( + std::vector(view->begin(), view->end())); + } else { + return std::nullopt; + } + } else { + return view; + } +} + +/** + * @brief Creates an instance of a type that will own a property value from a + * view on that value. See \ref PropertyValueViewToOwner. + * + * @tparam T The type of the view to copy. + * @param view A view on the value that will be copied. + * @return PropertyValueViewToCopy + */ +template +static PropertyValueViewToCopy propertyValueViewToCopy(const T& view) { + if constexpr (IsMetadataNumericArray::value) { + return PropertyValueViewToCopy(std::vector(view.begin(), view.end())); + } else { + return view; + } +} + +/** + * @brief Creates a view on an owned copy of a property value. See \ref + * PropertyValueCopyToView. + * + * @tparam T The type of the value to create a view from. + * @param copy The value to create a view from. + * @return PropertyValueCopyToView + */ +template +static PropertyValueCopyToView propertyValueCopyToView(const T& copy) { + if constexpr (IsMetadataNumericArray::value) { + return copy.view(); + } else { + return copy; + } +} + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyView.h new file mode 100644 index 0000000..8e017c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyView.h @@ -0,0 +1,2629 @@ +#pragma once + +#include "CesiumGltf/ClassProperty.h" +#include "CesiumGltf/PropertyAttributeProperty.h" +#include "CesiumGltf/PropertyTableProperty.h" +#include "CesiumGltf/PropertyTextureProperty.h" +#include "CesiumGltf/PropertyTypeTraits.h" + +#include +#include + +namespace CesiumGltf { + +/** + * @brief The type used for fields of \ref PropertyViewStatus. + */ +typedef int32_t PropertyViewStatusType; + +/** + * @brief Indicates the status of a property view. + * + * The {@link PropertyView} constructor always completes successfully. + * However, there may be fundamental errors with the property definition. In + * such cases, this enumeration provides the reason. + * + * This is defined with a class of static consts as opposed to an enum, so that + * derived property view classes can extend the statuses with their own specific + * errors. + */ +class PropertyViewStatus { +public: + /** + * @brief This property view is valid and ready to use. + */ + static const PropertyViewStatusType Valid = 0; + + /** + * @brief This property view does not contain any data, but specifies a + * default value. This happens when a class property is defined with a default + * value and omitted from an instance of the class's collective properties. In + * this case, it is not possible to retrieve the raw data from a property, but + * its default value will be accessible. + */ + static const PropertyViewStatusType EmptyPropertyWithDefault = 1; + + /** + * @brief This property view is trying to view a property that does not + * exist. + */ + static const PropertyViewStatusType ErrorNonexistentProperty = 2; + + /** + * @brief This property view's type does not match what is + * specified in {@link ClassProperty::type}. + */ + static const PropertyViewStatusType ErrorTypeMismatch = 3; + + /** + * @brief This property view's component type does not match what + * is specified in {@link ClassProperty::componentType}. + */ + static const PropertyViewStatusType ErrorComponentTypeMismatch = 4; + + /** + * @brief This property view differs from what is specified in + * {@link ClassProperty::array}. + */ + static const PropertyViewStatusType ErrorArrayTypeMismatch = 5; + + /** + * @brief This property says it is normalized, but it does not have an integer + * component type. + */ + static const PropertyViewStatusType ErrorInvalidNormalization = 6; + + /** + * @brief This property view's normalization differs from what + * is specified in {@link ClassProperty::normalized} + */ + static const PropertyViewStatusType ErrorNormalizationMismatch = 7; + + /** + * @brief The property provided an invalid offset value. + */ + static const PropertyViewStatusType ErrorInvalidOffset = 8; + + /** + * @brief The property provided an invalid scale value. + */ + static const PropertyViewStatusType ErrorInvalidScale = 9; + + /** + * @brief The property provided an invalid maximum value. + */ + static const PropertyViewStatusType ErrorInvalidMax = 10; + + /** + * @brief The property provided an invalid minimum value. + */ + static const PropertyViewStatusType ErrorInvalidMin = 11; + + /** + * @brief The property provided an invalid "no data" value. + */ + static const PropertyViewStatusType ErrorInvalidNoDataValue = 12; + + /** + * @brief The property provided an invalid default value. + */ + static const PropertyViewStatusType ErrorInvalidDefaultValue = 13; +}; + +/** + * @brief Validates a \ref ClassProperty, checking for any type mismatches. + * + * @returns A \ref PropertyViewStatus value representing the error found while + * validating, or \ref PropertyViewStatus::Valid if no errors were found. + */ +template +PropertyViewStatusType +validatePropertyType(const ClassProperty& classProperty) { + if (TypeToPropertyType::value != + convertStringToPropertyType(classProperty.type)) { + return PropertyViewStatus::ErrorTypeMismatch; + } + + PropertyComponentType expectedComponentType = + TypeToPropertyType::component; + + if (!classProperty.componentType && + expectedComponentType != PropertyComponentType::None) { + return PropertyViewStatus::ErrorComponentTypeMismatch; + } + + if (classProperty.componentType && + expectedComponentType != + convertStringToPropertyComponentType(*classProperty.componentType)) { + return PropertyViewStatus::ErrorComponentTypeMismatch; + } + + if (classProperty.array) { + return PropertyViewStatus::ErrorArrayTypeMismatch; + } + + return PropertyViewStatus::Valid; +} + +/** + * @brief Validates a \ref ClassProperty representing an array, checking for any + * type mismatches. + * + * @returns A \ref PropertyViewStatus value representing the error found while + * validating, or \ref PropertyViewStatus::Valid if no errors were found. + */ +template +PropertyViewStatusType +validateArrayPropertyType(const ClassProperty& classProperty) { + using ElementType = typename MetadataArrayType::type; + if (TypeToPropertyType::value != + convertStringToPropertyType(classProperty.type)) { + return PropertyViewStatus::ErrorTypeMismatch; + } + + PropertyComponentType expectedComponentType = + TypeToPropertyType::component; + + if (!classProperty.componentType && + expectedComponentType != PropertyComponentType::None) { + return PropertyViewStatus::ErrorComponentTypeMismatch; + } + + if (classProperty.componentType && + expectedComponentType != + convertStringToPropertyComponentType(*classProperty.componentType)) { + return PropertyViewStatus::ErrorComponentTypeMismatch; + } + + if (!classProperty.array) { + return PropertyViewStatus::ErrorArrayTypeMismatch; + } + + return PropertyViewStatus::Valid; +} + +/** + * @brief Attempts to get a scalar value from the provided \ref + * CesiumUtility::JsonValue "JsonValue". + * + * @param jsonValue The value to attempt to get as a scalar. + * @returns A scalar of type `T` if successful, or `std::nullopt` if not. + */ +template +static std::optional getScalar(const CesiumUtility::JsonValue& jsonValue) { + return jsonValue.getSafeNumber(); +} + +/** + * @brief Attempts to obtain a vector of type `VecType` from the provided \ref + * CesiumUtility::JsonValue "JsonValue". + * + * @param jsonValue The value to attempt to get as a vector. To be successful, + * this \ref CesiumUtility::JsonValue "JsonValue" must be an array with the same + * number of elements as `VecType`. + * @returns A vector of type `VecType` if successful, or `std::nullopt` if not. + */ +template +static std::optional +getVecN(const CesiumUtility::JsonValue& jsonValue) { + if (!jsonValue.isArray()) { + return std::nullopt; + } + + const CesiumUtility::JsonValue::Array& array = jsonValue.getArray(); + constexpr glm::length_t N = VecType::length(); + if (array.size() != N) { + return std::nullopt; + } + + using T = typename VecType::value_type; + + VecType result; + for (glm::length_t i = 0; i < N; i++) { + std::optional value = getScalar(array[i]); + if (!value) { + return std::nullopt; + } + + result[i] = *value; + } + + return result; +} + +/** + * @brief Attempts to obtain a matrix of type `MatType` from the provided \ref + * CesiumUtility::JsonValue "JsonValue". + * + * @param jsonValue The value to attempt to get as a matrix. To be successful, + * this \ref CesiumUtility::JsonValue "JsonValue" must be an array with the same + * number of elements as `MatType`. For example, to read a 4x4 matrix, the \ref + * CesiumUtility::JsonValue "JsonValue" must be an array with 16 elements. + * @returns A matrix of type `MatType` if successful, or `std::nullopt` if not. + */ +template +static std::optional +getMatN(const CesiumUtility::JsonValue& jsonValue) { + if (!jsonValue.isArray()) { + return std::nullopt; + } + + const CesiumUtility::JsonValue::Array& array = jsonValue.getArray(); + constexpr glm::length_t N = MatType::length(); + if (array.size() != N * N) { + return std::nullopt; + } + + using T = typename MatType::value_type; + + MatType result; + for (glm::length_t i = 0; i < N; i++) { + // Try to parse each value in the column. + for (glm::length_t j = 0; j < N; j++) { + std::optional value = getScalar(array[i * N + j]); + if (!value) { + return std::nullopt; + } + + result[i][j] = *value; + } + } + + return result; +} + +/** + * @brief Obtains the number of values of type `ElementType` that could fit in + * the buffer. + * + * @param buffer The buffer whose size will be used for this calculation. + * @returns The number of values of type `ElementType` that could fit in + * `buffer`. This value will be equivalent to `floor(buffer->size() / + * sizeof(ElementType))`. + */ +template +int64_t getCount(std::optional>& buffer) { + if (!buffer) { + return 0; + } + + return static_cast(buffer->size() / sizeof(ElementType)); +} + +/** + * @brief Represents a metadata property in EXT_structural_metadata. + */ +template class PropertyView; + +/** + * @brief Represents a non-normalized metadata property in + * EXT_structural_metadata. + * + * Whether they belong to property tables, property textures, or property + * attributes, properties have their own sub-properties affecting the actual + * property values. Although they are typically defined via class property, they + * may be overridden by individual instances of the property themselves. The + * constructor is responsible for resolving those differences. + * + * @tparam ElementType The C++ type of the values in this property + */ +template class PropertyView { +public: + /** + * @brief Constructs an empty property instance. + */ + PropertyView() + : _status(PropertyViewStatus::ErrorNonexistentProperty), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _offset(std::nullopt), + _scale(std::nullopt), + _max(std::nullopt), + _min(std::nullopt), + _required(false), + _noData(std::nullopt), + _defaultValue(std::nullopt) {} + + /** + * @brief Constructs a property instance from a class definition only. + */ + PropertyView(const ClassProperty& classProperty) + : _status(validatePropertyType(classProperty)), + _name(classProperty.name), + _semantic(classProperty.semantic), + _description(classProperty.description), + _offset(std::nullopt), + _scale(std::nullopt), + _max(std::nullopt), + _min(std::nullopt), + _required(classProperty.required), + _noData(std::nullopt), + _defaultValue(std::nullopt) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + if (classProperty.normalized) { + _status = PropertyViewStatus::ErrorNormalizationMismatch; + return; + } + + getNumericPropertyValues(classProperty); + if (_status != PropertyViewStatus::Valid) { + return; + } + + if (classProperty.noData) { + if (!_required) { + // "noData" can only be defined if the property is not required. + _noData = getValue(*classProperty.noData); + } + + if (!_noData) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidNoDataValue; + return; + } + } + + if (classProperty.defaultProperty) { + if (!_required) { + // "default" can only be defined if the property is not required. + _defaultValue = getValue(*classProperty.defaultProperty); + } + + if (!_defaultValue) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidDefaultValue; + return; + } + } + } + +protected: + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The value of {@link PropertyViewStatus} indicating the error + * with the property. + */ + PropertyView(PropertyViewStatusType status) + : _status(status), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _offset(std::nullopt), + _scale(std::nullopt), + _max(std::nullopt), + _min(std::nullopt), + _required(false), + _noData(std::nullopt), + _defaultValue(std::nullopt) {} + + /** + * @brief Constructs a property instance from a property table property and + * its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyTableProperty& property) + : PropertyView(classProperty) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + // If the property has its own values, override the class-provided values. + getNumericPropertyValues(property); + } + + /** + * @brief Constructs a property instance from a property texture property and + * its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyTextureProperty& property) + : PropertyView(classProperty) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + // If the property has its own values, override the class-provided values. + getNumericPropertyValues(property); + } + + /** + * @brief Constructs a property instance from a property attribute property + * and its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyAttributeProperty& property) + : PropertyView(classProperty) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + // If the property has its own values, override the class-provided values. + getNumericPropertyValues(property); + } + +public: + /** + * @brief Gets the status of this property view, indicating whether an error + * occurred. + * + * @return The status of this property view. + */ + PropertyViewStatusType status() const noexcept { return _status; } + + /** + * @brief Gets the name of the property being viewed. Returns std::nullopt if + * no name was specified. + */ + const std::optional& name() const noexcept { return _name; } + + /** + * @brief Gets the semantic of the property being viewed. The semantic is an + * identifier that describes how this property should be interpreted, and + * cannot be used by other properties in the class. Returns std::nullopt if no + * semantic was specified. + */ + const std::optional& semantic() const noexcept { + return _semantic; + } + + /** + * @brief Gets the description of the property being viewed. Returns + * std::nullopt if no description was specified. + */ + const std::optional& description() const noexcept { + return _description; + } + + /** + * @brief Get the element count of the fixed-length arrays in this property. + * Only applicable when the property is an array type. + * + * @return The count of this property. + */ + int64_t arrayCount() const noexcept { return 0; } + + /** + * @brief Whether this property has a normalized integer type. + */ + bool normalized() const noexcept { return false; } + + /** + * @brief Gets the offset to apply to property values. Only applicable to + * SCALAR, VECN, and MATN types when the component type is FLOAT32 or + * FLOAT64, or when the property is normalized. + * + * @returns The property's offset, or std::nullopt if it was not specified. + */ + std::optional offset() const noexcept { return _offset; } + + /** + * @brief Gets the scale to apply to property values. Only applicable to + * SCALAR, VECN, and MATN types when the component type is FLOAT32 or + * FLOAT64, or when the property is normalized. + * + * @returns The property's scale, or std::nullopt if it was not specified. + */ + std::optional scale() const noexcept { return _scale; } + + /** + * @brief Gets the maximum allowed value for the property. Only applicable to + * SCALAR, VECN, and MATN types. This is the maximum of all property + * values, after the transforms based on the normalized, offset, and + * scale properties have been applied. + * + * @returns The property's maximum value, or std::nullopt if it was not + * specified. + */ + std::optional max() const noexcept { return _max; } + + /** + * @brief Gets the minimum allowed value for the property. Only applicable to + * SCALAR, VECN, and MATN types. This is the minimum of all property + * values, after the transforms based on the normalized, offset, and + * scale properties have been applied. + * + * @returns The property's minimum value, or std::nullopt if it was not + * specified. + */ + std::optional min() const noexcept { return _min; } + + /** + * @brief Whether the property must be present in every entity conforming to + * the class. If not required, instances of the property may include "no data" + * values, or the entire property may be omitted. + */ + bool required() const noexcept { return _required; } + + /** + * @brief Gets the "no data" value, i.e., the value representing missing data + * in the property wherever it appears. Also known as a sentinel value. This + * is given as the plain property value, without the transforms from the + * normalized, offset, and scale properties. + * + * @returns The property's "no data" value, or std::nullopt if it was not + * specified. + */ + std::optional noData() const noexcept { return _noData; } + + /** + * @brief Gets the default value to use when encountering a "no data" value or + * an omitted property. The value is given in its final form, taking the + * effect of normalized, offset, and scale properties into account. + * + * @returns The property's default value, or std::nullopt if it was not + * specified. + */ + std::optional defaultValue() const noexcept { + return _defaultValue; + } + +protected: + /** @copydoc PropertyViewStatus */ + PropertyViewStatusType _status; + +private: + std::optional _name; + std::optional _semantic; + std::optional _description; + + std::optional _offset; + std::optional _scale; + std::optional _max; + std::optional _min; + + bool _required; + std::optional _noData; + std::optional _defaultValue; + + /** + * @brief Attempts to parse an ElementType from the given json value. + * + * If ElementType is a type with multiple components, e.g. a VECN or MATN + * type, this will return std::nullopt if one or more components could not be + * parsed. + * + * @return The value as an instance of ElementType, or std::nullopt if it + * could not be parsed. + */ + static std::optional + getValue(const CesiumUtility::JsonValue& jsonValue) { + if constexpr (IsMetadataScalar::value) { + return getScalar(jsonValue); + } + + if constexpr (IsMetadataVecN::value) { + return getVecN(jsonValue); + } + + if constexpr (IsMetadataMatN::value) { + return getMatN(jsonValue); + } + } + + using PropertyDefinitionType = std::variant< + ClassProperty, + PropertyTableProperty, + PropertyTextureProperty, + PropertyAttributeProperty>; + + /** + * @brief Attempts to parse offset, scale, min, and max properties from the + * given property type. + */ + void getNumericPropertyValues(const PropertyDefinitionType& inProperty) { + std::visit( + [this](auto property) { + if (property.offset) { + // Only floating point types can specify an offset. + switch (TypeToPropertyType::component) { + case PropertyComponentType::Float32: + case PropertyComponentType::Float64: + this->_offset = getValue(*property.offset); + if (this->_offset) { + break; + } + // If it does not break here, something went wrong. + [[fallthrough]]; + default: + this->_status = PropertyViewStatus::ErrorInvalidOffset; + return; + } + } + + if (property.scale) { + // Only floating point types can specify a scale. + switch (TypeToPropertyType::component) { + case PropertyComponentType::Float32: + case PropertyComponentType::Float64: + this->_scale = getValue(*property.scale); + if (this->_scale) { + break; + } + // If it does not break here, something went wrong. + [[fallthrough]]; + default: + this->_status = PropertyViewStatus::ErrorInvalidScale; + return; + } + } + + if (property.max) { + this->_max = getValue(*property.max); + if (!this->_max) { + // The value was specified but something went wrong. + this->_status = PropertyViewStatus::ErrorInvalidMax; + return; + } + } + + if (property.min) { + this->_min = getValue(*property.min); + if (!this->_min) { + // The value was specified but something went wrong. + this->_status = PropertyViewStatus::ErrorInvalidMin; + return; + } + } + }, + inProperty); + } +}; + +/** + * @brief Represents a normalized metadata property in + * EXT_structural_metadata. + * + * Whether they belong to property tables, property textures, or property + * attributes, properties have their own sub-properties affecting the actual + * property values. Although they are typically defined via class property, they + * may be overridden by individual instances of the property themselves. The + * constructor is responsible for resolving those differences. + * + * @tparam ElementType The C++ type of the values in this property. Must have an + * integer component type. + */ +template class PropertyView { +private: + using NormalizedType = typename TypeToNormalizedType::type; + +public: + /** + * @brief Constructs an empty property instance. + */ + PropertyView() + : _status(PropertyViewStatus::ErrorNonexistentProperty), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _offset(std::nullopt), + _scale(std::nullopt), + _max(std::nullopt), + _min(std::nullopt), + _required(false), + _noData(std::nullopt), + _defaultValue(std::nullopt) {} + + /** + * @brief Constructs a property instance from a class definition only. + */ + PropertyView(const ClassProperty& classProperty) + : _status(validatePropertyType(classProperty)), + _name(classProperty.name), + _semantic(classProperty.semantic), + _description(classProperty.description), + _offset(std::nullopt), + _scale(std::nullopt), + _max(std::nullopt), + _min(std::nullopt), + _required(classProperty.required), + _noData(std::nullopt), + _defaultValue(std::nullopt) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + if (!classProperty.normalized) { + _status = PropertyViewStatus::ErrorNormalizationMismatch; + } + + getNumericPropertyValues(classProperty); + if (_status != PropertyViewStatus::Valid) { + return; + } + + if (classProperty.noData) { + if (!_required) { + // "noData" should not be defined if the property is required. + _noData = getValue(*classProperty.noData); + } + if (!_noData) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidNoDataValue; + return; + } + } + + if (classProperty.defaultProperty) { + // default value should not be defined if the property is required. + if (!_required) { + _defaultValue = + getValue(*classProperty.defaultProperty); + } + if (!_defaultValue) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidDefaultValue; + return; + } + } + } + +protected: + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The value of {@link PropertyViewStatus} indicating the error with the property. + */ + PropertyView(PropertyViewStatusType status) + : _status(status), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _offset(std::nullopt), + _scale(std::nullopt), + _max(std::nullopt), + _min(std::nullopt), + _required(false), + _noData(std::nullopt), + _defaultValue(std::nullopt) {} + + /** + * @brief Constructs a property instance from a property table property and + * its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyTableProperty& property) + : PropertyView(classProperty) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + // If the property has its own values, override the class-provided values. + getNumericPropertyValues(property); + } + + /** + * @brief Constructs a property instance from a property texture property and + * its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyTextureProperty& property) + : PropertyView(classProperty) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + // If the property has its own values, override the class-provided values. + getNumericPropertyValues(property); + } + + /** + * @brief Constructs a property instance from a property attribute property + * and its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyAttributeProperty& property) + : PropertyView(classProperty) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + // If the property has its own values, override the class-provided values. + getNumericPropertyValues(property); + } + +public: + /** + * @copydoc PropertyView::status + */ + PropertyViewStatusType status() const noexcept { return _status; } + + /** + * @copydoc PropertyView::name + */ + const std::optional& name() const noexcept { return _name; } + + /** + * @copydoc PropertyView::semantic + */ + const std::optional& semantic() const noexcept { + return _semantic; + } + + /** + * @copydoc PropertyView::description + */ + const std::optional& description() const noexcept { + return _description; + } + + /** + * @copydoc PropertyView::arrayCount + */ + int64_t arrayCount() const noexcept { return 0; } + + /** + * @copydoc PropertyView::normalized + */ + bool normalized() const noexcept { return true; } + + /** + * @copydoc PropertyView::offset + */ + std::optional offset() const noexcept { return _offset; } + + /** + * @copydoc PropertyView::scale + */ + std::optional scale() const noexcept { return _scale; } + + /** + * @copydoc PropertyView::max + */ + std::optional max() const noexcept { return _max; } + + /** + * @copydoc PropertyView::min + */ + std::optional min() const noexcept { return _min; } + + /** + * @copydoc PropertyView::required + */ + bool required() const noexcept { return _required; } + + /** + * @copydoc PropertyView::noData + */ + std::optional noData() const noexcept { return _noData; } + + /** + * @copydoc PropertyView::defaultValue + */ + std::optional defaultValue() const noexcept { + return _defaultValue; + } + +protected: + /** @copydoc PropertyViewStatus */ + PropertyViewStatusType _status; + +private: + std::optional _name; + std::optional _semantic; + std::optional _description; + + std::optional _offset; + std::optional _scale; + std::optional _max; + std::optional _min; + + bool _required; + std::optional _noData; + std::optional _defaultValue; + + /** + * @brief Attempts to parse from the given json value. + * + * If T is a type with multiple components, e.g. a VECN or MATN type, this + * will return std::nullopt if one or more components could not be parsed. + * + * @return The value as an instance of T, or std::nullopt if it could not be + * parsed. + */ + template + static std::optional getValue(const CesiumUtility::JsonValue& jsonValue) { + if constexpr (IsMetadataScalar::value) { + return getScalar(jsonValue); + } + + if constexpr (IsMetadataVecN::value) { + return getVecN(jsonValue); + } + + if constexpr (IsMetadataMatN::value) { + return getMatN(jsonValue); + } + } + + using PropertyDefinitionType = std::variant< + ClassProperty, + PropertyTableProperty, + PropertyTextureProperty, + PropertyAttributeProperty>; + + /** + * @brief Attempts to parse offset, scale, min, and max properties from the + * given property type. + */ + void getNumericPropertyValues(const PropertyDefinitionType& inProperty) { + std::visit( + [this](auto property) { + if (property.offset) { + _offset = getValue(*property.offset); + if (!_offset) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidOffset; + return; + } + } + + if (property.scale) { + _scale = getValue(*property.scale); + if (!_scale) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidScale; + return; + } + } + + if (property.max) { + _max = getValue(*property.max); + if (!_scale) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidMax; + return; + } + } + + if (property.min) { + _min = getValue(*property.min); + if (!_scale) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidMin; + return; + } + } + }, + inProperty); + } +}; + +/** + * @brief Represents a boolean metadata property in + * EXT_structural_metadata. + */ +template <> class PropertyView { +public: + /** + * @brief Constructs an empty property instance. + */ + PropertyView() + : _status(PropertyViewStatus::ErrorNonexistentProperty), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _required(false), + _defaultValue(std::nullopt) {} + + /** + * @brief Constructs a property instance from a class definition only. + */ + PropertyView(const ClassProperty& classProperty) + : _status(validatePropertyType(classProperty)), + _name(classProperty.name), + _semantic(classProperty.semantic), + _description(classProperty.description), + _required(classProperty.required), + _defaultValue(std::nullopt) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + if (classProperty.defaultProperty) { + if (!_required) { + _defaultValue = getBooleanValue(*classProperty.defaultProperty); + } + + if (!_defaultValue) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidDefaultValue; + return; + } + } + } + +protected: + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The value of {@link PropertyViewStatus} indicating the error with the property. + */ + PropertyView(PropertyViewStatusType status) + : _status(status), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _required(false), + _defaultValue(std::nullopt) {} + + /** + * @brief Constructs a property instance from a property table property and + * its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyTableProperty& /*property*/) + : PropertyView(classProperty) {} + +public: + /** + * @copydoc PropertyView::status + */ + PropertyViewStatusType status() const noexcept { return _status; } + + /** + * @copydoc PropertyView::name + */ + const std::optional& name() const noexcept { return _name; } + + /** + * @copydoc PropertyView::semantic + */ + const std::optional& semantic() const noexcept { + return _semantic; + } + + /** + * @copydoc PropertyView::description + */ + const std::optional& description() const noexcept { + return _description; + } + + /** + * @copydoc PropertyView::arrayCount + */ + int64_t arrayCount() const noexcept { return 0; } + + /** + * @copydoc PropertyView::normalized + */ + bool normalized() const noexcept { return false; } + + /** + * @copydoc PropertyView::offset + */ + std::optional offset() const noexcept { return std::nullopt; } + + /** + * @copydoc PropertyView::scale + */ + std::optional scale() const noexcept { return std::nullopt; } + + /** + * @copydoc PropertyView::max + */ + std::optional max() const noexcept { return std::nullopt; } + + /** + * @copydoc PropertyView::min + */ + std::optional min() const noexcept { return std::nullopt; } + + /** + * @copydoc PropertyView::required + */ + bool required() const noexcept { return _required; } + + /** + * @copydoc PropertyView::noData + */ + std::optional noData() const noexcept { return std::nullopt; } + + /** + * @copydoc PropertyView::defaultValue + */ + std::optional defaultValue() const noexcept { return _defaultValue; } + +protected: + /** @copydoc PropertyViewStatus */ + PropertyViewStatusType _status; + +private: + std::optional _name; + std::optional _semantic; + std::optional _description; + + bool _required; + std::optional _defaultValue; + + static std::optional + getBooleanValue(const CesiumUtility::JsonValue& value) { + if (!value.isBool()) { + return std::nullopt; + } + + return value.getBool(); + } +}; + +/** + * @brief Represents a string metadata property in + * EXT_structural_metadata. + */ +template <> class PropertyView { +public: + /** + * @brief Constructs an empty property instance. + */ + PropertyView() + : _status(PropertyViewStatus::ErrorNonexistentProperty), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _required(false), + _noData(std::nullopt), + _defaultValue(std::nullopt) {} + + /** + * @brief Constructs a property instance from a class definition only. + */ + PropertyView(const ClassProperty& classProperty) + : _status(validatePropertyType(classProperty)), + _name(classProperty.name), + _semantic(classProperty.semantic), + _description(classProperty.description), + _required(classProperty.required), + _noData(std::nullopt), + _defaultValue(std::nullopt) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + if (classProperty.noData) { + if (!_required) { + _noData = getStringValue(*classProperty.noData); + } + + if (!_noData) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidNoDataValue; + return; + } + } + + if (classProperty.defaultProperty) { + if (!_required) { + _defaultValue = getStringValue(*classProperty.defaultProperty); + } + + if (!_defaultValue) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidDefaultValue; + return; + } + } + } + +protected: + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The value of {@link PropertyViewStatus} indicating the error with the property. + */ + PropertyView(PropertyViewStatusType status) + : _status(status), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _required(false), + _noData(std::nullopt), + _defaultValue(std::nullopt) {} + + /** + * @brief Constructs a property instance from a property table property and + * its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyTableProperty& /*property*/) + : PropertyView(classProperty) {} + +public: + /** + * @copydoc PropertyView::status + */ + PropertyViewStatusType status() const noexcept { return _status; } + + /** + * @copydoc PropertyView::name + */ + const std::optional& name() const noexcept { return _name; } + + /** + * @copydoc PropertyView::semantic + */ + const std::optional& semantic() const noexcept { + return _semantic; + } + + /** + * @copydoc PropertyView::description + */ + const std::optional& description() const noexcept { + return _description; + } + + /** + * @copydoc PropertyView::arrayCount + */ + int64_t arrayCount() const noexcept { return 0; } + + /** + * @copydoc PropertyView::normalized + */ + bool normalized() const noexcept { return false; } + + /** + * @copydoc PropertyView::offset + */ + std::optional offset() const noexcept { + return std::nullopt; + } + + /** + * @copydoc PropertyView::scale + */ + std::optional scale() const noexcept { + return std::nullopt; + } + + /** + * @copydoc PropertyView::max + */ + std::optional max() const noexcept { return std::nullopt; } + + /** + * @copydoc PropertyView::min + */ + std::optional min() const noexcept { return std::nullopt; } + + /** + * @copydoc PropertyView::required + */ + bool required() const noexcept { return _required; } + + /** + * @copydoc PropertyView::noData + */ + std::optional noData() const noexcept { + if (_noData) + return std::string_view(*_noData); + + return std::nullopt; + } + + /** + * @copydoc PropertyView::defaultValue + */ + std::optional defaultValue() const noexcept { + if (_defaultValue) + return std::string_view(*_defaultValue); + + return std::nullopt; + } + +protected: + /** @copydoc PropertyViewStatus */ + PropertyViewStatusType _status; + +private: + std::optional _name; + std::optional _semantic; + std::optional _description; + + bool _required; + std::optional _noData; + std::optional _defaultValue; + + static std::optional + getStringValue(const CesiumUtility::JsonValue& value) { + if (!value.isString()) { + return std::nullopt; + } + + return std::string(value.getString().c_str()); + } +}; + +/** + * @brief Represents a non-normalized array metadata property in + * EXT_structural_metadata. + * + * Whether they belong to property tables, property textures, or property + * attributes, properties have their own sub-properties affecting the actual + * property values. Although they are typically defined via class property, they + * may be overridden by individual instances of the property themselves. The + * constructor is responsible for resolving those differences. + * + * @tparam ElementType The C++ type of the elements in the array values for this + * property. + */ +template +class PropertyView, false> { +public: + /** + * @brief Constructs an empty property instance. + */ + PropertyView() + : _status(PropertyViewStatus::ErrorNonexistentProperty), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _count(0), + _offset(std::nullopt), + _scale(std::nullopt), + _max(std::nullopt), + _min(std::nullopt), + _required(false), + _noData(std::nullopt), + _defaultValue(std::nullopt) {} + + /** + * @brief Constructs a property instance from a class definition only. + */ + PropertyView(const ClassProperty& classProperty) + : _status(validateArrayPropertyType>( + classProperty)), + _name(classProperty.name), + _semantic(classProperty.semantic), + _description(classProperty.description), + _count(_count = classProperty.count ? *classProperty.count : 0), + _offset(std::nullopt), + _scale(std::nullopt), + _max(std::nullopt), + _min(std::nullopt), + _required(classProperty.required), + _noData(std::nullopt), + _defaultValue(std::nullopt) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + if (classProperty.normalized) { + _status = PropertyViewStatus::ErrorNormalizationMismatch; + return; + } + + getNumericPropertyValues(classProperty); + if (_status != PropertyViewStatus::Valid) { + return; + } + + if (classProperty.noData) { + if (!_required) { + _noData = getArrayValue(*classProperty.noData); + } + + if (!_noData) { + _status = PropertyViewStatus::ErrorInvalidNoDataValue; + return; + } + } + + if (classProperty.defaultProperty) { + if (!_required) { + _defaultValue = getArrayValue(*classProperty.defaultProperty); + } + + if (!_defaultValue) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidDefaultValue; + return; + } + } + } + +protected: + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The value of {@link PropertyViewStatus} indicating the error with the property. + */ + PropertyView(PropertyViewStatusType status) + : _status(status), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _count(0), + _offset(std::nullopt), + _scale(std::nullopt), + _max(std::nullopt), + _min(std::nullopt), + _required(false), + _noData(std::nullopt), + _defaultValue(std::nullopt) {} + + /** + * @brief Constructs a property instance from a property table property and + * its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyTableProperty& property) + : PropertyView(classProperty) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + // If the property has its own values, override the class-provided values. + getNumericPropertyValues(property); + } + + /** + * @brief Constructs a property instance from a property texture property and + * its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyTextureProperty& property) + : PropertyView(classProperty) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + // If the property has its own values, override the class-provided values. + getNumericPropertyValues(property); + } + +public: + /** + * @copydoc PropertyView::status + */ + PropertyViewStatusType status() const noexcept { return _status; } + + /** + * @copydoc PropertyView::name + */ + const std::optional& name() const noexcept { return _name; } + + /** + * @copydoc PropertyView::semantic + */ + const std::optional& semantic() const noexcept { + return _semantic; + } + + /** + * @copydoc PropertyView::description + */ + const std::optional& description() const noexcept { + return _description; + } + + /** + * @copydoc PropertyView::arrayCount + */ + int64_t arrayCount() const noexcept { return _count; } + + /** + * @copydoc PropertyView::normalized + */ + bool normalized() const noexcept { return false; } + + /** + * @copydoc PropertyView::offset + */ + std::optional> offset() const noexcept { + if (!_offset) { + return std::nullopt; + } + + return PropertyArrayView( + std::span(_offset->data(), _offset->size())); + } + + /** + * @copydoc PropertyView::scale + */ + std::optional> scale() const noexcept { + if (!_scale) { + return std::nullopt; + } + + return PropertyArrayView( + std::span(_scale->data(), _scale->size())); + } + + /** + * @copydoc PropertyView::max + */ + std::optional> max() const noexcept { + if (!_max) { + return std::nullopt; + } + + return PropertyArrayView( + std::span(_max->data(), _max->size())); + } + + /** + * @copydoc PropertyView::min + */ + std::optional> min() const noexcept { + if (!_min) { + return std::nullopt; + } + + return PropertyArrayView( + std::span(_min->data(), _min->size())); + } + + /** + * @copydoc PropertyView::required + */ + bool required() const noexcept { return _required; } + + /** + * @copydoc PropertyView::noData + */ + std::optional> noData() const noexcept { + if (!_noData) { + return std::nullopt; + } + + return PropertyArrayView( + std::span(_noData->data(), _noData->size())); + } + + /** + * @copydoc PropertyView::defaultValue + */ + std::optional> defaultValue() const noexcept { + if (!_defaultValue) { + return std::nullopt; + } + + return PropertyArrayView(std::span( + _defaultValue->data(), + _defaultValue->size())); + } + +protected: + /** @copydoc PropertyViewStatus */ + PropertyViewStatusType _status; + +private: + std::optional _name; + std::optional _semantic; + std::optional _description; + + int64_t _count; + + std::optional> _offset; + std::optional> _scale; + std::optional> _max; + std::optional> _min; + + bool _required; + std::optional> _noData; + std::optional> _defaultValue; + + using PropertyDefinitionType = std:: + variant; + void getNumericPropertyValues(const PropertyDefinitionType& inProperty) { + std::visit( + [this](auto property) { + if (property.offset) { + // Only floating point types can specify an offset. + switch (TypeToPropertyType::component) { + case PropertyComponentType::Float32: + case PropertyComponentType::Float64: + if (this->_count > 0) { + this->_offset = getArrayValue(*property.offset); + } + if (this->_offset && + getCount(this->_offset) == this->_count) { + break; + } + // If it does not break here, something went wrong. + [[fallthrough]]; + default: + this->_status = PropertyViewStatus::ErrorInvalidOffset; + return; + } + } + + if (property.scale) { + // Only floating point types can specify a scale. + switch (TypeToPropertyType::component) { + case PropertyComponentType::Float32: + case PropertyComponentType::Float64: + if (_count > 0) { + this->_scale = getArrayValue(*property.scale); + } + if (this->_scale && + getCount(this->_scale) == this->_count) { + break; + } + // If it does not break here, something went wrong. + [[fallthrough]]; + default: + this->_status = PropertyViewStatus::ErrorInvalidScale; + return; + } + } + + if (property.max) { + if (this->_count > 0) { + this->_max = getArrayValue(*property.max); + } + if (!this->_max || + getCount(this->_max) != this->_count) { + // The value was specified but something went wrong. + this->_status = PropertyViewStatus::ErrorInvalidMax; + return; + } + } + + if (property.min) { + if (this->_count > 0) { + this->_min = getArrayValue(*property.min); + } + if (!this->_min || + getCount(this->_min) != this->_count) { + // The value was specified but something went wrong. + this->_status = PropertyViewStatus::ErrorInvalidMin; + return; + } + } + }, + inProperty); + } + + static std::optional> + getArrayValue(const CesiumUtility::JsonValue& jsonValue) { + if (!jsonValue.isArray()) { + return std::nullopt; + } + + const CesiumUtility::JsonValue::Array& array = jsonValue.getArray(); + std::vector values; + values.reserve(array.size()); + + if constexpr (IsMetadataScalar::value) { + for (size_t i = 0; i < array.size(); i++) { + std::optional element = getScalar(array[i]); + if (!element) { + return std::nullopt; + } + + values.push_back(*element); + } + } + if constexpr (IsMetadataVecN::value) { + for (size_t i = 0; i < array.size(); i++) { + std::optional element = getVecN(array[i]); + if (!element) { + return std::nullopt; + } + + values.push_back(*element); + } + } + + if constexpr (IsMetadataMatN::value) { + for (size_t i = 0; i < array.size(); i++) { + std::optional element = getMatN(array[i]); + if (!element) { + return std::nullopt; + } + + values.push_back(*element); + } + } + + std::vector result(values.size() * sizeof(ElementType)); + std::memcpy(result.data(), values.data(), result.size()); + + return result; + } +}; + +/** + * @brief Represents a normalized array metadata property in + * EXT_structural_metadata. + * + * Whether they belong to property tables, property textures, or property + * attributes, properties have their own sub-properties affecting the actual + * property values. Although they are typically defined via class property, they + * may be overridden by individual instances of the property themselves. The + * constructor is responsible for resolving those differences. + * + * @tparam ElementType The C++ type of the elements in the array values for this + * property. Must have an integer component type. + */ +template +class PropertyView, true> { +private: + using NormalizedType = typename TypeToNormalizedType::type; + +public: + /** + * @brief Constructs an empty property instance. + */ + PropertyView() + : _status(PropertyViewStatus::ErrorNonexistentProperty), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _count(0), + _offset(std::nullopt), + _scale(std::nullopt), + _max(std::nullopt), + _min(std::nullopt), + _required(false), + _noData(std::nullopt), + _defaultValue(std::nullopt) {} + + /** + * @brief Constructs a property instance from a class definition only. + */ + PropertyView(const ClassProperty& classProperty) + : _status(validateArrayPropertyType>( + classProperty)), + _name(classProperty.name), + _semantic(classProperty.semantic), + _description(classProperty.description), + _count(_count = classProperty.count ? *classProperty.count : 0), + _offset(std::nullopt), + _scale(std::nullopt), + _max(std::nullopt), + _min(std::nullopt), + _required(classProperty.required), + _noData(std::nullopt), + _defaultValue(std::nullopt) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + if (!classProperty.normalized) { + _status = PropertyViewStatus::ErrorNormalizationMismatch; + return; + } + + getNumericPropertyValues(classProperty); + if (_status != PropertyViewStatus::Valid) { + return; + } + + if (classProperty.noData) { + if (!_required) { + _noData = getArrayValue(*classProperty.noData); + } + + if (!_noData) { + _status = PropertyViewStatus::ErrorInvalidNoDataValue; + return; + } + } + + if (classProperty.defaultProperty) { + if (!_required) { + _defaultValue = + getArrayValue(*classProperty.defaultProperty); + } + + if (!_defaultValue) { + _status = PropertyViewStatus::ErrorInvalidDefaultValue; + return; + } + } + } + +protected: + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The value of {@link PropertyViewStatus} indicating the error with the property. + */ + PropertyView(PropertyViewStatusType status) + : _status(status), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _count(0), + _offset(std::nullopt), + _scale(std::nullopt), + _max(std::nullopt), + _min(std::nullopt), + _required(false), + _noData(std::nullopt), + _defaultValue(std::nullopt) {} + + /** + * @brief Constructs a property instance from a property table property and + * its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyTableProperty& property) + : PropertyView(classProperty) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + // If the property has its own values, override the class-provided values. + getNumericPropertyValues(property); + } + + /** + * @brief Constructs a property instance from a property texture property and + * its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyTextureProperty& property) + : PropertyView(classProperty) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + // If the property has its own values, override the class-provided values. + getNumericPropertyValues(property); + } + +public: + /** + * @copydoc PropertyView::status + */ + PropertyViewStatusType status() const noexcept { return _status; } + + /** + * @copydoc PropertyView::name + */ + const std::optional& name() const noexcept { return _name; } + + /** + * @copydoc PropertyView::semantic + */ + const std::optional& semantic() const noexcept { + return _semantic; + } + + /** + * @copydoc PropertyView::description + */ + const std::optional& description() const noexcept { + return _description; + } + + /** + * @copydoc PropertyView::arrayCount + */ + int64_t arrayCount() const noexcept { return _count; } + + /** + * @copydoc PropertyView::normalized + */ + bool normalized() const noexcept { return true; } + + /** + * @copydoc PropertyView::offset + */ + std::optional> offset() const noexcept { + if (!_offset) { + return std::nullopt; + } + + return PropertyArrayView( + std::span(_offset->data(), _offset->size())); + } + + /** + * @copydoc PropertyView::scale + */ + std::optional> scale() const noexcept { + if (!_scale) { + return std::nullopt; + } + + return PropertyArrayView( + std::span(_scale->data(), _scale->size())); + } + + /** + * @copydoc PropertyView::max + */ + std::optional> max() const noexcept { + if (!_max) { + return std::nullopt; + } + + return PropertyArrayView( + std::span(_max->data(), _max->size())); + } + + /** + * @copydoc PropertyView::min + */ + std::optional> min() const noexcept { + if (!_min) { + return std::nullopt; + } + + return PropertyArrayView( + std::span(_min->data(), _min->size())); + } + + /** + * @copydoc PropertyView::required + */ + bool required() const noexcept { return _required; } + + /** + * @copydoc PropertyView::noData + */ + std::optional> noData() const noexcept { + if (!_noData) { + return std::nullopt; + } + + return PropertyArrayView( + std::span(_noData->data(), _noData->size())); + } + + /** + * @copydoc PropertyView::defaultValue + */ + std::optional> + defaultValue() const noexcept { + if (!_defaultValue) { + return std::nullopt; + } + + return PropertyArrayView(std::span( + _defaultValue->data(), + _defaultValue->size())); + } + +protected: + /** @copydoc PropertyViewStatus */ + PropertyViewStatusType _status; + +private: + std::optional _name; + std::optional _semantic; + std::optional _description; + + int64_t _count; + + std::optional> _offset; + std::optional> _scale; + std::optional> _max; + std::optional> _min; + + bool _required; + std::optional> _noData; + std::optional> _defaultValue; + + using PropertyDefinitionType = std:: + variant; + void getNumericPropertyValues(const PropertyDefinitionType& inProperty) { + std::visit( + [this](auto property) { + if (property.offset) { + if (_count > 0) { + _offset = getArrayValue(*property.offset); + } + if (!_offset || getCount(_offset) != _count) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidOffset; + return; + } + } + + if (property.scale) { + if (_count > 0) { + _scale = getArrayValue(*property.scale); + } + if (!_scale || getCount(_scale) != _count) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidScale; + return; + } + } + + if (property.max) { + if (_count > 0) { + _max = getArrayValue(*property.max); + } + if (!_max || getCount(_max) != _count) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidMax; + return; + } + } + + if (property.min) { + if (_count > 0) { + _min = getArrayValue(*property.min); + } + if (!_min || getCount(_min) != _count) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidMin; + return; + } + } + }, + inProperty); + } + + template + static std::optional> + getArrayValue(const CesiumUtility::JsonValue& jsonValue) { + if (!jsonValue.isArray()) { + return std::nullopt; + } + + const CesiumUtility::JsonValue::Array& array = jsonValue.getArray(); + std::vector values; + values.reserve(array.size()); + + if constexpr (IsMetadataScalar::value) { + for (size_t i = 0; i < array.size(); i++) { + std::optional element = getScalar(array[i]); + if (!element) { + return std::nullopt; + } + + values.push_back(*element); + } + } + + if constexpr (IsMetadataVecN::value) { + for (size_t i = 0; i < array.size(); i++) { + std::optional element = getVecN(array[i]); + if (!element) { + return std::nullopt; + } + + values.push_back(*element); + } + } + + if constexpr (IsMetadataMatN::value) { + for (size_t i = 0; i < array.size(); i++) { + std::optional element = getMatN(array[i]); + if (!element) { + return std::nullopt; + } + + values.push_back(*element); + } + } + + std::vector result(values.size() * sizeof(T)); + std::memcpy(result.data(), values.data(), result.size()); + + return result; + } +}; + +/** + * @brief Represents a boolean array metadata property in + * EXT_structural_metadata. + */ +template <> class PropertyView> { +public: + /** + * @brief Constructs an empty property instance. + */ + PropertyView() + : _status(PropertyViewStatus::ErrorNonexistentProperty), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _count(0), + _required(false), + _defaultValue(), + _size(0) {} + + /** + * @brief Constructs a property instance from a class definition only. + */ + PropertyView(const ClassProperty& classProperty) + : _status( + validateArrayPropertyType>(classProperty)), + _name(classProperty.name), + _semantic(classProperty.semantic), + _description(classProperty.description), + _count(classProperty.count ? *classProperty.count : 0), + _required(classProperty.required), + _defaultValue(), + _size(0) { + if (_status != PropertyViewStatus::Valid) { + return; + } + + if (classProperty.defaultProperty) { + if (!_required) { + _defaultValue = + getBooleanArrayValue(*classProperty.defaultProperty, _size); + } + + if (_size == 0 || (_count > 0 && _size != _count)) { + _status = PropertyViewStatus::ErrorInvalidDefaultValue; + return; + } + } + } + +protected: + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The value of {@link PropertyViewStatus} indicating the error with the property. + */ + PropertyView(PropertyViewStatusType status) + : _status(status), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _count(0), + _required(false), + _defaultValue(), + _size(0) {} + + /** + * @brief Constructs a property instance from a property table property and + * its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyTableProperty& /*property*/) + : PropertyView(classProperty) {} + +public: + /** + * @copydoc PropertyView::status + */ + PropertyViewStatusType status() const noexcept { return _status; } + + /** + * @copydoc PropertyView::name + */ + const std::optional& name() const noexcept { return _name; } + + /** + * @copydoc PropertyView::semantic + */ + const std::optional& semantic() const noexcept { + return _semantic; + } + + /** + * @copydoc PropertyView::description + */ + const std::optional& description() const noexcept { + return _description; + } + + /** + * @copydoc PropertyView::arrayCount + */ + int64_t arrayCount() const noexcept { return _count; } + + /** + * @copydoc PropertyView::normalized + */ + bool normalized() const noexcept { return false; } + + /** + * @copydoc PropertyView::offset + */ + std::optional> offset() const noexcept { + return std::nullopt; + } + + /** + * @copydoc PropertyView::scale + */ + std::optional> scale() const noexcept { + return std::nullopt; + } + + /** + * @copydoc PropertyView::max + */ + std::optional> max() const noexcept { + return std::nullopt; + } + + /** + * @copydoc PropertyView::min + */ + std::optional> min() const noexcept { + return std::nullopt; + } + + /** + * @copydoc PropertyView::required + */ + bool required() const noexcept { return _required; } + + /** + * @copydoc PropertyView::noData + */ + std::optional> noData() const noexcept { + return std::nullopt; + } + + /** + * @copydoc PropertyView::defaultValue + */ + std::optional> defaultValue() const noexcept { + if (_size > 0) { + return PropertyArrayView( + std::span( + _defaultValue.data(), + _defaultValue.size()), + /* bitOffset = */ 0, + _size); + } + + return std::nullopt; + } + +protected: + /** @copydoc PropertyViewStatus */ + PropertyViewStatusType _status; + +private: + std::optional _name; + std::optional _semantic; + std::optional _description; + + int64_t _count; + bool _required; + + std::vector _defaultValue; + int64_t _size; + + static std::vector getBooleanArrayValue( + const CesiumUtility::JsonValue& jsonValue, + int64_t& size) { + if (!jsonValue.isArray()) { + return std::vector(); + } + + const CesiumUtility::JsonValue::Array& array = jsonValue.getArray(); + std::vector values; + values.reserve((array.size() / 8) + 1); + + size_t byteIndex = 0; + uint8_t bitIndex = 0; + + for (size_t i = 0; i < array.size(); i++, size++) { + if (!array[i].isBool()) { + size = 0; + return values; + } + + if (values.size() < byteIndex - 1) { + values.push_back(std::byte(0)); + } + + std::byte value = std::byte(array[i].getBool() ? 1 : 0); + value = value << bitIndex; + + values[byteIndex] |= value; + + bitIndex++; + if (bitIndex > 7) { + byteIndex++; + bitIndex = 0; + } + } + + return values; + } +}; + +/** + * @brief Represents a string array metadata property in + * EXT_structural_metadata. + */ +template <> class PropertyView> { +public: + /** + * @brief Constructs an empty property instance. + */ + PropertyView() + : _status(PropertyViewStatus::ErrorNonexistentProperty), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _count(0), + _required(false), + _noData(), + _defaultValue() {} + + /** + * @brief Constructs a property instance from a class definition only. + */ + PropertyView(const ClassProperty& classProperty) + : _status(validateArrayPropertyType>( + classProperty)), + _name(classProperty.name), + _semantic(classProperty.semantic), + _description(classProperty.description), + _count(classProperty.count ? *classProperty.count : 0), + _required(classProperty.required), + _noData(), + _defaultValue() { + if (_status != PropertyViewStatus::Valid) { + return; + } + + if (classProperty.noData) { + if (!_required) { + _noData = getStringArrayValue(*classProperty.noData); + } + + if (_noData.size == 0 || (_count > 0 && _noData.size != _count)) { + _status = PropertyViewStatus::ErrorInvalidNoDataValue; + return; + } + } + + if (classProperty.defaultProperty) { + if (!_required) { + _defaultValue = getStringArrayValue(*classProperty.defaultProperty); + } + + if (_defaultValue.size == 0 || + (_count > 0 && _defaultValue.size != _count)) { + // The value was specified but something went wrong. + _status = PropertyViewStatus::ErrorInvalidDefaultValue; + return; + } + } + } + +protected: + /** + * @brief Constructs an invalid instance for an erroneous property. + * + * @param status The value of {@link PropertyViewStatus} indicating the error with the property. + */ + PropertyView(PropertyViewStatusType status) + : _status(status), + _name(std::nullopt), + _semantic(std::nullopt), + _description(std::nullopt), + _count(0), + _required(false), + _noData(), + _defaultValue() {} + + /** + * @brief Constructs a property instance from a property table property + * and its class definition. + */ + PropertyView( + const ClassProperty& classProperty, + const PropertyTableProperty& /*property*/) + : PropertyView(classProperty) {} + +public: + /** + * @copydoc PropertyView::status + */ + PropertyViewStatusType status() const noexcept { return _status; } + + /** + * @copydoc PropertyView::name + */ + const std::optional& name() const noexcept { return _name; } + + /** + * @copydoc PropertyView::semantic + */ + const std::optional& semantic() const noexcept { + return _semantic; + } + + /** + * @copydoc PropertyView::description + */ + const std::optional& description() const noexcept { + return _description; + } + + /** + * @copydoc PropertyView::arrayCount + */ + int64_t arrayCount() const noexcept { return _count; } + + /** + * @copydoc PropertyView::normalized + */ + bool normalized() const noexcept { return false; } + + /** + * @copydoc PropertyView::offset + */ + std::optional> offset() const noexcept { + return std::nullopt; + } + + /** + * @copydoc PropertyView::scale + */ + std::optional> scale() const noexcept { + return std::nullopt; + } + + /** + * @copydoc PropertyView::max + */ + std::optional> max() const noexcept { + return std::nullopt; + } + + /** + * @copydoc PropertyView::min + */ + std::optional> min() const noexcept { + return std::nullopt; + } + + /** + * @copydoc PropertyView::required + */ + bool required() const noexcept { return _required; } + + /** + * @copydoc PropertyView::noData + */ + std::optional> noData() const noexcept { + if (_noData.size > 0) { + return PropertyArrayView( + std::span(_noData.data.data(), _noData.data.size()), + std::span( + _noData.offsets.data(), + _noData.offsets.size()), + _noData.offsetType, + _noData.size); + } + + return std::nullopt; + } + + /** + * @copydoc PropertyView::defaultValue + */ + std::optional> + defaultValue() const noexcept { + if (_defaultValue.size > 0) { + return PropertyArrayView( + std::span( + _defaultValue.data.data(), + _defaultValue.data.size()), + std::span( + _defaultValue.offsets.data(), + _defaultValue.offsets.size()), + _defaultValue.offsetType, + _defaultValue.size); + } + + return std::nullopt; + } + +protected: + /** @copydoc PropertyViewStatus */ + PropertyViewStatusType _status; + +private: + std::optional _name; + std::optional _semantic; + std::optional _description; + + int64_t _count; + bool _required; + + struct StringArrayValue { + std::vector data; + std::vector offsets; + PropertyComponentType offsetType = PropertyComponentType::None; + int64_t size = 0; + }; + + StringArrayValue _noData; + StringArrayValue _defaultValue; + + static StringArrayValue + getStringArrayValue(const CesiumUtility::JsonValue& jsonValue) { + StringArrayValue result; + if (!jsonValue.isArray()) { + return result; + } + + std::vector strings; + std::vector stringOffsets; + + const auto array = jsonValue.getArray(); + strings.reserve(array.size()); + stringOffsets.reserve(array.size() + 1); + stringOffsets.push_back(static_cast(0)); + + for (size_t i = 0; i < array.size(); i++) { + if (!array[i].isString()) { + // The entire array is invalidated; return. + return result; + } + + const std::string& string = array[i].getString(); + strings.push_back(string); + stringOffsets.push_back(stringOffsets[i] + string.size()); + } + + uint64_t totalLength = stringOffsets.back(); + result.data.resize(totalLength); + for (size_t i = 0; i < strings.size(); ++i) { + std::memcpy( + result.data.data() + stringOffsets[i], + strings[i].data(), + strings[i].size()); + }; + + if (totalLength <= std::numeric_limits::max()) { + result.offsets = narrowOffsetsBuffer(stringOffsets); + result.offsetType = PropertyComponentType::Uint8; + } else if (totalLength <= std::numeric_limits::max()) { + result.offsets = narrowOffsetsBuffer(stringOffsets); + result.offsetType = PropertyComponentType::Uint16; + } else if (totalLength <= std::numeric_limits::max()) { + result.offsets = narrowOffsetsBuffer(stringOffsets); + result.offsetType = PropertyComponentType::Uint32; + } else { + result.offsets.resize(stringOffsets.size() * sizeof(uint64_t)); + std::memcpy( + result.offsets.data(), + stringOffsets.data(), + result.offsets.size()); + result.offsetType = PropertyComponentType::Uint64; + } + + result.size = static_cast(strings.size()); + + return result; + } + + template + static std::vector + narrowOffsetsBuffer(std::vector offsets) { + std::vector result(offsets.size() * sizeof(T)); + size_t bufferOffset = 0; + for (size_t i = 0; i < offsets.size(); i++, bufferOffset += sizeof(T)) { + T offset = static_cast(offsets[i]); + std::memcpy(result.data() + bufferOffset, &offset, sizeof(T)); + } + + return result; + } +}; + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Sampler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Sampler.h new file mode 100644 index 0000000..79e5143 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Sampler.h @@ -0,0 +1,131 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief Texture sampler properties for filtering and wrapping modes. + */ +struct CESIUMGLTF_API Sampler final : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Sampler"; + + /** + * @brief Known values for Magnification filter. + */ + struct MagFilter { + /** @brief NEAREST (`9728`) */ + static constexpr int32_t NEAREST = 9728; + + /** @brief LINEAR (`9729`) */ + static constexpr int32_t LINEAR = 9729; + }; + + /** + * @brief Known values for Minification filter. + */ + struct MinFilter { + /** @brief NEAREST (`9728`) */ + static constexpr int32_t NEAREST = 9728; + + /** @brief LINEAR (`9729`) */ + static constexpr int32_t LINEAR = 9729; + + /** @brief NEAREST_MIPMAP_NEAREST (`9984`) */ + static constexpr int32_t NEAREST_MIPMAP_NEAREST = 9984; + + /** @brief LINEAR_MIPMAP_NEAREST (`9985`) */ + static constexpr int32_t LINEAR_MIPMAP_NEAREST = 9985; + + /** @brief NEAREST_MIPMAP_LINEAR (`9986`) */ + static constexpr int32_t NEAREST_MIPMAP_LINEAR = 9986; + + /** @brief LINEAR_MIPMAP_LINEAR (`9987`) */ + static constexpr int32_t LINEAR_MIPMAP_LINEAR = 9987; + }; + + /** + * @brief Known values for S (U) wrapping mode. + */ + struct WrapS { + /** @brief CLAMP_TO_EDGE (`33071`) */ + static constexpr int32_t CLAMP_TO_EDGE = 33071; + + /** @brief MIRRORED_REPEAT (`33648`) */ + static constexpr int32_t MIRRORED_REPEAT = 33648; + + /** @brief REPEAT (`10497`) */ + static constexpr int32_t REPEAT = 10497; + }; + + /** + * @brief Known values for T (V) wrapping mode. + */ + struct WrapT { + /** @brief CLAMP_TO_EDGE (`33071`) */ + static constexpr int32_t CLAMP_TO_EDGE = 33071; + + /** @brief MIRRORED_REPEAT (`33648`) */ + static constexpr int32_t MIRRORED_REPEAT = 33648; + + /** @brief REPEAT (`10497`) */ + static constexpr int32_t REPEAT = 10497; + }; + + /** + * @brief Magnification filter. + * + * Known values are defined in {@link MagFilter}. + * + */ + std::optional magFilter; + + /** + * @brief Minification filter. + * + * Known values are defined in {@link MinFilter}. + * + */ + std::optional minFilter; + + /** + * @brief S (U) wrapping mode. + * + * Known values are defined in {@link WrapS}. + * + * + * All valid values correspond to WebGL enums. + */ + int32_t wrapS = WrapS::REPEAT; + + /** + * @brief T (V) wrapping mode. + * + * Known values are defined in {@link WrapT}. + * + */ + int32_t wrapT = WrapT::REPEAT; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Sampler)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/SamplerUtility.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/SamplerUtility.h new file mode 100644 index 0000000..ac62b84 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/SamplerUtility.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace CesiumGltf { +/** + * @brief Applies a sampler's WrapS value to the given U component of a texture + * coordinate. + * + * @param u The U coordinate to apply the sampler wrap value to. + * @param wrapS The sampler's WrapS value, matching a member of \ref + * Sampler::WrapS, to apply. + * @returns The U coordinate after applying the WrapS operation. + */ +double applySamplerWrapS(const double u, const int32_t wrapS); +/** + * @brief Applies a sampler's WrapT value to the given V component of a texture + * coordinate. + * + * @param v The V coordinate to apply the sampler wrap value to. + * @param wrapT The sampler's WrapT value, matching a member of \ref + * Sampler::WrapT, to apply. + * @returns The V coordinate after applying the WrapT operation. + */ +double applySamplerWrapT(const double v, const int32_t wrapT); +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Scene.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Scene.h new file mode 100644 index 0000000..3d726cc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Scene.h @@ -0,0 +1,41 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief The root nodes of a scene. + */ +struct CESIUMGLTF_API Scene final : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Scene"; + + /** + * @brief The indices of each root node. + */ + std::vector nodes; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Scene)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + accum += int64_t(sizeof(int32_t) * this->nodes.capacity()); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Schema.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Schema.h new file mode 100644 index 0000000..c16e3f3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Schema.h @@ -0,0 +1,97 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace CesiumGltf { +/** + * @brief An object defining classes and enums. + */ +struct CESIUMGLTF_API Schema final : public CesiumUtility::SharedAsset { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Schema"; + + /** + * @brief Unique identifier for the schema. Schema IDs must be alphanumeric + * identifiers matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`. + */ + std::string id; + + /** + * @brief The name of the schema, e.g. for display purposes. + */ + std::optional name; + + /** + * @brief The description of the schema. + */ + std::optional description; + + /** + * @brief Application-specific version of the schema. + */ + std::optional version; + + /** + * @brief A dictionary, where each key is a class ID and each value is an + * object defining the class. Class IDs must be alphanumeric identifiers + * matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`. + */ + std::unordered_map classes; + + /** + * @brief A dictionary, where each key is an enum ID and each value is an + * object defining the values for the enum. Enum IDs must be alphanumeric + * identifiers matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`. + */ + std::unordered_map enums; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Schema)); + accum += CesiumUtility::SharedAsset::getSizeBytes() - + int64_t(sizeof(CesiumUtility::SharedAsset)); + accum += int64_t(this->id.capacity() * sizeof(char)); + if (this->name) { + accum += int64_t(this->name->capacity() * sizeof(char)); + } + if (this->description) { + accum += int64_t(this->description->capacity() * sizeof(char)); + } + if (this->version) { + accum += int64_t(this->version->capacity() * sizeof(char)); + } + accum += int64_t( + this->classes.bucket_count() * + (sizeof(std::string) + sizeof(CesiumGltf::Class))); + for (const auto& [k, v] : this->classes) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - int64_t(sizeof(CesiumGltf::Class)); + } + accum += int64_t( + this->enums.bucket_count() * + (sizeof(std::string) + sizeof(CesiumGltf::Enum))); + for (const auto& [k, v] : this->enums) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - int64_t(sizeof(CesiumGltf::Enum)); + } + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Skin.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Skin.h new file mode 100644 index 0000000..ce5d00a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Skin.h @@ -0,0 +1,59 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include +#include + +namespace CesiumGltf { +/** + * @brief Joints and matrices defining a skin. + */ +struct CESIUMGLTF_API Skin final : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Skin"; + + /** + * @brief The index of the accessor containing the floating-point 4x4 + * inverse-bind matrices. + * + * Its `accessor.count` property **MUST** be greater than or equal to the + * number of elements of the `joints` array. When undefined, each matrix is a + * 4x4 identity matrix. + */ + int32_t inverseBindMatrices = -1; + + /** + * @brief The index of the node used as a skeleton root. + * + * The node **MUST** be the closest common root of the joints hierarchy or a + * direct or indirect parent node of the closest common root. + */ + int32_t skeleton = -1; + + /** + * @brief Indices of skeleton nodes, used as joints in this skin. + */ + std::vector joints; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Skin)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + accum += int64_t(sizeof(int32_t) * this->joints.capacity()); + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Texture.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Texture.h new file mode 100644 index 0000000..9326756 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Texture.h @@ -0,0 +1,48 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief A texture and its sampler. + */ +struct CESIUMGLTF_API Texture final : public CesiumGltf::NamedObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Texture"; + + /** + * @brief The index of the sampler used by this texture. When undefined, a + * sampler with repeat wrapping and auto filtering **SHOULD** be used. + */ + int32_t sampler = -1; + + /** + * @brief The index of the image used by this texture. When undefined, an + * extension or other mechanism **SHOULD** supply an alternate texture source, + * otherwise behavior is undefined. + */ + int32_t source = -1; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(Texture)); + accum += CesiumGltf::NamedObject::getSizeBytes() - + int64_t(sizeof(CesiumGltf::NamedObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/TextureInfo.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/TextureInfo.h new file mode 100644 index 0000000..391f26f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/TextureInfo.h @@ -0,0 +1,52 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumGltf { +/** + * @brief Reference to a texture. + */ +struct CESIUMGLTF_API TextureInfo : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "TextureInfo"; + + /** + * @brief The index of the texture. + */ + int32_t index = -1; + + /** + * @brief The set index of texture's TEXCOORD attribute used for texture + * coordinate mapping. + * + * This integer value is used to construct a string in the format + * `TEXCOORD_` which is a reference to a key in + * `mesh.primitives.attributes` (e.g. a value of `0` corresponds to + * `TEXCOORD_0`). A mesh primitive **MUST** have the corresponding texture + * coordinate attributes for the material to be applicable to it. + */ + int64_t texCoord = 0; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(TextureInfo)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/TextureView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/TextureView.h new file mode 100644 index 0000000..6bbf6f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/TextureView.h @@ -0,0 +1,225 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace CesiumGltf { + +struct Model; + +/** + * @brief Describes options for constructing a view on a glTF texture. + */ +struct TextureViewOptions { + /** + * @brief Whether to automatically apply the `KHR_texture_transform` extension + * to the texture view, if it exists. + * + * A glTF texture may contain the `KHR_texture_transform` extension, which + * transforms the texture coordinates used to sample the texture. The + * extension may also override the TEXCOORD set index that was specified by + * the original texture info. + * + * If a view is constructed with applyKhrTextureTransformExtension set to + * true, it should automatically apply the texture transform to any UV + * coordinates used to sample the texture. If the extension defines its own + * TEXCOORD set index, it will override the original value. + * + * Otherwise, if the flag is set to false, UVs will not be transformed and + * the original TEXCOORD set index will be preserved. The extension's values + * may still be retrieved using getTextureTransform, if desired. + */ + bool applyKhrTextureTransformExtension = false; + + /** + * @brief Whether to copy the input image. + * + * By default, a view is constructed on the input glTF image without copying + * its pixels. This can be problematic for clients that move or delete the + * original glTF model. When this flag is true, the view will manage its own + * copy of the pixel data to avoid such issues. + */ + bool makeImageCopy = false; +}; + +/** + * @brief Indicates the status of a texture view. + * + * The {@link TextureView} constructor always completes + * successfully. However it may not always reflect the actual content of the + * corresponding texture. This enumeration provides the reason. + */ +enum class TextureViewStatus { + /** + * @brief This texture view is valid and ready to use. + */ + Valid, + + /** + * @brief This texture view has not yet been initialized. + */ + ErrorUninitialized, + + /** + * @brief This texture view does not have a valid texture index. + */ + ErrorInvalidTexture, + + /** + * @brief This texture view does not have a valid sampler index. + */ + ErrorInvalidSampler, + + /** + * @brief This texture view does not have a valid image index. + */ + ErrorInvalidImage, + + /** + * @brief This texture is viewing an empty image. + */ + ErrorEmptyImage, + + /** + * @brief The image for this texture has channels that take up more than a + * byte. Only single-byte channels are supported. + */ + ErrorInvalidBytesPerChannel, +}; + +/** + * @brief A view into the texture data of a single texture from a \ref Model. + */ +class TextureView { +public: + /** + * @brief Constructs an empty, uninitialized texture view. + */ + TextureView() noexcept; + + /** + * @brief Constructs a view of the texture specified by the given {@link TextureInfo}. + * + * @param model The glTF model in which to look for the texture's data. + * @param textureInfo The texture info to create a view for. + * @param options The options for constructing the view. + */ + TextureView( + const Model& model, + const TextureInfo& textureInfo, + const TextureViewOptions& options = TextureViewOptions()) noexcept; + + /** + * @brief Constructs a view of the texture specified by the given {@link Sampler} + * and {@link ImageAsset}. + * + * @param sampler The {@link Sampler} used by the texture. + * @param image The {@link ImageAsset} used by the texture. + * @param textureCoordinateSetIndex The set index for the `TEXCOORD_n` + * attribute used to sample this texture. + * @param pKhrTextureTransformExtension A pointer to the KHR_texture_transform + * extension on the texture, if it exists. + * @param options The options for constructing the view. + */ + TextureView( + const Sampler& sampler, + const ImageAsset& image, + int64_t textureCoordinateSetIndex, + const ExtensionKhrTextureTransform* pKhrTextureTransformExtension = + nullptr, + const TextureViewOptions& options = TextureViewOptions()) noexcept; + + /** + * @brief Get the status of this texture view. + * + * If invalid, it will not be safe to sample from this view. + */ + TextureViewStatus getTextureViewStatus() const noexcept { + return this->_textureViewStatus; + } + + /** + * @brief Get the texture coordinate set index for this view. + * If this view was constructed with options.applyKhrTextureTransformExtension + * as true, and if the texture contains the `KHR_texture_transform` extension, + * then this will return the value from the extension since it is meant to + * override the original index. However, if the extension does not specify a + * TEXCOORD set index, then the original index of the texture is returned. + */ + int64_t getTexCoordSetIndex() const noexcept { + if (this->_applyTextureTransform && this->_textureTransform) { + return this->_textureTransform->getTexCoordSetIndex().value_or( + this->_texCoordSetIndex); + } + return this->_texCoordSetIndex; + } + + /** + * @brief Get the sampler describing how to sample the data from the + * property's texture. + * + * This will be nullptr if the property texture property view runs into + * problems during construction. + */ + const Sampler* getSampler() const noexcept { return this->_pSampler; } + + /** + * @brief Get the image containing this property's data. If this view was + * constructed with options.makeImageCopy set to true, this will return a + * pointer to the copied image. + * + * This will be nullptr if the texture view runs into + * problems during construction. + */ + const ImageAsset* getImage() const noexcept { + if (this->_pImageCopy) { + return this->_pImageCopy.get(); + } + return this->_pImage.get(); + } + + /** + * @brief Get the KHR_texture_transform for this texture if it exists. + * + * Even if this view was constructed with + * options.applyKhrTextureTransformExtension set to false, it will save the + * extension's values, and they may be retrieved through this function. + * + * If this view was constructed with applyKhrTextureTransformExtension set + * to true, any texture coordinates passed into `get` or `getRaw` will be + * automatically transformed, so there's no need to re-apply the transform + * here. + */ + std::optional getTextureTransform() const noexcept { + return this->_textureTransform; + } + + /** + * @brief Samples the image at the specified texture coordinates using NEAREST + * pixel filtering, returning the bytes as uint8_t values. A channels vector + * must be supplied to specify how many image channels are needed, and in what + * order the bytes should be retrieved. + */ + std::vector sampleNearestPixel( + double u, + double v, + const std::vector& channels) const noexcept; + +private: + TextureViewStatus _textureViewStatus; + + const Sampler* _pSampler; + CesiumUtility::IntrusivePointer _pImage; + int64_t _texCoordSetIndex; + + bool _applyTextureTransform; + std::optional _textureTransform; + + CesiumUtility::IntrusivePointer _pImageCopy; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/VertexAttributeSemantics.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/VertexAttributeSemantics.h new file mode 100644 index 0000000..9eb0f21 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/VertexAttributeSemantics.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include + +namespace CesiumGltf { + +/** + * @brief The standard glTF vertex attribute semantics from the specification + * plus additional vertex attribute semantics from extensions. + */ +struct VertexAttributeSemantics { + /** + * @brief Unitless XYZ vertex positions. + */ + static const std::string POSITION; + + /** + * @brief Normalized XYZ vertex normals. + */ + static const std::string NORMAL; + + /** + * @brief XYZW vertex tangents where the XYZ portion is normalized, and the W + * component is a sign value (-1 or +1) indicating handedness of the tangent + * basis. + */ + static const std::string TANGENT; + + /** + * @brief ST texture coordinates + */ + static const std::array TEXCOORD_n; + + /** + * @brief RGB or RGBA vertex color linear multiplier. + */ + static const std::array COLOR_n; + + /** + * @brief The indices of the joints from the corresponding skin.joints array + * that affect the vertex. + */ + static const std::array JOINTS_n; + + /** + * @brief The weights indicating how strongly the joint influences the vertex. + */ + static const std::array WEIGHTS_n; + + /** + * @brief Feature IDs used by `EXT_mesh_features`. + */ + static const std::array FEATURE_ID_n; +}; + +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/getOffsetFromOffsetsBuffer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/getOffsetFromOffsetsBuffer.h new file mode 100644 index 0000000..6fcb96d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/getOffsetFromOffsetsBuffer.h @@ -0,0 +1,46 @@ +#pragma once + +#include "CesiumGltf/PropertyType.h" + +#include +#include + +#include +#include + +namespace CesiumGltf { +static size_t getOffsetFromOffsetsBuffer( + size_t index, + const std::span& offsetBuffer, + PropertyComponentType offsetType) noexcept { + switch (offsetType) { + case PropertyComponentType::Uint8: { + CESIUM_ASSERT(index < offsetBuffer.size() / sizeof(uint8_t)); + const uint8_t offset = *reinterpret_cast( + offsetBuffer.data() + index * sizeof(uint8_t)); + return static_cast(offset); + } + case PropertyComponentType::Uint16: { + CESIUM_ASSERT(index < offsetBuffer.size() / sizeof(uint16_t)); + const uint16_t offset = *reinterpret_cast( + offsetBuffer.data() + index * sizeof(uint16_t)); + return static_cast(offset); + } + case PropertyComponentType::Uint32: { + CESIUM_ASSERT(index < offsetBuffer.size() / sizeof(uint32_t)); + const uint32_t offset = *reinterpret_cast( + offsetBuffer.data() + index * sizeof(uint32_t)); + return static_cast(offset); + } + case PropertyComponentType::Uint64: { + CESIUM_ASSERT(index < offsetBuffer.size() / sizeof(uint64_t)); + const uint64_t offset = *reinterpret_cast( + offsetBuffer.data() + index * sizeof(uint64_t)); + return static_cast(offset); + } + default: + CESIUM_ASSERT(false && "Offset type is invalid"); + return 0; + } +} +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfContent/GltfUtilities.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfContent/GltfUtilities.h new file mode 100644 index 0000000..f6cce9a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfContent/GltfUtilities.h @@ -0,0 +1,344 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace CesiumGltf { +struct Buffer; +struct Model; +struct Node; +} // namespace CesiumGltf + +namespace CesiumGeometry { +class Ray; +} // namespace CesiumGeometry + +namespace CesiumGltfContent { +/** + * A collection of utility functions that are used to process and transform a + * gltf model + */ +struct CESIUMGLTFCONTENT_API GltfUtilities { + /** + * @brief Gets the transformation matrix for a given node. + * + * This returns the node's local transform as-is. It does not incorporate + * transforms from any of the node's ancestors. + * + * @param node The node from which to get the transformation matrix. + * @return The transformation matrix, or std::nullopt if the node's + * transformation is invalid, .e.g, because it has a matrix with fewer than + * 16 elements in it. + */ + static std::optional + getNodeTransform(const CesiumGltf::Node& node); + + /** + * @brief Sets the transformation matrix for a given node. + * + * This sets only the local transform of the node. It does not affect the + * transforms of any ancestor or descendant nodes, if present. + * + * @param node The node on which to set the transformation matrix. + * @param newTransform The new transformation matrix. + */ + static void + setNodeTransform(CesiumGltf::Node& node, const glm::dmat4x4& newTransform); + + /** + * @brief Applies the glTF's RTC_CENTER, if any, to the given transform. + * + * If the glTF has a `CESIUM_RTC` extension, this function will multiply the + * given matrix with the (translation) matrix that is created from the + * `RTC_CENTER` in the. If the given model does not have this extension, then + * this function will return the `rootTransform` unchanged. + * + * @param gltf The glTF model + * @param rootTransform The matrix that will be multiplied with the transform + * @return The result of multiplying the `RTC_CENTER` with the + * `rootTransform`. + */ + static glm::dmat4x4 applyRtcCenter( + const CesiumGltf::Model& gltf, + const glm::dmat4x4& rootTransform); + + /** + * @brief Applies the glTF's `gltfUpAxis`, if any, to the given transform. + * + * By default, the up-axis of a glTF model will the the Y-axis. + * + * If the tileset that contained the model had the `asset.gltfUpAxis` string + * property, then the information about the up-axis has been stored in as a + * number property called `gltfUpAxis` in the `extras` of the given model. + * + * Depending on whether this value is `CesiumGeometry::Axis::X`, `Y`, or `Z`, + * the given matrix will be multiplied with a matrix that converts the + * respective axis to be the Z-axis, as required by the 3D Tiles standard. + * + * @param model The glTF model + * @param rootTransform The matrix that will be multiplied with the transform + * @return The result of multiplying the `rootTransform` with the + * `gltfUpAxis`. + */ + static glm::dmat4x4 applyGltfUpAxisTransform( + const CesiumGltf::Model& model, + const glm::dmat4x4& rootTransform); + + /** + * @brief Computes a bounding region from the vertex positions in a glTF + * model. + * + * If the glTF model spans the anti-meridian, the west and east longitude + * values will be in the usual -PI to PI range, but east will have a smaller + * value than west. + * + * If the glTF contains no geometry, the returned region's rectangle + * will be {@link CesiumGeospatial::GlobeRectangle::EMPTY}, its minimum height will be 1.0, and + * its maximum height will be -1.0 (the minimum will be greater than the + * maximum). + * + * @param gltf The model. + * @param transform The transform from model coordinates to ECEF coordinates. + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + * @return The computed bounding region. + */ + static CesiumGeospatial::BoundingRegion computeBoundingRegion( + const CesiumGltf::Model& gltf, + const glm::dmat4& transform, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief Parse the copyright field of a glTF model and return the individual + * credits. + * + * Credits are read from the glTF's asset.copyright field. This method assumes + * that individual credits are separated by semicolons. + * + * @param gltf The model. + * @return The credits from the glTF. + */ + static std::vector + parseGltfCopyright(const CesiumGltf::Model& gltf); + + /** + * @brief Merges all of the glTF's buffers into a single buffer (the first + * one). + * + * This is useful when writing the glTF as a GLB, which supports only a single + * embedded buffer. + * + * @param gltf The glTF in which to merge buffers. + */ + static void collapseToSingleBuffer(CesiumGltf::Model& gltf); + + /** + * @brief Copies the content of one {@link CesiumGltf::Buffer} to the end of another, + * updates all {@link CesiumGltf::BufferView} instances to refer to the destination + * buffer, and clears the contents of the original buffer. + * + * The source buffer is not removed, but it has a `byteLength` of zero after + * this function completes. + * + * @param gltf The glTF model to modify. + * @param destination The destination Buffer into which to move content. + * @param source The source Buffer from which to move content. + */ + static void moveBufferContent( + CesiumGltf::Model& gltf, + CesiumGltf::Buffer& destination, + CesiumGltf::Buffer& source); + + /** + * @brief Removes unused textures from the given glTF model. + * + * @param gltf The glTF to remove unused textures from. + * @param extraUsedTextureIndices Indices of textures that should be + * considered "used" even if they're not referenced by anything else in the + * glTF. + */ + static void removeUnusedTextures( + CesiumGltf::Model& gltf, + const std::vector& extraUsedTextureIndices = {}); + + /** + * @brief Removes unused samplers from the given glTF model. + * + * @param gltf The glTF to remove unused samplers from. + * @param extraUsedSamplerIndices Indices of samplers that should be + * considered "used" even if they're not referenced by anything else in the + * glTF. + */ + static void removeUnusedSamplers( + CesiumGltf::Model& gltf, + const std::vector& extraUsedSamplerIndices = {}); + + /** + * @brief Removes unused images from the given glTF model. + * + * @param gltf The glTF to remove unused images from. + * @param extraUsedImageIndices Indices of images that should be + * considered "used" even if they're not referenced by anything else in the + * glTF. + */ + static void removeUnusedImages( + CesiumGltf::Model& gltf, + const std::vector& extraUsedImageIndices = {}); + + /** + * @brief Removes unused accessors from the given glTF model. + * + * @param gltf The glTF to remove unused accessors from. + * @param extraUsedAccessorIndices Indices of accessors that should be + * considered "used" even if they're not referenced by anything else in the + * glTF. + */ + static void removeUnusedAccessors( + CesiumGltf::Model& gltf, + const std::vector& extraUsedAccessorIndices = {}); + + /** + * @brief Removes unused buffer views from the given glTF model. + * + * @param gltf The glTF to remove unused buffer views from. + * @param extraUsedBufferViewIndices Indices of buffer views that should be + * considered "used" even if they're not referenced by anything else in the + * glTF. + */ + static void removeUnusedBufferViews( + CesiumGltf::Model& gltf, + const std::vector& extraUsedBufferViewIndices = {}); + + /** + * @brief Removes unused buffers from the given glTF model. + * + * @param gltf The glTF to remove unused buffers from. + * @param extraUsedBufferIndices Indices of buffers that should be + * considered "used" even if they're not referenced by anything else in the + * glTF. + */ + static void removeUnusedBuffers( + CesiumGltf::Model& gltf, + const std::vector& extraUsedBufferIndices = {}); + + /** + * @brief Removes unused meshes from the given glTF model. + * + * @param gltf The glTF to remove unused meshes from. + * @param extraUsedMeshIndices Indices of meshes that should be + * considered "used" even if they're not referenced by anything else in the + * glTF. + */ + static void removeUnusedMeshes( + CesiumGltf::Model& gltf, + const std::vector& extraUsedMeshIndices = {}); + + /** + * @brief Removes unused materials from the given glTF model. + * + * @param gltf The glTF to remove unused materials from. + * @param extraUsedMaterialIndices Indices of materials that should be + * considered "used" even if they're not referenced by anything else in the + * glTF. + */ + static void removeUnusedMaterials( + CesiumGltf::Model& gltf, + const std::vector& extraUsedMaterialIndices = {}); + + /** + * @brief Shrink buffers by removing any sections that are not referenced by + * any BufferView. + * + * @param gltf The glTF to modify. + */ + static void compactBuffers(CesiumGltf::Model& gltf); + + /** + * @brief Shrink a buffer by removing any sections that are not referenced by + * any BufferView. + * + * @param gltf The glTF to modify. + * @param bufferIndex The index of the buffer to compact. + */ + static void compactBuffer(CesiumGltf::Model& gltf, int32_t bufferIndex); + + /** + * @brief Data describing a hit from a ray / gltf intersection test + */ + struct RayGltfHit { + /** + * @brief Hit point in primitive space + */ + glm::dvec3 primitivePoint = {}; + + /** + * @brief Transformation from primitive to world space + */ + glm::dmat4x4 primitiveToWorld = {}; + + /** + * @brief Hit point in world space + */ + glm::dvec3 worldPoint = {}; + + /** + * @brief Square dist from intersection ray origin to world point + */ + double rayToWorldPointDistanceSq = -1.0; + + /** + * @brief ID of the glTF mesh that was hit + */ + int32_t meshId = -1; + + /** + * @brief ID of the glTF primitive that was hit + */ + int32_t primitiveId = -1; + }; + + /** + * @brief Hit result data for intersectRayGltfModel + */ + struct IntersectResult { + /** + * @brief Optional hit result, if an intersection occurred + */ + std::optional hit; + + /** + * @brief Warnings encountered when traversing the glTF model + */ + std::vector warnings{}; + }; + + /** + * @brief Intersects a ray with a glTF model and returns the first + * intersection point. + * + * Supports all mesh primitive modes. + * Points and lines are assumed to have no area, and are ignored + * + * @param ray A ray in world space. + * @param gltf The glTF model to intersect. + * @param cullBackFaces Ignore triangles that face away from ray. Front faces + * use CCW winding order. + * @param gltfTransform Optional matrix to apply to entire gltf model. + * @returns IntersectResult describing outcome + */ + static IntersectResult intersectRayGltfModel( + const CesiumGeometry::Ray& ray, + const CesiumGltf::Model& gltf, + bool cullBackFaces = true, + const glm::dmat4x4& gltfTransform = glm::dmat4(1.0)); +}; +} // namespace CesiumGltfContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfContent/ImageManipulation.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfContent/ImageManipulation.h new file mode 100644 index 0000000..57c2a0b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfContent/ImageManipulation.h @@ -0,0 +1,123 @@ +#pragma once + +#include "Library.h" + +#include +#include + +// Forward declarations +namespace CesiumGltf { +struct ImageAsset; +} + +namespace CesiumGltfContent { + +/** + * @brief Specifies a rectangle of pixels in an image. + */ +struct PixelRectangle { + /** + * @brief The X coordinate of the top-left corner of the rectangle. + */ + int32_t x; + + /** + * @brief The Y coordinate of the top-left corner of the rectangle. + */ + int32_t y; + + /** + * @brief The total number of pixels in the horizontal direction. + */ + int32_t width; + + /** + * @brief The total number of pixels in the vertical direction. + */ + int32_t height; +}; + +/** + * @brief A collection of utility functions for image manipulation operations. + */ +class CESIUMGLTFCONTENT_API ImageManipulation { +public: + /** + * @brief Directly copies pixels from a source to a target, without validating + * the provided pointers or ranges. + * + * @param pTarget The pointer at which to start writing pixels. + * @param targetRowStride The number of bytes between rows in the target + * image. + * @param pSource The pointer at which to start reading pixels. + * @param sourceRowStride The number of bytes between rows in the source + * image. + * @param sourceWidth The number of pixels to copy in the horizontal + * direction. + * @param sourceHeight The number of pixels to copy in the vertical direction. + * @param bytesPerPixel The number of bytes used to represent each pixel. + */ + static void unsafeBlitImage( + std::byte* pTarget, + size_t targetRowStride, + const std::byte* pSource, + size_t sourceRowStride, + size_t sourceWidth, + size_t sourceHeight, + size_t bytesPerPixel); + + /** + * @brief Copies pixels from a source image to a target image. + * + * If the source and target dimensions are the same, the source pixels are + * copied exactly into the target. If not, the source image is scaled to fit + * the target rectangle. + * + * The filtering algorithm for scaling is not specified, but can be assumed + * to provide reasonably good quality. + * + * The source and target images must have the same number of channels and same + * bytes per channel. If scaling is required, they must also use exactly 1 + * byte per channel. If any of these requirements are violated, this function + * will return false and will not change any target pixels. + * + * The provided rectangles are validated to ensure that they fall within the + * range of the images. If they do not, this function will return false and + * will not change any pixels. + * + * @param target The image in which to write pixels. + * @param targetPixels The pixels to write in the target. + * @param source The image from which to read pixels. + * @param sourcePixels The pixels to read from the target. + * @returns True if the source image was blitted successfully into the target, + * or false if the blit could not be completed due to invalid ranges or + * incompatible formats. + */ + static bool blitImage( + CesiumGltf::ImageAsset& target, + const PixelRectangle& targetPixels, + const CesiumGltf::ImageAsset& source, + const PixelRectangle& sourcePixels); + + /** + * @brief Saves an image to a new byte buffer in PNG format. + * + * @param image The image to save. + * @return The byte buffer containing the image. If the buffer is empty, the + * image could not be written. + */ + static std::vector savePng(const CesiumGltf::ImageAsset& image); + + /** + * @brief Saves an image to an existing byte buffer in PNG format. + * + * @param image The image to save. + * @param output The buffer in which to store the PNG. The image is written to + * the end of the buffer. If the buffer size is unchanged on return the image + * could not be written. + */ + static void + savePng(const CesiumGltf::ImageAsset& image, std::vector& output); +}; + +} // namespace CesiumGltfContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfContent/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfContent/Library.h new file mode 100644 index 0000000..fe24b38 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfContent/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes that support manipulating the content of a glTF. + * + * @mermaid-interactive{dependencies/CesiumGltfContent} + */ +namespace CesiumGltfContent {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMGLTFCONTENT_BUILDING +#define CESIUMGLTFCONTENT_API __declspec(dllexport) +#else +#define CESIUMGLTFCONTENT_API __declspec(dllimport) +#endif +#else +#define CESIUMGLTFCONTENT_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfContent/SkirtMeshMetadata.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfContent/SkirtMeshMetadata.h new file mode 100644 index 0000000..594be7d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfContent/SkirtMeshMetadata.h @@ -0,0 +1,112 @@ +#include + +#include + +#include + +namespace CesiumGltfContent { + +/** + * @brief Metadata obtained from a glTF that describes the skirts present on the + * mesh. + * + * @remarks Skirts are a technique for hiding cracks between adjacent tiles + * where the geometry at the edges of tiles is extended downwards, like the + * edges of a tablecloth hanging off of a table. These skirts are included in + * the glTF when they're generated, in the case of 3D Tiles, or they are + * generated by Cesium Native when terrain is loaded, in the case of Quantized + * Mesh terrain. `SkirtMeshMetadata` is attached to the glTF to allow Cesium + * Native to know which parts of the mesh are original and which contain the + * generated skirts, for operations such as creating texture coordinates for + * raster overlays. + */ +struct SkirtMeshMetadata { + /** + * @brief Creates a new `SkirtMeshMetadata` with zeroes in all fields. + */ + SkirtMeshMetadata() noexcept + : noSkirtIndicesBegin{0}, + noSkirtIndicesCount{0}, + noSkirtVerticesBegin{0}, + noSkirtVerticesCount{0}, + meshCenter{0.0, 0.0, 0.0}, + skirtWestHeight{0.0}, + skirtSouthHeight{0.0}, + skirtEastHeight{0.0}, + skirtNorthHeight{0.0} {} + + /** + * @brief Parses `SkirtMeshMetadata` from the `extras` field of a glTF mesh, + * if present. + * + * @param extras The extras field of the glTF mesh. + * @returns An optional containing the `SkirtMeshMetadata` if it was present + * on the mesh. + */ + static std::optional + parseFromGltfExtras(const CesiumUtility::JsonValue::Object& extras); + + /** + * @brief Creates a glTF mesh extras value from the provided + * `SkirtMeshMetadata`. + * + * This might be used when generating a glTF at runtime, in order to provide + * information on the mesh's skirts to the rest of Cesium Native. + * + * @param skirt The skirt to create the glTF extras object from. + * @returns An object representing the value of a glTF extras field containing + * the skirt metadata. + */ + static CesiumUtility::JsonValue::Object + createGltfExtras(const SkirtMeshMetadata& skirt); + + /** + * @brief The start index of the range of a glTF mesh's indices buffer that + * should \b NOT be considered part of the skirt. + */ + uint32_t noSkirtIndicesBegin; + /** + * @brief The length of the range of a glTF mesh's indices buffer that should + * \b NOT be considered part of the skirt. + * + * Any indices outside of the range `(noSkirtIndicesBegin, + * noSkirtIndicesBegin + noSkirtIndicesCount)` will be considered part of the + * skirt. + */ + uint32_t noSkirtIndicesCount; + /** + * @brief The start index of the range of a glTF mesh's vertices buffer that + * should \b NOT be considered part of the skirt. + */ + uint32_t noSkirtVerticesBegin; + /** + * @brief The length of the range of a glTF mesh's vertices buffer that should + * \b NOT be considered part of the skirt. + * + * Any vertices outside of the range `(noSkirtVerticesBegin, + * noSkirtVerticesBegin + noSkirtVerticesCount)` will be considered part of + * the skirt. + */ + uint32_t noSkirtVerticesCount; + /** + * @brief The center coordinates of the mesh, in \ref glossary-ecef. + */ + glm::dvec3 meshCenter; + /** + * @brief The height of the skirt on the western edge of the mesh. + */ + double skirtWestHeight; + /** + * @brief The height of the skirt on the southern edge of the mesh. + */ + double skirtSouthHeight; + /** + * @brief The height of the skirt on the eastern edge of the mesh. + */ + double skirtEastHeight; + /** + * @brief The height of the skirt on the northern edge of the mesh. + */ + double skirtNorthHeight; +}; +} // namespace CesiumGltfContent diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AccessorReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AccessorReader.h new file mode 100644 index 0000000..b87236c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AccessorReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Accessor; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Accessor "Accessor" instances from JSON. + */ +class CESIUMGLTFREADER_API AccessorReader { +public: + /** + * @brief Constructs a new instance. + */ + AccessorReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Accessor from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Accessor from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Accessor from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AccessorSparseIndicesReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AccessorSparseIndicesReader.h new file mode 100644 index 0000000..d348c09 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AccessorSparseIndicesReader.h @@ -0,0 +1,75 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct AccessorSparseIndices; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::AccessorSparseIndices "AccessorSparseIndices" + * instances from JSON. + */ +class CESIUMGLTFREADER_API AccessorSparseIndicesReader { +public: + /** + * @brief Constructs a new instance. + */ + AccessorSparseIndicesReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of AccessorSparseIndices from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of AccessorSparseIndices from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of AccessorSparseIndices from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AccessorSparseReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AccessorSparseReader.h new file mode 100644 index 0000000..a823aab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AccessorSparseReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct AccessorSparse; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::AccessorSparse "AccessorSparse" instances from + * JSON. + */ +class CESIUMGLTFREADER_API AccessorSparseReader { +public: + /** + * @brief Constructs a new instance. + */ + AccessorSparseReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of AccessorSparse from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of AccessorSparse from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of AccessorSparse from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AccessorSparseValuesReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AccessorSparseValuesReader.h new file mode 100644 index 0000000..a3f783c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AccessorSparseValuesReader.h @@ -0,0 +1,75 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct AccessorSparseValues; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::AccessorSparseValues "AccessorSparseValues" + * instances from JSON. + */ +class CESIUMGLTFREADER_API AccessorSparseValuesReader { +public: + /** + * @brief Constructs a new instance. + */ + AccessorSparseValuesReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of AccessorSparseValues from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of AccessorSparseValues from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of AccessorSparseValues from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AnimationChannelReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AnimationChannelReader.h new file mode 100644 index 0000000..e62e5f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AnimationChannelReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct AnimationChannel; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::AnimationChannel "AnimationChannel" instances + * from JSON. + */ +class CESIUMGLTFREADER_API AnimationChannelReader { +public: + /** + * @brief Constructs a new instance. + */ + AnimationChannelReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of AnimationChannel from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of AnimationChannel from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of AnimationChannel from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AnimationChannelTargetReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AnimationChannelTargetReader.h new file mode 100644 index 0000000..ca25dbe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AnimationChannelTargetReader.h @@ -0,0 +1,75 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct AnimationChannelTarget; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::AnimationChannelTarget "AnimationChannelTarget" + * instances from JSON. + */ +class CESIUMGLTFREADER_API AnimationChannelTargetReader { +public: + /** + * @brief Constructs a new instance. + */ + AnimationChannelTargetReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of AnimationChannelTarget from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of AnimationChannelTarget from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of AnimationChannelTarget from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AnimationReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AnimationReader.h new file mode 100644 index 0000000..e6f3ba9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AnimationReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Animation; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Animation "Animation" instances from JSON. + */ +class CESIUMGLTFREADER_API AnimationReader { +public: + /** + * @brief Constructs a new instance. + */ + AnimationReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Animation from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Animation from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Animation from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AnimationSamplerReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AnimationSamplerReader.h new file mode 100644 index 0000000..7817383 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AnimationSamplerReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct AnimationSampler; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::AnimationSampler "AnimationSampler" instances + * from JSON. + */ +class CESIUMGLTFREADER_API AnimationSamplerReader { +public: + /** + * @brief Constructs a new instance. + */ + AnimationSamplerReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of AnimationSampler from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of AnimationSampler from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of AnimationSampler from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AssetReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AssetReader.h new file mode 100644 index 0000000..002e18a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/AssetReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Asset; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Asset "Asset" instances from JSON. + */ +class CESIUMGLTFREADER_API AssetReader { +public: + /** + * @brief Constructs a new instance. + */ + AssetReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Asset from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Asset from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Asset from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/BufferReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/BufferReader.h new file mode 100644 index 0000000..6bbc0bb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/BufferReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Buffer; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Buffer "Buffer" instances from JSON. + */ +class CESIUMGLTFREADER_API BufferReader { +public: + /** + * @brief Constructs a new instance. + */ + BufferReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Buffer from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Buffer from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Buffer from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/BufferViewReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/BufferViewReader.h new file mode 100644 index 0000000..4888253 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/BufferViewReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct BufferView; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::BufferView "BufferView" instances from JSON. + */ +class CESIUMGLTFREADER_API BufferViewReader { +public: + /** + * @brief Constructs a new instance. + */ + BufferViewReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of BufferView from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of BufferView from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of BufferView from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/CameraOrthographicReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/CameraOrthographicReader.h new file mode 100644 index 0000000..544cecd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/CameraOrthographicReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct CameraOrthographic; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::CameraOrthographic "CameraOrthographic" + * instances from JSON. + */ +class CESIUMGLTFREADER_API CameraOrthographicReader { +public: + /** + * @brief Constructs a new instance. + */ + CameraOrthographicReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of CameraOrthographic from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of CameraOrthographic from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of CameraOrthographic from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/CameraPerspectiveReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/CameraPerspectiveReader.h new file mode 100644 index 0000000..75e94d1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/CameraPerspectiveReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct CameraPerspective; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::CameraPerspective "CameraPerspective" instances + * from JSON. + */ +class CESIUMGLTFREADER_API CameraPerspectiveReader { +public: + /** + * @brief Constructs a new instance. + */ + CameraPerspectiveReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of CameraPerspective from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of CameraPerspective from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of CameraPerspective from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/CameraReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/CameraReader.h new file mode 100644 index 0000000..997ec2f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/CameraReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Camera; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Camera "Camera" instances from JSON. + */ +class CESIUMGLTFREADER_API CameraReader { +public: + /** + * @brief Constructs a new instance. + */ + CameraReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Camera from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Camera from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Camera from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ClassPropertyReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ClassPropertyReader.h new file mode 100644 index 0000000..ba4c87b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ClassPropertyReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ClassProperty; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ClassProperty "ClassProperty" instances from + * JSON. + */ +class CESIUMGLTFREADER_API ClassPropertyReader { +public: + /** + * @brief Constructs a new instance. + */ + ClassPropertyReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ClassProperty from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ClassProperty from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ClassProperty from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ClassReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ClassReader.h new file mode 100644 index 0000000..1925ffe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ClassReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Class; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Class "Class" instances from JSON. + */ +class CESIUMGLTFREADER_API ClassReader { +public: + /** + * @brief Constructs a new instance. + */ + ClassReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Class from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Class from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Class from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/EnumReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/EnumReader.h new file mode 100644 index 0000000..2c72bbd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/EnumReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Enum; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Enum "Enum" instances from JSON. + */ +class CESIUMGLTFREADER_API EnumReader { +public: + /** + * @brief Constructs a new instance. + */ + EnumReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Enum from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Enum from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Enum from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/EnumValueReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/EnumValueReader.h new file mode 100644 index 0000000..53a9c90 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/EnumValueReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct EnumValue; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::EnumValue "EnumValue" instances from JSON. + */ +class CESIUMGLTFREADER_API EnumValueReader { +public: + /** + * @brief Constructs a new instance. + */ + EnumValueReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of EnumValue from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of EnumValue from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of EnumValue from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionBufferExtMeshoptCompressionReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionBufferExtMeshoptCompressionReader.h new file mode 100644 index 0000000..4eef47a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionBufferExtMeshoptCompressionReader.h @@ -0,0 +1,79 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionBufferExtMeshoptCompression; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionBufferExtMeshoptCompression + * "ExtensionBufferExtMeshoptCompression" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionBufferExtMeshoptCompressionReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionBufferExtMeshoptCompressionReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionBufferExtMeshoptCompression from a + * byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionBufferExtMeshoptCompression> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionBufferExtMeshoptCompression from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionBufferExtMeshoptCompression> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionBufferExtMeshoptCompression + * from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionBufferViewExtMeshoptCompressionReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionBufferViewExtMeshoptCompressionReader.h new file mode 100644 index 0000000..755b636 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionBufferViewExtMeshoptCompressionReader.h @@ -0,0 +1,79 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionBufferViewExtMeshoptCompression; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionBufferViewExtMeshoptCompression + * "ExtensionBufferViewExtMeshoptCompression" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionBufferViewExtMeshoptCompressionReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionBufferViewExtMeshoptCompressionReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionBufferViewExtMeshoptCompression from a + * byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionBufferViewExtMeshoptCompression> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionBufferViewExtMeshoptCompression from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionBufferViewExtMeshoptCompression> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of + * ExtensionBufferViewExtMeshoptCompression from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionCesiumPrimitiveOutlineReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionCesiumPrimitiveOutlineReader.h new file mode 100644 index 0000000..4bd9e2f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionCesiumPrimitiveOutlineReader.h @@ -0,0 +1,77 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionCesiumPrimitiveOutline; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionCesiumPrimitiveOutline + * "ExtensionCesiumPrimitiveOutline" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionCesiumPrimitiveOutlineReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionCesiumPrimitiveOutlineReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionCesiumPrimitiveOutline from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionCesiumPrimitiveOutline from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionCesiumPrimitiveOutline from + * a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionCesiumRTCReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionCesiumRTCReader.h new file mode 100644 index 0000000..99f52c6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionCesiumRTCReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionCesiumRTC; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionCesiumRTC "ExtensionCesiumRTC" + * instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionCesiumRTCReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionCesiumRTCReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionCesiumRTC from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionCesiumRTC from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionCesiumRTC from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionCesiumTileEdgesReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionCesiumTileEdgesReader.h new file mode 100644 index 0000000..65aa076 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionCesiumTileEdgesReader.h @@ -0,0 +1,76 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionCesiumTileEdges; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionCesiumTileEdges + * "ExtensionCesiumTileEdges" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionCesiumTileEdgesReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionCesiumTileEdgesReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionCesiumTileEdges from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionCesiumTileEdges from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionCesiumTileEdges from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtInstanceFeaturesFeatureIdReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtInstanceFeaturesFeatureIdReader.h new file mode 100644 index 0000000..d5af96d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtInstanceFeaturesFeatureIdReader.h @@ -0,0 +1,79 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionExtInstanceFeaturesFeatureId; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionExtInstanceFeaturesFeatureId + * "ExtensionExtInstanceFeaturesFeatureId" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionExtInstanceFeaturesFeatureIdReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionExtInstanceFeaturesFeatureIdReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionExtInstanceFeaturesFeatureId from a + * byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionExtInstanceFeaturesFeatureId> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionExtInstanceFeaturesFeatureId from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionExtInstanceFeaturesFeatureId> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionExtInstanceFeaturesFeatureId + * from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtInstanceFeaturesReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtInstanceFeaturesReader.h new file mode 100644 index 0000000..13b8236 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtInstanceFeaturesReader.h @@ -0,0 +1,77 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionExtInstanceFeatures; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionExtInstanceFeatures + * "ExtensionExtInstanceFeatures" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionExtInstanceFeaturesReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionExtInstanceFeaturesReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionExtInstanceFeatures from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionExtInstanceFeatures from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionExtInstanceFeatures from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtMeshFeaturesReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtMeshFeaturesReader.h new file mode 100644 index 0000000..fe79296 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtMeshFeaturesReader.h @@ -0,0 +1,76 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionExtMeshFeatures; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionExtMeshFeatures + * "ExtensionExtMeshFeatures" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionExtMeshFeaturesReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionExtMeshFeaturesReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionExtMeshFeatures from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionExtMeshFeatures from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionExtMeshFeatures from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtMeshGpuInstancingReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtMeshGpuInstancingReader.h new file mode 100644 index 0000000..f945917 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtMeshGpuInstancingReader.h @@ -0,0 +1,77 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionExtMeshGpuInstancing; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionExtMeshGpuInstancing + * "ExtensionExtMeshGpuInstancing" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionExtMeshGpuInstancingReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionExtMeshGpuInstancingReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionExtMeshGpuInstancing from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionExtMeshGpuInstancing from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionExtMeshGpuInstancing from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtStructuralMetadataReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtStructuralMetadataReader.h new file mode 100644 index 0000000..10f195c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionExtStructuralMetadataReader.h @@ -0,0 +1,77 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionExtStructuralMetadata; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionExtStructuralMetadata + * "ExtensionExtStructuralMetadata" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionExtStructuralMetadataReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionExtStructuralMetadataReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionExtStructuralMetadata from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionExtStructuralMetadata from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionExtStructuralMetadata from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionKhrDracoMeshCompressionReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionKhrDracoMeshCompressionReader.h new file mode 100644 index 0000000..4813766 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionKhrDracoMeshCompressionReader.h @@ -0,0 +1,77 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionKhrDracoMeshCompression; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionKhrDracoMeshCompression + * "ExtensionKhrDracoMeshCompression" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionKhrDracoMeshCompressionReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionKhrDracoMeshCompressionReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionKhrDracoMeshCompression from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionKhrDracoMeshCompression from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionKhrDracoMeshCompression from + * a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionKhrMaterialsUnlitReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionKhrMaterialsUnlitReader.h new file mode 100644 index 0000000..48d25a2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionKhrMaterialsUnlitReader.h @@ -0,0 +1,76 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionKhrMaterialsUnlit; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionKhrMaterialsUnlit + * "ExtensionKhrMaterialsUnlit" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionKhrMaterialsUnlitReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionKhrMaterialsUnlitReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionKhrMaterialsUnlit from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionKhrMaterialsUnlit from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionKhrMaterialsUnlit from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionKhrTextureBasisuReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionKhrTextureBasisuReader.h new file mode 100644 index 0000000..75d9c04 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionKhrTextureBasisuReader.h @@ -0,0 +1,76 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionKhrTextureBasisu; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionKhrTextureBasisu + * "ExtensionKhrTextureBasisu" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionKhrTextureBasisuReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionKhrTextureBasisuReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionKhrTextureBasisu from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionKhrTextureBasisu from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionKhrTextureBasisu from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionKhrTextureTransformReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionKhrTextureTransformReader.h new file mode 100644 index 0000000..df54c2c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionKhrTextureTransformReader.h @@ -0,0 +1,77 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionKhrTextureTransform; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionKhrTextureTransform + * "ExtensionKhrTextureTransform" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionKhrTextureTransformReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionKhrTextureTransformReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionKhrTextureTransform from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionKhrTextureTransform from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionKhrTextureTransform from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionMeshPrimitiveExtStructuralMetadataReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionMeshPrimitiveExtStructuralMetadataReader.h new file mode 100644 index 0000000..bc36bf1d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionMeshPrimitiveExtStructuralMetadataReader.h @@ -0,0 +1,79 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionMeshPrimitiveExtStructuralMetadata; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata + * "ExtensionMeshPrimitiveExtStructuralMetadata" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionMeshPrimitiveExtStructuralMetadataReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionMeshPrimitiveExtStructuralMetadataReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionMeshPrimitiveExtStructuralMetadata + * from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionMeshPrimitiveExtStructuralMetadata + * from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of + * ExtensionMeshPrimitiveExtStructuralMetadata from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValueReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValueReader.h new file mode 100644 index 0000000..ddb925d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValueReader.h @@ -0,0 +1,84 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref + * CesiumGltf::ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue + * "ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue" instances from + * JSON. + */ +class CESIUMGLTFREADER_API + ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValueReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValueReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of + * ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of + * ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of + * ExtensionMeshPrimitiveKhrMaterialsVariantsMappingsValue from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionMeshPrimitiveKhrMaterialsVariantsReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionMeshPrimitiveKhrMaterialsVariantsReader.h new file mode 100644 index 0000000..10cab5f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionMeshPrimitiveKhrMaterialsVariantsReader.h @@ -0,0 +1,79 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionMeshPrimitiveKhrMaterialsVariants; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionMeshPrimitiveKhrMaterialsVariants + * "ExtensionMeshPrimitiveKhrMaterialsVariants" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionMeshPrimitiveKhrMaterialsVariantsReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionMeshPrimitiveKhrMaterialsVariantsReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionMeshPrimitiveKhrMaterialsVariants from + * a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionMeshPrimitiveKhrMaterialsVariants> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionMeshPrimitiveKhrMaterialsVariants from + * a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionMeshPrimitiveKhrMaterialsVariants> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of + * ExtensionMeshPrimitiveKhrMaterialsVariants from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelExtStructuralMetadataReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelExtStructuralMetadataReader.h new file mode 100644 index 0000000..7fa70ca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelExtStructuralMetadataReader.h @@ -0,0 +1,79 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionModelExtStructuralMetadata; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionModelExtStructuralMetadata + * "ExtensionModelExtStructuralMetadata" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionModelExtStructuralMetadataReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionModelExtStructuralMetadataReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionModelExtStructuralMetadata from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionModelExtStructuralMetadata> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionModelExtStructuralMetadata from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionModelExtStructuralMetadata> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionModelExtStructuralMetadata + * from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelKhrMaterialsVariantsReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelKhrMaterialsVariantsReader.h new file mode 100644 index 0000000..9818c78 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelKhrMaterialsVariantsReader.h @@ -0,0 +1,79 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionModelKhrMaterialsVariants; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionModelKhrMaterialsVariants + * "ExtensionModelKhrMaterialsVariants" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionModelKhrMaterialsVariantsReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionModelKhrMaterialsVariantsReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionModelKhrMaterialsVariants from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionModelKhrMaterialsVariants> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionModelKhrMaterialsVariants from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionModelKhrMaterialsVariants> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionModelKhrMaterialsVariants + * from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelKhrMaterialsVariantsValueReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelKhrMaterialsVariantsValueReader.h new file mode 100644 index 0000000..581a9ba --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelKhrMaterialsVariantsValueReader.h @@ -0,0 +1,79 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionModelKhrMaterialsVariantsValue; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionModelKhrMaterialsVariantsValue + * "ExtensionModelKhrMaterialsVariantsValue" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionModelKhrMaterialsVariantsValueReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionModelKhrMaterialsVariantsValueReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionModelKhrMaterialsVariantsValue from a + * byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionModelKhrMaterialsVariantsValue> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionModelKhrMaterialsVariantsValue from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionModelKhrMaterialsVariantsValue> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of + * ExtensionModelKhrMaterialsVariantsValue from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelMaxarMeshVariantsReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelMaxarMeshVariantsReader.h new file mode 100644 index 0000000..f2011ce --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelMaxarMeshVariantsReader.h @@ -0,0 +1,77 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionModelMaxarMeshVariants; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionModelMaxarMeshVariants + * "ExtensionModelMaxarMeshVariants" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionModelMaxarMeshVariantsReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionModelMaxarMeshVariantsReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionModelMaxarMeshVariants from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionModelMaxarMeshVariants from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionModelMaxarMeshVariants from + * a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelMaxarMeshVariantsValueReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelMaxarMeshVariantsValueReader.h new file mode 100644 index 0000000..70630c9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionModelMaxarMeshVariantsValueReader.h @@ -0,0 +1,79 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionModelMaxarMeshVariantsValue; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionModelMaxarMeshVariantsValue + * "ExtensionModelMaxarMeshVariantsValue" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionModelMaxarMeshVariantsValueReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionModelMaxarMeshVariantsValueReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionModelMaxarMeshVariantsValue from a + * byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionModelMaxarMeshVariantsValue> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionModelMaxarMeshVariantsValue from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionModelMaxarMeshVariantsValue> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionModelMaxarMeshVariantsValue + * from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionNodeMaxarMeshVariantsMappingsValueReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionNodeMaxarMeshVariantsMappingsValueReader.h new file mode 100644 index 0000000..f85e9dd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionNodeMaxarMeshVariantsMappingsValueReader.h @@ -0,0 +1,79 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionNodeMaxarMeshVariantsMappingsValue; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionNodeMaxarMeshVariantsMappingsValue + * "ExtensionNodeMaxarMeshVariantsMappingsValue" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionNodeMaxarMeshVariantsMappingsValueReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionNodeMaxarMeshVariantsMappingsValueReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionNodeMaxarMeshVariantsMappingsValue + * from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionNodeMaxarMeshVariantsMappingsValue> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionNodeMaxarMeshVariantsMappingsValue + * from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumGltf::ExtensionNodeMaxarMeshVariantsMappingsValue> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of + * ExtensionNodeMaxarMeshVariantsMappingsValue from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionNodeMaxarMeshVariantsReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionNodeMaxarMeshVariantsReader.h new file mode 100644 index 0000000..e40fda5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionNodeMaxarMeshVariantsReader.h @@ -0,0 +1,77 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionNodeMaxarMeshVariants; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionNodeMaxarMeshVariants + * "ExtensionNodeMaxarMeshVariants" instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionNodeMaxarMeshVariantsReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionNodeMaxarMeshVariantsReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionNodeMaxarMeshVariants from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionNodeMaxarMeshVariants from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionNodeMaxarMeshVariants from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionTextureWebpReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionTextureWebpReader.h new file mode 100644 index 0000000..00cb45e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ExtensionTextureWebpReader.h @@ -0,0 +1,75 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct ExtensionTextureWebp; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::ExtensionTextureWebp "ExtensionTextureWebp" + * instances from JSON. + */ +class CESIUMGLTFREADER_API ExtensionTextureWebpReader { +public: + /** + * @brief Constructs a new instance. + */ + ExtensionTextureWebpReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of ExtensionTextureWebp from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of ExtensionTextureWebp from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of ExtensionTextureWebp from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/FeatureIdReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/FeatureIdReader.h new file mode 100644 index 0000000..5ebae3d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/FeatureIdReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct FeatureId; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::FeatureId "FeatureId" instances from JSON. + */ +class CESIUMGLTFREADER_API FeatureIdReader { +public: + /** + * @brief Constructs a new instance. + */ + FeatureIdReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of FeatureId from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of FeatureId from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of FeatureId from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/FeatureIdTextureReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/FeatureIdTextureReader.h new file mode 100644 index 0000000..e22a2b3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/FeatureIdTextureReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct FeatureIdTexture; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::FeatureIdTexture "FeatureIdTexture" instances + * from JSON. + */ +class CESIUMGLTFREADER_API FeatureIdTextureReader { +public: + /** + * @brief Constructs a new instance. + */ + FeatureIdTextureReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of FeatureIdTexture from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of FeatureIdTexture from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of FeatureIdTexture from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/GltfReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/GltfReader.h new file mode 100644 index 0000000..9a6eb8f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/GltfReader.h @@ -0,0 +1,227 @@ +#pragma once + +#include "CesiumGltfReader/ImageDecoder.h" +#include "CesiumGltfReader/Library.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace CesiumGltfReader { + +/** + * @brief The result of reading a glTF model with + * {@link GltfReader::readGltf}. + */ +struct CESIUMGLTFREADER_API GltfReaderResult { + /** + * @brief The read model, or std::nullopt if the model could not be read. + */ + std::optional model; + + /** + * @brief Errors, if any, that occurred during the load process. + */ + std::vector errors; + + /** + * @brief Warnings, if any, that occurred during the load process. + */ + std::vector warnings; +}; + +/** + * @brief Options for how to read a glTF. + */ +struct CESIUMGLTFREADER_API GltfReaderOptions { + /** + * @brief Whether data URLs in buffers and images should be automatically + * decoded as part of the load process. + */ + bool decodeDataUrls = true; + + /** + * @brief Whether data URLs should be cleared after they are successfully + * decoded. + * + * This reduces the memory usage of the model. + */ + bool clearDecodedDataUrls = true; + + /** + * @brief Whether embedded images in {@link CesiumGltf::Model::buffers} should be + * automatically decoded as part of the load process. + * + * The {@link CesiumGltf::ImageSpec::mimeType} property is ignored, and instead the + * [stb_image](https://github.com/nothings/stb) library is used to decode + * images in `JPG`, `PNG`, `TGA`, `BMP`, `PSD`, `GIF`, `HDR`, or `PIC` format. + */ + bool decodeEmbeddedImages = true; + + /** + * @brief Whether external images should be resolved. + */ + bool resolveExternalImages = true; + + /** + * @brief Whether geometry compressed using the `KHR_draco_mesh_compression` + * extension should be automatically decoded as part of the load process. + */ + bool decodeDraco = true; + + /** + * @brief Whether the mesh data are decompressed as part of the load process, + * or left in the compressed format according to the EXT_meshopt_compression + * extension + */ + bool decodeMeshOptData = true; + + /** + * @brief Whether the quantized mesh data are dequantized and converted to + * floating-point values when loading, according to the KHR_mesh_quantization + * extension. + */ + bool dequantizeMeshData = true; + + /** + * @brief Whether the texture coordinates of a texture are transformed or + * not, according to the KHR_texture_transform extension + */ + bool applyTextureTransform = true; + + /** + * @brief For each possible input transmission format, this struct names + * the ideal target gpu-compressed pixel format to transcode to. + */ + CesiumGltf::Ktx2TranscodeTargets ktx2TranscodeTargets; + + /** + * The shared asset system that will be used to store all of the shared assets + * that might appear in this glTF. + */ + CesiumUtility::IntrusivePointer pSharedAssetSystem = + GltfSharedAssetSystem::getDefault(); + + /** + * @brief Whether the `schemaUri` property of `EXT_structural_metadata` will + * be properly resolved. If false, any external schemas will be ignored. + */ + bool resolveExternalStructuralMetadata = true; +}; + +/** + * @brief Reads glTF models and images. + */ +class CESIUMGLTFREADER_API GltfReader { +public: + /** + * @brief Constructs a new instance. + */ + GltfReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getExtensions() const; + + /** + * @brief Reads a glTF or binary glTF (GLB) from a buffer. + * + * @param data The buffer from which to read the glTF. + * @param options Options for how to read the glTF. + * @return The result of reading the glTF. + */ + GltfReaderResult readGltf( + const std::span& data, + const GltfReaderOptions& options = GltfReaderOptions()) const; + + /** + * @brief Reads a glTF or binary glTF file from a URL and resolves external + * buffers and images. + * + * @param asyncSystem The async system to use for resolving external data. + * @param url The url for reading the file. + * @param headers http headers needed to make the request. + * @param pAssetAccessor The asset accessor to use to make the necessary + * requests. + * @param options Options for how to read the glTF. + */ + CesiumAsync::Future loadGltf( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::string& url, + const std::vector& headers, + const std::shared_ptr& pAssetAccessor, + const GltfReaderOptions& options = GltfReaderOptions()) const; + + /** + * @brief Performs post-load processing on a glTF. The specific operations + * performed are controlled by the provided `options`. + * + * @param readGltf The result of reading the glTF. + * @param options The options to use in post-processing. + */ + void + postprocessGltf(GltfReaderResult& readGltf, const GltfReaderOptions& options); + + /** + * @brief Accepts the result of {@link readGltf} and resolves any remaining + * external buffers and images. + * + * @param asyncSystem The async system to use for resolving external data. + * @param baseUrl The base url that all the external uris are relative to. + * @param headers The http headers needed to make any external data requests. + * @param pAssetAccessor The asset accessor to use to request the external + * buffers and images. + * @param options Options for how to read the glTF. + * @param result The result of the synchronous readGltf invocation. + */ + static CesiumAsync::Future resolveExternalData( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::string& baseUrl, + const CesiumAsync::HttpHeaders& headers, + const std::shared_ptr& pAssetAccessor, + const GltfReaderOptions& options, + GltfReaderResult&& result); + + /** + * @brief Reads an Image from a buffer. + * @deprecated Use {@link ImageDecoder::readImage} instead. + */ + [[deprecated( + "Use ImageDecoder::readImage instead.")]] static ImageReaderResult + readImage( + const std::span& data, + const CesiumGltf::Ktx2TranscodeTargets& ktx2TranscodeTargets); + + /** + * @brief Generate mipmaps for this image. + * @deprecated Use {@link ImageDecoder::generateMipMaps} instead. + */ + [[deprecated("Use ImageDecoder::generateMipMaps instead.")]] static std:: + optional + generateMipMaps(CesiumGltf::ImageAsset& image); + +private: + CesiumJsonReader::JsonReaderOptions _context; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/GltfSharedAssetSystem.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/GltfSharedAssetSystem.h new file mode 100644 index 0000000..cd1d166 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/GltfSharedAssetSystem.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#include + +namespace CesiumGltf { +struct Schema; +} + +namespace CesiumGltfReader { + +/** + * @brief Contains assets that are potentially shared across multiple glTF + * models. + */ +class GltfSharedAssetSystem + : public CesiumUtility::ReferenceCountedThreadSafe { +public: + /** + * @brief Obtains an `IntrusivePointer` to the `GltfSharedAssetSystem` + * singleton. + */ + static CesiumUtility::IntrusivePointer getDefault(); + + virtual ~GltfSharedAssetSystem() = default; + + /** + * @brief A depot containing images loaded from glTFs. + * + * See \ref CesiumGltf::ImageAsset "ImageAsset" and \ref + * NetworkImageAssetDescriptor. + */ + using ImageDepot = CesiumAsync:: + SharedAssetDepot; + + /** + * @brief The asset depot for images. + */ + CesiumUtility::IntrusivePointer pImage; + + /** + * @brief A depot containing schemas loaded from URIs contained in the glTF + * EXT_structural_metadata extension. + * + * See \ref CesiumGltf::Schema "Schema" and \ref NetworkSchemaAssetDescriptor. + */ + using SchemaDepot = CesiumAsync:: + SharedAssetDepot; + + /** + * @brief The asset depot for schemas. + */ + CesiumUtility::IntrusivePointer pExternalMetadataSchema; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ImageDecoder.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ImageDecoder.h new file mode 100644 index 0000000..d07ec06 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ImageDecoder.h @@ -0,0 +1,99 @@ +#pragma once + +#include "CesiumGltf/ImageAsset.h" +#include "CesiumGltfReader/Library.h" + +#include + +#include +#include +#include +#include + +namespace CesiumGltfReader { + +/** + * @brief The result of reading an image with {@link ImageDecoder::readImage}. + */ +struct CESIUMGLTFREADER_API ImageReaderResult { + + /** + * @brief The {@link CesiumGltf::ImageAsset} that was read. + * + * This will be `std::nullopt` if the image could not be read. + */ + CesiumUtility::IntrusivePointer pImage; + + /** + * @brief Error messages that occurred while trying to read the image. + */ + std::vector errors; + + /** + * @brief Warning messages that occurred while reading the image. + */ + std::vector warnings; +}; + +/** + * @brief Contains methods for reading and manipulating images. + */ +class ImageDecoder { +public: + /** + * @brief Reads an image from a buffer. + * + * The [stb_image](https://github.com/nothings/stb) library is used to decode + * images in `JPG`, `PNG`, `TGA`, `BMP`, `PSD`, `GIF`, `HDR`, or `PIC` format. + * + * @param data The buffer from which to read the image. + * @param ktx2TranscodeTargets The compression format to transcode + * KTX v2 textures into. If this is std::nullopt, KTX v2 textures will be + * fully decompressed into raw pixels. + * @return The result of reading the image. + */ + static ImageReaderResult readImage( + const std::span& data, + const CesiumGltf::Ktx2TranscodeTargets& ktx2TranscodeTargets); + + /** + * @brief Generate mipmaps for this image. + * + * Does nothing if mipmaps already exist or the compressedPixelFormat is not + * GpuCompressedPixelFormat::NONE. + * + * @param image The image to generate mipmaps for. * + * @return A string describing the error, if unable to generate mipmaps. + */ + static std::optional + generateMipMaps(CesiumGltf::ImageAsset& image); + + /** + * @brief Resize an image, without validating the provided pointers or ranges. + * + * @param pInputPixels The input image. + * @param inputWidth The width of the input image, in pixels. + * @param inputHeight The height of the input image, in pixels. + * @param inputStrideBytes The stride of the input image, in bytes. Stride is + * the number of bytes between successive rows. + * @param pOutputPixels The buffer into which to write the output image. + * @param outputWidth The width of the output image, in pixels. + * @param outputHeight The height of the otuput image, in pixels. + * @param outputStrideBytes The stride of the output image, in bytes. Stride + * is the number of bytes between successive rows. + * @param channels The number of channels in both the input and output images. + * @return True if the resize succeeded, false if it failed. + */ + static bool unsafeResize( + const std::byte* pInputPixels, + int32_t inputWidth, + int32_t inputHeight, + int32_t inputStrideBytes, + std::byte* pOutputPixels, + int32_t outputWidth, + int32_t outputHeight, + int32_t outputStrideBytes, + int32_t channels); +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ImageReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ImageReader.h new file mode 100644 index 0000000..9a0393f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ImageReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Image; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Image "Image" instances from JSON. + */ +class CESIUMGLTFREADER_API ImageReader { +public: + /** + * @brief Constructs a new instance. + */ + ImageReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Image from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Image from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Image from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/Library.h new file mode 100644 index 0000000..a4dabcb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes for reading [glTF](https://www.khronos.org/gltf/) models. + * + * @mermaid-interactive{dependencies/CesiumGltfReader} + */ +namespace CesiumGltfReader {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMGLTFREADER_BUILDING +#define CESIUMGLTFREADER_API __declspec(dllexport) +#else +#define CESIUMGLTFREADER_API __declspec(dllimport) +#endif +#else +#define CESIUMGLTFREADER_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MaterialNormalTextureInfoReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MaterialNormalTextureInfoReader.h new file mode 100644 index 0000000..f662044 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MaterialNormalTextureInfoReader.h @@ -0,0 +1,76 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct MaterialNormalTextureInfo; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::MaterialNormalTextureInfo + * "MaterialNormalTextureInfo" instances from JSON. + */ +class CESIUMGLTFREADER_API MaterialNormalTextureInfoReader { +public: + /** + * @brief Constructs a new instance. + */ + MaterialNormalTextureInfoReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of MaterialNormalTextureInfo from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of MaterialNormalTextureInfo from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of MaterialNormalTextureInfo from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MaterialOcclusionTextureInfoReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MaterialOcclusionTextureInfoReader.h new file mode 100644 index 0000000..6391945 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MaterialOcclusionTextureInfoReader.h @@ -0,0 +1,77 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct MaterialOcclusionTextureInfo; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::MaterialOcclusionTextureInfo + * "MaterialOcclusionTextureInfo" instances from JSON. + */ +class CESIUMGLTFREADER_API MaterialOcclusionTextureInfoReader { +public: + /** + * @brief Constructs a new instance. + */ + MaterialOcclusionTextureInfoReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of MaterialOcclusionTextureInfo from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of MaterialOcclusionTextureInfo from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of MaterialOcclusionTextureInfo from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MaterialPBRMetallicRoughnessReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MaterialPBRMetallicRoughnessReader.h new file mode 100644 index 0000000..30d851f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MaterialPBRMetallicRoughnessReader.h @@ -0,0 +1,77 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct MaterialPBRMetallicRoughness; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::MaterialPBRMetallicRoughness + * "MaterialPBRMetallicRoughness" instances from JSON. + */ +class CESIUMGLTFREADER_API MaterialPBRMetallicRoughnessReader { +public: + /** + * @brief Constructs a new instance. + */ + MaterialPBRMetallicRoughnessReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of MaterialPBRMetallicRoughness from a byte + * buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of MaterialPBRMetallicRoughness from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of MaterialPBRMetallicRoughness from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MaterialReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MaterialReader.h new file mode 100644 index 0000000..ac8ccca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MaterialReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Material; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Material "Material" instances from JSON. + */ +class CESIUMGLTFREADER_API MaterialReader { +public: + /** + * @brief Constructs a new instance. + */ + MaterialReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Material from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Material from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Material from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MeshPrimitiveReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MeshPrimitiveReader.h new file mode 100644 index 0000000..68b29f7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MeshPrimitiveReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct MeshPrimitive; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::MeshPrimitive "MeshPrimitive" instances from + * JSON. + */ +class CESIUMGLTFREADER_API MeshPrimitiveReader { +public: + /** + * @brief Constructs a new instance. + */ + MeshPrimitiveReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of MeshPrimitive from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of MeshPrimitive from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of MeshPrimitive from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MeshReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MeshReader.h new file mode 100644 index 0000000..51e46f4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/MeshReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Mesh; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Mesh "Mesh" instances from JSON. + */ +class CESIUMGLTFREADER_API MeshReader { +public: + /** + * @brief Constructs a new instance. + */ + MeshReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Mesh from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Mesh from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Mesh from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ModelReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ModelReader.h new file mode 100644 index 0000000..9d4d993 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ModelReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Model; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Model "Model" instances from JSON. + */ +class CESIUMGLTFREADER_API ModelReader { +public: + /** + * @brief Constructs a new instance. + */ + ModelReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Model from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Model from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Model from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/NetworkImageAssetDescriptor.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/NetworkImageAssetDescriptor.h new file mode 100644 index 0000000..3417c7d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/NetworkImageAssetDescriptor.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +namespace CesiumAsync { +class AsyncSystem; +} + +namespace CesiumGltfReader { + +/** + * @brief A description of an image asset that can be loaded from the network + * using an {@link CesiumAsync::IAssetAccessor}. This includes a URL, any headers to be + * included in the request, and the set of supported GPU texture formats for + * KTX2 decoding. + */ +struct NetworkImageAssetDescriptor + : public CesiumAsync::NetworkAssetDescriptor { + /** + * @brief The supported GPU texture formats used for KTX2 decoding. + */ + CesiumGltf::Ktx2TranscodeTargets ktx2TranscodeTargets{}; + + /** + * @brief Determines if this descriptor is identical to another one. + */ + bool operator==(const NetworkImageAssetDescriptor& rhs) const noexcept; + + /** + * @brief Request this asset from the network using the provided asset + * accessor and return the loaded {@link CesiumGltf::ImageAsset}. + * + * @param asyncSystem The async system. + * @param pAssetAccessor The asset accessor. + * @return A future that resolves to the image asset once the request is + * complete. + */ + CesiumAsync::Future> + load( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor) const; +}; + +} // namespace CesiumGltfReader + +/** @brief Hash implementation for \ref + * CesiumGltfReader::NetworkImageAssetDescriptor. */ +template <> struct std::hash { + /** @brief Returns a `size_t` hash of the provided \ref + * CesiumGltfReader::NetworkImageAssetDescriptor. */ + std::size_t operator()( + const CesiumGltfReader::NetworkImageAssetDescriptor& key) const noexcept; +}; diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/NetworkSchemaAssetDescriptor.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/NetworkSchemaAssetDescriptor.h new file mode 100644 index 0000000..c74b0ad --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/NetworkSchemaAssetDescriptor.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace CesiumAsync { +class AsyncSystem; +} + +namespace CesiumGltfReader { + +/** + * @brief A description of a schema asset that can be loaded from the network + * using an {@link CesiumAsync::IAssetAccessor}. This includes a URL and any headers to be + * included in the request. + */ +struct NetworkSchemaAssetDescriptor + : public CesiumAsync::NetworkAssetDescriptor { + /** + * @brief Determines if this descriptor is identical to another one. + */ + bool operator==(const NetworkSchemaAssetDescriptor& rhs) const noexcept; + + /** + * @brief Request this asset from the network using the provided asset + * accessor and return the loaded {@link CesiumGltf::Schema}. + * + * @param asyncSystem The async system. + * @param pAssetAccessor The asset accessor. + * @return A future that resolves to the schema asset once the request is + * complete. + */ + CesiumAsync::Future> load( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor) const; +}; + +} // namespace CesiumGltfReader + +/** @brief Hash implementation for \ref + * CesiumGltfReader::NetworkSchemaAssetDescriptor. */ +template <> struct std::hash { + /** @brief Returns a `size_t` hash of the provided \ref + * CesiumGltfReader::NetworkSchemaAssetDescriptor. */ + std::size_t operator()( + const CesiumGltfReader::NetworkSchemaAssetDescriptor& key) const noexcept; +}; diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/NodeReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/NodeReader.h new file mode 100644 index 0000000..19763c6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/NodeReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Node; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Node "Node" instances from JSON. + */ +class CESIUMGLTFREADER_API NodeReader { +public: + /** + * @brief Constructs a new instance. + */ + NodeReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Node from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Node from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Node from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyAttributePropertyReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyAttributePropertyReader.h new file mode 100644 index 0000000..2bde7c5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyAttributePropertyReader.h @@ -0,0 +1,76 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct PropertyAttributeProperty; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::PropertyAttributeProperty + * "PropertyAttributeProperty" instances from JSON. + */ +class CESIUMGLTFREADER_API PropertyAttributePropertyReader { +public: + /** + * @brief Constructs a new instance. + */ + PropertyAttributePropertyReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of PropertyAttributeProperty from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of PropertyAttributeProperty from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of PropertyAttributeProperty from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyAttributeReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyAttributeReader.h new file mode 100644 index 0000000..beab5fc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyAttributeReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct PropertyAttribute; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::PropertyAttribute "PropertyAttribute" instances + * from JSON. + */ +class CESIUMGLTFREADER_API PropertyAttributeReader { +public: + /** + * @brief Constructs a new instance. + */ + PropertyAttributeReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of PropertyAttribute from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of PropertyAttribute from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of PropertyAttribute from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyTablePropertyReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyTablePropertyReader.h new file mode 100644 index 0000000..bbc9dac --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyTablePropertyReader.h @@ -0,0 +1,75 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct PropertyTableProperty; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::PropertyTableProperty "PropertyTableProperty" + * instances from JSON. + */ +class CESIUMGLTFREADER_API PropertyTablePropertyReader { +public: + /** + * @brief Constructs a new instance. + */ + PropertyTablePropertyReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of PropertyTableProperty from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of PropertyTableProperty from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of PropertyTableProperty from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyTableReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyTableReader.h new file mode 100644 index 0000000..c36a694 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyTableReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct PropertyTable; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::PropertyTable "PropertyTable" instances from + * JSON. + */ +class CESIUMGLTFREADER_API PropertyTableReader { +public: + /** + * @brief Constructs a new instance. + */ + PropertyTableReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of PropertyTable from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of PropertyTable from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of PropertyTable from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyTexturePropertyReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyTexturePropertyReader.h new file mode 100644 index 0000000..198cb65 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyTexturePropertyReader.h @@ -0,0 +1,76 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct PropertyTextureProperty; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::PropertyTextureProperty + * "PropertyTextureProperty" instances from JSON. + */ +class CESIUMGLTFREADER_API PropertyTexturePropertyReader { +public: + /** + * @brief Constructs a new instance. + */ + PropertyTexturePropertyReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of PropertyTextureProperty from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of PropertyTextureProperty from a + * rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of PropertyTextureProperty from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyTextureReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyTextureReader.h new file mode 100644 index 0000000..a2e5f22 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/PropertyTextureReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct PropertyTexture; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::PropertyTexture "PropertyTexture" instances + * from JSON. + */ +class CESIUMGLTFREADER_API PropertyTextureReader { +public: + /** + * @brief Constructs a new instance. + */ + PropertyTextureReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of PropertyTexture from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of PropertyTexture from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of PropertyTexture from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/SamplerReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/SamplerReader.h new file mode 100644 index 0000000..1206b97 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/SamplerReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Sampler; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Sampler "Sampler" instances from JSON. + */ +class CESIUMGLTFREADER_API SamplerReader { +public: + /** + * @brief Constructs a new instance. + */ + SamplerReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Sampler from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Sampler from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Sampler from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/SceneReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/SceneReader.h new file mode 100644 index 0000000..72b5fb2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/SceneReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Scene; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Scene "Scene" instances from JSON. + */ +class CESIUMGLTFREADER_API SceneReader { +public: + /** + * @brief Constructs a new instance. + */ + SceneReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Scene from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Scene from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Scene from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/SchemaReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/SchemaReader.h new file mode 100644 index 0000000..352d830 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/SchemaReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Schema; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Schema "Schema" instances from JSON. + */ +class CESIUMGLTFREADER_API SchemaReader { +public: + /** + * @brief Constructs a new instance. + */ + SchemaReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Schema from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Schema from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Schema from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/SkinReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/SkinReader.h new file mode 100644 index 0000000..332a926 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/SkinReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Skin; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Skin "Skin" instances from JSON. + */ +class CESIUMGLTFREADER_API SkinReader { +public: + /** + * @brief Constructs a new instance. + */ + SkinReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Skin from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Skin from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Skin from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/TextureInfoReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/TextureInfoReader.h new file mode 100644 index 0000000..908ac1d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/TextureInfoReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct TextureInfo; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::TextureInfo "TextureInfo" instances from JSON. + */ +class CESIUMGLTFREADER_API TextureInfoReader { +public: + /** + * @brief Constructs a new instance. + */ + TextureInfoReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of TextureInfo from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of TextureInfo from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of TextureInfo from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/TextureReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/TextureReader.h new file mode 100644 index 0000000..3da9d4d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/TextureReader.h @@ -0,0 +1,72 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumGltf { +struct Texture; +} // namespace CesiumGltf + +namespace CesiumGltfReader { + +/** + * @brief Reads \ref CesiumGltf::Texture "Texture" instances from JSON. + */ +class CESIUMGLTFREADER_API TextureReader { +public: + /** + * @brief Constructs a new instance. + */ + TextureReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Texture from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Texture from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Texture from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfWriter/GltfWriter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfWriter/GltfWriter.h new file mode 100644 index 0000000..e2ca35e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfWriter/GltfWriter.h @@ -0,0 +1,112 @@ +#pragma once + +#include "CesiumGltfWriter/Library.h" + +#include + +#include + +// forward declarations +namespace CesiumGltf { +struct Model; +} + +namespace CesiumGltfWriter { + +/** + * @brief The result of writing a glTF with + * {@link GltfWriter::writeGltf} or {@link GltfWriter::writeGlb} + */ +struct CESIUMGLTFWRITER_API GltfWriterResult { + /** + * @brief The final generated std::vector of the glTF or glb. + */ + std::vector gltfBytes; + + /** + * @brief Errors, if any, that occurred during the write process. + */ + std::vector errors; + + /** + * @brief Warnings, if any, that occurred during the write process. + */ + std::vector warnings; +}; + +/** + * @brief Options for how to write a glTF. + */ +struct CESIUMGLTFWRITER_API GltfWriterOptions { + /** + * @brief If the glTF JSON should be pretty printed. Usable with glTF or GLB + * (not advised). + */ + bool prettyPrint = false; + + /** + * @brief Byte alignment of the GLB binary chunk. When using 64-bit types in + * EXT_mesh_features this value should be set to 8. + */ + size_t binaryChunkByteAlignment = 4; +}; + +/** + * @brief Writes glTF. + */ +class CESIUMGLTFWRITER_API GltfWriter { +public: + /** + * @brief Constructs a new instance. + */ + GltfWriter(); + + /** + * @brief Gets the context used to control how glTF extensions are written. + */ + CesiumJsonWriter::ExtensionWriterContext& getExtensions(); + + /** + * @brief Gets the context used to control how glTF extensions are written. + */ + const CesiumJsonWriter::ExtensionWriterContext& getExtensions() const; + + /** + * @brief Serializes the provided model into a glTF JSON byte vector. + * + * @details Ignores internal data such as {@link CesiumGltf::BufferCesium} + * and {@link CesiumGltf::ImageAsset} when serializing the glTF. Internal + * data must either be converted to data uris or saved as external files. The + * buffer.uri and image.uri fields must be set accordingly prior to calling + * this function. + * + * @param model The model. + * @param options Options for how to write the glTF. + * @return The result of writing the glTF. + */ + GltfWriterResult writeGltf( + const CesiumGltf::Model& model, + const GltfWriterOptions& options = GltfWriterOptions()) const; + + /** + * @brief Serializes the provided model into a glb byte vector. + * + * @details The first buffer object implicitly refers to the GLB binary chunk + * and should not have a uri. Ignores internal data such as + * {@link CesiumGltf::BufferCesium} and {@link CesiumGltf::ImageAsset}. + * + * @param model The model. + * @param bufferData The buffer data to store in the GLB binary chunk. + * @param options Options for how to write the glb. + * @return The result of writing the glb. + */ + GltfWriterResult writeGlb( + const CesiumGltf::Model& model, + const std::span& bufferData, + const GltfWriterOptions& options = GltfWriterOptions()) const; + +private: + CesiumJsonWriter::ExtensionWriterContext _context; +}; + +} // namespace CesiumGltfWriter diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfWriter/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfWriter/Library.h new file mode 100644 index 0000000..d990077 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfWriter/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes for writing [glTF](https://www.khronos.org/gltf/) models. + * + * @mermaid-interactive{dependencies/CesiumGltfWriter} + */ +namespace CesiumGltfWriter {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMGLTFWRITER_BUILDING +#define CESIUMGLTFWRITER_API __declspec(dllexport) +#else +#define CESIUMGLTFWRITER_API __declspec(dllimport) +#endif +#else +#define CESIUMGLTFWRITER_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfWriter/SchemaWriter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfWriter/SchemaWriter.h new file mode 100644 index 0000000..9a66a3c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfWriter/SchemaWriter.h @@ -0,0 +1,81 @@ +#pragma once + +#include "CesiumGltfWriter/Library.h" + +#include + +// forward declarations +namespace CesiumGltf { +struct Schema; +} + +namespace CesiumGltfWriter { + +/** + * @brief The result of writing a schema with + * {@link SchemaWriter::writeSchema}. + */ +struct CESIUMGLTFWRITER_API SchemaWriterResult { + /** + * @brief The final generated std::vector of the schema JSON. + */ + std::vector schemaBytes; + + /** + * @brief Errors, if any, that occurred during the write process. + */ + std::vector errors; + + /** + * @brief Warnings, if any, that occurred during the write process. + */ + std::vector warnings; +}; + +/** + * @brief Options for how to write a schema. + */ +struct CESIUMGLTFWRITER_API SchemaWriterOptions { + /** + * @brief If the schema JSON should be pretty printed. + */ + bool prettyPrint = false; +}; + +/** + * @brief Writes schemas. + */ +class CESIUMGLTFWRITER_API SchemaWriter { +public: + /** + * @brief Constructs a new instance. + */ + SchemaWriter(); + + /** + * @brief Gets the context used to control how schema extensions are written. + */ + CesiumJsonWriter::ExtensionWriterContext& getExtensions(); + + /** + * @brief Gets the context used to control how schema extensions are written. + */ + const CesiumJsonWriter::ExtensionWriterContext& getExtensions() const; + + /** + * @brief Serializes the provided schema object into a byte vector using the + * provided flags to convert. + * + * @param schema The schema. + * @param options Options for how to write the schema. + * @return The result of writing the schema. + */ + SchemaWriterResult writeSchema( + const CesiumGltf::Schema& schema, + const SchemaWriterOptions& options = SchemaWriterOptions()) const; + +private: + CesiumJsonWriter::ExtensionWriterContext _context; +}; + +} // namespace CesiumGltfWriter diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/ApplicationData.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/ApplicationData.h new file mode 100644 index 0000000..72f168a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/ApplicationData.h @@ -0,0 +1,62 @@ +#pragma once + +#include + +namespace CesiumIonClient { + +/** + * @brief An enumeration representing the values of the `authenticationMode` + * property in the `appData` response. + */ +enum AuthenticationMode { + /** + * Authentication using OAuth with an ion.cesium.com account. + */ + CesiumIon, + /** + * Authentication using OAuth with Cesium ion Self-Hosted. + * On the server, this uses the Security Assertion Markup Language (SAML) to + * communicate with another authentication server. + * From our perspective, we can treat this the same as {@link AuthenticationMode::CesiumIon}. + */ + Saml, + /** + * A Cesium ion Self-Hosted server without authentication. + * In single-user mode, any application that can reach the server has + * permissions to use its endpoints. In this mode, some endpoints (like /me + * and /tokens) are unavailable. + */ + SingleUser +}; + +/** + * @brief Data retrieved from the Cesium ion server via an "appData" request + * from Cesium ion. This actually represents information about the server + * itself. + */ +struct ApplicationData { + /** + * The authentication mode that the ion server is running in. + */ + AuthenticationMode authenticationMode; + + /** + * The type of store used by this ion server to hold files. + * Known values: FILE_SYSTEM, S3 + */ + std::string dataStoreType; + + /** + * The attribution HTML for this ion server. + */ + std::string attribution; + + /** + * @brief Does the `authenticationMode` require OAuth authentication? + */ + bool needsOauthAuthentication() const { + return this->authenticationMode != AuthenticationMode::SingleUser; + } +}; + +} // namespace CesiumIonClient diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Assets.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Assets.h new file mode 100644 index 0000000..4fcd373 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Assets.h @@ -0,0 +1,93 @@ +#pragma once + +#include +#include +#include + +namespace CesiumIonClient { +/** + * @brief A Cesium ion Asset, such as a 3D Tiles tileset or an imagery layer. + */ +struct Asset { + /** + * @brief The unique identifier for this asset. + */ + int64_t id = -1; + + /** + * @brief The name of this asset. + */ + std::string name; + + /** + * @brief A Markdown compatible string describing this asset. + */ + std::string description; + + /** + * @brief A Markdown compatible string containing any required attribution for + * this asset. + * + * Clients will be required to display this attribution to end users. + */ + std::string attribution; + + /** + * @brief The asset's [type](https://cesium.com/docs/rest-api/#tag/Assets)./ + */ + std::string type; + + /** + * @brief The number of bytes this asset occupies in the user's account. + */ + int64_t bytes = 0; + + /** + * @brief The date and time that this asset was created in [RFC + * 3339](https://tools.ietf.org/html/rfc3339) format. + */ + std::string dateAdded; + + /** + * @brief Describes the state of the asset during the upload and tiling + * processes. + * + * | *Value* | *Description* | + * | AWAITING_FILES | The asset has been created but the server is waiting for + * source data to be uploaded. | | NOT_STARTED | The server was notified that + * all source data was uploaded and is waiting for the tiling process to + * start. | | IN_PROGRESS | The source data is being tiled, see + * percentComplete to monitor progress. | | COMPLETE | The asset was tiled + * successfully. | | DATA_ERROR | The uploaded source data was invalid or + * unsupported. | | ERROR | An internal error occurred during the tiling + * process. Please contact support@cesium.com. | + */ + std::string status; + + /** + * @brief The percentage progress of the tiling pipeline preparing this asset. + */ + int8_t percentComplete = 0; +}; + +/** + * @brief A page of assets obtained from the Cesium ion `v1/assets` endpoint, + * including a link to obtain the next page, if one exists. + */ +struct Assets { + /** + * @brief An [RFC 5988](https://tools.ietf.org/html/rfc5988) formatted string + * with a relation type of next which points to the next page of data on the + * server, if it exists. + * + * This url should be treated as an opaque link as the actual format may + * change at any time. + */ + std::string link; + + /** + * @brief A page of assets. + */ + std::vector items; +}; +} // namespace CesiumIonClient diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Connection.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Connection.h new file mode 100644 index 0000000..14ff5f3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Connection.h @@ -0,0 +1,342 @@ +#pragma once + +#include "ApplicationData.h" +#include "Assets.h" +#include "Defaults.h" +#include "Profile.h" +#include "Response.h" +#include "Token.h" +#include "TokenList.h" + +#include +#include +#include + +#include + +namespace CesiumIonClient { + +/** + * @brief Whether sorted results should be ascending or descending. + */ +enum class SortOrder { Ascending, Descending }; + +/** + * @brief Options to be passed to {@link Connection::tokens}. + */ +struct ListTokensOptions { + /** + * @brief The maximum number of tokens to return in a single page. + * + * Receiving fewer tokens should not be interpreted as the end of the + * collection. The end of the collection is reached when the response does not + * contain {@link Response::nextPageUrl}. + */ + std::optional limit; + + /** + * @brief The page number, where the first page of results is page 1 (not 0). + */ + std::optional page; + + /** + * @brief One or more keywords separated by whitespace by which to + * filter the list of tokens. The token name will contain each keyword of the + * search string. + */ + std::optional search; + + /** + * @brief The property by which to sort results. Valid values are + * `"NAME"` and `"LAST_USED"`. + */ + std::optional sortBy; + + /** + * @brief The property by which to sort results. Valid values are + * `"NAME"` and `"LAST_USED"`. + */ + std::optional sortOrder; +}; + +/** + * @brief A connection to Cesium ion that can be used to interact with it via + * its REST API. + */ +class CESIUMASYNC_API Connection { +public: + /** + * @brief Authorizes access to Cesium ion on behalf of a user, and returns a + * {@link Connection} that can be used to interact with ion. + * + * Uses the "Authorization Code with PKCE" OAuth2 flow. + * + * See [Connecting to Cesium ion with + * OAuth2](https://cesium.com/learn/ion/ion-oauth2/) for a description of the + * authorization process. + * + * @param asyncSystem The async system used to do work in threads. + * @param pAssetAccessor The interface used to interact with the Cesium ion + * REST API. + * @param friendlyApplicationName A friendly name for the application + * requesting access. It will be displayed to the user when authorization is + * complete, informing them that they can return to the original application. + * @param clientID The client ID that was assigned to your application when + * you registered it. + * @param redirectPath The path on http://127.0.0.1 that a user will be + * redirected to once they authorize your application. This must match the URI + * provided when you registered your application, without the protocol, + * hostname, or port. + * @param scopes The list of scopes that the eventually-granted token should + * allow access to. + * @param openUrlCallback A function that is invoked to launch the user's web + * browser with a given URL so that they can authorize access. + * @param appData The app data retrieved from the Cesium ion server. + * @param ionApiUrl The base URL of the Cesium ion API. + * @param ionAuthorizeUrl The URL of the Cesium ion OAuth authorization page. + * @return A future that resolves to a Cesium ion {@link Connection} once the + * user authorizes the application and the token handshake completes. + */ + static CesiumAsync::Future authorize( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::string& friendlyApplicationName, + int64_t clientID, + const std::string& redirectPath, + const std::vector& scopes, + std::function&& openUrlCallback, + const CesiumIonClient::ApplicationData& appData, + const std::string& ionApiUrl = "https://api.cesium.com/", + const std::string& ionAuthorizeUrl = "https://ion.cesium.com/oauth"); + + /** + * @brief Retrieves information about the ion API server. + * + * @param asyncSystem The async system used to do work in threads. + * @param pAssetAccessor The interface used to interact with the Cesium ion + * REST API. + * @param apiUrl The URL of the ion REST API to make requests against. + * @return A future that resolves to the application information. + */ + static CesiumAsync::Future> appData( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::string& apiUrl = "https://api.cesium.com"); + + /** + * @brief Attempts to retrieve the ion endpoint URL by looking for a + * `config.json` file on the server. + * + * This config file isn't present on `ion.cesium.com`, but will be present on + * Cesium ion self-hosted instances to allow the user to configure the URLs of + * their self-hosted instance as needed. + * + * @param asyncSystem The async system used to do work in threads. + * @param pAssetAccessor The interface used to interact with the Cesium ion + * REST API. + * @param ionUrl The URL of the Cesium ion instance to make this request + * against. + * @returns The Cesium ion REST API url for this ion instance, or + * `std::nullopt` if none found. + */ + static CesiumAsync::Future> getApiUrl( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::string& ionUrl); + + /** + * @brief Creates a connection to Cesium ion using the provided access token. + * + * @param asyncSystem The async system used to do work in threads. + * @param pAssetAccessor The interface used to interact with the Cesium ion + * REST API. + * @param accessToken The access token + * @param appData The app data retrieved from the Cesium ion server. + * @param apiUrl The base URL of the Cesium ion API. + */ + Connection( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::string& accessToken, + const CesiumIonClient::ApplicationData& appData, + const std::string& apiUrl = "https://api.cesium.com"); + + /** + * @brief Gets the async system used by this connection to do work in threads. + */ + const CesiumAsync::AsyncSystem& getAsyncSystem() const noexcept { + return this->_asyncSystem; + } + + /** + * @brief Gets the interface used by this connection to interact with the + * Cesium ion REST API. + */ + const std::shared_ptr& + getAssetAccessor() const noexcept { + return this->_pAssetAccessor; + } + + /** + * @brief Gets the access token used by this connection. + */ + const std::string& getAccessToken() const noexcept { + return this->_accessToken; + } + + /** + * @brief Gets the Cesium ion API base URL. + */ + const std::string& getApiUrl() const noexcept { return this->_apiUrl; } + + /** + * @brief Retrieves profile information for the access token currently being + * used to make API calls. + * + * This route works with any valid token, but additional information is + * returned if the token uses the `profile:read` scope. + * + * @return A future that resolves to the profile information. + */ + CesiumAsync::Future> me() const; + + /** + * @brief Retrieves default imagery, terrain and building assets along with + * quick add assets that can be useful to use within other applications. + * + * This route will always return data, but will return user specific + * information with any valid token. + * + * @return A future that resolves to the default information. + */ + CesiumAsync::Future> defaults() const; + + /** + * @brief Gets the list of available assets. + * + * @return A future that resolves to the asset information. + */ + CesiumAsync::Future> assets() const; + + /** + * @brief Invokes the "List tokens" service to get the list of available + * tokens. + * + * Only a single page is returned. To obtain additional pages, use + * {@link Connection::nextPage} and {@link Connection::previousPage}. + * + * @param options Options to include in the "List tokens" request. + * @return A future that resolves to a page of token information. + */ + CesiumAsync::Future> + tokens(const ListTokensOptions& options = {}) const; + + /** + * @brief Gets details of the asset with the given ID. + * + * @param assetID The asset ID. + * @return A future that resolves to the asset details. + */ + CesiumAsync::Future> asset(int64_t assetID) const; + + /** + * @brief Gets details of the token with the given ID. + * + * @param tokenID The token ID. + * @return A future that resolves to the token details. + */ + CesiumAsync::Future> token(const std::string& tokenID) const; + + /** + * @brief Gets the next page of results from the "List tokens" service. + * + * To get the first page, use {@link Connection::tokens}. + * + * @param currentPage The current page from which to get the next page. + * @return A future that resolves to the next page of tokens, or to a + * response with an {@link Response::errorCode} of "NoMorePages" if the + * currentPage is the last one. + */ + CesiumAsync::Future> + nextPage(const Response& currentPage) const; + + /** + * @brief Gets the previous page of results from the "List tokens" service. + * + * To get the first page (or a particular page), use {@link Connection::tokens}. + * + * @param currentPage The current page from which to get the previous page. + * @return A future that resolves to the previous page of tokens, or to a + * response with an {@link Response::errorCode} of "NoMorePages" if the + * currentPage is the first one. + */ + CesiumAsync::Future> + previousPage(const Response& currentPage) const; + + /** + * @brief Creates a new token. + * + * @param name The name of the new token. + * @param scopes The scopes allowed by this token. + * @param assetIds The assets that may be accessed by this token. If + * `std::nullopt`, access to all assets is allowed. + * @param allowedUrls The URLs from which this token can be accessed. If + * `std::nullopt`, the token can be accessed from any URL. + * @return The new token. + */ + CesiumAsync::Future> createToken( + const std::string& name, + const std::vector& scopes, + const std::optional>& assetIds = std::nullopt, + const std::optional>& allowedUrls = + std::nullopt) const; + + /** + * @brief Modifies a token. + * + * @param tokenID The ID of the token to modify. + * @param newName The new name of the token. + * @param newAssetIDs The assets that may be accessed by this token. If + * `std::nullopt`, access to all assets is allowed. + * @param newScopes The new OAuth scopes allowed by this token. + * @param newAllowedUrls The new URLs from which this token can be accessed. + * If `std::nullopt`, the token can be accessed from any URL. + * @return A value-less response. If the response is successful, the token has + * been modified. + */ + CesiumAsync::Future> modifyToken( + const std::string& tokenID, + const std::string& newName, + const std::optional>& newAssetIDs, + const std::vector& newScopes, + const std::optional>& newAllowedUrls) const; + + /** + * @brief Decodes a token ID from a token. + * + * @param token The token to decode. + * @return The token ID, or std::nullopt if the token ID cannot be determined + * from the token. + */ + static std::optional getIdFromToken(const std::string& token); + +private: + static CesiumAsync::Future completeTokenExchange( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + int64_t clientID, + const std::string& ionApiUrl, + const CesiumIonClient::ApplicationData& appData, + const std::string& code, + const std::string& redirectUrl, + const std::string& codeVerifier); + + CesiumAsync::Future> tokens(const std::string& url) const; + + CesiumAsync::AsyncSystem _asyncSystem; + std::shared_ptr _pAssetAccessor; + std::string _accessToken; + std::string _apiUrl; + CesiumIonClient::ApplicationData _appData; +}; +} // namespace CesiumIonClient diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Defaults.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Defaults.h new file mode 100644 index 0000000..eec7649 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Defaults.h @@ -0,0 +1,107 @@ +#pragma once + +namespace CesiumIonClient { + +/** + * @brief The default assets. + */ +struct DefaultAssets { + /** + * @brief The asset id of the default imagery asset. + */ + int64_t imagery = -1; + + /** + * @brief The asset id of the default terrain asset. + */ + int64_t terrain = -1; + + /** + * @brief The asset id of the default buildings asset. + */ + int64_t buildings = -1; +}; + +/** + * @brief A raster overlay available for use with a quick add asset. + */ +struct QuickAddRasterOverlay { + /** + * @brief The name of this asset. + */ + std::string name{}; + + /** + * @brief The unique identifier for this asset. + */ + int64_t assetId = -1; + + /** + * @brief `true` if the user is subscribed to the asset, `false` otherwise. + */ + bool subscribed = false; +}; + +/** + * @brief A quick add asset. + */ +struct QuickAddAsset { + /** + * @brief The name of this asset. + */ + std::string name{}; + + /** + * @brief The name of the main asset. In most cases this will be the same as + * `name`, but in the cases of assets with raster overlays, this will be the + * non-imagery asset. + */ + std::string objectName{}; + + /** + * @brief A Markdown compatible string describing this asset. + */ + std::string description{}; + + /** + * @brief The unique identifier for this asset. + */ + int64_t assetId = -1; + + /** + * @brief This asset's type. + * + * Valid values are: `3DTILES`, `GLTF`, `IMAGERY`, `TERRAIN`, `KML`, `CZML`, + * `GEOJSON`. + */ + std::string type{}; + + /** + * @brief `true` if the user is subscribed to the asset, `false` otherwise. + */ + bool subscribed = false; + + /** + * @brief The raster overlays available for this asset + */ + std::vector rasterOverlays{}; +}; + +/** + * @brief The data returned by Cesium ion's `v1/defaults` service. It includes + * information about default imagery, terrain and building assets along with + * quick add assets that can be useful to use within other applications. + */ +struct Defaults { + /** + * @brief The default assets + */ + DefaultAssets defaultAssets{}; + + /** + * @brief The quick add assets + */ + std::vector quickAddAssets{}; +}; + +} // namespace CesiumIonClient diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Library.h new file mode 100644 index 0000000..62ea3fd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes for working with Cesium ion clients + * + * @mermaid-interactive{dependencies/CesiumIonClient} + */ +namespace CesiumIonClient {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMIONCLIENT_BUILDING +#define CESIUMIONCLIENT_API __declspec(dllexport) +#else +#define CESIUMIONCLIENT_API __declspec(dllimport) +#endif +#else +#define CESIUMIONCLIENT_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Profile.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Profile.h new file mode 100644 index 0000000..20c744a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Profile.h @@ -0,0 +1,74 @@ +#pragma once + +#include +#include +#include + +namespace CesiumIonClient { + +/** + * @brief Information about the amount of storage available in a user's account. + */ +struct ProfileStorage final { + /** + * @brief The number of bytes currently being used by this account. + */ + int64_t used = 0; + + /** + * @brief The number of bytes available for additional asset uploads to this + * account. + */ + int64_t available = 0; + + /** + * @brief The total number of bytes currently allowed to be used by this + * account. + */ + int64_t total = 0; +}; + +/** + * @brief Contains of a Cesium ion user. + * + * @see CesiumIonConnection#me + */ +struct Profile final { + /** + * @brief The unique identifier for this account. + */ + int64_t id = -1; + + /** + * @brief The array of scopes available with this token. + */ + std::vector scopes{}; + + /** + * @brief The account username. + */ + std::string username{}; + + /** + * @brief The primary email address associated with this account. + */ + std::string email{}; + + /** + * @brief If true, the email address has been verified for this account. + */ + bool emailVerified = false; + + /** + * @brief A url to the profile image associated with this account. + */ + std::string avatar{}; + + /** + * @brief Information about the amount of storage available in the user's + * account. + */ + ProfileStorage storage{0, 0, 0}; +}; + +} // namespace CesiumIonClient diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Response.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Response.h new file mode 100644 index 0000000..fe41023 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Response.h @@ -0,0 +1,124 @@ +#pragma once + +#include +#include +#include +#include + +namespace CesiumAsync { +class IAssetRequest; +} + +namespace CesiumIonClient { + +/** + * @brief A response from Cesium ion. + * + * @tparam T The type of the response object. + */ +template struct Response final { + /** + * @brief Creates a new empty `Response`. + */ + Response(); + + /** + * @brief Creates a `Response` from a completed request and a response value. + * + * @param pRequest A completed request. The constructor will attempt to obtain + * the `httpStatusCode`, `previousPageUrl`, and `nextPageUrl` from this + * request. + * @param value The response value. + */ + Response( + const std::shared_ptr& pRequest, + T&& value); + + /** + * @brief Creates a `Response` from a response value, status code, and error + * information + * + * @param value The response value. + * @param httpStatusCode The HTTP status code of the response. + * @param errorCode The error code. See \ref Response::errorCode. If no error + * occurred, pass an empty string. + * @param errorMessage The error message. See \ref Response::errorMessage. If + * no error occurred, pass an empty string. + */ + Response( + T&& value, + uint16_t httpStatusCode, + const std::string& errorCode, + const std::string& errorMessage); + + /** + * @brief Creates a `Response` with no value, a status code, and error + * information. + * + * @param httpStatusCode The HTTP status code of the response. + * @param errorCode The error code. See \ref Response::errorCode. + * @param errorMessage The error message. See \ref Response::errorMessage. + */ + Response( + uint16_t httpStatusCode, + const std::string& errorCode, + const std::string& errorMessage); + + /** + * @brief The response value, or `std::nullopt` if the response was + * unsuccessful. + */ + std::optional value; + + /** + * @brief The HTTP status code returned by Cesium ion. + */ + uint16_t httpStatusCode; + + /** + * @brief The error code, or empty string if there was no error. + * + * If no response is received at all, the code will be `"NoResponse"`. + * + * If Cesium ion returns an error, this will be the `code` reported by Cesium + * ion. + * + * If Cesium ion reports success but an error occurs while attempting to parse + * the response, the code will be + * `"ParseError"`. + */ + std::string errorCode; + + /** + * @brief The error message returned, or an empty string if there was no + * error. + * + * If Cesium ion returns an error, this will be the `message` reported by + * Cesium ion. If Cesium ion reports success but another error occurs, the + * message will contain further details of the error. + */ + std::string errorMessage; + + /** + * @brief The URL to use to obtain the next page of results, if there is a + * next page. + * + * Call {@link Connection::nextPage} rather than using this field directly. + */ + std::optional nextPageUrl; + + /** + * @brief The URL to use to obtain the previous page of results, if there is + * one. + * + * Call {@link Connection::previousPage} rather than using this field directly. + */ + std::optional previousPageUrl; +}; + +/** + * @brief A non-value, for use with a valueless {@link Response}. + */ +struct NoValue {}; + +} // namespace CesiumIonClient diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Token.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Token.h new file mode 100644 index 0000000..4881361 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Token.h @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include +#include + +namespace CesiumIonClient { +/** + * @brief A Cesium ion access token. + */ +struct Token { + /** + * @brief The identifier of the token. + */ + std::string id{}; + + /** + * @brief The name of the token. + */ + std::string name{}; + + /** + * @brief The token value. + */ + std::string token{}; + + /** + * @brief The date and time that this token was created, in RFC 3339 format. + */ + std::string dateAdded{}; + + /** + * @brief The date and time that this token was last modified, in RFC 3339 + * format. + */ + std::string dateModified{}; + + /** + * @brief The date and time that this token was last used, in RFC 3339 format. + */ + std::string dateLastUsed{}; + + /** + * @brief The IDs of the assets that can be accessed using this token. + * + * If `std::nullopt`, the token allows access to all assets. + */ + std::optional> assetIds{}; + + /** + * @brief True if this is the default token. + */ + bool isDefault{}; + + /** + * @brief The URLs from which this token can be accessed. + * + * If `std::nullopt`, the token can be accessed from any URL. + */ + std::optional> allowedUrls{}; + + /** + * @brief The scopes granted by this token. + */ + std::vector scopes{}; +}; +} // namespace CesiumIonClient diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/TokenList.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/TokenList.h new file mode 100644 index 0000000..32da351 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/TokenList.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Token.h" + +namespace CesiumIonClient { + +/** + * @brief A list of Cesium ion access tokens, as returned by the "List Tokens" + * service. + */ +struct TokenList { + /** + * @brief The tokens. + * + */ + std::vector items; +}; + +} // namespace CesiumIonClient diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ArrayJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ArrayJsonHandler.h new file mode 100644 index 0000000..ff00374 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ArrayJsonHandler.h @@ -0,0 +1,628 @@ +#pragma once + +#include "CesiumUtility/Assert.h" +#include "DoubleJsonHandler.h" +#include "IntegerJsonHandler.h" +#include "JsonHandler.h" +#include "Library.h" +#include "StringJsonHandler.h" + +#include +#include +#include + +namespace CesiumJsonReader { +/** + * @brief \ref IJsonHandler for reading a JSON array into an `std::vector`. + * + * @tparam T The element type of the destination vector. + * @tparam THandler The \ref IJsonHandler to handle each element. + */ +template +class CESIUMJSONREADER_API ArrayJsonHandler : public JsonHandler { +public: + /** @brief The destination type. */ + using ValueType = std::vector; + + /** + * @brief Creates a new \ref ArrayJsonHandler. + * + * @param args The arguments that will be passed to the constructor of + * THandler when it's instantiated. + */ + template + ArrayJsonHandler(Ts&&... args) noexcept + : JsonHandler(), + _handlerFactory( + std::bind(handlerFactory, std::forward(args)...)), + _objectHandler() {} + + /** + * @brief Resets the parent and destination array of this \ref + * ArrayJsonHandler. + */ + void reset(IJsonHandler* pParent, std::vector* pArray) { + JsonHandler::reset(pParent); + this->_pArray = pArray; + this->_arrayIsOpen = false; + this->_objectHandler.reset(this->_handlerFactory()); + } + + virtual IJsonHandler* readNull() override { + return this->invalid("A null")->readNull(); + } + + virtual IJsonHandler* readBool(bool b) override { + return this->invalid("A boolean")->readBool(b); + } + + virtual IJsonHandler* readInt32(int32_t i) override { + return this->invalid("An integer")->readInt32(i); + } + + virtual IJsonHandler* readUint32(uint32_t i) override { + return this->invalid("An integer")->readUint32(i); + } + + virtual IJsonHandler* readInt64(int64_t i) override { + return this->invalid("An integer")->readInt64(i); + } + + virtual IJsonHandler* readUint64(uint64_t i) override { + return this->invalid("An integer")->readUint64(i); + } + + virtual IJsonHandler* readDouble(double d) override { + return this->invalid("A double (floating-point)")->readDouble(d); + } + + virtual IJsonHandler* readString(const std::string_view& str) override { + return this->invalid("A string")->readString(str); + } + + virtual IJsonHandler* readObjectStart() override { + if (!this->_arrayIsOpen) { + return this->invalid("An object")->readObjectStart(); + } + + CESIUM_ASSERT(this->_pArray); + T& o = this->_pArray->emplace_back(); + this->_objectHandler->reset(this, &o); + return this->_objectHandler->readObjectStart(); + } + + virtual IJsonHandler* + readObjectKey(const std::string_view& /*str*/) noexcept override { + return nullptr; + } + + virtual IJsonHandler* readObjectEnd() noexcept override { return nullptr; } + + virtual IJsonHandler* readArrayStart() override { + if (this->_arrayIsOpen) { + return this->invalid("An array")->readArrayStart(); + } + + this->_arrayIsOpen = true; + this->_pArray->clear(); + return this; + } + + virtual IJsonHandler* readArrayEnd() override { return this->parent(); } + + virtual void reportWarning( + const std::string& warning, + std::vector&& context = + std::vector()) override { + context.push_back( + std::string("[") + std::to_string(this->_pArray->size()) + "]"); + this->parent()->reportWarning(warning, std::move(context)); + } + +private: + IJsonHandler* invalid(const std::string& type) { + if (this->_arrayIsOpen) { + this->reportWarning( + type + " value is not allowed in the object array and has been " + "replaced with a default value."); + this->_pArray->emplace_back(); + return this->ignoreAndContinue(); + } else { + this->reportWarning(type + " is not allowed and has been ignored."); + return this->ignoreAndReturnToParent(); + } + } + + template static THandler* handlerFactory(Ts&&... args) { + return new THandler(std::forward(args)...); + } + + std::vector* _pArray = nullptr; + bool _arrayIsOpen = false; + + std::function _handlerFactory; + std::unique_ptr _objectHandler; +}; + +/** + * @brief Special case of \ref ArrayJsonHandler for handling arrays of double + * values. This will read every scalar value as a double, regardless of whether + * it's floating point or not. Attempting to read other values will cause a + * warning. + */ +template <> +class CESIUMJSONREADER_API ArrayJsonHandler + : public JsonHandler { +public: + /** @brief The destination type. */ + using ValueType = std::vector; + + ArrayJsonHandler() noexcept : JsonHandler() {} + + /** + * @brief Resets the parent and destination array of this \ref + * ArrayJsonHandler. + */ + void reset(IJsonHandler* pParent, std::vector* pArray) { + JsonHandler::reset(pParent); + this->_pArray = pArray; + this->_arrayIsOpen = false; + } + + virtual IJsonHandler* readNull() override { + return this->invalid("A null")->readNull(); + } + + virtual IJsonHandler* readBool(bool b) override { + return this->invalid("A bool")->readBool(b); + } + + virtual IJsonHandler* readInt32(int32_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readInt32(i); + } + + CESIUM_ASSERT(this->_pArray); + this->_pArray->emplace_back(static_cast(i)); + return this; + } + + virtual IJsonHandler* readUint32(uint32_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readUint32(i); + } + + CESIUM_ASSERT(this->_pArray); + this->_pArray->emplace_back(static_cast(i)); + return this; + } + + virtual IJsonHandler* readInt64(int64_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readInt64(i); + } + + CESIUM_ASSERT(this->_pArray); + this->_pArray->emplace_back(static_cast(i)); + return this; + } + + virtual IJsonHandler* readUint64(uint64_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readUint64(i); + } + + CESIUM_ASSERT(this->_pArray); + this->_pArray->emplace_back(static_cast(i)); + return this; + } + + virtual IJsonHandler* readDouble(double d) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readDouble(d); + } + + CESIUM_ASSERT(this->_pArray); + this->_pArray->emplace_back(d); + return this; + } + + virtual IJsonHandler* readString(const std::string_view& str) override { + return this->invalid("A string")->readString(str); + } + + virtual IJsonHandler* readObjectStart() override { + return this->invalid("An object")->readObjectStart(); + } + + virtual IJsonHandler* readArrayStart() override { + if (this->_arrayIsOpen) { + return this->invalid("An array")->readArrayStart(); + } + + this->_arrayIsOpen = true; + this->_pArray->clear(); + return this; + } + + virtual IJsonHandler* readArrayEnd() override { return this->parent(); } + + virtual void reportWarning( + const std::string& warning, + std::vector&& context = + std::vector()) override { + context.push_back( + std::string("[") + std::to_string(this->_pArray->size()) + "]"); + this->parent()->reportWarning(warning, std::move(context)); + } + +private: + IJsonHandler* invalid(const std::string& type) { + if (this->_arrayIsOpen) { + this->reportWarning( + type + " value is not allowed in the double array and has been " + "replaced with a default value."); + this->_pArray->emplace_back(); + return this->ignoreAndContinue(); + } else { + this->reportWarning(type + " is not allowed and has been ignored."); + return this->ignoreAndReturnToParent(); + } + } + + std::vector* _pArray = nullptr; + bool _arrayIsOpen = false; +}; + +/** + * @brief Special case of \ref ArrayJsonHandler for handling arrays of integer + * values. Attempting to read other values will cause a warning. + */ +template +class CESIUMJSONREADER_API ArrayJsonHandler> + : public JsonHandler { +public: + /** @brief The destination type. */ + using ValueType = std::vector; + + ArrayJsonHandler() noexcept : JsonHandler() {} + + /** + * @brief Resets the parent and destination array of this \ref + * ArrayJsonHandler. + */ + void reset(IJsonHandler* pParent, std::vector* pArray) { + JsonHandler::reset(pParent); + this->_pArray = pArray; + this->_arrayIsOpen = false; + } + + virtual IJsonHandler* readNull() override { + return this->invalid("A null")->readNull(); + } + + virtual IJsonHandler* readBool(bool b) override { + return this->invalid("A bool")->readBool(b); + } + + virtual IJsonHandler* readInt32(int32_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readInt32(i); + } + + CESIUM_ASSERT(this->_pArray); + this->_pArray->emplace_back(static_cast(i)); + return this; + } + + virtual IJsonHandler* readUint32(uint32_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readUint32(i); + } + + CESIUM_ASSERT(this->_pArray); + this->_pArray->emplace_back(static_cast(i)); + return this; + } + + virtual IJsonHandler* readInt64(int64_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readInt64(i); + } + + CESIUM_ASSERT(this->_pArray); + this->_pArray->emplace_back(static_cast(i)); + return this; + } + + virtual IJsonHandler* readUint64(uint64_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readUint64(i); + } + + CESIUM_ASSERT(this->_pArray); + this->_pArray->emplace_back(static_cast(i)); + return this; + } + + virtual IJsonHandler* readDouble(double d) override { + return this->invalid("A double (floating-point)")->readDouble(d); + } + + virtual IJsonHandler* readString(const std::string_view& str) override { + return this->invalid("A string")->readString(str); + } + + virtual IJsonHandler* readObjectStart() override { + return this->invalid("An object")->readObjectStart(); + } + + virtual IJsonHandler* readArrayStart() override { + if (this->_arrayIsOpen) { + return this->invalid("An array")->readArrayStart(); + } + + this->_arrayIsOpen = true; + this->_pArray->clear(); + return this; + } + + virtual IJsonHandler* readArrayEnd() override { return this->parent(); } + + virtual void reportWarning( + const std::string& warning, + std::vector&& context = + std::vector()) override { + context.push_back( + std::string("[") + std::to_string(this->_pArray->size()) + "]"); + this->parent()->reportWarning(warning, std::move(context)); + } + +private: + IJsonHandler* invalid(const std::string& type) { + if (this->_arrayIsOpen) { + this->reportWarning( + type + " value is not allowed in the integer array and has been " + "replaced with a default value."); + this->_pArray->emplace_back(); + return this->ignoreAndContinue(); + } else { + this->reportWarning(type + " is not allowed and has been ignored."); + return this->ignoreAndReturnToParent(); + } + } + + std::vector* _pArray = nullptr; + bool _arrayIsOpen = false; +}; + +/** + * @brief Special case of \ref ArrayJsonHandler for reading arrays of string + * values. Attempting to read other values will cause a warning. + */ +template <> +class CESIUMJSONREADER_API ArrayJsonHandler + : public JsonHandler { +public: + /** @brief The destination type. */ + using ValueType = std::vector; + + ArrayJsonHandler() noexcept : JsonHandler() {} + + /** + * @brief Resets the parent and destination array of this \ref + * ArrayJsonHandler. + */ + void reset(IJsonHandler* pParent, std::vector* pArray) { + JsonHandler::reset(pParent); + this->_pArray = pArray; + this->_arrayIsOpen = false; + } + + virtual IJsonHandler* readNull() override { + return this->invalid("A null")->readNull(); + } + + virtual IJsonHandler* readBool(bool b) override { + return this->invalid("A bool")->readBool(b); + } + + virtual IJsonHandler* readInt32(int32_t i) override { + return this->invalid("An integer")->readInt32(i); + } + + virtual IJsonHandler* readUint32(uint32_t i) override { + return this->invalid("An integer")->readUint32(i); + } + + virtual IJsonHandler* readInt64(int64_t i) override { + return this->invalid("An integer")->readInt64(i); + } + + virtual IJsonHandler* readUint64(uint64_t i) override { + return this->invalid("An integer")->readUint64(i); + } + + virtual IJsonHandler* readDouble(double d) override { + return this->invalid("A double (floating-point)")->readDouble(d); + } + + virtual IJsonHandler* readObjectStart() override { + return this->invalid("An object")->readObjectStart(); + } + + virtual IJsonHandler* readArrayStart() override { + if (this->_arrayIsOpen) { + return this->invalid("An array")->readArrayStart(); + } + + this->_arrayIsOpen = true; + this->_pArray->clear(); + return this; + } + + virtual IJsonHandler* readArrayEnd() override { return this->parent(); } + + virtual IJsonHandler* readString(const std::string_view& str) override { + if (!this->_arrayIsOpen) { + return this->invalid("A string")->readString(str); + } + + CESIUM_ASSERT(this->_pArray); + this->_pArray->emplace_back(str); + return this; + } + + virtual void reportWarning( + const std::string& warning, + std::vector&& context = + std::vector()) override { + context.push_back( + std::string("[") + std::to_string(this->_pArray->size()) + "]"); + this->parent()->reportWarning(warning, std::move(context)); + } + +private: + IJsonHandler* invalid(const std::string& type) { + if (this->_arrayIsOpen) { + this->reportWarning( + type + " value is not allowed in the string array and has been " + "replaced with a default value."); + this->_pArray->emplace_back(); + return this->ignoreAndContinue(); + } else { + this->reportWarning(type + " is not allowed and has been ignored."); + return this->ignoreAndReturnToParent(); + } + } + + std::vector* _pArray = nullptr; + bool _arrayIsOpen = false; +}; + +/** + * @brief Special case of \ref ArrayJsonHandler for reading arrays of arrays. + * Attempting to read other values will cause a warning. + * + * @tparam T The inner type of the nested array. + * @tparam THandler The handler of the inner type of the array. + */ +template +class CESIUMJSONREADER_API + ArrayJsonHandler, ArrayJsonHandler> + : public JsonHandler { +public: + /** @brief The destination type. */ + using ValueType = std::vector; + + /** + * @brief Creates a new \ref ArrayJsonHandler. + * + * @param args The arguments passed to the constructor of THandler when it's + * instantiated. + */ + template + ArrayJsonHandler(Ts&&... args) noexcept + : JsonHandler(), + _handlerFactory( + std::bind(handlerFactory, std::forward(args)...)), + _elementHandler() {} + + /** + * @brief Resets the parent and destination array of this \ref + * ArrayJsonHandler. + */ + void reset(IJsonHandler* pParent, std::vector>* pArray) { + JsonHandler::reset(pParent); + this->_pArray = pArray; + this->_arrayIsOpen = false; + this->_elementHandler.reset(this->_handlerFactory()); + } + + virtual IJsonHandler* readNull() override { + return this->invalid("A null")->readNull(); + } + + virtual IJsonHandler* readBool(bool b) override { + return this->invalid("A bool")->readBool(b); + } + + virtual IJsonHandler* readInt32(int32_t i) override { + return this->invalid("An integer")->readInt32(i); + } + + virtual IJsonHandler* readUint32(uint32_t i) override { + return this->invalid("An integer")->readUint32(i); + } + + virtual IJsonHandler* readInt64(int64_t i) override { + return this->invalid("An integer")->readInt64(i); + } + + virtual IJsonHandler* readUint64(uint64_t i) override { + return this->invalid("An integer")->readUint64(i); + } + + virtual IJsonHandler* readDouble(double d) override { + return this->invalid("A double (floating-point)")->readDouble(d); + } + + virtual IJsonHandler* readString(const std::string_view& str) override { + return this->invalid("A string")->readString(str); + } + + virtual IJsonHandler* readObjectStart() override { + return this->invalid("An object")->readObjectStart(); + } + + virtual IJsonHandler* readArrayStart() override { + if (this->_arrayIsOpen) { + CESIUM_ASSERT(this->_pArray); + std::vector& o = this->_pArray->emplace_back(); + this->_elementHandler->reset(this, &o); + return this->_elementHandler->readArrayStart(); + } else { + this->_arrayIsOpen = true; + this->_pArray->clear(); + return this; + } + } + + virtual IJsonHandler* readArrayEnd() override { return this->parent(); } + + virtual void reportWarning( + const std::string& warning, + std::vector&& context = + std::vector()) override { + context.push_back( + std::string("[") + std::to_string(this->_pArray->size()) + "]"); + this->parent()->reportWarning(warning, std::move(context)); + } + +private: + IJsonHandler* invalid(const std::string& type) { + if (this->_arrayIsOpen) { + this->reportWarning( + type + " value is not allowed in the array of arrays and has been " + "replaced with a default value."); + this->_pArray->emplace_back(); + return this->ignoreAndContinue(); + } else { + this->reportWarning(type + " is not allowed and has been ignored."); + return this->ignoreAndReturnToParent(); + } + } + + template + static ArrayJsonHandler* handlerFactory(Ts&&... args) { + return new ArrayJsonHandler(std::forward(args)...); + } + + std::vector>* _pArray = nullptr; + bool _arrayIsOpen = false; + + std::function*()> _handlerFactory; + std::unique_ptr> _elementHandler; +}; + +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/BoolJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/BoolJsonHandler.h new file mode 100644 index 0000000..7188cb4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/BoolJsonHandler.h @@ -0,0 +1,25 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +namespace CesiumJsonReader { +/** + * @brief \ref IJsonHandler for reading bool values. + */ +class CESIUMJSONREADER_API BoolJsonHandler : public JsonHandler { +public: + BoolJsonHandler() noexcept; + /** + * @brief Resets the parent \ref IJsonHandler of this handler, and the pointer + * to its destination bool value. + */ + void reset(IJsonHandler* pParent, bool* pBool); + + /** @copydoc IJsonHandler::readBool */ + virtual IJsonHandler* readBool(bool b) override; + +private: + bool* _pBool = nullptr; +}; +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/DictionaryJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/DictionaryJsonHandler.h new file mode 100644 index 0000000..33b7674 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/DictionaryJsonHandler.h @@ -0,0 +1,76 @@ +#pragma once + +#include "CesiumUtility/Assert.h" +#include "IntegerJsonHandler.h" +#include "Library.h" +#include "ObjectJsonHandler.h" + +#include +#include + +namespace CesiumJsonReader { +/** + * @brief Reads the keys and values of a JSON object into a + * `std::map` or an `std::unordered_map`. + * + * @tparam T The type of values in the map. + * @tparam THandler The type of the \ref IJsonHandler to handle the map values. + */ +template +class CESIUMJSONREADER_API DictionaryJsonHandler : public ObjectJsonHandler { +public: + /** + * @brief Creates a new \ref DictionaryJsonHandler, passing the specified + * arguments to the constructor of THandler. + */ + template + DictionaryJsonHandler(Ts&&... args) noexcept + : ObjectJsonHandler(), _item(std::forward(args)...) {} + + /** + * @brief Resets the parent of this \ref IJsonHandler and sets the destination + * pointer of this handler to an `std::unordered_map`. + * + * @warning Technically, there is no reason why you can't call `reset` twice + * on the same \ref DictionaryJsonHandler, once with an `std::map` and once + * with an `std::unordered_map`. In practice, if a pointer to an + * `std::unordered_map` is present, it will always be used as the destination + * and the pointer to an `std::map` will be ignored. + */ + void reset( + IJsonHandler* pParent, + std::unordered_map* pDictionary) { + ObjectJsonHandler::reset(pParent); + this->_pDictionary1 = pDictionary; + } + + /** + * @brief Resets the parent of this \ref IJsonHandler and sets the destination + * pointer of this handler to an `std::map`. + */ + void reset(IJsonHandler* pParent, std::map* pDictionary) { + ObjectJsonHandler::reset(pParent); + this->_pDictionary2 = pDictionary; + } + + /** @copydoc IJsonHandler::readObjectKey */ + virtual IJsonHandler* readObjectKey(const std::string_view& str) override { + CESIUM_ASSERT(this->_pDictionary1 || this->_pDictionary2); + + if (this->_pDictionary1) { + auto it = this->_pDictionary1->emplace(str, T()).first; + + return this->property(it->first.c_str(), this->_item, it->second); + } + + auto it = this->_pDictionary2->emplace(str, T()).first; + + return this->property(it->first.c_str(), this->_item, it->second); + } + +private: + std::unordered_map* _pDictionary1 = nullptr; + std::map* _pDictionary2 = nullptr; + THandler _item; +}; +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/DoubleJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/DoubleJsonHandler.h new file mode 100644 index 0000000..c4b5d26 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/DoubleJsonHandler.h @@ -0,0 +1,33 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +namespace CesiumJsonReader { +/** + * @brief \ref IJsonHandler for reading double values. + */ +class CESIUMJSONREADER_API DoubleJsonHandler : public JsonHandler { +public: + DoubleJsonHandler() noexcept; + /** + * @brief Resets the parent \ref IJsonHandler of this handler, and the pointer + * to its destination double value. + */ + void reset(IJsonHandler* pParent, double* pDouble); + + /** @copydoc IJsonHandler::readInt32 */ + virtual IJsonHandler* readInt32(int32_t i) override; + /** @copydoc IJsonHandler::readUint32 */ + virtual IJsonHandler* readUint32(uint32_t i) override; + /** @copydoc IJsonHandler::readInt64 */ + virtual IJsonHandler* readInt64(int64_t i) override; + /** @copydoc IJsonHandler::readUint64 */ + virtual IJsonHandler* readUint64(uint64_t i) override; + /** @copydoc IJsonHandler::readDouble */ + virtual IJsonHandler* readDouble(double d) override; + +private: + double* _pDouble = nullptr; +}; +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ExtensibleObjectJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ExtensibleObjectJsonHandler.h new file mode 100644 index 0000000..be514c7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ExtensibleObjectJsonHandler.h @@ -0,0 +1,58 @@ +#pragma once + +#include "DictionaryJsonHandler.h" +#include "ExtensionsJsonHandler.h" +#include "JsonObjectJsonHandler.h" +#include "JsonReaderOptions.h" +#include "ObjectJsonHandler.h" + +#include +#include + +namespace CesiumJsonReader { + +/** + * @brief An \ref IJsonHandler for reading \ref CesiumUtility::ExtensibleObject + * "ExtensibleObject" types. + */ +class ExtensibleObjectJsonHandler : public CesiumJsonReader::ObjectJsonHandler { +public: + /** + * @brief Creates an \ref ExtensibleObjectJsonHandler with the specified + * options. + * + * @param context Options to configure how the JSON is parsed. + */ + explicit ExtensibleObjectJsonHandler( + const JsonReaderOptions& context) noexcept; + +protected: + /** + * @brief Resets the current parent of this handler, and the current object + * being handled. + */ + void reset(IJsonHandler* pParent, CesiumUtility::ExtensibleObject* pObject); + /** + * @brief Reads a property of an \ref CesiumUtility::ExtensibleObject + * "ExtensibleObject" from the JSON. + * + * @param objectType The name of the ExtensibleObject's type. + * @param str The object key being read. + * @param o The \ref CesiumUtility::ExtensibleObject "ExtensibleObject" we're + * currently reading into. + */ + IJsonHandler* readObjectKeyExtensibleObject( + const std::string& objectType, + const std::string_view& str, + CesiumUtility::ExtensibleObject& o); + +private: + CesiumJsonReader::DictionaryJsonHandler< + CesiumUtility::JsonValue, + CesiumJsonReader::JsonObjectJsonHandler> + _extras; + ExtensionsJsonHandler _extensions; + JsonObjectJsonHandler _unknownProperties; + bool _captureUnknownProperties; +}; +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ExtensionsJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ExtensionsJsonHandler.h new file mode 100644 index 0000000..2a9391e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ExtensionsJsonHandler.h @@ -0,0 +1,49 @@ +#pragma once + +#include "IExtensionJsonHandler.h" +#include "JsonReaderOptions.h" +#include "ObjectJsonHandler.h" + +#include + +#include + +namespace CesiumJsonReader { +/** + * @brief \ref IJsonHandler for reading extensions, such as those listed in an + * \ref CesiumUtility::ExtensibleObject "ExtensibleObject". + */ +class ExtensionsJsonHandler : public CesiumJsonReader::ObjectJsonHandler { +public: + /** + * @brief Creates a new \ref ExtensionsJsonHandler with the specified reader + * options. + * + * @param context Options to configure how the JSON is read. + */ + explicit ExtensionsJsonHandler(const JsonReaderOptions& context) noexcept + : ObjectJsonHandler(), + _context(context), + _pObject(nullptr), + _currentExtensionHandler() {} + + /** + * @brief Resets the \ref IJsonHandler's parent and pointer to destination, as + * well as the name of the object type that the extension is attached to. + */ + void reset( + IJsonHandler* pParent, + CesiumUtility::ExtensibleObject* pObject, + const std::string& objectType); + + /** @copydoc IJsonHandler::readObjectKey */ + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + +private: + const JsonReaderOptions& _context; + CesiumUtility::ExtensibleObject* _pObject = nullptr; + std::string _objectType; + std::unique_ptr _currentExtensionHandler; +}; + +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IExtensionJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IExtensionJsonHandler.h new file mode 100644 index 0000000..f01e4ff --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IExtensionJsonHandler.h @@ -0,0 +1,40 @@ +#pragma once + +#include "IJsonHandler.h" + +#include + +#include +#include + +namespace CesiumJsonReader { + +/** + * @brief An interface for JSON handlers that handle extensions on \ref + * CesiumUtility::ExtensibleObject "ExtensibleObject" types. + * + * Usually, this will be a handler deriving from \ref ExtensionsJsonHandler that + * handles the specific extension found in the JSON. However, unknown extensions + * are read by a special \ref IExtensionJsonHandler returned by \ref + * JsonReaderOptions::createExtensionHandler, which reads the extension into the + * ExtensibleObject's `extensions` map as a \ref CesiumUtility::JsonValue + * "JsonValue". + */ +class IExtensionJsonHandler { +public: + virtual ~IExtensionJsonHandler() noexcept = default; + /** + * @brief Resets this \ref IExtensionJsonHandler's parent handler, destination + * object, and extension name. + */ + virtual void reset( + IJsonHandler* pParentHandler, + CesiumUtility::ExtensibleObject& o, + const std::string_view& extensionName) = 0; + /** + * @brief Obtains an \ref IJsonHandler from this \ref IExtensionJsonHandler. + */ + virtual IJsonHandler& getHandler() = 0; +}; + +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IJsonHandler.h new file mode 100644 index 0000000..bd03fe3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IJsonHandler.h @@ -0,0 +1,122 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include +#include + +namespace CesiumJsonReader { +/** + * @brief Base interface for all JSON handlers. Types that need to be + * deserialized from JSON should implement `IJsonHandler` or a class that + * derives from it. As the JSON is parsed, the corresponding `read...` method to + * the token that was parsed will be called. These methods can return themselves + * or a different handler to handle the value. + */ +class CESIUMJSONREADER_API IJsonHandler { +public: + virtual ~IJsonHandler(){}; + /** + * @brief Called when the JSON parser encounters a `null`. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readNull() = 0; + /** + * @brief Called when the JSON parser encounters a boolean value. + * @param b The boolean value. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readBool(bool b) = 0; + /** + * @brief Called when the JSON parser encounters an int32 value. + * @param i The int32 value. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readInt32(int32_t i) = 0; + /** + * @brief Called when the JSON parser encounters a uint32 value. + * @param i The uint32 value. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readUint32(uint32_t i) = 0; + /** + * @brief Called when the JSON parser encounters an int64 value. + * @param i The int64 value. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readInt64(int64_t i) = 0; + /** + * @brief Called when the JSON parser encounters a uint64 value. + * @param i The uint64 value. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readUint64(uint64_t i) = 0; + /** + * @brief Called when the JSON parser encounters a double value. + * @param d The double value. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readDouble(double d) = 0; + /** + * @brief Called when the JSON parser encounters a string value. + * @param str The string value. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readString(const std::string_view& str) = 0; + + /** + * @brief Called when the JSON parser encounters the beginning of an object. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readObjectStart() = 0; + /** + * @brief Called when the JSON parser encounters a key while reading an + * object. + * @param str The key. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readObjectKey(const std::string_view& str) = 0; + /** + * @brief Called when the JSON parser encounters the end of an object. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readObjectEnd() = 0; + + /** + * @brief Called when the JSON parser encounters the start of an array. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readArrayStart() = 0; + /** + * @brief Called when the JSON parser encounters the end of an array. + * @returns A \ref IJsonHandler that will handle the next `read...` call. + * This can be the same handler as the current one. + */ + virtual IJsonHandler* readArrayEnd() = 0; + + /** + * @brief Report a warning while reading JSON. + * + * @param warning The warning to report. + * @param context Context information to include with this warning to help + * debugging. + */ + virtual void reportWarning( + const std::string& warning, + std::vector&& context = std::vector()) = 0; +}; +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IgnoreValueJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IgnoreValueJsonHandler.h new file mode 100644 index 0000000..47f25d8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IgnoreValueJsonHandler.h @@ -0,0 +1,65 @@ +#pragma once + +#include "IJsonHandler.h" +#include "Library.h" + +#include + +namespace CesiumJsonReader { +/** + * @brief \ref IJsonHandler that does nothing but ignore the next value. + * + * Each `read...` call will return the current parent of this JsonHandler, + * unless the value being read is an object or array, in which case it will + * continue until the object or array is ended before returning. + */ +class CESIUMJSONREADER_API IgnoreValueJsonHandler : public IJsonHandler { +public: + /** + * @brief Resets the parent of this \ref IJsonHandler. + */ + void reset(IJsonHandler* pParent) noexcept; + + /** @copydoc IJsonHandler::readNull */ + virtual IJsonHandler* readNull() override; + /** @copydoc IJsonHandler::readBool */ + virtual IJsonHandler* readBool(bool b) override; + /** @copydoc IJsonHandler::readInt32 */ + virtual IJsonHandler* readInt32(int32_t i) override; + /** @copydoc IJsonHandler::readUint32 */ + virtual IJsonHandler* readUint32(uint32_t i) override; + /** @copydoc IJsonHandler::readInt64 */ + virtual IJsonHandler* readInt64(int64_t i) override; + /** @copydoc IJsonHandler::readUint64 */ + virtual IJsonHandler* readUint64(uint64_t i) override; + /** @copydoc IJsonHandler::readDouble */ + virtual IJsonHandler* readDouble(double d) override; + /** @copydoc IJsonHandler::readString */ + virtual IJsonHandler* readString(const std::string_view& str) override; + /** @copydoc IJsonHandler::readObjectStart */ + virtual IJsonHandler* readObjectStart() override; + /** @copydoc IJsonHandler::readObjectKey */ + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + /** @copydoc IJsonHandler::readObjectEnd */ + virtual IJsonHandler* readObjectEnd() override; + /** @copydoc IJsonHandler::readArrayStart */ + virtual IJsonHandler* readArrayStart() override; + /** @copydoc IJsonHandler::readArrayEnd */ + virtual IJsonHandler* readArrayEnd() override; + + /** @copydoc IJsonHandler::reportWarning */ + virtual void reportWarning( + const std::string& warning, + std::vector&& context = std::vector()) override; + + /** + * @brief Obtains the currently set parent of this handler, or `nullptr` if + * `reset` hasn't yet been called. + */ + IJsonHandler* parent() noexcept; + +private: + IJsonHandler* _pParent = nullptr; + int32_t _depth = 0; +}; +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IntegerJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IntegerJsonHandler.h new file mode 100644 index 0000000..27b146c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IntegerJsonHandler.h @@ -0,0 +1,79 @@ +#pragma once + +#include "CesiumUtility/Assert.h" +#include "JsonHandler.h" +#include "Library.h" + +#include + +namespace CesiumJsonReader { +/** + * @brief \ref IJsonHandler for reading integer values. + */ +template +class CESIUMJSONREADER_API IntegerJsonHandler : public JsonHandler { +public: + IntegerJsonHandler() noexcept : JsonHandler() {} + + /** + * @brief Resets the parent \ref IJsonHandler of this instance and sets the + * pointer to its destination integer value. + */ + void reset(IJsonHandler* pParent, T* pInteger) { + JsonHandler::reset(pParent); + this->_pInteger = pInteger; + } + + /** + * @brief Obtains the integer pointer set on this handler by \ref reset. + */ + T* getObject() { return this->_pInteger; } + + /** @copydoc IJsonHandler::readInt32 */ + virtual IJsonHandler* readInt32(int32_t i) override { + CESIUM_ASSERT(this->_pInteger); + *this->_pInteger = static_cast(i); + return this->parent(); + } + /** @copydoc IJsonHandler::readUint32 */ + virtual IJsonHandler* readUint32(uint32_t i) override { + CESIUM_ASSERT(this->_pInteger); + *this->_pInteger = static_cast(i); + return this->parent(); + } + /** @copydoc IJsonHandler::readInt64 */ + virtual IJsonHandler* readInt64(int64_t i) override { + CESIUM_ASSERT(this->_pInteger); + *this->_pInteger = static_cast(i); + return this->parent(); + } + /** @copydoc IJsonHandler::readUint64 */ + virtual IJsonHandler* readUint64(uint64_t i) override { + CESIUM_ASSERT(this->_pInteger); + *this->_pInteger = static_cast(i); + return this->parent(); + } + /** @copydoc IJsonHandler::readDouble */ + virtual IJsonHandler* readDouble(double d) override { + CESIUM_ASSERT(this->_pInteger); + double intPart; + double fractPart = std::modf(d, &intPart); + if (fractPart != 0) { + return JsonHandler::readDouble(d); + } + *this->_pInteger = static_cast(intPart); + return this->parent(); + } + + /** @copydoc IJsonHandler::reportWarning */ + virtual void reportWarning( + const std::string& warning, + std::vector&& context) override { + context.push_back("(expecting an integer)"); + this->parent()->reportWarning(warning, std::move(context)); + } + +private: + T* _pInteger = nullptr; +}; +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonHandler.h new file mode 100644 index 0000000..b8863f5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonHandler.h @@ -0,0 +1,81 @@ +#pragma once + +#include "IJsonHandler.h" +#include "IgnoreValueJsonHandler.h" +#include "Library.h" + +#include +#include + +namespace CesiumJsonReader { +/** + * @brief A dummy implementation of \ref IJsonHandler that will report a warning + * and return its parent when any of its `read...` methods are called. + * + * This class can be used as a base for any specialized JsonHandlers, overriding + * the methods required for the value you're handling and leaving the rest to + * report warnings if called. + */ +class CESIUMJSONREADER_API JsonHandler : public IJsonHandler { +public: + JsonHandler() noexcept; + /** @copydoc IJsonHandler::readNull */ + virtual IJsonHandler* readNull() override; + /** @copydoc IJsonHandler::readBool */ + virtual IJsonHandler* readBool(bool b) override; + /** @copydoc IJsonHandler::readInt32 */ + virtual IJsonHandler* readInt32(int32_t i) override; + /** @copydoc IJsonHandler::readUint32 */ + virtual IJsonHandler* readUint32(uint32_t i) override; + /** @copydoc IJsonHandler::readInt64 */ + virtual IJsonHandler* readInt64(int64_t i) override; + /** @copydoc IJsonHandler::readUint64 */ + virtual IJsonHandler* readUint64(uint64_t i) override; + /** @copydoc IJsonHandler::readDouble */ + virtual IJsonHandler* readDouble(double d) override; + /** @copydoc IJsonHandler::readString */ + virtual IJsonHandler* readString(const std::string_view& str) override; + /** @copydoc IJsonHandler::readObjectStart */ + virtual IJsonHandler* readObjectStart() override; + /** @copydoc IJsonHandler::readObjectKey */ + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + /** @copydoc IJsonHandler::readObjectEnd */ + virtual IJsonHandler* readObjectEnd() override; + /** @copydoc IJsonHandler::readArrayStart */ + virtual IJsonHandler* readArrayStart() override; + /** @copydoc IJsonHandler::readArrayEnd */ + virtual IJsonHandler* readArrayEnd() override; + + /** @copydoc IJsonHandler::reportWarning */ + virtual void reportWarning( + const std::string& warning, + std::vector&& context = std::vector()) override; + +protected: + /** + * @brief Resets the parent \ref IJsonHandler of this handler. + */ + void reset(IJsonHandler* pParent); + + /** + * @brief Obtains the parent \ref IJsonHandler of this handler. + */ + IJsonHandler* parent(); + + /** + * @brief Ignore a single value and then return to the parent handler. + */ + IJsonHandler* ignoreAndReturnToParent(); + + /** + * @brief Ignore a single value and the continue processing more tokens with + * this handler. + */ + IJsonHandler* ignoreAndContinue(); + +private: + IJsonHandler* _pParent = nullptr; + IgnoreValueJsonHandler _ignore; +}; + +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonObjectJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonObjectJsonHandler.h new file mode 100644 index 0000000..1856aab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonObjectJsonHandler.h @@ -0,0 +1,58 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +#include + +namespace CesiumJsonReader { + +/** + * @brief \ref IJsonHandler for arbitrary \ref CesiumUtility::JsonValue + * JsonValue objects. + */ +class CESIUMJSONREADER_API JsonObjectJsonHandler : public JsonHandler { +public: + JsonObjectJsonHandler() noexcept; + + /** + * @brief Resets this \ref IJsonHandler's parent handler, as well as its + * destination pointer. + */ + void reset(IJsonHandler* pParent, CesiumUtility::JsonValue* pValue); + + /** @copydoc IJsonHandler::readNull */ + virtual IJsonHandler* readNull() override; + /** @copydoc IJsonHandler::readBool */ + virtual IJsonHandler* readBool(bool b) override; + /** @copydoc IJsonHandler::readInt32 */ + virtual IJsonHandler* readInt32(int32_t i) override; + /** @copydoc IJsonHandler::readUint32 */ + virtual IJsonHandler* readUint32(uint32_t i) override; + /** @copydoc IJsonHandler::readInt64 */ + virtual IJsonHandler* readInt64(int64_t i) override; + /** @copydoc IJsonHandler::readUint64 */ + virtual IJsonHandler* readUint64(uint64_t i) override; + /** @copydoc IJsonHandler::readDouble */ + virtual IJsonHandler* readDouble(double d) override; + /** @copydoc IJsonHandler::readString */ + virtual IJsonHandler* readString(const std::string_view& str) override; + /** @copydoc IJsonHandler::readObjectStart */ + virtual IJsonHandler* readObjectStart() override; + /** @copydoc IJsonHandler::readObjectKey */ + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + /** @copydoc IJsonHandler::readObjectEnd */ + virtual IJsonHandler* readObjectEnd() override; + /** @copydoc IJsonHandler::readArrayStart */ + virtual IJsonHandler* readArrayStart() override; + /** @copydoc IJsonHandler::readArrayEnd */ + virtual IJsonHandler* readArrayEnd() override; + +private: + IJsonHandler* doneElement(); + + std::vector _stack; + std::string_view _currentKey; +}; + +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonReader.h new file mode 100644 index 0000000..c3569ed --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonReader.h @@ -0,0 +1,148 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +#include + +#include +#include +#include +#include +#include + +namespace rapidjson { +struct MemoryStream; +} + +namespace CesiumJsonReader { + +/** + * @brief The result of {@link JsonReader::readJson}. + */ +template struct ReadJsonResult { + /** + * @brief The value read from the JSON, or `std::nullopt` on error. + */ + std::optional value; + + /** + * @brief Errors that occurred while reading. + */ + std::vector errors; + + /** + * @brief Warnings that occurred while reading. + */ + std::vector warnings; +}; + +/** + * @brief Reads JSON. + */ +class CESIUMJSONREADER_API JsonReader { +public: + /** + * @brief Reads JSON from a byte buffer into a statically-typed class. + * + * @param data The buffer from which to read JSON. + * @param handler The handler to receive the top-level JSON object. This + * instance must: + * - Implement {@link IJsonHandler}. + * - Contain a `ValueType` type alias indicating the type of the instance to + * be read into. + * - Have a `reset` method taking 1) a parent `IJsonHandler` pointer, and 2) + * and a pointer to a value of type `ValueType`. + * @return The result of reading the JSON. + */ + template + static ReadJsonResult + readJson(const std::span& data, T& handler) { + ReadJsonResult result; + + result.value.emplace(); + + FinalJsonHandler finalHandler(result.warnings); + handler.reset(&finalHandler, &result.value.value()); + + JsonReader::internalRead( + data, + handler, + finalHandler, + result.errors, + result.warnings); + + if (!result.errors.empty()) { + result.value.reset(); + } + + return result; + } + + /** + * @brief Reads JSON from a `rapidjson::Value` into a statically-typed class. + * + * @param jsonValue The `rapidjson::Value` from which to read JSON. + * @param handler The handler to receive the top-level JSON object. This + * instance must: + * - Implement {@link IJsonHandler}. + * - Contain a `ValueType` type alias indicating the type of the instance to + * be read into. + * - Have a `reset` method taking 1) a parent `IJsonHandler` pointer, and 2) + * and a pointer to a value of type `ValueType`. + * @return The result of reading the JSON. + */ + template + static ReadJsonResult + readJson(const rapidjson::Value& jsonValue, T& handler) { + ReadJsonResult result; + + result.value.emplace(); + + FinalJsonHandler finalHandler(result.warnings); + handler.reset(&finalHandler, &result.value.value()); + + JsonReader::internalRead( + jsonValue, + handler, + finalHandler, + result.errors, + result.warnings); + + if (!result.errors.empty()) { + result.value.reset(); + } + + return result; + } + +private: + class FinalJsonHandler : public JsonHandler { + public: + FinalJsonHandler(std::vector& warnings); + virtual void reportWarning( + const std::string& warning, + std::vector&& context) override; + void setInputStream(rapidjson::MemoryStream* pInputStream) noexcept; + + private: + std::vector& _warnings; + rapidjson::MemoryStream* _pInputStream; + }; + + static void internalRead( + const std::span& data, + IJsonHandler& handler, + FinalJsonHandler& finalHandler, + std::vector& errors, + std::vector& warnings); + + static void internalRead( + const rapidjson::Value& jsonValue, + IJsonHandler& handler, + FinalJsonHandler& finalHandler, + std::vector& errors, + std::vector& warnings); +}; + +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonReaderOptions.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonReaderOptions.h new file mode 100644 index 0000000..bc6f2dc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonReaderOptions.h @@ -0,0 +1,165 @@ +#pragma once + +#include "IExtensionJsonHandler.h" +#include "Library.h" + +#include +#include +#include +#include +#include +#include + +namespace CesiumJsonReader { + +/** + * @brief The state of an extension. + */ +enum class ExtensionState { + /** + * @brief The extension is enabled. + * + * If a statically-typed class is available for the extension, it will be + * used. Otherwise the extension will be represented as a + * {@link CesiumUtility::JsonValue}. + */ + Enabled, + + /** + * @brief The extension is enabled but will always be deserialized as a + * {@link CesiumUtility::JsonValue}. + * + * Even if a statically-typed class is available for the extension, it will + * not be used. + */ + JsonOnly, + + /** + * @brief The extension is disabled. + * + * It will not be represented in the loaded model at all. + */ + Disabled +}; + +/** + * @brief Holds options for reading statically-typed data structures from JSON. + */ +class CESIUMJSONREADER_API JsonReaderOptions { +public: + /** + * @brief Gets a value indicating whether the values of unknown properties are + * captured in the {@link CesiumUtility::ExtensibleObject::unknownProperties} field. + * + * If this is false, unknown properties are completely ignored. + */ + bool getCaptureUnknownProperties() const { + return this->_captureUnknownProperties; + } + + /** + * @brief Sets a value indicating whether the values of unknown properties are + * captured in the {@link CesiumUtility::ExtensibleObject::unknownProperties} field. + * + * If this is false, unknown properties are completely ignored. + */ + void setCaptureUnknownProperties(bool value) { + this->_captureUnknownProperties = value; + } + + /** + * @brief Registers an extension for an object. + * + * @tparam TExtended The object to extend. + * @tparam TExtensionHandler The extension's + * {@link CesiumJsonReader::JsonHandler}. + * @param extensionName The name of the extension. + */ + template + void registerExtension(const std::string& extensionName) { + auto it = + this->_extensions.emplace(extensionName, ObjectTypeToHandler()).first; + it->second.insert_or_assign( + TExtended::TypeName, + ExtensionReaderFactory([](const JsonReaderOptions& context) { + return std::make_unique(context); + })); + } + + /** + * @brief Registers an extension for an object. + * + * The extension name is obtained from `TExtensionHandler::ExtensionName`. + * + * @tparam TExtended The object to extend. + * @tparam TExtensionHandler The extension's + * {@link CesiumJsonReader::JsonHandler}. + */ + template + void registerExtension() { + auto it = + this->_extensions + .emplace(TExtensionHandler::ExtensionName, ObjectTypeToHandler()) + .first; + it->second.insert_or_assign( + TExtended::TypeName, + ExtensionHandlerFactory([](const JsonReaderOptions& context) { + return std::make_unique(context); + })); + } + + /** + * @brief Returns whether an extension is enabled or disabled. + * + * By default, all extensions are enabled. + * + * @param extensionName The name of the extension. + */ + ExtensionState getExtensionState(const std::string& extensionName) const; + + /** + * @brief Enables or disables an extension. + * + * By default, all extensions are enabled. When an enabled extension is + * encountered in the source JSON, it is read into a statically-typed + * extension class, if one is registered, or into a + * {@link CesiumUtility::JsonValue} if not. + * + * When a disabled extension is encountered in the source JSON, it is ignored + * completely. + * + * An extension may also be set to `ExtensionState::JsonOnly`, in which case + * it will be read into a {@link CesiumUtility::JsonValue} even if a + * statically-typed extension class is registered. + * + * @param extensionName The name of the extension to be enabled or disabled. + * @param newState The new state for the extension. + */ + void + setExtensionState(const std::string& extensionName, ExtensionState newState); + + /** + * @brief Creates an extension handler for the given extension. + * + * @param extensionName The name of the extension to create a handler for. + * @param extendedObjectType The name of the type of the object that is being + * extended. + * @returns An \ref IExtensionJsonHandler to read the extension. + */ + std::unique_ptr createExtensionHandler( + const std::string_view& extensionName, + const std::string& extendedObjectType) const; + +private: + using ExtensionHandlerFactory = + std::function( + const JsonReaderOptions&)>; + using ObjectTypeToHandler = std::map; + using ExtensionNameMap = std::map; + + ExtensionNameMap _extensions; + std::unordered_map _extensionStates; + bool _captureUnknownProperties = true; +}; + +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/Library.h new file mode 100644 index 0000000..8f42531 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes for reading JSON. + * + * @mermaid-interactive{dependencies/CesiumJsonReader} + */ +namespace CesiumJsonReader {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMJSONREADER_BUILDING +#define CESIUMJSONREADER_API __declspec(dllexport) +#else +#define CESIUMJSONREADER_API __declspec(dllimport) +#endif +#else +#define CESIUMJSONREADER_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ObjectJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ObjectJsonHandler.h new file mode 100644 index 0000000..0bcc37d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ObjectJsonHandler.h @@ -0,0 +1,101 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +#include + +#include + +namespace CesiumJsonReader { +/** + * @brief \ref IJsonHandler for handling JSON objects. + */ +class CESIUMJSONREADER_API ObjectJsonHandler : public JsonHandler { +public: + ObjectJsonHandler() noexcept : JsonHandler() {} + + /** @copydoc IJsonHandler::readObjectStart */ + virtual IJsonHandler* readObjectStart() override /* final */; + /** @copydoc IJsonHandler::readObjectEnd */ + virtual IJsonHandler* readObjectEnd() override /* final */; + +protected: + /** + * @brief Called when \ref readObjectStart is called when the depth of the + * \ref ObjectJsonHandler is greater than 0. + */ + virtual IJsonHandler* StartSubObject() noexcept; + /** + * @brief Called when \ref readObjectEnd is called when the depth of the + * \ref ObjectJsonHandler is greater than 0. + */ + virtual IJsonHandler* EndSubObject() noexcept; + + /** + * @brief Called from \ref IJsonHandler::readObjectKey to read a property into + * an object. + * + * @param currentKey The key that's currently being read. + * @param accessor An \ref IJsonHandler that can read the type of this + * property. + * @param value A reference to the location to store the read value. + * @returns The `accessor` \ref IJsonHandler that will read the next token + * into `value`. + */ + template + IJsonHandler* + property(const char* currentKey, TAccessor& accessor, TProperty& value) { + this->_currentKey = currentKey; + + if constexpr (isOptional::value) { + value.emplace(); + accessor.reset(this, &value.value()); + } else if constexpr (isIntrusivePointer::value) { + value.emplace(); + accessor.reset(this, value.get()); + } else { + accessor.reset(this, &value); + } + + return &accessor; + } + + /** + * @brief Obtains the most recent key handled by this JsonHandler. + */ + const char* getCurrentKey() const noexcept; + + /** @copydoc IJsonHandler::reportWarning */ + virtual void reportWarning( + const std::string& warning, + std::vector&& context = std::vector()) override; + +protected: + /** + * @brief Sets the most recent key handled by this JsonHandler. + */ + void setCurrentKey(const char* key) noexcept; + +private: + template struct isOptional { + static constexpr bool value = false; + }; + + template struct isOptional> { + static constexpr bool value = true; + }; + + template struct isIntrusivePointer { + static constexpr bool value = false; + }; + + template + struct isIntrusivePointer> { + static constexpr bool value = true; + }; + + int32_t _depth = 0; + const char* _currentKey = nullptr; +}; +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/SharedAssetJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/SharedAssetJsonHandler.h new file mode 100644 index 0000000..36287aa --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/SharedAssetJsonHandler.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include + +#include + +namespace CesiumJsonReader { + +/** + * @brief \ref IJsonHandler for \ref CesiumUtility::SharedAsset "SharedAsset" + * values. + * + * This is more or less the same as directly using \ref + * ExtensibleObjectJsonHandler, and exists for compatibility with generated + * code. + */ +class SharedAssetJsonHandler + : public CesiumJsonReader::ExtensibleObjectJsonHandler { +public: + /** + * @brief Creates an \ref SharedAssetJsonHandler with the specified + * options. + * + * @param context Options to configure how the JSON is parsed. + */ + explicit SharedAssetJsonHandler( + const CesiumJsonReader::JsonReaderOptions& context) noexcept; + +protected: + /** @copydoc ExtensibleObjectJsonHandler::reset */ + void reset(IJsonHandler* pParent, CesiumUtility::ExtensibleObject* pObject); + /** @copydoc ExtensibleObjectJsonHandler::readObjectKeyExtensibleObject */ + IJsonHandler* readObjectKeySharedAsset( + const std::string& objectType, + const std::string_view& str, + CesiumUtility::ExtensibleObject& o); + +private: +}; +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/StringJsonHandler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/StringJsonHandler.h new file mode 100644 index 0000000..5353f8b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/StringJsonHandler.h @@ -0,0 +1,31 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +#include + +namespace CesiumJsonReader { +/** + * @brief \ref IJsonHandler for reading string values. + */ +class CESIUMJSONREADER_API StringJsonHandler : public JsonHandler { +public: + StringJsonHandler() noexcept; + /** + * @brief Resets the parent \ref IJsonHandler of this handler, and the pointer + * to its destination string value. + */ + void reset(IJsonHandler* pParent, std::string* pString); + /** + * @brief Obtains the pointer to the current destination string value of this + * handler. + */ + std::string* getObject() noexcept; + /** @copydoc IJsonHandler::readString */ + virtual IJsonHandler* readString(const std::string_view& str) override; + +private: + std::string* _pString = nullptr; +}; +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/ExtensionWriterContext.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/ExtensionWriterContext.h new file mode 100644 index 0000000..4317956 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/ExtensionWriterContext.h @@ -0,0 +1,133 @@ +#pragma once + +#include "CesiumJsonWriter/JsonWriter.h" +#include "CesiumJsonWriter/Library.h" + +#include +#include +#include +#include +#include + +namespace CesiumJsonWriter { + +/** + * @brief The state of an extension. + */ +enum class ExtensionState { + /** + * @brief The extension is enabled. + * + * If the extension is a {@link CesiumUtility::JsonValue} or a registered + * statically-typed class it will be written to the serialized model; + * otherwise it will be ignored and a warning will be reported. + */ + Enabled, + + /** + * @brief The extension is disabled. + * + * It will not be represented in the serialized model at all. + */ + Disabled +}; + +/** + * @brief A context for writing extensions where known extensions and their + * handlers can be registered. + */ +class CESIUMJSONWRITER_API ExtensionWriterContext { +private: + template + using ExtensionHandler = std::function< + void(const TExtension&, JsonWriter&, const ExtensionWriterContext&)>; + +public: + /** + * @brief Registers an extension for an object. + * + * @tparam TExtended The object to extend. + * @tparam TExtensionHandler The extension's writer. + * @param extensionName The name of the extension. + */ + template + void registerExtension(const std::string& extensionName) { + using TExtension = typename TExtensionHandler::ValueType; + + auto it = + this->_extensions.emplace(extensionName, ObjectTypeToHandler()).first; + it->second.insert_or_assign( + TExtended::TypeName, + [](const std::any& obj, + JsonWriter& jsonWriter, + const ExtensionWriterContext& context) { + return TExtensionHandler::write( + std::any_cast(obj), + jsonWriter, + context); + }); + } + + /** + * @brief Registers an extension for an object. + * + * The extension name is obtained from `TExtensionHandler::ExtensionName`. + * + * @tparam TExtended The object to extend. + * @tparam TExtensionHandler The extension's writer. + */ + template + void registerExtension() { + registerExtension( + TExtensionHandler::ExtensionName); + } + + /** + * @brief Returns whether an extension is enabled or disabled. + * + * By default, all extensions are enabled. + * + * @param extensionName The name of the extension. + */ + ExtensionState getExtensionState(const std::string& extensionName) const; + + /** + * @brief Enables or disables an extension. + * + * By default, all extensions are enabled. However, if the extension is a + * statically-typed class and is not registered it will be ignored and a + * warning will be reported. + * + * When a disabled extension is encountered, it is ignored completely. + * + * @param extensionName The name of the extension to be enabled or disabled. + * @param newState The new state for the extension. + */ + void + setExtensionState(const std::string& extensionName, ExtensionState newState); + + /** + * @brief Attempts to create an `ExtensionHandler` for the given object, + * returning `nullptr` if no handler could be found. + * + * @param extensionName The name of the extension. + * @param obj The object of unknown type to create the handler for. + * @param extendedObjectType The `TypeName` of the extended object. + * @returns The handler for this extension, or `nullptr` if none could be + * created. + */ + ExtensionHandler createExtensionHandler( + const std::string_view& extensionName, + const std::any& obj, + const std::string& extendedObjectType) const; + +private: + using ObjectTypeToHandler = + std::unordered_map>; + using ExtensionNameMap = std::map; + + ExtensionNameMap _extensions; + std::unordered_map _extensionStates; +}; + +} // namespace CesiumJsonWriter diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/JsonObjectWriter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/JsonObjectWriter.h new file mode 100644 index 0000000..b023eef --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/JsonObjectWriter.h @@ -0,0 +1,21 @@ +#pragma once + +// forward declarations +namespace CesiumJsonWriter { +class JsonWriter; +} + +// forward declarations +namespace CesiumUtility { +class JsonValue; +} + +namespace CesiumJsonWriter { +/** + * @brief Writes the given \ref CesiumUtility::JsonValue to the provided writer. + * + * @param value The value to write. + * @param writer The writer used to write the provided value. + */ +void writeJsonValue(const CesiumUtility::JsonValue& value, JsonWriter& writer); +} // namespace CesiumJsonWriter diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/JsonWriter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/JsonWriter.h new file mode 100644 index 0000000..b9b1b07 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/JsonWriter.h @@ -0,0 +1,295 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace CesiumJsonWriter { +/** + * @brief Wrapper around `rapidjson::Writer` for writing objects to JSON. + */ +class JsonWriter { +public: + JsonWriter(); + virtual ~JsonWriter() {} + + /** + * @brief Writes a `null` value to the output. + * @returns True if the write was successful. + */ + virtual bool Null(); + /** + * @brief Writes a boolean value to the output. + * @param b The boolean value to write. + * @returns True if the write was successful. + */ + virtual bool Bool(bool b); + /** + * @brief Writes a signed integer value to the output. + * @param i The integer value to write. + * @returns True if the write was successful. + */ + virtual bool Int(int i); + /** + * @brief Writes an unsigned integer value to the output. + * @param i The integer value to write. + * @returns True if the write was successful. + */ + virtual bool Uint(unsigned int i); + /** + * @brief Writes an unsigned 64-bit integer value to the output. + * @param i The integer value to write. + * @returns True if the write was successful. + */ + virtual bool Uint64(std::uint64_t i); + /** + * @brief Writes an signed 64-bit integer value to the output. + * @param i The integer value to write. + * @returns True if the write was successful. + */ + virtual bool Int64(std::int64_t i); + /** + * @brief Writes a 64-bit floating point value to the output. + * @param d The double value to write. + * @returns True if the write was successful. + */ + virtual bool Double(double d); + /** + * @brief Writes the given string as a number to the output without any kind + * of special handling. + * + * @param str The raw number to write directly to the output. + * @param length The length of the string. + * @param copy If true, the string will be copied. + * @returns True if the write was successful. + */ + virtual bool RawNumber(const char* str, unsigned int length, bool copy); + /** + * @brief Writes the given string as an object key to the output. + * + * @param string The key to write. + * @returns True if the write was successful. + */ + virtual bool Key(std::string_view string); + /** + * @brief Writes the given string as a value to the output. + * + * @param string The string to write. + * @returns True if the write was successful. + */ + virtual bool String(std::string_view string); + /** + * @brief Writes the start of a JSON object to the output. + * + * @returns True if the write was successful. + */ + virtual bool StartObject(); + /** + * @brief Writes the end of a JSON object to the output. + * + * @returns True if the write was successful. + */ + virtual bool EndObject(); + /** + * @brief Writes the start of a JSON array to the output. + * + * @returns True if the write was successful. + */ + virtual bool StartArray(); + /** + * @brief Writes the end of a JSON array to the output. + * + * @returns True if the write was successful. + */ + virtual bool EndArray(); + + /** + * @brief Writes the given primitive to the output. This is a convenience + * function for \ref Int. + * @param value The int32_t value to write. + */ + virtual void Primitive(std::int32_t value); + /** + * @brief Writes the given primitive to the output. This is a convenience + * function for \ref Uint. + * @param value The uint32_t value to write. + */ + virtual void Primitive(std::uint32_t value); + /** + * @brief Writes the given primitive to the output. This is a convenience + * function for \ref Int64. + * @param value The int64_t value to write. + */ + virtual void Primitive(std::int64_t value); + /** + * @brief Writes the given primitive to the output. This is a convenience + * function for \ref Uint64. + * @param value The uint64_t value to write. + */ + virtual void Primitive(std::uint64_t value); + /** + * @brief Writes the given primitive to the output. This is a convenience + * function for \ref Double. + * @param value The float value to write. + */ + virtual void Primitive(float value); + /** + * @brief Writes the given primitive to the output. This is a convenience + * function for \ref Double. + * @param value The double value to write. + */ + virtual void Primitive(double value); + /** + * @brief Writes the given primitive to the output. This is a convenience + * function for \ref Null. + * @param value The null value to write. + */ + virtual void Primitive(std::nullptr_t value); + /** + * @brief Writes the given primitive to the output. This is a convenience + * function for \ref String. + * @param string The string value to write. + */ + virtual void Primitive(std::string_view string); + + /** + * @brief Writes the given key and its corresponding value primitive to the + * output. This is a convenience function for calling \ref Key followed by + * \ref Int. + * @param keyName The key to write to the output. + * @param value The primitive value to write. + */ + virtual void KeyPrimitive(std::string_view keyName, std::int32_t value); + /** + * @brief Writes the given key and its corresponding value primitive to the + * output. This is a convenience function for calling \ref Key followed by + * \ref Uint. + * @param keyName The key to write to the output. + * @param value The primitive value to write. + */ + virtual void KeyPrimitive(std::string_view keyName, std::uint32_t value); + /** + * @brief Writes the given key and its corresponding value primitive to the + * output. This is a convenience function for calling \ref Key followed by + * \ref Int64. + * @param keyName The key to write to the output. + * @param value The primitive value to write. + */ + virtual void KeyPrimitive(std::string_view keyName, std::int64_t value); + /** + * @brief Writes the given key and its corresponding value primitive to the + * output. This is a convenience function for calling \ref Key followed by + * \ref Uint64. + * @param keyName The key to write to the output. + * @param value The primitive value to write. + */ + virtual void KeyPrimitive(std::string_view keyName, std::uint64_t value); + /** + * @brief Writes the given key and its corresponding value primitive to the + * output. This is a convenience function for calling \ref Key followed by + * \ref String. + * @param keyName The key to write to the output. + * @param value The primitive value to write. + */ + virtual void KeyPrimitive(std::string_view keyName, std::string_view value); + /** + * @brief Writes the given key and its corresponding value primitive to the + * output. This is a convenience function for calling \ref Key followed by + * \ref Double. + * @param keyName The key to write to the output. + * @param value The primitive value to write. + */ + virtual void KeyPrimitive(std::string_view keyName, float value); + /** + * @brief Writes the given key and its corresponding value primitive to the + * output. This is a convenience function for calling \ref Key followed by + * \ref Double. + * @param keyName The key to write to the output. + * @param value The primitive value to write. + */ + virtual void KeyPrimitive(std::string_view keyName, double value); + /** + * @brief Writes the given key and its corresponding value primitive to the + * output. This is a convenience function for calling \ref Key followed by + * \ref Null. + * @param keyName The key to write to the output. + * @param value The primitive value to write. + */ + virtual void KeyPrimitive(std::string_view keyName, std::nullptr_t value); + + /** + * @brief Writes an array to the output with the given key and calls the + * provided callback to write values inside of the array. This is a + * convenience function for calling \ref Key followed by \ref StartArray + * followed by the values you wish to write and ending with \ref EndArray. + * + * @param keyName The key to write to the output. + * @param insideArray The callback to run, after \ref StartArray but before + * \ref EndArray. + */ + virtual void + KeyArray(std::string_view keyName, std::function insideArray); + /** + * @brief Writes an object to the output with the given key and calls the + * provided callback to write values inside of the object. This is a + * convenience function for calling \ref Key followed by \ref StartObject + * followed by the values you wish to write and ending with \ref EndObject. + * + * @param keyName The key to write to the output. + * @param insideObject The callback to run, after \ref StartObject but before + * \ref EndObject. + */ + virtual void + KeyObject(std::string_view keyName, std::function insideObject); + + /** + * @brief Obtains the written output as a string. + */ + virtual std::string toString(); + /** + * @brief Obtains the written output as a string_view. + */ + virtual std::string_view toStringView(); + /** + * @brief Obtains the written output as a buffer of bytes. + */ + virtual std::vector toBytes(); + + /** + * @brief Emplaces a new error into the internal error buffer. + */ + template void emplaceError(ErrorStr&& error) { + _errors.emplace_back(std::forward(error)); + } + + /** + * @brief Emplaces a new warning into the internal warning buffer. + */ + template void emplaceWarning(WarningStr&& warning) { + _warnings.emplace_back(std::forward(warning)); + } + + /** + * @brief Obtains the current error buffer. + */ + const std::vector& getErrors() const { return _errors; } + /** + * @brief Obtains the current warning buffer. + */ + const std::vector& getWarnings() const { return _warnings; } + +private: + rapidjson::StringBuffer _compactBuffer; + std::unique_ptr> _compact; + + std::vector _errors; + std::vector _warnings; +}; +} // namespace CesiumJsonWriter diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/Library.h new file mode 100644 index 0000000..c7dbc66 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Classes for writing JSON. + * + * @mermaid-interactive{dependencies/CesiumJsonWriter} + */ +namespace CesiumJsonWriter {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMJSONWRITER_BUILDING +#define CESIUMJSONWRITER_API __declspec(dllexport) +#else +#define CESIUMJSONWRITER_API __declspec(dllimport) +#endif +#else +#define CESIUMJSONWRITER_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/PrettyJsonWriter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/PrettyJsonWriter.h new file mode 100644 index 0000000..0361ebf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/PrettyJsonWriter.h @@ -0,0 +1,71 @@ +#pragma once + +#include "JsonWriter.h" + +#include +#include + +#include +#include +#include +#include +#include + +namespace CesiumJsonWriter { + +/** + * @brief Implementation of \ref JsonWriter that "pretty-prints" JSON to the + * output, formatted with new lines and indentation. + */ +class PrettyJsonWriter : public JsonWriter { + rapidjson::StringBuffer _prettyBuffer; + std::unique_ptr> pretty; + +public: + PrettyJsonWriter() noexcept; + ~PrettyJsonWriter() {} + + bool Null() override; + bool Bool(bool b) override; + bool Int(int i) override; + bool Uint(unsigned int i) override; + bool Uint64(std::uint64_t i) override; + bool Int64(std::int64_t i) override; + bool Double(double d) override; + bool RawNumber(const char* str, unsigned int length, bool copy) override; + bool Key(std::string_view string) override; + bool String(std::string_view string) override; + bool StartObject() override; + bool EndObject() override; + bool StartArray() override; + bool EndArray() override; + + void Primitive(std::int32_t value) override; + void Primitive(std::uint32_t value) override; + void Primitive(std::int64_t value) override; + void Primitive(std::uint64_t value) override; + void Primitive(float value) override; + void Primitive(double value) override; + void Primitive(std::nullptr_t value) override; + void Primitive(std::string_view string) override; + + void KeyPrimitive(std::string_view keyName, std::int32_t value) override; + void KeyPrimitive(std::string_view keyName, std::uint32_t value) override; + void KeyPrimitive(std::string_view keyName, std::int64_t value) override; + void KeyPrimitive(std::string_view keyName, std::uint64_t value) override; + void KeyPrimitive(std::string_view keyName, std::string_view value) override; + void KeyPrimitive(std::string_view keyName, float value) override; + void KeyPrimitive(std::string_view keyName, double value) override; + void KeyPrimitive(std::string_view keyName, std::nullptr_t value) override; + + void KeyArray(std::string_view keyName, std::function insideArray) + override; + void KeyObject( + std::string_view keyName, + std::function insideObject) override; + + std::string toString() override; + std::string_view toStringView() override; + std::vector toBytes() override; +}; +} // namespace CesiumJsonWriter diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/writeJsonExtensions.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/writeJsonExtensions.h new file mode 100644 index 0000000..25d3326 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/writeJsonExtensions.h @@ -0,0 +1,85 @@ +#pragma once + +#include "CesiumJsonWriter/ExtensionWriterContext.h" +#include "CesiumJsonWriter/JsonWriter.h" + +#include + +namespace CesiumJsonWriter { + +/** + * @brief Writes the extensions attached to the provided object as a new JSON + * object. + * + * @tparam TExtended The type with extensions attached to write. This type must + * have an `extensions` property of type `std::unordered_map` or a similar type with an `empty()` method that returns pairs of + * `` when iterated. + * @param obj The object with extensions to write. + * @param jsonWriter The writer to write the extensions object to. + * @param context The \ref ExtensionWriterContext that provides information on + * how to write each extension. + */ +template +void writeJsonExtensions( + const TExtended& obj, + JsonWriter& jsonWriter, + const ExtensionWriterContext& context) { + if (obj.extensions.empty()) { + return; + } + jsonWriter.StartObject(); + for (const auto& item : obj.extensions) { + auto handler = context.createExtensionHandler( + item.first, + item.second, + TExtended::TypeName); + if (handler) { + jsonWriter.Key(item.first); + handler(item.second, jsonWriter, context); + } + } + jsonWriter.EndObject(); +} + +/** + * @brief Checks if the provided object has any extensions attached that have + * been registered with the provided \ref ExtensionWriterContext. + * + * @tparam TExtended The type with extensions attached to write. This type must + * have an `extensions` property of type `std::unordered_map` or a similar type with an `empty()` method that returns pairs of + * `` when iterated. + * @param obj The object with extensions to write. + * @param jsonWriter The writer to write the extensions object to. + * @param context The \ref ExtensionWriterContext with registered extensions. + * @returns True if any extensions attached to `obj` have been registered, false + * otherwise. + */ +template +bool hasRegisteredExtensions( + const TExtended& obj, + JsonWriter& jsonWriter, + const ExtensionWriterContext& context) { + bool hasRegisteredExtensions = false; + + for (const auto& item : obj.extensions) { + auto handler = context.createExtensionHandler( + item.first, + item.second, + TExtended::TypeName); + if (handler) { + hasRegisteredExtensions = true; + } else if ( + context.getExtensionState(item.first) != ExtensionState::Disabled) { + jsonWriter.emplaceWarning(fmt::format( + "Encountered unregistered extension {}. This extension will be " + "ignored. To silence this warning, disable the extension with " + "ExtensionWriterContext::setExtensionState.", + item.first)); + } + } + + return hasRegisteredExtensions; +} +} // namespace CesiumJsonWriter diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/AvailabilityRectangle.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/AvailabilityRectangle.h new file mode 100644 index 0000000..c65d11e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/AvailabilityRectangle.h @@ -0,0 +1,56 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include + +#include + +namespace CesiumQuantizedMeshTerrain { +/** + * @brief A rectangle of tile availability. + */ +struct CESIUMQUANTIZEDMESHTERRAIN_API AvailabilityRectangle final + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "AvailabilityRectangle"; + + /** + * @brief The index of the start tile in the X direction. + */ + int64_t startX = int64_t(); + + /** + * @brief The index of the start tile in the Y direction. + */ + int64_t startY = int64_t(); + + /** + * @brief The index of the end tile in the X direction. + */ + int64_t endX = int64_t(); + + /** + * @brief The index of the end tile in the Y direction. + */ + int64_t endY = int64_t(); + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(AvailabilityRectangle)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + + return accum; + } +}; +} // namespace CesiumQuantizedMeshTerrain diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/AvailabilityRectangleReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/AvailabilityRectangleReader.h new file mode 100644 index 0000000..ebeb76f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/AvailabilityRectangleReader.h @@ -0,0 +1,77 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumQuantizedMeshTerrain { +struct AvailabilityRectangle; +} // namespace CesiumQuantizedMeshTerrain + +namespace CesiumQuantizedMeshTerrain { + +/** + * @brief Reads \ref CesiumQuantizedMeshTerrain::AvailabilityRectangle + * "AvailabilityRectangle" instances from JSON. + */ +class CESIUMQUANTIZEDMESHTERRAIN_API AvailabilityRectangleReader { +public: + /** + * @brief Constructs a new instance. + */ + AvailabilityRectangleReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of AvailabilityRectangle from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumQuantizedMeshTerrain::AvailabilityRectangle> + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of AvailabilityRectangle from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult< + CesiumQuantizedMeshTerrain::AvailabilityRectangle> + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of AvailabilityRectangle from a + * rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumQuantizedMeshTerrain diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/Layer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/Layer.h new file mode 100644 index 0000000..f588b3e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/Layer.h @@ -0,0 +1,53 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include +#include + +#include + +namespace CesiumQuantizedMeshTerrain { + +/** + * @brief A quantized-mesh terrain layer.json. + */ +struct Layer : public LayerSpec { + /** + * @brief Gets the projection specified by this layer.json. + * + * @return The projection, or std::nullopt if this layer.json does not specify + * a valid projection. + */ + std::optional + getProjection(const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) const noexcept; + + /** + * @brief Gets the tiling scheme specified by this layer.json. + * + * @return The tiling scheme, or std::nullopt if this layer.json does not + * specify a tiling scheme. + */ + std::optional + getTilingScheme(const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) const noexcept; + + /** + * @brief Gets the bounding region for the root tile. + * + * The rectangle will be the maximum rectangle for the terrain's projection + * (geographic or web mercator). The heights will range from -1000.0 to + * 9000.0. + * + * @return The bounding rectangle, or std::nullopt if the bounding region + * cannot be determined from this layer.json. + */ + std::optional + getRootBoundingRegion(const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) const noexcept; +}; + +} // namespace CesiumQuantizedMeshTerrain diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/LayerReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/LayerReader.h new file mode 100644 index 0000000..97f7fe4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/LayerReader.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CesiumQuantizedMeshTerrain { +struct Layer; +} // namespace CesiumQuantizedMeshTerrain + +namespace CesiumQuantizedMeshTerrain { + +/** + * @brief Reads \ref CesiumQuantizedMeshTerrain::Layer "Layer" instances from + * JSON. + */ +class CESIUMQUANTIZEDMESHTERRAIN_API LayerReader { +public: + /** + * @brief Constructs a new instance. + */ + LayerReader(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + CesiumJsonReader::JsonReaderOptions& getOptions(); + + /** + * @brief Gets the options controlling how the JSON is read. + */ + const CesiumJsonReader::JsonReaderOptions& getOptions() const; + + /** + * @brief Reads an instance of Layer from a byte buffer. + * + * @param data The buffer from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const std::span& data) const; + + /** + * @brief Reads an instance of Layer from a rapidJson::Value. + * + * @param value The value from which to read the instance. + * @return The result of reading the instance. + */ + CesiumJsonReader::ReadJsonResult + readFromJson(const rapidjson::Value& value) const; + + /** + * @brief Reads an array of instances of Layer from a rapidJson::Value. + * + * @param value The value from which to read the array of instances. + * @return The result of reading the array of instances. + */ + CesiumJsonReader::ReadJsonResult< + std::vector> + readArrayFromJson(const rapidjson::Value& value) const; + +private: + CesiumJsonReader::JsonReaderOptions _options; +}; + +} // namespace CesiumQuantizedMeshTerrain diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/LayerSpec.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/LayerSpec.h new file mode 100644 index 0000000..9c39ec2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/LayerSpec.h @@ -0,0 +1,156 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +namespace CesiumQuantizedMeshTerrain { +/** + * @brief A quantized-mesh terrain layer.json. + */ +struct CESIUMQUANTIZEDMESHTERRAIN_API LayerSpec + : public CesiumUtility::ExtensibleObject { + /** + * @brief The original name of this type. + */ + static constexpr const char* TypeName = "Layer"; + + /** + * @brief The attribution (credit) string for the terrain. + */ + std::string attribution; + + /** + * @brief The tile availability information. The outer array is indexed by + * tile level. The inner array is a list of rectangles of availability at that + * level. Tiles themselves may also contain further availability information + * for their subtree. + */ + std::vector> + available; + + /** + * @brief The bounding box of the terrain, expressed as west, south, east, + * north in degrees. + */ + std::vector bounds = {-180, -90, 180, 90}; + + /** + * @brief The description of this terrain tileset. + */ + std::string description; + + /** + * @brief The extensions available for this tileset. + */ + std::vector extensionsProperty; + + /** + * @brief The format of the terrain tiles. Should be `"quantized-mesh-1.0"`. + */ + std::string format = "quantized-mesh-1.0"; + + /** + * @brief The maximum level for which there are any available tiles. + */ + int64_t maxzoom = int64_t(); + + /** + * @brief The minimum level for which there are any available tiles. + */ + int64_t minzoom = 0; + + /** + * @brief The levels at metadata is found in tiles. For example, if this value + * is 10, then metadata is found at levels 0, 10, 20, etc. + */ + std::optional metadataAvailability; + + /** + * @brief The name of this terrain tileset. + */ + std::string name = "Terrain"; + + /** + * @brief The URL of the parent layer.json that this one is layered on top of. + */ + std::optional parentUrl; + + /** + * @brief The map projection of this tileset. Valid values are `"EPSG:4326"` + * and `"EPSG:3857"`. + */ + std::string projection = "EPSG:4326"; + + /** + * @brief The tiling scheme. The only valid value is `"tms"`. + */ + std::string scheme = "tms"; + + /** + * @brief The URL templates from which to obtain tiles. + */ + std::vector tiles; + + /** + * @brief The version of this tileset. + */ + std::string version = "1.0.0"; + + /** + * @brief Calculates the size in bytes of this object, including the contents + * of all collections, pointers, and strings. This will NOT include the size + * of any extensions attached to the object. Calling this method may be slow + * as it requires traversing the object's entire structure. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(LayerSpec)); + accum += CesiumUtility::ExtensibleObject::getSizeBytes() - + int64_t(sizeof(CesiumUtility::ExtensibleObject)); + accum += int64_t(this->attribution.capacity() * sizeof(char)); + accum += int64_t( + sizeof(std::vector) * + this->available.capacity()); + for (const std::vector& + valueOuter : this->available) { + accum += int64_t( + sizeof(CesiumQuantizedMeshTerrain::AvailabilityRectangle) * + valueOuter.capacity()); + for (const CesiumQuantizedMeshTerrain::AvailabilityRectangle& value : + valueOuter) { + accum += + value.getSizeBytes() - + int64_t(sizeof(CesiumQuantizedMeshTerrain::AvailabilityRectangle)); + } + } + accum += int64_t(sizeof(double) * this->bounds.capacity()); + accum += int64_t(this->description.capacity() * sizeof(char)); + accum += int64_t(sizeof(std::string) * this->extensionsProperty.capacity()); + accum += int64_t(this->format.capacity() * sizeof(char)); + accum += int64_t(this->name.capacity() * sizeof(char)); + if (this->parentUrl) { + accum += int64_t(this->parentUrl->capacity() * sizeof(char)); + } + accum += int64_t(this->projection.capacity() * sizeof(char)); + accum += int64_t(this->scheme.capacity() * sizeof(char)); + accum += int64_t(sizeof(std::string) * this->tiles.capacity()); + accum += int64_t(this->version.capacity() * sizeof(char)); + return accum; + } + +protected: + /** + * @brief This class is not meant to be instantiated directly. Use {@link Layer} instead. + */ + LayerSpec() = default; + friend struct Layer; +}; +} // namespace CesiumQuantizedMeshTerrain diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/LayerWriter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/LayerWriter.h new file mode 100644 index 0000000..d759417 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/LayerWriter.h @@ -0,0 +1,83 @@ +#pragma once + +#include "CesiumQuantizedMeshTerrain/Library.h" + +#include + +#include + +// forward declarations +namespace CesiumQuantizedMeshTerrain { +struct Layer; +} + +namespace CesiumQuantizedMeshTerrain { + +/** + * @brief The result of writing a layer.json with {@link LayerWriter::write}. + */ +struct CESIUMQUANTIZEDMESHTERRAIN_API LayerWriterResult { + /** + * @brief The final generated std::vector of the layer.json. + */ + std::vector bytes; + + /** + * @brief Errors, if any, that occurred during the write process. + */ + std::vector errors; + + /** + * @brief Warnings, if any, that occurred during the write process. + */ + std::vector warnings; +}; + +/** + * @brief Options for how to write a layer.json. + */ +struct CESIUMQUANTIZEDMESHTERRAIN_API LayerWriterOptions { + /** + * @brief If the layer.json should be pretty printed. + */ + bool prettyPrint = false; +}; + +/** + * @brief Writes layer.json. + */ +class CESIUMQUANTIZEDMESHTERRAIN_API LayerWriter { +public: + /** + * @brief Constructs a new instance. + */ + LayerWriter(); + + /** + * @brief Gets the context used to control how layer.json extensions are + * written. + */ + CesiumJsonWriter::ExtensionWriterContext& getExtensions(); + + /** + * @brief Gets the context used to control how layer.json extensions are + * written. + */ + const CesiumJsonWriter::ExtensionWriterContext& getExtensions() const; + + /** + * @brief Serializes the provided `Layer` into a layer.json byte vector. + * + * @param layer The layer. + * @param options Options for how to write the layer.json. + * @return The result of writing the layer.json. + */ + LayerWriterResult write( + const CesiumQuantizedMeshTerrain::Layer& layer, + const LayerWriterOptions& options = LayerWriterOptions()) const; + +private: + CesiumJsonWriter::ExtensionWriterContext _context; +}; + +} // namespace CesiumQuantizedMeshTerrain diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/Library.h new file mode 100644 index 0000000..0c6ccf9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/Library.h @@ -0,0 +1,19 @@ +#pragma once + +/** + * @brief Classes for accessing terrain based on layer.json and + * quantized-mesh-1.0. + * + * @mermaid-interactive{dependencies/CesiumQuantizedMeshTerrain} + */ +namespace CesiumQuantizedMeshTerrain {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMQUANTIZEDMESHTERRAIN_BUILDING +#define CESIUMQUANTIZEDMESHTERRAIN_API __declspec(dllexport) +#else +#define CESIUMQUANTIZEDMESHTERRAIN_API __declspec(dllimport) +#endif +#else +#define CESIUMQUANTIZEDMESHTERRAIN_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/QuantizedMeshLoader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/QuantizedMeshLoader.h new file mode 100644 index 0000000..823234c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumQuantizedMeshTerrain/QuantizedMeshLoader.h @@ -0,0 +1,140 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace CesiumAsync { +class IAssetRequest; +} + +namespace CesiumQuantizedMeshTerrain { + +/** + * @brief The results of a \ref QuantizedMeshLoader::load operation, containing + * either the loaded model, an improved bounding region for the tile, and + * available quadtree tiles discovered, if the load succeeded - or the request + * made and the errors that were returned, if the load failed. + */ +struct QuantizedMeshLoadResult { + /** + * @brief The glTF model to be rendered for this tile. + * + * If this is `std::nullopt`, the tile cannot be rendered. + * If it has a value but the model is blank, the tile can + * be "rendered", but it is rendered as nothing. + */ + std::optional model; + + /** + * @brief An improved bounding region for this tile. + * + * If this is available, then it is more accurate than the one the tile used + * originally. + */ + std::optional updatedBoundingVolume{}; + + /** + * @brief Available quadtree tiles discovered as a result of loading this + * tile. + */ + std::vector + availableTileRectangles{}; + + /** + * @brief The request that was used to download the tile content, if any. + * + * This field is only populated when there are request-related errors. + */ + std::shared_ptr pRequest; + + /** + * @brief The errors and warnings reported while loading this tile. + */ + CesiumUtility::ErrorList errors; +}; + +/** + * @brief The metadata of a Quantized Mesh tile, returned by \ref + * QuantizedMeshLoader::loadMetadata. + */ +struct QuantizedMeshMetadataResult { + /** + * @brief Information about the availability of child tiles. + */ + std::vector availability; + + /** + * @brief The errors and warnings reported while loading this tile, if any. + */ + CesiumUtility::ErrorList errors; +}; + +/** + * @brief Loads `quantized-mesh-1.0` terrain data. + */ +class CESIUMQUANTIZEDMESHTERRAIN_API QuantizedMeshLoader final { +public: + /** + * @brief Create a {@link QuantizedMeshLoadResult} from the given data. + * + * @param tileID The tile ID. + * @param tileBoundingVolume The tile bounding volume. + * @param url The URL from which the data was loaded. + * @param data The actual tile data. + * @param enableWaterMask If true, will attempt to load a water mask from the + * quantized mesh data. + * @param ellipsoid The ellipsoid to use for this quantized mesh. + * @return The {@link QuantizedMeshLoadResult} + */ + static QuantizedMeshLoadResult load( + const CesiumGeometry::QuadtreeTileID& tileID, + const CesiumGeospatial::BoundingRegion& tileBoundingVolume, + const std::string& url, + const std::span& data, + bool enableWaterMask, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief Parses the metadata (tile availability) from the given + * quantized-mesh terrain tile data. + * + * @param data The actual tile data. + * @param tileID The tile ID. + * @return The parsed metadata. + */ + static QuantizedMeshMetadataResult loadMetadata( + const std::span& data, + const CesiumGeometry::QuadtreeTileID& tileID); + + /** + * @brief Extracts tile availability information from a parsed layer.json + * or tile metadata extension. + * + * The actual availability information will be found in a property called + * `available`. + * + * @param layerJson The RapidJSON document containing the layer.json. + * @param startingLevel The first tile level number to which the availability + * information applies. + * @return The availability. + */ + static QuantizedMeshMetadataResult loadAvailabilityRectangles( + const rapidjson::Document& layerJson, + uint32_t startingLevel); +}; + +} // namespace CesiumQuantizedMeshTerrain diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/BingMapsRasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/BingMapsRasterOverlay.h new file mode 100644 index 0000000..e97e8c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/BingMapsRasterOverlay.h @@ -0,0 +1,129 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlay.h" + +#include +#include + +#include +#include + +namespace CesiumRasterOverlays { + +/** + * @brief Styles of Bing Maps overlays. + * + * Constants that can be passed to a {@link BingMapsRasterOverlay} to + * indicate the overlays that should be painted. + */ +struct BingMapsStyle final { + /** + * @brief Aerial imagery. + */ + static const std::string AERIAL; + + /** + * @brief Aerial imagery with a road overlay. + * @deprecated See https://github.com/CesiumGS/cesium/issues/7128. + * Use `BingMapsStyle.AERIAL_WITH_LABELS_ON_DEMAND` instead + */ + static const std::string AERIAL_WITH_LABELS; + + /** + * @brief Aerial imagery with a road overlay. + */ + static const std::string AERIAL_WITH_LABELS_ON_DEMAND; + + /** + * @brief Roads without additional imagery. + * @deprecated See https://github.com/CesiumGS/cesium/issues/7128. + * Use `BingMapsStyle.ROAD_ON_DEMAND` instead + */ + static const std::string ROAD; + + /** + * @brief Roads without additional imagery. + */ + static const std::string ROAD_ON_DEMAND; + + /** + * @brief A dark version of the road maps. + */ + static const std::string CANVAS_DARK; + + /** + * @brief A lighter version of the road maps. + */ + static const std::string CANVAS_LIGHT; + + /** + * @brief A grayscale version of the road maps. + */ + static const std::string CANVAS_GRAY; + + /** + * @brief Ordnance Survey imagery. + * + * This imagery is visible only for the London, UK area. + */ + static const std::string ORDNANCE_SURVEY; + + /** + * @brief Collins Bart imagery. + */ + static const std::string COLLINS_BART; +}; + +/** + * @brief A {@link RasterOverlay} that uses Bing Maps as the source for the + * imagery data. + */ +class CESIUMRASTEROVERLAYS_API BingMapsRasterOverlay final + : public RasterOverlay { +public: + /** + * @brief Creates a new instance. + * + * @param name The user-given name of this overlay layer. + * @param url The url of the Bing Maps server hosting the imagery. + * @param key The Bing Maps key for your application, which can be created at + * https://www.bingmapsportal.com/. + * @param mapStyle The type of Bing Maps imagery to load. A value from + * {@link BingMapsStyle}, with {@link BingMapsStyle::AERIAL} being the + * default. + * @param culture The culture to use when requesting Bing Maps imagery. Not + * all cultures are supported. See + * http://msdn.microsoft.com/en-us/library/hh441729.aspx for information on + * the supported cultures. + * @param overlayOptions The {@link RasterOverlayOptions} for this instance. + */ + BingMapsRasterOverlay( + const std::string& name, + const std::string& url, + const std::string& key, + const std::string& mapStyle = BingMapsStyle::AERIAL, + const std::string& culture = "", + const RasterOverlayOptions& overlayOptions = {}); + virtual ~BingMapsRasterOverlay() override; + + virtual CesiumAsync::Future createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pCreditSystem, + const std::shared_ptr& + pPrepareRendererResources, + const std::shared_ptr& pLogger, + CesiumUtility::IntrusivePointer pOwner) + const override; + +private: + static const std::string BING_LOGO_HTML; + + std::string _url; + std::string _key; + std::string _mapStyle; + std::string _culture; +}; + +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/DebugColorizeTilesRasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/DebugColorizeTilesRasterOverlay.h new file mode 100644 index 0000000..c99b245 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/DebugColorizeTilesRasterOverlay.h @@ -0,0 +1,37 @@ +#pragma once + +#include "CesiumGeospatial/Ellipsoid.h" +#include "RasterOverlay.h" + +namespace CesiumRasterOverlays { + +/** + * @brief A raster overlay that gives each tile to which it is attached a random + * color with 50% opacity. This is useful for debugging a tileset, to visualize + * how it is divided into tiles. + */ +class CESIUMRASTEROVERLAYS_API DebugColorizeTilesRasterOverlay + : public RasterOverlay { +public: + /** + * @copydoc RasterOverlay::RasterOverlay + */ + DebugColorizeTilesRasterOverlay( + const std::string& name, + const RasterOverlayOptions& overlayOptions = RasterOverlayOptions()); + + /** + * @copydoc RasterOverlay::createTileProvider + */ + virtual CesiumAsync::Future createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pCreditSystem, + const std::shared_ptr& + pPrepareRendererResources, + const std::shared_ptr& pLogger, + CesiumUtility::IntrusivePointer pOwner) + const override; +}; + +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/IPrepareRasterOverlayRendererResources.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/IPrepareRasterOverlayRendererResources.h new file mode 100644 index 0000000..43fb643 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/IPrepareRasterOverlayRendererResources.h @@ -0,0 +1,83 @@ +#pragma once + +#include "Library.h" + +#include + +namespace CesiumGltf { +struct ImageAsset; +} + +namespace CesiumRasterOverlays { +class RasterOverlayTile; +} + +namespace CesiumRasterOverlays { + +/** + * @brief An interface between Cesium Native and the application using it, + * allowing Cesium Native to pass loaded raster overlay data to the implementing + * application in order for the application to prepare it to be used in its + * renderer of choice. This could involve creating a texture asset, uploading + * the texture data to the GPU, or any other similar tasks required. + */ +class CESIUMRASTEROVERLAYS_API IPrepareRasterOverlayRendererResources { +public: + /** + * @brief Prepares a raster overlay tile. + * + * This method is invoked in the load thread and may modify the image. + * + * @param image The raster tile image to prepare. + * @param rendererOptions Renderer options associated with the raster overlay tile from {@link RasterOverlayOptions::rendererOptions}. + * @returns Arbitrary data representing the result of the load process. This + * data is passed to {@link prepareRasterInMainThread} as the + * `pLoadThreadResult` parameter. + */ + virtual void* prepareRasterInLoadThread( + CesiumGltf::ImageAsset& image, + const std::any& rendererOptions) = 0; + + /** + * @brief Further preprares a raster overlay tile. + * + * This is called after {@link prepareRasterInLoadThread}, and unlike that + * method, this one is called from the same thread that called + * {@link Cesium3DTilesSelection::Tileset::updateView}. + * + * @param rasterTile The raster tile to prepare. + * @param pLoadThreadResult The value returned from + * {@link prepareRasterInLoadThread}. + * @returns Arbitrary data representing the result of the load process. Note + * that the value returned by {@link prepareRasterInLoadThread} will _not_ be + * automatically preserved and passed to {@link freeRaster}. If you need to free + * that value, do it in this method before returning. If you need that value + * later, add it to the object returned from this method. + */ + virtual void* prepareRasterInMainThread( + RasterOverlayTile& rasterTile, + void* pLoadThreadResult) = 0; + + /** + * @brief Frees previously-prepared renderer resources for a raster tile. + * + * This method is always called from the thread that destroyed the + * {@link RasterOverlayTile}. When raster overlays are used with tilesets, + * this is the thread that called {@link Cesium3DTilesSelection::Tileset::updateView} or deleted the + * tileset. + * + * @param rasterTile The tile for which to free renderer resources. + * @param pLoadThreadResult The result returned by + * {@link prepareRasterInLoadThread}. If {@link prepareRasterInMainThread} + * has already been called, this parameter will be `nullptr`. + * @param pMainThreadResult The result returned by + * {@link prepareRasterInMainThread}. If {@link prepareRasterInMainThread} + * has not yet been called, this parameter will be `nullptr`. + */ + virtual void freeRaster( + const RasterOverlayTile& rasterTile, + void* pLoadThreadResult, + void* pMainThreadResult) noexcept = 0; +}; + +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/IonRasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/IonRasterOverlay.h new file mode 100644 index 0000000..6b96818 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/IonRasterOverlay.h @@ -0,0 +1,84 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlay.h" + +#include +#include + +#include +#include + +namespace CesiumRasterOverlays { + +/** + * @brief A {@link RasterOverlay} that obtains imagery data from Cesium ion. + */ +class CESIUMRASTEROVERLAYS_API IonRasterOverlay final : public RasterOverlay { +public: + /** + * @brief Creates a new instance. + * + * The tiles that are provided by this instance will contain + * imagery data that was obtained from the Cesium ion asset + * with the given ID, accessed with the given access token. + * + * @param name The user-given name of this overlay layer. + * @param ionAssetID The asset ID. + * @param ionAccessToken The access token. + * @param overlayOptions The {@link RasterOverlayOptions} for this instance. + * @param ionAssetEndpointUrl The URL of the ion endpoint to make our requests + * to. + */ + IonRasterOverlay( + const std::string& name, + int64_t ionAssetID, + const std::string& ionAccessToken, + const RasterOverlayOptions& overlayOptions = {}, + const std::string& ionAssetEndpointUrl = "https://api.cesium.com/"); + virtual ~IonRasterOverlay() override; + + virtual CesiumAsync::Future createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pCreditSystem, + const std::shared_ptr& + pPrepareRendererResources, + const std::shared_ptr& pLogger, + CesiumUtility::IntrusivePointer pOwner) + const override; + +private: + int64_t _ionAssetID; + std::string _ionAccessToken; + std::string _ionAssetEndpointUrl; + + struct AssetEndpointAttribution { + std::string html; + bool collapsible = true; + }; + + struct ExternalAssetEndpoint { + std::string externalType; + std::string url; + std::string mapStyle; + std::string key; + std::string culture; + std::string accessToken; + std::vector attributions; + }; + + static std::unordered_map endpointCache; + + CesiumAsync::Future createTileProvider( + const ExternalAssetEndpoint& endpoint, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pCreditSystem, + const std::shared_ptr& + pPrepareRendererResources, + const std::shared_ptr& pLogger, + CesiumUtility::IntrusivePointer pOwner) const; +}; + +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/Library.h new file mode 100644 index 0000000..cab3f40 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/Library.h @@ -0,0 +1,19 @@ +#pragma once + +/** + * @brief Classes for raster overlays, which allow draping massive 2D textures + * over a model. + * + * @mermaid-interactive{dependencies/CesiumRasterOverlays} + */ +namespace CesiumRasterOverlays {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMRASTEROVERLAYS_BUILDING +#define CESIUMRASTEROVERLAYS_API __declspec(dllexport) +#else +#define CESIUMRASTEROVERLAYS_API __declspec(dllimport) +#endif +#else +#define CESIUMRASTEROVERLAYS_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/QuadtreeRasterOverlayTileProvider.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/QuadtreeRasterOverlayTileProvider.h new file mode 100644 index 0000000..4551b42 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/QuadtreeRasterOverlayTileProvider.h @@ -0,0 +1,195 @@ +#pragma once + +#include "IPrepareRasterOverlayRendererResources.h" +#include "Library.h" +#include "RasterOverlayTileProvider.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace CesiumRasterOverlays { + +/** + * @brief A base class used for raster overlay providers that use a + * quadtree-based tiling scheme. This includes \ref TileMapServiceRasterOverlay, + * \ref BingMapsRasterOverlay, and \ref WebMapServiceRasterOverlay. + * + * To implement a new raster overlay provider based on + * QuadtreeRasterOverlayTileProvider, use this as the base class and override + * \ref QuadtreeRasterOverlayTileProvider::loadQuadtreeTileImage + * "loadQuadtreeTileImage" with code that makes requests to your service. + */ +class CESIUMRASTEROVERLAYS_API QuadtreeRasterOverlayTileProvider + : public RasterOverlayTileProvider { + +public: + /** + * @brief Creates a new instance. + * + * @param pOwner The raster overlay that created this tile provider. + * @param asyncSystem The async system used to do work in threads. + * @param pAssetAccessor The interface used to obtain assets (tiles, etc.) for + * this raster overlay. + * @param credit The {@link CesiumUtility::Credit} for this tile provider, if it exists. + * @param pPrepareRendererResources The interface used to prepare raster + * images for rendering. + * @param pLogger The logger to which to send messages about the tile provider + * and tiles. + * @param projection The {@link CesiumGeospatial::Projection}. + * @param tilingScheme The tiling scheme to be used by this {@link QuadtreeRasterOverlayTileProvider}. + * @param coverageRectangle The {@link CesiumGeometry::Rectangle}. + * @param minimumLevel The minimum quadtree tile level. + * @param maximumLevel The maximum quadtree tile level. + * @param imageWidth The image width. + * @param imageHeight The image height. + */ + QuadtreeRasterOverlayTileProvider( + const CesiumUtility::IntrusivePointer& pOwner, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + std::optional credit, + const std::shared_ptr& + pPrepareRendererResources, + const std::shared_ptr& pLogger, + const CesiumGeospatial::Projection& projection, + const CesiumGeometry::QuadtreeTilingScheme& tilingScheme, + const CesiumGeometry::Rectangle& coverageRectangle, + uint32_t minimumLevel, + uint32_t maximumLevel, + uint32_t imageWidth, + uint32_t imageHeight) noexcept; + + /** + * @brief Returns the minimum tile level of this instance. + */ + uint32_t getMinimumLevel() const noexcept { return this->_minimumLevel; } + + /** + * @brief Returns the maximum tile level of this instance. + */ + uint32_t getMaximumLevel() const noexcept { return this->_maximumLevel; } + + /** + * @brief Returns the image width of this instance, in pixels. + */ + uint32_t getWidth() const noexcept { return this->_imageWidth; } + + /** + * @brief Returns the image height of this instance, in pixels. + */ + uint32_t getHeight() const noexcept { return this->_imageHeight; } + + /** + * @brief Returns the {@link CesiumGeometry::QuadtreeTilingScheme} of this + * instance. + */ + const CesiumGeometry::QuadtreeTilingScheme& getTilingScheme() const noexcept { + return this->_tilingScheme; + } + + /** + * @brief Computes the best quadtree level to use for an image intended to + * cover a given projected rectangle when it is a given size on the screen. + * + * @param rectangle The range of projected coordinates to cover. + * @param screenPixels The number of screen pixels to be covered by the + * rectangle. + * @return The level. + */ + uint32_t computeLevelFromTargetScreenPixels( + const CesiumGeometry::Rectangle& rectangle, + const glm::dvec2& screenPixels); + +protected: + /** + * @brief Asynchronously loads a tile in the quadtree. + * + * @param tileID The ID of the quadtree tile to load. + * @return A Future that resolves to the loaded image data or error + * information. + */ + virtual CesiumAsync::Future + loadQuadtreeTileImage(const CesiumGeometry::QuadtreeTileID& tileID) const = 0; + +private: + virtual CesiumAsync::Future + loadTileImage(RasterOverlayTile& overlayTile) override final; + + struct LoadedQuadtreeImage + : public CesiumUtility::SharedAsset { + LoadedQuadtreeImage( + const std::shared_ptr& pLoaded_, + const std::optional& subset_) + : pLoaded(pLoaded_), subset(subset_) {} + std::shared_ptr pLoaded = nullptr; + std::optional subset = std::nullopt; + + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(LoadedQuadtreeImage)); + if (pLoaded) { + accum += pLoaded->getSizeBytes(); + } + return accum; + } + }; + + CesiumAsync::SharedFuture> + getQuadtreeTile(const CesiumGeometry::QuadtreeTileID& tileID); + + /** + * @brief Map raster tiles to geometry tile. + * + * @param geometryRectangle The rectangle for which to load tiles. + * @param targetGeometricError The geometric error controlling which quadtree + * level to use to cover the rectangle. + * @return A vector of shared futures, each of which will resolve to image + * data that is required to cover the rectangle with the given geometric + * error. + */ + std::vector>> + mapRasterTilesToGeometryTile( + const CesiumGeometry::Rectangle& geometryRectangle, + const glm::dvec2 targetScreenPixels); + + struct CombinedImageMeasurements { + CesiumGeometry::Rectangle rectangle; + int32_t widthPixels; + int32_t heightPixels; + int32_t channels; + int32_t bytesPerChannel; + }; + + static CombinedImageMeasurements measureCombinedImage( + const CesiumGeometry::Rectangle& targetRectangle, + const std::vector>& + images); + + static LoadedRasterOverlayImage combineImages( + const CesiumGeometry::Rectangle& targetRectangle, + const CesiumGeospatial::Projection& projection, + std::vector>&& images); + + uint32_t _minimumLevel; + uint32_t _maximumLevel; + uint32_t _imageWidth; + uint32_t _imageHeight; + CesiumGeometry::QuadtreeTilingScheme _tilingScheme; + + CesiumUtility::IntrusivePointer> + _pTileDepot; +}; +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlay.h new file mode 100644 index 0000000..bdad340 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlay.h @@ -0,0 +1,256 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlayLoadFailureDetails.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace CesiumUtility { +struct Credit; +class CreditSystem; +} // namespace CesiumUtility + +namespace CesiumRasterOverlays { + +class IPrepareRasterOverlayRendererResources; +class RasterOverlayTileProvider; + +/** + * @brief Options for loading raster overlays. + */ +struct CESIUMRASTEROVERLAYS_API RasterOverlayOptions { + /** + * @brief The maximum number of overlay tiles that may simultaneously be in + * the process of loading. + */ + int32_t maximumSimultaneousTileLoads = 20; + + /** + * @brief The maximum number of bytes to use to cache sub-tiles in memory. + * + * This is used by provider types, such as + * {@link QuadtreeRasterOverlayTileProvider}, that have an underlying tiling + * scheme that may not align with the tiling scheme of the geometry tiles on + * which the raster overlay tiles are draped. Because a single sub-tile may + * overlap multiple geometry tiles, it is useful to cache loaded sub-tiles + * in memory in case they're needed again soon. This property controls the + * maximum size of that cache. + */ + int64_t subTileCacheBytes = 16 * 1024 * 1024; + + /** + * @brief The maximum pixel size of raster overlay textures, in either + * direction. + * + * Images created by this overlay will be no more than this number of pixels + * in either direction. This may result in reduced raster overlay detail in + * some cases. For example, in a {@link QuadtreeRasterOverlayTileProvider}, + * this property will limit the number of quadtree tiles that may be mapped to + * a given geometry tile. The selected quadtree level for a geometry tile is + * reduced in order to stay under this limit. + */ + int32_t maximumTextureSize = 2048; + + /** + * @brief The maximum number of pixels of error when rendering this overlay. + * This is used to select an appropriate level-of-detail. + * + * When this property has its default value, 2.0, it means that raster overlay + * images will be sized so that, when zoomed in closest, a single pixel in + * the raster overlay maps to approximately 2x2 pixels on the screen. + */ + double maximumScreenSpaceError = 2.0; + + /** + * @brief For each possible input transmission format, this struct names + * the ideal target gpu-compressed pixel format to transcode to. + */ + CesiumGltf::Ktx2TranscodeTargets ktx2TranscodeTargets; + + /** + * @brief A callback function that is invoked when a raster overlay resource + * fails to load. + * + * Raster overlay resources include a Cesium ion asset endpoint or any + * resources required for raster overlay metadata. + * + * This callback is invoked by the {@link Cesium3DTilesSelection::RasterOverlayCollection} when an + * error occurs while it is creating a tile provider for this RasterOverlay. + * It is always invoked in the main thread. + */ + std::function loadErrorCallback; + + /** + * @brief Whether or not to display the credits on screen. + */ + bool showCreditsOnScreen = false; + + /** + * @brief Arbitrary data that will be passed to {@link Cesium3DTilesSelection::IPrepareRendererResources::prepareRasterInLoadThread}, + * for example, data to control the per-raster overlay client-specific texture + * properties. + * + * This object is copied and given to background texture preparation threads, + * so it must be inexpensive to copy. + */ + std::any rendererOptions; + + /** + * @brief The ellipsoid used for this raster overlay. + */ + CesiumGeospatial::Ellipsoid ellipsoid = CesiumGeospatial::Ellipsoid::WGS84; +}; + +/** + * @brief The base class for a rasterized image that can be draped + * over a {@link Cesium3DTilesSelection::Tileset}. The image may be very, very high resolution, so only + * small pieces of it are mapped to the Tileset at a time. + * + * Instances of this class can be added to the {@link Cesium3DTilesSelection::RasterOverlayCollection} + * that is returned by {@link Cesium3DTilesSelection::Tileset::getOverlays}. + * + * Instances of this class must be allocated on the heap, and their lifetimes + * must be managed with {@link CesiumUtility::IntrusivePointer}. + * + * @see BingMapsRasterOverlay + * @see IonRasterOverlay + * @see TileMapServiceRasterOverlay + * @see WebMapServiceRasterOverlay + */ +class RasterOverlay + : public CesiumUtility::ReferenceCountedNonThreadSafe { +public: + /** + * @brief Creates a new instance. + * + * @param name The user-given name of this overlay layer. + * @param overlayOptions The {@link RasterOverlayOptions} for this instance. + */ + RasterOverlay( + const std::string& name, + const RasterOverlayOptions& overlayOptions = RasterOverlayOptions()); + virtual ~RasterOverlay() noexcept; + + /** + * @brief A future that resolves when this RasterOverlay has been destroyed + * (i.e. its destructor has been called) and all async operations that it was + * executing have completed. + * + * @param asyncSystem The AsyncSystem to use for the returned SharedFuture, + * if required. If this method is called multiple times, all invocations + * must pass {@link CesiumAsync::AsyncSystem} instances that compare equal to each other. + */ + CesiumAsync::SharedFuture& + getAsyncDestructionCompleteEvent(const CesiumAsync::AsyncSystem& asyncSystem); + + /** + * @brief Gets the name of this overlay. + */ + const std::string& getName() const noexcept { return this->_name; } + + /** + * @brief Gets options for this overlay. + */ + RasterOverlayOptions& getOptions() noexcept { return this->_options; } + + /** @copydoc getOptions */ + const RasterOverlayOptions& getOptions() const noexcept { + return this->_options; + } + + /** + * @brief Gets the credits for this overlay. + */ + const std::vector& getCredits() const noexcept { + return this->_credits; + } + + /** + * @brief Gets the credits for this overlay. + */ + std::vector& getCredits() noexcept { + return this->_credits; + } + + /** + * @brief Create a placeholder tile provider can be used in place of the real + * one while {@link createTileProvider} completes asynchronously. + * + * @param asyncSystem The async system used to do work in threads. + * @param pAssetAccessor The interface used to download assets like overlay + * metadata and tiles. + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + * @return The placeholder. + */ + CesiumUtility::IntrusivePointer createPlaceholder( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) const; + + /** + * @brief A result from a call to \ref createTileProvider. This is expected to + * be an \ref CesiumUtility::IntrusivePointer "IntrusivePointer" to a \ref + * RasterOverlayTileProvider, but may be a \ref + * RasterOverlayLoadFailureDetails if creating the tile provider wasn't + * successful. + */ + using CreateTileProviderResult = nonstd::expected< + CesiumUtility::IntrusivePointer, + RasterOverlayLoadFailureDetails>; + + /** + * @brief Begins asynchronous creation of a tile provider for this overlay + * and eventually returns it via a Future. + * + * @param asyncSystem The async system used to do work in threads. + * @param pAssetAccessor The interface used to download assets like overlay + * metadata and tiles. + * @param pCreditSystem The {@link CesiumUtility::CreditSystem} to use when creating a + * per-TileProvider {@link CesiumUtility::Credit}. + * @param pPrepareRendererResources The interface used to prepare raster + * images for rendering. + * @param pLogger The logger to which to send messages about the tile provider + * and tiles. + * @param pOwner The overlay that owns this overlay, or nullptr if this + * overlay is not aggregated. + * @return The future that resolves to the tile provider when it is ready, or + * to error details in the case of an error. + */ + virtual CesiumAsync::Future createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pCreditSystem, + const std::shared_ptr& + pPrepareRendererResources, + const std::shared_ptr& pLogger, + CesiumUtility::IntrusivePointer pOwner) const = 0; + +private: + struct DestructionCompleteDetails { + CesiumAsync::AsyncSystem asyncSystem; + CesiumAsync::Promise promise; + CesiumAsync::SharedFuture future; + }; + + std::string _name; + RasterOverlayOptions _options; + std::vector _credits; + std::optional _destructionCompleteDetails; +}; + +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayDetails.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayDetails.h new file mode 100644 index 0000000..75fded2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayDetails.h @@ -0,0 +1,82 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include + +#include + +namespace CesiumRasterOverlays { +/** + * @brief Holds details of the {@link Cesium3DTilesSelection::TileRenderContent} that are useful + * for raster overlays. + */ +struct CESIUMRASTEROVERLAYS_API RasterOverlayDetails { + /** + * @brief Construct an empty RasterOverlayDetails. + */ + RasterOverlayDetails(); + + /** + * @brief Construct a RasterOverlayDetails with given projections, the + * rectangles generated by the projections, and the bounding region covered + * those rectangles. + * + * @param rasterOverlayProjections The raster overlay projections for which + * texture coordinates have been generated. + * @param rasterOverlayRectangles The rectangle covered by this tile in each + * of the {@link rasterOverlayProjections}. + * @param boundingRegion The precise bounding region of this tile. + */ + RasterOverlayDetails( + std::vector&& rasterOverlayProjections, + std::vector&& rasterOverlayRectangles, + const CesiumGeospatial::BoundingRegion& boundingRegion); + + /** + * @brief Finds the rectangle corresponding to a given projection in + * {@link rasterOverlayProjections}. + * + * @param projection The projection. + * @return The tile's rectangle in the given projection, or nullptr if the + * projection is not in {@link rasterOverlayProjections}. + */ + const CesiumGeometry::Rectangle* findRectangleForOverlayProjection( + const CesiumGeospatial::Projection& projection) const; + + /** + * @brief Merge the other RasterOverlayDetails's projections, rectangles, and + * bounding region together. + * + * @param other The other instance of RasterOverlayDetails that will be merged + * with this. + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + */ + void merge( + const RasterOverlayDetails& other, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief The raster overlay projections for which texture coordinates have + * been generated. + * + * For the projection at index `n`, there is a set of texture coordinates + * with the attribute name `_CESIUMOVERLAY_n` that corresponds to that + * projection. + */ + std::vector rasterOverlayProjections; + + /** + * @brief The rectangle covered by this tile in each of the + * {@link rasterOverlayProjections}. + */ + std::vector rasterOverlayRectangles; + + /** + * @brief The precise bounding region of this tile. + */ + CesiumGeospatial::BoundingRegion boundingRegion; +}; +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayLoadFailureDetails.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayLoadFailureDetails.h new file mode 100644 index 0000000..210739d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayLoadFailureDetails.h @@ -0,0 +1,58 @@ +#pragma once + +#include + +#include +#include + +namespace CesiumAsync { +class IAssetRequest; +} + +namespace CesiumRasterOverlays { + +class RasterOverlay; + +/** + * @brief The type of load that failed in `RasterOverlayLoadFailureDetails`. + */ +enum class RasterOverlayLoadType { + /** + * @brief An unknown load error. + */ + Unknown, + + /** + * @brief A Cesium ion asset endpoint. + */ + CesiumIon, + + /** + * @brief An initial load needed to create the overlay's tile provider. + */ + TileProvider +}; + +/** + * @brief Details on a failure while attempting to load a raster overlay tile. + */ +class RasterOverlayLoadFailureDetails { +public: + /** + * @brief The type of request that failed to load. + */ + RasterOverlayLoadType type = RasterOverlayLoadType::Unknown; + + /** + * @brief The request that failed. The request itself may have succeeded, but + * the failure occurred while processing this request. + */ + std::shared_ptr pRequest = nullptr; + + /** + * @brief A human-readable explanation of what failed. + */ + std::string message = ""; +}; + +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayTile.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayTile.h new file mode 100644 index 0000000..2d14dde --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayTile.h @@ -0,0 +1,267 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +namespace CesiumUtility { +struct Credit; +} + +namespace CesiumRasterOverlays { + +class RasterOverlay; +class RasterOverlayTileProvider; + +/** + * @brief Raster image data for a tile in a quadtree. + * + * Instances of this clas represent tiles of a quadtree that have + * an associated image, which us used as an imagery overlay + * for tile geometry. The connection between the imagery data + * and the actual tile geometry is established via the + * {@link Cesium3DTilesSelection::RasterMappedTo3DTile} class, which combines a + * raster overlay tile with texture coordinates, to map the + * image on the geometry of a {@link Cesium3DTilesSelection::Tile}. + */ +class RasterOverlayTile final + : public CesiumUtility::ReferenceCountedNonThreadSafe { +public: + /** + * @brief Lifecycle states of a raster overlay tile. + */ + enum class LoadState { + /** + * @brief Indicator for a placeholder tile. + */ + Placeholder = -2, + + /** + * @brief The image request or image creation failed. + */ + Failed = -1, + + /** + * @brief The initial state + */ + Unloaded = 0, + + /** + * @brief The request for loading the image data is still pending. + */ + Loading = 1, + + /** + * @brief The image data has been loaded and the image has been created. + */ + Loaded = 2, + + /** + * @brief The rendering resources for the image data have been created. + */ + Done = 3 + }; + + /** + * @brief Tile availability states. + * + * Values of this enumeration are returned by + * {@link Cesium3DTilesSelection::RasterMappedTo3DTile::update}, which in turn is called by + * `TilesetContentManager::updateDoneState`. These values are used to + * determine whether a leaf tile has been reached, but the associated raster + * tiles are not yet the most detailed ones that are available. + */ + enum class MoreDetailAvailable { + + /** @brief There are no more detailed raster tiles. */ + No = 0, + + /** @brief There are more detailed raster tiles. */ + Yes = 1, + + /** @brief It is not known whether more detailed raster tiles are available. + */ + Unknown = 2 + }; + + /** + * @brief Constructs a placeholder tile for the tile provider. + * + * The {@link getState} of this instance will always be + * {@link LoadState::Placeholder}. + * + * @param tileProvider The {@link RasterOverlayTileProvider}. This object + * _must_ remain valid for the entire lifetime of the tile. If the tile + * provider is destroyed before the tile, undefined behavior will result. + */ + RasterOverlayTile(RasterOverlayTileProvider& tileProvider) noexcept; + + /** + * @brief Creates a new instance. + * + * The tile will start in the `Unloaded` state, and will not begin loading + * until {@link RasterOverlayTileProvider::loadTile} or + * {@link RasterOverlayTileProvider::loadTileThrottled} is called. + * + * @param tileProvider The {@link RasterOverlayTileProvider}. This object + * _must_ remain valid for the entire lifetime of the tile. If the tile + * provider is destroyed before the tile, undefined behavior may result. + * @param targetScreenPixels The maximum number of pixels on the screen that + * this tile is meant to cover. The overlay image should be approximately this + * many pixels divided by the + * {@link RasterOverlayOptions::maximumScreenSpaceError} in order to achieve + * the desired level-of-detail, but it does not need to be exactly this size. + * @param imageryRectangle The rectangle that the returned image must cover. + * It is allowed to cover a slightly larger rectangle in order to maintain + * pixel alignment. It may also cover a smaller rectangle when the overlay + * itself does not cover the entire rectangle. + */ + RasterOverlayTile( + RasterOverlayTileProvider& tileProvider, + const glm::dvec2& targetScreenPixels, + const CesiumGeometry::Rectangle& imageryRectangle) noexcept; + + /** @brief Default destructor. */ + ~RasterOverlayTile(); + + /** + * @brief Returns the {@link RasterOverlayTileProvider} that created this instance. + */ + RasterOverlayTileProvider& getTileProvider() noexcept { + return *this->_pTileProvider; + } + + /** + * @brief Returns the {@link RasterOverlayTileProvider} that created this instance. + */ + const RasterOverlayTileProvider& getTileProvider() const noexcept { + return *this->_pTileProvider; + } + + /** + * @brief Returns the {@link RasterOverlay} that created this instance. + */ + RasterOverlay& getOverlay() noexcept; + + /** + * @brief Returns the {@link RasterOverlay} that created this instance. + */ + const RasterOverlay& getOverlay() const noexcept; + + /** + * @brief Returns the {@link CesiumGeometry::Rectangle} that defines the bounds + * of this tile in the raster overlay's projected coordinates. + */ + const CesiumGeometry::Rectangle& getRectangle() const noexcept { + return this->_rectangle; + } + + /** + * @brief Gets the number of screen pixels in each direction that should be + * covered by this tile's texture. + * + * This is used to control which content (how highly detailed) the + * {@link RasterOverlayTileProvider} uses within the bounds of this tile. + */ + glm::dvec2 getTargetScreenPixels() const noexcept { + return this->_targetScreenPixels; + } + + /** + * @brief Returns the current {@link LoadState}. + */ + LoadState getState() const noexcept { return this->_state; } + + /** + * @brief Returns the list of \ref CesiumUtility::Credit "Credit"s needed for + * this tile. + */ + const std::vector& getCredits() const noexcept { + return this->_tileCredits; + } + + /** + * @brief Returns the image data for the tile. + * + * This will only contain valid image data if the {@link getState} of + * this tile is {@link LoadState `Loaded`} or {@link LoadState `Done`}. + * + * @return The image data. + */ + CesiumUtility::IntrusivePointer + getImage() const noexcept { + return this->_pImage; + } + + /** + * @brief Returns the image data for the tile. + * + * This will only contain valid image data if the {@link getState} of + * this tile is {@link LoadState `Loaded`} or {@link LoadState `Done`}. + * + * @return The image data. + */ + CesiumUtility::IntrusivePointer getImage() noexcept { + return this->_pImage; + } + + /** + * @brief Create the renderer resources for the loaded image. + * + * If the {@link getState} of this tile is not {@link LoadState `Loaded`}, + * then nothing will be done. Otherwise, the renderer resources will be + * prepared, so that they may later be obtained with + * {@link getRendererResources}, and the {@link getState} of this tile + * will change to {@link LoadState `Done`}. + */ + void loadInMainThread(); + + /** + * @brief Returns the renderer resources that have been created for this tile. + */ + void* getRendererResources() const noexcept { + return this->_pRendererResources; + } + + /** + * @brief Set the renderer resources for this tile. + * + * This function is not supposed to be called by clients. + */ + void setRendererResources(void* pValue) noexcept { + this->_pRendererResources = pValue; + } + + /** + * @brief Determines if more detailed data is available for the spatial area + * covered by this tile. + */ + MoreDetailAvailable isMoreDetailAvailable() const noexcept { + return this->_moreDetailAvailable; + } + +private: + friend class RasterOverlayTileProvider; + + void setState(LoadState newState) noexcept; + + // This is a raw pointer instead of an IntrusivePointer in order to avoid + // circular references, particularly among a placeholder tile provider and + // placeholder tile. However, to avoid undefined behavior, the tile provider + // is required to outlive the tile. In normal use, the RasterOverlayCollection + // ensures that this is true. + RasterOverlayTileProvider* _pTileProvider; + glm::dvec2 _targetScreenPixels; + CesiumGeometry::Rectangle _rectangle; + std::vector _tileCredits; + LoadState _state; + CesiumUtility::IntrusivePointer _pImage; + void* _pRendererResources; + MoreDetailAvailable _moreDetailAvailable; +}; +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayTileProvider.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayTileProvider.h new file mode 100644 index 0000000..cac05ee --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayTileProvider.h @@ -0,0 +1,436 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace CesiumRasterOverlays { + +class RasterOverlay; +class RasterOverlayTile; +class IPrepareRasterOverlayRendererResources; + +/** + * @brief Summarizes the result of loading an image of a {@link RasterOverlay}. + */ +struct CESIUMRASTEROVERLAYS_API LoadedRasterOverlayImage { + /** + * @brief The loaded image. + * + * This will be an empty optional if the loading failed. In this case, + * the `errors` vector will contain the corresponding error messages. + */ + CesiumUtility::IntrusivePointer pImage{nullptr}; + + /** + * @brief The projected rectangle defining the bounds of this image. + * + * The rectangle extends from the left side of the leftmost pixel to the + * right side of the rightmost pixel, and similar for the vertical direction. + */ + CesiumGeometry::Rectangle rectangle{}; + + /** + * @brief The {@link CesiumUtility::Credit} objects that decribe the attributions that + * are required when using the image. + */ + std::vector credits{}; + + /** + * @brief Errors and warnings from loading the image. + * + * If the image was loaded successfully, there should not be any errors (but + * there may be warnings). + */ + CesiumUtility::ErrorList errorList{}; + + /** + * @brief Whether more detailed data, beyond this image, is available within + * the bounds of this image. + */ + bool moreDetailAvailable = false; + + /** + * @brief Returns the size of this `LoadedRasterOverlayImage` in bytes. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(LoadedRasterOverlayImage)); + accum += int64_t(this->credits.capacity() * sizeof(CesiumUtility::Credit)); + if (this->pImage) { + accum += this->pImage->getSizeBytes(); + } + return accum; + } +}; + +/** + * @brief Options for {@link RasterOverlayTileProvider::loadTileImageFromUrl}. + */ +struct LoadTileImageFromUrlOptions { + /** + * @brief The rectangle definining the bounds of the image being loaded, + * expressed in the {@link RasterOverlayTileProvider}'s projection. + */ + CesiumGeometry::Rectangle rectangle{}; + + /** + * @brief The credits to display with this tile. + * + * This property is copied verbatim to the + * {@link LoadedRasterOverlayImage::credits} property. + */ + std::vector credits{}; + + /** + * @brief Whether more detailed data, beyond this image, is available within + * the bounds of this image. + */ + bool moreDetailAvailable = true; + + /** + * @brief Whether empty (zero length) images are accepted as a valid + * response. + * + * If true, an otherwise valid response with zero length will be accepted as + * a valid 0x0 image. If false, such a response will be reported as an + * error. + * + * {@link RasterOverlayTileProvider::loadTile} and + * {@link RasterOverlayTileProvider::loadTileThrottled} will treat such an + * image as "failed" and use the quadtree parent (or ancestor) image + * instead, but will not report any error. + * + * This flag should only be set to `true` when the tile source uses a + * zero-length response as an indication that this tile is - as expected - + * not available. + */ + bool allowEmptyImages = false; +}; + +class RasterOverlayTileProvider; + +/** + * @brief Holds a tile and its corresponding tile provider. Used as the return + * value of {@link RasterOverlayTileProvider::loadTile}. + */ +struct TileProviderAndTile { + /** @brief A \ref CesiumUtility::IntrusivePointer to the \ref + * RasterOverlayTileProvider used for this tile. */ + CesiumUtility::IntrusivePointer pTileProvider; + /** @brief A \ref CesiumUtility::IntrusivePointer to the \ref + * RasterOverlayTile used for this tile. */ + CesiumUtility::IntrusivePointer pTile; + + ~TileProviderAndTile() noexcept; +}; + +/** + * @brief Provides individual tiles for a {@link RasterOverlay} on demand. + * + * Instances of this class must be allocated on the heap, and their lifetimes + * must be managed with {@link CesiumUtility::IntrusivePointer}. + */ +class CESIUMRASTEROVERLAYS_API RasterOverlayTileProvider + : public CesiumUtility::ReferenceCountedNonThreadSafe< + RasterOverlayTileProvider> { +public: + /** + * Constructs a placeholder tile provider. + * + * @see RasterOverlayTileProvider::isPlaceholder + * + * @param pOwner The raster overlay that created this tile provider. + * @param asyncSystem The async system used to do work in threads. + * @param pAssetAccessor The interface used to obtain assets (tiles, etc.) for + * this raster overlay. + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + */ + RasterOverlayTileProvider( + const CesiumUtility::IntrusivePointer& pOwner, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const CesiumGeospatial::Ellipsoid& ellipsoid + CESIUM_DEFAULT_ELLIPSOID) noexcept; + + /** + * @brief Creates a new instance. + * + * @param pOwner The raster overlay that created this tile provider. + * @param asyncSystem The async system used to do work in threads. + * @param pAssetAccessor The interface used to obtain assets (tiles, etc.) for + * this raster overlay. + * @param credit The {@link CesiumUtility::Credit} for this tile provider, if it exists. + * @param pPrepareRendererResources The interface used to prepare raster + * images for rendering. + * @param pLogger The logger to which to send messages about the tile provider + * and tiles. + * @param projection The {@link CesiumGeospatial::Projection}. + * @param coverageRectangle The rectangle that bounds all the area covered by + * this overlay, expressed in projected coordinates. + */ + RasterOverlayTileProvider( + const CesiumUtility::IntrusivePointer& pOwner, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + std::optional credit, + const std::shared_ptr& + pPrepareRendererResources, + const std::shared_ptr& pLogger, + const CesiumGeospatial::Projection& projection, + const CesiumGeometry::Rectangle& coverageRectangle) noexcept; + + /** @brief Default destructor. */ + virtual ~RasterOverlayTileProvider() noexcept; + + /** + * @brief Returns whether this is a placeholder. + * + * For many types of {@link RasterOverlay}, we can't create a functioning + * `RasterOverlayTileProvider` right away. For example, we may not know the + * bounds of the overlay, or what projection it uses, until after we've + * (asynchronously) loaded a metadata service that gives us this information. + * + * So until that real `RasterOverlayTileProvider` becomes available, we use + * a placeholder. When {@link RasterOverlayTileProvider::getTile} is invoked + * on a placeholder, it returns a {@link RasterOverlayTile} that is also + * a placeholder. And whenever we see a placeholder `RasterOverlayTile` in + * {@link Cesium3DTilesSelection::RasterMappedTo3DTile::update}, we check if the corresponding `RasterOverlay` is + * ready yet. Once it's ready, we remove the placeholder tile and replace + * it with the real tiles. + * + * So the placeholder system gives us a way to defer the mapping of raster + * overlay tiles to geometry tiles until that mapping can be determined. + */ + bool isPlaceholder() const noexcept { return this->_pPlaceholder != nullptr; } + + /** + * @brief Returns the {@link RasterOverlay} that created this instance. + */ + RasterOverlay& getOwner() noexcept { return *this->_pOwner; } + + /** @copydoc getOwner */ + const RasterOverlay& getOwner() const noexcept { return *this->_pOwner; } + + /** + * @brief Get the system to use for asychronous requests and threaded work. + */ + const std::shared_ptr& + getAssetAccessor() const noexcept { + return this->_pAssetAccessor; + } + + /** + * @brief Gets the async system used to do work in threads. + */ + const CesiumAsync::AsyncSystem& getAsyncSystem() const noexcept { + return this->_asyncSystem; + } + + /** + * @brief Gets the interface used to prepare raster overlay images for + * rendering. + */ + const std::shared_ptr& + getPrepareRendererResources() const noexcept { + return this->_pPrepareRendererResources; + } + + /** + * @brief Gets the logger to which to send messages about the tile provider + * and tiles. + */ + const std::shared_ptr& getLogger() const noexcept { + return this->_pLogger; + } + + /** + * @brief Returns the {@link CesiumGeospatial::Projection} of this instance. + */ + const CesiumGeospatial::Projection& getProjection() const noexcept { + return this->_projection; + } + + /** + * @brief Returns the coverage {@link CesiumGeometry::Rectangle} of this + * instance. + */ + const CesiumGeometry::Rectangle& getCoverageRectangle() const noexcept { + return this->_coverageRectangle; + } + + /** + * @brief Returns a new {@link RasterOverlayTile} with the given + * specifications. + * + * The returned tile will not start loading immediately. To start loading, + * call {@link RasterOverlayTileProvider::loadTile} or + * {@link RasterOverlayTileProvider::loadTileThrottled}. + * + * @param rectangle The rectangle that the returned image must cover. It is + * allowed to cover a slightly larger rectangle in order to maintain pixel + * alignment. It may also cover a smaller rectangle when the overlay itself + * does not cover the entire rectangle. + * @param targetScreenPixels The maximum number of pixels on the screen that + * this tile is meant to cover. The overlay image should be approximately this + * many pixels divided by the + * {@link RasterOverlayOptions::maximumScreenSpaceError} in order to achieve + * the desired level-of-detail, but it does not need to be exactly this size. + * @return The tile. + */ + CesiumUtility::IntrusivePointer getTile( + const CesiumGeometry::Rectangle& rectangle, + const glm::dvec2& targetScreenPixels); + + /** + * @brief Gets the number of bytes of tile data that are currently loaded. + */ + int64_t getTileDataBytes() const noexcept { return this->_tileDataBytes; } + + /** + * @brief Returns the number of tiles that are currently loading. + */ + uint32_t getNumberOfTilesLoading() const noexcept { + CESIUM_ASSERT(this->_totalTilesCurrentlyLoading > -1); + return static_cast(this->_totalTilesCurrentlyLoading); + } + + /** + * @brief Removes a no-longer-referenced tile from this provider's cache and + * deletes it. + * + * This function is not supposed to be called by client. Calling this method + * in a tile with a reference count greater than 0 will result in undefined + * behavior. + * + * @param pTile The tile, which must have no oustanding references. + */ + void removeTile(RasterOverlayTile* pTile) noexcept; + + /** + * @brief Get the per-TileProvider {@link CesiumUtility::Credit} if one exists. + */ + const std::optional& getCredit() const noexcept { + return _credit; + } + + /** + * @brief Loads a tile immediately, without throttling requests. + * + * If the tile is not in the `Tile::LoadState::Unloaded` state, this method + * returns without doing anything. Otherwise, it puts the tile into the + * `Tile::LoadState::Loading` state and begins the asynchronous process + * to load the tile. When the process completes, the tile will be in the + * `Tile::LoadState::Loaded` or `Tile::LoadState::Failed` state. + * + * Calling this method on many tiles at once can result in very slow + * performance. Consider using {@link loadTileThrottled} instead. + * + * @param tile The tile to load. + * @return A future that, when the tile is loaded, resolves to the loaded tile + * and the tile provider that loaded it. + */ + CesiumAsync::Future loadTile(RasterOverlayTile& tile); + + /** + * @brief Loads a tile, unless there are too many tile loads already in + * progress. + * + * If the tile is not in the `Tile::LoadState::Unloading` state, this method + * returns true without doing anything. If too many tile loads are + * already in flight, it returns false without doing anything. Otherwise, it + * puts the tile into the `Tile::LoadState::Loading` state, begins the + * asynchronous process to load the tile, and returns true. When the process + * completes, the tile will be in the `Tile::LoadState::Loaded` or + * `Tile::LoadState::Failed` state. + * + * The number of allowable simultaneous tile requests is provided in the + * {@link RasterOverlayOptions::maximumSimultaneousTileLoads} property of + * {@link RasterOverlay::getOptions}. + * + * @param tile The tile to load. + * @returns True if the tile load process is started or is already complete, + * false if the load could not be started because too many loads are already + * in progress. + */ + bool loadTileThrottled(RasterOverlayTile& tile); + +protected: + /** + * @brief Loads the image for a tile. + * + * @param overlayTile The overlay tile for which to load the image. + * @return A future that resolves to the image or error information. + */ + virtual CesiumAsync::Future + loadTileImage(RasterOverlayTile& overlayTile) = 0; + + /** + * @brief Loads an image from a URL and optionally some request headers. + * + * This is a useful helper function for implementing {@link loadTileImage}. + * + * @param url The URL. + * @param headers The request headers. + * @param options Additional options for the load process. + * @return A future that resolves to the image or error information. + */ + CesiumAsync::Future loadTileImageFromUrl( + const std::string& url, + const std::vector& headers = {}, + LoadTileImageFromUrlOptions&& options = {}) const; + +private: + CesiumAsync::Future + doLoad(RasterOverlayTile& tile, bool isThrottledLoad); + + /** + * @brief Begins the process of loading of a tile. + * + * This method should be called at the beginning of the tile load process. + * + * @param isThrottledLoad True if the load was originally throttled. + */ + void beginTileLoad(bool isThrottledLoad) noexcept; + + /** + * @brief Finalizes loading of a tile. + * + * This method should be called at the end of the tile load process, + * no matter whether the load succeeded or failed. + * + * @param isThrottledLoad True if the load was originally throttled. + */ + void finalizeTileLoad(bool isThrottledLoad) noexcept; + +private: + CesiumUtility::IntrusivePointer _pOwner; + CesiumAsync::AsyncSystem _asyncSystem; + std::shared_ptr _pAssetAccessor; + std::optional _credit; + std::shared_ptr + _pPrepareRendererResources; + std::shared_ptr _pLogger; + CesiumGeospatial::Projection _projection; + CesiumGeometry::Rectangle _coverageRectangle; + CesiumUtility::IntrusivePointer _pPlaceholder; + int64_t _tileDataBytes; + int32_t _totalTilesCurrentlyLoading; + int32_t _throttledTilesCurrentlyLoading; + CESIUM_TRACE_DECLARE_TRACK_SET( + _loadingSlots, + "Raster Overlay Tile Loading Slot") +}; +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayUtilities.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayUtilities.h new file mode 100644 index 0000000..0d03664 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterOverlayUtilities.h @@ -0,0 +1,194 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlayDetails.h" + +#include +#include +#include + +#include + +#include +#include +#include + +namespace CesiumGltf { +struct Model; +} + +namespace CesiumRasterOverlays { + +/** + * @brief A collection of utilities useful for operations involving raster + * overlay tiles. + */ +struct CESIUMRASTEROVERLAYS_API RasterOverlayUtilities { + /** + * @brief Texture coordinates will be stored in the glTF under the following + * name, appended with a number. See \ref + * createRasterOverlayTextureCoordinates. + */ + static constexpr std::string_view DEFAULT_TEXTURE_COORDINATE_BASE_NAME = + "_CESIUMOVERLAY_"; + + /** + * @brief Creates texture coordinates for mapping {@link RasterOverlay} tiles + * to a glTF model. + * + * Generates new texture coordinates for the `gltf` using the given + * `projections`. The first new texture coordinate (`u` or `s`) will be 0.0 at + * the `minimumX` of the given `rectangle` and 1.0 at the `maximumX`. The + * second texture coordinate (`v` or `t`) will be 0.0 at the `minimumY` of + * the given `rectangle` and 1.0 at the `maximumY`. + * + * Coordinate values for vertices in between these extremes are determined by + * projecting the vertex position with the `projection` and then computing the + * fractional distance of that projected position between the minimum and + * maximum. + * + * Projected positions that fall outside the `globeRectangle` will be clamped + * to the edges, so the coordinate values will never be less then 0.0 or + * greater than 1.0. + * + * These texture coordinates are stored in the provided glTF, and a new + * primitive attribute is added to each primitive for each projection. The new + * primitive attributes are named with `textureCoordinateAttributeBaseName` + * followed by a number, starting with `firstTextureCoordinateID` and + * incrementing for each projection. For example, if + * `textureCoordinateAttributeBaseName` is + * `_CESIUMOVERLAY_` and `firstTextureCoordinateID` is 0 (the defaults), then + * the texture coordinates for the first projection will be stored in an + * attribute named `_CESIUMOVERLAY_0`, the second will be in + * `_CESIUMOVERLAY_1`, and so on. + * + * @param gltf The glTF model. + * @param modelToEcefTransform The transformation of this glTF to ECEF + * coordinates. + * @param globeRectangle The rectangle that all projected vertex positions are + * expected to lie within. If this parameter is std::nullopt, it is computed + * from the vertices. + * @param projections The projections for which to generate texture + * coordinates. There is a linear relationship between the coordinates of this + * projection and the generated texture coordinates. + * @param invertVCoordinate True if the V texture coordinate should be + * inverted so that it is 1.0 at the Southern end of the rectangle and 0.0 at + * the Northern end. This is useful with images that use the typical North-up + * orientation. + * @param textureCoordinateAttributeBaseName The base name to use for the + * texture coordinate attributes, without a number on the end. Defaults to + * {@link DEFAULT_TEXTURE_COORDINATE_BASE_NAME}. + * @param firstTextureCoordinateID The texture coordinate ID of the first + * projection. + * @return The details of the generated texture coordinates. + */ + static std::optional + createRasterOverlayTextureCoordinates( + CesiumGltf::Model& gltf, + const glm::dmat4& modelToEcefTransform, + const std::optional& globeRectangle, + std::vector&& projections, + bool invertVCoordinate = false, + const std::string_view& textureCoordinateAttributeBaseName = + DEFAULT_TEXTURE_COORDINATE_BASE_NAME, + int32_t firstTextureCoordinateID = 0); + + /** + * @brief Creates a new glTF model from one of the quadtree children of the + * given parent model. + * + * The parent model subdivision is guided by texture coordinates. These + * texture coordinates must follow a map projection, and the parent tile is + * divided into quadrants as divided by this map projection. To create the + * necessary texture coordinates, use + * {@link createRasterOverlayTextureCoordinates}. + * + * @param parentModel The parent model to upsample. + * @param childID The quadtree tile ID of the child model. This is used to + * determine which of the four children of the parent tile to generate. + * @param hasInvertedVCoordinate True if the V texture coordinate has 0.0 as + * the Northern-most coordinate; False if the V texture coordinate has 0.0 as + * the Southern-most coordiante. + * @param textureCoordinateAttributeBaseName The base name of the attribute + * that holds the projected texture coordinates. The `textureCoordinateIndex` + * is appended to this name. Defaults to + * {@link DEFAULT_TEXTURE_COORDINATE_BASE_NAME}. + * @param textureCoordinateIndex The index of the texture coordinate set to + * use. For example, if `textureCoordinateAttributeBaseName` is + * `_CESIUMOVERLAY_` and this parameter is 0 (the defaults), then the texture + * coordinates are read from a vertex attribute named `_CESIUMOVERLAY_0`. + * @param ellipsoid The {@link CesiumGeospatial::Ellipsoid}. + * @return The upsampled model. + */ + static std::optional upsampleGltfForRasterOverlays( + const CesiumGltf::Model& parentModel, + CesiumGeometry::UpsampledQuadtreeNode childID, + bool hasInvertedVCoordinate = false, + const std::string_view& textureCoordinateAttributeBaseName = + DEFAULT_TEXTURE_COORDINATE_BASE_NAME, + int32_t textureCoordinateIndex = 0, + const CesiumGeospatial::Ellipsoid& ellipsoid = + CesiumGeospatial::Ellipsoid::WGS84); + + /** + * @brief Computes the desired screen pixels for a raster overlay texture. + * + * This method is used to determine the appropriate number of "screen pixels" + * to use for a raster overlay texture to be attached to a glTF (which is + * usually a 3D Tiles tile). In other words, how detailed should the texture + * be? The answer depends, of course, on how close we'll get to the model. If + * we're going to get very close, we'll need a higher-resolution raster + * overlay texture than if we will stay far away from it. + * + * In 3D Tiles, we can only get so close to a model before it switches to the + * next higher level-of-detail by showing its children instead. The switch + * distance is controlled by the `geometric error` of the tile, as well as by + * the `maximum screen space error` of the tileset. So this method requires + * both of those parameters. + * + * The answer also depends on the size of the model on the screen at this + * switch distance. To determine that, this method takes a projection and a + * rectangle that bounds the tile, expressed in that projection. This + * rectangle is projected onto the screen at the switch distance, and the size + * of that rectangle on the screen is the `target screen pixels` returned by + * this method. + * + * The `target screen pixels` returned here may be further modified by the + * raster overlay's {@link RasterOverlayTileProvider::getTile} method. In particular, it + * will usually be divided by the raster overlay's `maximum screen space + * error` of the raster overlay (not to be confused with the `maximum screen + * space error` of the tileset, mentioned above). + * + * @param geometricError The geometric error of the tile. + * @param maximumScreenSpaceError The maximum screen-space error used to + * render the tileset. + * @param projection The projection in which the `rectangle` parameter is + * provided. + * @param rectangle The 2D extent of the tile, expressed in the `projection`. + * @param ellipsoid The ellipsoid with which computations are performed. + * @return The desired screen pixels. + */ + static glm::dvec2 computeDesiredScreenPixels( + double geometricError, + double maximumScreenSpaceError, + const CesiumGeospatial::Projection& projection, + const CesiumGeometry::Rectangle& rectangle, + const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + + /** + * @brief Computes the texture translation and scale necessary to align a + * raster overlay with the given rectangle on geometry whose texture + * coordinates were computed using a different rectangle. + * + * @param geometryRectangle The geometry rectangle used to the compute the + * texture coordinates. + * @param overlayRectangle The rectangle covered by the raster overlay + * texture. + * @return The translation in X and Y, and the scale in Z and W. + */ + static glm::dvec4 computeTranslationAndScale( + const CesiumGeometry::Rectangle& geometryRectangle, + const CesiumGeometry::Rectangle& overlayRectangle); +}; + +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterizedPolygonsOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterizedPolygonsOverlay.h new file mode 100644 index 0000000..e355a26 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/RasterizedPolygonsOverlay.h @@ -0,0 +1,90 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlay.h" +#include "RasterOverlayTileProvider.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include + +namespace CesiumRasterOverlays { + +/** + * @brief A raster overlay made from rasterizing a set of \ref + * CesiumGeospatial::CartographicPolygon "CartographicPolygon" objects. The + * resulting overlay is monochromatic - white where pixels are inside of the + * polygons, and black where they are not. + */ +class CESIUMRASTEROVERLAYS_API RasterizedPolygonsOverlay final + : public RasterOverlay { + +public: + /** + * @brief Creates a new RasterizedPolygonsOverlay. + * + * @param name The user-given name of this polygon layer. + * @param polygons The \ref CesiumGeospatial::CartographicPolygon + * "CartographicPolygon" objects to rasterize. + * @param invertSelection If true, the overlay's colors will be inverted. The + * pixels inside of polygons will be black, and those outside will be white. + * @param ellipsoid The ellipsoid that this RasterOverlay is being generated + * for. + * @param projection The projection that this RasterOverlay is being generated + * for. + * @param overlayOptions Options to use for this RasterOverlay. + */ + RasterizedPolygonsOverlay( + const std::string& name, + const std::vector& polygons, + bool invertSelection, + const CesiumGeospatial::Ellipsoid& ellipsoid, + const CesiumGeospatial::Projection& projection, + const RasterOverlayOptions& overlayOptions = {}); + virtual ~RasterizedPolygonsOverlay() override; + + virtual CesiumAsync::Future createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pCreditSystem, + const std::shared_ptr& + pPrepareRendererResources, + const std::shared_ptr& pLogger, + CesiumUtility::IntrusivePointer pOwner) + const override; + + /** + * @brief Gets the polygons that are being rasterized to create this overlay. + */ + const std::vector& + getPolygons() const noexcept { + return this->_polygons; + } + + /** + * @brief Gets the value of the `invertSelection` value passed to the + * constructor. + */ + bool getInvertSelection() const noexcept { return this->_invertSelection; } + + /** + * @brief Gets the ellipsoid that this overlay is being generated for. + */ + const CesiumGeospatial::Ellipsoid& getEllipsoid() const noexcept { + return this->_ellipsoid; + } + +private: + std::vector _polygons; + bool _invertSelection; + CesiumGeospatial::Ellipsoid _ellipsoid; + CesiumGeospatial::Projection _projection; +}; +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/TileMapServiceRasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/TileMapServiceRasterOverlay.h new file mode 100644 index 0000000..f7d9da4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/TileMapServiceRasterOverlay.h @@ -0,0 +1,125 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlay.h" + +#include +#include +#include +#include +#include + +#include +#include + +namespace CesiumRasterOverlays { + +/** + * @brief Options for tile map service accesses. + */ +struct TileMapServiceRasterOverlayOptions { + + /** + * @brief The file extension for images on the server. + */ + std::optional fileExtension; + + /** + * @brief A credit for the data source, which is displayed on the canvas. + */ + std::optional credit; + + /** + * @brief The minimum level-of-detail supported by the imagery provider. + * + * Take care when specifying this that the number of tiles at the minimum + * level is small, such as four or less. A larger number is likely to + * result in rendering problems. + */ + std::optional minimumLevel; + + /** + * @brief The maximum level-of-detail supported by the imagery provider. + * + * This will be `std::nullopt` if there is no limit. + */ + std::optional maximumLevel; + + /** + * @brief The {@link CesiumGeometry::Rectangle}, in radians, covered by the + * image. + */ + std::optional coverageRectangle; + + /** + * @brief The {@link CesiumGeospatial::Projection} that is used. + */ + std::optional projection; + + /** + * @brief The {@link CesiumGeometry::QuadtreeTilingScheme} specifying how + * the ellipsoidal surface is broken into tiles. + */ + std::optional tilingScheme; + + /** + * @brief Pixel width of image tiles. + */ + std::optional tileWidth; + + /** + * @brief Pixel height of image tiles. + */ + std::optional tileHeight; + + /** + * @brief An otion to flip the x- and y values of a tile map resource. + * + * Older versions of gdal2tiles.py flipped X and Y values in + * `tilemapresource.xml`. Specifying this option will do the same, allowing + * for loading of these incorrect tilesets. + */ + std::optional flipXY; +}; + +/** + * @brief A {@link RasterOverlay} based on tile map service imagery. + */ +class CESIUMRASTEROVERLAYS_API TileMapServiceRasterOverlay final + : public RasterOverlay { +public: + /** + * @brief Creates a new instance. + * + * @param name The user-given name of this overlay layer. + * @param url The base URL. + * @param headers The headers. This is a list of pairs of strings of the + * form (Key,Value) that will be inserted as request headers internally. + * @param tmsOptions The {@link TileMapServiceRasterOverlayOptions}. + * @param overlayOptions The {@link RasterOverlayOptions} for this instance. + */ + TileMapServiceRasterOverlay( + const std::string& name, + const std::string& url, + const std::vector& headers = {}, + const TileMapServiceRasterOverlayOptions& tmsOptions = {}, + const RasterOverlayOptions& overlayOptions = {}); + virtual ~TileMapServiceRasterOverlay() override; + + virtual CesiumAsync::Future createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pCreditSystem, + const std::shared_ptr& + pPrepareRendererResources, + const std::shared_ptr& pLogger, + CesiumUtility::IntrusivePointer pOwner) + const override; + +private: + std::string _url; + std::vector _headers; + TileMapServiceRasterOverlayOptions _options; +}; + +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/WebMapServiceRasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/WebMapServiceRasterOverlay.h new file mode 100644 index 0000000..8a01d18 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/WebMapServiceRasterOverlay.h @@ -0,0 +1,107 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlay.h" + +#include +#include +#include +#include +#include + +#include + +namespace CesiumRasterOverlays { + +/** + * @brief Options for Web Map Service (WMS) overlays. + */ +struct WebMapServiceRasterOverlayOptions { + + /** + * @brief The Web Map Service version. The default is "1.3.0". + */ + std::string version = "1.3.0"; + + /** + * @brief Comma separated Web Map Service layer names to request. + */ + std::string layers; + + /** + * @brief The image format to request, expressed as a MIME type to be given to + * the server. The default is "image/png". + */ + std::string format = "image/png"; + + /** + * @brief A credit for the data source, which is displayed on the canvas. + */ + std::optional credit; + + /** + * @brief The minimum level-of-detail supported by the imagery provider. + * + * Take care when specifying this that the number of tiles at the minimum + * level is small, such as four or less. A larger number is likely to + * result in rendering problems. + */ + int32_t minimumLevel = 0; + + /** + * @brief The maximum level-of-detail supported by the imagery provider. + */ + int32_t maximumLevel = 14; + + /** + * @brief Pixel width of image tiles. + */ + int32_t tileWidth = 256; + + /** + * @brief Pixel height of image tiles. + */ + int32_t tileHeight = 256; +}; + +/** + * @brief A {@link RasterOverlay} accessing images from a Web Map Service (WMS) server. + */ +class CESIUMRASTEROVERLAYS_API WebMapServiceRasterOverlay final + : public RasterOverlay { +public: + /** + * @brief Creates a new instance. + * + * @param name The user-given name of this overlay layer. + * @param url The base URL. + * @param headers The headers. This is a list of pairs of strings of the + * form (Key,Value) that will be inserted as request headers internally. + * @param wmsOptions The {@link WebMapServiceRasterOverlayOptions}. + * @param overlayOptions The {@link RasterOverlayOptions} for this instance. + */ + WebMapServiceRasterOverlay( + const std::string& name, + const std::string& url, + const std::vector& headers = {}, + const WebMapServiceRasterOverlayOptions& wmsOptions = {}, + const RasterOverlayOptions& overlayOptions = {}); + virtual ~WebMapServiceRasterOverlay() override; + + virtual CesiumAsync::Future createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pCreditSystem, + const std::shared_ptr& + pPrepareRendererResources, + const std::shared_ptr& pLogger, + CesiumUtility::IntrusivePointer pOwner) + const override; + +private: + std::string _baseUrl; + std::vector _headers; + WebMapServiceRasterOverlayOptions _options; +}; + +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/WebMapTileServiceRasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/WebMapTileServiceRasterOverlay.h new file mode 100644 index 0000000..caeb2ca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumRasterOverlays/WebMapTileServiceRasterOverlay.h @@ -0,0 +1,159 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlay.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace CesiumRasterOverlays { + +/** + * @brief Options for {@link WebMapTileServiceRasterOverlay}. + */ +struct WebMapTileServiceRasterOverlayOptions { + + /** + * @brief The MIME type for images to retrieve from the server. + * + * Default value is "image/jpeg" + */ + std::optional format; + + /** + * @brief The subdomains to use for the {s} placeholder in the URL template. + * + * If this parameter is a single string, each character in the string is a + * subdomain. If it is an array, each element in the array is a subdomain. + */ + std::vector subdomains; + + /** + * @brief A credit for the data source, which is displayed on the canvas. + */ + std::optional credit; + + /** + * @brief The layer name for WMTS requests. + */ + std::string layer; + + /** + * @brief The style name for WMTS requests. + */ + std::string style; + + /** + * @brief The identifier of the TileMatrixSet to use for WMTS requests. + */ + std::string tileMatrixSetID; + + /** + * @brief A list of identifiers in the TileMatrix to use for WMTS requests, + * one per TileMatrix level. + */ + std::optional> tileMatrixLabels; + + /** + * @brief The minimum level-of-detail supported by the imagery provider. + * + * Take care when specifying this that the number of tiles at the minimum + * level is small, such as four or less. A larger number is likely to + * result in rendering problems. + * Default value is 0. + */ + std::optional minimumLevel; + + /** + * @brief The maximum level-of-detail supported by the imagery provider. + * + * Default value is 25. + */ + std::optional maximumLevel; + + /** + * @brief The {@link CesiumGeometry::Rectangle}, in radians, covered by the + * image. + */ + std::optional coverageRectangle; + + /** + * @brief The {@link CesiumGeospatial::Projection} that is used. + */ + std::optional projection; + + /** + * @brief The {@link CesiumGeometry::QuadtreeTilingScheme} specifying how + * the ellipsoidal surface is broken into tiles. + */ + std::optional tilingScheme; + + /** + * @brief A object containing static dimensions and their values. + */ + std::optional> dimensions; + + /** + * @brief Pixel width of image tiles. + * + * Default value is 256 + */ + std::optional tileWidth; + + /** + * @brief Pixel height of image tiles. + * + * Default value is 256 + */ + std::optional tileHeight; +}; + +/** + * @brief A {@link RasterOverlay} accessing images from a Web Map Tile Service + * (WMTS) server. + */ +class CESIUMRASTEROVERLAYS_API WebMapTileServiceRasterOverlay final + : public RasterOverlay { +public: + /** + * @brief Creates a new instance. + * + * @param name The user-given name of this overlay layer. + * @param url The base URL. + * @param headers The headers. This is a list of pairs of strings of the + * form (Key,Value) that will be inserted as request headers internally. + * @param tmsOptions The {@link WebMapTileServiceRasterOverlayOptions}. + * @param overlayOptions The {@link RasterOverlayOptions} for this instance. + */ + WebMapTileServiceRasterOverlay( + const std::string& name, + const std::string& url, + const std::vector& headers = {}, + const WebMapTileServiceRasterOverlayOptions& tmsOptions = {}, + const RasterOverlayOptions& overlayOptions = {}); + virtual ~WebMapTileServiceRasterOverlay() override; + + virtual CesiumAsync::Future createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr& pAssetAccessor, + const std::shared_ptr& pCreditSystem, + const std::shared_ptr& + pPrepareRendererResources, + const std::shared_ptr& pLogger, + CesiumUtility::IntrusivePointer pOwner) + const override; + +private: + std::string _url; + std::vector _headers; + WebMapTileServiceRasterOverlayOptions _options; +}; + +} // namespace CesiumRasterOverlays diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Assert.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Assert.h new file mode 100644 index 0000000..a567d3e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Assert.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +// +// Define our own assertion, so that users can forcebly turn them on if needed +// +#if defined CESIUM_FORCE_ASSERTIONS && defined NDEBUG +// Asserts are defined in cassert and normally compiled out when NDEBUG is +// defined. Redirect to our own assertion that can't be compiled out +namespace CesiumUtility { +std::int32_t forceAssertFailure(); +}; +#define CESIUM_ASSERT(expression) \ + ((expression) ? 0 : CesiumUtility::forceAssertFailure()) +#else +// Let assertions get defined with default behavior +#include +#define CESIUM_ASSERT(expression) assert(expression) +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/AttributeCompression.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/AttributeCompression.h new file mode 100644 index 0000000..1c468b8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/AttributeCompression.h @@ -0,0 +1,82 @@ +#pragma once + +#include "Library.h" +#include "Math.h" + +#include + +namespace CesiumUtility { +/** + * @brief Functions to handle compressed attributes in different formats + */ +class CESIUMUTILITY_API AttributeCompression final { + +public: + /** + * @brief Decodes a unit-length vector in 'oct' encoding to a normalized + * 3-component vector. + * + * @param x The x component of the oct-encoded unit length vector. + * @param y The y component of the oct-encoded unit length vector. + * @param rangeMax The maximum value of the SNORM range. The encoded vector is + * stored in log2(rangeMax+1) bits. + * @returns The decoded and normalized vector. + */ + template < + typename T, + class = typename std::enable_if::value>::type> + static glm::dvec3 octDecodeInRange(T x, T y, T rangeMax) { + glm::dvec3 result; + + result.x = CesiumUtility::Math::fromSNorm(x, rangeMax); + result.y = CesiumUtility::Math::fromSNorm(y, rangeMax); + result.z = 1.0 - (glm::abs(result.x) + glm::abs(result.y)); + + if (result.z < 0.0) { + const double oldVX = result.x; + result.x = + (1.0 - glm::abs(result.y)) * CesiumUtility::Math::signNotZero(oldVX); + result.y = + (1.0 - glm::abs(oldVX)) * CesiumUtility::Math::signNotZero(result.y); + } + + return glm::normalize(result); + } + + /** + * @brief Decodes a unit-length vector in 2 byte 'oct' encoding to a + * normalized 3-component vector. + * + * @param x The x component of the oct-encoded unit length vector. + * @param y The y component of the oct-encoded unit length vector. + * @returns The decoded and normalized vector. + * + * @see AttributeCompression::octDecodeInRange + */ + static glm::dvec3 octDecode(uint8_t x, uint8_t y) { + constexpr uint8_t rangeMax = 255; + return AttributeCompression::octDecodeInRange(x, y, rangeMax); + } + + /** + * @brief Decodes a RGB565-encoded color to a 3-component vector + * containing the normalized RGB values. + * + * @param value The RGB565-encoded value. + * @returns The normalized RGB values. + */ + static glm::dvec3 decodeRGB565(const uint16_t value) { + constexpr uint16_t mask5 = (1 << 5) - 1; + constexpr uint16_t mask6 = (1 << 6) - 1; + constexpr float normalize5 = 1.0f / 31.0f; // normalize [0, 31] to [0, 1] + constexpr float normalize6 = 1.0f / 63.0f; // normalize [0, 63] to [0, 1] + + const uint16_t red = static_cast(value >> 11); + const uint16_t green = static_cast((value >> 5) & mask6); + const uint16_t blue = value & mask5; + + return glm::dvec3(red * normalize5, green * normalize6, blue * normalize5); + }; +}; + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/CreditSystem.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/CreditSystem.h new file mode 100644 index 0000000..138a33c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/CreditSystem.h @@ -0,0 +1,114 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include +#include + +namespace CesiumUtility { + +/** + * @brief Represents an HTML string that should be shown on screen to attribute + * third parties for used data, imagery, etc. Acts as a handle into a + * {@link CreditSystem} object that actually holds the credit string. + */ +struct CESIUMUTILITY_API Credit { +public: + /** + * @brief Returns `true` if two credit objects have the same ID. + */ + bool operator==(const Credit& rhs) const noexcept { + return this->id == rhs.id; + } + +private: + size_t id; + + Credit(size_t id_) noexcept { id = id_; } + + friend class CreditSystem; +}; + +/** + * @brief Creates and manages {@link Credit} objects. Avoids repetitions and + * tracks which credits should be shown and which credits should be removed this + * frame. + */ +class CESIUMUTILITY_API CreditSystem final { +public: + /** + * @brief Inserts a credit string + * + * @return If this string already exists, returns a Credit handle to the + * existing entry. Otherwise returns a Credit handle to a new entry. + */ + Credit createCredit(std::string&& html, bool showOnScreen = false); + + /** + * @brief Inserts a credit string + * + * @return If this string already exists, returns a Credit handle to the + * existing entry. Otherwise returns a Credit handle to a new entry. + */ + Credit createCredit(const std::string& html, bool showOnScreen = false); + + /** + * @brief Gets whether or not the credit should be shown on screen. + */ + bool shouldBeShownOnScreen(Credit credit) const noexcept; + + /** + * @brief Sets whether or not the credit should be shown on screen. + */ + void setShowOnScreen(Credit credit, bool showOnScreen) noexcept; + + /** + * @brief Get the HTML string for this credit + */ + const std::string& getHtml(Credit credit) const noexcept; + + /** + * @brief Adds the Credit to the set of credits to show this frame + */ + void addCreditToFrame(Credit credit); + + /** + * @brief Notifies this CreditSystem to start tracking the credits to show for + * the next frame. + */ + void startNextFrame() noexcept; + + /** + * @brief Get the credits to show this frame. + */ + const std::vector& getCreditsToShowThisFrame() noexcept; + + /** + * @brief Get the credits that were shown last frame but should no longer be + * shown. + */ + const std::vector& + getCreditsToNoLongerShowThisFrame() const noexcept { + return _creditsToNoLongerShowThisFrame; + } + +private: + const std::string INVALID_CREDIT_MESSAGE = + "Error: Invalid Credit, cannot get HTML string."; + + struct HtmlAndLastFrameNumber { + std::string html; + bool showOnScreen; + int32_t lastFrameNumber; + int count; + }; + + std::vector _credits; + + int32_t _currentFrameNumber = 0; + std::vector _creditsToShowThisFrame; + std::vector _creditsToNoLongerShowThisFrame; +}; +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/DoublyLinkedList.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/DoublyLinkedList.h new file mode 100644 index 0000000..c0e8c50 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/DoublyLinkedList.h @@ -0,0 +1,274 @@ +#pragma once + +#include + +namespace CesiumUtility { + +/** + * @brief Contains the previous and next pointers for an element in + * a {@link DoublyLinkedList}. + */ +template class DoublyLinkedListPointers final { +public: + /** + * @brief Default constructor. + */ + DoublyLinkedListPointers() noexcept : pNext(nullptr), pPrevious(nullptr) {} + + /** + * @brief Copy constructor. + * + * @param rhs The other instance. + */ + // Following the example of boost::instrusive::list's list_member_hook, the + // copy constructor and assignment operator do nothing. + // https://www.boost.org/doc/libs/1_73_0/doc/html/boost/intrusive/list_member_hook.html + DoublyLinkedListPointers( + [[maybe_unused]] DoublyLinkedListPointers& rhs) noexcept + : DoublyLinkedListPointers() {} + + /** + * @brief Assignment operator. + */ + DoublyLinkedListPointers& + operator=(const DoublyLinkedListPointers& /*rhs*/) noexcept { + return *this; + } + +private: + template < + typename TElement, + typename TElementBase, + DoublyLinkedListPointers(TElementBase::*Pointers)> + friend class DoublyLinkedListAdvanced; + + T* pNext; + T* pPrevious; +}; + +/** + * @brief A doubly-linked list. + * + * In this implementation, the previous and next pointers are embedded directly + * in the data object. + * + * @tparam T The data object type. + * @tparam (T::*Pointers) A member pointer to the field that holds the links to + * the previous and next nodes. + */ +template < + typename T, + typename TPointerBase, + DoublyLinkedListPointers(TPointerBase::*Pointers)> +class DoublyLinkedListAdvanced final { +public: + /** + * @brief Removes the given node from this list. + */ + void remove(T& node) noexcept { + DoublyLinkedListPointers& nodePointers = node.*Pointers; + + if (nodePointers.pPrevious) { + DoublyLinkedListPointers& previousPointers = + nodePointers.pPrevious->*Pointers; + previousPointers.pNext = nodePointers.pNext; + --this->_size; + } else if (this->_pHead == &node) { + this->_pHead = nodePointers.pNext; + --this->_size; + } + + if (nodePointers.pNext) { + DoublyLinkedListPointers& nextPointers = nodePointers.pNext->*Pointers; + nextPointers.pPrevious = nodePointers.pPrevious; + } else if (this->_pTail == &node) { + this->_pTail = nodePointers.pPrevious; + } + + nodePointers.pPrevious = nullptr; + nodePointers.pNext = nullptr; + } + + /** + * @brief Insert the given node after the other node. + */ + void insertAfter(T& after, T& node) noexcept { + this->remove(node); + + DoublyLinkedListPointers& afterPointers = after.*Pointers; + DoublyLinkedListPointers& nodePointers = node.*Pointers; + + nodePointers.pPrevious = &after; + nodePointers.pNext = afterPointers.pNext; + afterPointers.pNext = &node; + + if (nodePointers.pNext) { + DoublyLinkedListPointers& nextPointers = nodePointers.pNext->*Pointers; + nextPointers.pPrevious = &node; + } + + if (this->_pTail == &after) { + this->_pTail = &node; + } + + ++this->_size; + } + + /** + * @brief Insert the given node before the other node. + */ + void insertBefore(T& before, T& node) noexcept { + this->remove(node); + + DoublyLinkedListPointers& beforePointers = before.*Pointers; + DoublyLinkedListPointers& nodePointers = node.*Pointers; + + nodePointers.pPrevious = beforePointers.pPrevious; + nodePointers.pNext = &before; + beforePointers.pPrevious = &node; + + if (nodePointers.pPrevious) { + DoublyLinkedListPointers& previousPointers = + nodePointers.pPrevious->*Pointers; + previousPointers.pNext = &node; + } + + if (this->_pHead == &before) { + this->_pHead = &node; + } + + ++this->_size; + } + + /** + * @brief Insert the given node as the new head of the list. + */ + void insertAtHead(T& node) noexcept { + this->remove(node); + + if (this->_pHead) { + (this->_pHead->*Pointers).pPrevious = &node; + (node.*Pointers).pNext = this->_pHead; + } else { + this->_pTail = &node; + } + this->_pHead = &node; + + ++this->_size; + } + + /** + * @brief Insert the given node as the new tail of the list. + */ + void insertAtTail(T& node) noexcept { + this->remove(node); + + if (this->_pTail) { + (this->_pTail->*Pointers).pNext = &node; + (node.*Pointers).pPrevious = this->_pTail; + } else { + this->_pHead = &node; + } + this->_pTail = &node; + + ++this->_size; + } + + /** + * @brief Returns the size of this list. + */ + size_t size() const noexcept { return this->_size; } + + /** + * @brief Returns the head node of this list, or `nullptr` if the list is + * empty. + */ + T* head() noexcept { return this->_pHead; } + + /** @copydoc DoublyLinkedList::head() */ + const T* head() const noexcept { return this->_pHead; } + + /** + * @brief Returns the tail node of this list, or `nullptr` if the list is + * empty. + */ + T* tail() noexcept { return this->_pTail; } + + /** @copydoc DoublyLinkedList::tail() */ + const T* tail() const noexcept { return this->_pTail; } + + /** + * @brief Returns the next node after the given one, or `nullptr` if the given + * node is the tail. + */ + T* next(T& node) noexcept { return (node.*Pointers).pNext; } + + /** @copydoc DoublyLinkedList::next(T&) */ + const T* next(const T& node) const noexcept { return (node.*Pointers).pNext; } + + /** + * @brief Returns the next node after the given one, or the head if the given + * node is `nullptr`. + */ + T* next(T* pNode) noexcept { + return pNode ? this->next(*pNode) : this->_pHead; + } + + /** @copydoc DoublyLinkedList::next(T*) */ + const T* next(const T* pNode) const noexcept { + return pNode ? this->next(*pNode) : this->_pHead; + } + + /** + * @brief Returns the previous node before the given one, or `nullptr` if the + * given node is the head. + */ + T* previous(T& node) noexcept { return (node.*Pointers).pPrevious; } + + /** @copydoc DoublyLinkedList::previous(T&) */ + const T* previous(const T& node) const noexcept { + return (node.*Pointers).pPrevious; + } + + /** + * @brief Returns the previous node before the given one, or the tail if the + * given node is `nullptr`. + */ + T* previous(T* pNode) { + return pNode ? this->previous(*pNode) : this->_pTail; + } + + /** @copydoc DoublyLinkedList::previous(T*) */ + const T* previous(const T* pNode) const noexcept { + return pNode ? this->previous(*pNode) : this->_pTail; + } + + /** + * @brief Determines if this list contains a given node in constant time. In + * order to avoid a full list scan, this method assumes that if the node has + * any next or previous node, then it is contained in this list. Do not use + * this method to determine which of multiple lists contain this node. + * + * @param node The node to check. + * @return True if this node is the head of the list, or if the node has next + * or previous nodes. False if the node does not have next or previous nodes + * and it is not the head of this list. + */ + bool contains(const T& node) const { + return this->next(node) != nullptr || this->previous(node) != nullptr || + this->_pHead == &node; + } + +private: + size_t _size = 0; + T* _pHead = nullptr; + T* _pTail = nullptr; +}; + +/** + * @brief An intrusive doubly-linked list. + */ +template (T::*Pointers)> +using DoublyLinkedList = DoublyLinkedListAdvanced; + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ErrorList.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ErrorList.h new file mode 100644 index 0000000..12a21e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ErrorList.h @@ -0,0 +1,127 @@ +#pragma once + +#include "Library.h" +#include "joinToString.h" + +#include + +#include +#include + +namespace CesiumUtility { + +/** + * @brief The container to store the error and warning list when loading a tile + * or glTF content + */ +struct CESIUMUTILITY_API ErrorList { + /** + * @brief Creates an {@link ErrorList} containing a single error. + * + * @param errorMessage The error message. + * @return The new list containing the single error. + */ + static ErrorList error(std::string errorMessage); + + /** + * @brief Creates an {@link ErrorList} containing a single warning. + * + * @param warningMessage The warning message. + * @return The new list containing the single warning. + */ + static ErrorList warning(std::string warningMessage); + + /** + * @brief Merge the errors and warnings from other ErrorList together + * + * @param errorList The other instance of ErrorList that will be merged with + * the current instance. + */ + void merge(const ErrorList& errorList); + + /** + * @brief Merge the errors and warnings from other ErrorList together + * + * @param errorList The other instance of ErrorList that will be merged with + * the current instance. + */ + void merge(ErrorList&& errorList); + + /** + * @brief Add an error message + * + * @param error The error message to be added. + */ + template void emplaceError(ErrorStr&& error) { + errors.emplace_back(std::forward(error)); + } + + /** + * @brief Add a warning message + * + * @param warning The warning message to be added. + */ + template void emplaceWarning(WarningStr&& warning) { + warnings.emplace_back(std::forward(warning)); + } + + /** + * @brief Check if there are any error messages. + */ + bool hasErrors() const noexcept; + + /** + * @brief Log all the error messages. + * + * @param pLogger The logger to log the messages + * @param prompt The message prompt for the error messages. + */ + template + void logError( + const std::shared_ptr& pLogger, + PromptStr&& prompt) const noexcept { + if (!errors.empty()) { + SPDLOG_LOGGER_ERROR( + pLogger, + "{}:\n- {}", + std::forward(prompt), + CesiumUtility::joinToString(errors, "\n- ")); + } + } + + /** + * @brief Log all the warning messages + * + * @param pLogger The logger to log the messages + * @param prompt The message prompt for the warning messages. + */ + template + void logWarning( + const std::shared_ptr& pLogger, + PromptStr&& prompt) const noexcept { + if (!warnings.empty()) { + SPDLOG_LOGGER_WARN( + pLogger, + "{}:\n- {}", + std::forward(prompt), + CesiumUtility::joinToString(warnings, "\n- ")); + } + } + + /** + * @brief Check if there are any error messages. + */ + explicit operator bool() const noexcept; + + /** + * @brief The error messages of this container + */ + std::vector errors; + + /** + * @brief The warning messages of this container + */ + std::vector warnings; +}; + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ExtensibleObject.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ExtensibleObject.h new file mode 100644 index 0000000..c307181 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ExtensibleObject.h @@ -0,0 +1,149 @@ +#pragma once + +#include "JsonValue.h" +#include "Library.h" + +#include +#include +#include +#include + +namespace CesiumUtility { +/** + * @brief The base class for objects that have extensions and extras. + */ +struct CESIUMUTILITY_API ExtensibleObject { + /** + * @brief Checks if an extension exists given its static type. + * + * @tparam T The type of the extension. + * @return A boolean indicating whether the extension exists. + */ + template bool hasExtension() const noexcept { + auto it = this->extensions.find(T::ExtensionName); + return it != this->extensions.end(); + } + + /** + * @brief Gets an extension given its static type. + * + * @tparam T The type of the extension. + * @return A pointer to the extension, or nullptr if the extension is not + * attached to this object. + */ + template const T* getExtension() const noexcept { + auto it = this->extensions.find(T::ExtensionName); + if (it == this->extensions.end()) { + return nullptr; + } + + return std::any_cast(&it->second); + } + + /** @copydoc ExtensibleObject::getExtension */ + template T* getExtension() noexcept { + return const_cast(std::as_const(*this).getExtension()); + } + + /** + * @brief Gets a generic extension with the given name as a + * {@link CesiumUtility::JsonValue}. + * + * If the extension exists but has a static type, this method will return + * nullptr. Use {@link getExtension} to retrieve a statically-typed extension. + * + * @param extensionName The name of the extension. + * @return The generic extension, or nullptr if the generic extension doesn't + * exist. + */ + const JsonValue* + getGenericExtension(const std::string& extensionName) const noexcept; + + /** @copydoc ExtensibleObject::getGenericExtension */ + JsonValue* getGenericExtension(const std::string& extensionName) noexcept; + + /** + * @brief Adds a statically-typed extension to this object. + * + * If the extension already exists, the existing one is returned. + * + * @tparam T The type of the extension to add. + * @return The added extension. + */ + template + T& addExtension(ConstructorArgumentTypes&&... constructorArguments) { + std::any& extension = + extensions + .try_emplace( + T::ExtensionName, + std::make_any(std::forward( + constructorArguments)...)) + .first->second; + return std::any_cast(extension); + } + + /** + * @brief Removes a statically-typed extension from this object. + * + * @tparam T The type of the extension to remove. + */ + template void removeExtension() { + extensions.erase(T::ExtensionName); + } + + /** + * @brief The extensions attached to this object. + * + * Use {@link getExtension} to get the extension with a particular static + * type. Use {@link getGenericExtension} to get unknown extensions as a + * generic {@link CesiumUtility::JsonValue}. + */ + std::unordered_map extensions; + + /** + * @brief Application-specific data. + * + * **Implementation Note:** Although extras may have any type, it is common + * for applications to store and access custom data as key/value pairs. As + * best practice, extras should be an Object rather than a primitive value for + * best portability. + */ + JsonValue::Object extras; + + /** + * @brief Unknown properties that exist on this object but do not have any + * representation in the statically-typed classes. + * + * These properties may be invalid, or they may represent deprecated, + * experimental, or next-version properties. + */ + JsonValue::Object unknownProperties; + + /** + * @brief Calculates the size in bytes of this ExtensibleObject, including all + * of its extras but NOT including its extensions. Calling this method may be + * slow as it requires traversing the entire object. + */ + int64_t getSizeBytes() const { + int64_t accum = 0; + accum += int64_t(sizeof(ExtensibleObject)); + + accum += int64_t( + this->extras.size() * (sizeof(std::string) + sizeof(JsonValue))); + for (const auto& [k, v] : this->extras) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - int64_t(sizeof(JsonValue)); + } + + accum += int64_t( + this->unknownProperties.size() * + (sizeof(std::string) + sizeof(JsonValue))); + for (const auto& [k, v] : this->unknownProperties) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - int64_t(sizeof(JsonValue)); + } + + return accum; + } +}; +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Gzip.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Gzip.h new file mode 100644 index 0000000..6a2ccc7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Gzip.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include + +namespace CesiumUtility { + +/** + * @brief Checks whether the data is gzipped. + * + * @param data The data. + * + * @returns Whether the data is gzipped + */ +bool isGzip(const std::span& data); + +/** + * @brief Gzips data. + * + * If successful, it will return true and the result will be in the + * provided vector. + * + * @param data The data to gzip. + * @param out The gzipped data. + * + * @returns True if successful, false otherwise. + */ +bool gzip(const std::span& data, std::vector& out); + +/** + * @brief Gunzips data. + * + * If successful, it will return true and the result will be in the + * provided vector. + * + * @param data The data to gunzip. + * @param out The gunzipped data. + * + * @returns True if successful, false otherwise. + */ +bool gunzip( + const std::span& data, + std::vector& out); + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Hash.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Hash.h new file mode 100644 index 0000000..950d2ca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Hash.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +namespace CesiumUtility { + +/** + * @brief Contains functions for working with hashes. + * + */ +struct Hash { + /** + * @brief Combines two hash values, usually generated using `std::hash`, to + * form a single hash value. + * + * @param first The first hash value. + * @param second The second hash value. + * @return A new hash value which is a combination of the two. + */ + static std::size_t combine(std::size_t first, std::size_t second); +}; + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/IDepotOwningAsset.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/IDepotOwningAsset.h new file mode 100644 index 0000000..b5a43c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/IDepotOwningAsset.h @@ -0,0 +1,43 @@ +#pragma once + +namespace CesiumUtility { + +/** + * @brief An interface representing the depot that owns a {@link SharedAsset}. + * This interface is an implementation detail of the shared asset system and + * should not be used directly. + * + * {@link SharedAsset} has a pointer to the asset depot that owns it using this + * interface, rather than a complete {@link CesiumAsync::SharedAssetDepot}, in + * order to "erase" the type of the asset key. This allows SharedAsset to be + * templatized only on the asset type, not on the asset key type. + */ +template class IDepotOwningAsset { +public: + virtual ~IDepotOwningAsset() {} + + /** + * @brief Marks the given asset as a candidate for deletion. + * Should only be called by {@link SharedAsset}. May be called from any thread. + * + * @param asset The asset to mark for deletion. + * @param threadOwnsDepotLock True if the calling thread already owns the + * depot lock; otherwise, false. + */ + virtual void + markDeletionCandidate(const TAssetType& asset, bool threadOwnsDepotLock) = 0; + + /** + * @brief Unmarks the given asset as a candidate for deletion. + * Should only be called by {@link SharedAsset}. May be called from any thread. + * + * @param asset The asset to unmark for deletion. + * @param threadOwnsDepotLock True if the calling thread already owns the + * depot lock; otherwise, false. + */ + virtual void unmarkDeletionCandidate( + const TAssetType& asset, + bool threadOwnsDepotLock) = 0; +}; + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/IntrusivePointer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/IntrusivePointer.h new file mode 100644 index 0000000..fc5114c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/IntrusivePointer.h @@ -0,0 +1,241 @@ +#pragma once +#include +#include + +namespace CesiumUtility { + +/** + * @brief A smart pointer that calls `addReference` and `releaseReference` on + * the controlled object. + * + * Please note that the thread-safety of this type is entirely dependent on the + * implementation of `addReference` and `releaseReference`. If these methods are + * not thread safe on a particular type - which is common for objects that are + * not meant to be used from multiple threads simultaneously - then using an + * `IntrusivePointer` from multiple threads is also unsafe. + * + * @tparam T The type of object controlled. + */ +template class IntrusivePointer final { +public: + /** + * @brief Default constructor. + */ + IntrusivePointer(T* p = nullptr) noexcept : _p(p) { this->addReference(); } + + /** + * @brief Copy constructor. + */ + IntrusivePointer(const IntrusivePointer& rhs) noexcept : _p(rhs._p) { + this->addReference(); + } + + /** + * @brief Implicit conversion to a pointer to a base (or otherwise + * convertible) type. + * + * @tparam U The new type, usually a base class. + * @param rhs The pointer. + */ + template + IntrusivePointer(const IntrusivePointer& rhs) noexcept : _p(rhs._p) { + this->addReference(); + } + + /** + * @brief Move constructor. + */ + IntrusivePointer(IntrusivePointer&& rhs) noexcept + : _p(std::exchange(rhs._p, nullptr)) { + // Reference count is unchanged + } + + /** + * @brief Implicit conversion of an r-value to a pointer to a base (or + * otherwise convertible) type. + * + * @tparam U The new type, usually a base class. + * @param rhs The pointer. + */ + template + IntrusivePointer(IntrusivePointer&& rhs) noexcept + : _p(std::exchange(rhs._p, nullptr)) { + // Reference count is unchanged + } + + /** + * @brief Default destructor. + */ + ~IntrusivePointer() noexcept { this->releaseReference(); } + + /** + * @brief Constructs a new instance and assigns it to this IntrusivePointer. + * If this IntrusivePointer already points to another instance, + * {@link releaseReference} is called on it. + * + * @param constructorArguments The arguments to the constructor to create the + * new instance. + * @return A reference to the newly-created instance. + */ + template + T& emplace(ConstructorArgumentTypes&&... constructorArguments) { + *this = + new T(std::forward(constructorArguments)...); + return *this->get(); + } + + /** + * @brief Reset this pointer to nullptr. + */ + void reset() { *this = nullptr; } + + /** + * @brief Assignment operator. + */ + IntrusivePointer& operator=(const IntrusivePointer& rhs) noexcept { + if (this->_p != rhs._p) { + // addReference the new pointer before releaseReference'ing the old. + T* pOld = this->_p; + this->_p = rhs._p; + addReference(); + + if (pOld) { + pOld->releaseReference(); + } + } + + return *this; + } + + /** + * @brief Assigns an \ref IntrusivePointer of another type to this \ref + * IntrusivePointer. + */ + template + IntrusivePointer& operator=(const IntrusivePointer& rhs) noexcept { + if (this->_p != rhs._p) { + // addReference the new pointer before releaseReference'ing the old. + T* pOld = this->_p; + this->_p = rhs._p; + addReference(); + + if (pOld) { + pOld->releaseReference(); + } + } + + return *this; + } + + /** + * @brief Move assignment operator. + */ + IntrusivePointer& operator=(IntrusivePointer&& rhs) noexcept { + if (this->_p != rhs._p) { + std::swap(this->_p, rhs._p); + } + + return *this; + } + + /** + * @brief Assignment operator. + */ + IntrusivePointer& operator=(T* p) noexcept { + if (this->_p != p) { + // addReference the new pointer before releaseReference'ing the old. + T* pOld = this->_p; + this->_p = p; + addReference(); + + if (pOld) { + pOld->releaseReference(); + } + } + + return *this; + } + + /** + * @brief Dereferencing operator. + */ + T& operator*() const noexcept { return *this->_p; } + + /** + * @brief Arrow operator. + */ + T* operator->() const noexcept { return this->_p; } + + /** + * @brief Implicit conversion to `bool`, being `true` iff this is not the + * `nullptr`. + */ + explicit operator bool() const noexcept { return this->_p != nullptr; } + + /** + * @brief Returns the internal pointer. + */ + T* get() const noexcept { return this->_p; } + + /** + * @brief Returns `true` if two pointers are equal. + */ + bool operator==(const IntrusivePointer& rhs) const noexcept { + return this->_p == rhs._p; + } + + /** @brief Returns `true` if two pointers are equal. */ + template + bool operator==(const IntrusivePointer& rhs) const noexcept { + return this->_p == rhs._p; + } + + /** + * @brief Returns `true` if two pointers are *not* equal. + */ + bool operator!=(const IntrusivePointer& rhs) const noexcept { + return !(*this == rhs); + } + + /** + * @brief Returns `true` if the contents of this pointer is equal to the given + * pointer. + */ + bool operator==(const T* pRhs) const noexcept { return this->_p == pRhs; } + + /** + * @brief Returns `true` if the contents of this pointer is *not* equal to the + * given pointer. + */ + bool operator!=(const T* pRhs) const noexcept { return !(*this == pRhs); } + +private: + void addReference() noexcept { + if (this->_p) { + this->_p->addReference(); + } + } + + void releaseReference() noexcept { + if (this->_p) { + this->_p->releaseReference(); + } + } + + T* _p; + template friend class IntrusivePointer; +}; + +/** + * @brief Casts a `const` \ref IntrusivePointer to its non-const equivalent. + * + * @param p The `const` \ref IntrusivePointer. + * @returns A non-const \ref IntrusivePointer with the same underlying pointer. + */ +template +IntrusivePointer +const_intrusive_cast(const IntrusivePointer& p) noexcept { + return IntrusivePointer(const_cast(p.get())); +} + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/JsonHelpers.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/JsonHelpers.h new file mode 100644 index 0000000..f5ea452 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/JsonHelpers.h @@ -0,0 +1,246 @@ +#pragma once + +#include +#include + +#include +#include +#include + +namespace CesiumUtility { + +/** + * @brief A collection of helper functions to make reading JSON simpler. + */ +class JsonHelpers final { +public: + /** + * @brief Attempts to read the value at `key` of `tileJson` as a `double`, + * returning std::nullopt if it wasn't found or couldn't be read as a double. + * + * @param tileJson The JSON object to obtain the scalar property from. + * @param key The key of the scalar property to obtain. + */ + static std::optional + getScalarProperty(const rapidjson::Value& tileJson, const std::string& key); + /** + * @brief Attempts to read the value at `key` of `tileJson` as a + * `glm::dmat4x4`, returning std::nullopt if it wasn't found or couldn't be + * read as a glm::dmat4x4. + * + * @param tileJson The JSON object to obtain the transform property from. + * @param key The key of the transform property. + */ + static std::optional getTransformProperty( + const rapidjson::Value& tileJson, + const std::string& key); + + /** + * @brief Obtains an array of numbers from the given JSON. + * + * If the property is not found, or is not an array, or does contain + * elements that are not numbers, then `std::nullopt` is returned. + * + * If the given expected size is not negative, and the actual size of the + * array does not match the expected size, then `nullopt` is returned. + * + * @param json The JSON object. + * @param expectedSize The expected size of the array. + * @param key The key (property name) of the array. + * @return The array, or `nullopt`. + */ + static std::optional> getDoubles( + const rapidjson::Value& json, + int32_t expectedSize, + const std::string& key); + + /** + * @brief Attempts to obtain a string from the given key on the JSON object, + * returning a default value if this isn't possible. + * + * @param json The JSON object. + * @param key The key (property name) of the string. + * @param defaultValue The default value to return if the string property + * `key` of `json` couldn't be read. + */ + static std::string getStringOrDefault( + const rapidjson::Value& json, + const std::string& key, + const std::string& defaultValue); + /** + * @brief Attempts to read `json` as a string, returning a default value if + * this isn't possible. + * + * @param json The JSON value that might be a string. + * @param defaultValue The default value to return if `json` couldn't be read + * as a string. + */ + static std::string getStringOrDefault( + const rapidjson::Value& json, + const std::string& defaultValue); + + /** + * @brief Attempts to obtain a double from the given key on the JSON object, + * returning a default value if this isn't possible. + * + * @param json The JSON object. + * @param key The key (property name) of the double. + * @param defaultValue The default value to return if the double property + * `key` of `json` couldn't be read. + */ + static double getDoubleOrDefault( + const rapidjson::Value& json, + const std::string& key, + double defaultValue); + /** + * @brief Attempts to read `json` as a double, returning a default value if + * this isn't possible. + * + * @param json The JSON value that might be a double. + * @param defaultValue The default value to return if `json` couldn't be read + * as a double. + */ + static double + getDoubleOrDefault(const rapidjson::Value& json, double defaultValue); + + /** + * @brief Attempts to obtain a uint32_t from the given key on the JSON object, + * returning a default value if this isn't possible. + * + * @param json The JSON object. + * @param key The key (property name) of the uint32_t. + * @param defaultValue The default value to return if the uint32_t property + * `key` of `json` couldn't be read. + */ + static uint32_t getUint32OrDefault( + const rapidjson::Value& json, + const std::string& key, + uint32_t defaultValue); + /** + * @brief Attempts to read `json` as a uint32_t, returning a default value if + * this isn't possible. + * + * @param json The JSON value that might be a uint32_t. + * @param defaultValue The default value to return if `json` couldn't be read + * as a uint32_t. + */ + static uint32_t + getUint32OrDefault(const rapidjson::Value& json, uint32_t defaultValue); + + /** + * @brief Attempts to obtain a int32_t from the given key on the JSON object, + * returning a default value if this isn't possible. + * + * @param json The JSON object. + * @param key The key (property name) of the int32_t. + * @param defaultValue The default value to return if the int32_t property + * `key` of `json` couldn't be read. + */ + static int32_t getInt32OrDefault( + const rapidjson::Value& json, + const std::string& key, + int32_t defaultValue); + /** + * @brief Attempts to read `json` as a int32_t, returning a default value if + * this isn't possible. + * + * @param json The JSON value that might be a int32_t. + * @param defaultValue The default value to return if `json` couldn't be read + * as a int32_t. + */ + static int32_t + getInt32OrDefault(const rapidjson::Value& json, int32_t defaultValue); + + /** + * @brief Attempts to obtain a uint64_t from the given key on the JSON object, + * returning a default value if this isn't possible. + * + * @param json The JSON object. + * @param key The key (property name) of the uint64_t. + * @param defaultValue The default value to return if the uint64_t property + * `key` of `json` couldn't be read. + */ + static uint64_t getUint64OrDefault( + const rapidjson::Value& json, + const std::string& key, + uint64_t defaultValue); + /** + * @brief Attempts to read `json` as a uint64_t, returning a default value if + * this isn't possible. + * + * @param json The JSON value that might be a uint64_t. + * @param defaultValue The default value to return if `json` couldn't be read + * as a uint64_t. + */ + static uint64_t + getUint64OrDefault(const rapidjson::Value& json, uint64_t defaultValue); + + /** + * @brief Attempts to obtain a int64_t from the given key on the JSON object, + * returning a default value if this isn't possible. + * + * @param json The JSON object. + * @param key The key (property name) of the int64_t. + * @param defaultValue The default value to return if the int64_t property + * `key` of `json` couldn't be read. + */ + static int64_t getInt64OrDefault( + const rapidjson::Value& json, + const std::string& key, + int64_t defaultValue); + /** + * @brief Attempts to read `json` as a int64_t, returning a default value if + * this isn't possible. + * + * @param json The JSON value that might be a int64_t. + * @param defaultValue The default value to return if `json` couldn't be read + * as a int64_t. + */ + static int64_t + getInt64OrDefault(const rapidjson::Value& json, int64_t defaultValue); + + /** + * @brief Attempts to obtain a bool from the given key on the JSON object, + * returning a default value if this isn't possible. + * + * @param json The JSON object. + * @param key The key (property name) of the bool. + * @param defaultValue The default value to return if the bool property + * `key` of `json` couldn't be read. + */ + static bool getBoolOrDefault( + const rapidjson::Value& json, + const std::string& key, + bool defaultValue); + /** + * @brief Attempts to read `json` as a bool, returning a default value if + * this isn't possible. + * + * @param json The JSON value that might be a bool. + * @param defaultValue The default value to return if `json` couldn't be read + * as a bool. + */ + static bool getBoolOrDefault(const rapidjson::Value& json, bool defaultValue); + + /** + * @brief Attempts to read an array of strings from the property `key` of + * `json`, returning an empty vector if this isn't possible. + * + * @param json The JSON object. + * @param key The key (property name) of the string array. + */ + static std::vector + getStrings(const rapidjson::Value& json, const std::string& key); + + /** + * @brief Attempts to read an int64_t array from the property `key` of + * `json`, returning an empty vector if this isn't possible. + * + * @param json The JSON object. + * @param key The key (property name) of the int64_t array. + */ + static std::vector + getInt64s(const rapidjson::Value& json, const std::string& key); +}; + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/JsonValue.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/JsonValue.h new file mode 100644 index 0000000..3adca37 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/JsonValue.h @@ -0,0 +1,712 @@ +#pragma once + +#include "Library.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace CesiumUtility { + +/** + * @brief Attempts a narrowing conversion of `U` into `T` without losing + * information. If a lossless conversion can't be performed, `std::nullopt` is + * returned. + * + * @tparam U The type to convert from. + * @tparam T The type to convert to. + * @param u The value to perform the conversion on. + */ +template +constexpr std::optional losslessNarrow(U u) noexcept { + constexpr const bool is_different_signedness = + (std::is_signed::value != std::is_signed::value); + + const T t = static_cast(u); + + if (static_cast(t) != u || + (is_different_signedness && ((t < T{}) != (u < U{})))) { + return std::nullopt; + } + + return t; +} + +/** + * @brief Attempts a narrowing conversion of `U` into `T` without losing + * information. If a lossless conversion can't be performed, `defaultValue` is + * returned. + * + * @tparam U The type to convert from. + * @tparam T The type to convert to. + * @param u The value to perform the conversion on. + * @param defaultValue The value that will be returned if a lossless conversion + * can't be performed. + */ +template +constexpr T losslessNarrowOrDefault(U u, T defaultValue) noexcept { + constexpr const bool is_different_signedness = + (std::is_signed::value != std::is_signed::value); + + const T t = static_cast(u); + + if (static_cast(t) != u || + (is_different_signedness && ((t < T{}) != (u < U{})))) { + return defaultValue; + } + + return t; +} + +/** + * @brief A generic implementation of a value in a JSON structure. + * + * Instances of this class are used to represent the common `extras` field + * of glTF elements that extend the the {@link ExtensibleObject} class. + */ +class CESIUMUTILITY_API JsonValue final { +public: + /** + * @brief The type to represent a `null` JSON value. + */ + using Null = std::nullptr_t; + + /** + * @brief The type to represent a `Bool` JSON value. + */ + using Bool = bool; + + /** + * @brief The type to represent a `String` JSON value. + */ + using String = std::string; + + /** + * @brief The type to represent an `Object` JSON value. + */ + using Object = std::map; + + /** + * @brief The type to represent an `Array` JSON value. + */ + using Array = std::vector; + + /** + * @brief Default constructor. + */ + JsonValue() noexcept : value() {} + + /** + * @brief Creates a `null` JSON value. + */ + JsonValue(std::nullptr_t) noexcept : value(nullptr) {} + + /** + * @brief Creates a `Number` JSON value. + * + * NaN and ±Infinity are represented as {@link JsonValue::Null}. + */ + JsonValue(double v) noexcept { + if (std::isnan(v) || std::isinf(v)) { + value = nullptr; + } else { + value = v; + } + } + + /** + * @brief Creates a `std::int64_t` JSON value (Widening conversion from + * std::int8_t). + */ + JsonValue(std::int8_t v) noexcept : value(static_cast(v)) {} + + /** + * @brief Creates a `std::uint64_t` JSON value (Widening conversion from + * std::uint8_t). + */ + JsonValue(std::uint8_t v) noexcept : value(static_cast(v)) {} + + /** + * @brief Creates a `std::int64_t` JSON value (Widening conversion from + * std::int16_t). + */ + JsonValue(std::int16_t v) noexcept : value(static_cast(v)) {} + + /** + * @brief Creates a `std::uint64_t` JSON value (Widening conversion from + * std::uint16_t). + */ + JsonValue(std::uint16_t v) noexcept : value(static_cast(v)) {} + + /** + * @brief Creates a `std::int64_t` JSON value (Widening conversion from + * std::int32_t). + */ + JsonValue(std::int32_t v) noexcept : value(static_cast(v)) {} + + /** + * @brief Creates a `std::uint64_t` JSON value (Widening conversion from + * std::uint32_t). + */ + JsonValue(std::uint32_t v) noexcept : value(static_cast(v)) {} + + /** + * @brief Creates a `std::int64_t` JSON value. + */ + JsonValue(std::int64_t v) noexcept : value(v) {} + + /** + * @brief Creates a `std::uint64_t` JSON value. + */ + JsonValue(std::uint64_t v) noexcept : value(v) {} + + /** + * @brief Creates a `Bool` JSON value. + */ + JsonValue(bool v) noexcept : value(v) {} + + /** + * @brief Creates a `String` JSON value. + */ + JsonValue(const std::string& v) : value(v) {} + + /** + * @brief Creates a `String` JSON value. + */ + JsonValue(std::string&& v) noexcept : value(std::move(v)) {} + + /** + * @brief Creates a `String` JSON value. + */ + JsonValue(const char* v) : value(std::string(v)) {} + + /** + * @brief Creates an `Object` JSON value with the given properties. + */ + JsonValue(const std::map& v) : value(v) {} + + /** + * @brief Creates an `Object` JSON value with the given properties. + */ + JsonValue(std::map&& v) : value(std::move(v)) {} + + /** + * @brief Creates an `Array` JSON value with the given elements. + */ + JsonValue(const std::vector& v) : value(v) {} + + /** + * @brief Creates an `Array` JSON value with the given elements. + */ + JsonValue(std::vector&& v) noexcept : value(std::move(v)) {} + + /** + * @brief Creates an JSON value from the given initializer list. + */ + JsonValue(std::initializer_list v) + : value(std::vector(v)) {} + + /** + * @brief Creates an JSON value from the given initializer list. + */ + JsonValue(std::initializer_list> v) + : value(std::map(v)) {} + + /** + * @brief Attempts to obtain a pointer to a \ref JsonValue for the given key + * on this object. + * + * @param key The key to lookup. + * @returns A pointer to the \ref JsonValue for the provided key, or + * `nullptr`. + */ + [[nodiscard]] const JsonValue* + getValuePtrForKey(const std::string& key) const; + /** @copydoc getValuePtrForKey */ + [[nodiscard]] JsonValue* getValuePtrForKey(const std::string& key); + + /** + * @brief Gets a typed value corresponding to the given key in the + * object represented by this instance. + * + * If this instance is not a {@link JsonValue::Object}, returns + * `nullptr`. If the key does not exist in this object, returns + * `nullptr`. If the named value does not have the type T, returns + * nullptr. + * + * @tparam T The expected type of the value. + * @param key The key for which to retrieve the value from this object. + * @return A pointer to the requested value, or nullptr if the value + * cannot be obtained as requested. + */ + template + const T* getValuePtrForKey(const std::string& key) const { + const JsonValue* pValue = this->getValuePtrForKey(key); + if (!pValue) { + return nullptr; + } + + return std::get_if(&pValue->value); + } + + /** + * @brief Gets a typed value corresponding to the given key in the + * object represented by this instance. + * + * If this instance is not a {@link JsonValue::Object}, returns + * `nullptr`. If the key does not exist in this object, returns + * `nullptr`. If the named value does not have the type T, returns + * nullptr. + * + * @tparam T The expected type of the value. + * @param key The key for which to retrieve the value from this object. + * @return A pointer to the requested value, or nullptr if the value + * cannot be obtained as requested. + */ + template T* getValuePtrForKey(const std::string& key) { + JsonValue* pValue = this->getValuePtrForKey(key); + return std::get_if(&pValue->value); + } + + /** + * @brief Converts the numerical value corresponding to the given key + * to the provided numerical template type. + + * If this instance is not a {@link JsonValue::Object}, the key does not exist + * in this object, the named value does not have a numerical type, or if the + * named value cannot be converted from `double` / `std::uint64_t` / + * `std::int64_t` without precision loss, returns `std::nullopt`. + * @tparam To The expected type of the value. + * @param key The key for which to retrieve the value from this object. + * @return The converted value, or std::nullopt if it cannot be converted for + * any of the previously-mentioned reasons. + * @remarks Compilation will fail if type 'To' is not an integral / float / + * double type. + */ + template < + typename To, + typename std::enable_if< + std::is_integral::value || + std::is_floating_point::value>::type* = nullptr> + [[nodiscard]] std::optional + getSafeNumericalValueForKey(const std::string& key) const { + const Object& pObject = std::get(this->value); + const auto it = pObject.find(key); + if (it == pObject.end()) { + return std::nullopt; + } + return it->second.getSafeNumber(); + } + + /** + * @brief Converts the numerical value corresponding to the given key + * to the provided numerical template type. + * + * If this instance is not a {@link JsonValue::Object}, the key does not exist + * in this object, or the named value does not have a numerical type that can + * be represented as T without precision loss, then the default value is + * returned. + * + * @tparam To The expected type of the value. + * @param key The key for which to retrieve the value from this object. + * @param defaultValue The value that will be returned if a numerical value + * can't be obtained. + * @return The converted value. + * @throws If unable to convert the converted value for one of the + * aforementioned reasons. + * @remarks Compilation will fail if type 'To' is not an integral / float / + * double type. + */ + template < + typename To, + typename std::enable_if< + std::is_integral::value || + std::is_floating_point::value>::type* = nullptr> + [[nodiscard]] To getSafeNumericalValueOrDefaultForKey( + const std::string& key, + To defaultValue) const { + const Object& pObject = std::get(this->value); + const auto it = pObject.find(key); + if (it == pObject.end()) { + return defaultValue; + } + return it->second.getSafeNumberOrDefault(defaultValue); + } + + /** + * @brief Determines if this value is an Object and has the given key. + * + * @param key The key. + * @return true if this value contains the key. false if it is not an object + * or does not contain the given key. + */ + [[nodiscard]] inline bool hasKey(const std::string& key) const { + const Object* pObject = std::get_if(&this->value); + if (!pObject) { + return false; + } + + return pObject->find(key) != pObject->end(); + } + + /** + * @brief Gets the numerical quantity from the value casted to the `To` + * type. This function should be used over `getDouble()` / `getUint64()` / + * `getInt64()` if you plan on casting that type into another smaller type or + * different type. + * @returns The converted type if it is numerical and it can be cast without + * precision loss; otherwise, std::nullopt. + */ + template < + typename To, + typename std::enable_if< + std::is_integral::value || + std::is_floating_point::value>::type* = nullptr> + [[nodiscard]] std::optional getSafeNumber() const { + const std::uint64_t* uInt = std::get_if(&this->value); + if (uInt) { + return losslessNarrow(*uInt); + } + + const std::int64_t* sInt = std::get_if(&this->value); + if (sInt) { + return losslessNarrow(*sInt); + } + + const double* real = std::get_if(&this->value); + if (real) { + return losslessNarrow(*real); + } + + return std::nullopt; + } + + /** + * @brief Gets the numerical quantity from the value casted to the `To` + * type or returns defaultValue if unable to do so. + + * @returns The converted type if it can be cast without precision loss + * or `defaultValue` if it cannot be converted safely. + */ + template < + typename To, + typename std::enable_if< + std::is_integral::value || + std::is_floating_point::value>::type* = nullptr> + [[nodiscard]] To getSafeNumberOrDefault(To defaultValue) const noexcept { + const std::uint64_t* uInt = std::get_if(&this->value); + if (uInt) { + return losslessNarrowOrDefault(*uInt, defaultValue); + } + + const std::int64_t* sInt = std::get_if(&this->value); + if (sInt) { + return losslessNarrowOrDefault(*sInt, defaultValue); + } + + const double* real = std::get_if(&this->value); + if (real) { + return losslessNarrowOrDefault(*real, defaultValue); + } + + return defaultValue; + } + + /** + * @brief Gets the object from the value. + * @return The object. + * @throws std::bad_variant_access if the underlying type is not a + * JsonValue::Object + */ + + [[nodiscard]] inline const JsonValue::Object& getObject() const { + return std::get(this->value); + } + + /** + * @brief Gets the string from the value. + * @return The string. + * @throws std::bad_variant_access if the underlying type is not a + * JsonValue::String + */ + [[nodiscard]] inline const JsonValue::String& getString() const { + return std::get(this->value); + } + + /** + * @brief Gets the array from the value. + * @return The array. + * @throws std::bad_variant_access if the underlying type is not a + * JsonValue::Array + */ + [[nodiscard]] inline const JsonValue::Array& getArray() const { + return std::get(this->value); + } + + /** + * @brief Gets an array of strings from the value. + * + * @param defaultString The default string to include in the array for an + * element that is not a string. + * @return The array of strings, or an empty array if this value is not an + * array at all. + */ + [[nodiscard]] std::vector + getArrayOfStrings(const std::string& defaultString) const; + + /** + * @brief Gets the bool from the value. + * @return The bool. + * @throws std::bad_variant_access if the underlying type is not a + * JsonValue::Bool + */ + [[nodiscard]] inline bool getBool() const { + return std::get(this->value); + } + + /** + * @brief Gets the double from the value. + * @return The double. + * @throws std::bad_variant_access if the underlying type is not a double + */ + [[nodiscard]] inline double getDouble() const { + return std::get(this->value); + } + + /** + * @brief Gets the std::uint64_t from the value. + * @return The std::uint64_t. + * @throws std::bad_variant_access if the underlying type is not a + * std::uint64_t + */ + [[nodiscard]] std::uint64_t getUint64() const { + return std::get(this->value); + } + + /** + * @brief Gets the std::int64_t from the value. + * @return The std::int64_t. + * @throws std::bad_variant_access if the underlying type is not a + * std::int64_t + */ + [[nodiscard]] std::int64_t getInt64() const { + return std::get(this->value); + } + + /** + * @brief Gets the bool from the value or returns defaultValue + * @return The bool or defaultValue if this->value is not a bool. + */ + [[nodiscard]] inline bool getBoolOrDefault(bool defaultValue) const noexcept { + const auto* v = std::get_if(&this->value); + if (v) { + return *v; + } + + return defaultValue; + } + + /** + * @brief Gets the string from the value or returns defaultValue + * @return The string or defaultValue if this->value is not a string. + */ + [[nodiscard]] inline const JsonValue::String + getStringOrDefault(String defaultValue) const { + const auto* v = std::get_if(&this->value); + if (v) { + return *v; + } + + return defaultValue; + } + + /** + * @brief Gets the double from the value or returns defaultValue + * @return The double or defaultValue if this->value is not a double. + */ + [[nodiscard]] inline double + getDoubleOrDefault(double defaultValue) const noexcept { + const auto* v = std::get_if(&this->value); + if (v) { + return *v; + } + + return defaultValue; + } + + /** + * @brief Gets the uint64_t from the value or returns defaultValue + * @return The uint64_t or defaultValue if this->value is not a uint64_t. + */ + [[nodiscard]] inline std::uint64_t + getUint64OrDefault(std::uint64_t defaultValue) const noexcept { + const auto* v = std::get_if(&this->value); + if (v) { + return *v; + } + + return defaultValue; + } + + /** + * @brief Gets the int64_t from the value or returns defaultValue + * @return The int64_t or defaultValue if this->value is not a int64_t. + */ + [[nodiscard]] inline std::int64_t + getInt64OrDefault(std::int64_t defaultValue) const noexcept { + const auto* v = std::get_if(&this->value); + if (v) { + return *v; + } + + return defaultValue; + } + + /** + * @brief Returns whether this value is a `null` value. + */ + [[nodiscard]] inline bool isNull() const noexcept { + return std::holds_alternative(this->value); + } + + /** + * @brief Returns whether this value is a `double`, `std::uint64_t` or + * `std::int64_t`. Use this function in conjunction with `getNumber` for + * safely casting to arbitrary types + */ + [[nodiscard]] inline bool isNumber() const noexcept { + return isDouble() || isUint64() || isInt64(); + } + + /** + * @brief Returns whether this value is a `Bool` value. + */ + [[nodiscard]] inline bool isBool() const noexcept { + return std::holds_alternative(this->value); + } + + /** + * @brief Returns whether this value is a `String` value. + */ + [[nodiscard]] inline bool isString() const noexcept { + return std::holds_alternative(this->value); + } + + /** + * @brief Returns whether this value is an `Object` value. + */ + [[nodiscard]] inline bool isObject() const noexcept { + return std::holds_alternative(this->value); + } + + /** + * @brief Returns whether this value is an `Array` value. + */ + [[nodiscard]] inline bool isArray() const noexcept { + return std::holds_alternative(this->value); + } + + /** + * @brief Returns whether this value is a `double` value. + */ + [[nodiscard]] inline bool isDouble() const noexcept { + return std::holds_alternative(this->value); + } + + /** + * @brief Returns whether this value is a `std::uint64_t` value. + */ + [[nodiscard]] inline bool isUint64() const noexcept { + return std::holds_alternative(this->value); + } + + /** + * @brief Returns whether this value is a `std::int64_t` value. + */ + [[nodiscard]] inline bool isInt64() const noexcept { + return std::holds_alternative(this->value); + } + + /** + * @brief Returns `true` if two values are equal. + */ + inline bool operator==(const JsonValue& rhs) const noexcept { + return this->value == rhs.value; + }; + + /** + * @brief Returns the size in bytes of this `JsonValue`. + */ + int64_t getSizeBytes() const noexcept { + struct Operation { + int64_t operator()([[maybe_unused]] const Null& /*inside*/) { return 0; } + int64_t operator()([[maybe_unused]] const double& /*inside*/) { + return 0; + } + int64_t operator()([[maybe_unused]] const std::uint64_t& /*inside*/) { + return 0; + } + int64_t operator()([[maybe_unused]] const std::int64_t& /*inside*/) { + return 0; + } + int64_t operator()([[maybe_unused]] const Bool& /*inside*/) { return 0; } + int64_t operator()(const String& inside) { + return int64_t(inside.capacity() * sizeof(char)); + } + int64_t operator()(const Object& inside) { + int64_t accum = 0; + accum += + int64_t(inside.size() * (sizeof(std::string) + sizeof(JsonValue))); + for (const auto& [k, v] : inside) { + accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string)); + accum += v.getSizeBytes() - int64_t(sizeof(JsonValue)); + } + + return accum; + } + int64_t operator()(const Array& inside) { + int64_t accum = 0; + accum += int64_t(sizeof(JsonValue) * inside.capacity()); + for (const JsonValue& v : inside) { + accum += v.getSizeBytes() - int64_t(sizeof(JsonValue)); + } + return accum; + } + }; + + return static_cast(sizeof(JsonValue)) + + std::visit(Operation{}, this->value); + } + + /** + * @brief The actual value. + * + * The type of the value may be queried with the `isNull`, `isDouble`, + * `isBool`, `isString`, `isObject`, `isUint64`, `isInt64`, `isNumber`, and + * `isArray` functions. + * + * The actual value may be obtained with the `getNumber`, `getBool`, + * and `getString` functions for the respective types. For + * `Object` values, the properties may be accessed with the + * `getValueForKey` functions. + */ + std::variant< + Null, + double, + std::uint64_t, + std::int64_t, + Bool, + String, + Object, + Array> + value; +}; +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Library.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Library.h new file mode 100644 index 0000000..509c5cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Library.h @@ -0,0 +1,18 @@ +#pragma once + +/** + * @brief Utility classes for Cesium + * + * @mermaid-interactive{dependencies/CesiumUtility} + */ +namespace CesiumUtility {} + +#if defined(_WIN32) && defined(CESIUM_SHARED) +#ifdef CESIUMUTILITY_BUILDING +#define CESIUMUTILITY_API __declspec(dllexport) +#else +#define CESIUMUTILITY_API __declspec(dllimport) +#endif +#else +#define CESIUMUTILITY_API +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Log.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Log.h new file mode 100644 index 0000000..19fddc5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Log.h @@ -0,0 +1,73 @@ +#pragma once +#include +#include + +/** @cond Doxygen_Exclude */ +template <> +struct fmt::formatter : formatter { + // parse is inherited from formatter. + + auto format(rapidjson::ParseErrorCode code, format_context& ctx) const { + string_view name = "unknown"; + switch (code) { + case rapidjson::ParseErrorCode::kParseErrorNone: + name = "No error."; + break; + case rapidjson::ParseErrorCode::kParseErrorDocumentEmpty: + name = "The document is empty."; + break; + case rapidjson::ParseErrorCode::kParseErrorDocumentRootNotSingular: + name = "The document root must not follow by other values."; + break; + case rapidjson::ParseErrorCode::kParseErrorValueInvalid: + name = "Invalid value."; + break; + case rapidjson::ParseErrorCode::kParseErrorObjectMissName: + name = "Missing a name for object member."; + break; + case rapidjson::ParseErrorCode::kParseErrorObjectMissColon: + name = "Missing a colon after a name of object member."; + break; + case rapidjson::ParseErrorCode::kParseErrorObjectMissCommaOrCurlyBracket: + name = "Missing a comma or '}' after an object member."; + break; + case rapidjson::ParseErrorCode::kParseErrorArrayMissCommaOrSquareBracket: + name = "Missing a comma or ']' after an array element."; + break; + case rapidjson::ParseErrorCode::kParseErrorStringUnicodeEscapeInvalidHex: + name = "Incorrect hex digit after \\u escape in string."; + break; + case rapidjson::ParseErrorCode::kParseErrorStringUnicodeSurrogateInvalid: + name = "The surrogate pair in string is invalid."; + break; + case rapidjson::ParseErrorCode::kParseErrorStringEscapeInvalid: + name = "Invalid escape character in string."; + break; + case rapidjson::ParseErrorCode::kParseErrorStringMissQuotationMark: + name = "Missing a closing quotation mark in string."; + break; + case rapidjson::ParseErrorCode::kParseErrorStringInvalidEncoding: + name = "Invalid encoding in string."; + break; + case rapidjson::ParseErrorCode::kParseErrorNumberTooBig: + name = "Number too big to be stored in double."; + break; + case rapidjson::ParseErrorCode::kParseErrorNumberMissFraction: + name = "Miss fraction part in number."; + break; + case rapidjson::ParseErrorCode::kParseErrorNumberMissExponent: + name = "Miss exponent in number."; + break; + case rapidjson::ParseErrorCode::kParseErrorTermination: + name = "Parsing was terminated."; + break; + case rapidjson::ParseErrorCode::kParseErrorUnspecificSyntaxError: + name = "Unspecific syntax error."; + break; + default: + break; + } + return formatter::format(name, ctx); + } +}; +/** @endcond */ \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Math.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Math.h new file mode 100644 index 0000000..ded8212 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Math.h @@ -0,0 +1,503 @@ +#pragma once + +#include "Library.h" + +#include + +namespace CesiumUtility { + +/** + * @brief Mathematical constants and functions + */ +class CESIUMUTILITY_API Math final { +public: + /** @brief 0.1 */ + static constexpr double Epsilon1 = 1e-1; + + /** @brief 0.01 */ + static constexpr double Epsilon2 = 1e-2; + + /** @brief 0.001 */ + static constexpr double Epsilon3 = 1e-3; + + /** @brief 0.0001 */ + static constexpr double Epsilon4 = 1e-4; + + /** @brief 0.00001 */ + static constexpr double Epsilon5 = 1e-5; + + /** @brief 0.000001 */ + static constexpr double Epsilon6 = 1e-6; + + /** @brief 0.0000001 */ + static constexpr double Epsilon7 = 1e-7; + + /** @brief 0.00000001 */ + static constexpr double Epsilon8 = 1e-8; + + /** @brief 0.000000001 */ + static constexpr double Epsilon9 = 1e-9; + + /** @brief 0.0000000001 */ + static constexpr double Epsilon10 = 1e-10; + + /** @brief 0.00000000001 */ + static constexpr double Epsilon11 = 1e-11; + + /** @brief 0.000000000001 */ + static constexpr double Epsilon12 = 1e-12; + + /** @brief 0.0000000000001 */ + static constexpr double Epsilon13 = 1e-13; + + /** @brief 0.00000000000001 */ + static constexpr double Epsilon14 = 1e-14; + + /** @brief 0.000000000000001 */ + static constexpr double Epsilon15 = 1e-15; + + /** @brief 0.0000000000000001 */ + static constexpr double Epsilon16 = 1e-16; + + /** @brief 0.00000000000000001 */ + static constexpr double Epsilon17 = 1e-17; + + /** @brief 0.000000000000000001 */ + static constexpr double Epsilon18 = 1e-18; + + /** @brief 0.0000000000000000001 */ + static constexpr double Epsilon19 = 1e-19; + + /** @brief 0.00000000000000000001 */ + static constexpr double Epsilon20 = 1e-20; + + /** @brief 0.000000000000000000001 */ + static constexpr double Epsilon21 = 1e-21; + + /** + * @brief pi + */ + static constexpr double OnePi = 3.14159265358979323846; + + /** + * @brief two times pi + */ + static constexpr double TwoPi = OnePi * 2.0; + + /** + * @brief pi divded by two + */ + static constexpr double PiOverTwo = OnePi / 2.0; + + /** + * @brief Converts a relative to an absolute epsilon, for the epsilon-equality + * check between two values. + * + * @tparam L The length type. + * @tparam T value value type. + * @tparam Q The GLM qualifier type. + * + * @param a The first value. + * @param b The second value. + * @param relativeEpsilon The relative epsilon. + * @return The absolute epsilon. + */ + template + static constexpr glm::vec relativeEpsilonToAbsolute( + const glm::vec& a, + const glm::vec& b, + double relativeEpsilon) noexcept { + return relativeEpsilon * glm::max(glm::abs(a), glm::abs(b)); + } + + /** + * @brief Converts a relative to an absolute epsilon, for the epsilon-equality + * check between two values. + * + * @param a The first value. + * @param b The second value. + * @param relativeEpsilon The relative epsilon. + * @return The absolute epsilon. + */ + static constexpr double relativeEpsilonToAbsolute( + double a, + double b, + double relativeEpsilon) noexcept { + return relativeEpsilon * glm::max(glm::abs(a), glm::abs(b)); + } + + /** + * @brief Checks whether two values are equal up to a given relative epsilon. + * + * @tparam L The length type. + * @tparam T value value type. + * @tparam Q The GLM qualifier type. + * + * @param left The first value. + * @param right The second value. + * @param relativeEpsilon The relative epsilon. + * @return Whether the values are epsilon-equal + */ + template + static bool constexpr equalsEpsilon( + const glm::vec& left, + const glm::vec& right, + double relativeEpsilon) noexcept { + return Math::equalsEpsilon(left, right, relativeEpsilon, relativeEpsilon); + } + + /** + * @brief Checks whether two values are equal up to a given relative epsilon. + * + * @param left The first value. + * @param right The second value. + * @param relativeEpsilon The relative epsilon. + * @return Whether the values are epsilon-equal + */ + static constexpr bool + equalsEpsilon(double left, double right, double relativeEpsilon) noexcept { + return equalsEpsilon(left, right, relativeEpsilon, relativeEpsilon); + } + + /** + * @brief Determines if two values are equal using an absolute or relative + * tolerance test. + * + * This is useful to avoid problems due to roundoff error when comparing + * floating-point values directly. The values are first compared using an + * absolute tolerance test. If that fails, a relative tolerance test is + * performed. Use this test if you are unsure of the magnitudes of left and + * right. + * + * @param left The first value to compare. + * @param right The other value to compare. + * @param relativeEpsilon The maximum inclusive delta between `left` and + * `right` for the relative tolerance test. + * @param absoluteEpsilon The maximum inclusive delta between `left` and + * `right` for the absolute tolerance test. + * @returns `true` if the values are equal within the epsilon; otherwise, + * `false`. + * + * @snippet TestMath.cpp equalsEpsilon + */ + static constexpr bool equalsEpsilon( + double left, + double right, + double relativeEpsilon, + double absoluteEpsilon) noexcept { + const double diff = glm::abs(left - right); + return diff <= absoluteEpsilon || + diff <= relativeEpsilonToAbsolute(left, right, relativeEpsilon); + } + + /** + * @brief Determines if two values are equal using an absolute or relative + * tolerance test. + * + * This is useful to avoid problems due to roundoff error when comparing + * floating-point values directly. The values are first compared using an + * absolute tolerance test. If that fails, a relative tolerance test is + * performed. Use this test if you are unsure of the magnitudes of left and + * right. + * + * @tparam L The length type. + * @tparam T value value type. + * @tparam Q The GLM qualifier type. + * + * @param left The first value to compare. + * @param right The other value to compare. + * @param relativeEpsilon The maximum inclusive delta between `left` and + * `right` for the relative tolerance test. + * @param absoluteEpsilon The maximum inclusive delta between `left` and + * `right` for the absolute tolerance test. + * @returns `true` if the values are equal within the epsilon; otherwise, + * `false`. + */ + template + static constexpr bool equalsEpsilon( + const glm::vec& left, + const glm::vec& right, + double relativeEpsilon, + double absoluteEpsilon) noexcept { + const glm::vec diff = glm::abs(left - right); + return glm::lessThanEqual(diff, glm::vec(absoluteEpsilon)) == + glm::vec(true) || + glm::lessThanEqual( + diff, + relativeEpsilonToAbsolute(left, right, relativeEpsilon)) == + glm::vec(true); + } + + /** + * @brief Returns the sign of the value. + * + * This is 1 if the value is positive, -1 if the value is + * negative, or 0 if the value is 0. + * + * @param value The value to return the sign of. + * @returns The sign of value. + */ + static constexpr double sign(double value) noexcept { + if (value == 0.0 || value != value) { + // zero or NaN + return value; + } + return value > 0 ? 1 : -1; + } + + /** + * @brief Returns 1.0 if the given value is positive or zero, and -1.0 if it + * is negative. + * + * This is similar to {@link Math::sign} except that returns 1.0 instead of + * 0.0 when the input value is 0.0. + * + * @param value The value to return the sign of. + * @returns The sign of value. + */ + static constexpr double signNotZero(double value) noexcept { + return value < 0.0 ? -1.0 : 1.0; + } + + /** + * @brief Produces an angle in the range -Pi <= angle <= Pi which is + * equivalent to the provided angle. + * + * @param angle The angle in radians. + * @returns The angle in the range [`-Math::OnePi`, `Math::OnePi`]. + */ + static double negativePiToPi(double angle) noexcept { + if (angle >= -Math::OnePi && angle <= Math::OnePi) { + // Early exit if the input is already inside the range. This avoids + // unnecessary math which could introduce floating point error. + return angle; + } + return Math::zeroToTwoPi(angle + Math::OnePi) - Math::OnePi; + } + + /** + * @brief Produces an angle in the range 0 <= angle <= 2Pi which is equivalent + * to the provided angle. + * + * @param angle The angle in radians. + * @returns The angle in the range [0, `Math::TwoPi`]. + */ + static double zeroToTwoPi(double angle) noexcept { + if (angle >= 0 && angle <= Math::TwoPi) { + // Early exit if the input is already inside the range. This avoids + // unnecessary math which could introduce floating point error. + return angle; + } + const double mod = Math::mod(angle, Math::TwoPi); + if (glm::abs(mod) < Math::Epsilon14 && glm::abs(angle) > Math::Epsilon14) { + return Math::TwoPi; + } + return mod; + } + + /** + * @brief The modulo operation that also works for negative dividends. + * + * @param m The dividend. + * @param n The divisor. + * @returns The remainder. + */ + static double mod(double m, double n) noexcept { + if (Math::sign(m) == Math::sign(n) && glm::abs(m) < glm::abs(n)) { + // Early exit if the input does not need to be modded. This avoids + // unnecessary math which could introduce floating point error. + return m; + } + return fmod(fmod(m, n) + n, n); + } + + /** + * @brief Converts degrees to radians. + * + * @param angleDegrees The angle to convert in degrees. + * @returns The corresponding angle in radians. + */ + static constexpr double degreesToRadians(double angleDegrees) noexcept { + return angleDegrees * Math::OnePi / 180.0; + } + + /** + * @brief Converts radians to degrees. + * + * @param angleRadians The angle to convert in radians. + * @returns The corresponding angle in degrees. + */ + static constexpr double radiansToDegrees(double angleRadians) noexcept { + return angleRadians * 180.0 / Math::OnePi; + } + + /** + * @brief Computes the linear interpolation of two values. + * + * @param p The start value to interpolate. + * @param q The end value to interpolate. + * @param time The time of interpolation generally in the range `[0.0, 1.0]`. + * @returns The linearly interpolated value. + * + * @snippet TestMath.cpp lerp + */ + static double lerp(double p, double q, double time) noexcept { + return glm::mix(p, q, time); + } + + /** + * @brief Constrain a value to lie between two values. + * + * @param value The value to constrain. + * @param min The minimum value. + * @param max The maximum value. + * @returns The value clamped so that min <= value <= max. + */ + static constexpr double clamp(double value, double min, double max) noexcept { + return glm::clamp(value, min, max); + }; + + /** + * @brief Converts a scalar value in the range [-1.0, 1.0] to a SNORM in the + * range [0, rangeMaximum] + * + * @param value The scalar value in the range [-1.0, 1.0]. + * @param rangeMaximum The maximum value in the mapped range, 255 by default. + * @returns A SNORM value, where 0 maps to -1.0 and rangeMaximum maps to 1.0. + * + * @see Math::fromSNorm + */ + static double toSNorm(double value, double rangeMaximum = 255.0) noexcept { + return glm::round( + (Math::clamp(value, -1.0, 1.0) * 0.5 + 0.5) * rangeMaximum); + }; + /** + * @brief Converts a SNORM value in the range [0, rangeMaximum] to a scalar in + * the range [-1.0, 1.0]. + * + * @param value SNORM value in the range [0, rangeMaximum]. + * @param rangeMaximum The maximum value in the SNORM range, 255 by default. + * @returns Scalar in the range [-1.0, 1.0]. + * + * @see Math::toSNorm + */ + static constexpr double + fromSNorm(double value, double rangeMaximum = 255.0) noexcept { + return (Math::clamp(value, 0.0, rangeMaximum) / rangeMaximum) * 2.0 - 1.0; + } + + /** + * Converts a longitude value, in radians, to the range [`-Math::OnePi`, + * `Math::OnePi`). + * + * @param angle The longitude value, in radians, to convert to the range + * [`-Math::OnePi`, `Math::OnePi`). + * @returns The equivalent longitude value in the range [`-Math::OnePi`, + * `Math::OnePi`). + * + * @snippet TestMath.cpp convertLongitudeRange + */ + static double convertLongitudeRange(double angle) noexcept { + constexpr double twoPi = Math::TwoPi; + + const double simplified = angle - glm::floor(angle / twoPi) * twoPi; + + if (simplified < -Math::OnePi) { + return simplified + twoPi; + } + if (simplified >= Math::OnePi) { + return simplified - twoPi; + } + + return simplified; + }; + + /** + * @brief Rounds a value up to the nearest integer, like `ceil`, except + * that if the value is very close to the lower integer it is rounded down + * (like `floor`) instead. + * + * @param value The value to round. + * @param tolerance The tolerance. If the value is closer than this to the + * lower integer, it is rounded down instead. + * @return The rounded value. + */ + static double roundUp(double value, double tolerance) noexcept { + const double up = glm::ceil(value); + const double down = glm::floor(value); + if (value - down < tolerance) { + return down; + } else { + return up; + } + } + + /** + * @brief Rounds a value down to the nearest integer, like `floor`, except + * that if the value is very close to the higher integer it is rounded up + * (like `ceil`) instead. + * + * @param value The value to round. + * @param tolerance The tolerance. If the value is closer than this to the + * higher integer, it is rounded up instead. + * @return The rounded value. + */ + static double roundDown(double value, double tolerance) noexcept { + const double up = glm::ceil(value); + const double down = glm::floor(value); + if (up - value < tolerance) { + return up; + } else { + return down; + } + } + + /** + * @brief Construct a vector perpendicular to the argument. + * @param v The input vector + * @return A vector perpendicular to the input vector + */ + template + static glm::vec<3, T, Q> perpVec(const glm::vec<3, T, Q>& v) { + // This constructs a vector whose dot product with v will be 0, hence + // perpendicular to v. As seen in the "Physically Based Rendering". + if (std::abs(v.x) > std::abs(v.y)) { + return glm::vec<3, T, Q>(-v.z, 0, v.x) / std::sqrt(v.x * v.x + v.z * v.z); + } + return glm::vec<3, T, Q>(0, v.z, -v.y) / std::sqrt(v.y * v.y + v.z * v.z); + } + + /** @brief Compute the rotation between two unit vectors. + * @param vec1 The first vector. + * @param vec2 The second vector. + * @return A quaternion representing the rotation of vec1 to vec2. + */ + template + static glm::qua + rotation(const glm::vec<3, T, Q>& vec1, const glm::vec<3, T, Q>& vec2) { + // If we take the dot and cross products of the two vectors and store + // them in a quaternion, that quaternion represents twice the required + // rotation. We get the correct quaternion by "averaging" with the zero + // rotation quaternion, in a way analagous to finding the half vector + // between two 3D vectors. + auto cosRot = dot(vec1, vec2); + auto rotAxis = cross(vec1, vec2); + auto rotAxisLen2 = dot(rotAxis, rotAxis); + // Not using epsilon for these tests. If abs(cosRot) < 1.0, we can still + // create a sensible rotation. + if (cosRot >= 1 || (rotAxisLen2 == 0 && cosRot > 0)) { + // zero rotation + return glm::qua(1, 0, 0, 0); + } + if (cosRot <= -1 || (rotAxisLen2 == 0 && cosRot < 0)) { + auto perpAxis = CesiumUtility::Math::perpVec(vec1); + // rotation by pi radians + return glm::qua(0, perpAxis); + } + + glm::qua sumQuat(cosRot + 1, rotAxis); + return normalize(sumQuat); + } +}; + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ReferenceCounted.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ReferenceCounted.h new file mode 100644 index 0000000..b25bb42 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ReferenceCounted.h @@ -0,0 +1,136 @@ +#pragma once + +#include + +#include +#include + +#ifndef NDEBUG +#include +#endif + +namespace CesiumUtility { + +/** \cond Doxygen_Suppress */ +#ifndef NDEBUG +template class ThreadIdHolder; + +template <> class ThreadIdHolder { + ThreadIdHolder() : _threadID(std::this_thread::get_id()) {} + + std::thread::id _threadID; + + template friend class ReferenceCounted; +}; + +template <> class ThreadIdHolder {}; +#endif +/** \endcond */ + +/** + * @brief A reference-counted base class, meant to be used with + * {@link IntrusivePointer}. + * + * Consider using {@link ReferenceCountedThreadSafe} or + * {@link ReferenceCountedNonThreadSafe} instead of using this class directly. + * + * @tparam T The type that is _deriving_ from this class. For example, you + * should declare your class as + * `class MyClass : public ReferenceCounted { ... };` + * @tparam isThreadSafe If `true`, the reference count will be thread-safe by + * using `std::atomic`, allowing references to safely be added and removed from + * any thread at any time. The object will be destroyed in the thread that + * releases the last reference. If false, it uses a simple integer for the + * reference count, which is not thread safe. In this case, references must be + * added and removed (including automatically via `IntrusivePointer`) from only + * one thread at a time. However, this mode has a bit less overhead for objects + * that are only ever accessed from a single thread. + */ +template +class ReferenceCounted +#ifndef NDEBUG + : public ThreadIdHolder +#endif +{ +public: + ReferenceCounted() noexcept {} + ~ReferenceCounted() noexcept { CESIUM_ASSERT(this->_referenceCount == 0); } + + /** + * @brief Adds a counted reference to this object. Use + * {@link CesiumUtility::IntrusivePointer} instead of calling this method + * directly. + */ + void addReference() const /*noexcept*/ { +#ifndef NDEBUG + if constexpr (!isThreadSafe) { + CESIUM_ASSERT(std::this_thread::get_id() == this->_threadID); + } +#endif + + ++this->_referenceCount; + } + + /** + * @brief Removes a counted reference from this object. When the last + * reference is removed, this method will delete this instance. Use + * {@link CesiumUtility::IntrusivePointer} instead of calling this method + * directly. + */ + void releaseReference() const /*noexcept*/ { +#ifndef NDEBUG + if constexpr (!isThreadSafe) { + CESIUM_ASSERT(std::this_thread::get_id() == this->_threadID); + } +#endif + + CESIUM_ASSERT(this->_referenceCount > 0); + const int32_t references = --this->_referenceCount; + if (references == 0) { + delete static_cast(this); + } + } + + /** + * @brief Returns the current reference count of this instance. + */ + std::int32_t getReferenceCount() const noexcept { + return this->_referenceCount; + } + +private: + using ThreadSafeCounter = std::atomic; + using NonThreadSafeCounter = std::int32_t; + using CounterType = + std::conditional_t; + + mutable CounterType _referenceCount{0}; +}; + +/** + * @brief A reference-counted base class, meant to be used with + * {@link IntrusivePointer}. The reference count is thread-safe, so references + * may be added and removed from any thread at any time. The object will be + * destroyed in the thread that releases the last reference. + * + * @tparam T The type that is _deriving_ from this class. For example, you + * should declare your class as + * `class MyClass : public ReferenceCountedThreadSafe { ... };` + */ +template +using ReferenceCountedThreadSafe = ReferenceCounted; + +/** + * @brief A reference-counted base class, meant to be used with + * {@link IntrusivePointer}. The reference count is not thread-safe, so + * references must be added and removed (including automatically via + * `IntrusivePointer`) from only one thread at a time. + * + * @tparam T The type that is _deriving_ from this class. For example, you + * should declare your class as + * `class MyClass : public ReferenceCountedNonThreadSafe { ... };` + */ +template +using ReferenceCountedNonThreadSafe = ReferenceCounted; + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Result.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Result.h new file mode 100644 index 0000000..20ab356 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Result.h @@ -0,0 +1,124 @@ +#pragma once + +#include +#include + +#include + +namespace CesiumUtility { + +/** + * @brief Holds the result of an operation. If the operation succeeds, it will + * provide a value. It may also provide errors and warnings. + * + * @tparam T The type of value included in the result. + */ +template struct Result { + /** + * @brief Creates a `Result` with the given value and an empty \ref ErrorList. + * + * @param value_ The value that will be contained in this `Result`. + */ + Result(T value_) noexcept : value(std::move(value_)), errors() {} + + /** + * @brief Creates a `Result` with the given value and \ref ErrorList. + * + * @param value_ The value that will be contained in this `Result`. + * @param errors_ The \ref ErrorList containing errors and warnings related to + * this `Result`. + */ + Result(T value_, ErrorList errors_) noexcept + : value(std::move(value_)), errors(std::move(errors_)) {} + + /** + * @brief Creates a `Result` with an empty value and the given \ref ErrorList. + * + * @param errors_ The \ref ErrorList containing errors and warnings related to + * this `Result`. + */ + Result(ErrorList errors_) noexcept : value(), errors(std::move(errors_)) {} + + /** + * @brief The value, if the operation succeeded to the point where it can + * provide one. + * + * If a value is not provided because the operation failed, then there should + * be at least one error in {@link errors} indicating what went wrong. + */ + std::optional value; + + /** + * @brief The errors and warnings that occurred during the operation. + * + * If a {@link value} is provided, there should not be any errors in this + * list, but there may be warnings. If a value is not provided, there should + * be at least one error in this list. + */ + ErrorList errors; +}; + +/** + * @brief Holds the result of an operation. If the operation succeeds, it will + * provide a value. It may also provide errors and warnings. + * + * @tparam T The type of value included in the result. + */ +template struct Result> { + /** + * @brief Creates a `Result` with the given value and an empty \ref ErrorList. + * + * @param pValue_ An intrusive pointer to the value that will be contained in + * this `Result`. + */ + Result(CesiumUtility::IntrusivePointer pValue_) noexcept + : pValue(std::move(pValue_)), errors() {} + + /** + * @brief Creates a `Result` with the given value and \ref ErrorList. + * + * @param pValue_ An intrusive pointer to the value that will be contained in + * this `Result`. + * @param errors_ The \ref ErrorList containing errors and warnings related to + * this `Result`. + */ + Result(CesiumUtility::IntrusivePointer pValue_, ErrorList errors_) noexcept + : pValue(std::move(pValue_)), errors(std::move(errors_)) {} + + /** + * @brief Creates a `Result` with an empty value and the given \ref ErrorList. + * + * @param errors_ The \ref ErrorList containing errors and warnings related to + * this `Result`. + */ + Result(ErrorList errors_) noexcept + : pValue(nullptr), errors(std::move(errors_)) {} + + /** + * @brief The value, if the operation succeeded to the point where it can + * provide one. + * + * If a value is not provided because the operation failed, then there should + * be at least one error in {@link errors} indicating what went wrong. + */ + CesiumUtility::IntrusivePointer pValue; + + /** + * @brief The errors and warnings that occurred during the operation. + * + * If a {@link pValue} is provided, there should not be any errors in this + * list, but there may be warnings. If a pValue is not provided, there should + * be at least one error in this list. + */ + ErrorList errors; +}; + +/** + * @brief A convenient shortcut for + * `CesiumUtility::Result>`. + * + * @tparam T The type of object that the IntrusivePointer points to. + */ +template using ResultPointer = Result>; + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ScopeGuard.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ScopeGuard.h new file mode 100644 index 0000000..1115519 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ScopeGuard.h @@ -0,0 +1,87 @@ +#pragma once + +#include +#include + +namespace CesiumUtility { +/** + * @brief A utility that will automatically call the lambda function when + * exiting a scope. + * + * @tparam ExitFunction The function type to be called when the guard is out of + * scope. + */ +template class ScopeGuard { +public: + /** + * @brief Constructor. + * + * @param exitFunc The function type to be called when the guard is out + * of scope + */ + template < + typename ExitFunctionArg, + typename std::enable_if_t< + !std::is_same_v< + std::remove_reference_t>, + ScopeGuard>, + int> = 0> + explicit ScopeGuard(ExitFunctionArg&& exitFunc) + : _callExitFuncOnDestruct{true}, + _exitFunc{std::forward(exitFunc)} {} + + ScopeGuard(const ScopeGuard& rhs) = delete; + + /** + * @brief Move constructor. The rhs will move its lambda to the lhs, and the + * rhs will not call its lambda upon exiting a scope + */ + ScopeGuard(ScopeGuard&& rhs) noexcept + : _callExitFuncOnDestruct{rhs._callExitFuncOnDestruct}, + _exitFunc{std::move(rhs._exitFunc)} { + rhs.release(); + } + + ScopeGuard& operator=(const ScopeGuard& rhs) = delete; + + /** + * @brief Move assignment operator. The rhs will move its lambda to the lhs, + * and the rhs will not call its lambda upon exiting a scope + */ + ScopeGuard& operator=(ScopeGuard&& rhs) noexcept { + if (&rhs != this) { + _callExitFuncOnDestruct = rhs._callExitFuncOnDestruct; + _exitFunc = std::move(rhs._exitFunc); + rhs.release(); + } + + return *this; + } + + /** + * @brief Destructor. The guard will execute the lambda function when exiting + * a scope if it's not released + */ + ~ScopeGuard() noexcept { + if (_callExitFuncOnDestruct) { + _exitFunc(); + } + } + + /** + * @brief Upon calling ScopeGuard::release(), the guard will not execute the + * lambda function when exiting a scope + */ + void release() noexcept { _callExitFuncOnDestruct = false; } + +private: + bool _callExitFuncOnDestruct; + ExitFunction _exitFunc; +}; + +/** @brief Template deduction guide for \ref ScopeGuard to help the compiler + * figure out that the type of `ExitFunction` should be the type of the + * function passed to the constructor. */ +template +ScopeGuard(ExitFunction) -> ScopeGuard; +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/SharedAsset.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/SharedAsset.h new file mode 100644 index 0000000..4a2c4a5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/SharedAsset.h @@ -0,0 +1,154 @@ +#pragma once + +#include +#include +#include +#include + +#include + +namespace CesiumAsync { +template class SharedAssetDepot; +} + +namespace CesiumUtility { + +/** + * @brief An asset that is potentially shared between multiple objects, such as + * an image shared between multiple glTF models. This is intended to be the base + * class for such assets. + * + * The lifetime of instances of this class should be managed by reference + * counting with {@link IntrusivePointer}. + * + * @tparam T The type that is _deriving_ from this class. For example, you + * should declare your class as + * `class MyClass : public SharedAsset { ... };` + * + * @remarks @parblock + * A `SharedAsset` can be in one of three possible states: + * + * **Independent Asset** + * An independent asset isn't affiliated with an asset depot at all. + * Its lifetime is controlled exclusively by IntrusivePointer / reference + * counting. When the asset's reference count goes to zero, it deletes itself. + * An independent asset's {@link getDepot} returns nullptr. + * + * **Active Depot Asset** + * This is an asset that is owned by an asset depot and that is in use, meaning + * it has a reference count greater than zero. The asset depot owns the asset + * via an `std::unique_ptr`, not via adding to the reference count. So when the + * reference count goes to zero, only the asset depot itself still has a + * reference to it, so it becomes an inactive depot asset. + * + * **Inactive Depot Asset** + * This is also an asset that is owned by the asset depot, but there are no + * other references to it (it has a reference count of zero). It is found in the + * asset depot's `deletionCandidates` list. When a reference to it is added, it + * is removed from `deletionCandidates` and it becomes an active depot asset. + * @endparblock + */ +template +class CESIUMUTILITY_API SharedAsset : public CesiumUtility::ExtensibleObject { +public: + /** + * @brief Adds a counted reference to this object. Use + * {@link CesiumUtility::IntrusivePointer} instead of calling this method + * directly. + */ + void addReference() const noexcept { this->addReference(false); } + + /** + * @brief Removes a counted reference from this object. When the last + * reference is removed, this method will delete this instance. Use + * {@link CesiumUtility::IntrusivePointer} instead of calling this method + * directly. + */ + void releaseReference() const noexcept { this->releaseReference(false); } + + /** + * @brief Gets the shared asset depot that owns this asset, or nullptr if this + * asset is independent of an asset depot. + */ + const IDepotOwningAsset* getDepot() const { return this->_pDepot; } + + /** + * @brief Gets the shared asset depot that owns this asset, or nullptr if this + * asset is independent of an asset depot. + */ + IDepotOwningAsset* getDepot() { return this->_pDepot; } + +protected: + SharedAsset() = default; + ~SharedAsset() { CESIUM_ASSERT(this->_referenceCount == 0); } + + /** + * Assets can be copied, but the fresh instance has no references and is not + * in the asset depot. + */ + SharedAsset(const SharedAsset& rhs) + : ExtensibleObject(rhs), _referenceCount(0), _pDepot(nullptr) {} + + /** + * After a move construction, the content of the asset is moved to the new + * instance, but the asset depot still references the old instance. + */ + SharedAsset(SharedAsset&& rhs) + : ExtensibleObject(std::move(rhs)), + _referenceCount(0), + _pDepot(nullptr) {} + + /** + * Assignment does not affect the asset's relationship with the depot, but is + * useful to assign the data in derived classes. + */ + SharedAsset& operator=(const SharedAsset& rhs) { + CesiumUtility::ExtensibleObject::operator=(rhs); + return *this; + } + + /** + * Assignment does not affect the asset's relationship with the depot, but is + * useful to assign the data in derived classes. + */ + SharedAsset& operator=(SharedAsset&& rhs) { + CesiumUtility::ExtensibleObject::operator=(std::move(rhs)); + return *this; + } + +private: + void addReference(bool threadOwnsDepotLock) const noexcept { + const int32_t prevReferences = this->_referenceCount++; + if (this->_pDepot && prevReferences <= 0) { + this->_pDepot->unmarkDeletionCandidate( + *static_cast(this), + threadOwnsDepotLock); + } + } + + void releaseReference(bool threadOwnsDepotLock) const noexcept { + CESIUM_ASSERT(this->_referenceCount > 0); + const int32_t references = --this->_referenceCount; + if (references == 0) { + IDepotOwningAsset* pDepot = this->_pDepot; + if (pDepot) { + // Let the depot manage this object's lifetime. + pDepot->markDeletionCandidate( + *static_cast(this), + threadOwnsDepotLock); + } else { + // No depot, so destroy this object directly. + delete static_cast(this); + } + } + } + + mutable std::atomic _referenceCount{0}; + IDepotOwningAsset* _pDepot{nullptr}; + + // To allow the depot to modify _pDepot. + template + friend class CesiumAsync::SharedAssetDepot; +}; + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/SpanHelper.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/SpanHelper.h new file mode 100644 index 0000000..ba0c5c4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/SpanHelper.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace CesiumUtility { +/** + * @brief This function converts between span types. This function + * has the same rules with C++ reintepret_cast + * https://en.cppreference.com/w/cpp/language/reinterpret_cast. So please use it + * carefully + */ +template +std::span reintepretCastSpan(const std::span& from) noexcept { + return std::span( + reinterpret_cast(from.data()), + from.size() * sizeof(From) / sizeof(To)); +} +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/StringHelpers.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/StringHelpers.h new file mode 100644 index 0000000..c93680a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/StringHelpers.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace CesiumUtility { + +/** + * @brief Helper functions for working with strings. + */ +class StringHelpers { +public: + /** + * @brief Converts a `u8string` to a `string` without changing its encoding. + * The output string is encoded in UTF-8, just like the input. + * + * @param s The `std::u8string`. + * @return The equivalent `std::string`. + */ + static std::string toStringUtf8(const std::u8string& s); +}; + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Tracing.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Tracing.h new file mode 100644 index 0000000..d1b9452 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Tracing.h @@ -0,0 +1,349 @@ +#pragma once + +#ifndef CESIUM_OVERRIDE_TRACING + +// If the build system doesn't enable the tracing support +// consider it disabled by default. +#ifndef CESIUM_TRACING_ENABLED +#define CESIUM_TRACING_ENABLED 0 +#endif + +#if !CESIUM_TRACING_ENABLED + +#define CESIUM_TRACE_INIT(filename) +#define CESIUM_TRACE_SHUTDOWN() +#define CESIUM_TRACE(name) +#define CESIUM_TRACE_BEGIN(name) +#define CESIUM_TRACE_END(name) +#define CESIUM_TRACE_BEGIN_IN_TRACK(name) +#define CESIUM_TRACE_END_IN_TRACK(name) +#define CESIUM_TRACE_DECLARE_TRACK_SET(id, name) +#define CESIUM_TRACE_USE_TRACK_SET(id) +#define CESIUM_TRACE_LAMBDA_CAPTURE_TRACK() tracingTrack = false +#define CESIUM_TRACE_USE_CAPTURED_TRACK() + +#else + +#include +#include +#include +#include +#include +#include +#include + +// helper macros to avoid shadowing variables +#define TRACE_NAME_AUX1(A, B) A##B +#define TRACE_NAME_AUX2(A, B) TRACE_NAME_AUX1(A, B) + +/** + * @brief Initializes the tracing framework and begins recording to a given JSON + * filename. + * + * @param filename The path and named of the file in which to record traces. + */ +#define CESIUM_TRACE_INIT(filename) \ + CesiumUtility::CesiumImpl::Tracer::instance().startTracing(filename) + +/** + * @brief Shuts down tracing and closes the JSON tracing file. + */ +#define CESIUM_TRACE_SHUTDOWN() \ + CesiumUtility::CesiumImpl::Tracer::instance().endTracing() + +/** + * @brief Measures and records the time spent in the current scope. + * + * The time is measured from the `CESIUM_TRACE` line to the end of the scope. + * If the current thread is enlisted in an async process + * ({@link CESIUM_TRACE_ASYNC_ENLIST}), the time is recorded against the async + * process. Otherwise, it is recorded against the current thread. + * + * @param name The name of the measured operation. + */ +#define CESIUM_TRACE(name) \ + CesiumUtility::CesiumImpl::ScopedTrace TRACE_NAME_AUX2( \ + cesiumTrace, \ + __LINE__)(name) + +/** + * @brief Begins measuring an operation which may span scope but not threads. + * + * Begins measuring the time of an operation which completes with a + * corresponding call to {@link CESIUM_TRACE_END}. If the calling thread is + * operating in a track ({@link CESIUM_TRACE_USE_TRACK_SET}), the + * time is recorded in the track. Otherwise, is is recorded against the current + * thread. + * + * Extreme care must be taken to match calls to `CESIUM_TRACE_BEGIN` and + * `CESIUM_TRACE_END`: + * + * * Paired calls must use an identical `name`. + * * If either BEGIN or END is called from a thread operating in a track, + * then both must be, and it must be the same track in + * both cases. In this case BEGIN and END may be called from different + * threads. However, it safer to use {@link CESIUM_TRACE_BEGIN_IN_TRACK} + * in this scenario. + * * If either BEGIN or END is called from a thread _not_ enlisted into a + * track, then both must be called from the same thread and neither + * thread may be in a track. + * * Paired calls must not be interleaved with other BEGIN/END calls for the + * same thread or track. Other BEGIN/END pairs may be fully + * nested within this one, but this pair must not END in between a nested + * measurement's BEGIN and END calls. + * + * Failure to ensure the above may lead to generation of a trace file that the + * Chromium trace viewer is not able to correctly interpret. + * + * @param name The name of the measured operation. + */ +#define CESIUM_TRACE_BEGIN(name) \ + CesiumUtility::CesiumImpl::Tracer::instance().writeAsyncEventBegin(name) + +/** + * @brief Ends measuring an operation which may span scopes but not threads. + * + * Finishes measuring the time of an operation that began with a call to + * {@link CESIUM_TRACE_BEGIN}. See the documentation for that macro for more + * details and caveats. + * + * @param name The name of the measured operation. + */ +#define CESIUM_TRACE_END(name) \ + CesiumUtility::CesiumImpl::Tracer::instance().writeAsyncEventEnd(name) + +/** + * @brief Begins measuring an operation that may span both scopes and threads. + * + * This macro is identical to {@link CESIUM_TRACE_BEGIN} except that it does + * nothing if the calling thread and scope are not operating as part of a + * track. This allows it to be safely used to measure operations that span + * threads. Use {@link CESIUM_TRACE_USE_TRACK_SET} to use a track from a set. + * + * @param name The name of the measured operation. + */ +#define CESIUM_TRACE_BEGIN_IN_TRACK(name) \ + if (CesiumUtility::CesiumImpl::TrackReference::current() != nullptr) { \ + CESIUM_TRACE_BEGIN(name); \ + } + +/** + * @brief Ends measuring an operation that may span both scopes and threads. + * + * This macro is identical to {@link CESIUM_TRACE_END} except that it does + * nothing if the calling thread and scope are not operating as part of a + * track. This allows it to be safely used to measure operations that span + * threads. Use {@link CESIUM_TRACE_USE_TRACK_SET} to use a track from a set. + * + * @param name The name of the measured operation. + */ +#define CESIUM_TRACE_END_IN_TRACK(name) \ + if (CesiumUtility::CesiumImpl::TrackReference::current() != nullptr) { \ + CESIUM_TRACE_END(name); \ + } + +/** + * @brief Declares a set of tracing tracks as a field inside a class. + * + * A track is a sequential process that may take place across multiple threads. + * An instance of a class may have multiple such tracks running simultaneously. + * For example, a single 3D Tiles tile will load in a particular track, while + * other tiles will be loading in other parallel tracks in the same set. + * + * Note that when the track set is destroyed, an assertion will check that no + * tracks are still in progress. + * + * @param id The name of the field to hold the track set. + * @param name A human-friendly name for this set of tracks. + */ +#define CESIUM_TRACE_DECLARE_TRACK_SET(id, name) \ + CesiumUtility::CesiumImpl::TrackSet id { name } + +/** + * @brief Begins using a track set in this thread. + * + * The calling thread will be allocated a track from the track set, and will + * continue using it for the remainder of the current scope. In addition, if + * the thread starts an async operation using {@link CesiumAsync::AsyncSystem}, + * all continuations of that async operation will use the same track as well. + * + * @param id The ID (field name) of the track set declared with + * {@link CESIUM_TRACE_DECLARE_TRACK_SET}. + */ +#define CESIUM_TRACE_USE_TRACK_SET(id) \ + CesiumUtility::CesiumImpl::TrackReference TRACE_NAME_AUX2( \ + cesiumTraceEnlistTrack, \ + __LINE__)(id); + +/** + * @brief Capture the current tracing track for a lambda, so that the lambda may + * use the same track. + * + * This macro should be used in a lambda's capture list to capture the track of + * the current thread so that the lambda (which may execute in a different + * thread) can use the same track by executing + * {@link CESIUM_TRACE_USE_CAPTURED_TRACK}. + */ +#define CESIUM_TRACE_LAMBDA_CAPTURE_TRACK() \ + tracingTrack = CesiumUtility::CesiumImpl::LambdaCaptureTrack() + +/** + * @brief Uses a captured track for the current thread and the current scope. + * + * This macro should be used as the first line in a lambda that should inherit + * the tracing track of the thread that created it. The lambda's capture list + * must also contain {@link CESIUM_TRACE_USE_CAPTURED_TRACK}. + */ +#define CESIUM_TRACE_USE_CAPTURED_TRACK() \ + CESIUM_TRACE_USE_TRACK_SET(tracingTrack) + +namespace CesiumUtility { +namespace CesiumImpl { + +// The following are internal classes used by the tracing framework, do not use +// directly. + +struct Trace { + std::string name; + int64_t start; + int64_t duration; + std::thread::id threadID; +}; + +class TrackReference; + +class Tracer { +public: + static Tracer& instance(); + + ~Tracer(); + + void startTracing(const std::string& filePath = "trace.json"); + void endTracing(); + + void writeCompleteEvent(const Trace& trace); + void writeAsyncEventBegin(const char* name, int64_t id); + void writeAsyncEventBegin(const char* name); + void writeAsyncEventEnd(const char* name, int64_t id); + void writeAsyncEventEnd(const char* name); + + int64_t allocateTrackID(); + +private: + Tracer(); + + int64_t getCurrentThreadTrackID() const; + void writeAsyncEvent( + const char* category, + const char* name, + char type, + int64_t id); + + std::ofstream _output; + uint32_t _numTraces; + std::mutex _lock; + std::atomic _lastAllocatedID; +}; + +class ScopedTrace { +public: + explicit ScopedTrace(const std::string& message); + ~ScopedTrace(); + + void reset(); + + ScopedTrace(const ScopedTrace& rhs) = delete; + ScopedTrace(ScopedTrace&& rhs) = delete; + ScopedTrace& operator=(const ScopedTrace& rhs) = delete; + ScopedTrace& operator=(ScopedTrace&& rhs) = delete; + +private: + std::string _name; + std::chrono::steady_clock::time_point _startTime; + std::thread::id _threadId; + bool _reset; +}; + +class TrackSet { +public: + explicit TrackSet(const char* name); + ~TrackSet(); + + size_t acquireTrack(); + void addReference(size_t trackIndex) noexcept; + void releaseReference(size_t trackIndex) noexcept; + + int64_t getTracingID(size_t trackIndex) noexcept; + + TrackSet(TrackSet&& rhs) noexcept; + TrackSet& operator=(TrackSet&& rhs) noexcept; + +private: + struct Track { + Track(int64_t id_, bool inUse_) + : id(id_), referenceCount(0), inUse(inUse_) {} + + int64_t id; + int32_t referenceCount; + bool inUse; + }; + + std::string name; + std::vector tracks; + std::mutex mutex; +}; + +class LambdaCaptureTrack { +public: + LambdaCaptureTrack(); + LambdaCaptureTrack(LambdaCaptureTrack&& rhs) noexcept; + LambdaCaptureTrack(const LambdaCaptureTrack& rhs) noexcept; + ~LambdaCaptureTrack(); + LambdaCaptureTrack& operator=(const LambdaCaptureTrack& rhs) noexcept; + LambdaCaptureTrack& operator=(LambdaCaptureTrack&& rhs) noexcept; + +private: + TrackSet* pSet; + size_t index; + + friend class TrackReference; +}; + +// An RAII object to reference an async operation track. +// When the last instance associated with a particular track index is destroyed, +// the track is released back to the track set. +class TrackReference { +public: + static TrackReference* current(); + + TrackReference(TrackSet& set) noexcept; + TrackReference(TrackSet& set, size_t index) noexcept; + TrackReference(const LambdaCaptureTrack& lambdaCapture) noexcept; + ~TrackReference() noexcept; + + operator bool() const noexcept; + int64_t getTracingID() const noexcept; + + TrackReference(const TrackReference& rhs) = delete; + TrackReference(TrackReference&& rhs) = delete; + TrackReference& operator=(const TrackReference& rhs) = delete; + TrackReference& operator=(TrackReference&& rhs) = delete; + +private: + void enlistCurrentThread(); + void dismissCurrentThread(); + + TrackSet* pSet; + size_t index; + + static thread_local std::vector _threadEnlistedTracks; + + friend class LambdaCaptureTrack; +}; + +} // namespace CesiumImpl +} // namespace CesiumUtility + +#endif // CESIUM_TRACING_ENABLED + +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Uri.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Uri.h new file mode 100644 index 0000000..c50bbb7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Uri.h @@ -0,0 +1,211 @@ +#pragma once + +#include +#include + +namespace CesiumUtility { +/** + * @brief A class for building and manipulating Uniform Resource Identifiers + * (URIs). + */ +class Uri final { +public: + /** + * @brief Attempts to resolve a relative URI using a base URI. + * + * For example, a relative URI `/v1/example` together with the base URI + * `https://api.cesium.com` would resolve to + * `https://api.cesium.com/v1/example`. + * + * @param base The base URI that the relative URI is relative to. + * @param relative The relative URI to be resolved against the base URI. + * @param useBaseQuery If true, any query parameters of the base URI will be + * retained in the resolved URI. + * @param assumeHttpsDefault If true, protocol-relative URIs (such as + * `//api.cesium.com`) will be assumed to be `https`. If false, they will be + * assumed to be `http`. + * @returns The resolved URI. + */ + static std::string resolve( + const std::string& base, + const std::string& relative, + bool useBaseQuery = false, + bool assumeHttpsDefault = true); + /** + * @brief Adds the given key and value to the query string of a URI. For + * example, `addQuery("https://api.cesium.com/v1/example", "key", "value")` + * would produce the URL `https://api.cesium.com/v1/example?key=value`. + * + * @param uri The URI whose query string will be modified. + * @param key The key to be added to the query string. + * @param value The value to be added to the query string. + * @returns The modified URI including the new query string parameter. + */ + static std::string addQuery( + const std::string& uri, + const std::string& key, + const std::string& value); + /** + * @brief Obtains the value of the given key from the query string of the URI, + * if possible. + * + * If the URI can't be parsed, or the key doesn't exist in the + * query string, an empty string will be returned. + * + * @param uri The URI with a query string to obtain a value from. + * @param key The key whose value will be obtained from the URI, if possible. + * @returns The value of the given key in the query string, or an empty string + * if not found. + */ + static std::string + getQueryValue(const std::string& uri, const std::string& key); + + /** + * @brief A callback to fill-in a placeholder value in a URL. + * + * @param placeholder The text of the placeholder. For example, if the + * placeholder was `{example}`, the value of `placeholder` will be `example`. + * @returns The value to use in place of the placeholder. + */ + typedef std::string + SubstitutionCallbackSignature(const std::string& placeholder); + + /** + * @brief Substitutes the placeholders in a templated URI with their + * appropriate values obtained using a specified callback function. + * + * A templated URI has placeholders in the form of `{name}`. For example, + * `https://example.com/{x}/{y}/{z}` has three placeholders, `x`, `y`, and `z`. + * The callback will be called for each placeholder and they will be replaced + * with the return value of this callback. + * + * @param templateUri The templated URI whose placeholders will be substituted + * by this method. + * @param substitutionCallback The callback that will be called for each + * placeholder in the provided URI. See \ref SubstitutionCallbackSignature. + */ + static std::string substituteTemplateParameters( + const std::string& templateUri, + const std::function& substitutionCallback); + + /** + * @brief Escapes a portion of a URI, percent-encoding disallowed characters. + * + * @param s The string to escape. + * @return The escaped string. + */ + static std::string escape(const std::string& s); + + /** + * @brief Unescapes a portion of a URI, decoding any percent-encoded + * characters. + * + * @param s The string to unescape. + * @return The unescaped string. + */ + static std::string unescape(const std::string& s); + + /** + * @brief Converts a Unix file system path to a string suitable for use as the + * path portion of a URI. Characters that are not allowed in the path portion + * of a URI are percent-encoded as necessary. + * + * If the path is absolute (it starts with a slash), then the URI will start + * with a slash as well. + * + * @param unixPath The file system path. + * @return The URI path. + */ + static std::string unixPathToUriPath(const std::string& unixPath); + + /** + * @brief Converts a Windows file system path to a string suitable for use as + * the path portion of a URI. Characters that are not allowed in the path + * portion of a URI are percent-encoded as necessary. + * + * Either `/` or `\` may be used as a path separator on input, but the output + * will contain only `/`. + * + * If the path is absolute (it starts with a slash or with C:\ or similar), + * then the URI will start with a slash well. + * + * @param windowsPath The file system path. + * @return The URI path. + */ + static std::string windowsPathToUriPath(const std::string& windowsPath); + + /** + * @brief Converts a file system path on the current system to a string + * suitable for use as the path portion of a URI. Characters that are not + * allowed in the path portion of a URI are percent-encoded as necessary. + * + * If the `_WIN32` preprocessor definition is defined when compiling + * cesium-native, this is assumed to be a Windows-like system and this + * function calls {@link windowsPathToUriPath}. Otherwise, this is assumed to + * be a Unix-like system and this function calls {@link unixPathToUriPath}. + * + * @param nativePath The file system path. + * @return The URI path. + */ + static std::string nativePathToUriPath(const std::string& nativePath); + + /** + * @brief Converts the path portion of a URI to a Unix file system path. + * Percent-encoded characters in the URI are decoded. + * + * If the URI path is absolute (it starts with a slash), then the file system + * path will start with a slash as well. + * + * @param uriPath The URI path. + * @return The file system path. + */ + static std::string uriPathToUnixPath(const std::string& uriPath); + + /** + * @brief Converts the path portion of a URI to a Windows file system path. + * Percent-encoded characters in the URI are decoded. + * + * If the URI path is absolute (it starts with a slash), then the file system + * path will start with a slash or a drive letter. + * + * @param uriPath The URI path. + * @return The file system path. + */ + static std::string uriPathToWindowsPath(const std::string& uriPath); + + /** + * @brief Converts the path portion of a URI to a file system path on the + * current system. Percent-encoded characters in the URI are decoded. + * + * If the `_WIN32` preprocessor definition is defined when compiling + * cesium-native, this is assumed to be a Windows-like system and this + * function calls {@link uriPathToWindowsPath}. Otherwise, this is assumed to + * be a Unix-like system and this function calls {@link uriPathToUnixPath}. + * + * @param uriPath The URI path. + * @return The file system path. + */ + static std::string uriPathToNativePath(const std::string& uriPath); + + /** + * @brief Gets the path portion of the URI. This will not include path + * parameters, if present. + * + * @param uri The URI from which to get the path. + * @return The path, or empty string if the URI could not be parsed. + */ + static std::string getPath(const std::string& uri); + + /** + * @brief Sets the path portion of a URI to a new value. The other portions of + * the URI are left unmodified, including any path parameters. + * + * @param uri The URI for which to set the path. + * @param newPath The new path portion of the URI. + * @returns The new URI after setting the path. If the original URI cannot be + * parsed, it is returned unmodified. + */ + static std::string + setPath(const std::string& uri, const std::string& newPath); +}; +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/joinToString.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/joinToString.h new file mode 100644 index 0000000..d92a53f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/joinToString.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include + +namespace CesiumUtility { +/** + * @brief Joins multiple elements together into a string, separated by a given + * separator. + * + * @tparam TIterator The type of the collection iterator. + * @param begin An iterator referring to the first element to join. + * @param end An iterator referring to one past the last element to join. + * @param separator The string to use to separate successive elements. + * @return The joined string. + */ +template +std::string +joinToString(TIterator begin, TIterator end, const std::string& separator) { + if (begin == end) + return std::string(); + + std::string first = *begin; + + return std::accumulate( + ++begin, + end, + std::move(first), + [&separator](const std::string& acc, const std::string& element) { + return acc + separator + element; + }); +} + +/** + * @brief Joins multiple elements together into a string, separated by a given + * separator. + * + * @tparam TIterator The type of the collection iterator. + * @param collection The collection of elements to be joined. + * @param separator The string to use to separate successive elements. + * @return The joined string. + */ +template +std::string joinToString(TCollection collection, const std::string& separator) { + return joinToString(collection.cbegin(), collection.cend(), separator); +} +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++.h new file mode 100644 index 0000000..36e1516 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++.h @@ -0,0 +1,158 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +#define ASYNCXX_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Export declaration to make symbols visible for dll/so +#ifdef LIBASYNC_STATIC +# define LIBASYNC_EXPORT +# define LIBASYNC_EXPORT_EXCEPTION +#else +# ifdef _WIN32 +# ifdef LIBASYNC_BUILD +# define LIBASYNC_EXPORT __declspec(dllexport) +# else +# define LIBASYNC_EXPORT __declspec(dllimport) +# endif +# define LIBASYNC_EXPORT_EXCEPTION +# else +# define LIBASYNC_EXPORT __attribute__((visibility("default"))) +# define LIBASYNC_EXPORT_EXCEPTION __attribute__((visibility("default"))) +# endif +#endif + +// Support compiling without exceptions +#ifndef LIBASYNC_NO_EXCEPTIONS +# ifdef __clang__ +# if !defined(__EXCEPTIONS) || !__has_feature(cxx_exceptions) +# define LIBASYNC_NO_EXCEPTIONS +# endif +# elif defined(__GNUC__) && !defined(__EXCEPTIONS) +# define LIBASYNC_NO_EXCEPTIONS +# elif defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS +# define LIBASYNC_NO_EXCEPTIONS +# endif +#endif +#ifdef LIBASYNC_NO_EXCEPTIONS +# define LIBASYNC_THROW(...) std::abort() +# define LIBASYNC_RETHROW() do {} while (false) +# define LIBASYNC_RETHROW_EXCEPTION(except) std::terminate() +# define LIBASYNC_TRY if (true) +# define LIBASYNC_CATCH(...) else if (false) +#else +# define LIBASYNC_THROW(...) throw __VA_ARGS__ +# define LIBASYNC_RETHROW() throw +# define LIBASYNC_RETHROW_EXCEPTION(except) std::rethrow_exception(except) +# define LIBASYNC_TRY try +# define LIBASYNC_CATCH(...) catch (__VA_ARGS__) +#endif + +// Optional debug assertions. If exceptions are enabled then use those, but +// otherwise fall back to an assert message. +#ifndef NDEBUG +# ifndef LIBASYNC_NO_EXCEPTIONS +# define LIBASYNC_ASSERT(pred, except, message) ((pred) ? ((void)0) : throw except(message)) +# else +# define LIBASYNC_ASSERT(pred, except, message) ((pred) ? ((void)0) : assert(message)) +# endif +#else +# define LIBASYNC_ASSERT(pred, except, message) ((void)0) +#endif + +// Annotate move constructors and move assignment with noexcept to allow objects +// to be moved if they are in containers. Compilers which don't support noexcept +// will usually move regardless. +#if defined(__GNUC__) || _MSC_VER >= 1900 +# define LIBASYNC_NOEXCEPT noexcept +#else +# define LIBASYNC_NOEXCEPT throw() +#endif + +// Cacheline alignment to avoid false sharing between different threads +#define LIBASYNC_CACHELINE_SIZE 64 +#ifdef __GNUC__ +# define LIBASYNC_CACHELINE_ALIGN __attribute__((aligned(LIBASYNC_CACHELINE_SIZE))) +#elif defined(_MSC_VER) +# define LIBASYNC_CACHELINE_ALIGN __declspec(align(LIBASYNC_CACHELINE_SIZE)) +#else +# define LIBASYNC_CACHELINE_ALIGN alignas(LIBASYNC_CACHELINE_SIZE) +#endif + +// Force symbol visibility to hidden unless explicity exported +#ifndef LIBASYNC_STATIC +#if defined(__GNUC__) && !defined(_WIN32) +# pragma GCC visibility push(hidden) +#endif +#endif + +// Some forward declarations +namespace async { + +template +class task; +template +class shared_task; +template +class event_task; + +} // namespace async + +// Include sub-headers +#include "async++/traits.h" +#include "async++/aligned_alloc.h" +#include "async++/ref_count.h" +#include "async++/scheduler_fwd.h" +#include "async++/continuation_vector.h" +#include "async++/task_base.h" +#include "async++/scheduler.h" +#include "async++/task.h" +#include "async++/when_all_any.h" +#include "async++/cancel.h" +#include "async++/range.h" +#include "async++/partitioner.h" +#include "async++/parallel_invoke.h" +#include "async++/parallel_for.h" +#include "async++/parallel_reduce.h" + +#ifndef LIBASYNC_STATIC +#if defined(__GNUC__) && !defined(_WIN32) +# pragma GCC visibility pop +#endif +#endif + +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/aligned_alloc.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/aligned_alloc.h new file mode 100644 index 0000000..cf4c2a3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/aligned_alloc.h @@ -0,0 +1,99 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace async { +namespace detail { + +// Allocate an aligned block of memory +LIBASYNC_EXPORT void* aligned_alloc(std::size_t size, std::size_t align); + +// Free an aligned block of memory +LIBASYNC_EXPORT void aligned_free(void* addr) LIBASYNC_NOEXCEPT; + +// Class representing an aligned array and its length +template::value> +class aligned_array { + std::size_t length; + T* ptr; + +public: + aligned_array() + : length(0), ptr(nullptr) {} + aligned_array(std::nullptr_t) + : length(0), ptr(nullptr) {} + explicit aligned_array(std::size_t length_) + : length(length_) + { + ptr = static_cast(aligned_alloc(length * sizeof(T), Align)); + std::size_t i; + LIBASYNC_TRY { + for (i = 0; i < length; i++) + new(ptr + i) T; + } LIBASYNC_CATCH(...) { + for (std::size_t j = 0; j < i; j++) + ptr[i].~T(); + aligned_free(ptr); + LIBASYNC_RETHROW(); + } + } + aligned_array(aligned_array&& other) LIBASYNC_NOEXCEPT + : length(other.length), ptr(other.ptr) + { + other.ptr = nullptr; + other.length = 0; + } + aligned_array& operator=(aligned_array&& other) LIBASYNC_NOEXCEPT + { + aligned_array(std::move(*this)); + std::swap(ptr, other.ptr); + std::swap(length, other.length); + return *this; + } + aligned_array& operator=(std::nullptr_t) + { + return *this = aligned_array(); + } + ~aligned_array() + { + for (std::size_t i = 0; i < length; i++) + ptr[i].~T(); + aligned_free(ptr); + } + + T& operator[](std::size_t i) const + { + return ptr[i]; + } + std::size_t size() const + { + return length; + } + T* get() const + { + return ptr; + } + explicit operator bool() const + { + return ptr != nullptr; + } +}; + +} // namespace detail +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/cancel.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/cancel.h new file mode 100644 index 0000000..36d0307 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/cancel.h @@ -0,0 +1,68 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { + +// Exception thrown by cancel_current_task() +struct LIBASYNC_EXPORT_EXCEPTION task_canceled {}; + +// A flag which can be used to request cancellation +class cancellation_token { + std::atomic state; + +public: + cancellation_token() + : state(false) {} + + // Non-copyable and non-movable + cancellation_token(const cancellation_token&) = delete; + cancellation_token& operator=(const cancellation_token&) = delete; + + bool is_canceled() const + { + bool s = state.load(std::memory_order_relaxed); + if (s) + std::atomic_thread_fence(std::memory_order_acquire); + return s; + } + + void cancel() + { + state.store(true, std::memory_order_release); + } + + void reset() + { + state.store(false, std::memory_order_relaxed); + } +}; + +// Interruption point, throws task_canceled if the specified token is set. +inline void interruption_point(const cancellation_token& token) +{ + if (token.is_canceled()) + LIBASYNC_THROW(task_canceled()); +} + +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/continuation_vector.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/continuation_vector.h new file mode 100644 index 0000000..f0d9095 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/continuation_vector.h @@ -0,0 +1,225 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { +namespace detail { + +// Compress the flags in the low bits of the pointer if the structures are +// suitably aligned. Fall back to a separate flags variable otherwise. +template +class compressed_ptr { + void* ptr; + std::uintptr_t flags; + +public: + compressed_ptr() = default; + compressed_ptr(void* ptr_, std::uintptr_t flags_) + : ptr(ptr_), flags(flags_) {} + + template + T* get_ptr() const + { + return static_cast(ptr); + } + std::uintptr_t get_flags() const + { + return flags; + } + + void set_ptr(void* p) + { + ptr = p; + } + void set_flags(std::uintptr_t f) + { + flags = f; + } +}; +template +class compressed_ptr { + std::uintptr_t data; + +public: + compressed_ptr() = default; + compressed_ptr(void* ptr_, std::uintptr_t flags_) + : data(reinterpret_cast(ptr_) | flags_) {} + + template + T* get_ptr() const + { + return reinterpret_cast(data & ~Mask); + } + std::uintptr_t get_flags() const + { + return data & Mask; + } + + void set_ptr(void* p) + { + data = reinterpret_cast(p) | (data & Mask); + } + void set_flags(std::uintptr_t f) + { + data = (data & ~Mask) | f; + } +}; + +// Thread-safe vector of task_ptr which is optimized for the common case of +// only having a single continuation. +class continuation_vector { + // Heap-allocated data for the slow path + struct vector_data { + std::vector vector; + std::mutex lock; + }; + + // Flags to describe the state of the vector + enum flags { + // If set, no more changes are allowed to internal_data + is_locked = 1, + + // If set, the pointer is a vector_data* instead of a task_base*. If + // there are 0 or 1 elements in the vector, the task_base* form is used. + is_vector = 2 + }; + static const std::uintptr_t flags_mask = 3; + + // Embed the two bits in the data if they are suitably aligned. We only + // check the alignment of vector_data here because task_base isn't defined + // yet. Since we align task_base to LIBASYNC_CACHELINE_SIZE just use that. + typedef compressed_ptr::value & flags_mask) == 0> internal_data; + + // All changes to the internal data are atomic + std::atomic atomic_data; + +public: + // Start unlocked with zero elements in the fast path + continuation_vector() + { + // Workaround for a bug in certain versions of clang with libc++ + // error: no viable conversion from 'async::detail::compressed_ptr<3, true>' to '_Atomic(async::detail::compressed_ptr<3, true>)' + atomic_data.store(internal_data(nullptr, 0), std::memory_order_relaxed); + } + + // Free any left over data + ~continuation_vector() + { + // Converting to task_ptr instead of using remove_ref because task_base + // isn't defined yet at this point. + internal_data data = atomic_data.load(std::memory_order_relaxed); + if (data.get_flags() & flags::is_vector) { + // No need to lock the mutex, we are the only thread at this point + for (task_base* i: data.get_ptr()->vector) + (task_ptr(i)); + delete data.get_ptr(); + } else { + // If the data is locked then the inline pointer is already gone + if (!(data.get_flags() & flags::is_locked)) + task_ptr tmp(data.get_ptr()); + } + } + + // Try adding an element to the vector. This fails and returns false if + // the vector has been locked. In that case t is not modified. + bool try_add(task_ptr&& t) + { + // Cache to avoid re-allocating vector_data multiple times. This is + // automatically freed if it is not successfully saved to atomic_data. + std::unique_ptr vector; + + // Compare-exchange loop on atomic_data + internal_data data = atomic_data.load(std::memory_order_relaxed); + internal_data new_data; + do { + // Return immediately if the vector is locked + if (data.get_flags() & flags::is_locked) + return false; + + if (data.get_flags() & flags::is_vector) { + // Larger vectors use a mutex, so grab the lock + std::atomic_thread_fence(std::memory_order_acquire); + std::lock_guard locked(data.get_ptr()->lock); + + // We need to check again if the vector has been locked here + // to avoid a race condition with flush_and_lock + if (atomic_data.load(std::memory_order_relaxed).get_flags() & flags::is_locked) + return false; + + // Add the element to the vector and return + data.get_ptr()->vector.push_back(t.release()); + return true; + } else { + if (data.get_ptr()) { + // Going from 1 to 2 elements, allocate a vector_data + if (!vector) + vector.reset(new vector_data{{data.get_ptr(), t.get()}, {}}); + new_data = {vector.get(), flags::is_vector}; + } else { + // Going from 0 to 1 elements + new_data = {t.get(), 0}; + } + } + } while (!atomic_data.compare_exchange_weak(data, new_data, std::memory_order_release, std::memory_order_relaxed)); + + // If we reach this point then atomic_data was successfully changed. + // Since the pointers are now saved in the vector, release them from + // the smart pointers. + t.release(); + vector.release(); + return true; + } + + // Lock the vector and flush all elements through the given function + template void flush_and_lock(Func&& func) + { + // Try to lock the vector using a compare-exchange loop + internal_data data = atomic_data.load(std::memory_order_relaxed); + internal_data new_data; + do { + new_data = data; + new_data.set_flags(data.get_flags() | flags::is_locked); + } while (!atomic_data.compare_exchange_weak(data, new_data, std::memory_order_acquire, std::memory_order_relaxed)); + + if (data.get_flags() & flags::is_vector) { + // If we are using vector_data, lock it and flush all elements + std::lock_guard locked(data.get_ptr()->lock); + for (auto i: data.get_ptr()->vector) + func(task_ptr(i)); + + // Clear the vector to save memory. Note that we don't actually free + // the vector_data here because other threads may still be using it. + // This isn't a very significant cost since multiple continuations + // are relatively rare. + data.get_ptr()->vector.clear(); + } else { + // If there is an inline element, just pass it on + if (data.get_ptr()) + func(task_ptr(data.get_ptr())); + } + } +}; + +} // namespace detail +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/parallel_for.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/parallel_for.h new file mode 100644 index 0000000..4fe5268 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/parallel_for.h @@ -0,0 +1,77 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { +namespace detail { + +// Internal implementation of parallel_for that only accepts a partitioner +// argument. +template +void internal_parallel_for(Sched& sched, Partitioner partitioner, const Func& func) +{ + // Split the partition, run inline if no more splits are possible + auto subpart = partitioner.split(); + if (subpart.begin() == subpart.end()) { + for (auto&& i: partitioner) + func(std::forward(i)); + return; + } + + // Run the function over each half in parallel + auto&& t = async::local_spawn(sched, [&sched, &subpart, &func] { + detail::internal_parallel_for(sched, std::move(subpart), func); + }); + detail::internal_parallel_for(sched, std::move(partitioner), func); + t.get(); +} + +} // namespace detail + +// Run a function for each element in a range +template +void parallel_for(Sched& sched, Range&& range, const Func& func) +{ + detail::internal_parallel_for(sched, async::to_partitioner(std::forward(range)), func); +} + +// Overload with default scheduler +template +void parallel_for(Range&& range, const Func& func) +{ + async::parallel_for(::async::default_scheduler(), range, func); +} + +// Overloads with std::initializer_list +template +void parallel_for(Sched& sched, std::initializer_list range, const Func& func) +{ + async::parallel_for(sched, async::make_range(range.begin(), range.end()), func); +} +template +void parallel_for(std::initializer_list range, const Func& func) +{ + async::parallel_for(async::make_range(range.begin(), range.end()), func); +} + +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/parallel_invoke.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/parallel_invoke.h new file mode 100644 index 0000000..0734bb6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/parallel_invoke.h @@ -0,0 +1,70 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { +namespace detail { + +// Recursively split the arguments so tasks are spawned in parallel +template +struct parallel_invoke_internal { + template + static void run(Sched& sched, const Tuple& args) + { + auto&& t = async::local_spawn(sched, [&sched, &args] { + parallel_invoke_internal::run(sched, args); + }); + parallel_invoke_internal::run(sched, args); + t.get(); + } +}; +template +struct parallel_invoke_internal { + template + static void run(Sched&, const Tuple& args) + { + // Make sure to preserve the rvalue/lvalue-ness of the original parameter + std::forward::type>(std::get(args))(); + } +}; +template +struct parallel_invoke_internal { + template + static void run(Sched&, const Tuple&) {} +}; + +} // namespace detail + +// Run several functions in parallel, optionally using the specified scheduler. +template +typename std::enable_if::value>::type parallel_invoke(Sched& sched, Args&&... args) +{ + detail::parallel_invoke_internal<0, sizeof...(Args)>::run(sched, std::forward_as_tuple(std::forward(args)...)); +} +template +void parallel_invoke(Args&&... args) +{ + async::parallel_invoke(::async::default_scheduler(), std::forward(args)...); +} + +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/parallel_reduce.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/parallel_reduce.h new file mode 100644 index 0000000..06545f6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/parallel_reduce.h @@ -0,0 +1,109 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { +namespace detail { + +// Default map function which simply passes its parameter through unmodified +struct default_map { + template + T&& operator()(T&& x) const + { + return std::forward(x); + } +}; + +// Internal implementation of parallel_map_reduce that only accepts a +// partitioner argument. +template +Result internal_parallel_map_reduce(Sched& sched, Partitioner partitioner, Result init, const MapFunc& map, const ReduceFunc& reduce) +{ + // Split the partition, run inline if no more splits are possible + auto subpart = partitioner.split(); + if (subpart.begin() == subpart.end()) { + Result out = init; + for (auto&& i: partitioner) + out = reduce(std::move(out), map(std::forward(i))); + return out; + } + + // Run the function over each half in parallel + auto&& t = async::local_spawn(sched, [&sched, &subpart, init, &map, &reduce] { + return detail::internal_parallel_map_reduce(sched, std::move(subpart), init, map, reduce); + }); + Result out = detail::internal_parallel_map_reduce(sched, std::move(partitioner), init, map, reduce); + return reduce(std::move(out), t.get()); +} + +} // namespace detail + +// Run a function for each element in a range and then reduce the results of that function to a single value +template +Result parallel_map_reduce(Sched& sched, Range&& range, Result init, const MapFunc& map, const ReduceFunc& reduce) +{ + return detail::internal_parallel_map_reduce(sched, async::to_partitioner(std::forward(range)), init, map, reduce); +} + +// Overload with default scheduler +template +Result parallel_map_reduce(Range&& range, Result init, const MapFunc& map, const ReduceFunc& reduce) +{ + return async::parallel_map_reduce(::async::default_scheduler(), range, init, map, reduce); +} + +// Overloads with std::initializer_list +template +Result parallel_map_reduce(Sched& sched, std::initializer_list range, Result init, const MapFunc& map, const ReduceFunc& reduce) +{ + return async::parallel_map_reduce(sched, async::make_range(range.begin(), range.end()), init, map, reduce); +} +template +Result parallel_map_reduce(std::initializer_list range, Result init, const MapFunc& map, const ReduceFunc& reduce) +{ + return async::parallel_map_reduce(async::make_range(range.begin(), range.end()), init, map, reduce); +} + +// Variant with identity map operation +template +Result parallel_reduce(Sched& sched, Range&& range, Result init, const ReduceFunc& reduce) +{ + return async::parallel_map_reduce(sched, range, init, detail::default_map(), reduce); +} +template +Result parallel_reduce(Range&& range, Result init, const ReduceFunc& reduce) +{ + return async::parallel_reduce(::async::default_scheduler(), range, init, reduce); +} +template +Result parallel_reduce(Sched& sched, std::initializer_list range, Result init, const ReduceFunc& reduce) +{ + return async::parallel_reduce(sched, async::make_range(range.begin(), range.end()), init, reduce); +} +template +Result parallel_reduce(std::initializer_list range, Result init, const ReduceFunc& reduce) +{ + return async::parallel_reduce(async::make_range(range.begin(), range.end()), init, reduce); +} + +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/partitioner.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/partitioner.h new file mode 100644 index 0000000..f6403bd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/partitioner.h @@ -0,0 +1,196 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { +namespace detail { + +// Partitioners are essentially ranges with an extra split() function. The +// split() function returns a partitioner containing a range to be executed in a +// child task and modifies the parent partitioner's range to represent the rest +// of the original range. If the range cannot be split any more then split() +// should return an empty range. + +// Detect whether a range is a partitioner +template().split())> +two& is_partitioner_helper(int); +template +one& is_partitioner_helper(...); +template +struct is_partitioner: public std::integral_constant(0)) - 1> {}; + +// Automatically determine a grain size for a sequence length +inline std::size_t auto_grain_size(std::size_t dist) +{ + // Determine the grain size automatically using a heuristic + std::size_t grain = dist / (8 * hardware_concurrency()); + if (grain < 1) + grain = 1; + if (grain > 2048) + grain = 2048; + return grain; +} + +template +class static_partitioner_impl { + Iter iter_begin, iter_end; + std::size_t grain; + +public: + static_partitioner_impl(Iter begin_, Iter end_, std::size_t grain_) + : iter_begin(begin_), iter_end(end_), grain(grain_) {} + Iter begin() const + { + return iter_begin; + } + Iter end() const + { + return iter_end; + } + static_partitioner_impl split() + { + // Don't split if below grain size + std::size_t length = std::distance(iter_begin, iter_end); + static_partitioner_impl out(iter_end, iter_end, grain); + if (length <= grain) + return out; + + // Split our range in half + iter_end = iter_begin; + std::advance(iter_end, (length + 1) / 2); + out.iter_begin = iter_end; + return out; + } +}; + +template +class auto_partitioner_impl { + Iter iter_begin, iter_end; + std::size_t grain; + std::size_t num_threads; + std::thread::id last_thread; + +public: + // thread_id is initialized to "no thread" and will be set on first split + auto_partitioner_impl(Iter begin_, Iter end_, std::size_t grain_) + : iter_begin(begin_), iter_end(end_), grain(grain_) {} + Iter begin() const + { + return iter_begin; + } + Iter end() const + { + return iter_end; + } + auto_partitioner_impl split() + { + // Don't split if below grain size + std::size_t length = std::distance(iter_begin, iter_end); + auto_partitioner_impl out(iter_end, iter_end, grain); + if (length <= grain) + return out; + + // Check if we are in a different thread than we were before + std::thread::id current_thread = std::this_thread::get_id(); + if (current_thread != last_thread) + num_threads = hardware_concurrency(); + + // If we only have one thread, don't split + if (num_threads <= 1) + return out; + + // Split our range in half + iter_end = iter_begin; + std::advance(iter_end, (length + 1) / 2); + out.iter_begin = iter_end; + out.last_thread = current_thread; + last_thread = current_thread; + out.num_threads = num_threads / 2; + num_threads -= out.num_threads; + return out; + } +}; + +} // namespace detail + +// A simple partitioner which splits until a grain size is reached. If a grain +// size is not specified, one is chosen automatically. +template +detail::static_partitioner_impl()))> static_partitioner(Range&& range, std::size_t grain) +{ + return {std::begin(range), std::end(range), grain}; +} +template +detail::static_partitioner_impl()))> static_partitioner(Range&& range) +{ + std::size_t grain = detail::auto_grain_size(std::distance(std::begin(range), std::end(range))); + return {std::begin(range), std::end(range), grain}; +} + +// A more advanced partitioner which initially divides the range into one chunk +// for each available thread. The range is split further if a chunk gets stolen +// by a different thread. +template +detail::auto_partitioner_impl()))> auto_partitioner(Range&& range) +{ + std::size_t grain = detail::auto_grain_size(std::distance(std::begin(range), std::end(range))); + return {std::begin(range), std::end(range), grain}; +} + +// Wrap a range in a partitioner. If the input is already a partitioner then it +// is returned unchanged. This allows parallel algorithms to accept both ranges +// and partitioners as parameters. +template +typename std::enable_if::type>::value, Partitioner&&>::type to_partitioner(Partitioner&& partitioner) +{ + return std::forward(partitioner); +} +template +typename std::enable_if::type>::value, detail::auto_partitioner_impl()))>>::type to_partitioner(Range&& range) +{ + return async::auto_partitioner(std::forward(range)); +} + +// Overloads with std::initializer_list +template +detail::static_partitioner_impl>().begin())> static_partitioner(std::initializer_list range) +{ + return async::static_partitioner(async::make_range(range.begin(), range.end())); +} +template +detail::static_partitioner_impl>().begin())> static_partitioner(std::initializer_list range, std::size_t grain) +{ + return async::static_partitioner(async::make_range(range.begin(), range.end()), grain); +} +template +detail::auto_partitioner_impl>().begin())> auto_partitioner(std::initializer_list range) +{ + return async::auto_partitioner(async::make_range(range.begin(), range.end())); +} +template +detail::auto_partitioner_impl>().begin())> to_partitioner(std::initializer_list range) +{ + return async::auto_partitioner(async::make_range(range.begin(), range.end())); +} + +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/range.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/range.h new file mode 100644 index 0000000..d23ee0c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/range.h @@ -0,0 +1,182 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { + +// Range type representing a pair of iterators +template +class range { + Iter iter_begin, iter_end; + +public: + range() = default; + range(Iter a, Iter b) + : iter_begin(a), iter_end(b) {} + + Iter begin() const + { + return iter_begin; + } + Iter end() const + { + return iter_end; + } +}; + +// Construct a range from 2 iterators +template +range make_range(Iter begin, Iter end) +{ + return {begin, end}; +} + +// A range of integers +template +class int_range { + T value_begin, value_end; + + static_assert(std::is_integral::value, "int_range can only be used with integral types"); + +public: + class iterator { + T current; + + explicit iterator(T a) + : current(a) {} + friend class int_range; + + public: + typedef T value_type; + typedef std::ptrdiff_t difference_type; + typedef iterator pointer; + typedef T reference; + typedef std::random_access_iterator_tag iterator_category; + + iterator() = default; + + T operator*() const + { + return current; + } + T operator[](difference_type offset) const + { + return current + offset; + } + + iterator& operator++() + { + ++current; + return *this; + } + iterator operator++(int) + { + return iterator(current++); + } + iterator& operator--() + { + --current; + return *this; + } + iterator operator--(int) + { + return iterator(current--); + } + + iterator& operator+=(difference_type offset) + { + current += offset; + return *this; + } + iterator& operator-=(difference_type offset) + { + current -= offset; + return *this; + } + + iterator operator+(difference_type offset) const + { + return iterator(current + offset); + } + iterator operator-(difference_type offset) const + { + return iterator(current - offset); + } + + friend iterator operator+(difference_type offset, iterator other) + { + return other + offset; + } + + friend difference_type operator-(iterator a, iterator b) + { + return a.current - b.current; + } + + friend bool operator==(iterator a, iterator b) + { + return a.current == b.current; + } + friend bool operator!=(iterator a, iterator b) + { + return a.current != b.current; + } + friend bool operator>(iterator a, iterator b) + { + return a.current > b.current; + } + friend bool operator<(iterator a, iterator b) + { + return a.current < b.current; + } + friend bool operator>=(iterator a, iterator b) + { + return a.current >= b.current; + } + friend bool operator<=(iterator a, iterator b) + { + return a.current <= b.current; + } + }; + + int_range(T begin, T end) + : value_begin(begin), value_end(end) {} + + iterator begin() const + { + return iterator(value_begin); + } + iterator end() const + { + return iterator(value_end); + } +}; + +// Construct an int_range between 2 values +template +int_range::type> irange(T begin, U end) +{ + return {begin, end}; +} + +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/ref_count.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/ref_count.h new file mode 100644 index 0000000..5eb1185 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/ref_count.h @@ -0,0 +1,177 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { +namespace detail { + +// Default deleter which just uses the delete keyword +template +struct default_deleter { + static void do_delete(T* p) + { + delete p; + } +}; + +// Reference-counted object base class +template> +struct ref_count_base { + std::atomic ref_count; + + // By default the reference count is initialized to 1 + explicit ref_count_base(std::size_t count = 1) + : ref_count(count) {} + + void add_ref(std::size_t count = 1) + { + ref_count.fetch_add(count, std::memory_order_relaxed); + } + void remove_ref(std::size_t count = 1) + { + if (ref_count.fetch_sub(count, std::memory_order_release) == count) { + std::atomic_thread_fence(std::memory_order_acquire); + Deleter::do_delete(static_cast(this)); + } + } + void add_ref_unlocked() + { + ref_count.store(ref_count.load(std::memory_order_relaxed) + 1, std::memory_order_relaxed); + } + bool is_unique_ref(std::memory_order order) + { + return ref_count.load(order) == 1; + } +}; + +// Pointer to reference counted object, based on boost::intrusive_ptr +template +class ref_count_ptr { + T* p; + +public: + // Note that this doesn't increment the reference count, instead it takes + // ownership of a pointer which you already own a reference to. + explicit ref_count_ptr(T* t) + : p(t) {} + + ref_count_ptr() + : p(nullptr) {} + ref_count_ptr(std::nullptr_t) + : p(nullptr) {} + ref_count_ptr(const ref_count_ptr& other) LIBASYNC_NOEXCEPT + : p(other.p) + { + if (p) + p->add_ref(); + } + ref_count_ptr(ref_count_ptr&& other) LIBASYNC_NOEXCEPT + : p(other.p) + { + other.p = nullptr; + } + ref_count_ptr& operator=(std::nullptr_t) + { + if (p) + p->remove_ref(); + p = nullptr; + return *this; + } + ref_count_ptr& operator=(const ref_count_ptr& other) LIBASYNC_NOEXCEPT + { + if (p) { + p->remove_ref(); + p = nullptr; + } + p = other.p; + if (p) + p->add_ref(); + return *this; + } + ref_count_ptr& operator=(ref_count_ptr&& other) LIBASYNC_NOEXCEPT + { + if (p) { + p->remove_ref(); + p = nullptr; + } + p = other.p; + other.p = nullptr; + return *this; + } + ~ref_count_ptr() + { + if (p) + p->remove_ref(); + } + + T& operator*() const + { + return *p; + } + T* operator->() const + { + return p; + } + T* get() const + { + return p; + } + T* release() + { + T* out = p; + p = nullptr; + return out; + } + + explicit operator bool() const + { + return p != nullptr; + } + friend bool operator==(const ref_count_ptr& a, const ref_count_ptr& b) + { + return a.p == b.p; + } + friend bool operator!=(const ref_count_ptr& a, const ref_count_ptr& b) + { + return a.p != b.p; + } + friend bool operator==(const ref_count_ptr& a, std::nullptr_t) + { + return a.p == nullptr; + } + friend bool operator!=(const ref_count_ptr& a, std::nullptr_t) + { + return a.p != nullptr; + } + friend bool operator==(std::nullptr_t, const ref_count_ptr& a) + { + return a.p == nullptr; + } + friend bool operator!=(std::nullptr_t, const ref_count_ptr& a) + { + return a.p != nullptr; + } +}; + +} // namespace detail +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/scheduler.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/scheduler.h new file mode 100644 index 0000000..6718095 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/scheduler.h @@ -0,0 +1,175 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { + +// Improved version of std::hardware_concurrency: +// - It never returns 0, 1 is returned instead. +// - It is guaranteed to remain constant for the duration of the program. +LIBASYNC_EXPORT std::size_t hardware_concurrency() LIBASYNC_NOEXCEPT; + +// Task handle used by a wait handler +class task_wait_handle { + detail::task_base* handle; + + // Allow construction in wait_for_task() + friend LIBASYNC_EXPORT void detail::wait_for_task(detail::task_base* t); + task_wait_handle(detail::task_base* t) + : handle(t) {} + + // Execution function for use by wait handlers + template + struct wait_exec_func: private detail::func_base { + template + explicit wait_exec_func(F&& f) + : detail::func_base(std::forward(f)) {} + void operator()(detail::task_base*) + { + // Just call the function directly, all this wrapper does is remove + // the task_base* parameter. + this->get_func()(); + } + }; + +public: + task_wait_handle() + : handle(nullptr) {} + + // Check if the handle is valid + explicit operator bool() const + { + return handle != nullptr; + } + + // Check if the task has finished executing + bool ready() const + { + return detail::is_finished(handle->state.load(std::memory_order_acquire)); + } + + // Queue a function to be executed when the task has finished executing. + template + void on_finish(Func&& func) + { + // Make sure the function type is callable + static_assert(detail::is_callable::value, "Invalid function type passed to on_finish()"); + + auto cont = new detail::task_func::type, wait_exec_func::type>, detail::fake_void>(std::forward(func)); + cont->sched = std::addressof(inline_scheduler()); + handle->add_continuation(inline_scheduler(), detail::task_ptr(cont)); + } +}; + +// Wait handler function prototype +typedef void (*wait_handler)(task_wait_handle t); + +// Set a wait handler to control what a task does when it has "free time", which +// is when it is waiting for another task to complete. The wait handler can do +// other work, but should return when it detects that the task has completed. +// The previously installed handler is returned. +LIBASYNC_EXPORT wait_handler set_thread_wait_handler(wait_handler w) LIBASYNC_NOEXCEPT; + +// Exception thrown if a task_run_handle is destroyed without being run +struct LIBASYNC_EXPORT_EXCEPTION task_not_executed {}; + +// Task handle used in scheduler, acts as a unique_ptr to a task object +class task_run_handle { + detail::task_ptr handle; + + // Allow construction in schedule_task() + template + friend void detail::schedule_task(Sched& sched, detail::task_ptr t); + explicit task_run_handle(detail::task_ptr t) + : handle(std::move(t)) {} + +public: + // Movable but not copyable + task_run_handle() = default; + task_run_handle(task_run_handle&& other) LIBASYNC_NOEXCEPT + : handle(std::move(other.handle)) {} + task_run_handle& operator=(task_run_handle&& other) LIBASYNC_NOEXCEPT + { + handle = std::move(other.handle); + return *this; + } + + // If the task is not executed, cancel it with an exception + ~task_run_handle() + { + if (handle) + handle->vtable->cancel(handle.get(), std::make_exception_ptr(task_not_executed())); + } + + // Check if the handle is valid + explicit operator bool() const + { + return handle != nullptr; + } + + // Run the task and release the handle + void run() + { + handle->vtable->run(handle.get()); + handle = nullptr; + } + + // Run the task but run the given wait handler when waiting for a task, + // instead of just sleeping. + void run_with_wait_handler(wait_handler handler) + { + wait_handler old = set_thread_wait_handler(handler); + run(); + set_thread_wait_handler(old); + } + + // Conversion to and from void pointer. This allows the task handle to be + // sent through C APIs which don't preserve types. + void* to_void_ptr() + { + return handle.release(); + } + static task_run_handle from_void_ptr(void* ptr) + { + return task_run_handle(detail::task_ptr(static_cast(ptr))); + } +}; + +namespace detail { + +// Schedule a task for execution using its scheduler +template +void schedule_task(Sched& sched, task_ptr t) +{ + static_assert(is_scheduler::value, "Type is not a valid scheduler"); + sched.schedule(task_run_handle(std::move(t))); +} + +// Inline scheduler implementation +inline void inline_scheduler_impl::schedule(task_run_handle t) +{ + t.run(); +} + +} // namespace detail +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/scheduler_fwd.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/scheduler_fwd.h new file mode 100644 index 0000000..6e124b0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/scheduler_fwd.h @@ -0,0 +1,157 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { + +// Forward declarations +class task_run_handle; +class threadpool_scheduler; + +// Scheduler interface: +// A scheduler is any type that implements this function: +// void schedule(async::task_run_handle t); +// This function should result in t.run() being called at some future point. + +namespace detail { + +// Detect whether an object is a scheduler +template().schedule(std::declval()))> +two& is_scheduler_helper(int); +template +one& is_scheduler_helper(...); +template +struct is_scheduler: public std::integral_constant(0)) - 1> {}; + +// Singleton scheduler classes +class thread_scheduler_impl { +public: + LIBASYNC_EXPORT static void schedule(task_run_handle t); +}; +class inline_scheduler_impl { +public: + static void schedule(task_run_handle t); +}; + +// Reference counted pointer to task data +struct task_base; +typedef ref_count_ptr task_ptr; + +// Helper function to schedule a task using a scheduler +template +void schedule_task(Sched& sched, task_ptr t); + +// Wait for the given task to finish. This will call the wait handler currently +// active for this thread, which causes the thread to sleep by default. +LIBASYNC_EXPORT void wait_for_task(task_base* wait_task); + +// Forward-declaration for data used by threadpool_scheduler +struct threadpool_data; + +} // namespace detail + +// Run a task in the current thread as soon as it is scheduled +inline detail::inline_scheduler_impl& inline_scheduler() +{ + static detail::inline_scheduler_impl instance; + return instance; +} + +// Run a task in a separate thread. Note that this scheduler does not wait for +// threads to finish at process exit. You must ensure that all threads finish +// before ending the process. +inline detail::thread_scheduler_impl& thread_scheduler() +{ + static detail::thread_scheduler_impl instance; + return instance; +} + +// Built-in thread pool scheduler with a size that is configurable from the +// LIBASYNC_NUM_THREADS environment variable. If that variable does not exist +// then the number of CPUs in the system is used instead. +LIBASYNC_EXPORT threadpool_scheduler& default_threadpool_scheduler(); + +// Default scheduler that is used when one isn't specified. This defaults to +// default_threadpool_scheduler(), but can be overriden by defining +// LIBASYNC_CUSTOM_DEFAULT_SCHEDULER before including async++.h. Keep in mind +// that in that case async::default_scheduler should be declared before +// including async++.h. +#ifndef LIBASYNC_CUSTOM_DEFAULT_SCHEDULER +inline threadpool_scheduler& default_scheduler() +{ + return default_threadpool_scheduler(); +} +#endif + +// Scheduler that holds a list of tasks which can then be explicitly executed +// by a thread. Both adding and running tasks are thread-safe operations. +class fifo_scheduler { + struct internal_data; + std::unique_ptr impl; + +public: + LIBASYNC_EXPORT fifo_scheduler(); + LIBASYNC_EXPORT ~fifo_scheduler(); + + // Add a task to the queue + LIBASYNC_EXPORT void schedule(task_run_handle t); + + // Try running one task from the queue. Returns false if the queue was empty. + LIBASYNC_EXPORT bool try_run_one_task(); + + // Run all tasks in the queue + LIBASYNC_EXPORT void run_all_tasks(); +}; + +// Scheduler that runs tasks in a work-stealing thread pool of the given size. +// Note that destroying the thread pool before all tasks have completed may +// result in some tasks not being executed. +class threadpool_scheduler { + std::unique_ptr impl; + +public: + LIBASYNC_EXPORT threadpool_scheduler(threadpool_scheduler&& other); + + // Create a thread pool with the given number of threads + LIBASYNC_EXPORT threadpool_scheduler(std::size_t num_threads); + + // Create a thread pool with the given number of threads. Call `prerun` + // function before execution loop and `postrun` after. + LIBASYNC_EXPORT threadpool_scheduler(std::size_t num_threads, + std::function&& prerun_, + std::function&& postrun_); + + // Destroy the thread pool, tasks that haven't been started are dropped + LIBASYNC_EXPORT ~threadpool_scheduler(); + + // Schedule a task to be run in the thread pool + LIBASYNC_EXPORT void schedule(task_run_handle t); +}; + +namespace detail { + +// Work-around for Intel compiler handling decltype poorly in function returns +typedef std::remove_reference::type default_scheduler_type; + +} // namespace detail +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/task.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/task.h new file mode 100644 index 0000000..7735c30 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/task.h @@ -0,0 +1,579 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { + +// Exception thrown when an event_task is destroyed without setting a value +struct LIBASYNC_EXPORT_EXCEPTION abandoned_event_task {}; + +namespace detail { + +// Common code for task and shared_task +template +class basic_task { + // Reference counted internal task object + detail::task_ptr internal_task; + + // Real result type, with void turned into fake_void + typedef typename void_to_fake_void::type internal_result; + + // Type-specific task object + typedef task_result internal_task_type; + + // Friend access + friend async::task; + friend async::shared_task; + template + friend typename T::internal_task_type* get_internal_task(const T& t); + template + friend void set_internal_task(T& t, task_ptr p); + + // Common code for get() + void get_internal() const + { + LIBASYNC_ASSERT(internal_task, std::invalid_argument, "Use of empty task object"); + + // If the task was canceled, throw the associated exception + get_internal_task(*this)->wait_and_throw(); + } + + // Common code for then() + template + typename continuation_traits::task_type then_internal(Sched& sched, Func&& f, Parent&& parent) const + { + LIBASYNC_ASSERT(internal_task, std::invalid_argument, "Use of empty task object"); + + // Save a copy of internal_task because it might get moved into exec_func + task_base* my_internal = internal_task.get(); + + // Create continuation + typedef continuation_traits traits; + typedef typename void_to_fake_void::type cont_internal_result; + typedef continuation_exec_func::type, cont_internal_result, typename traits::decay_func, typename traits::is_value_cont, is_task::value> exec_func; + typename traits::task_type cont; + set_internal_task(cont, task_ptr(new task_func(std::forward(f), std::forward(parent)))); + + // Add the continuation to this task + // Avoid an expensive ref-count modification since the task isn't shared yet + get_internal_task(cont)->add_ref_unlocked(); + get_internal_task(cont)->sched = std::addressof(sched); + my_internal->add_continuation(sched, task_ptr(get_internal_task(cont))); + + return cont; + } + +public: + // Task result type + typedef Result result_type; + + // Check if this task is not empty + bool valid() const + { + return internal_task != nullptr; + } + + // Query whether the task has finished executing + bool ready() const + { + LIBASYNC_ASSERT(internal_task, std::invalid_argument, "Use of empty task object"); + return internal_task->ready(); + } + + // Query whether the task has been canceled with an exception + bool canceled() const + { + LIBASYNC_ASSERT(internal_task, std::invalid_argument, "Use of empty task object"); + return internal_task->state.load(std::memory_order_acquire) == task_state::canceled; + } + + // Wait for the task to complete + void wait() const + { + LIBASYNC_ASSERT(internal_task, std::invalid_argument, "Use of empty task object"); + internal_task->wait(); + } + + // Get the exception associated with a canceled task + std::exception_ptr get_exception() const + { + LIBASYNC_ASSERT(internal_task, std::invalid_argument, "Use of empty task object"); + if (internal_task->wait() == task_state::canceled) + return get_internal_task(*this)->get_exception(); + else + return std::exception_ptr(); + } +}; + +// Common code for event_task specializations +template +class basic_event { + // Reference counted internal task object + detail::task_ptr internal_task; + + // Real result type, with void turned into fake_void + typedef typename detail::void_to_fake_void::type internal_result; + + // Type-specific task object + typedef detail::task_result internal_task_type; + + // Friend access + friend async::event_task; + template + friend typename T::internal_task_type* get_internal_task(const T& t); + + // Common code for set() + template + bool set_internal(T&& result) const + { + LIBASYNC_ASSERT(internal_task, std::invalid_argument, "Use of empty event_task object"); + + // Only allow setting the value once + detail::task_state expected = detail::task_state::pending; + if (!internal_task->state.compare_exchange_strong(expected, detail::task_state::locked, std::memory_order_acquire, std::memory_order_relaxed)) + return false; + + LIBASYNC_TRY { + // Store the result and finish + get_internal_task(*this)->set_result(std::forward(result)); + internal_task->finish(); + } LIBASYNC_CATCH(...) { + // At this point we have already committed to setting a value, so + // we can't return the exception to the caller. If we did then it + // could cause concurrent set() calls to fail, thinking a value has + // already been set. Instead, we simply cancel the task with the + // exception we just got. + get_internal_task(*this)->cancel_base(std::current_exception()); + } + return true; + } + +public: + // Movable but not copyable + basic_event(basic_event&& other) LIBASYNC_NOEXCEPT + : internal_task(std::move(other.internal_task)) {} + basic_event& operator=(basic_event&& other) LIBASYNC_NOEXCEPT + { + internal_task = std::move(other.internal_task); + return *this; + } + + // Main constructor + basic_event() + : internal_task(new internal_task_type) + { + internal_task->event_task_got_task = false; + } + + // Cancel events if they are destroyed before they are set + ~basic_event() + { + // This check isn't thread-safe but set_exception does a proper check + if (internal_task && !internal_task->ready() && !internal_task->is_unique_ref(std::memory_order_relaxed)) { +#ifdef LIBASYNC_NO_EXCEPTIONS + // This will result in an abort if the task result is read + set_exception(std::exception_ptr()); +#else + set_exception(std::make_exception_ptr(abandoned_event_task())); +#endif + } + } + + // Get the task linked to this event. This can only be called once. + task get_task() + { + LIBASYNC_ASSERT(internal_task, std::invalid_argument, "Use of empty event_task object"); + LIBASYNC_ASSERT(!internal_task->event_task_got_task, std::logic_error, "get_task() called twice on event_task"); + + // Even if we didn't trigger an assert, don't return a task if one has + // already been returned. + task out; + if (!internal_task->event_task_got_task) + set_internal_task(out, internal_task); + internal_task->event_task_got_task = true; + return out; + } + + // Cancel the event with an exception and cancel continuations + bool set_exception(std::exception_ptr except) const + { + LIBASYNC_ASSERT(internal_task, std::invalid_argument, "Use of empty event_task object"); + + // Only allow setting the value once + detail::task_state expected = detail::task_state::pending; + if (!internal_task->state.compare_exchange_strong(expected, detail::task_state::locked, std::memory_order_acquire, std::memory_order_relaxed)) + return false; + + // Cancel the task + get_internal_task(*this)->cancel_base(std::move(except)); + return true; + } +}; + +} // namespace detail + +template +class task: public detail::basic_task { +public: + // Movable but not copyable + task() = default; + task(task&& other) LIBASYNC_NOEXCEPT + : detail::basic_task(std::move(other)) {} + task& operator=(task&& other) LIBASYNC_NOEXCEPT + { + detail::basic_task::operator=(std::move(other)); + return *this; + } + + // Get the result of the task + Result get() + { + this->get_internal(); + + // Move the internal state pointer so that the task becomes invalid, + // even if an exception is thrown. + detail::task_ptr my_internal = std::move(this->internal_task); + return detail::fake_void_to_void(static_cast(my_internal.get())->get_result(*this)); + } + + // Add a continuation to the task + template + typename detail::continuation_traits::task_type then(Sched& sched, Func&& f) + { + return this->then_internal(sched, std::forward(f), std::move(*this)); + } + template + typename detail::continuation_traits::task_type then(Func&& f) + { + return then(::async::default_scheduler(), std::forward(f)); + } + + // Create a shared_task from this task + shared_task share() + { + LIBASYNC_ASSERT(this->internal_task, std::invalid_argument, "Use of empty task object"); + + shared_task out; + detail::set_internal_task(out, std::move(this->internal_task)); + return out; + } +}; + +template +class shared_task: public detail::basic_task { + // get() return value: const Result& -or- void + typedef typename std::conditional< + std::is_void::value, + void, + typename std::add_lvalue_reference< + typename std::add_const::type + >::type + >::type get_result; + +public: + // Movable and copyable + shared_task() = default; + + // Get the result of the task + get_result get() const + { + this->get_internal(); + return detail::fake_void_to_void(detail::get_internal_task(*this)->get_result(*this)); + } + + // Add a continuation to the task + template + typename detail::continuation_traits::task_type then(Sched& sched, Func&& f) const + { + return this->then_internal(sched, std::forward(f), *this); + } + template + typename detail::continuation_traits::task_type then(Func&& f) const + { + return then(::async::default_scheduler(), std::forward(f)); + } +}; + +// Special task type which can be triggered manually rather than when a function executes. +template +class event_task: public detail::basic_event { +public: + // Movable but not copyable + event_task() = default; + event_task(event_task&& other) LIBASYNC_NOEXCEPT + : detail::basic_event(std::move(other)) {} + event_task& operator=(event_task&& other) LIBASYNC_NOEXCEPT + { + detail::basic_event::operator=(std::move(other)); + return *this; + } + + // Set the result of the task, mark it as completed and run its continuations + bool set(const Result& result) const + { + return this->set_internal(result); + } + bool set(Result&& result) const + { + return this->set_internal(std::move(result)); + } +}; + +// Specialization for references +template +class event_task: public detail::basic_event { +public: + // Movable but not copyable + event_task() = default; + event_task(event_task&& other) LIBASYNC_NOEXCEPT + : detail::basic_event(std::move(other)) {} + event_task& operator=(event_task&& other) LIBASYNC_NOEXCEPT + { + detail::basic_event::operator=(std::move(other)); + return *this; + } + + // Set the result of the task, mark it as completed and run its continuations + bool set(Result& result) const + { + return this->set_internal(result); + } +}; + +// Specialization for void +template<> +class event_task: public detail::basic_event { +public: + // Movable but not copyable + event_task() = default; + event_task(event_task&& other) LIBASYNC_NOEXCEPT + : detail::basic_event(std::move(other)) {} + event_task& operator=(event_task&& other) LIBASYNC_NOEXCEPT + { + detail::basic_event::operator=(std::move(other)); + return *this; + } + + // Set the result of the task, mark it as completed and run its continuations + bool set() + { + return this->set_internal(detail::fake_void()); + } +}; + +// Task type returned by local_spawn() +template +class local_task { + // Make sure the function type is callable + typedef typename std::decay::type decay_func; + static_assert(detail::is_callable::value, "Invalid function type passed to local_spawn()"); + + // Task result type + typedef typename detail::remove_task()())>::type result_type; + typedef typename detail::void_to_fake_void::type internal_result; + + // Task execution function type + typedef detail::root_exec_func()())>::value> exec_func; + + // Task object embedded directly. The ref-count is initialized to 1 so it + // will never be freed using delete, only when the local_task is destroyed. + detail::task_func internal_task; + + // Friend access for local_spawn + template + friend local_task local_spawn(S& sched, F&& f); + template + friend local_task local_spawn(F&& f); + + // Constructor, used by local_spawn + local_task(Sched& sched, Func&& f) + : internal_task(std::forward(f)) + { + // Avoid an expensive ref-count modification since the task isn't shared yet + internal_task.add_ref_unlocked(); + detail::schedule_task(sched, detail::task_ptr(&internal_task)); + } + +public: + // Non-movable and non-copyable + local_task(const local_task&) = delete; + local_task& operator=(const local_task&) = delete; + + // Wait for the task to complete when destroying + ~local_task() + { + wait(); + + // Now spin until the reference count drops to 1, since the scheduler + // may still have a reference to the task. + while (!internal_task.is_unique_ref(std::memory_order_acquire)) { +#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20140612 + // Some versions of libstdc++ (4.7 and below) don't include a + // definition of std::this_thread::yield(). + sched_yield(); +#else + std::this_thread::yield(); +#endif + } + } + + // Query whether the task has finished executing + bool ready() const + { + return internal_task.ready(); + } + + // Query whether the task has been canceled with an exception + bool canceled() const + { + return internal_task.state.load(std::memory_order_acquire) == detail::task_state::canceled; + } + + // Wait for the task to complete + void wait() + { + internal_task.wait(); + } + + // Get the result of the task + result_type get() + { + internal_task.wait_and_throw(); + return detail::fake_void_to_void(internal_task.get_result(task())); + } + + // Get the exception associated with a canceled task + std::exception_ptr get_exception() const + { + if (internal_task.wait() == detail::task_state::canceled) + return internal_task.get_exception(); + else + return std::exception_ptr(); + } +}; + +// Spawn a function asynchronously +#if (__cplusplus >= 201703L) +// Use std::invoke_result instead of std::result_of for C++17 or greater because std::result_of was deprecated in C++17 and removed in C++20 +template +task>>::type> spawn(Sched& sched, Func&& f) +#else +template +task::type()>::type>::type> spawn(Sched& sched, Func&& f) +#endif +{ + // Using result_of in the function return type to work around bugs in the Intel + // C++ compiler. + + // Make sure the function type is callable + typedef typename std::decay::type decay_func; + static_assert(detail::is_callable::value, "Invalid function type passed to spawn()"); + + // Create task + typedef typename detail::void_to_fake_void()())>::type>::type internal_result; + typedef detail::root_exec_func()())>::value> exec_func; + task()())>::type> out; + detail::set_internal_task(out, detail::task_ptr(new detail::task_func(std::forward(f)))); + + // Avoid an expensive ref-count modification since the task isn't shared yet + detail::get_internal_task(out)->add_ref_unlocked(); + detail::schedule_task(sched, detail::task_ptr(detail::get_internal_task(out))); + + return out; +} +template +decltype(async::spawn(::async::default_scheduler(), std::declval())) spawn(Func&& f) +{ + return async::spawn(::async::default_scheduler(), std::forward(f)); +} + +// Create a completed task containing a value +template +task::type> make_task(T&& value) +{ + task::type> out; + + detail::set_internal_task(out, detail::task_ptr(new detail::task_result::type>)); + detail::get_internal_task(out)->set_result(std::forward(value)); + detail::get_internal_task(out)->state.store(detail::task_state::completed, std::memory_order_relaxed); + + return out; +} +template +task make_task(std::reference_wrapper value) +{ + task out; + + detail::set_internal_task(out, detail::task_ptr(new detail::task_result)); + detail::get_internal_task(out)->set_result(value.get()); + detail::get_internal_task(out)->state.store(detail::task_state::completed, std::memory_order_relaxed); + + return out; +} +inline task make_task() +{ + task out; + + detail::set_internal_task(out, detail::task_ptr(new detail::task_result)); + detail::get_internal_task(out)->state.store(detail::task_state::completed, std::memory_order_relaxed); + + return out; +} + +// Create a canceled task containing an exception +template +task make_exception_task(std::exception_ptr except) +{ + task out; + + detail::set_internal_task(out, detail::task_ptr(new detail::task_result::type>)); + detail::get_internal_task(out)->set_exception(std::move(except)); + detail::get_internal_task(out)->state.store(detail::task_state::canceled, std::memory_order_relaxed); + + return out; +} + +// Spawn a very limited task which is restricted to the current function and +// joins on destruction. Because local_task is not movable, the result must +// be captured in a reference, like this: +// auto&& x = local_spawn(...); +template +#ifdef __GNUC__ +__attribute__((warn_unused_result)) +#endif +local_task local_spawn(Sched& sched, Func&& f) +{ + // Since local_task is not movable, we construct it in-place and let the + // caller extend the lifetime of the returned object using a reference. + return {sched, std::forward(f)}; +} +template +#ifdef __GNUC__ +__attribute__((warn_unused_result)) +#endif +local_task local_spawn(Func&& f) +{ + return {::async::default_scheduler(), std::forward(f)}; +} + +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/task_base.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/task_base.h new file mode 100644 index 0000000..377ac8f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/task_base.h @@ -0,0 +1,615 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { +namespace detail { + +// Task states +enum class task_state: unsigned char { + pending, // Task has not completed yet + locked, // Task is locked (used by event_task to prevent double set) + unwrapped, // Task is waiting for an unwrapped task to finish + completed, // Task has finished execution and a result is available + canceled // Task has been canceled and an exception is available +}; + +// Determine whether a task is in a final state +inline bool is_finished(task_state s) +{ + return s == task_state::completed || s == task_state::canceled; +} + +// Virtual function table used to allow dynamic dispatch for task objects. +// While this is very similar to what a compiler would generate with virtual +// functions, this scheme was found to result in significantly smaller +// generated code size. +struct task_base_vtable { + // Destroy the function and result + void (*destroy)(task_base*) LIBASYNC_NOEXCEPT; + + // Run the associated function + void (*run)(task_base*) LIBASYNC_NOEXCEPT; + + // Cancel the task with an exception + void (*cancel)(task_base*, std::exception_ptr&&) LIBASYNC_NOEXCEPT; + + // Schedule the task using its scheduler + void (*schedule)(task_base* parent, task_ptr t); +}; + +// Type-generic base task object +struct task_base_deleter; +struct LIBASYNC_CACHELINE_ALIGN task_base: public ref_count_base { + // Task state + std::atomic state; + + // Whether get_task() was already called on an event_task + bool event_task_got_task; + + // Vector of continuations + continuation_vector continuations; + + // Virtual function table used for dynamic dispatch + const task_base_vtable* vtable; + + // Use aligned memory allocation + static void* operator new(std::size_t size) + { + return aligned_alloc(size, LIBASYNC_CACHELINE_SIZE); + } + static void operator delete(void* ptr) + { + aligned_free(ptr); + } + + // Initialize task state + task_base() + : state(task_state::pending) {} + + // Check whether the task is ready and include an acquire barrier if it is + bool ready() const + { + return is_finished(state.load(std::memory_order_acquire)); + } + + // Run a single continuation + template + void run_continuation(Sched& sched, task_ptr&& cont) + { + LIBASYNC_TRY { + detail::schedule_task(sched, cont); + } LIBASYNC_CATCH(...) { + // This is suboptimal, but better than letting the exception leak + cont->vtable->cancel(cont.get(), std::current_exception()); + } + } + + // Run all of the task's continuations after it has completed or canceled. + // The list of continuations is emptied and locked to prevent any further + // continuations from being added. + void run_continuations() + { + continuations.flush_and_lock([this](task_ptr t) { + const task_base_vtable* vtable_ptr = t->vtable; + vtable_ptr->schedule(this, std::move(t)); + }); + } + + // Add a continuation to this task + template + void add_continuation(Sched& sched, task_ptr cont) + { + // Check for task completion + task_state current_state = state.load(std::memory_order_relaxed); + if (!is_finished(current_state)) { + // Try to add the task to the continuation list. This can fail only + // if the task has just finished, in which case we run it directly. + if (continuations.try_add(std::move(cont))) + return; + } + + // Otherwise run the continuation directly + std::atomic_thread_fence(std::memory_order_acquire); + run_continuation(sched, std::move(cont)); + } + + // Finish the task after it has been executed and the result set + void finish() + { + state.store(task_state::completed, std::memory_order_release); + run_continuations(); + } + + // Wait for the task to finish executing + task_state wait() + { + task_state s = state.load(std::memory_order_acquire); + if (!is_finished(s)) { + wait_for_task(this); + s = state.load(std::memory_order_relaxed); + } + return s; + } +}; + +// Deleter for task_ptr +struct task_base_deleter { + static void do_delete(task_base* p) + { + // Go through the vtable to delete p with its proper type + p->vtable->destroy(p); + } +}; + +// Result type-specific task object +template +struct task_result_holder: public task_base { + union { + alignas(Result) std::uint8_t result[sizeof(Result)]; + alignas(std::exception_ptr) std::uint8_t except[sizeof(std::exception_ptr)]; + + // Scheduler that should be used to schedule this task. The scheduler + // type has been erased and is held by vtable->schedule. + void* sched; + }; + + template + void set_result(T&& t) + { + new(&result) Result(std::forward(t)); + } + + // Return a result using an lvalue or rvalue reference depending on the task + // type. The task parameter is not used, it is just there for overload resolution. + template + Result&& get_result(const task&) + { + return std::move(*reinterpret_cast(&result)); + } + template + const Result& get_result(const shared_task&) + { + return *reinterpret_cast(&result); + } + + // Destroy the result + ~task_result_holder() + { + // Result is only present if the task completed successfully + if (state.load(std::memory_order_relaxed) == task_state::completed) + reinterpret_cast(&result)->~Result(); + } +}; + +// Specialization for references +template +struct task_result_holder: public task_base { + union { + // Store as pointer internally + Result* result; + alignas(std::exception_ptr) std::uint8_t except[sizeof(std::exception_ptr)]; + void* sched; + }; + + void set_result(Result& obj) + { + result = std::addressof(obj); + } + + template + Result& get_result(const task&) + { + return *result; + } + template + Result& get_result(const shared_task&) + { + return *result; + } +}; + +// Specialization for void +template<> +struct task_result_holder: public task_base { + union { + alignas(std::exception_ptr) std::uint8_t except[sizeof(std::exception_ptr)]; + void* sched; + }; + + void set_result(fake_void) {} + + // Get the result as fake_void so that it can be passed to set_result and + // continuations + template + fake_void get_result(const task&) + { + return fake_void(); + } + template + fake_void get_result(const shared_task&) + { + return fake_void(); + } +}; + +template +struct task_result: public task_result_holder { + // Virtual function table for task_result + static const task_base_vtable vtable_impl; + task_result() + { + this->vtable = &vtable_impl; + } + + // Destroy the exception + ~task_result() + { + // Exception is only present if the task was canceled + if (this->state.load(std::memory_order_relaxed) == task_state::canceled) + reinterpret_cast(&this->except)->~exception_ptr(); + } + + // Cancel a task with the given exception + void cancel_base(std::exception_ptr&& except_) + { + set_exception(std::move(except_)); + this->state.store(task_state::canceled, std::memory_order_release); + this->run_continuations(); + } + + // Set the exception value of the task + void set_exception(std::exception_ptr&& except_) + { + new(&this->except) std::exception_ptr(std::move(except_)); + } + + // Get the exception a task was canceled with + std::exception_ptr& get_exception() + { + return *reinterpret_cast(&this->except); + } + + // Wait and throw the exception if the task was canceled + void wait_and_throw() + { + if (this->wait() == task_state::canceled) + LIBASYNC_RETHROW_EXCEPTION(get_exception()); + } + + // Delete the task using its proper type + static void destroy(task_base* t) LIBASYNC_NOEXCEPT + { + delete static_cast*>(t); + } +}; +template +const task_base_vtable task_result::vtable_impl = { + task_result::destroy, // destroy + nullptr, // run + nullptr, // cancel + nullptr // schedule +}; + +// Class to hold a function object, with empty base class optimization +template +struct func_base { + Func func; + + template + explicit func_base(F&& f) + : func(std::forward(f)) {} + Func& get_func() + { + return func; + } +}; +template +struct func_base::value>::type> { + template + explicit func_base(F&& f) + { + new(this) Func(std::forward(f)); + } + ~func_base() + { + get_func().~Func(); + } + Func& get_func() + { + return *reinterpret_cast(this); + } +}; + +// Class to hold a function object and initialize/destroy it at any time +template +struct func_holder { + alignas(Func) std::uint8_t func[sizeof(Func)]; + + Func& get_func() + { + return *reinterpret_cast(&func); + } + template + void init_func(Args&&... args) + { + new(&func) Func(std::forward(args)...); + } + void destroy_func() + { + get_func().~Func(); + } +}; +template +struct func_holder::value>::type> { + Func& get_func() + { + return *reinterpret_cast(this); + } + template + void init_func(Args&&... args) + { + new(this) Func(std::forward(args)...); + } + void destroy_func() + { + get_func().~Func(); + } +}; + +// Task object with an associated function object +// Using private inheritance so empty Func doesn't take up space +template +struct task_func: public task_result, func_holder { + // Virtual function table for task_func + static const task_base_vtable vtable_impl; + template + explicit task_func(Args&&... args) + { + this->vtable = &vtable_impl; + this->init_func(std::forward(args)...); + } + + // Run the stored function + static void run(task_base* t) LIBASYNC_NOEXCEPT + { + LIBASYNC_TRY { + // Dispatch to execution function + static_cast*>(t)->get_func()(t); + } LIBASYNC_CATCH(...) { + cancel(t, std::current_exception()); + } + } + + // Cancel the task + static void cancel(task_base* t, std::exception_ptr&& except) LIBASYNC_NOEXCEPT + { + // Destroy the function object when canceling since it won't be + // used anymore. + static_cast*>(t)->destroy_func(); + static_cast*>(t)->cancel_base(std::move(except)); + } + + // Schedule a continuation task using its scheduler + static void schedule(task_base* parent, task_ptr t) + { + void* sched = static_cast*>(t.get())->sched; + parent->run_continuation(*static_cast(sched), std::move(t)); + } + + // Free the function + ~task_func() + { + // If the task hasn't completed yet, destroy the function object. Note + // that an unwrapped task has already destroyed its function object. + if (this->state.load(std::memory_order_relaxed) == task_state::pending) + this->destroy_func(); + } + + // Delete the task using its proper type + static void destroy(task_base* t) LIBASYNC_NOEXCEPT + { + delete static_cast*>(t); + } +}; +template +const task_base_vtable task_func::vtable_impl = { + task_func::destroy, // destroy + task_func::run, // run + task_func::cancel, // cancel + task_func::schedule // schedule +}; + +// Helper functions to access the internal_task member of a task object, which +// avoids us having to specify half of the functions in the detail namespace +// as friend. Also, internal_task is downcast to the appropriate task_result<>. +template +typename Task::internal_task_type* get_internal_task(const Task& t) +{ + return static_cast(t.internal_task.get()); +} +template +void set_internal_task(Task& t, task_ptr p) +{ + t.internal_task = std::move(p); +} + +// Common code for task unwrapping +template +struct unwrapped_func { + explicit unwrapped_func(task_ptr t) + : parent_task(std::move(t)) {} + void operator()(Child child_task) const + { + // Forward completion state and result to parent task + task_result* parent = static_cast*>(parent_task.get()); + LIBASYNC_TRY { + if (get_internal_task(child_task)->state.load(std::memory_order_relaxed) == task_state::completed) { + parent->set_result(get_internal_task(child_task)->get_result(child_task)); + parent->finish(); + } else { + // We don't call the generic cancel function here because + // the function of the parent task has already been destroyed. + parent->cancel_base(std::exception_ptr(get_internal_task(child_task)->get_exception())); + } + } LIBASYNC_CATCH(...) { + // If the copy/move constructor of the result threw, propagate the exception + parent->cancel_base(std::current_exception()); + } + } + task_ptr parent_task; +}; +template +void unwrapped_finish(task_base* parent_base, Child child_task) +{ + // Destroy the parent task's function since it has been executed + parent_base->state.store(task_state::unwrapped, std::memory_order_relaxed); + static_cast*>(parent_base)->destroy_func(); + + // Set up a continuation on the child to set the result of the parent + LIBASYNC_TRY { + parent_base->add_ref(); + child_task.then(inline_scheduler(), unwrapped_func(task_ptr(parent_base))); + } LIBASYNC_CATCH(...) { + // Use cancel_base here because the function object is already destroyed. + static_cast*>(parent_base)->cancel_base(std::current_exception()); + } +} + +// Execution functions for root tasks: +// - With and without task unwraping +template +struct root_exec_func: private func_base { + template + explicit root_exec_func(F&& f) + : func_base(std::forward(f)) {} + void operator()(task_base* t) + { + static_cast*>(t)->set_result(detail::invoke_fake_void(std::move(this->get_func()))); + static_cast*>(t)->destroy_func(); + t->finish(); + } +}; +template +struct root_exec_func: private func_base { + template + explicit root_exec_func(F&& f) + : func_base(std::forward(f)) {} + void operator()(task_base* t) + { + unwrapped_finish(t, std::move(this->get_func())()); + } +}; + +// Execution functions for continuation tasks: +// - With and without task unwraping +// - For void, value-based and task-based continuations +template +struct continuation_exec_func: private func_base { + template + continuation_exec_func(F&& f, P&& p) + : func_base(std::forward(f)), parent(std::forward

(p)) {} + void operator()(task_base* t) + { + static_cast*>(t)->set_result(detail::invoke_fake_void(std::move(this->get_func()), std::move(parent))); + static_cast*>(t)->destroy_func(); + t->finish(); + } + Parent parent; +}; +template +struct continuation_exec_func: private func_base { + template + continuation_exec_func(F&& f, P&& p) + : func_base(std::forward(f)), parent(std::forward

(p)) {} + void operator()(task_base* t) + { + if (get_internal_task(parent)->state.load(std::memory_order_relaxed) == task_state::canceled) + task_func::cancel(t, std::exception_ptr(get_internal_task(parent)->get_exception())); + else { + static_cast*>(t)->set_result(detail::invoke_fake_void(std::move(this->get_func()), get_internal_task(parent)->get_result(parent))); + static_cast*>(t)->destroy_func(); + t->finish(); + } + } + Parent parent; +}; +template +struct continuation_exec_func: private func_base { + template + continuation_exec_func(F&& f, P&& p) + : func_base(std::forward(f)), parent(std::forward

(p)) {} + void operator()(task_base* t) + { + if (get_internal_task(parent)->state.load(std::memory_order_relaxed) == task_state::canceled) + task_func::cancel(t, std::exception_ptr(get_internal_task(parent)->get_exception())); + else { + static_cast*>(t)->set_result(detail::invoke_fake_void(std::move(this->get_func()), fake_void())); + static_cast*>(t)->destroy_func(); + t->finish(); + } + } + Parent parent; +}; +template +struct continuation_exec_func: private func_base { + template + continuation_exec_func(F&& f, P&& p) + : func_base(std::forward(f)), parent(std::forward

(p)) {} + void operator()(task_base* t) + { + unwrapped_finish(t, detail::invoke_fake_void(std::move(this->get_func()), std::move(parent))); + } + Parent parent; +}; +template +struct continuation_exec_func: private func_base { + template + continuation_exec_func(F&& f, P&& p) + : func_base(std::forward(f)), parent(std::forward

(p)) {} + void operator()(task_base* t) + { + if (get_internal_task(parent)->state.load(std::memory_order_relaxed) == task_state::canceled) + task_func::cancel(t, std::exception_ptr(get_internal_task(parent)->get_exception())); + else + unwrapped_finish(t, detail::invoke_fake_void(std::move(this->get_func()), get_internal_task(parent)->get_result(parent))); + } + Parent parent; +}; +template +struct continuation_exec_func: private func_base { + template + continuation_exec_func(F&& f, P&& p) + : func_base(std::forward(f)), parent(std::forward

(p)) {} + void operator()(task_base* t) + { + if (get_internal_task(parent)->state.load(std::memory_order_relaxed) == task_state::canceled) + task_func::cancel(t, std::exception_ptr(get_internal_task(parent)->get_exception())); + else + unwrapped_finish(t, detail::invoke_fake_void(std::move(this->get_func()), fake_void())); + } + Parent parent; +}; + +} // namespace detail +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/traits.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/traits.h new file mode 100644 index 0000000..087e60b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/traits.h @@ -0,0 +1,140 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { +namespace detail { + +// Pseudo-void type: it takes up no space but can be moved and copied +struct fake_void {}; +template +struct void_to_fake_void { + typedef T type; +}; +template<> +struct void_to_fake_void { + typedef fake_void type; +}; +template +T fake_void_to_void(T&& x) +{ + return std::forward(x); +} +inline void fake_void_to_void(fake_void) {} + +// Check if type is a task type, used to detect task unwraping +template +struct is_task: public std::false_type {}; +template +struct is_task>: public std::true_type {}; +template +struct is_task>: public std::true_type {}; +template +struct is_task>: public std::true_type {}; +template +struct is_task>: public std::true_type {}; + +// Extract the result type of a task if T is a task, otherwise just return T +template +struct remove_task { + typedef T type; +}; +template +struct remove_task> { + typedef T type; +}; +template +struct remove_task> { + typedef T type; +}; +template +struct remove_task> { + typedef T type; +}; +template +struct remove_task> { + typedef T type; +}; + +// Check if a type is callable with the given arguments +typedef char one[1]; +typedef char two[2]; +template()(std::declval()...))> +two& is_callable_helper(int); +template +one& is_callable_helper(...); +template +struct is_callable; +template +struct is_callable: public std::integral_constant(0)) - 1> {}; + +// Wrapper to run a function object with an optional parameter: +// - void returns are turned into fake_void +// - fake_void parameter will invoke the function with no arguments +template()())>::value>::type> +decltype(std::declval()()) invoke_fake_void(Func&& f) +{ + return std::forward(f)(); +} +template()())>::value>::type> +fake_void invoke_fake_void(Func&& f) +{ + std::forward(f)(); + return fake_void(); +} +template +typename void_to_fake_void()(std::declval()))>::type invoke_fake_void(Func&& f, Param&& p) +{ + return detail::invoke_fake_void([&f, &p] {return std::forward(f)(std::forward(p));}); +} +template +typename void_to_fake_void()())>::type invoke_fake_void(Func&& f, fake_void) +{ + return detail::invoke_fake_void(std::forward(f)); +} + +// Various properties of a continuation function +template()())> +fake_void is_value_cont_helper(const Parent&, int, int); +template()(std::declval().get()))> +std::true_type is_value_cont_helper(const Parent&, int, int); +template()())> +std::true_type is_value_cont_helper(const task&, int, int); +template()())> +std::true_type is_value_cont_helper(const shared_task&, int, int); +template()(std::declval()))> +std::false_type is_value_cont_helper(const Parent&, int, ...); +template +void is_value_cont_helper(const Parent&, ...); +template +struct continuation_traits { + typedef typename std::decay::type decay_func; + typedef decltype(detail::is_value_cont_helper(std::declval(), 0, 0)) is_value_cont; + static_assert(!std::is_void::value, "Parameter type for continuation function is invalid for parent task type"); + typedef typename std::conditional::value, fake_void, typename std::conditional::value, typename void_to_fake_void().get())>::type, Parent>::type>::type param_type; + typedef decltype(detail::fake_void_to_void(detail::invoke_fake_void(std::declval(), std::declval()))) result_type; + typedef task::type> task_type; +}; + +} // namespace detail +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/when_all_any.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/when_all_any.h new file mode 100644 index 0000000..7166026 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++/when_all_any.h @@ -0,0 +1,292 @@ +// Copyright (c) 2015 Amanieu d'Antras +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASYNCXX_H_ +# error "Do not include this header directly, include instead." +#endif + +namespace async { + +// Result type for when_any +template +struct when_any_result { + // Index of the task that finished first + std::size_t index; + + // List of tasks that were passed in + Result tasks; +}; + +namespace detail { + +// Shared state for when_all +template +struct when_all_state: public ref_count_base> { + event_task event; + Result result; + + when_all_state(std::size_t count) + : ref_count_base>(count) {} + + // When all references are dropped, signal the event + ~when_all_state() + { + event.set(std::move(result)); + } +}; + +// Execution functions for when_all, for ranges and tuples +template +struct when_all_func_range { + std::size_t index; + ref_count_ptr> state; + + when_all_func_range(std::size_t index_, ref_count_ptr> state_) + : index(index_), state(std::move(state_)) {} + + // Copy the completed task object to the shared state. The event is + // automatically signaled when all references are dropped. + void operator()(Task t) const + { + state->result[index] = std::move(t); + } +}; +template +struct when_all_func_tuple { + ref_count_ptr> state; + + when_all_func_tuple(ref_count_ptr> state_) + : state(std::move(state_)) {} + + // Copy the completed task object to the shared state. The event is + // automatically signaled when all references are dropped. + void operator()(Task t) const + { + std::get(state->result) = std::move(t); + } +}; + +// Shared state for when_any +template +struct when_any_state: public ref_count_base> { + event_task> event; + Result result; + + when_any_state(std::size_t count) + : ref_count_base>(count) {} + + // Signal the event when the first task reaches here + void set(std::size_t i) + { + event.set({i, std::move(result)}); + } +}; + +// Execution function for when_any +template +struct when_any_func { + std::size_t index; + ref_count_ptr> state; + + when_any_func(std::size_t index_, ref_count_ptr> state_) + : index(index_), state(std::move(state_)) {} + + // Simply tell the state that our task has finished, it already has a copy + // of the task object. + void operator()(Task) const + { + state->set(index); + } +}; + +// Internal implementation of when_all for variadic arguments +template +void when_all_variadic(when_all_state*) {} +template +void when_all_variadic(when_all_state* state, First&& first, T&&... tasks) +{ + typedef typename std::decay::type task_type; + + // Add a continuation to the task + LIBASYNC_TRY { + first.then(inline_scheduler(), detail::when_all_func_tuple(detail::ref_count_ptr>(state))); + } LIBASYNC_CATCH(...) { + // Make sure we don't leak memory if then() throws + state->remove_ref(sizeof...(T)); + LIBASYNC_RETHROW(); + } + + // Add continuations to remaining tasks + detail::when_all_variadic(state, std::forward(tasks)...); +} + +// Internal implementation of when_any for variadic arguments +template +void when_any_variadic(when_any_state*) {} +template +void when_any_variadic(when_any_state* state, First&& first, T&&... tasks) +{ + typedef typename std::decay::type task_type; + + // Add a copy of the task to the results because the event may be + // set before all tasks have finished. + detail::task_base* t = detail::get_internal_task(first); + t->add_ref(); + detail::set_internal_task(std::get(state->result), detail::task_ptr(t)); + + // Add a continuation to the task + LIBASYNC_TRY { + first.then(inline_scheduler(), detail::when_any_func(index, detail::ref_count_ptr>(state))); + } LIBASYNC_CATCH(...) { + // Make sure we don't leak memory if then() throws + state->remove_ref(sizeof...(T)); + LIBASYNC_RETHROW(); + } + + // Add continuations to remaining tasks + detail::when_any_variadic(state, std::forward(tasks)...); +} + +} // namespace detail + +// Combine a set of tasks into one task which is signaled when all specified tasks finish +template +task::value_type>::type>> when_all(Iter begin, Iter end) +{ + typedef typename std::decay::value_type>::type task_type; + typedef std::vector result_type; + + // Handle empty ranges + if (begin == end) + return make_task(result_type()); + + // Create shared state, initialized with the proper reference count + std::size_t count = std::distance(begin, end); + auto* state = new detail::when_all_state(count); + state->result.resize(count); + auto out = state->event.get_task(); + + // Add a continuation to each task to add its result to the shared state + // Last task sets the event result + for (std::size_t i = 0; begin != end; i++, ++begin) { + LIBASYNC_TRY { + (*begin).then(inline_scheduler(), detail::when_all_func_range(i, detail::ref_count_ptr>(state))); + } LIBASYNC_CATCH(...) { + // Make sure we don't leak memory if then() throws + state->remove_ref(std::distance(begin, end) - 1); + LIBASYNC_RETHROW(); + } + } + + return out; +} + +// Combine a set of tasks into one task which is signaled when one of the tasks finishes +template +task::value_type>::type>>> when_any(Iter begin, Iter end) +{ + typedef typename std::decay::value_type>::type task_type; + typedef std::vector result_type; + + // Handle empty ranges + if (begin == end) + return make_task(when_any_result()); + + // Create shared state, initialized with the proper reference count + std::size_t count = std::distance(begin, end); + auto* state = new detail::when_any_state(count); + state->result.resize(count); + auto out = state->event.get_task(); + + // Add a continuation to each task to set the event. First one wins. + for (std::size_t i = 0; begin != end; i++, ++begin) { + // Add a copy of the task to the results because the event may be + // set before all tasks have finished. + detail::task_base* t = detail::get_internal_task(*begin); + t->add_ref(); + detail::set_internal_task(state->result[i], detail::task_ptr(t)); + + LIBASYNC_TRY { + (*begin).then(inline_scheduler(), detail::when_any_func(i, detail::ref_count_ptr>(state))); + } LIBASYNC_CATCH(...) { + // Make sure we don't leak memory if then() throws + state->remove_ref(std::distance(begin, end) - 1); + LIBASYNC_RETHROW(); + } + } + + return out; +} + +// when_all wrapper accepting ranges +template +decltype(async::when_all(std::begin(std::declval()), std::end(std::declval()))) when_all(T&& tasks) +{ + return async::when_all(std::begin(std::forward(tasks)), std::end(std::forward(tasks))); +} + +// when_any wrapper accepting ranges +template +decltype(async::when_any(std::begin(std::declval()), std::end(std::declval()))) when_any(T&& tasks) +{ + return async::when_any(std::begin(std::forward(tasks)), std::end(std::forward(tasks))); +} + +// when_all with variadic arguments +inline task> when_all() +{ + return async::make_task(std::tuple<>()); +} +template +task::type...>> when_all(T&&... tasks) +{ + typedef std::tuple::type...> result_type; + + // Create shared state + auto state = new detail::when_all_state(sizeof...(tasks)); + auto out = state->event.get_task(); + + // Register all the tasks on the event + detail::when_all_variadic<0>(state, std::forward(tasks)...); + + return out; +} + +// when_any with variadic arguments +inline task>> when_any() +{ + return async::make_task(when_any_result>()); +} +template +task::type...>>> when_any(T&&... tasks) +{ + typedef std::tuple::type...> result_type; + + // Create shared state + auto state = new detail::when_any_state(sizeof...(tasks)); + auto out = state->event.get_task(); + + // Register all the tasks on the event + detail::when_any_variadic<0>(state, std::forward(tasks)...); + + return out; +} + +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/args.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/args.h new file mode 100644 index 0000000..31a60e8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/args.h @@ -0,0 +1,228 @@ +// Formatting library for C++ - dynamic argument lists +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_ARGS_H_ +#define FMT_ARGS_H_ + +#ifndef FMT_MODULE +# include // std::reference_wrapper +# include // std::unique_ptr +# include +#endif + +#include "format.h" // std_string_view + +FMT_BEGIN_NAMESPACE + +namespace detail { + +template struct is_reference_wrapper : std::false_type {}; +template +struct is_reference_wrapper> : std::true_type {}; + +template auto unwrap(const T& v) -> const T& { return v; } +template +auto unwrap(const std::reference_wrapper& v) -> const T& { + return static_cast(v); +} + +// node is defined outside dynamic_arg_list to workaround a C2504 bug in MSVC +// 2022 (v17.10.0). +// +// Workaround for clang's -Wweak-vtables. Unlike for regular classes, for +// templates it doesn't complain about inability to deduce single translation +// unit for placing vtable. So node is made a fake template. +template struct node { + virtual ~node() = default; + std::unique_ptr> next; +}; + +class dynamic_arg_list { + template struct typed_node : node<> { + T value; + + template + FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {} + + template + FMT_CONSTEXPR typed_node(const basic_string_view& arg) + : value(arg.data(), arg.size()) {} + }; + + std::unique_ptr> head_; + + public: + template auto push(const Arg& arg) -> const T& { + auto new_node = std::unique_ptr>(new typed_node(arg)); + auto& value = new_node->value; + new_node->next = std::move(head_); + head_ = std::move(new_node); + return value; + } +}; +} // namespace detail + +/** + * A dynamic list of formatting arguments with storage. + * + * It can be implicitly converted into `fmt::basic_format_args` for passing + * into type-erased formatting functions such as `fmt::vformat`. + */ +template +class dynamic_format_arg_store +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 + // Workaround a GCC template argument substitution bug. + : public basic_format_args +#endif +{ + private: + using char_type = typename Context::char_type; + + template struct need_copy { + static constexpr detail::type mapped_type = + detail::mapped_type_constant::value; + + enum { + value = !(detail::is_reference_wrapper::value || + std::is_same>::value || + std::is_same>::value || + (mapped_type != detail::type::cstring_type && + mapped_type != detail::type::string_type && + mapped_type != detail::type::custom_type)) + }; + }; + + template + using stored_type = conditional_t< + std::is_convertible>::value && + !detail::is_reference_wrapper::value, + std::basic_string, T>; + + // Storage of basic_format_arg must be contiguous. + std::vector> data_; + std::vector> named_info_; + + // Storage of arguments not fitting into basic_format_arg must grow + // without relocation because items in data_ refer to it. + detail::dynamic_arg_list dynamic_args_; + + friend class basic_format_args; + + auto get_types() const -> unsigned long long { + return detail::is_unpacked_bit | data_.size() | + (named_info_.empty() + ? 0ULL + : static_cast(detail::has_named_args_bit)); + } + + auto data() const -> const basic_format_arg* { + return named_info_.empty() ? data_.data() : data_.data() + 1; + } + + template void emplace_arg(const T& arg) { + data_.emplace_back(detail::make_arg(arg)); + } + + template + void emplace_arg(const detail::named_arg& arg) { + if (named_info_.empty()) { + constexpr const detail::named_arg_info* zero_ptr{nullptr}; + data_.insert(data_.begin(), {zero_ptr, 0}); + } + data_.emplace_back(detail::make_arg(detail::unwrap(arg.value))); + auto pop_one = [](std::vector>* data) { + data->pop_back(); + }; + std::unique_ptr>, decltype(pop_one)> + guard{&data_, pop_one}; + named_info_.push_back({arg.name, static_cast(data_.size() - 2u)}); + data_[0].value_.named_args = {named_info_.data(), named_info_.size()}; + guard.release(); + } + + public: + constexpr dynamic_format_arg_store() = default; + + /** + * Adds an argument into the dynamic store for later passing to a formatting + * function. + * + * Note that custom types and string types (but not string views) are copied + * into the store dynamically allocating memory if necessary. + * + * **Example**: + * + * fmt::dynamic_format_arg_store store; + * store.push_back(42); + * store.push_back("abc"); + * store.push_back(1.5f); + * std::string result = fmt::vformat("{} and {} and {}", store); + */ + template void push_back(const T& arg) { + if (detail::const_check(need_copy::value)) + emplace_arg(dynamic_args_.push>(arg)); + else + emplace_arg(detail::unwrap(arg)); + } + + /** + * Adds a reference to the argument into the dynamic store for later passing + * to a formatting function. + * + * **Example**: + * + * fmt::dynamic_format_arg_store store; + * char band[] = "Rolling Stones"; + * store.push_back(std::cref(band)); + * band[9] = 'c'; // Changing str affects the output. + * std::string result = fmt::vformat("{}", store); + * // result == "Rolling Scones" + */ + template void push_back(std::reference_wrapper arg) { + static_assert( + need_copy::value, + "objects of built-in types and string views are always copied"); + emplace_arg(arg.get()); + } + + /** + * Adds named argument into the dynamic store for later passing to a + * formatting function. `std::reference_wrapper` is supported to avoid + * copying of the argument. The name is always copied into the store. + */ + template + void push_back(const detail::named_arg& arg) { + const char_type* arg_name = + dynamic_args_.push>(arg.name).c_str(); + if (detail::const_check(need_copy::value)) { + emplace_arg( + fmt::arg(arg_name, dynamic_args_.push>(arg.value))); + } else { + emplace_arg(fmt::arg(arg_name, arg.value)); + } + } + + /// Erase all elements from the store. + void clear() { + data_.clear(); + named_info_.clear(); + dynamic_args_ = detail::dynamic_arg_list(); + } + + /// Reserves space to store at least `new_cap` arguments including + /// `new_cap_named` named arguments. + void reserve(size_t new_cap, size_t new_cap_named) { + FMT_ASSERT(new_cap >= new_cap_named, + "Set of arguments includes set of named arguments"); + data_.reserve(new_cap); + named_info_.reserve(new_cap_named); + } +}; + +FMT_END_NAMESPACE + +#endif // FMT_ARGS_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/base.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/base.h new file mode 100644 index 0000000..6276494 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/base.h @@ -0,0 +1,3077 @@ +// Formatting library for C++ - the base API for char/UTF-8 +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_BASE_H_ +#define FMT_BASE_H_ + +#if defined(FMT_IMPORT_STD) && !defined(FMT_MODULE) +# define FMT_MODULE +#endif + +#ifndef FMT_MODULE +# include // CHAR_BIT +# include // FILE +# include // strlen + +// is also included transitively from . +# include // std::byte +# include // std::enable_if +#endif + +// The fmt library version in the form major * 10000 + minor * 100 + patch. +#define FMT_VERSION 110002 + +// Detect compiler versions. +#if defined(__clang__) && !defined(__ibmxl__) +# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) +#else +# define FMT_CLANG_VERSION 0 +#endif +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) +# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#else +# define FMT_GCC_VERSION 0 +#endif +#if defined(__ICL) +# define FMT_ICC_VERSION __ICL +#elif defined(__INTEL_COMPILER) +# define FMT_ICC_VERSION __INTEL_COMPILER +#else +# define FMT_ICC_VERSION 0 +#endif +#if defined(_MSC_VER) +# define FMT_MSC_VERSION _MSC_VER +#else +# define FMT_MSC_VERSION 0 +#endif + +// Detect standard library versions. +#ifdef _GLIBCXX_RELEASE +# define FMT_GLIBCXX_RELEASE _GLIBCXX_RELEASE +#else +# define FMT_GLIBCXX_RELEASE 0 +#endif +#ifdef _LIBCPP_VERSION +# define FMT_LIBCPP_VERSION _LIBCPP_VERSION +#else +# define FMT_LIBCPP_VERSION 0 +#endif + +#ifdef _MSVC_LANG +# define FMT_CPLUSPLUS _MSVC_LANG +#else +# define FMT_CPLUSPLUS __cplusplus +#endif + +// Detect __has_*. +#ifdef __has_feature +# define FMT_HAS_FEATURE(x) __has_feature(x) +#else +# define FMT_HAS_FEATURE(x) 0 +#endif +#ifdef __has_include +# define FMT_HAS_INCLUDE(x) __has_include(x) +#else +# define FMT_HAS_INCLUDE(x) 0 +#endif +#ifdef __has_cpp_attribute +# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +# define FMT_HAS_CPP_ATTRIBUTE(x) 0 +#endif + +#define FMT_HAS_CPP14_ATTRIBUTE(attribute) \ + (FMT_CPLUSPLUS >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute)) + +#define FMT_HAS_CPP17_ATTRIBUTE(attribute) \ + (FMT_CPLUSPLUS >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute)) + +// Detect C++14 relaxed constexpr. +#ifdef FMT_USE_CONSTEXPR +// Use the provided definition. +#elif FMT_GCC_VERSION >= 600 && FMT_CPLUSPLUS >= 201402L +// GCC only allows throw in constexpr since version 6: +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67371. +# define FMT_USE_CONSTEXPR 1 +#elif FMT_ICC_VERSION +# define FMT_USE_CONSTEXPR 0 // https://github.com/fmtlib/fmt/issues/1628 +#elif FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VERSION >= 1912 +# define FMT_USE_CONSTEXPR 1 +#else +# define FMT_USE_CONSTEXPR 0 +#endif +#if FMT_USE_CONSTEXPR +# define FMT_CONSTEXPR constexpr +#else +# define FMT_CONSTEXPR +#endif + +// Detect consteval, C++20 constexpr extensions and std::is_constant_evaluated. +#if !defined(__cpp_lib_is_constant_evaluated) +# define FMT_USE_CONSTEVAL 0 +#elif FMT_CPLUSPLUS < 201709L +# define FMT_USE_CONSTEVAL 0 +#elif FMT_GLIBCXX_RELEASE && FMT_GLIBCXX_RELEASE < 10 +# define FMT_USE_CONSTEVAL 0 +#elif FMT_LIBCPP_VERSION && FMT_LIBCPP_VERSION < 10000 +# define FMT_USE_CONSTEVAL 0 +#elif defined(__apple_build_version__) && __apple_build_version__ < 14000029L +# define FMT_USE_CONSTEVAL 0 // consteval is broken in Apple clang < 14. +#elif FMT_MSC_VERSION && FMT_MSC_VERSION < 1929 +# define FMT_USE_CONSTEVAL 0 // consteval is broken in MSVC VS2019 < 16.10. +#elif defined(__cpp_consteval) +# define FMT_USE_CONSTEVAL 1 +#elif FMT_GCC_VERSION >= 1002 || FMT_CLANG_VERSION >= 1101 +# define FMT_USE_CONSTEVAL 1 +#else +# define FMT_USE_CONSTEVAL 0 +#endif +#if FMT_USE_CONSTEVAL +# define FMT_CONSTEVAL consteval +# define FMT_CONSTEXPR20 constexpr +#else +# define FMT_CONSTEVAL +# define FMT_CONSTEXPR20 +#endif + +#if defined(FMT_USE_NONTYPE_TEMPLATE_ARGS) +// Use the provided definition. +#elif defined(__NVCOMPILER) +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 0 +#elif FMT_GCC_VERSION >= 903 && FMT_CPLUSPLUS >= 201709L +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1 +#elif defined(__cpp_nontype_template_args) && \ + __cpp_nontype_template_args >= 201911L +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1 +#elif FMT_CLANG_VERSION >= 1200 && FMT_CPLUSPLUS >= 202002L +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1 +#else +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 0 +#endif + +#ifdef FMT_USE_CONCEPTS +// Use the provided definition. +#elif defined(__cpp_concepts) +# define FMT_USE_CONCEPTS 1 +#else +# define FMT_USE_CONCEPTS 0 +#endif + +// Check if exceptions are disabled. +#ifdef FMT_EXCEPTIONS +// Use the provided definition. +#elif defined(__GNUC__) && !defined(__EXCEPTIONS) +# define FMT_EXCEPTIONS 0 +#elif FMT_MSC_VERSION && !_HAS_EXCEPTIONS +# define FMT_EXCEPTIONS 0 +#else +# define FMT_EXCEPTIONS 1 +#endif +#if FMT_EXCEPTIONS +# define FMT_TRY try +# define FMT_CATCH(x) catch (x) +#else +# define FMT_TRY if (true) +# define FMT_CATCH(x) if (false) +#endif + +#if FMT_HAS_CPP17_ATTRIBUTE(fallthrough) +# define FMT_FALLTHROUGH [[fallthrough]] +#elif defined(__clang__) +# define FMT_FALLTHROUGH [[clang::fallthrough]] +#elif FMT_GCC_VERSION >= 700 && \ + (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520) +# define FMT_FALLTHROUGH [[gnu::fallthrough]] +#else +# define FMT_FALLTHROUGH +#endif + +// Disable [[noreturn]] on MSVC/NVCC because of bogus unreachable code warnings. +#if FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VERSION && !defined(__NVCC__) +# define FMT_NORETURN [[noreturn]] +#else +# define FMT_NORETURN +#endif + +#ifndef FMT_NODISCARD +# if FMT_HAS_CPP17_ATTRIBUTE(nodiscard) +# define FMT_NODISCARD [[nodiscard]] +# else +# define FMT_NODISCARD +# endif +#endif + +#ifdef FMT_DEPRECATED +// Use the provided definition. +#elif FMT_HAS_CPP14_ATTRIBUTE(deprecated) +# define FMT_DEPRECATED [[deprecated]] +#else +# define FMT_DEPRECATED /* deprecated */ +#endif + +#ifdef FMT_INLINE +// Use the provided definition. +#elif FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_ALWAYS_INLINE inline __attribute__((always_inline)) +#else +# define FMT_ALWAYS_INLINE inline +#endif +// A version of FMT_INLINE to prevent code bloat in debug mode. +#ifdef NDEBUG +# define FMT_INLINE FMT_ALWAYS_INLINE +#else +# define FMT_INLINE inline +#endif + +#if FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_VISIBILITY(value) __attribute__((visibility(value))) +#else +# define FMT_VISIBILITY(value) +#endif + +#ifndef FMT_GCC_PRAGMA +// Workaround a _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884 +// and an nvhpc warning: https://github.com/fmtlib/fmt/pull/2582. +# if FMT_GCC_VERSION >= 504 && !defined(__NVCOMPILER) +# define FMT_GCC_PRAGMA(arg) _Pragma(arg) +# else +# define FMT_GCC_PRAGMA(arg) +# endif +#endif + +// GCC < 5 requires this-> in decltype. +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500 +# define FMT_DECLTYPE_THIS this-> +#else +# define FMT_DECLTYPE_THIS +#endif + +#if FMT_MSC_VERSION +# define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__)) +# define FMT_UNCHECKED_ITERATOR(It) \ + using _Unchecked_type = It // Mark iterator as checked. +#else +# define FMT_MSC_WARNING(...) +# define FMT_UNCHECKED_ITERATOR(It) using unchecked_type = It +#endif + +#ifndef FMT_BEGIN_NAMESPACE +# define FMT_BEGIN_NAMESPACE \ + namespace fmt { \ + inline namespace v11 { +# define FMT_END_NAMESPACE \ + } \ + } +#endif + +#ifndef FMT_EXPORT +# define FMT_EXPORT +# define FMT_BEGIN_EXPORT +# define FMT_END_EXPORT +#endif + +#if !defined(FMT_HEADER_ONLY) && defined(_WIN32) +# if defined(FMT_LIB_EXPORT) +# define FMT_API __declspec(dllexport) +# elif defined(FMT_SHARED) +# define FMT_API __declspec(dllimport) +# endif +#elif defined(FMT_LIB_EXPORT) || defined(FMT_SHARED) +# define FMT_API FMT_VISIBILITY("default") +#endif +#ifndef FMT_API +# define FMT_API +#endif + +#ifndef FMT_UNICODE +# define FMT_UNICODE 1 +#endif + +// Check if rtti is available. +#ifndef FMT_USE_RTTI +// __RTTI is for EDG compilers. _CPPRTTI is for MSVC. +# if defined(__GXX_RTTI) || FMT_HAS_FEATURE(cxx_rtti) || defined(_CPPRTTI) || \ + defined(__INTEL_RTTI__) || defined(__RTTI) +# define FMT_USE_RTTI 1 +# else +# define FMT_USE_RTTI 0 +# endif +#endif + +#define FMT_FWD(...) static_cast(__VA_ARGS__) + +// Enable minimal optimizations for more compact code in debug mode. +FMT_GCC_PRAGMA("GCC push_options") +#if !defined(__OPTIMIZE__) && !defined(__CUDACC__) +FMT_GCC_PRAGMA("GCC optimize(\"Og\")") +#endif + +FMT_BEGIN_NAMESPACE + +// Implementations of enable_if_t and other metafunctions for older systems. +template +using enable_if_t = typename std::enable_if::type; +template +using conditional_t = typename std::conditional::type; +template using bool_constant = std::integral_constant; +template +using remove_reference_t = typename std::remove_reference::type; +template +using remove_const_t = typename std::remove_const::type; +template +using remove_cvref_t = typename std::remove_cv>::type; +template struct type_identity { + using type = T; +}; +template using type_identity_t = typename type_identity::type; +template +using make_unsigned_t = typename std::make_unsigned::type; +template +using underlying_t = typename std::underlying_type::type; + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500 +// A workaround for gcc 4.8 to make void_t work in a SFINAE context. +template struct void_t_impl { + using type = void; +}; +template using void_t = typename void_t_impl::type; +#else +template using void_t = void; +#endif + +struct monostate { + constexpr monostate() {} +}; + +// An enable_if helper to be used in template parameters which results in much +// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed +// to workaround a bug in MSVC 2019 (see #1140 and #1186). +#ifdef FMT_DOC +# define FMT_ENABLE_IF(...) +#else +# define FMT_ENABLE_IF(...) fmt::enable_if_t<(__VA_ARGS__), int> = 0 +#endif + +// This is defined in base.h instead of format.h to avoid injecting in std. +// It is a template to avoid undesirable implicit conversions to std::byte. +#ifdef __cpp_lib_byte +template ::value)> +inline auto format_as(T b) -> unsigned char { + return static_cast(b); +} +#endif + +namespace detail { +// Suppresses "unused variable" warnings with the method described in +// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/. +// (void)var does not work on many Intel compilers. +template FMT_CONSTEXPR void ignore_unused(const T&...) {} + +constexpr auto is_constant_evaluated(bool default_value = false) noexcept + -> bool { +// Workaround for incompatibility between libstdc++ consteval-based +// std::is_constant_evaluated() implementation and clang-14: +// https://github.com/fmtlib/fmt/issues/3247. +#if FMT_CPLUSPLUS >= 202002L && FMT_GLIBCXX_RELEASE >= 12 && \ + (FMT_CLANG_VERSION >= 1400 && FMT_CLANG_VERSION < 1500) + ignore_unused(default_value); + return __builtin_is_constant_evaluated(); +#elif defined(__cpp_lib_is_constant_evaluated) + ignore_unused(default_value); + return std::is_constant_evaluated(); +#else + return default_value; +#endif +} + +// Suppresses "conditional expression is constant" warnings. +template constexpr auto const_check(T value) -> T { return value; } + +FMT_NORETURN FMT_API void assert_fail(const char* file, int line, + const char* message); + +#if defined(FMT_ASSERT) +// Use the provided definition. +#elif defined(NDEBUG) +// FMT_ASSERT is not empty to avoid -Wempty-body. +# define FMT_ASSERT(condition, message) \ + fmt::detail::ignore_unused((condition), (message)) +#else +# define FMT_ASSERT(condition, message) \ + ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \ + ? (void)0 \ + : fmt::detail::assert_fail(__FILE__, __LINE__, (message))) +#endif + +#ifdef FMT_USE_INT128 +// Do nothing. +#elif defined(__SIZEOF_INT128__) && !defined(__NVCC__) && \ + !(FMT_CLANG_VERSION && FMT_MSC_VERSION) +# define FMT_USE_INT128 1 +using int128_opt = __int128_t; // An optional native 128-bit integer. +using uint128_opt = __uint128_t; +template inline auto convert_for_visit(T value) -> T { + return value; +} +#else +# define FMT_USE_INT128 0 +#endif +#if !FMT_USE_INT128 +enum class int128_opt {}; +enum class uint128_opt {}; +// Reduce template instantiations. +template auto convert_for_visit(T) -> monostate { return {}; } +#endif + +// Casts a nonnegative integer to unsigned. +template +FMT_CONSTEXPR auto to_unsigned(Int value) -> make_unsigned_t { + FMT_ASSERT(std::is_unsigned::value || value >= 0, "negative value"); + return static_cast>(value); +} + +// A heuristic to detect std::string and std::[experimental::]string_view. +// It is mainly used to avoid dependency on <[experimental/]string_view>. +template +struct is_std_string_like : std::false_type {}; +template +struct is_std_string_like().find_first_of( + typename T::value_type(), 0))>> + : std::is_convertible().data()), + const typename T::value_type*> {}; + +// Returns true iff the literal encoding is UTF-8. +constexpr auto is_utf8_enabled() -> bool { + // Avoid an MSVC sign extension bug: https://github.com/fmtlib/fmt/pull/2297. + using uchar = unsigned char; + return sizeof("\u00A7") == 3 && uchar("\u00A7"[0]) == 0xC2 && + uchar("\u00A7"[1]) == 0xA7; +} +constexpr auto use_utf8() -> bool { + return !FMT_MSC_VERSION || is_utf8_enabled(); +} + +static_assert(!FMT_UNICODE || use_utf8(), + "Unicode support requires compiling with /utf-8"); + +template FMT_CONSTEXPR auto length(const Char* s) -> size_t { + size_t len = 0; + while (*s++) ++len; + return len; +} + +template +FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, std::size_t n) + -> int { + if (!is_constant_evaluated() && sizeof(Char) == 1) return memcmp(s1, s2, n); + for (; n != 0; ++s1, ++s2, --n) { + if (*s1 < *s2) return -1; + if (*s1 > *s2) return 1; + } + return 0; +} + +namespace adl { +using namespace std; + +template +auto invoke_back_inserter() + -> decltype(back_inserter(std::declval())); +} // namespace adl + +template +struct is_back_insert_iterator : std::false_type {}; + +template +struct is_back_insert_iterator< + It, bool_constant()), + It>::value>> : std::true_type {}; + +// Extracts a reference to the container from *insert_iterator. +template +inline auto get_container(OutputIt it) -> typename OutputIt::container_type& { + struct accessor : OutputIt { + accessor(OutputIt base) : OutputIt(base) {} + using OutputIt::container; + }; + return *accessor(it).container; +} +} // namespace detail + +// Checks whether T is a container with contiguous storage. +template struct is_contiguous : std::false_type {}; + +/** + * An implementation of `std::basic_string_view` for pre-C++17. It provides a + * subset of the API. `fmt::basic_string_view` is used for format strings even + * if `std::basic_string_view` is available to prevent issues when a library is + * compiled with a different `-std` option than the client code (which is not + * recommended). + */ +FMT_EXPORT +template class basic_string_view { + private: + const Char* data_; + size_t size_; + + public: + using value_type = Char; + using iterator = const Char*; + + constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {} + + /// Constructs a string reference object from a C string and a size. + constexpr basic_string_view(const Char* s, size_t count) noexcept + : data_(s), size_(count) {} + + constexpr basic_string_view(std::nullptr_t) = delete; + + /// Constructs a string reference object from a C string. + FMT_CONSTEXPR20 + basic_string_view(const Char* s) + : data_(s), + size_(detail::const_check(std::is_same::value && + !detail::is_constant_evaluated(false)) + ? strlen(reinterpret_cast(s)) + : detail::length(s)) {} + + /// Constructs a string reference from a `std::basic_string` or a + /// `std::basic_string_view` object. + template ::value&& std::is_same< + typename S::value_type, Char>::value)> + FMT_CONSTEXPR basic_string_view(const S& s) noexcept + : data_(s.data()), size_(s.size()) {} + + /// Returns a pointer to the string data. + constexpr auto data() const noexcept -> const Char* { return data_; } + + /// Returns the string size. + constexpr auto size() const noexcept -> size_t { return size_; } + + constexpr auto begin() const noexcept -> iterator { return data_; } + constexpr auto end() const noexcept -> iterator { return data_ + size_; } + + constexpr auto operator[](size_t pos) const noexcept -> const Char& { + return data_[pos]; + } + + FMT_CONSTEXPR void remove_prefix(size_t n) noexcept { + data_ += n; + size_ -= n; + } + + FMT_CONSTEXPR auto starts_with(basic_string_view sv) const noexcept + -> bool { + return size_ >= sv.size_ && detail::compare(data_, sv.data_, sv.size_) == 0; + } + FMT_CONSTEXPR auto starts_with(Char c) const noexcept -> bool { + return size_ >= 1 && *data_ == c; + } + FMT_CONSTEXPR auto starts_with(const Char* s) const -> bool { + return starts_with(basic_string_view(s)); + } + + // Lexicographically compare this string reference to other. + FMT_CONSTEXPR auto compare(basic_string_view other) const -> int { + size_t str_size = size_ < other.size_ ? size_ : other.size_; + int result = detail::compare(data_, other.data_, str_size); + if (result == 0) + result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1); + return result; + } + + FMT_CONSTEXPR friend auto operator==(basic_string_view lhs, + basic_string_view rhs) -> bool { + return lhs.compare(rhs) == 0; + } + friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) != 0; + } + friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) < 0; + } + friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) <= 0; + } + friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) > 0; + } + friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) >= 0; + } +}; + +FMT_EXPORT +using string_view = basic_string_view; + +/// Specifies if `T` is a character type. Can be specialized by users. +FMT_EXPORT +template struct is_char : std::false_type {}; +template <> struct is_char : std::true_type {}; + +namespace detail { + +// Constructs fmt::basic_string_view from types implicitly convertible +// to it, deducing Char. Explicitly convertible types such as the ones returned +// from FMT_STRING are intentionally excluded. +template ::value)> +constexpr auto to_string_view(const Char* s) -> basic_string_view { + return s; +} +template ::value)> +constexpr auto to_string_view(const T& s) + -> basic_string_view { + return s; +} +template +constexpr auto to_string_view(basic_string_view s) + -> basic_string_view { + return s; +} + +template +struct has_to_string_view : std::false_type {}; +// detail:: is intentional since to_string_view is not an extension point. +template +struct has_to_string_view< + T, void_t()))>> + : std::true_type {}; + +template struct string_literal { + static constexpr Char value[sizeof...(C)] = {C...}; + constexpr operator basic_string_view() const { + return {value, sizeof...(C)}; + } +}; +#if FMT_CPLUSPLUS < 201703L +template +constexpr Char string_literal::value[sizeof...(C)]; +#endif + +enum class type { + none_type, + // Integer types should go first, + int_type, + uint_type, + long_long_type, + ulong_long_type, + int128_type, + uint128_type, + bool_type, + char_type, + last_integer_type = char_type, + // followed by floating-point types. + float_type, + double_type, + long_double_type, + last_numeric_type = long_double_type, + cstring_type, + string_type, + pointer_type, + custom_type +}; + +// Maps core type T to the corresponding type enum constant. +template +struct type_constant : std::integral_constant {}; + +#define FMT_TYPE_CONSTANT(Type, constant) \ + template \ + struct type_constant \ + : std::integral_constant {} + +FMT_TYPE_CONSTANT(int, int_type); +FMT_TYPE_CONSTANT(unsigned, uint_type); +FMT_TYPE_CONSTANT(long long, long_long_type); +FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type); +FMT_TYPE_CONSTANT(int128_opt, int128_type); +FMT_TYPE_CONSTANT(uint128_opt, uint128_type); +FMT_TYPE_CONSTANT(bool, bool_type); +FMT_TYPE_CONSTANT(Char, char_type); +FMT_TYPE_CONSTANT(float, float_type); +FMT_TYPE_CONSTANT(double, double_type); +FMT_TYPE_CONSTANT(long double, long_double_type); +FMT_TYPE_CONSTANT(const Char*, cstring_type); +FMT_TYPE_CONSTANT(basic_string_view, string_type); +FMT_TYPE_CONSTANT(const void*, pointer_type); + +constexpr auto is_integral_type(type t) -> bool { + return t > type::none_type && t <= type::last_integer_type; +} +constexpr auto is_arithmetic_type(type t) -> bool { + return t > type::none_type && t <= type::last_numeric_type; +} + +constexpr auto set(type rhs) -> int { return 1 << static_cast(rhs); } +constexpr auto in(type t, int set) -> bool { + return ((set >> static_cast(t)) & 1) != 0; +} + +// Bitsets of types. +enum { + sint_set = + set(type::int_type) | set(type::long_long_type) | set(type::int128_type), + uint_set = set(type::uint_type) | set(type::ulong_long_type) | + set(type::uint128_type), + bool_set = set(type::bool_type), + char_set = set(type::char_type), + float_set = set(type::float_type) | set(type::double_type) | + set(type::long_double_type), + string_set = set(type::string_type), + cstring_set = set(type::cstring_type), + pointer_set = set(type::pointer_type) +}; +} // namespace detail + +/// Reports a format error at compile time or, via a `format_error` exception, +/// at runtime. +// This function is intentionally not constexpr to give a compile-time error. +FMT_NORETURN FMT_API void report_error(const char* message); + +FMT_DEPRECATED FMT_NORETURN inline void throw_format_error( + const char* message) { + report_error(message); +} + +/// String's character (code unit) type. +template ()))> +using char_t = typename V::value_type; + +/** + * Parsing context consisting of a format string range being parsed and an + * argument counter for automatic indexing. + * You can use the `format_parse_context` type alias for `char` instead. + */ +FMT_EXPORT +template class basic_format_parse_context { + private: + basic_string_view format_str_; + int next_arg_id_; + + FMT_CONSTEXPR void do_check_arg_id(int id); + + public: + using char_type = Char; + using iterator = const Char*; + + explicit constexpr basic_format_parse_context( + basic_string_view format_str, int next_arg_id = 0) + : format_str_(format_str), next_arg_id_(next_arg_id) {} + + /// Returns an iterator to the beginning of the format string range being + /// parsed. + constexpr auto begin() const noexcept -> iterator { + return format_str_.begin(); + } + + /// Returns an iterator past the end of the format string range being parsed. + constexpr auto end() const noexcept -> iterator { return format_str_.end(); } + + /// Advances the begin iterator to `it`. + FMT_CONSTEXPR void advance_to(iterator it) { + format_str_.remove_prefix(detail::to_unsigned(it - begin())); + } + + /// Reports an error if using the manual argument indexing; otherwise returns + /// the next argument index and switches to the automatic indexing. + FMT_CONSTEXPR auto next_arg_id() -> int { + if (next_arg_id_ < 0) { + report_error("cannot switch from manual to automatic argument indexing"); + return 0; + } + int id = next_arg_id_++; + do_check_arg_id(id); + return id; + } + + /// Reports an error if using the automatic argument indexing; otherwise + /// switches to the manual indexing. + FMT_CONSTEXPR void check_arg_id(int id) { + if (next_arg_id_ > 0) { + report_error("cannot switch from automatic to manual argument indexing"); + return; + } + next_arg_id_ = -1; + do_check_arg_id(id); + } + FMT_CONSTEXPR void check_arg_id(basic_string_view) { + next_arg_id_ = -1; + } + FMT_CONSTEXPR void check_dynamic_spec(int arg_id); +}; + +FMT_EXPORT +using format_parse_context = basic_format_parse_context; + +namespace detail { +// A parse context with extra data used only in compile-time checks. +template +class compile_parse_context : public basic_format_parse_context { + private: + int num_args_; + const type* types_; + using base = basic_format_parse_context; + + public: + explicit FMT_CONSTEXPR compile_parse_context( + basic_string_view format_str, int num_args, const type* types, + int next_arg_id = 0) + : base(format_str, next_arg_id), num_args_(num_args), types_(types) {} + + constexpr auto num_args() const -> int { return num_args_; } + constexpr auto arg_type(int id) const -> type { return types_[id]; } + + FMT_CONSTEXPR auto next_arg_id() -> int { + int id = base::next_arg_id(); + if (id >= num_args_) report_error("argument not found"); + return id; + } + + FMT_CONSTEXPR void check_arg_id(int id) { + base::check_arg_id(id); + if (id >= num_args_) report_error("argument not found"); + } + using base::check_arg_id; + + FMT_CONSTEXPR void check_dynamic_spec(int arg_id) { + detail::ignore_unused(arg_id); + if (arg_id < num_args_ && types_ && !is_integral_type(types_[arg_id])) + report_error("width/precision is not integer"); + } +}; + +/// A contiguous memory buffer with an optional growing ability. It is an +/// internal class and shouldn't be used directly, only via `memory_buffer`. +template class buffer { + private: + T* ptr_; + size_t size_; + size_t capacity_; + + using grow_fun = void (*)(buffer& buf, size_t capacity); + grow_fun grow_; + + protected: + // Don't initialize ptr_ since it is not accessed to save a few cycles. + FMT_MSC_WARNING(suppress : 26495) + FMT_CONSTEXPR20 buffer(grow_fun grow, size_t sz) noexcept + : size_(sz), capacity_(sz), grow_(grow) {} + + constexpr buffer(grow_fun grow, T* p = nullptr, size_t sz = 0, + size_t cap = 0) noexcept + : ptr_(p), size_(sz), capacity_(cap), grow_(grow) {} + + FMT_CONSTEXPR20 ~buffer() = default; + buffer(buffer&&) = default; + + /// Sets the buffer data and capacity. + FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) noexcept { + ptr_ = buf_data; + capacity_ = buf_capacity; + } + + public: + using value_type = T; + using const_reference = const T&; + + buffer(const buffer&) = delete; + void operator=(const buffer&) = delete; + + auto begin() noexcept -> T* { return ptr_; } + auto end() noexcept -> T* { return ptr_ + size_; } + + auto begin() const noexcept -> const T* { return ptr_; } + auto end() const noexcept -> const T* { return ptr_ + size_; } + + /// Returns the size of this buffer. + constexpr auto size() const noexcept -> size_t { return size_; } + + /// Returns the capacity of this buffer. + constexpr auto capacity() const noexcept -> size_t { return capacity_; } + + /// Returns a pointer to the buffer data (not null-terminated). + FMT_CONSTEXPR auto data() noexcept -> T* { return ptr_; } + FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; } + + /// Clears this buffer. + void clear() { size_ = 0; } + + // Tries resizing the buffer to contain `count` elements. If T is a POD type + // the new elements may not be initialized. + FMT_CONSTEXPR void try_resize(size_t count) { + try_reserve(count); + size_ = count <= capacity_ ? count : capacity_; + } + + // Tries increasing the buffer capacity to `new_capacity`. It can increase the + // capacity by a smaller amount than requested but guarantees there is space + // for at least one additional element either by increasing the capacity or by + // flushing the buffer if it is full. + FMT_CONSTEXPR void try_reserve(size_t new_capacity) { + if (new_capacity > capacity_) grow_(*this, new_capacity); + } + + FMT_CONSTEXPR void push_back(const T& value) { + try_reserve(size_ + 1); + ptr_[size_++] = value; + } + + /// Appends data to the end of the buffer. + template void append(const U* begin, const U* end) { + while (begin != end) { + auto count = to_unsigned(end - begin); + try_reserve(size_ + count); + auto free_cap = capacity_ - size_; + if (free_cap < count) count = free_cap; + // A loop is faster than memcpy on small sizes. + T* out = ptr_ + size_; + for (size_t i = 0; i < count; ++i) out[i] = begin[i]; + size_ += count; + begin += count; + } + } + + template FMT_CONSTEXPR auto operator[](Idx index) -> T& { + return ptr_[index]; + } + template + FMT_CONSTEXPR auto operator[](Idx index) const -> const T& { + return ptr_[index]; + } +}; + +struct buffer_traits { + explicit buffer_traits(size_t) {} + auto count() const -> size_t { return 0; } + auto limit(size_t size) -> size_t { return size; } +}; + +class fixed_buffer_traits { + private: + size_t count_ = 0; + size_t limit_; + + public: + explicit fixed_buffer_traits(size_t limit) : limit_(limit) {} + auto count() const -> size_t { return count_; } + auto limit(size_t size) -> size_t { + size_t n = limit_ > count_ ? limit_ - count_ : 0; + count_ += size; + return size < n ? size : n; + } +}; + +// A buffer that writes to an output iterator when flushed. +template +class iterator_buffer : public Traits, public buffer { + private: + OutputIt out_; + enum { buffer_size = 256 }; + T data_[buffer_size]; + + static FMT_CONSTEXPR void grow(buffer& buf, size_t) { + if (buf.size() == buffer_size) static_cast(buf).flush(); + } + + void flush() { + auto size = this->size(); + this->clear(); + const T* begin = data_; + const T* end = begin + this->limit(size); + while (begin != end) *out_++ = *begin++; + } + + public: + explicit iterator_buffer(OutputIt out, size_t n = buffer_size) + : Traits(n), buffer(grow, data_, 0, buffer_size), out_(out) {} + iterator_buffer(iterator_buffer&& other) noexcept + : Traits(other), + buffer(grow, data_, 0, buffer_size), + out_(other.out_) {} + ~iterator_buffer() { + // Don't crash if flush fails during unwinding. + FMT_TRY { flush(); } + FMT_CATCH(...) {} + } + + auto out() -> OutputIt { + flush(); + return out_; + } + auto count() const -> size_t { return Traits::count() + this->size(); } +}; + +template +class iterator_buffer : public fixed_buffer_traits, + public buffer { + private: + T* out_; + enum { buffer_size = 256 }; + T data_[buffer_size]; + + static FMT_CONSTEXPR void grow(buffer& buf, size_t) { + if (buf.size() == buf.capacity()) + static_cast(buf).flush(); + } + + void flush() { + size_t n = this->limit(this->size()); + if (this->data() == out_) { + out_ += n; + this->set(data_, buffer_size); + } + this->clear(); + } + + public: + explicit iterator_buffer(T* out, size_t n = buffer_size) + : fixed_buffer_traits(n), buffer(grow, out, 0, n), out_(out) {} + iterator_buffer(iterator_buffer&& other) noexcept + : fixed_buffer_traits(other), + buffer(static_cast(other)), + out_(other.out_) { + if (this->data() != out_) { + this->set(data_, buffer_size); + this->clear(); + } + } + ~iterator_buffer() { flush(); } + + auto out() -> T* { + flush(); + return out_; + } + auto count() const -> size_t { + return fixed_buffer_traits::count() + this->size(); + } +}; + +template class iterator_buffer : public buffer { + public: + explicit iterator_buffer(T* out, size_t = 0) + : buffer([](buffer&, size_t) {}, out, 0, ~size_t()) {} + + auto out() -> T* { return &*this->end(); } +}; + +// A buffer that writes to a container with the contiguous storage. +template +class iterator_buffer< + OutputIt, + enable_if_t::value && + is_contiguous::value, + typename OutputIt::container_type::value_type>> + : public buffer { + private: + using container_type = typename OutputIt::container_type; + using value_type = typename container_type::value_type; + container_type& container_; + + static FMT_CONSTEXPR void grow(buffer& buf, size_t capacity) { + auto& self = static_cast(buf); + self.container_.resize(capacity); + self.set(&self.container_[0], capacity); + } + + public: + explicit iterator_buffer(container_type& c) + : buffer(grow, c.size()), container_(c) {} + explicit iterator_buffer(OutputIt out, size_t = 0) + : iterator_buffer(get_container(out)) {} + + auto out() -> OutputIt { return back_inserter(container_); } +}; + +// A buffer that counts the number of code units written discarding the output. +template class counting_buffer : public buffer { + private: + enum { buffer_size = 256 }; + T data_[buffer_size]; + size_t count_ = 0; + + static FMT_CONSTEXPR void grow(buffer& buf, size_t) { + if (buf.size() != buffer_size) return; + static_cast(buf).count_ += buf.size(); + buf.clear(); + } + + public: + counting_buffer() : buffer(grow, data_, 0, buffer_size) {} + + auto count() -> size_t { return count_ + this->size(); } +}; +} // namespace detail + +template +FMT_CONSTEXPR void basic_format_parse_context::do_check_arg_id(int id) { + // Argument id is only checked at compile-time during parsing because + // formatting has its own validation. + if (detail::is_constant_evaluated() && + (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200)) { + using context = detail::compile_parse_context; + if (id >= static_cast(this)->num_args()) + report_error("argument not found"); + } +} + +template +FMT_CONSTEXPR void basic_format_parse_context::check_dynamic_spec( + int arg_id) { + if (detail::is_constant_evaluated() && + (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200)) { + using context = detail::compile_parse_context; + static_cast(this)->check_dynamic_spec(arg_id); + } +} + +FMT_EXPORT template class basic_format_arg; +FMT_EXPORT template class basic_format_args; +FMT_EXPORT template class dynamic_format_arg_store; + +// A formatter for objects of type T. +FMT_EXPORT +template +struct formatter { + // A deleted default constructor indicates a disabled formatter. + formatter() = delete; +}; + +// Specifies if T has an enabled formatter specialization. A type can be +// formattable even if it doesn't have a formatter e.g. via a conversion. +template +using has_formatter = + std::is_constructible>; + +// An output iterator that appends to a buffer. It is used instead of +// back_insert_iterator to reduce symbol sizes and avoid dependency. +template class basic_appender { + private: + detail::buffer* buffer_; + + friend auto get_container(basic_appender app) -> detail::buffer& { + return *app.buffer_; + } + + public: + using iterator_category = int; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; + using container_type = detail::buffer; + FMT_UNCHECKED_ITERATOR(basic_appender); + + FMT_CONSTEXPR basic_appender(detail::buffer& buf) : buffer_(&buf) {} + + auto operator=(T c) -> basic_appender& { + buffer_->push_back(c); + return *this; + } + auto operator*() -> basic_appender& { return *this; } + auto operator++() -> basic_appender& { return *this; } + auto operator++(int) -> basic_appender { return *this; } +}; + +using appender = basic_appender; + +namespace detail { +template +struct is_back_insert_iterator> : std::true_type {}; + +template +struct locking : std::true_type {}; +template +struct locking>::nonlocking>> + : std::false_type {}; + +template FMT_CONSTEXPR inline auto is_locking() -> bool { + return locking::value; +} +template +FMT_CONSTEXPR inline auto is_locking() -> bool { + return locking::value || is_locking(); +} + +// An optimized version of std::copy with the output value type (T). +template ::value)> +auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { + get_container(out).append(begin, end); + return out; +} + +template ::value)> +FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { + while (begin != end) *out++ = static_cast(*begin++); + return out; +} + +template +FMT_CONSTEXPR auto copy(basic_string_view s, OutputIt out) -> OutputIt { + return copy(s.begin(), s.end(), out); +} + +template +constexpr auto has_const_formatter_impl(T*) + -> decltype(typename Context::template formatter_type().format( + std::declval(), std::declval()), + true) { + return true; +} +template +constexpr auto has_const_formatter_impl(...) -> bool { + return false; +} +template +constexpr auto has_const_formatter() -> bool { + return has_const_formatter_impl(static_cast(nullptr)); +} + +template +struct is_buffer_appender : std::false_type {}; +template +struct is_buffer_appender< + It, bool_constant< + is_back_insert_iterator::value && + std::is_base_of, + typename It::container_type>::value>> + : std::true_type {}; + +// Maps an output iterator to a buffer. +template ::value)> +auto get_buffer(OutputIt out) -> iterator_buffer { + return iterator_buffer(out); +} +template ::value)> +auto get_buffer(OutputIt out) -> buffer& { + return get_container(out); +} + +template +auto get_iterator(Buf& buf, OutputIt) -> decltype(buf.out()) { + return buf.out(); +} +template +auto get_iterator(buffer&, OutputIt out) -> OutputIt { + return out; +} + +struct view {}; + +template struct named_arg : view { + const Char* name; + const T& value; + named_arg(const Char* n, const T& v) : name(n), value(v) {} +}; + +template struct named_arg_info { + const Char* name; + int id; +}; + +template struct is_named_arg : std::false_type {}; +template struct is_statically_named_arg : std::false_type {}; + +template +struct is_named_arg> : std::true_type {}; + +template constexpr auto count() -> size_t { return B ? 1 : 0; } +template constexpr auto count() -> size_t { + return (B1 ? 1 : 0) + count(); +} + +template constexpr auto count_named_args() -> size_t { + return count::value...>(); +} + +template +constexpr auto count_statically_named_args() -> size_t { + return count::value...>(); +} + +struct unformattable {}; +struct unformattable_char : unformattable {}; +struct unformattable_pointer : unformattable {}; + +template struct string_value { + const Char* data; + size_t size; +}; + +template struct named_arg_value { + const named_arg_info* data; + size_t size; +}; + +template struct custom_value { + using parse_context = typename Context::parse_context_type; + void* value; + void (*format)(void* arg, parse_context& parse_ctx, Context& ctx); +}; + +// A formatting argument value. +template class value { + public: + using char_type = typename Context::char_type; + + union { + monostate no_value; + int int_value; + unsigned uint_value; + long long long_long_value; + unsigned long long ulong_long_value; + int128_opt int128_value; + uint128_opt uint128_value; + bool bool_value; + char_type char_value; + float float_value; + double double_value; + long double long_double_value; + const void* pointer; + string_value string; + custom_value custom; + named_arg_value named_args; + }; + + constexpr FMT_ALWAYS_INLINE value() : no_value() {} + constexpr FMT_ALWAYS_INLINE value(int val) : int_value(val) {} + constexpr FMT_ALWAYS_INLINE value(unsigned val) : uint_value(val) {} + constexpr FMT_ALWAYS_INLINE value(long long val) : long_long_value(val) {} + constexpr FMT_ALWAYS_INLINE value(unsigned long long val) + : ulong_long_value(val) {} + FMT_ALWAYS_INLINE value(int128_opt val) : int128_value(val) {} + FMT_ALWAYS_INLINE value(uint128_opt val) : uint128_value(val) {} + constexpr FMT_ALWAYS_INLINE value(float val) : float_value(val) {} + constexpr FMT_ALWAYS_INLINE value(double val) : double_value(val) {} + FMT_ALWAYS_INLINE value(long double val) : long_double_value(val) {} + constexpr FMT_ALWAYS_INLINE value(bool val) : bool_value(val) {} + constexpr FMT_ALWAYS_INLINE value(char_type val) : char_value(val) {} + FMT_CONSTEXPR FMT_ALWAYS_INLINE value(const char_type* val) { + string.data = val; + if (is_constant_evaluated()) string.size = {}; + } + FMT_CONSTEXPR FMT_ALWAYS_INLINE value(basic_string_view val) { + string.data = val.data(); + string.size = val.size(); + } + FMT_ALWAYS_INLINE value(const void* val) : pointer(val) {} + FMT_ALWAYS_INLINE value(const named_arg_info* args, size_t size) + : named_args{args, size} {} + + template FMT_CONSTEXPR20 FMT_ALWAYS_INLINE value(T& val) { + using value_type = remove_const_t; + // T may overload operator& e.g. std::vector::reference in libc++. +#if defined(__cpp_if_constexpr) + if constexpr (std::is_same::value) + custom.value = const_cast(&val); +#endif + if (!is_constant_evaluated()) + custom.value = const_cast(&reinterpret_cast(val)); + // Get the formatter type through the context to allow different contexts + // have different extension points, e.g. `formatter` for `format` and + // `printf_formatter` for `printf`. + custom.format = format_custom_arg< + value_type, typename Context::template formatter_type>; + } + value(unformattable); + value(unformattable_char); + value(unformattable_pointer); + + private: + // Formats an argument of a custom type, such as a user-defined class. + template + static void format_custom_arg(void* arg, + typename Context::parse_context_type& parse_ctx, + Context& ctx) { + auto f = Formatter(); + parse_ctx.advance_to(f.parse(parse_ctx)); + using qualified_type = + conditional_t(), const T, T>; + // format must be const for compatibility with std::format and compilation. + const auto& cf = f; + ctx.advance_to(cf.format(*static_cast(arg), ctx)); + } +}; + +// To minimize the number of types we need to deal with, long is translated +// either to int or to long long depending on its size. +enum { long_short = sizeof(long) == sizeof(int) }; +using long_type = conditional_t; +using ulong_type = conditional_t; + +template struct format_as_result { + template ::value || std::is_class::value)> + static auto map(U*) -> remove_cvref_t()))>; + static auto map(...) -> void; + + using type = decltype(map(static_cast(nullptr))); +}; +template using format_as_t = typename format_as_result::type; + +template +struct has_format_as + : bool_constant, void>::value> {}; + +#define FMT_MAP_API FMT_CONSTEXPR FMT_ALWAYS_INLINE + +// Maps formatting arguments to core types. +// arg_mapper reports errors by returning unformattable instead of using +// static_assert because it's used in the is_formattable trait. +template struct arg_mapper { + using char_type = typename Context::char_type; + + FMT_MAP_API auto map(signed char val) -> int { return val; } + FMT_MAP_API auto map(unsigned char val) -> unsigned { return val; } + FMT_MAP_API auto map(short val) -> int { return val; } + FMT_MAP_API auto map(unsigned short val) -> unsigned { return val; } + FMT_MAP_API auto map(int val) -> int { return val; } + FMT_MAP_API auto map(unsigned val) -> unsigned { return val; } + FMT_MAP_API auto map(long val) -> long_type { return val; } + FMT_MAP_API auto map(unsigned long val) -> ulong_type { return val; } + FMT_MAP_API auto map(long long val) -> long long { return val; } + FMT_MAP_API auto map(unsigned long long val) -> unsigned long long { + return val; + } + FMT_MAP_API auto map(int128_opt val) -> int128_opt { return val; } + FMT_MAP_API auto map(uint128_opt val) -> uint128_opt { return val; } + FMT_MAP_API auto map(bool val) -> bool { return val; } + + template ::value || + std::is_same::value)> + FMT_MAP_API auto map(T val) -> char_type { + return val; + } + template ::value || +#ifdef __cpp_char8_t + std::is_same::value || +#endif + std::is_same::value || + std::is_same::value) && + !std::is_same::value, + int> = 0> + FMT_MAP_API auto map(T) -> unformattable_char { + return {}; + } + + FMT_MAP_API auto map(float val) -> float { return val; } + FMT_MAP_API auto map(double val) -> double { return val; } + FMT_MAP_API auto map(long double val) -> long double { return val; } + + FMT_MAP_API auto map(char_type* val) -> const char_type* { return val; } + FMT_MAP_API auto map(const char_type* val) -> const char_type* { return val; } + template , + FMT_ENABLE_IF(std::is_same::value && + !std::is_pointer::value)> + FMT_MAP_API auto map(const T& val) -> basic_string_view { + return to_string_view(val); + } + template , + FMT_ENABLE_IF(!std::is_same::value && + !std::is_pointer::value)> + FMT_MAP_API auto map(const T&) -> unformattable_char { + return {}; + } + + FMT_MAP_API auto map(void* val) -> const void* { return val; } + FMT_MAP_API auto map(const void* val) -> const void* { return val; } + FMT_MAP_API auto map(volatile void* val) -> const void* { + return const_cast(val); + } + FMT_MAP_API auto map(const volatile void* val) -> const void* { + return const_cast(val); + } + FMT_MAP_API auto map(std::nullptr_t val) -> const void* { return val; } + + // Use SFINAE instead of a const T* parameter to avoid a conflict with the + // array overload. + template < + typename T, + FMT_ENABLE_IF( + std::is_pointer::value || std::is_member_pointer::value || + std::is_function::type>::value || + (std::is_array::value && + !std::is_convertible::value))> + FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer { + return {}; + } + + template ::value)> + FMT_MAP_API auto map(const T (&values)[N]) -> const T (&)[N] { + return values; + } + + // Only map owning types because mapping views can be unsafe. + template , + FMT_ENABLE_IF(std::is_arithmetic::value)> + FMT_MAP_API auto map(const T& val) -> decltype(FMT_DECLTYPE_THIS map(U())) { + return map(format_as(val)); + } + + template > + struct formattable : bool_constant() || + (has_formatter::value && + !std::is_const::value)> {}; + + template ::value)> + FMT_MAP_API auto do_map(T& val) -> T& { + return val; + } + template ::value)> + FMT_MAP_API auto do_map(T&) -> unformattable { + return {}; + } + + // is_fundamental is used to allow formatters for extended FP types. + template , + FMT_ENABLE_IF( + (std::is_class::value || std::is_enum::value || + std::is_union::value || std::is_fundamental::value) && + !has_to_string_view::value && !is_char::value && + !is_named_arg::value && !std::is_integral::value && + !std::is_arithmetic>::value)> + FMT_MAP_API auto map(T& val) -> decltype(FMT_DECLTYPE_THIS do_map(val)) { + return do_map(val); + } + + template ::value)> + FMT_MAP_API auto map(const T& named_arg) + -> decltype(FMT_DECLTYPE_THIS map(named_arg.value)) { + return map(named_arg.value); + } + + auto map(...) -> unformattable { return {}; } +}; + +// A type constant after applying arg_mapper. +template +using mapped_type_constant = + type_constant().map(std::declval())), + typename Context::char_type>; + +enum { packed_arg_bits = 4 }; +// Maximum number of arguments with packed types. +enum { max_packed_args = 62 / packed_arg_bits }; +enum : unsigned long long { is_unpacked_bit = 1ULL << 63 }; +enum : unsigned long long { has_named_args_bit = 1ULL << 62 }; + +template +struct is_output_iterator : std::false_type {}; + +template <> struct is_output_iterator : std::true_type {}; + +template +struct is_output_iterator< + It, T, void_t()++ = std::declval())>> + : std::true_type {}; + +// A type-erased reference to an std::locale to avoid a heavy include. +class locale_ref { + private: + const void* locale_; // A type-erased pointer to std::locale. + + public: + constexpr locale_ref() : locale_(nullptr) {} + template explicit locale_ref(const Locale& loc); + + explicit operator bool() const noexcept { return locale_ != nullptr; } + + template auto get() const -> Locale; +}; + +template constexpr auto encode_types() -> unsigned long long { + return 0; +} + +template +constexpr auto encode_types() -> unsigned long long { + return static_cast(mapped_type_constant::value) | + (encode_types() << packed_arg_bits); +} + +template +constexpr unsigned long long make_descriptor() { + return NUM_ARGS <= max_packed_args ? encode_types() + : is_unpacked_bit | NUM_ARGS; +} + +// This type is intentionally undefined, only used for errors. +template +#if FMT_CLANG_VERSION && FMT_CLANG_VERSION <= 1500 +// https://github.com/fmtlib/fmt/issues/3796 +struct type_is_unformattable_for { +}; +#else +struct type_is_unformattable_for; +#endif + +template +FMT_CONSTEXPR auto make_arg(T& val) -> value { + using arg_type = remove_cvref_t().map(val))>; + + // Use enum instead of constexpr because the latter may generate code. + enum { + formattable_char = !std::is_same::value + }; + static_assert(formattable_char, "Mixing character types is disallowed."); + + // Formatting of arbitrary pointers is disallowed. If you want to format a + // pointer cast it to `void*` or `const void*`. In particular, this forbids + // formatting of `[const] volatile char*` printed as bool by iostreams. + enum { + formattable_pointer = !std::is_same::value + }; + static_assert(formattable_pointer, + "Formatting of non-void pointers is disallowed."); + + enum { formattable = !std::is_same::value }; +#if defined(__cpp_if_constexpr) + if constexpr (!formattable) + type_is_unformattable_for _; +#endif + static_assert( + formattable, + "Cannot format an argument. To make type T formattable provide a " + "formatter specialization: https://fmt.dev/latest/api.html#udt"); + return {arg_mapper().map(val)}; +} + +template +FMT_CONSTEXPR auto make_arg(T& val) -> basic_format_arg { + auto arg = basic_format_arg(); + arg.type_ = mapped_type_constant::value; + arg.value_ = make_arg(val); + return arg; +} + +template +FMT_CONSTEXPR inline auto make_arg(T& val) -> basic_format_arg { + return make_arg(val); +} + +template +using arg_t = conditional_t, + basic_format_arg>; + +template ::value)> +void init_named_arg(named_arg_info*, int& arg_index, int&, const T&) { + ++arg_index; +} +template ::value)> +void init_named_arg(named_arg_info* named_args, int& arg_index, + int& named_arg_index, const T& arg) { + named_args[named_arg_index++] = {arg.name, arg_index++}; +} + +// An array of references to arguments. It can be implicitly converted to +// `fmt::basic_format_args` for passing into type-erased formatting functions +// such as `fmt::vformat`. +template +struct format_arg_store { + // args_[0].named_args points to named_args to avoid bloating format_args. + // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. + static constexpr size_t ARGS_ARR_SIZE = 1 + (NUM_ARGS != 0 ? NUM_ARGS : +1); + + arg_t args[ARGS_ARR_SIZE]; + named_arg_info named_args[NUM_NAMED_ARGS]; + + template + FMT_MAP_API format_arg_store(T&... values) + : args{{named_args, NUM_NAMED_ARGS}, + make_arg(values)...} { + using dummy = int[]; + int arg_index = 0, named_arg_index = 0; + (void)dummy{ + 0, + (init_named_arg(named_args, arg_index, named_arg_index, values), 0)...}; + } + + format_arg_store(format_arg_store&& rhs) { + args[0] = {named_args, NUM_NAMED_ARGS}; + for (size_t i = 1; i < ARGS_ARR_SIZE; ++i) args[i] = rhs.args[i]; + for (size_t i = 0; i < NUM_NAMED_ARGS; ++i) + named_args[i] = rhs.named_args[i]; + } + + format_arg_store(const format_arg_store& rhs) = delete; + format_arg_store& operator=(const format_arg_store& rhs) = delete; + format_arg_store& operator=(format_arg_store&& rhs) = delete; +}; + +// A specialization of format_arg_store without named arguments. +// It is a plain struct to reduce binary size in debug mode. +template +struct format_arg_store { + // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. + arg_t args[NUM_ARGS != 0 ? NUM_ARGS : +1]; +}; + +} // namespace detail +FMT_BEGIN_EXPORT + +// A formatting argument. Context is a template parameter for the compiled API +// where output can be unbuffered. +template class basic_format_arg { + private: + detail::value value_; + detail::type type_; + + template + friend FMT_CONSTEXPR auto detail::make_arg(T& value) + -> basic_format_arg; + + friend class basic_format_args; + friend class dynamic_format_arg_store; + + using char_type = typename Context::char_type; + + template + friend struct detail::format_arg_store; + + basic_format_arg(const detail::named_arg_info* args, size_t size) + : value_(args, size) {} + + public: + class handle { + public: + explicit handle(detail::custom_value custom) : custom_(custom) {} + + void format(typename Context::parse_context_type& parse_ctx, + Context& ctx) const { + custom_.format(custom_.value, parse_ctx, ctx); + } + + private: + detail::custom_value custom_; + }; + + constexpr basic_format_arg() : type_(detail::type::none_type) {} + + constexpr explicit operator bool() const noexcept { + return type_ != detail::type::none_type; + } + + auto type() const -> detail::type { return type_; } + + auto is_integral() const -> bool { return detail::is_integral_type(type_); } + auto is_arithmetic() const -> bool { + return detail::is_arithmetic_type(type_); + } + + /** + * Visits an argument dispatching to the appropriate visit method based on + * the argument type. For example, if the argument type is `double` then + * `vis(value)` will be called with the value of type `double`. + */ + template + FMT_CONSTEXPR FMT_INLINE auto visit(Visitor&& vis) const -> decltype(vis(0)) { + switch (type_) { + case detail::type::none_type: + break; + case detail::type::int_type: + return vis(value_.int_value); + case detail::type::uint_type: + return vis(value_.uint_value); + case detail::type::long_long_type: + return vis(value_.long_long_value); + case detail::type::ulong_long_type: + return vis(value_.ulong_long_value); + case detail::type::int128_type: + return vis(detail::convert_for_visit(value_.int128_value)); + case detail::type::uint128_type: + return vis(detail::convert_for_visit(value_.uint128_value)); + case detail::type::bool_type: + return vis(value_.bool_value); + case detail::type::char_type: + return vis(value_.char_value); + case detail::type::float_type: + return vis(value_.float_value); + case detail::type::double_type: + return vis(value_.double_value); + case detail::type::long_double_type: + return vis(value_.long_double_value); + case detail::type::cstring_type: + return vis(value_.string.data); + case detail::type::string_type: + using sv = basic_string_view; + return vis(sv(value_.string.data, value_.string.size)); + case detail::type::pointer_type: + return vis(value_.pointer); + case detail::type::custom_type: + return vis(typename basic_format_arg::handle(value_.custom)); + } + return vis(monostate()); + } + + auto format_custom(const char_type* parse_begin, + typename Context::parse_context_type& parse_ctx, + Context& ctx) -> bool { + if (type_ != detail::type::custom_type) return false; + parse_ctx.advance_to(parse_begin); + value_.custom.format(value_.custom.value, parse_ctx, ctx); + return true; + } +}; + +template +FMT_DEPRECATED FMT_CONSTEXPR auto visit_format_arg( + Visitor&& vis, const basic_format_arg& arg) -> decltype(vis(0)) { + return arg.visit(static_cast(vis)); +} + +/** + * A view of a collection of formatting arguments. To avoid lifetime issues it + * should only be used as a parameter type in type-erased functions such as + * `vformat`: + * + * void vlog(fmt::string_view fmt, fmt::format_args args); // OK + * fmt::format_args args = fmt::make_format_args(); // Dangling reference + */ +template class basic_format_args { + public: + using size_type = int; + using format_arg = basic_format_arg; + + private: + // A descriptor that contains information about formatting arguments. + // If the number of arguments is less or equal to max_packed_args then + // argument types are passed in the descriptor. This reduces binary code size + // per formatting function call. + unsigned long long desc_; + union { + // If is_packed() returns true then argument values are stored in values_; + // otherwise they are stored in args_. This is done to improve cache + // locality and reduce compiled code size since storing larger objects + // may require more code (at least on x86-64) even if the same amount of + // data is actually copied to stack. It saves ~10% on the bloat test. + const detail::value* values_; + const format_arg* args_; + }; + + constexpr auto is_packed() const -> bool { + return (desc_ & detail::is_unpacked_bit) == 0; + } + constexpr auto has_named_args() const -> bool { + return (desc_ & detail::has_named_args_bit) != 0; + } + + FMT_CONSTEXPR auto type(int index) const -> detail::type { + int shift = index * detail::packed_arg_bits; + unsigned int mask = (1 << detail::packed_arg_bits) - 1; + return static_cast((desc_ >> shift) & mask); + } + + public: + constexpr basic_format_args() : desc_(0), args_(nullptr) {} + + /// Constructs a `basic_format_args` object from `format_arg_store`. + template + constexpr FMT_ALWAYS_INLINE basic_format_args( + const detail::format_arg_store& + store) + : desc_(DESC), values_(store.args + (NUM_NAMED_ARGS != 0 ? 1 : 0)) {} + + template detail::max_packed_args)> + constexpr basic_format_args( + const detail::format_arg_store& + store) + : desc_(DESC), args_(store.args + (NUM_NAMED_ARGS != 0 ? 1 : 0)) {} + + /// Constructs a `basic_format_args` object from `dynamic_format_arg_store`. + constexpr basic_format_args(const dynamic_format_arg_store& store) + : desc_(store.get_types()), args_(store.data()) {} + + /// Constructs a `basic_format_args` object from a dynamic list of arguments. + constexpr basic_format_args(const format_arg* args, int count) + : desc_(detail::is_unpacked_bit | detail::to_unsigned(count)), + args_(args) {} + + /// Returns the argument with the specified id. + FMT_CONSTEXPR auto get(int id) const -> format_arg { + format_arg arg; + if (!is_packed()) { + if (id < max_size()) arg = args_[id]; + return arg; + } + if (static_cast(id) >= detail::max_packed_args) return arg; + arg.type_ = type(id); + if (arg.type_ == detail::type::none_type) return arg; + arg.value_ = values_[id]; + return arg; + } + + template + auto get(basic_string_view name) const -> format_arg { + int id = get_id(name); + return id >= 0 ? get(id) : format_arg(); + } + + template + FMT_CONSTEXPR auto get_id(basic_string_view name) const -> int { + if (!has_named_args()) return -1; + const auto& named_args = + (is_packed() ? values_[-1] : args_[-1].value_).named_args; + for (size_t i = 0; i < named_args.size; ++i) { + if (named_args.data[i].name == name) return named_args.data[i].id; + } + return -1; + } + + auto max_size() const -> int { + unsigned long long max_packed = detail::max_packed_args; + return static_cast(is_packed() ? max_packed + : desc_ & ~detail::is_unpacked_bit); + } +}; + +// A formatting context. +class context { + private: + appender out_; + basic_format_args args_; + detail::locale_ref loc_; + + public: + /// The character type for the output. + using char_type = char; + + using iterator = appender; + using format_arg = basic_format_arg; + using parse_context_type = basic_format_parse_context; + template using formatter_type = formatter; + + /// Constructs a `basic_format_context` object. References to the arguments + /// are stored in the object so make sure they have appropriate lifetimes. + FMT_CONSTEXPR context(iterator out, basic_format_args ctx_args, + detail::locale_ref loc = {}) + : out_(out), args_(ctx_args), loc_(loc) {} + context(context&&) = default; + context(const context&) = delete; + void operator=(const context&) = delete; + + FMT_CONSTEXPR auto arg(int id) const -> format_arg { return args_.get(id); } + auto arg(string_view name) -> format_arg { return args_.get(name); } + FMT_CONSTEXPR auto arg_id(string_view name) -> int { + return args_.get_id(name); + } + auto args() const -> const basic_format_args& { return args_; } + + // Returns an iterator to the beginning of the output range. + FMT_CONSTEXPR auto out() -> iterator { return out_; } + + // Advances the begin iterator to `it`. + void advance_to(iterator) {} + + FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; } +}; + +template class generic_context; + +// Longer aliases for C++20 compatibility. +template +using basic_format_context = + conditional_t::value, context, + generic_context>; +using format_context = context; + +template +using buffered_context = basic_format_context, Char>; + +template +using is_formattable = bool_constant>() + .map(std::declval()))>::value>; + +#if FMT_USE_CONCEPTS +template +concept formattable = is_formattable, Char>::value; +#endif + +/** + * Constructs an object that stores references to arguments and can be + * implicitly converted to `format_args`. `Context` can be omitted in which case + * it defaults to `format_context`. See `arg` for lifetime considerations. + */ +// Take arguments by lvalue references to avoid some lifetime issues, e.g. +// auto args = make_format_args(std::string()); +template (), + unsigned long long DESC = detail::make_descriptor(), + FMT_ENABLE_IF(NUM_NAMED_ARGS == 0)> +constexpr FMT_ALWAYS_INLINE auto make_format_args(T&... args) + -> detail::format_arg_store { + return {{detail::make_arg( + args)...}}; +} + +#ifndef FMT_DOC +template (), + unsigned long long DESC = + detail::make_descriptor() | + static_cast(detail::has_named_args_bit), + FMT_ENABLE_IF(NUM_NAMED_ARGS != 0)> +constexpr auto make_format_args(T&... args) + -> detail::format_arg_store { + return {args...}; +} +#endif + +/** + * Returns a named argument to be used in a formatting function. + * It should only be used in a call to a formatting function or + * `dynamic_format_arg_store::push_back`. + * + * **Example**: + * + * fmt::print("The answer is {answer}.", fmt::arg("answer", 42)); + */ +template +inline auto arg(const Char* name, const T& arg) -> detail::named_arg { + static_assert(!detail::is_named_arg(), "nested named arguments"); + return {name, arg}; +} +FMT_END_EXPORT + +/// An alias for `basic_format_args`. +// A separate type would result in shorter symbols but break ABI compatibility +// between clang and gcc on ARM (#1919). +FMT_EXPORT using format_args = basic_format_args; + +// We cannot use enum classes as bit fields because of a gcc bug, so we put them +// in namespaces instead (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414). +// Additionally, if an underlying type is specified, older gcc incorrectly warns +// that the type is too small. Both bugs are fixed in gcc 9.3. +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 903 +# define FMT_ENUM_UNDERLYING_TYPE(type) +#else +# define FMT_ENUM_UNDERLYING_TYPE(type) : type +#endif +namespace align { +enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, left, right, center, + numeric}; +} +using align_t = align::type; +namespace sign { +enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, minus, plus, space}; +} +using sign_t = sign::type; + +namespace detail { + +template +using unsigned_char = typename conditional_t::value, + std::make_unsigned, + type_identity>::type; + +// Character (code unit) type is erased to prevent template bloat. +struct fill_t { + private: + enum { max_size = 4 }; + char data_[max_size] = {' '}; + unsigned char size_ = 1; + + public: + template + FMT_CONSTEXPR void operator=(basic_string_view s) { + auto size = s.size(); + size_ = static_cast(size); + if (size == 1) { + unsigned uchar = static_cast>(s[0]); + data_[0] = static_cast(uchar); + data_[1] = static_cast(uchar >> 8); + return; + } + FMT_ASSERT(size <= max_size, "invalid fill"); + for (size_t i = 0; i < size; ++i) data_[i] = static_cast(s[i]); + } + + FMT_CONSTEXPR void operator=(char c) { + data_[0] = c; + size_ = 1; + } + + constexpr auto size() const -> size_t { return size_; } + + template constexpr auto get() const -> Char { + using uchar = unsigned char; + return static_cast(static_cast(data_[0]) | + (static_cast(data_[1]) << 8)); + } + + template ::value)> + constexpr auto data() const -> const Char* { + return data_; + } + template ::value)> + constexpr auto data() const -> const Char* { + return nullptr; + } +}; +} // namespace detail + +enum class presentation_type : unsigned char { + // Common specifiers: + none = 0, + debug = 1, // '?' + string = 2, // 's' (string, bool) + + // Integral, bool and character specifiers: + dec = 3, // 'd' + hex, // 'x' or 'X' + oct, // 'o' + bin, // 'b' or 'B' + chr, // 'c' + + // String and pointer specifiers: + pointer = 3, // 'p' + + // Floating-point specifiers: + exp = 1, // 'e' or 'E' (1 since there is no FP debug presentation) + fixed, // 'f' or 'F' + general, // 'g' or 'G' + hexfloat // 'a' or 'A' +}; + +// Format specifiers for built-in and string types. +struct format_specs { + int width; + int precision; + presentation_type type; + align_t align : 4; + sign_t sign : 3; + bool upper : 1; // An uppercase version e.g. 'X' for 'x'. + bool alt : 1; // Alternate form ('#'). + bool localized : 1; + detail::fill_t fill; + + constexpr format_specs() + : width(0), + precision(-1), + type(presentation_type::none), + align(align::none), + sign(sign::none), + upper(false), + alt(false), + localized(false) {} +}; + +namespace detail { + +enum class arg_id_kind { none, index, name }; + +// An argument reference. +template struct arg_ref { + FMT_CONSTEXPR arg_ref() : kind(arg_id_kind::none), val() {} + + FMT_CONSTEXPR explicit arg_ref(int index) + : kind(arg_id_kind::index), val(index) {} + FMT_CONSTEXPR explicit arg_ref(basic_string_view name) + : kind(arg_id_kind::name), val(name) {} + + FMT_CONSTEXPR auto operator=(int idx) -> arg_ref& { + kind = arg_id_kind::index; + val.index = idx; + return *this; + } + + arg_id_kind kind; + union value { + FMT_CONSTEXPR value(int idx = 0) : index(idx) {} + FMT_CONSTEXPR value(basic_string_view n) : name(n) {} + + int index; + basic_string_view name; + } val; +}; + +// Format specifiers with width and precision resolved at formatting rather +// than parsing time to allow reusing the same parsed specifiers with +// different sets of arguments (precompilation of format strings). +template struct dynamic_format_specs : format_specs { + arg_ref width_ref; + arg_ref precision_ref; +}; + +// Converts a character to ASCII. Returns '\0' on conversion failure. +template ::value)> +constexpr auto to_ascii(Char c) -> char { + return c <= 0xff ? static_cast(c) : '\0'; +} + +// Returns the number of code units in a code point or 1 on error. +template +FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int { + if (const_check(sizeof(Char) != 1)) return 1; + auto c = static_cast(*begin); + return static_cast((0x3a55000000000000ull >> (2 * (c >> 3))) & 0x3) + 1; +} + +// Return the result via the out param to workaround gcc bug 77539. +template +FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr& out) -> bool { + for (out = first; out != last; ++out) { + if (*out == value) return true; + } + return false; +} + +template <> +inline auto find(const char* first, const char* last, char value, + const char*& out) -> bool { + out = + static_cast(memchr(first, value, to_unsigned(last - first))); + return out != nullptr; +} + +// Parses the range [begin, end) as an unsigned integer. This function assumes +// that the range is non-empty and the first character is a digit. +template +FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end, + int error_value) noexcept -> int { + FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', ""); + unsigned value = 0, prev = 0; + auto p = begin; + do { + prev = value; + value = value * 10 + unsigned(*p - '0'); + ++p; + } while (p != end && '0' <= *p && *p <= '9'); + auto num_digits = p - begin; + begin = p; + int digits10 = static_cast(sizeof(int) * CHAR_BIT * 3 / 10); + if (num_digits <= digits10) return static_cast(value); + // Check for overflow. + unsigned max = INT_MAX; + return num_digits == digits10 + 1 && + prev * 10ull + unsigned(p[-1] - '0') <= max + ? static_cast(value) + : error_value; +} + +FMT_CONSTEXPR inline auto parse_align(char c) -> align_t { + switch (c) { + case '<': + return align::left; + case '>': + return align::right; + case '^': + return align::center; + } + return align::none; +} + +template constexpr auto is_name_start(Char c) -> bool { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '_'; +} + +template +FMT_CONSTEXPR auto do_parse_arg_id(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + Char c = *begin; + if (c >= '0' && c <= '9') { + int index = 0; + if (c != '0') + index = parse_nonnegative_int(begin, end, INT_MAX); + else + ++begin; + if (begin == end || (*begin != '}' && *begin != ':')) + report_error("invalid format string"); + else + handler.on_index(index); + return begin; + } + if (!is_name_start(c)) { + report_error("invalid format string"); + return begin; + } + auto it = begin; + do { + ++it; + } while (it != end && (is_name_start(*it) || ('0' <= *it && *it <= '9'))); + handler.on_name({begin, to_unsigned(it - begin)}); + return it; +} + +template +FMT_CONSTEXPR auto parse_arg_id(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + FMT_ASSERT(begin != end, ""); + Char c = *begin; + if (c != '}' && c != ':') return do_parse_arg_id(begin, end, handler); + handler.on_auto(); + return begin; +} + +template struct dynamic_spec_id_handler { + basic_format_parse_context& ctx; + arg_ref& ref; + + FMT_CONSTEXPR void on_auto() { + int id = ctx.next_arg_id(); + ref = arg_ref(id); + ctx.check_dynamic_spec(id); + } + FMT_CONSTEXPR void on_index(int id) { + ref = arg_ref(id); + ctx.check_arg_id(id); + ctx.check_dynamic_spec(id); + } + FMT_CONSTEXPR void on_name(basic_string_view id) { + ref = arg_ref(id); + ctx.check_arg_id(id); + } +}; + +// Parses [integer | "{" [arg_id] "}"]. +template +FMT_CONSTEXPR auto parse_dynamic_spec(const Char* begin, const Char* end, + int& value, arg_ref& ref, + basic_format_parse_context& ctx) + -> const Char* { + FMT_ASSERT(begin != end, ""); + if ('0' <= *begin && *begin <= '9') { + int val = parse_nonnegative_int(begin, end, -1); + if (val != -1) + value = val; + else + report_error("number is too big"); + } else if (*begin == '{') { + ++begin; + auto handler = dynamic_spec_id_handler{ctx, ref}; + if (begin != end) begin = parse_arg_id(begin, end, handler); + if (begin != end && *begin == '}') return ++begin; + report_error("invalid format string"); + } + return begin; +} + +template +FMT_CONSTEXPR auto parse_precision(const Char* begin, const Char* end, + int& value, arg_ref& ref, + basic_format_parse_context& ctx) + -> const Char* { + ++begin; + if (begin == end || *begin == '}') { + report_error("invalid precision"); + return begin; + } + return parse_dynamic_spec(begin, end, value, ref, ctx); +} + +enum class state { start, align, sign, hash, zero, width, precision, locale }; + +// Parses standard format specifiers. +template +FMT_CONSTEXPR auto parse_format_specs(const Char* begin, const Char* end, + dynamic_format_specs& specs, + basic_format_parse_context& ctx, + type arg_type) -> const Char* { + auto c = '\0'; + if (end - begin > 1) { + auto next = to_ascii(begin[1]); + c = parse_align(next) == align::none ? to_ascii(*begin) : '\0'; + } else { + if (begin == end) return begin; + c = to_ascii(*begin); + } + + struct { + state current_state = state::start; + FMT_CONSTEXPR void operator()(state s, bool valid = true) { + if (current_state >= s || !valid) + report_error("invalid format specifier"); + current_state = s; + } + } enter_state; + + using pres = presentation_type; + constexpr auto integral_set = sint_set | uint_set | bool_set | char_set; + struct { + const Char*& begin; + dynamic_format_specs& specs; + type arg_type; + + FMT_CONSTEXPR auto operator()(pres pres_type, int set) -> const Char* { + if (!in(arg_type, set)) { + if (arg_type == type::none_type) return begin; + report_error("invalid format specifier"); + } + specs.type = pres_type; + return begin + 1; + } + } parse_presentation_type{begin, specs, arg_type}; + + for (;;) { + switch (c) { + case '<': + case '>': + case '^': + enter_state(state::align); + specs.align = parse_align(c); + ++begin; + break; + case '+': + case '-': + case ' ': + if (arg_type == type::none_type) return begin; + enter_state(state::sign, in(arg_type, sint_set | float_set)); + switch (c) { + case '+': + specs.sign = sign::plus; + break; + case '-': + specs.sign = sign::minus; + break; + case ' ': + specs.sign = sign::space; + break; + } + ++begin; + break; + case '#': + if (arg_type == type::none_type) return begin; + enter_state(state::hash, is_arithmetic_type(arg_type)); + specs.alt = true; + ++begin; + break; + case '0': + enter_state(state::zero); + if (!is_arithmetic_type(arg_type)) { + if (arg_type == type::none_type) return begin; + report_error("format specifier requires numeric argument"); + } + if (specs.align == align::none) { + // Ignore 0 if align is specified for compatibility with std::format. + specs.align = align::numeric; + specs.fill = '0'; + } + ++begin; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '{': + enter_state(state::width); + begin = parse_dynamic_spec(begin, end, specs.width, specs.width_ref, ctx); + break; + case '.': + if (arg_type == type::none_type) return begin; + enter_state(state::precision, + in(arg_type, float_set | string_set | cstring_set)); + begin = parse_precision(begin, end, specs.precision, specs.precision_ref, + ctx); + break; + case 'L': + if (arg_type == type::none_type) return begin; + enter_state(state::locale, is_arithmetic_type(arg_type)); + specs.localized = true; + ++begin; + break; + case 'd': + return parse_presentation_type(pres::dec, integral_set); + case 'X': + specs.upper = true; + FMT_FALLTHROUGH; + case 'x': + return parse_presentation_type(pres::hex, integral_set); + case 'o': + return parse_presentation_type(pres::oct, integral_set); + case 'B': + specs.upper = true; + FMT_FALLTHROUGH; + case 'b': + return parse_presentation_type(pres::bin, integral_set); + case 'E': + specs.upper = true; + FMT_FALLTHROUGH; + case 'e': + return parse_presentation_type(pres::exp, float_set); + case 'F': + specs.upper = true; + FMT_FALLTHROUGH; + case 'f': + return parse_presentation_type(pres::fixed, float_set); + case 'G': + specs.upper = true; + FMT_FALLTHROUGH; + case 'g': + return parse_presentation_type(pres::general, float_set); + case 'A': + specs.upper = true; + FMT_FALLTHROUGH; + case 'a': + return parse_presentation_type(pres::hexfloat, float_set); + case 'c': + if (arg_type == type::bool_type) report_error("invalid format specifier"); + return parse_presentation_type(pres::chr, integral_set); + case 's': + return parse_presentation_type(pres::string, + bool_set | string_set | cstring_set); + case 'p': + return parse_presentation_type(pres::pointer, pointer_set | cstring_set); + case '?': + return parse_presentation_type(pres::debug, + char_set | string_set | cstring_set); + case '}': + return begin; + default: { + if (*begin == '}') return begin; + // Parse fill and alignment. + auto fill_end = begin + code_point_length(begin); + if (end - fill_end <= 0) { + report_error("invalid format specifier"); + return begin; + } + if (*begin == '{') { + report_error("invalid fill character '{'"); + return begin; + } + auto align = parse_align(to_ascii(*fill_end)); + enter_state(state::align, align != align::none); + specs.fill = + basic_string_view(begin, to_unsigned(fill_end - begin)); + specs.align = align; + begin = fill_end + 1; + } + } + if (begin == end) return begin; + c = to_ascii(*begin); + } +} + +template +FMT_CONSTEXPR auto parse_replacement_field(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + struct id_adapter { + Handler& handler; + int arg_id; + + FMT_CONSTEXPR void on_auto() { arg_id = handler.on_arg_id(); } + FMT_CONSTEXPR void on_index(int id) { arg_id = handler.on_arg_id(id); } + FMT_CONSTEXPR void on_name(basic_string_view id) { + arg_id = handler.on_arg_id(id); + } + }; + + ++begin; + if (begin == end) return handler.on_error("invalid format string"), end; + if (*begin == '}') { + handler.on_replacement_field(handler.on_arg_id(), begin); + } else if (*begin == '{') { + handler.on_text(begin, begin + 1); + } else { + auto adapter = id_adapter{handler, 0}; + begin = parse_arg_id(begin, end, adapter); + Char c = begin != end ? *begin : Char(); + if (c == '}') { + handler.on_replacement_field(adapter.arg_id, begin); + } else if (c == ':') { + begin = handler.on_format_specs(adapter.arg_id, begin + 1, end); + if (begin == end || *begin != '}') + return handler.on_error("unknown format specifier"), end; + } else { + return handler.on_error("missing '}' in format string"), end; + } + } + return begin + 1; +} + +template +FMT_CONSTEXPR void parse_format_string(basic_string_view format_str, + Handler&& handler) { + auto begin = format_str.data(); + auto end = begin + format_str.size(); + if (end - begin < 32) { + // Use a simple loop instead of memchr for small strings. + const Char* p = begin; + while (p != end) { + auto c = *p++; + if (c == '{') { + handler.on_text(begin, p - 1); + begin = p = parse_replacement_field(p - 1, end, handler); + } else if (c == '}') { + if (p == end || *p != '}') + return handler.on_error("unmatched '}' in format string"); + handler.on_text(begin, p); + begin = ++p; + } + } + handler.on_text(begin, end); + return; + } + struct writer { + FMT_CONSTEXPR void operator()(const Char* from, const Char* to) { + if (from == to) return; + for (;;) { + const Char* p = nullptr; + if (!find(from, to, Char('}'), p)) + return handler_.on_text(from, to); + ++p; + if (p == to || *p != '}') + return handler_.on_error("unmatched '}' in format string"); + handler_.on_text(from, p); + from = p + 1; + } + } + Handler& handler_; + } write = {handler}; + while (begin != end) { + // Doing two passes with memchr (one for '{' and another for '}') is up to + // 2.5x faster than the naive one-pass implementation on big format strings. + const Char* p = begin; + if (*begin != '{' && !find(begin + 1, end, Char('{'), p)) + return write(begin, end); + write(begin, p); + begin = parse_replacement_field(p, end, handler); + } +} + +template ::value> struct strip_named_arg { + using type = T; +}; +template struct strip_named_arg { + using type = remove_cvref_t; +}; + +template +FMT_VISIBILITY("hidden") // Suppress an ld warning on macOS (#3769). +FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx) + -> decltype(ctx.begin()) { + using char_type = typename ParseContext::char_type; + using context = buffered_context; + using mapped_type = conditional_t< + mapped_type_constant::value != type::custom_type, + decltype(arg_mapper().map(std::declval())), + typename strip_named_arg::type>; +#if defined(__cpp_if_constexpr) + if constexpr (std::is_default_constructible< + formatter>::value) { + return formatter().parse(ctx); + } else { + type_is_unformattable_for _; + return ctx.begin(); + } +#else + return formatter().parse(ctx); +#endif +} + +// Checks char specs and returns true iff the presentation type is char-like. +FMT_CONSTEXPR inline auto check_char_specs(const format_specs& specs) -> bool { + if (specs.type != presentation_type::none && + specs.type != presentation_type::chr && + specs.type != presentation_type::debug) { + return false; + } + if (specs.align == align::numeric || specs.sign != sign::none || specs.alt) + report_error("invalid format specifier for char"); + return true; +} + +#if FMT_USE_NONTYPE_TEMPLATE_ARGS +template +constexpr auto get_arg_index_by_name(basic_string_view name) -> int { + if constexpr (is_statically_named_arg()) { + if (name == T::name) return N; + } + if constexpr (sizeof...(Args) > 0) + return get_arg_index_by_name(name); + (void)name; // Workaround an MSVC bug about "unused" parameter. + return -1; +} +#endif + +template +FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view name) -> int { +#if FMT_USE_NONTYPE_TEMPLATE_ARGS + if constexpr (sizeof...(Args) > 0) + return get_arg_index_by_name<0, Args...>(name); +#endif + (void)name; + return -1; +} + +template class format_string_checker { + private: + using parse_context_type = compile_parse_context; + static constexpr int num_args = sizeof...(Args); + + // Format specifier parsing function. + // In the future basic_format_parse_context will replace compile_parse_context + // here and will use is_constant_evaluated and downcasting to access the data + // needed for compile-time checks: https://godbolt.org/z/GvWzcTjh1. + using parse_func = const Char* (*)(parse_context_type&); + + type types_[num_args > 0 ? static_cast(num_args) : 1]; + parse_context_type context_; + parse_func parse_funcs_[num_args > 0 ? static_cast(num_args) : 1]; + + public: + explicit FMT_CONSTEXPR format_string_checker(basic_string_view fmt) + : types_{mapped_type_constant>::value...}, + context_(fmt, num_args, types_), + parse_funcs_{&parse_format_specs...} {} + + FMT_CONSTEXPR void on_text(const Char*, const Char*) {} + + FMT_CONSTEXPR auto on_arg_id() -> int { return context_.next_arg_id(); } + FMT_CONSTEXPR auto on_arg_id(int id) -> int { + return context_.check_arg_id(id), id; + } + FMT_CONSTEXPR auto on_arg_id(basic_string_view id) -> int { +#if FMT_USE_NONTYPE_TEMPLATE_ARGS + auto index = get_arg_index_by_name(id); + if (index < 0) on_error("named argument is not found"); + return index; +#else + (void)id; + on_error("compile-time checks for named arguments require C++20 support"); + return 0; +#endif + } + + FMT_CONSTEXPR void on_replacement_field(int id, const Char* begin) { + on_format_specs(id, begin, begin); // Call parse() on empty specs. + } + + FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char*) + -> const Char* { + context_.advance_to(begin); + // id >= 0 check is a workaround for gcc 10 bug (#2065). + return id >= 0 && id < num_args ? parse_funcs_[id](context_) : begin; + } + + FMT_NORETURN FMT_CONSTEXPR void on_error(const char* message) { + report_error(message); + } +}; + +// A base class for compile-time strings. +struct compile_string {}; + +template +using is_compile_string = std::is_base_of; + +// Reports a compile-time error if S is not a valid format string. +template ::value)> +FMT_ALWAYS_INLINE void check_format_string(const S&) { +#ifdef FMT_ENFORCE_COMPILE_STRING + static_assert(is_compile_string::value, + "FMT_ENFORCE_COMPILE_STRING requires all format strings to use " + "FMT_STRING."); +#endif +} +template ::value)> +void check_format_string(S format_str) { + using char_t = typename S::char_type; + FMT_CONSTEXPR auto s = basic_string_view(format_str); + using checker = format_string_checker...>; + FMT_CONSTEXPR bool error = (parse_format_string(s, checker(s)), true); + ignore_unused(error); +} + +// Report truncation to prevent silent data loss. +inline void report_truncation(bool truncated) { + if (truncated) report_error("output is truncated"); +} + +// Use vformat_args and avoid type_identity to keep symbols short and workaround +// a GCC <= 4.8 bug. +template struct vformat_args { + using type = basic_format_args>; +}; +template <> struct vformat_args { + using type = format_args; +}; + +template +void vformat_to(buffer& buf, basic_string_view fmt, + typename vformat_args::type args, locale_ref loc = {}); + +FMT_API void vprint_mojibake(FILE*, string_view, format_args, bool = false); +#ifndef _WIN32 +inline void vprint_mojibake(FILE*, string_view, format_args, bool) {} +#endif + +template struct native_formatter { + private: + dynamic_format_specs specs_; + + public: + using nonlocking = void; + + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const Char* { + if (ctx.begin() == ctx.end() || *ctx.begin() == '}') return ctx.begin(); + auto end = parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, TYPE); + if (const_check(TYPE == type::char_type)) check_char_specs(specs_); + return end; + } + + template + FMT_CONSTEXPR void set_debug_format(bool set = true) { + specs_.type = set ? presentation_type::debug : presentation_type::none; + } + + template + FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const + -> decltype(ctx.out()); +}; +} // namespace detail + +FMT_BEGIN_EXPORT + +// A formatter specialization for natively supported types. +template +struct formatter::value != + detail::type::custom_type>> + : detail::native_formatter::value> { +}; + +template struct runtime_format_string { + basic_string_view str; +}; + +/// A compile-time format string. +template class basic_format_string { + private: + basic_string_view str_; + + public: + template < + typename S, + FMT_ENABLE_IF( + std::is_convertible>::value || + (detail::is_compile_string::value && + std::is_constructible, const S&>::value))> + FMT_CONSTEVAL FMT_ALWAYS_INLINE basic_format_string(const S& s) : str_(s) { + static_assert( + detail::count< + (std::is_base_of>::value && + std::is_reference::value)...>() == 0, + "passing views as lvalues is disallowed"); +#if FMT_USE_CONSTEVAL + if constexpr (detail::count_named_args() == + detail::count_statically_named_args()) { + using checker = + detail::format_string_checker...>; + detail::parse_format_string(str_, checker(s)); + } +#else + detail::check_format_string(s); +#endif + } + basic_format_string(runtime_format_string fmt) : str_(fmt.str) {} + + FMT_ALWAYS_INLINE operator basic_string_view() const { return str_; } + auto get() const -> basic_string_view { return str_; } +}; + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 +// Workaround broken conversion on older gcc. +template using format_string = string_view; +inline auto runtime(string_view s) -> string_view { return s; } +#else +template +using format_string = basic_format_string...>; +/** + * Creates a runtime format string. + * + * **Example**: + * + * // Check format string at runtime instead of compile-time. + * fmt::print(fmt::runtime("{:d}"), "I am not a number"); + */ +inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; } +#endif + +/// Formats a string and writes the output to `out`. +template , + char>::value)> +auto vformat_to(OutputIt&& out, string_view fmt, format_args args) + -> remove_cvref_t { + auto&& buf = detail::get_buffer(out); + detail::vformat_to(buf, fmt, args, {}); + return detail::get_iterator(buf, out); +} + +/** + * Formats `args` according to specifications in `fmt`, writes the result to + * the output iterator `out` and returns the iterator past the end of the output + * range. `format_to` does not append a terminating null character. + * + * **Example**: + * + * auto out = std::vector(); + * fmt::format_to(std::back_inserter(out), "{}", 42); + */ +template , + char>::value)> +FMT_INLINE auto format_to(OutputIt&& out, format_string fmt, T&&... args) + -> remove_cvref_t { + return vformat_to(FMT_FWD(out), fmt, fmt::make_format_args(args...)); +} + +template struct format_to_n_result { + /// Iterator past the end of the output range. + OutputIt out; + /// Total (not truncated) output size. + size_t size; +}; + +template ::value)> +auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args) + -> format_to_n_result { + using traits = detail::fixed_buffer_traits; + auto buf = detail::iterator_buffer(out, n); + detail::vformat_to(buf, fmt, args, {}); + return {buf.out(), buf.count()}; +} + +/** + * Formats `args` according to specifications in `fmt`, writes up to `n` + * characters of the result to the output iterator `out` and returns the total + * (not truncated) output size and the iterator past the end of the output + * range. `format_to_n` does not append a terminating null character. + */ +template ::value)> +FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string fmt, + T&&... args) -> format_to_n_result { + return vformat_to_n(out, n, fmt, fmt::make_format_args(args...)); +} + +template +struct format_to_result { + /// Iterator pointing to just after the last successful write in the range. + OutputIt out; + /// Specifies if the output was truncated. + bool truncated; + + FMT_CONSTEXPR operator OutputIt&() & { + detail::report_truncation(truncated); + return out; + } + FMT_CONSTEXPR operator const OutputIt&() const& { + detail::report_truncation(truncated); + return out; + } + FMT_CONSTEXPR operator OutputIt&&() && { + detail::report_truncation(truncated); + return static_cast(out); + } +}; + +template +auto vformat_to(char (&out)[N], string_view fmt, format_args args) + -> format_to_result { + auto result = vformat_to_n(out, N, fmt, args); + return {result.out, result.size > N}; +} + +template +FMT_INLINE auto format_to(char (&out)[N], format_string fmt, T&&... args) + -> format_to_result { + auto result = fmt::format_to_n(out, N, fmt, static_cast(args)...); + return {result.out, result.size > N}; +} + +/// Returns the number of chars in the output of `format(fmt, args...)`. +template +FMT_NODISCARD FMT_INLINE auto formatted_size(format_string fmt, + T&&... args) -> size_t { + auto buf = detail::counting_buffer<>(); + detail::vformat_to(buf, fmt, fmt::make_format_args(args...), {}); + return buf.count(); +} + +FMT_API void vprint(string_view fmt, format_args args); +FMT_API void vprint(FILE* f, string_view fmt, format_args args); +FMT_API void vprint_buffered(FILE* f, string_view fmt, format_args args); +FMT_API void vprintln(FILE* f, string_view fmt, format_args args); + +/** + * Formats `args` according to specifications in `fmt` and writes the output + * to `stdout`. + * + * **Example**: + * + * fmt::print("The answer is {}.", 42); + */ +template +FMT_INLINE void print(format_string fmt, T&&... args) { + const auto& vargs = fmt::make_format_args(args...); + if (!detail::use_utf8()) return detail::vprint_mojibake(stdout, fmt, vargs); + return detail::is_locking() ? vprint_buffered(stdout, fmt, vargs) + : vprint(fmt, vargs); +} + +/** + * Formats `args` according to specifications in `fmt` and writes the + * output to the file `f`. + * + * **Example**: + * + * fmt::print(stderr, "Don't {}!", "panic"); + */ +template +FMT_INLINE void print(FILE* f, format_string fmt, T&&... args) { + const auto& vargs = fmt::make_format_args(args...); + if (!detail::use_utf8()) return detail::vprint_mojibake(f, fmt, vargs); + return detail::is_locking() ? vprint_buffered(f, fmt, vargs) + : vprint(f, fmt, vargs); +} + +/// Formats `args` according to specifications in `fmt` and writes the output +/// to the file `f` followed by a newline. +template +FMT_INLINE void println(FILE* f, format_string fmt, T&&... args) { + const auto& vargs = fmt::make_format_args(args...); + return detail::use_utf8() ? vprintln(f, fmt, vargs) + : detail::vprint_mojibake(f, fmt, vargs, true); +} + +/// Formats `args` according to specifications in `fmt` and writes the output +/// to `stdout` followed by a newline. +template +FMT_INLINE void println(format_string fmt, T&&... args) { + return fmt::println(stdout, fmt, static_cast(args)...); +} + +FMT_END_EXPORT +FMT_GCC_PRAGMA("GCC pop_options") +FMT_END_NAMESPACE + +#ifdef FMT_HEADER_ONLY +# include "format.h" +#endif +#endif // FMT_BASE_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/chrono.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/chrono.h new file mode 100644 index 0000000..c93123f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/chrono.h @@ -0,0 +1,2432 @@ +// Formatting library for C++ - chrono support +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_CHRONO_H_ +#define FMT_CHRONO_H_ + +#ifndef FMT_MODULE +# include +# include +# include // std::isfinite +# include // std::memcpy +# include +# include +# include +# include +# include +#endif + +#include "format.h" + +FMT_BEGIN_NAMESPACE + +// Check if std::chrono::local_t is available. +#ifndef FMT_USE_LOCAL_TIME +# ifdef __cpp_lib_chrono +# define FMT_USE_LOCAL_TIME (__cpp_lib_chrono >= 201907L) +# else +# define FMT_USE_LOCAL_TIME 0 +# endif +#endif + +// Check if std::chrono::utc_timestamp is available. +#ifndef FMT_USE_UTC_TIME +# ifdef __cpp_lib_chrono +# define FMT_USE_UTC_TIME (__cpp_lib_chrono >= 201907L) +# else +# define FMT_USE_UTC_TIME 0 +# endif +#endif + +// Enable tzset. +#ifndef FMT_USE_TZSET +// UWP doesn't provide _tzset. +# if FMT_HAS_INCLUDE("winapifamily.h") +# include +# endif +# if defined(_WIN32) && (!defined(WINAPI_FAMILY) || \ + (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)) +# define FMT_USE_TZSET 1 +# else +# define FMT_USE_TZSET 0 +# endif +#endif + +// Enable safe chrono durations, unless explicitly disabled. +#ifndef FMT_SAFE_DURATION_CAST +# define FMT_SAFE_DURATION_CAST 1 +#endif +#if FMT_SAFE_DURATION_CAST + +// For conversion between std::chrono::durations without undefined +// behaviour or erroneous results. +// This is a stripped down version of duration_cast, for inclusion in fmt. +// See https://github.com/pauldreik/safe_duration_cast +// +// Copyright Paul Dreik 2019 +namespace safe_duration_cast { + +template ::value && + std::numeric_limits::is_signed == + std::numeric_limits::is_signed)> +FMT_CONSTEXPR auto lossless_integral_conversion(const From from, int& ec) + -> To { + ec = 0; + using F = std::numeric_limits; + using T = std::numeric_limits; + static_assert(F::is_integer, "From must be integral"); + static_assert(T::is_integer, "To must be integral"); + + // A and B are both signed, or both unsigned. + if (detail::const_check(F::digits <= T::digits)) { + // From fits in To without any problem. + } else { + // From does not always fit in To, resort to a dynamic check. + if (from < (T::min)() || from > (T::max)()) { + // outside range. + ec = 1; + return {}; + } + } + return static_cast(from); +} + +/// Converts From to To, without loss. If the dynamic value of from +/// can't be converted to To without loss, ec is set. +template ::value && + std::numeric_limits::is_signed != + std::numeric_limits::is_signed)> +FMT_CONSTEXPR auto lossless_integral_conversion(const From from, int& ec) + -> To { + ec = 0; + using F = std::numeric_limits; + using T = std::numeric_limits; + static_assert(F::is_integer, "From must be integral"); + static_assert(T::is_integer, "To must be integral"); + + if (detail::const_check(F::is_signed && !T::is_signed)) { + // From may be negative, not allowed! + if (fmt::detail::is_negative(from)) { + ec = 1; + return {}; + } + // From is positive. Can it always fit in To? + if (detail::const_check(F::digits > T::digits) && + from > static_cast(detail::max_value())) { + ec = 1; + return {}; + } + } + + if (detail::const_check(!F::is_signed && T::is_signed && + F::digits >= T::digits) && + from > static_cast(detail::max_value())) { + ec = 1; + return {}; + } + return static_cast(from); // Lossless conversion. +} + +template ::value)> +FMT_CONSTEXPR auto lossless_integral_conversion(const From from, int& ec) + -> To { + ec = 0; + return from; +} // function + +// clang-format off +/** + * converts From to To if possible, otherwise ec is set. + * + * input | output + * ---------------------------------|--------------- + * NaN | NaN + * Inf | Inf + * normal, fits in output | converted (possibly lossy) + * normal, does not fit in output | ec is set + * subnormal | best effort + * -Inf | -Inf + */ +// clang-format on +template ::value)> +FMT_CONSTEXPR auto safe_float_conversion(const From from, int& ec) -> To { + ec = 0; + using T = std::numeric_limits; + static_assert(std::is_floating_point::value, "From must be floating"); + static_assert(std::is_floating_point::value, "To must be floating"); + + // catch the only happy case + if (std::isfinite(from)) { + if (from >= T::lowest() && from <= (T::max)()) { + return static_cast(from); + } + // not within range. + ec = 1; + return {}; + } + + // nan and inf will be preserved + return static_cast(from); +} // function + +template ::value)> +FMT_CONSTEXPR auto safe_float_conversion(const From from, int& ec) -> To { + ec = 0; + static_assert(std::is_floating_point::value, "From must be floating"); + return from; +} + +/// Safe duration cast between integral durations +template ::value), + FMT_ENABLE_IF(std::is_integral::value)> +auto safe_duration_cast(std::chrono::duration from, + int& ec) -> To { + using From = std::chrono::duration; + ec = 0; + // the basic idea is that we need to convert from count() in the from type + // to count() in the To type, by multiplying it with this: + struct Factor + : std::ratio_divide {}; + + static_assert(Factor::num > 0, "num must be positive"); + static_assert(Factor::den > 0, "den must be positive"); + + // the conversion is like this: multiply from.count() with Factor::num + // /Factor::den and convert it to To::rep, all this without + // overflow/underflow. let's start by finding a suitable type that can hold + // both To, From and Factor::num + using IntermediateRep = + typename std::common_type::type; + + // safe conversion to IntermediateRep + IntermediateRep count = + lossless_integral_conversion(from.count(), ec); + if (ec) return {}; + // multiply with Factor::num without overflow or underflow + if (detail::const_check(Factor::num != 1)) { + const auto max1 = detail::max_value() / Factor::num; + if (count > max1) { + ec = 1; + return {}; + } + const auto min1 = + (std::numeric_limits::min)() / Factor::num; + if (detail::const_check(!std::is_unsigned::value) && + count < min1) { + ec = 1; + return {}; + } + count *= Factor::num; + } + + if (detail::const_check(Factor::den != 1)) count /= Factor::den; + auto tocount = lossless_integral_conversion(count, ec); + return ec ? To() : To(tocount); +} + +/// Safe duration_cast between floating point durations +template ::value), + FMT_ENABLE_IF(std::is_floating_point::value)> +auto safe_duration_cast(std::chrono::duration from, + int& ec) -> To { + using From = std::chrono::duration; + ec = 0; + if (std::isnan(from.count())) { + // nan in, gives nan out. easy. + return To{std::numeric_limits::quiet_NaN()}; + } + // maybe we should also check if from is denormal, and decide what to do about + // it. + + // +-inf should be preserved. + if (std::isinf(from.count())) { + return To{from.count()}; + } + + // the basic idea is that we need to convert from count() in the from type + // to count() in the To type, by multiplying it with this: + struct Factor + : std::ratio_divide {}; + + static_assert(Factor::num > 0, "num must be positive"); + static_assert(Factor::den > 0, "den must be positive"); + + // the conversion is like this: multiply from.count() with Factor::num + // /Factor::den and convert it to To::rep, all this without + // overflow/underflow. let's start by finding a suitable type that can hold + // both To, From and Factor::num + using IntermediateRep = + typename std::common_type::type; + + // force conversion of From::rep -> IntermediateRep to be safe, + // even if it will never happen be narrowing in this context. + IntermediateRep count = + safe_float_conversion(from.count(), ec); + if (ec) { + return {}; + } + + // multiply with Factor::num without overflow or underflow + if (detail::const_check(Factor::num != 1)) { + constexpr auto max1 = detail::max_value() / + static_cast(Factor::num); + if (count > max1) { + ec = 1; + return {}; + } + constexpr auto min1 = std::numeric_limits::lowest() / + static_cast(Factor::num); + if (count < min1) { + ec = 1; + return {}; + } + count *= static_cast(Factor::num); + } + + // this can't go wrong, right? den>0 is checked earlier. + if (detail::const_check(Factor::den != 1)) { + using common_t = typename std::common_type::type; + count /= static_cast(Factor::den); + } + + // convert to the to type, safely + using ToRep = typename To::rep; + + const ToRep tocount = safe_float_conversion(count, ec); + if (ec) { + return {}; + } + return To{tocount}; +} +} // namespace safe_duration_cast +#endif + +// Prevents expansion of a preceding token as a function-style macro. +// Usage: f FMT_NOMACRO() +#define FMT_NOMACRO + +namespace detail { +template struct null {}; +inline auto localtime_r FMT_NOMACRO(...) -> null<> { return null<>(); } +inline auto localtime_s(...) -> null<> { return null<>(); } +inline auto gmtime_r(...) -> null<> { return null<>(); } +inline auto gmtime_s(...) -> null<> { return null<>(); } + +// It is defined here and not in ostream.h because the latter has expensive +// includes. +template class formatbuf : public Streambuf { + private: + using char_type = typename Streambuf::char_type; + using streamsize = decltype(std::declval().sputn(nullptr, 0)); + using int_type = typename Streambuf::int_type; + using traits_type = typename Streambuf::traits_type; + + buffer& buffer_; + + public: + explicit formatbuf(buffer& buf) : buffer_(buf) {} + + protected: + // The put area is always empty. This makes the implementation simpler and has + // the advantage that the streambuf and the buffer are always in sync and + // sputc never writes into uninitialized memory. A disadvantage is that each + // call to sputc always results in a (virtual) call to overflow. There is no + // disadvantage here for sputn since this always results in a call to xsputn. + + auto overflow(int_type ch) -> int_type override { + if (!traits_type::eq_int_type(ch, traits_type::eof())) + buffer_.push_back(static_cast(ch)); + return ch; + } + + auto xsputn(const char_type* s, streamsize count) -> streamsize override { + buffer_.append(s, s + count); + return count; + } +}; + +inline auto get_classic_locale() -> const std::locale& { + static const auto& locale = std::locale::classic(); + return locale; +} + +template struct codecvt_result { + static constexpr const size_t max_size = 32; + CodeUnit buf[max_size]; + CodeUnit* end; +}; + +template +void write_codecvt(codecvt_result& out, string_view in_buf, + const std::locale& loc) { +#if FMT_CLANG_VERSION +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated" + auto& f = std::use_facet>(loc); +# pragma clang diagnostic pop +#else + auto& f = std::use_facet>(loc); +#endif + auto mb = std::mbstate_t(); + const char* from_next = nullptr; + auto result = f.in(mb, in_buf.begin(), in_buf.end(), from_next, + std::begin(out.buf), std::end(out.buf), out.end); + if (result != std::codecvt_base::ok) + FMT_THROW(format_error("failed to format time")); +} + +template +auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc) + -> OutputIt { + if (detail::use_utf8() && loc != get_classic_locale()) { + // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and + // gcc-4. +#if FMT_MSC_VERSION != 0 || \ + (defined(__GLIBCXX__) && \ + (!defined(_GLIBCXX_USE_DUAL_ABI) || _GLIBCXX_USE_DUAL_ABI == 0)) + // The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5 + // and newer. + using code_unit = wchar_t; +#else + using code_unit = char32_t; +#endif + + using unit_t = codecvt_result; + unit_t unit; + write_codecvt(unit, in, loc); + // In UTF-8 is used one to four one-byte code units. + auto u = + to_utf8>(); + if (!u.convert({unit.buf, to_unsigned(unit.end - unit.buf)})) + FMT_THROW(format_error("failed to format time")); + return copy(u.c_str(), u.c_str() + u.size(), out); + } + return copy(in.data(), in.data() + in.size(), out); +} + +template ::value)> +auto write_tm_str(OutputIt out, string_view sv, const std::locale& loc) + -> OutputIt { + codecvt_result unit; + write_codecvt(unit, sv, loc); + return copy(unit.buf, unit.end, out); +} + +template ::value)> +auto write_tm_str(OutputIt out, string_view sv, const std::locale& loc) + -> OutputIt { + return write_encoded_tm_str(out, sv, loc); +} + +template +inline void do_write(buffer& buf, const std::tm& time, + const std::locale& loc, char format, char modifier) { + auto&& format_buf = formatbuf>(buf); + auto&& os = std::basic_ostream(&format_buf); + os.imbue(loc); + const auto& facet = std::use_facet>(loc); + auto end = facet.put(os, os, Char(' '), &time, format, modifier); + if (end.failed()) FMT_THROW(format_error("failed to format time")); +} + +template ::value)> +auto write(OutputIt out, const std::tm& time, const std::locale& loc, + char format, char modifier = 0) -> OutputIt { + auto&& buf = get_buffer(out); + do_write(buf, time, loc, format, modifier); + return get_iterator(buf, out); +} + +template ::value)> +auto write(OutputIt out, const std::tm& time, const std::locale& loc, + char format, char modifier = 0) -> OutputIt { + auto&& buf = basic_memory_buffer(); + do_write(buf, time, loc, format, modifier); + return write_encoded_tm_str(out, string_view(buf.data(), buf.size()), loc); +} + +template +struct is_same_arithmetic_type + : public std::integral_constant::value && + std::is_integral::value) || + (std::is_floating_point::value && + std::is_floating_point::value)> { +}; + +template < + typename To, typename FromRep, typename FromPeriod, + FMT_ENABLE_IF(is_same_arithmetic_type::value)> +auto fmt_duration_cast(std::chrono::duration from) -> To { +#if FMT_SAFE_DURATION_CAST + // Throwing version of safe_duration_cast is only available for + // integer to integer or float to float casts. + int ec; + To to = safe_duration_cast::safe_duration_cast(from, ec); + if (ec) FMT_THROW(format_error("cannot format duration")); + return to; +#else + // Standard duration cast, may overflow. + return std::chrono::duration_cast(from); +#endif +} + +template < + typename To, typename FromRep, typename FromPeriod, + FMT_ENABLE_IF(!is_same_arithmetic_type::value)> +auto fmt_duration_cast(std::chrono::duration from) -> To { + // Mixed integer <-> float cast is not supported by safe_duration_cast. + return std::chrono::duration_cast(from); +} + +template +auto to_time_t( + std::chrono::time_point time_point) + -> std::time_t { + // Cannot use std::chrono::system_clock::to_time_t since this would first + // require a cast to std::chrono::system_clock::time_point, which could + // overflow. + return fmt_duration_cast>( + time_point.time_since_epoch()) + .count(); +} +} // namespace detail + +FMT_BEGIN_EXPORT + +/** + * Converts given time since epoch as `std::time_t` value into calendar time, + * expressed in local time. Unlike `std::localtime`, this function is + * thread-safe on most platforms. + */ +inline auto localtime(std::time_t time) -> std::tm { + struct dispatcher { + std::time_t time_; + std::tm tm_; + + dispatcher(std::time_t t) : time_(t) {} + + auto run() -> bool { + using namespace fmt::detail; + return handle(localtime_r(&time_, &tm_)); + } + + auto handle(std::tm* tm) -> bool { return tm != nullptr; } + + auto handle(detail::null<>) -> bool { + using namespace fmt::detail; + return fallback(localtime_s(&tm_, &time_)); + } + + auto fallback(int res) -> bool { return res == 0; } + +#if !FMT_MSC_VERSION + auto fallback(detail::null<>) -> bool { + using namespace fmt::detail; + std::tm* tm = std::localtime(&time_); + if (tm) tm_ = *tm; + return tm != nullptr; + } +#endif + }; + dispatcher lt(time); + // Too big time values may be unsupported. + if (!lt.run()) FMT_THROW(format_error("time_t value out of range")); + return lt.tm_; +} + +#if FMT_USE_LOCAL_TIME +template +inline auto localtime(std::chrono::local_time time) -> std::tm { + return localtime( + detail::to_time_t(std::chrono::current_zone()->to_sys(time))); +} +#endif + +/** + * Converts given time since epoch as `std::time_t` value into calendar time, + * expressed in Coordinated Universal Time (UTC). Unlike `std::gmtime`, this + * function is thread-safe on most platforms. + */ +inline auto gmtime(std::time_t time) -> std::tm { + struct dispatcher { + std::time_t time_; + std::tm tm_; + + dispatcher(std::time_t t) : time_(t) {} + + auto run() -> bool { + using namespace fmt::detail; + return handle(gmtime_r(&time_, &tm_)); + } + + auto handle(std::tm* tm) -> bool { return tm != nullptr; } + + auto handle(detail::null<>) -> bool { + using namespace fmt::detail; + return fallback(gmtime_s(&tm_, &time_)); + } + + auto fallback(int res) -> bool { return res == 0; } + +#if !FMT_MSC_VERSION + auto fallback(detail::null<>) -> bool { + std::tm* tm = std::gmtime(&time_); + if (tm) tm_ = *tm; + return tm != nullptr; + } +#endif + }; + auto gt = dispatcher(time); + // Too big time values may be unsupported. + if (!gt.run()) FMT_THROW(format_error("time_t value out of range")); + return gt.tm_; +} + +template +inline auto gmtime( + std::chrono::time_point time_point) + -> std::tm { + return gmtime(detail::to_time_t(time_point)); +} + +namespace detail { + +// Writes two-digit numbers a, b and c separated by sep to buf. +// The method by Pavel Novikov based on +// https://johnnylee-sde.github.io/Fast-unsigned-integer-to-time-string/. +inline void write_digit2_separated(char* buf, unsigned a, unsigned b, + unsigned c, char sep) { + unsigned long long digits = + a | (b << 24) | (static_cast(c) << 48); + // Convert each value to BCD. + // We have x = a * 10 + b and we want to convert it to BCD y = a * 16 + b. + // The difference is + // y - x = a * 6 + // a can be found from x: + // a = floor(x / 10) + // then + // y = x + a * 6 = x + floor(x / 10) * 6 + // floor(x / 10) is (x * 205) >> 11 (needs 16 bits). + digits += (((digits * 205) >> 11) & 0x000f00000f00000f) * 6; + // Put low nibbles to high bytes and high nibbles to low bytes. + digits = ((digits & 0x00f00000f00000f0) >> 4) | + ((digits & 0x000f00000f00000f) << 8); + auto usep = static_cast(sep); + // Add ASCII '0' to each digit byte and insert separators. + digits |= 0x3030003030003030 | (usep << 16) | (usep << 40); + + constexpr const size_t len = 8; + if (const_check(is_big_endian())) { + char tmp[len]; + std::memcpy(tmp, &digits, len); + std::reverse_copy(tmp, tmp + len, buf); + } else { + std::memcpy(buf, &digits, len); + } +} + +template +FMT_CONSTEXPR inline auto get_units() -> const char* { + if (std::is_same::value) return "as"; + if (std::is_same::value) return "fs"; + if (std::is_same::value) return "ps"; + if (std::is_same::value) return "ns"; + if (std::is_same::value) return "µs"; + if (std::is_same::value) return "ms"; + if (std::is_same::value) return "cs"; + if (std::is_same::value) return "ds"; + if (std::is_same>::value) return "s"; + if (std::is_same::value) return "das"; + if (std::is_same::value) return "hs"; + if (std::is_same::value) return "ks"; + if (std::is_same::value) return "Ms"; + if (std::is_same::value) return "Gs"; + if (std::is_same::value) return "Ts"; + if (std::is_same::value) return "Ps"; + if (std::is_same::value) return "Es"; + if (std::is_same>::value) return "min"; + if (std::is_same>::value) return "h"; + if (std::is_same>::value) return "d"; + return nullptr; +} + +enum class numeric_system { + standard, + // Alternative numeric system, e.g. 十二 instead of 12 in ja_JP locale. + alternative +}; + +// Glibc extensions for formatting numeric values. +enum class pad_type { + // Pad a numeric result string with zeros (the default). + zero, + // Do not pad a numeric result string. + none, + // Pad a numeric result string with spaces. + space, +}; + +template +auto write_padding(OutputIt out, pad_type pad, int width) -> OutputIt { + if (pad == pad_type::none) return out; + return detail::fill_n(out, width, pad == pad_type::space ? ' ' : '0'); +} + +template +auto write_padding(OutputIt out, pad_type pad) -> OutputIt { + if (pad != pad_type::none) *out++ = pad == pad_type::space ? ' ' : '0'; + return out; +} + +// Parses a put_time-like format string and invokes handler actions. +template +FMT_CONSTEXPR auto parse_chrono_format(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + if (begin == end || *begin == '}') return begin; + if (*begin != '%') FMT_THROW(format_error("invalid format")); + auto ptr = begin; + while (ptr != end) { + pad_type pad = pad_type::zero; + auto c = *ptr; + if (c == '}') break; + if (c != '%') { + ++ptr; + continue; + } + if (begin != ptr) handler.on_text(begin, ptr); + ++ptr; // consume '%' + if (ptr == end) FMT_THROW(format_error("invalid format")); + c = *ptr; + switch (c) { + case '_': + pad = pad_type::space; + ++ptr; + break; + case '-': + pad = pad_type::none; + ++ptr; + break; + } + if (ptr == end) FMT_THROW(format_error("invalid format")); + c = *ptr++; + switch (c) { + case '%': + handler.on_text(ptr - 1, ptr); + break; + case 'n': { + const Char newline[] = {'\n'}; + handler.on_text(newline, newline + 1); + break; + } + case 't': { + const Char tab[] = {'\t'}; + handler.on_text(tab, tab + 1); + break; + } + // Year: + case 'Y': + handler.on_year(numeric_system::standard); + break; + case 'y': + handler.on_short_year(numeric_system::standard); + break; + case 'C': + handler.on_century(numeric_system::standard); + break; + case 'G': + handler.on_iso_week_based_year(); + break; + case 'g': + handler.on_iso_week_based_short_year(); + break; + // Day of the week: + case 'a': + handler.on_abbr_weekday(); + break; + case 'A': + handler.on_full_weekday(); + break; + case 'w': + handler.on_dec0_weekday(numeric_system::standard); + break; + case 'u': + handler.on_dec1_weekday(numeric_system::standard); + break; + // Month: + case 'b': + case 'h': + handler.on_abbr_month(); + break; + case 'B': + handler.on_full_month(); + break; + case 'm': + handler.on_dec_month(numeric_system::standard); + break; + // Day of the year/month: + case 'U': + handler.on_dec0_week_of_year(numeric_system::standard, pad); + break; + case 'W': + handler.on_dec1_week_of_year(numeric_system::standard, pad); + break; + case 'V': + handler.on_iso_week_of_year(numeric_system::standard, pad); + break; + case 'j': + handler.on_day_of_year(); + break; + case 'd': + handler.on_day_of_month(numeric_system::standard, pad); + break; + case 'e': + handler.on_day_of_month(numeric_system::standard, pad_type::space); + break; + // Hour, minute, second: + case 'H': + handler.on_24_hour(numeric_system::standard, pad); + break; + case 'I': + handler.on_12_hour(numeric_system::standard, pad); + break; + case 'M': + handler.on_minute(numeric_system::standard, pad); + break; + case 'S': + handler.on_second(numeric_system::standard, pad); + break; + // Other: + case 'c': + handler.on_datetime(numeric_system::standard); + break; + case 'x': + handler.on_loc_date(numeric_system::standard); + break; + case 'X': + handler.on_loc_time(numeric_system::standard); + break; + case 'D': + handler.on_us_date(); + break; + case 'F': + handler.on_iso_date(); + break; + case 'r': + handler.on_12_hour_time(); + break; + case 'R': + handler.on_24_hour_time(); + break; + case 'T': + handler.on_iso_time(); + break; + case 'p': + handler.on_am_pm(); + break; + case 'Q': + handler.on_duration_value(); + break; + case 'q': + handler.on_duration_unit(); + break; + case 'z': + handler.on_utc_offset(numeric_system::standard); + break; + case 'Z': + handler.on_tz_name(); + break; + // Alternative representation: + case 'E': { + if (ptr == end) FMT_THROW(format_error("invalid format")); + c = *ptr++; + switch (c) { + case 'Y': + handler.on_year(numeric_system::alternative); + break; + case 'y': + handler.on_offset_year(); + break; + case 'C': + handler.on_century(numeric_system::alternative); + break; + case 'c': + handler.on_datetime(numeric_system::alternative); + break; + case 'x': + handler.on_loc_date(numeric_system::alternative); + break; + case 'X': + handler.on_loc_time(numeric_system::alternative); + break; + case 'z': + handler.on_utc_offset(numeric_system::alternative); + break; + default: + FMT_THROW(format_error("invalid format")); + } + break; + } + case 'O': + if (ptr == end) FMT_THROW(format_error("invalid format")); + c = *ptr++; + switch (c) { + case 'y': + handler.on_short_year(numeric_system::alternative); + break; + case 'm': + handler.on_dec_month(numeric_system::alternative); + break; + case 'U': + handler.on_dec0_week_of_year(numeric_system::alternative, pad); + break; + case 'W': + handler.on_dec1_week_of_year(numeric_system::alternative, pad); + break; + case 'V': + handler.on_iso_week_of_year(numeric_system::alternative, pad); + break; + case 'd': + handler.on_day_of_month(numeric_system::alternative, pad); + break; + case 'e': + handler.on_day_of_month(numeric_system::alternative, pad_type::space); + break; + case 'w': + handler.on_dec0_weekday(numeric_system::alternative); + break; + case 'u': + handler.on_dec1_weekday(numeric_system::alternative); + break; + case 'H': + handler.on_24_hour(numeric_system::alternative, pad); + break; + case 'I': + handler.on_12_hour(numeric_system::alternative, pad); + break; + case 'M': + handler.on_minute(numeric_system::alternative, pad); + break; + case 'S': + handler.on_second(numeric_system::alternative, pad); + break; + case 'z': + handler.on_utc_offset(numeric_system::alternative); + break; + default: + FMT_THROW(format_error("invalid format")); + } + break; + default: + FMT_THROW(format_error("invalid format")); + } + begin = ptr; + } + if (begin != ptr) handler.on_text(begin, ptr); + return ptr; +} + +template struct null_chrono_spec_handler { + FMT_CONSTEXPR void unsupported() { + static_cast(this)->unsupported(); + } + FMT_CONSTEXPR void on_year(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_short_year(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_offset_year() { unsupported(); } + FMT_CONSTEXPR void on_century(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_iso_week_based_year() { unsupported(); } + FMT_CONSTEXPR void on_iso_week_based_short_year() { unsupported(); } + FMT_CONSTEXPR void on_abbr_weekday() { unsupported(); } + FMT_CONSTEXPR void on_full_weekday() { unsupported(); } + FMT_CONSTEXPR void on_dec0_weekday(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_dec1_weekday(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_abbr_month() { unsupported(); } + FMT_CONSTEXPR void on_full_month() { unsupported(); } + FMT_CONSTEXPR void on_dec_month(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system, pad_type) { + unsupported(); + } + FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system, pad_type) { + unsupported(); + } + FMT_CONSTEXPR void on_iso_week_of_year(numeric_system, pad_type) { + unsupported(); + } + FMT_CONSTEXPR void on_day_of_year() { unsupported(); } + FMT_CONSTEXPR void on_day_of_month(numeric_system, pad_type) { + unsupported(); + } + FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_second(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_datetime(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_loc_date(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_loc_time(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_us_date() { unsupported(); } + FMT_CONSTEXPR void on_iso_date() { unsupported(); } + FMT_CONSTEXPR void on_12_hour_time() { unsupported(); } + FMT_CONSTEXPR void on_24_hour_time() { unsupported(); } + FMT_CONSTEXPR void on_iso_time() { unsupported(); } + FMT_CONSTEXPR void on_am_pm() { unsupported(); } + FMT_CONSTEXPR void on_duration_value() { unsupported(); } + FMT_CONSTEXPR void on_duration_unit() { unsupported(); } + FMT_CONSTEXPR void on_utc_offset(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_tz_name() { unsupported(); } +}; + +struct tm_format_checker : null_chrono_spec_handler { + FMT_NORETURN void unsupported() { FMT_THROW(format_error("no format")); } + + template + FMT_CONSTEXPR void on_text(const Char*, const Char*) {} + FMT_CONSTEXPR void on_year(numeric_system) {} + FMT_CONSTEXPR void on_short_year(numeric_system) {} + FMT_CONSTEXPR void on_offset_year() {} + FMT_CONSTEXPR void on_century(numeric_system) {} + FMT_CONSTEXPR void on_iso_week_based_year() {} + FMT_CONSTEXPR void on_iso_week_based_short_year() {} + FMT_CONSTEXPR void on_abbr_weekday() {} + FMT_CONSTEXPR void on_full_weekday() {} + FMT_CONSTEXPR void on_dec0_weekday(numeric_system) {} + FMT_CONSTEXPR void on_dec1_weekday(numeric_system) {} + FMT_CONSTEXPR void on_abbr_month() {} + FMT_CONSTEXPR void on_full_month() {} + FMT_CONSTEXPR void on_dec_month(numeric_system) {} + FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_iso_week_of_year(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_day_of_year() {} + FMT_CONSTEXPR void on_day_of_month(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_24_hour(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_12_hour(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_minute(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_second(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_datetime(numeric_system) {} + FMT_CONSTEXPR void on_loc_date(numeric_system) {} + FMT_CONSTEXPR void on_loc_time(numeric_system) {} + FMT_CONSTEXPR void on_us_date() {} + FMT_CONSTEXPR void on_iso_date() {} + FMT_CONSTEXPR void on_12_hour_time() {} + FMT_CONSTEXPR void on_24_hour_time() {} + FMT_CONSTEXPR void on_iso_time() {} + FMT_CONSTEXPR void on_am_pm() {} + FMT_CONSTEXPR void on_utc_offset(numeric_system) {} + FMT_CONSTEXPR void on_tz_name() {} +}; + +inline auto tm_wday_full_name(int wday) -> const char* { + static constexpr const char* full_name_list[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday"}; + return wday >= 0 && wday <= 6 ? full_name_list[wday] : "?"; +} +inline auto tm_wday_short_name(int wday) -> const char* { + static constexpr const char* short_name_list[] = {"Sun", "Mon", "Tue", "Wed", + "Thu", "Fri", "Sat"}; + return wday >= 0 && wday <= 6 ? short_name_list[wday] : "???"; +} + +inline auto tm_mon_full_name(int mon) -> const char* { + static constexpr const char* full_name_list[] = { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}; + return mon >= 0 && mon <= 11 ? full_name_list[mon] : "?"; +} +inline auto tm_mon_short_name(int mon) -> const char* { + static constexpr const char* short_name_list[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + }; + return mon >= 0 && mon <= 11 ? short_name_list[mon] : "???"; +} + +template +struct has_member_data_tm_gmtoff : std::false_type {}; +template +struct has_member_data_tm_gmtoff> + : std::true_type {}; + +template +struct has_member_data_tm_zone : std::false_type {}; +template +struct has_member_data_tm_zone> + : std::true_type {}; + +#if FMT_USE_TZSET +inline void tzset_once() { + static bool init = []() -> bool { + _tzset(); + return true; + }(); + ignore_unused(init); +} +#endif + +// Converts value to Int and checks that it's in the range [0, upper). +template ::value)> +inline auto to_nonnegative_int(T value, Int upper) -> Int { + if (!std::is_unsigned::value && + (value < 0 || to_unsigned(value) > to_unsigned(upper))) { + FMT_THROW(fmt::format_error("chrono value is out of range")); + } + return static_cast(value); +} +template ::value)> +inline auto to_nonnegative_int(T value, Int upper) -> Int { + auto int_value = static_cast(value); + if (int_value < 0 || value > static_cast(upper)) + FMT_THROW(format_error("invalid value")); + return int_value; +} + +constexpr auto pow10(std::uint32_t n) -> long long { + return n == 0 ? 1 : 10 * pow10(n - 1); +} + +// Counts the number of fractional digits in the range [0, 18] according to the +// C++20 spec. If more than 18 fractional digits are required then returns 6 for +// microseconds precision. +template () / 10)> +struct count_fractional_digits { + static constexpr int value = + Num % Den == 0 ? N : count_fractional_digits::value; +}; + +// Base case that doesn't instantiate any more templates +// in order to avoid overflow. +template +struct count_fractional_digits { + static constexpr int value = (Num % Den == 0) ? N : 6; +}; + +// Format subseconds which are given as an integer type with an appropriate +// number of digits. +template +void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) { + constexpr auto num_fractional_digits = + count_fractional_digits::value; + + using subsecond_precision = std::chrono::duration< + typename std::common_type::type, + std::ratio<1, detail::pow10(num_fractional_digits)>>; + + const auto fractional = d - fmt_duration_cast(d); + const auto subseconds = + std::chrono::treat_as_floating_point< + typename subsecond_precision::rep>::value + ? fractional.count() + : fmt_duration_cast(fractional).count(); + auto n = static_cast>(subseconds); + const int num_digits = detail::count_digits(n); + + int leading_zeroes = (std::max)(0, num_fractional_digits - num_digits); + if (precision < 0) { + FMT_ASSERT(!std::is_floating_point::value, ""); + if (std::ratio_less::value) { + *out++ = '.'; + out = detail::fill_n(out, leading_zeroes, '0'); + out = format_decimal(out, n, num_digits).end; + } + } else if (precision > 0) { + *out++ = '.'; + leading_zeroes = (std::min)(leading_zeroes, precision); + int remaining = precision - leading_zeroes; + out = detail::fill_n(out, leading_zeroes, '0'); + if (remaining < num_digits) { + int num_truncated_digits = num_digits - remaining; + n /= to_unsigned(detail::pow10(to_unsigned(num_truncated_digits))); + if (n) { + out = format_decimal(out, n, remaining).end; + } + return; + } + if (n) { + out = format_decimal(out, n, num_digits).end; + remaining -= num_digits; + } + out = detail::fill_n(out, remaining, '0'); + } +} + +// Format subseconds which are given as a floating point type with an +// appropriate number of digits. We cannot pass the Duration here, as we +// explicitly need to pass the Rep value in the chrono_formatter. +template +void write_floating_seconds(memory_buffer& buf, Duration duration, + int num_fractional_digits = -1) { + using rep = typename Duration::rep; + FMT_ASSERT(std::is_floating_point::value, ""); + + auto val = duration.count(); + + if (num_fractional_digits < 0) { + // For `std::round` with fallback to `round`: + // On some toolchains `std::round` is not available (e.g. GCC 6). + using namespace std; + num_fractional_digits = + count_fractional_digits::value; + if (num_fractional_digits < 6 && static_cast(round(val)) != val) + num_fractional_digits = 6; + } + + fmt::format_to(std::back_inserter(buf), FMT_STRING("{:.{}f}"), + std::fmod(val * static_cast(Duration::period::num) / + static_cast(Duration::period::den), + static_cast(60)), + num_fractional_digits); +} + +template +class tm_writer { + private: + static constexpr int days_per_week = 7; + + const std::locale& loc_; + const bool is_classic_; + OutputIt out_; + const Duration* subsecs_; + const std::tm& tm_; + + auto tm_sec() const noexcept -> int { + FMT_ASSERT(tm_.tm_sec >= 0 && tm_.tm_sec <= 61, ""); + return tm_.tm_sec; + } + auto tm_min() const noexcept -> int { + FMT_ASSERT(tm_.tm_min >= 0 && tm_.tm_min <= 59, ""); + return tm_.tm_min; + } + auto tm_hour() const noexcept -> int { + FMT_ASSERT(tm_.tm_hour >= 0 && tm_.tm_hour <= 23, ""); + return tm_.tm_hour; + } + auto tm_mday() const noexcept -> int { + FMT_ASSERT(tm_.tm_mday >= 1 && tm_.tm_mday <= 31, ""); + return tm_.tm_mday; + } + auto tm_mon() const noexcept -> int { + FMT_ASSERT(tm_.tm_mon >= 0 && tm_.tm_mon <= 11, ""); + return tm_.tm_mon; + } + auto tm_year() const noexcept -> long long { return 1900ll + tm_.tm_year; } + auto tm_wday() const noexcept -> int { + FMT_ASSERT(tm_.tm_wday >= 0 && tm_.tm_wday <= 6, ""); + return tm_.tm_wday; + } + auto tm_yday() const noexcept -> int { + FMT_ASSERT(tm_.tm_yday >= 0 && tm_.tm_yday <= 365, ""); + return tm_.tm_yday; + } + + auto tm_hour12() const noexcept -> int { + const auto h = tm_hour(); + const auto z = h < 12 ? h : h - 12; + return z == 0 ? 12 : z; + } + + // POSIX and the C Standard are unclear or inconsistent about what %C and %y + // do if the year is negative or exceeds 9999. Use the convention that %C + // concatenated with %y yields the same output as %Y, and that %Y contains at + // least 4 characters, with more only if necessary. + auto split_year_lower(long long year) const noexcept -> int { + auto l = year % 100; + if (l < 0) l = -l; // l in [0, 99] + return static_cast(l); + } + + // Algorithm: https://en.wikipedia.org/wiki/ISO_week_date. + auto iso_year_weeks(long long curr_year) const noexcept -> int { + const auto prev_year = curr_year - 1; + const auto curr_p = + (curr_year + curr_year / 4 - curr_year / 100 + curr_year / 400) % + days_per_week; + const auto prev_p = + (prev_year + prev_year / 4 - prev_year / 100 + prev_year / 400) % + days_per_week; + return 52 + ((curr_p == 4 || prev_p == 3) ? 1 : 0); + } + auto iso_week_num(int tm_yday, int tm_wday) const noexcept -> int { + return (tm_yday + 11 - (tm_wday == 0 ? days_per_week : tm_wday)) / + days_per_week; + } + auto tm_iso_week_year() const noexcept -> long long { + const auto year = tm_year(); + const auto w = iso_week_num(tm_yday(), tm_wday()); + if (w < 1) return year - 1; + if (w > iso_year_weeks(year)) return year + 1; + return year; + } + auto tm_iso_week_of_year() const noexcept -> int { + const auto year = tm_year(); + const auto w = iso_week_num(tm_yday(), tm_wday()); + if (w < 1) return iso_year_weeks(year - 1); + if (w > iso_year_weeks(year)) return 1; + return w; + } + + void write1(int value) { + *out_++ = static_cast('0' + to_unsigned(value) % 10); + } + void write2(int value) { + const char* d = digits2(to_unsigned(value) % 100); + *out_++ = *d++; + *out_++ = *d; + } + void write2(int value, pad_type pad) { + unsigned int v = to_unsigned(value) % 100; + if (v >= 10) { + const char* d = digits2(v); + *out_++ = *d++; + *out_++ = *d; + } else { + out_ = detail::write_padding(out_, pad); + *out_++ = static_cast('0' + v); + } + } + + void write_year_extended(long long year) { + // At least 4 characters. + int width = 4; + if (year < 0) { + *out_++ = '-'; + year = 0 - year; + --width; + } + uint32_or_64_or_128_t n = to_unsigned(year); + const int num_digits = count_digits(n); + if (width > num_digits) + out_ = detail::fill_n(out_, width - num_digits, '0'); + out_ = format_decimal(out_, n, num_digits).end; + } + void write_year(long long year) { + if (year >= 0 && year < 10000) { + write2(static_cast(year / 100)); + write2(static_cast(year % 100)); + } else { + write_year_extended(year); + } + } + + void write_utc_offset(long offset, numeric_system ns) { + if (offset < 0) { + *out_++ = '-'; + offset = -offset; + } else { + *out_++ = '+'; + } + offset /= 60; + write2(static_cast(offset / 60)); + if (ns != numeric_system::standard) *out_++ = ':'; + write2(static_cast(offset % 60)); + } + template ::value)> + void format_utc_offset_impl(const T& tm, numeric_system ns) { + write_utc_offset(tm.tm_gmtoff, ns); + } + template ::value)> + void format_utc_offset_impl(const T& tm, numeric_system ns) { +#if defined(_WIN32) && defined(_UCRT) +# if FMT_USE_TZSET + tzset_once(); +# endif + long offset = 0; + _get_timezone(&offset); + if (tm.tm_isdst) { + long dstbias = 0; + _get_dstbias(&dstbias); + offset += dstbias; + } + write_utc_offset(-offset, ns); +#else + if (ns == numeric_system::standard) return format_localized('z'); + + // Extract timezone offset from timezone conversion functions. + std::tm gtm = tm; + std::time_t gt = std::mktime(>m); + std::tm ltm = gmtime(gt); + std::time_t lt = std::mktime(<m); + long offset = gt - lt; + write_utc_offset(offset, ns); +#endif + } + + template ::value)> + void format_tz_name_impl(const T& tm) { + if (is_classic_) + out_ = write_tm_str(out_, tm.tm_zone, loc_); + else + format_localized('Z'); + } + template ::value)> + void format_tz_name_impl(const T&) { + format_localized('Z'); + } + + void format_localized(char format, char modifier = 0) { + out_ = write(out_, tm_, loc_, format, modifier); + } + + public: + tm_writer(const std::locale& loc, OutputIt out, const std::tm& tm, + const Duration* subsecs = nullptr) + : loc_(loc), + is_classic_(loc_ == get_classic_locale()), + out_(out), + subsecs_(subsecs), + tm_(tm) {} + + auto out() const -> OutputIt { return out_; } + + FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) { + out_ = copy(begin, end, out_); + } + + void on_abbr_weekday() { + if (is_classic_) + out_ = write(out_, tm_wday_short_name(tm_wday())); + else + format_localized('a'); + } + void on_full_weekday() { + if (is_classic_) + out_ = write(out_, tm_wday_full_name(tm_wday())); + else + format_localized('A'); + } + void on_dec0_weekday(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) return write1(tm_wday()); + format_localized('w', 'O'); + } + void on_dec1_weekday(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) { + auto wday = tm_wday(); + write1(wday == 0 ? days_per_week : wday); + } else { + format_localized('u', 'O'); + } + } + + void on_abbr_month() { + if (is_classic_) + out_ = write(out_, tm_mon_short_name(tm_mon())); + else + format_localized('b'); + } + void on_full_month() { + if (is_classic_) + out_ = write(out_, tm_mon_full_name(tm_mon())); + else + format_localized('B'); + } + + void on_datetime(numeric_system ns) { + if (is_classic_) { + on_abbr_weekday(); + *out_++ = ' '; + on_abbr_month(); + *out_++ = ' '; + on_day_of_month(numeric_system::standard, pad_type::space); + *out_++ = ' '; + on_iso_time(); + *out_++ = ' '; + on_year(numeric_system::standard); + } else { + format_localized('c', ns == numeric_system::standard ? '\0' : 'E'); + } + } + void on_loc_date(numeric_system ns) { + if (is_classic_) + on_us_date(); + else + format_localized('x', ns == numeric_system::standard ? '\0' : 'E'); + } + void on_loc_time(numeric_system ns) { + if (is_classic_) + on_iso_time(); + else + format_localized('X', ns == numeric_system::standard ? '\0' : 'E'); + } + void on_us_date() { + char buf[8]; + write_digit2_separated(buf, to_unsigned(tm_mon() + 1), + to_unsigned(tm_mday()), + to_unsigned(split_year_lower(tm_year())), '/'); + out_ = copy(std::begin(buf), std::end(buf), out_); + } + void on_iso_date() { + auto year = tm_year(); + char buf[10]; + size_t offset = 0; + if (year >= 0 && year < 10000) { + copy2(buf, digits2(static_cast(year / 100))); + } else { + offset = 4; + write_year_extended(year); + year = 0; + } + write_digit2_separated(buf + 2, static_cast(year % 100), + to_unsigned(tm_mon() + 1), to_unsigned(tm_mday()), + '-'); + out_ = copy(std::begin(buf) + offset, std::end(buf), out_); + } + + void on_utc_offset(numeric_system ns) { format_utc_offset_impl(tm_, ns); } + void on_tz_name() { format_tz_name_impl(tm_); } + + void on_year(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) + return write_year(tm_year()); + format_localized('Y', 'E'); + } + void on_short_year(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) + return write2(split_year_lower(tm_year())); + format_localized('y', 'O'); + } + void on_offset_year() { + if (is_classic_) return write2(split_year_lower(tm_year())); + format_localized('y', 'E'); + } + + void on_century(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) { + auto year = tm_year(); + auto upper = year / 100; + if (year >= -99 && year < 0) { + // Zero upper on negative year. + *out_++ = '-'; + *out_++ = '0'; + } else if (upper >= 0 && upper < 100) { + write2(static_cast(upper)); + } else { + out_ = write(out_, upper); + } + } else { + format_localized('C', 'E'); + } + } + + void on_dec_month(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_mon() + 1); + format_localized('m', 'O'); + } + + void on_dec0_week_of_year(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2((tm_yday() + days_per_week - tm_wday()) / days_per_week, + pad); + format_localized('U', 'O'); + } + void on_dec1_week_of_year(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) { + auto wday = tm_wday(); + write2((tm_yday() + days_per_week - + (wday == 0 ? (days_per_week - 1) : (wday - 1))) / + days_per_week, + pad); + } else { + format_localized('W', 'O'); + } + } + void on_iso_week_of_year(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_iso_week_of_year(), pad); + format_localized('V', 'O'); + } + + void on_iso_week_based_year() { write_year(tm_iso_week_year()); } + void on_iso_week_based_short_year() { + write2(split_year_lower(tm_iso_week_year())); + } + + void on_day_of_year() { + auto yday = tm_yday() + 1; + write1(yday / 100); + write2(yday % 100); + } + void on_day_of_month(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_mday(), pad); + format_localized('d', 'O'); + } + + void on_24_hour(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_hour(), pad); + format_localized('H', 'O'); + } + void on_12_hour(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_hour12(), pad); + format_localized('I', 'O'); + } + void on_minute(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_min(), pad); + format_localized('M', 'O'); + } + + void on_second(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) { + write2(tm_sec(), pad); + if (subsecs_) { + if (std::is_floating_point::value) { + auto buf = memory_buffer(); + write_floating_seconds(buf, *subsecs_); + if (buf.size() > 1) { + // Remove the leading "0", write something like ".123". + out_ = std::copy(buf.begin() + 1, buf.end(), out_); + } + } else { + write_fractional_seconds(out_, *subsecs_); + } + } + } else { + // Currently no formatting of subseconds when a locale is set. + format_localized('S', 'O'); + } + } + + void on_12_hour_time() { + if (is_classic_) { + char buf[8]; + write_digit2_separated(buf, to_unsigned(tm_hour12()), + to_unsigned(tm_min()), to_unsigned(tm_sec()), ':'); + out_ = copy(std::begin(buf), std::end(buf), out_); + *out_++ = ' '; + on_am_pm(); + } else { + format_localized('r'); + } + } + void on_24_hour_time() { + write2(tm_hour()); + *out_++ = ':'; + write2(tm_min()); + } + void on_iso_time() { + on_24_hour_time(); + *out_++ = ':'; + on_second(numeric_system::standard, pad_type::zero); + } + + void on_am_pm() { + if (is_classic_) { + *out_++ = tm_hour() < 12 ? 'A' : 'P'; + *out_++ = 'M'; + } else { + format_localized('p'); + } + } + + // These apply to chrono durations but not tm. + void on_duration_value() {} + void on_duration_unit() {} +}; + +struct chrono_format_checker : null_chrono_spec_handler { + bool has_precision_integral = false; + + FMT_NORETURN void unsupported() { FMT_THROW(format_error("no date")); } + + template + FMT_CONSTEXPR void on_text(const Char*, const Char*) {} + FMT_CONSTEXPR void on_day_of_year() {} + FMT_CONSTEXPR void on_24_hour(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_12_hour(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_minute(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_second(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_12_hour_time() {} + FMT_CONSTEXPR void on_24_hour_time() {} + FMT_CONSTEXPR void on_iso_time() {} + FMT_CONSTEXPR void on_am_pm() {} + FMT_CONSTEXPR void on_duration_value() const { + if (has_precision_integral) { + FMT_THROW(format_error("precision not allowed for this argument type")); + } + } + FMT_CONSTEXPR void on_duration_unit() {} +}; + +template ::value&& has_isfinite::value)> +inline auto isfinite(T) -> bool { + return true; +} + +template ::value)> +inline auto mod(T x, int y) -> T { + return x % static_cast(y); +} +template ::value)> +inline auto mod(T x, int y) -> T { + return std::fmod(x, static_cast(y)); +} + +// If T is an integral type, maps T to its unsigned counterpart, otherwise +// leaves it unchanged (unlike std::make_unsigned). +template ::value> +struct make_unsigned_or_unchanged { + using type = T; +}; + +template struct make_unsigned_or_unchanged { + using type = typename std::make_unsigned::type; +}; + +template ::value)> +inline auto get_milliseconds(std::chrono::duration d) + -> std::chrono::duration { + // this may overflow and/or the result may not fit in the + // target type. +#if FMT_SAFE_DURATION_CAST + using CommonSecondsType = + typename std::common_type::type; + const auto d_as_common = fmt_duration_cast(d); + const auto d_as_whole_seconds = + fmt_duration_cast(d_as_common); + // this conversion should be nonproblematic + const auto diff = d_as_common - d_as_whole_seconds; + const auto ms = + fmt_duration_cast>(diff); + return ms; +#else + auto s = fmt_duration_cast(d); + return fmt_duration_cast(d - s); +#endif +} + +template ::value)> +auto format_duration_value(OutputIt out, Rep val, int) -> OutputIt { + return write(out, val); +} + +template ::value)> +auto format_duration_value(OutputIt out, Rep val, int precision) -> OutputIt { + auto specs = format_specs(); + specs.precision = precision; + specs.type = + precision >= 0 ? presentation_type::fixed : presentation_type::general; + return write(out, val, specs); +} + +template +auto copy_unit(string_view unit, OutputIt out, Char) -> OutputIt { + return std::copy(unit.begin(), unit.end(), out); +} + +template +auto copy_unit(string_view unit, OutputIt out, wchar_t) -> OutputIt { + // This works when wchar_t is UTF-32 because units only contain characters + // that have the same representation in UTF-16 and UTF-32. + utf8_to_utf16 u(unit); + return std::copy(u.c_str(), u.c_str() + u.size(), out); +} + +template +auto format_duration_unit(OutputIt out) -> OutputIt { + if (const char* unit = get_units()) + return copy_unit(string_view(unit), out, Char()); + *out++ = '['; + out = write(out, Period::num); + if (const_check(Period::den != 1)) { + *out++ = '/'; + out = write(out, Period::den); + } + *out++ = ']'; + *out++ = 's'; + return out; +} + +class get_locale { + private: + union { + std::locale locale_; + }; + bool has_locale_ = false; + + public: + get_locale(bool localized, locale_ref loc) : has_locale_(localized) { +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR + if (localized) + ::new (&locale_) std::locale(loc.template get()); +#endif + } + ~get_locale() { + if (has_locale_) locale_.~locale(); + } + operator const std::locale&() const { + return has_locale_ ? locale_ : get_classic_locale(); + } +}; + +template +struct chrono_formatter { + FormatContext& context; + OutputIt out; + int precision; + bool localized = false; + // rep is unsigned to avoid overflow. + using rep = + conditional_t::value && sizeof(Rep) < sizeof(int), + unsigned, typename make_unsigned_or_unchanged::type>; + rep val; + using seconds = std::chrono::duration; + seconds s; + using milliseconds = std::chrono::duration; + bool negative; + + using char_type = typename FormatContext::char_type; + using tm_writer_type = tm_writer; + + chrono_formatter(FormatContext& ctx, OutputIt o, + std::chrono::duration d) + : context(ctx), + out(o), + val(static_cast(d.count())), + negative(false) { + if (d.count() < 0) { + val = 0 - val; + negative = true; + } + + // this may overflow and/or the result may not fit in the + // target type. + // might need checked conversion (rep!=Rep) + s = fmt_duration_cast(std::chrono::duration(val)); + } + + // returns true if nan or inf, writes to out. + auto handle_nan_inf() -> bool { + if (isfinite(val)) { + return false; + } + if (isnan(val)) { + write_nan(); + return true; + } + // must be +-inf + if (val > 0) { + write_pinf(); + } else { + write_ninf(); + } + return true; + } + + auto days() const -> Rep { return static_cast(s.count() / 86400); } + auto hour() const -> Rep { + return static_cast(mod((s.count() / 3600), 24)); + } + + auto hour12() const -> Rep { + Rep hour = static_cast(mod((s.count() / 3600), 12)); + return hour <= 0 ? 12 : hour; + } + + auto minute() const -> Rep { + return static_cast(mod((s.count() / 60), 60)); + } + auto second() const -> Rep { return static_cast(mod(s.count(), 60)); } + + auto time() const -> std::tm { + auto time = std::tm(); + time.tm_hour = to_nonnegative_int(hour(), 24); + time.tm_min = to_nonnegative_int(minute(), 60); + time.tm_sec = to_nonnegative_int(second(), 60); + return time; + } + + void write_sign() { + if (negative) { + *out++ = '-'; + negative = false; + } + } + + void write(Rep value, int width, pad_type pad = pad_type::zero) { + write_sign(); + if (isnan(value)) return write_nan(); + uint32_or_64_or_128_t n = + to_unsigned(to_nonnegative_int(value, max_value())); + int num_digits = detail::count_digits(n); + if (width > num_digits) { + out = detail::write_padding(out, pad, width - num_digits); + } + out = format_decimal(out, n, num_digits).end; + } + + void write_nan() { std::copy_n("nan", 3, out); } + void write_pinf() { std::copy_n("inf", 3, out); } + void write_ninf() { std::copy_n("-inf", 4, out); } + + template + void format_tm(const tm& time, Callback cb, Args... args) { + if (isnan(val)) return write_nan(); + get_locale loc(localized, context.locale()); + auto w = tm_writer_type(loc, out, time); + (w.*cb)(args...); + out = w.out(); + } + + void on_text(const char_type* begin, const char_type* end) { + std::copy(begin, end, out); + } + + // These are not implemented because durations don't have date information. + void on_abbr_weekday() {} + void on_full_weekday() {} + void on_dec0_weekday(numeric_system) {} + void on_dec1_weekday(numeric_system) {} + void on_abbr_month() {} + void on_full_month() {} + void on_datetime(numeric_system) {} + void on_loc_date(numeric_system) {} + void on_loc_time(numeric_system) {} + void on_us_date() {} + void on_iso_date() {} + void on_utc_offset(numeric_system) {} + void on_tz_name() {} + void on_year(numeric_system) {} + void on_short_year(numeric_system) {} + void on_offset_year() {} + void on_century(numeric_system) {} + void on_iso_week_based_year() {} + void on_iso_week_based_short_year() {} + void on_dec_month(numeric_system) {} + void on_dec0_week_of_year(numeric_system, pad_type) {} + void on_dec1_week_of_year(numeric_system, pad_type) {} + void on_iso_week_of_year(numeric_system, pad_type) {} + void on_day_of_month(numeric_system, pad_type) {} + + void on_day_of_year() { + if (handle_nan_inf()) return; + write(days(), 0); + } + + void on_24_hour(numeric_system ns, pad_type pad) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) return write(hour(), 2, pad); + auto time = tm(); + time.tm_hour = to_nonnegative_int(hour(), 24); + format_tm(time, &tm_writer_type::on_24_hour, ns, pad); + } + + void on_12_hour(numeric_system ns, pad_type pad) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) return write(hour12(), 2, pad); + auto time = tm(); + time.tm_hour = to_nonnegative_int(hour12(), 12); + format_tm(time, &tm_writer_type::on_12_hour, ns, pad); + } + + void on_minute(numeric_system ns, pad_type pad) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) return write(minute(), 2, pad); + auto time = tm(); + time.tm_min = to_nonnegative_int(minute(), 60); + format_tm(time, &tm_writer_type::on_minute, ns, pad); + } + + void on_second(numeric_system ns, pad_type pad) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) { + if (std::is_floating_point::value) { + auto buf = memory_buffer(); + write_floating_seconds(buf, std::chrono::duration(val), + precision); + if (negative) *out++ = '-'; + if (buf.size() < 2 || buf[1] == '.') { + out = detail::write_padding(out, pad); + } + out = std::copy(buf.begin(), buf.end(), out); + } else { + write(second(), 2, pad); + write_fractional_seconds( + out, std::chrono::duration(val), precision); + } + return; + } + auto time = tm(); + time.tm_sec = to_nonnegative_int(second(), 60); + format_tm(time, &tm_writer_type::on_second, ns, pad); + } + + void on_12_hour_time() { + if (handle_nan_inf()) return; + format_tm(time(), &tm_writer_type::on_12_hour_time); + } + + void on_24_hour_time() { + if (handle_nan_inf()) { + *out++ = ':'; + handle_nan_inf(); + return; + } + + write(hour(), 2); + *out++ = ':'; + write(minute(), 2); + } + + void on_iso_time() { + on_24_hour_time(); + *out++ = ':'; + if (handle_nan_inf()) return; + on_second(numeric_system::standard, pad_type::zero); + } + + void on_am_pm() { + if (handle_nan_inf()) return; + format_tm(time(), &tm_writer_type::on_am_pm); + } + + void on_duration_value() { + if (handle_nan_inf()) return; + write_sign(); + out = format_duration_value(out, val, precision); + } + + void on_duration_unit() { + out = format_duration_unit(out); + } +}; + +} // namespace detail + +#if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907 +using weekday = std::chrono::weekday; +using day = std::chrono::day; +using month = std::chrono::month; +using year = std::chrono::year; +using year_month_day = std::chrono::year_month_day; +#else +// A fallback version of weekday. +class weekday { + private: + unsigned char value_; + + public: + weekday() = default; + constexpr explicit weekday(unsigned wd) noexcept + : value_(static_cast(wd != 7 ? wd : 0)) {} + constexpr auto c_encoding() const noexcept -> unsigned { return value_; } +}; + +class day { + private: + unsigned char value_; + + public: + day() = default; + constexpr explicit day(unsigned d) noexcept + : value_(static_cast(d)) {} + constexpr explicit operator unsigned() const noexcept { return value_; } +}; + +class month { + private: + unsigned char value_; + + public: + month() = default; + constexpr explicit month(unsigned m) noexcept + : value_(static_cast(m)) {} + constexpr explicit operator unsigned() const noexcept { return value_; } +}; + +class year { + private: + int value_; + + public: + year() = default; + constexpr explicit year(int y) noexcept : value_(y) {} + constexpr explicit operator int() const noexcept { return value_; } +}; + +class year_month_day { + private: + fmt::year year_; + fmt::month month_; + fmt::day day_; + + public: + year_month_day() = default; + constexpr year_month_day(const year& y, const month& m, const day& d) noexcept + : year_(y), month_(m), day_(d) {} + constexpr auto year() const noexcept -> fmt::year { return year_; } + constexpr auto month() const noexcept -> fmt::month { return month_; } + constexpr auto day() const noexcept -> fmt::day { return day_; } +}; +#endif + +template +struct formatter : private formatter { + private: + bool localized_ = false; + bool use_tm_formatter_ = false; + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + auto it = ctx.begin(), end = ctx.end(); + if (it != end && *it == 'L') { + ++it; + localized_ = true; + return it; + } + use_tm_formatter_ = it != end && *it != '}'; + return use_tm_formatter_ ? formatter::parse(ctx) : it; + } + + template + auto format(weekday wd, FormatContext& ctx) const -> decltype(ctx.out()) { + auto time = std::tm(); + time.tm_wday = static_cast(wd.c_encoding()); + if (use_tm_formatter_) return formatter::format(time, ctx); + detail::get_locale loc(localized_, ctx.locale()); + auto w = detail::tm_writer(loc, ctx.out(), time); + w.on_abbr_weekday(); + return w.out(); + } +}; + +template +struct formatter : private formatter { + private: + bool use_tm_formatter_ = false; + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + auto it = ctx.begin(), end = ctx.end(); + use_tm_formatter_ = it != end && *it != '}'; + return use_tm_formatter_ ? formatter::parse(ctx) : it; + } + + template + auto format(day d, FormatContext& ctx) const -> decltype(ctx.out()) { + auto time = std::tm(); + time.tm_mday = static_cast(static_cast(d)); + if (use_tm_formatter_) return formatter::format(time, ctx); + detail::get_locale loc(false, ctx.locale()); + auto w = detail::tm_writer(loc, ctx.out(), time); + w.on_day_of_month(detail::numeric_system::standard, detail::pad_type::zero); + return w.out(); + } +}; + +template +struct formatter : private formatter { + private: + bool localized_ = false; + bool use_tm_formatter_ = false; + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + auto it = ctx.begin(), end = ctx.end(); + if (it != end && *it == 'L') { + ++it; + localized_ = true; + return it; + } + use_tm_formatter_ = it != end && *it != '}'; + return use_tm_formatter_ ? formatter::parse(ctx) : it; + } + + template + auto format(month m, FormatContext& ctx) const -> decltype(ctx.out()) { + auto time = std::tm(); + time.tm_mon = static_cast(static_cast(m)) - 1; + if (use_tm_formatter_) return formatter::format(time, ctx); + detail::get_locale loc(localized_, ctx.locale()); + auto w = detail::tm_writer(loc, ctx.out(), time); + w.on_abbr_month(); + return w.out(); + } +}; + +template +struct formatter : private formatter { + private: + bool use_tm_formatter_ = false; + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + auto it = ctx.begin(), end = ctx.end(); + use_tm_formatter_ = it != end && *it != '}'; + return use_tm_formatter_ ? formatter::parse(ctx) : it; + } + + template + auto format(year y, FormatContext& ctx) const -> decltype(ctx.out()) { + auto time = std::tm(); + time.tm_year = static_cast(y) - 1900; + if (use_tm_formatter_) return formatter::format(time, ctx); + detail::get_locale loc(false, ctx.locale()); + auto w = detail::tm_writer(loc, ctx.out(), time); + w.on_year(detail::numeric_system::standard); + return w.out(); + } +}; + +template +struct formatter : private formatter { + private: + bool use_tm_formatter_ = false; + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + auto it = ctx.begin(), end = ctx.end(); + use_tm_formatter_ = it != end && *it != '}'; + return use_tm_formatter_ ? formatter::parse(ctx) : it; + } + + template + auto format(year_month_day val, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto time = std::tm(); + time.tm_year = static_cast(val.year()) - 1900; + time.tm_mon = static_cast(static_cast(val.month())) - 1; + time.tm_mday = static_cast(static_cast(val.day())); + if (use_tm_formatter_) return formatter::format(time, ctx); + detail::get_locale loc(true, ctx.locale()); + auto w = detail::tm_writer(loc, ctx.out(), time); + w.on_iso_date(); + return w.out(); + } +}; + +template +struct formatter, Char> { + private: + format_specs specs_; + detail::arg_ref width_ref_; + detail::arg_ref precision_ref_; + bool localized_ = false; + basic_string_view format_str_; + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + auto it = ctx.begin(), end = ctx.end(); + if (it == end || *it == '}') return it; + + it = detail::parse_align(it, end, specs_); + if (it == end) return it; + + it = detail::parse_dynamic_spec(it, end, specs_.width, width_ref_, ctx); + if (it == end) return it; + + auto checker = detail::chrono_format_checker(); + if (*it == '.') { + checker.has_precision_integral = !std::is_floating_point::value; + it = detail::parse_precision(it, end, specs_.precision, precision_ref_, + ctx); + } + if (it != end && *it == 'L') { + localized_ = true; + ++it; + } + end = detail::parse_chrono_format(it, end, checker); + format_str_ = {it, detail::to_unsigned(end - it)}; + return end; + } + + template + auto format(std::chrono::duration d, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto specs = specs_; + auto precision = specs.precision; + specs.precision = -1; + auto begin = format_str_.begin(), end = format_str_.end(); + // As a possible future optimization, we could avoid extra copying if width + // is not specified. + auto buf = basic_memory_buffer(); + auto out = std::back_inserter(buf); + detail::handle_dynamic_spec(specs.width, width_ref_, + ctx); + detail::handle_dynamic_spec(precision, + precision_ref_, ctx); + if (begin == end || *begin == '}') { + out = detail::format_duration_value(out, d.count(), precision); + detail::format_duration_unit(out); + } else { + using chrono_formatter = + detail::chrono_formatter; + auto f = chrono_formatter(ctx, out, d); + f.precision = precision; + f.localized = localized_; + detail::parse_chrono_format(begin, end, f); + } + return detail::write( + ctx.out(), basic_string_view(buf.data(), buf.size()), specs); + } +}; + +template +struct formatter, + Char> : formatter { + FMT_CONSTEXPR formatter() { + this->format_str_ = detail::string_literal{}; + } + + template + auto format(std::chrono::time_point val, + FormatContext& ctx) const -> decltype(ctx.out()) { + std::tm tm = gmtime(val); + using period = typename Duration::period; + if (detail::const_check( + period::num == 1 && period::den == 1 && + !std::is_floating_point::value)) { + return formatter::format(tm, ctx); + } + Duration epoch = val.time_since_epoch(); + Duration subsecs = detail::fmt_duration_cast( + epoch - detail::fmt_duration_cast(epoch)); + if (subsecs.count() < 0) { + auto second = + detail::fmt_duration_cast(std::chrono::seconds(1)); + if (tm.tm_sec != 0) + --tm.tm_sec; + else + tm = gmtime(val - second); + subsecs += detail::fmt_duration_cast(std::chrono::seconds(1)); + } + return formatter::do_format(tm, ctx, &subsecs); + } +}; + +#if FMT_USE_LOCAL_TIME +template +struct formatter, Char> + : formatter { + FMT_CONSTEXPR formatter() { + this->format_str_ = detail::string_literal{}; + } + + template + auto format(std::chrono::local_time val, FormatContext& ctx) const + -> decltype(ctx.out()) { + using period = typename Duration::period; + if (period::num != 1 || period::den != 1 || + std::is_floating_point::value) { + const auto epoch = val.time_since_epoch(); + const auto subsecs = detail::fmt_duration_cast( + epoch - detail::fmt_duration_cast(epoch)); + + return formatter::do_format(localtime(val), ctx, &subsecs); + } + + return formatter::format(localtime(val), ctx); + } +}; +#endif + +#if FMT_USE_UTC_TIME +template +struct formatter, + Char> + : formatter, + Char> { + template + auto format(std::chrono::time_point val, + FormatContext& ctx) const -> decltype(ctx.out()) { + return formatter< + std::chrono::time_point, + Char>::format(std::chrono::utc_clock::to_sys(val), ctx); + } +}; +#endif + +template struct formatter { + private: + format_specs specs_; + detail::arg_ref width_ref_; + + protected: + basic_string_view format_str_; + + template + auto do_format(const std::tm& tm, FormatContext& ctx, + const Duration* subsecs) const -> decltype(ctx.out()) { + auto specs = specs_; + auto buf = basic_memory_buffer(); + auto out = std::back_inserter(buf); + detail::handle_dynamic_spec(specs.width, width_ref_, + ctx); + + auto loc_ref = ctx.locale(); + detail::get_locale loc(static_cast(loc_ref), loc_ref); + auto w = + detail::tm_writer(loc, out, tm, subsecs); + detail::parse_chrono_format(format_str_.begin(), format_str_.end(), w); + return detail::write( + ctx.out(), basic_string_view(buf.data(), buf.size()), specs); + } + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + auto it = ctx.begin(), end = ctx.end(); + if (it == end || *it == '}') return it; + + it = detail::parse_align(it, end, specs_); + if (it == end) return it; + + it = detail::parse_dynamic_spec(it, end, specs_.width, width_ref_, ctx); + if (it == end) return it; + + end = detail::parse_chrono_format(it, end, detail::tm_format_checker()); + // Replace the default format_str only if the new spec is not empty. + if (end != it) format_str_ = {it, detail::to_unsigned(end - it)}; + return end; + } + + template + auto format(const std::tm& tm, FormatContext& ctx) const + -> decltype(ctx.out()) { + return do_format(tm, ctx, nullptr); + } +}; + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_CHRONO_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/color.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/color.h new file mode 100644 index 0000000..f0e9dd9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/color.h @@ -0,0 +1,612 @@ +// Formatting library for C++ - color support +// +// Copyright (c) 2018 - present, Victor Zverovich and fmt contributors +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_COLOR_H_ +#define FMT_COLOR_H_ + +#include "format.h" + +FMT_BEGIN_NAMESPACE +FMT_BEGIN_EXPORT + +enum class color : uint32_t { + alice_blue = 0xF0F8FF, // rgb(240,248,255) + antique_white = 0xFAEBD7, // rgb(250,235,215) + aqua = 0x00FFFF, // rgb(0,255,255) + aquamarine = 0x7FFFD4, // rgb(127,255,212) + azure = 0xF0FFFF, // rgb(240,255,255) + beige = 0xF5F5DC, // rgb(245,245,220) + bisque = 0xFFE4C4, // rgb(255,228,196) + black = 0x000000, // rgb(0,0,0) + blanched_almond = 0xFFEBCD, // rgb(255,235,205) + blue = 0x0000FF, // rgb(0,0,255) + blue_violet = 0x8A2BE2, // rgb(138,43,226) + brown = 0xA52A2A, // rgb(165,42,42) + burly_wood = 0xDEB887, // rgb(222,184,135) + cadet_blue = 0x5F9EA0, // rgb(95,158,160) + chartreuse = 0x7FFF00, // rgb(127,255,0) + chocolate = 0xD2691E, // rgb(210,105,30) + coral = 0xFF7F50, // rgb(255,127,80) + cornflower_blue = 0x6495ED, // rgb(100,149,237) + cornsilk = 0xFFF8DC, // rgb(255,248,220) + crimson = 0xDC143C, // rgb(220,20,60) + cyan = 0x00FFFF, // rgb(0,255,255) + dark_blue = 0x00008B, // rgb(0,0,139) + dark_cyan = 0x008B8B, // rgb(0,139,139) + dark_golden_rod = 0xB8860B, // rgb(184,134,11) + dark_gray = 0xA9A9A9, // rgb(169,169,169) + dark_green = 0x006400, // rgb(0,100,0) + dark_khaki = 0xBDB76B, // rgb(189,183,107) + dark_magenta = 0x8B008B, // rgb(139,0,139) + dark_olive_green = 0x556B2F, // rgb(85,107,47) + dark_orange = 0xFF8C00, // rgb(255,140,0) + dark_orchid = 0x9932CC, // rgb(153,50,204) + dark_red = 0x8B0000, // rgb(139,0,0) + dark_salmon = 0xE9967A, // rgb(233,150,122) + dark_sea_green = 0x8FBC8F, // rgb(143,188,143) + dark_slate_blue = 0x483D8B, // rgb(72,61,139) + dark_slate_gray = 0x2F4F4F, // rgb(47,79,79) + dark_turquoise = 0x00CED1, // rgb(0,206,209) + dark_violet = 0x9400D3, // rgb(148,0,211) + deep_pink = 0xFF1493, // rgb(255,20,147) + deep_sky_blue = 0x00BFFF, // rgb(0,191,255) + dim_gray = 0x696969, // rgb(105,105,105) + dodger_blue = 0x1E90FF, // rgb(30,144,255) + fire_brick = 0xB22222, // rgb(178,34,34) + floral_white = 0xFFFAF0, // rgb(255,250,240) + forest_green = 0x228B22, // rgb(34,139,34) + fuchsia = 0xFF00FF, // rgb(255,0,255) + gainsboro = 0xDCDCDC, // rgb(220,220,220) + ghost_white = 0xF8F8FF, // rgb(248,248,255) + gold = 0xFFD700, // rgb(255,215,0) + golden_rod = 0xDAA520, // rgb(218,165,32) + gray = 0x808080, // rgb(128,128,128) + green = 0x008000, // rgb(0,128,0) + green_yellow = 0xADFF2F, // rgb(173,255,47) + honey_dew = 0xF0FFF0, // rgb(240,255,240) + hot_pink = 0xFF69B4, // rgb(255,105,180) + indian_red = 0xCD5C5C, // rgb(205,92,92) + indigo = 0x4B0082, // rgb(75,0,130) + ivory = 0xFFFFF0, // rgb(255,255,240) + khaki = 0xF0E68C, // rgb(240,230,140) + lavender = 0xE6E6FA, // rgb(230,230,250) + lavender_blush = 0xFFF0F5, // rgb(255,240,245) + lawn_green = 0x7CFC00, // rgb(124,252,0) + lemon_chiffon = 0xFFFACD, // rgb(255,250,205) + light_blue = 0xADD8E6, // rgb(173,216,230) + light_coral = 0xF08080, // rgb(240,128,128) + light_cyan = 0xE0FFFF, // rgb(224,255,255) + light_golden_rod_yellow = 0xFAFAD2, // rgb(250,250,210) + light_gray = 0xD3D3D3, // rgb(211,211,211) + light_green = 0x90EE90, // rgb(144,238,144) + light_pink = 0xFFB6C1, // rgb(255,182,193) + light_salmon = 0xFFA07A, // rgb(255,160,122) + light_sea_green = 0x20B2AA, // rgb(32,178,170) + light_sky_blue = 0x87CEFA, // rgb(135,206,250) + light_slate_gray = 0x778899, // rgb(119,136,153) + light_steel_blue = 0xB0C4DE, // rgb(176,196,222) + light_yellow = 0xFFFFE0, // rgb(255,255,224) + lime = 0x00FF00, // rgb(0,255,0) + lime_green = 0x32CD32, // rgb(50,205,50) + linen = 0xFAF0E6, // rgb(250,240,230) + magenta = 0xFF00FF, // rgb(255,0,255) + maroon = 0x800000, // rgb(128,0,0) + medium_aquamarine = 0x66CDAA, // rgb(102,205,170) + medium_blue = 0x0000CD, // rgb(0,0,205) + medium_orchid = 0xBA55D3, // rgb(186,85,211) + medium_purple = 0x9370DB, // rgb(147,112,219) + medium_sea_green = 0x3CB371, // rgb(60,179,113) + medium_slate_blue = 0x7B68EE, // rgb(123,104,238) + medium_spring_green = 0x00FA9A, // rgb(0,250,154) + medium_turquoise = 0x48D1CC, // rgb(72,209,204) + medium_violet_red = 0xC71585, // rgb(199,21,133) + midnight_blue = 0x191970, // rgb(25,25,112) + mint_cream = 0xF5FFFA, // rgb(245,255,250) + misty_rose = 0xFFE4E1, // rgb(255,228,225) + moccasin = 0xFFE4B5, // rgb(255,228,181) + navajo_white = 0xFFDEAD, // rgb(255,222,173) + navy = 0x000080, // rgb(0,0,128) + old_lace = 0xFDF5E6, // rgb(253,245,230) + olive = 0x808000, // rgb(128,128,0) + olive_drab = 0x6B8E23, // rgb(107,142,35) + orange = 0xFFA500, // rgb(255,165,0) + orange_red = 0xFF4500, // rgb(255,69,0) + orchid = 0xDA70D6, // rgb(218,112,214) + pale_golden_rod = 0xEEE8AA, // rgb(238,232,170) + pale_green = 0x98FB98, // rgb(152,251,152) + pale_turquoise = 0xAFEEEE, // rgb(175,238,238) + pale_violet_red = 0xDB7093, // rgb(219,112,147) + papaya_whip = 0xFFEFD5, // rgb(255,239,213) + peach_puff = 0xFFDAB9, // rgb(255,218,185) + peru = 0xCD853F, // rgb(205,133,63) + pink = 0xFFC0CB, // rgb(255,192,203) + plum = 0xDDA0DD, // rgb(221,160,221) + powder_blue = 0xB0E0E6, // rgb(176,224,230) + purple = 0x800080, // rgb(128,0,128) + rebecca_purple = 0x663399, // rgb(102,51,153) + red = 0xFF0000, // rgb(255,0,0) + rosy_brown = 0xBC8F8F, // rgb(188,143,143) + royal_blue = 0x4169E1, // rgb(65,105,225) + saddle_brown = 0x8B4513, // rgb(139,69,19) + salmon = 0xFA8072, // rgb(250,128,114) + sandy_brown = 0xF4A460, // rgb(244,164,96) + sea_green = 0x2E8B57, // rgb(46,139,87) + sea_shell = 0xFFF5EE, // rgb(255,245,238) + sienna = 0xA0522D, // rgb(160,82,45) + silver = 0xC0C0C0, // rgb(192,192,192) + sky_blue = 0x87CEEB, // rgb(135,206,235) + slate_blue = 0x6A5ACD, // rgb(106,90,205) + slate_gray = 0x708090, // rgb(112,128,144) + snow = 0xFFFAFA, // rgb(255,250,250) + spring_green = 0x00FF7F, // rgb(0,255,127) + steel_blue = 0x4682B4, // rgb(70,130,180) + tan = 0xD2B48C, // rgb(210,180,140) + teal = 0x008080, // rgb(0,128,128) + thistle = 0xD8BFD8, // rgb(216,191,216) + tomato = 0xFF6347, // rgb(255,99,71) + turquoise = 0x40E0D0, // rgb(64,224,208) + violet = 0xEE82EE, // rgb(238,130,238) + wheat = 0xF5DEB3, // rgb(245,222,179) + white = 0xFFFFFF, // rgb(255,255,255) + white_smoke = 0xF5F5F5, // rgb(245,245,245) + yellow = 0xFFFF00, // rgb(255,255,0) + yellow_green = 0x9ACD32 // rgb(154,205,50) +}; // enum class color + +enum class terminal_color : uint8_t { + black = 30, + red, + green, + yellow, + blue, + magenta, + cyan, + white, + bright_black = 90, + bright_red, + bright_green, + bright_yellow, + bright_blue, + bright_magenta, + bright_cyan, + bright_white +}; + +enum class emphasis : uint8_t { + bold = 1, + faint = 1 << 1, + italic = 1 << 2, + underline = 1 << 3, + blink = 1 << 4, + reverse = 1 << 5, + conceal = 1 << 6, + strikethrough = 1 << 7, +}; + +// rgb is a struct for red, green and blue colors. +// Using the name "rgb" makes some editors show the color in a tooltip. +struct rgb { + FMT_CONSTEXPR rgb() : r(0), g(0), b(0) {} + FMT_CONSTEXPR rgb(uint8_t r_, uint8_t g_, uint8_t b_) : r(r_), g(g_), b(b_) {} + FMT_CONSTEXPR rgb(uint32_t hex) + : r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b(hex & 0xFF) {} + FMT_CONSTEXPR rgb(color hex) + : r((uint32_t(hex) >> 16) & 0xFF), + g((uint32_t(hex) >> 8) & 0xFF), + b(uint32_t(hex) & 0xFF) {} + uint8_t r; + uint8_t g; + uint8_t b; +}; + +namespace detail { + +// color is a struct of either a rgb color or a terminal color. +struct color_type { + FMT_CONSTEXPR color_type() noexcept : is_rgb(), value{} {} + FMT_CONSTEXPR color_type(color rgb_color) noexcept : is_rgb(true), value{} { + value.rgb_color = static_cast(rgb_color); + } + FMT_CONSTEXPR color_type(rgb rgb_color) noexcept : is_rgb(true), value{} { + value.rgb_color = (static_cast(rgb_color.r) << 16) | + (static_cast(rgb_color.g) << 8) | rgb_color.b; + } + FMT_CONSTEXPR color_type(terminal_color term_color) noexcept + : is_rgb(), value{} { + value.term_color = static_cast(term_color); + } + bool is_rgb; + union color_union { + uint8_t term_color; + uint32_t rgb_color; + } value; +}; +} // namespace detail + +/// A text style consisting of foreground and background colors and emphasis. +class text_style { + public: + FMT_CONSTEXPR text_style(emphasis em = emphasis()) noexcept + : set_foreground_color(), set_background_color(), ems(em) {} + + FMT_CONSTEXPR auto operator|=(const text_style& rhs) -> text_style& { + if (!set_foreground_color) { + set_foreground_color = rhs.set_foreground_color; + foreground_color = rhs.foreground_color; + } else if (rhs.set_foreground_color) { + if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb) + report_error("can't OR a terminal color"); + foreground_color.value.rgb_color |= rhs.foreground_color.value.rgb_color; + } + + if (!set_background_color) { + set_background_color = rhs.set_background_color; + background_color = rhs.background_color; + } else if (rhs.set_background_color) { + if (!background_color.is_rgb || !rhs.background_color.is_rgb) + report_error("can't OR a terminal color"); + background_color.value.rgb_color |= rhs.background_color.value.rgb_color; + } + + ems = static_cast(static_cast(ems) | + static_cast(rhs.ems)); + return *this; + } + + friend FMT_CONSTEXPR auto operator|(text_style lhs, const text_style& rhs) + -> text_style { + return lhs |= rhs; + } + + FMT_CONSTEXPR auto has_foreground() const noexcept -> bool { + return set_foreground_color; + } + FMT_CONSTEXPR auto has_background() const noexcept -> bool { + return set_background_color; + } + FMT_CONSTEXPR auto has_emphasis() const noexcept -> bool { + return static_cast(ems) != 0; + } + FMT_CONSTEXPR auto get_foreground() const noexcept -> detail::color_type { + FMT_ASSERT(has_foreground(), "no foreground specified for this style"); + return foreground_color; + } + FMT_CONSTEXPR auto get_background() const noexcept -> detail::color_type { + FMT_ASSERT(has_background(), "no background specified for this style"); + return background_color; + } + FMT_CONSTEXPR auto get_emphasis() const noexcept -> emphasis { + FMT_ASSERT(has_emphasis(), "no emphasis specified for this style"); + return ems; + } + + private: + FMT_CONSTEXPR text_style(bool is_foreground, + detail::color_type text_color) noexcept + : set_foreground_color(), set_background_color(), ems() { + if (is_foreground) { + foreground_color = text_color; + set_foreground_color = true; + } else { + background_color = text_color; + set_background_color = true; + } + } + + friend FMT_CONSTEXPR auto fg(detail::color_type foreground) noexcept + -> text_style; + + friend FMT_CONSTEXPR auto bg(detail::color_type background) noexcept + -> text_style; + + detail::color_type foreground_color; + detail::color_type background_color; + bool set_foreground_color; + bool set_background_color; + emphasis ems; +}; + +/// Creates a text style from the foreground (text) color. +FMT_CONSTEXPR inline auto fg(detail::color_type foreground) noexcept + -> text_style { + return text_style(true, foreground); +} + +/// Creates a text style from the background color. +FMT_CONSTEXPR inline auto bg(detail::color_type background) noexcept + -> text_style { + return text_style(false, background); +} + +FMT_CONSTEXPR inline auto operator|(emphasis lhs, emphasis rhs) noexcept + -> text_style { + return text_style(lhs) | rhs; +} + +namespace detail { + +template struct ansi_color_escape { + FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color, + const char* esc) noexcept { + // If we have a terminal color, we need to output another escape code + // sequence. + if (!text_color.is_rgb) { + bool is_background = esc == string_view("\x1b[48;2;"); + uint32_t value = text_color.value.term_color; + // Background ASCII codes are the same as the foreground ones but with + // 10 more. + if (is_background) value += 10u; + + size_t index = 0; + buffer[index++] = static_cast('\x1b'); + buffer[index++] = static_cast('['); + + if (value >= 100u) { + buffer[index++] = static_cast('1'); + value %= 100u; + } + buffer[index++] = static_cast('0' + value / 10u); + buffer[index++] = static_cast('0' + value % 10u); + + buffer[index++] = static_cast('m'); + buffer[index++] = static_cast('\0'); + return; + } + + for (int i = 0; i < 7; i++) { + buffer[i] = static_cast(esc[i]); + } + rgb color(text_color.value.rgb_color); + to_esc(color.r, buffer + 7, ';'); + to_esc(color.g, buffer + 11, ';'); + to_esc(color.b, buffer + 15, 'm'); + buffer[19] = static_cast(0); + } + FMT_CONSTEXPR ansi_color_escape(emphasis em) noexcept { + uint8_t em_codes[num_emphases] = {}; + if (has_emphasis(em, emphasis::bold)) em_codes[0] = 1; + if (has_emphasis(em, emphasis::faint)) em_codes[1] = 2; + if (has_emphasis(em, emphasis::italic)) em_codes[2] = 3; + if (has_emphasis(em, emphasis::underline)) em_codes[3] = 4; + if (has_emphasis(em, emphasis::blink)) em_codes[4] = 5; + if (has_emphasis(em, emphasis::reverse)) em_codes[5] = 7; + if (has_emphasis(em, emphasis::conceal)) em_codes[6] = 8; + if (has_emphasis(em, emphasis::strikethrough)) em_codes[7] = 9; + + size_t index = 0; + for (size_t i = 0; i < num_emphases; ++i) { + if (!em_codes[i]) continue; + buffer[index++] = static_cast('\x1b'); + buffer[index++] = static_cast('['); + buffer[index++] = static_cast('0' + em_codes[i]); + buffer[index++] = static_cast('m'); + } + buffer[index++] = static_cast(0); + } + FMT_CONSTEXPR operator const Char*() const noexcept { return buffer; } + + FMT_CONSTEXPR auto begin() const noexcept -> const Char* { return buffer; } + FMT_CONSTEXPR20 auto end() const noexcept -> const Char* { + return buffer + basic_string_view(buffer).size(); + } + + private: + static constexpr size_t num_emphases = 8; + Char buffer[7u + 3u * num_emphases + 1u]; + + static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out, + char delimiter) noexcept { + out[0] = static_cast('0' + c / 100); + out[1] = static_cast('0' + c / 10 % 10); + out[2] = static_cast('0' + c % 10); + out[3] = static_cast(delimiter); + } + static FMT_CONSTEXPR auto has_emphasis(emphasis em, emphasis mask) noexcept + -> bool { + return static_cast(em) & static_cast(mask); + } +}; + +template +FMT_CONSTEXPR auto make_foreground_color(detail::color_type foreground) noexcept + -> ansi_color_escape { + return ansi_color_escape(foreground, "\x1b[38;2;"); +} + +template +FMT_CONSTEXPR auto make_background_color(detail::color_type background) noexcept + -> ansi_color_escape { + return ansi_color_escape(background, "\x1b[48;2;"); +} + +template +FMT_CONSTEXPR auto make_emphasis(emphasis em) noexcept + -> ansi_color_escape { + return ansi_color_escape(em); +} + +template inline void reset_color(buffer& buffer) { + auto reset_color = string_view("\x1b[0m"); + buffer.append(reset_color.begin(), reset_color.end()); +} + +template struct styled_arg : detail::view { + const T& value; + text_style style; + styled_arg(const T& v, text_style s) : value(v), style(s) {} +}; + +template +void vformat_to( + buffer& buf, const text_style& ts, basic_string_view format_str, + basic_format_args>> args) { + bool has_style = false; + if (ts.has_emphasis()) { + has_style = true; + auto emphasis = detail::make_emphasis(ts.get_emphasis()); + buf.append(emphasis.begin(), emphasis.end()); + } + if (ts.has_foreground()) { + has_style = true; + auto foreground = detail::make_foreground_color(ts.get_foreground()); + buf.append(foreground.begin(), foreground.end()); + } + if (ts.has_background()) { + has_style = true; + auto background = detail::make_background_color(ts.get_background()); + buf.append(background.begin(), background.end()); + } + detail::vformat_to(buf, format_str, args, {}); + if (has_style) detail::reset_color(buf); +} + +} // namespace detail + +inline void vprint(FILE* f, const text_style& ts, string_view fmt, + format_args args) { + auto buf = memory_buffer(); + detail::vformat_to(buf, ts, fmt, args); + print(f, FMT_STRING("{}"), string_view(buf.begin(), buf.size())); +} + +/** + * Formats a string and prints it to the specified file stream using ANSI + * escape sequences to specify text formatting. + * + * **Example**: + * + * fmt::print(fmt::emphasis::bold | fg(fmt::color::red), + * "Elapsed time: {0:.2f} seconds", 1.23); + */ +template +void print(FILE* f, const text_style& ts, format_string fmt, + T&&... args) { + vprint(f, ts, fmt, fmt::make_format_args(args...)); +} + +/** + * Formats a string and prints it to stdout using ANSI escape sequences to + * specify text formatting. + * + * **Example**: + * + * fmt::print(fmt::emphasis::bold | fg(fmt::color::red), + * "Elapsed time: {0:.2f} seconds", 1.23); + */ +template +void print(const text_style& ts, format_string fmt, T&&... args) { + return print(stdout, ts, fmt, std::forward(args)...); +} + +inline auto vformat(const text_style& ts, string_view fmt, format_args args) + -> std::string { + auto buf = memory_buffer(); + detail::vformat_to(buf, ts, fmt, args); + return fmt::to_string(buf); +} + +/** + * Formats arguments and returns the result as a string using ANSI escape + * sequences to specify text formatting. + * + * **Example**: + * + * ``` + * #include + * std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red), + * "The answer is {}", 42); + * ``` + */ +template +inline auto format(const text_style& ts, format_string fmt, T&&... args) + -> std::string { + return fmt::vformat(ts, fmt, fmt::make_format_args(args...)); +} + +/// Formats a string with the given text_style and writes the output to `out`. +template ::value)> +auto vformat_to(OutputIt out, const text_style& ts, string_view fmt, + format_args args) -> OutputIt { + auto&& buf = detail::get_buffer(out); + detail::vformat_to(buf, ts, fmt, args); + return detail::get_iterator(buf, out); +} + +/** + * Formats arguments with the given text style, writes the result to the output + * iterator `out` and returns the iterator past the end of the output range. + * + * **Example**: + * + * std::vector out; + * fmt::format_to(std::back_inserter(out), + * fmt::emphasis::bold | fg(fmt::color::red), "{}", 42); + */ +template ::value)> +inline auto format_to(OutputIt out, const text_style& ts, + format_string fmt, T&&... args) -> OutputIt { + return vformat_to(out, ts, fmt, fmt::make_format_args(args...)); +} + +template +struct formatter, Char> : formatter { + template + auto format(const detail::styled_arg& arg, FormatContext& ctx) const + -> decltype(ctx.out()) { + const auto& ts = arg.style; + const auto& value = arg.value; + auto out = ctx.out(); + + bool has_style = false; + if (ts.has_emphasis()) { + has_style = true; + auto emphasis = detail::make_emphasis(ts.get_emphasis()); + out = std::copy(emphasis.begin(), emphasis.end(), out); + } + if (ts.has_foreground()) { + has_style = true; + auto foreground = + detail::make_foreground_color(ts.get_foreground()); + out = std::copy(foreground.begin(), foreground.end(), out); + } + if (ts.has_background()) { + has_style = true; + auto background = + detail::make_background_color(ts.get_background()); + out = std::copy(background.begin(), background.end(), out); + } + out = formatter::format(value, ctx); + if (has_style) { + auto reset_color = string_view("\x1b[0m"); + out = std::copy(reset_color.begin(), reset_color.end(), out); + } + return out; + } +}; + +/** + * Returns an argument that will be formatted using ANSI escape sequences, + * to be used in a formatting function. + * + * **Example**: + * + * fmt::print("Elapsed time: {0:.2f} seconds", + * fmt::styled(1.23, fmt::fg(fmt::color::green) | + * fmt::bg(fmt::color::blue))); + */ +template +FMT_CONSTEXPR auto styled(const T& value, text_style ts) + -> detail::styled_arg> { + return detail::styled_arg>{value, ts}; +} + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_COLOR_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/compile.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/compile.h new file mode 100644 index 0000000..b2afc2c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/compile.h @@ -0,0 +1,529 @@ +// Formatting library for C++ - experimental format string compilation +// +// Copyright (c) 2012 - present, Victor Zverovich and fmt contributors +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_COMPILE_H_ +#define FMT_COMPILE_H_ + +#ifndef FMT_MODULE +# include // std::back_inserter +#endif + +#include "format.h" + +FMT_BEGIN_NAMESPACE + +// A compile-time string which is compiled into fast formatting code. +FMT_EXPORT class compiled_string {}; + +namespace detail { + +template +FMT_CONSTEXPR inline auto copy(InputIt begin, InputIt end, counting_iterator it) + -> counting_iterator { + return it + (end - begin); +} + +template +struct is_compiled_string : std::is_base_of {}; + +/** + * Converts a string literal `s` into a format string that will be parsed at + * compile time and converted into efficient formatting code. Requires C++17 + * `constexpr if` compiler support. + * + * **Example**: + * + * // Converts 42 into std::string using the most efficient method and no + * // runtime format string processing. + * std::string s = fmt::format(FMT_COMPILE("{}"), 42); + */ +#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) +# define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::compiled_string, explicit) +#else +# define FMT_COMPILE(s) FMT_STRING(s) +#endif + +#if FMT_USE_NONTYPE_TEMPLATE_ARGS +template Str> +struct udl_compiled_string : compiled_string { + using char_type = Char; + explicit constexpr operator basic_string_view() const { + return {Str.data, N - 1}; + } +}; +#endif + +template +auto first(const T& value, const Tail&...) -> const T& { + return value; +} + +#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) +template struct type_list {}; + +// Returns a reference to the argument at index N from [first, rest...]. +template +constexpr const auto& get([[maybe_unused]] const T& first, + [[maybe_unused]] const Args&... rest) { + static_assert(N < 1 + sizeof...(Args), "index is out of bounds"); + if constexpr (N == 0) + return first; + else + return detail::get(rest...); +} + +template +constexpr int get_arg_index_by_name(basic_string_view name, + type_list) { + return get_arg_index_by_name(name); +} + +template struct get_type_impl; + +template struct get_type_impl> { + using type = + remove_cvref_t(std::declval()...))>; +}; + +template +using get_type = typename get_type_impl::type; + +template struct is_compiled_format : std::false_type {}; + +template struct text { + basic_string_view data; + using char_type = Char; + + template + constexpr OutputIt format(OutputIt out, const Args&...) const { + return write(out, data); + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +template +constexpr text make_text(basic_string_view s, size_t pos, + size_t size) { + return {{&s[pos], size}}; +} + +template struct code_unit { + Char value; + using char_type = Char; + + template + constexpr OutputIt format(OutputIt out, const Args&...) const { + *out++ = value; + return out; + } +}; + +// This ensures that the argument type is convertible to `const T&`. +template +constexpr const T& get_arg_checked(const Args&... args) { + const auto& arg = detail::get(args...); + if constexpr (detail::is_named_arg>()) { + return arg.value; + } else { + return arg; + } +} + +template +struct is_compiled_format> : std::true_type {}; + +// A replacement field that refers to argument N. +template struct field { + using char_type = Char; + + template + constexpr OutputIt format(OutputIt out, const Args&... args) const { + const T& arg = get_arg_checked(args...); + if constexpr (std::is_convertible>::value) { + auto s = basic_string_view(arg); + return copy(s.begin(), s.end(), out); + } + return write(out, arg); + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +// A replacement field that refers to argument with name. +template struct runtime_named_field { + using char_type = Char; + basic_string_view name; + + template + constexpr static bool try_format_argument( + OutputIt& out, + // [[maybe_unused]] due to unused-but-set-parameter warning in GCC 7,8,9 + [[maybe_unused]] basic_string_view arg_name, const T& arg) { + if constexpr (is_named_arg::type>::value) { + if (arg_name == arg.name) { + out = write(out, arg.value); + return true; + } + } + return false; + } + + template + constexpr OutputIt format(OutputIt out, const Args&... args) const { + bool found = (try_format_argument(out, name, args) || ...); + if (!found) { + FMT_THROW(format_error("argument with specified name is not found")); + } + return out; + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +// A replacement field that refers to argument N and has format specifiers. +template struct spec_field { + using char_type = Char; + formatter fmt; + + template + constexpr FMT_INLINE OutputIt format(OutputIt out, + const Args&... args) const { + const auto& vargs = + fmt::make_format_args>(args...); + basic_format_context ctx(out, vargs); + return fmt.format(get_arg_checked(args...), ctx); + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +template struct concat { + L lhs; + R rhs; + using char_type = typename L::char_type; + + template + constexpr OutputIt format(OutputIt out, const Args&... args) const { + out = lhs.format(out, args...); + return rhs.format(out, args...); + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +template +constexpr concat make_concat(L lhs, R rhs) { + return {lhs, rhs}; +} + +struct unknown_format {}; + +template +constexpr size_t parse_text(basic_string_view str, size_t pos) { + for (size_t size = str.size(); pos != size; ++pos) { + if (str[pos] == '{' || str[pos] == '}') break; + } + return pos; +} + +template +constexpr auto compile_format_string(S fmt); + +template +constexpr auto parse_tail(T head, S fmt) { + if constexpr (POS != basic_string_view(fmt).size()) { + constexpr auto tail = compile_format_string(fmt); + if constexpr (std::is_same, + unknown_format>()) + return tail; + else + return make_concat(head, tail); + } else { + return head; + } +} + +template struct parse_specs_result { + formatter fmt; + size_t end; + int next_arg_id; +}; + +enum { manual_indexing_id = -1 }; + +template +constexpr parse_specs_result parse_specs(basic_string_view str, + size_t pos, int next_arg_id) { + str.remove_prefix(pos); + auto ctx = + compile_parse_context(str, max_value(), nullptr, next_arg_id); + auto f = formatter(); + auto end = f.parse(ctx); + return {f, pos + fmt::detail::to_unsigned(end - str.data()), + next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()}; +} + +template struct arg_id_handler { + arg_ref arg_id; + + constexpr int on_auto() { + FMT_ASSERT(false, "handler cannot be used with automatic indexing"); + return 0; + } + constexpr int on_index(int id) { + arg_id = arg_ref(id); + return 0; + } + constexpr int on_name(basic_string_view id) { + arg_id = arg_ref(id); + return 0; + } +}; + +template struct parse_arg_id_result { + arg_ref arg_id; + const Char* arg_id_end; +}; + +template +constexpr auto parse_arg_id(const Char* begin, const Char* end) { + auto handler = arg_id_handler{arg_ref{}}; + auto arg_id_end = parse_arg_id(begin, end, handler); + return parse_arg_id_result{handler.arg_id, arg_id_end}; +} + +template struct field_type { + using type = remove_cvref_t; +}; + +template +struct field_type::value>> { + using type = remove_cvref_t; +}; + +template +constexpr auto parse_replacement_field_then_tail(S fmt) { + using char_type = typename S::char_type; + constexpr auto str = basic_string_view(fmt); + constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type(); + if constexpr (c == '}') { + return parse_tail( + field::type, ARG_INDEX>(), fmt); + } else if constexpr (c != ':') { + FMT_THROW(format_error("expected ':'")); + } else { + constexpr auto result = parse_specs::type>( + str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID); + if constexpr (result.end >= str.size() || str[result.end] != '}') { + FMT_THROW(format_error("expected '}'")); + return 0; + } else { + return parse_tail( + spec_field::type, ARG_INDEX>{ + result.fmt}, + fmt); + } + } +} + +// Compiles a non-empty format string and returns the compiled representation +// or unknown_format() on unrecognized input. +template +constexpr auto compile_format_string(S fmt) { + using char_type = typename S::char_type; + constexpr auto str = basic_string_view(fmt); + if constexpr (str[POS] == '{') { + if constexpr (POS + 1 == str.size()) + FMT_THROW(format_error("unmatched '{' in format string")); + if constexpr (str[POS + 1] == '{') { + return parse_tail(make_text(str, POS, 1), fmt); + } else if constexpr (str[POS + 1] == '}' || str[POS + 1] == ':') { + static_assert(ID != manual_indexing_id, + "cannot switch from manual to automatic argument indexing"); + constexpr auto next_id = + ID != manual_indexing_id ? ID + 1 : manual_indexing_id; + return parse_replacement_field_then_tail, Args, + POS + 1, ID, next_id>(fmt); + } else { + constexpr auto arg_id_result = + parse_arg_id(str.data() + POS + 1, str.data() + str.size()); + constexpr auto arg_id_end_pos = arg_id_result.arg_id_end - str.data(); + constexpr char_type c = + arg_id_end_pos != str.size() ? str[arg_id_end_pos] : char_type(); + static_assert(c == '}' || c == ':', "missing '}' in format string"); + if constexpr (arg_id_result.arg_id.kind == arg_id_kind::index) { + static_assert( + ID == manual_indexing_id || ID == 0, + "cannot switch from automatic to manual argument indexing"); + constexpr auto arg_index = arg_id_result.arg_id.val.index; + return parse_replacement_field_then_tail, + Args, arg_id_end_pos, + arg_index, manual_indexing_id>( + fmt); + } else if constexpr (arg_id_result.arg_id.kind == arg_id_kind::name) { + constexpr auto arg_index = + get_arg_index_by_name(arg_id_result.arg_id.val.name, Args{}); + if constexpr (arg_index >= 0) { + constexpr auto next_id = + ID != manual_indexing_id ? ID + 1 : manual_indexing_id; + return parse_replacement_field_then_tail< + decltype(get_type::value), Args, arg_id_end_pos, + arg_index, next_id>(fmt); + } else if constexpr (c == '}') { + return parse_tail( + runtime_named_field{arg_id_result.arg_id.val.name}, + fmt); + } else if constexpr (c == ':') { + return unknown_format(); // no type info for specs parsing + } + } + } + } else if constexpr (str[POS] == '}') { + if constexpr (POS + 1 == str.size()) + FMT_THROW(format_error("unmatched '}' in format string")); + return parse_tail(make_text(str, POS, 1), fmt); + } else { + constexpr auto end = parse_text(str, POS + 1); + if constexpr (end - POS > 1) { + return parse_tail(make_text(str, POS, end - POS), fmt); + } else { + return parse_tail(code_unit{str[POS]}, fmt); + } + } +} + +template ::value)> +constexpr auto compile(S fmt) { + constexpr auto str = basic_string_view(fmt); + if constexpr (str.size() == 0) { + return detail::make_text(str, 0, 0); + } else { + constexpr auto result = + detail::compile_format_string, 0, 0>(fmt); + return result; + } +} +#endif // defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) +} // namespace detail + +FMT_BEGIN_EXPORT + +#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) + +template ::value)> +FMT_INLINE std::basic_string format(const CompiledFormat& cf, + const Args&... args) { + auto s = std::basic_string(); + cf.format(std::back_inserter(s), args...); + return s; +} + +template ::value)> +constexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf, + const Args&... args) { + return cf.format(out, args...); +} + +template ::value)> +FMT_INLINE std::basic_string format(const S&, + Args&&... args) { + if constexpr (std::is_same::value) { + constexpr auto str = basic_string_view(S()); + if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') { + const auto& first = detail::first(args...); + if constexpr (detail::is_named_arg< + remove_cvref_t>::value) { + return fmt::to_string(first.value); + } else { + return fmt::to_string(first); + } + } + } + constexpr auto compiled = detail::compile(S()); + if constexpr (std::is_same, + detail::unknown_format>()) { + return fmt::format( + static_cast>(S()), + std::forward(args)...); + } else { + return fmt::format(compiled, std::forward(args)...); + } +} + +template ::value)> +FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) { + constexpr auto compiled = detail::compile(S()); + if constexpr (std::is_same, + detail::unknown_format>()) { + return fmt::format_to( + out, static_cast>(S()), + std::forward(args)...); + } else { + return fmt::format_to(out, compiled, std::forward(args)...); + } +} +#endif + +template ::value)> +auto format_to_n(OutputIt out, size_t n, const S& fmt, Args&&... args) + -> format_to_n_result { + using traits = detail::fixed_buffer_traits; + auto buf = detail::iterator_buffer(out, n); + fmt::format_to(std::back_inserter(buf), fmt, std::forward(args)...); + return {buf.out(), buf.count()}; +} + +template ::value)> +FMT_CONSTEXPR20 auto formatted_size(const S& fmt, const Args&... args) + -> size_t { + return fmt::format_to(detail::counting_iterator(), fmt, args...).count(); +} + +template ::value)> +void print(std::FILE* f, const S& fmt, const Args&... args) { + memory_buffer buffer; + fmt::format_to(std::back_inserter(buffer), fmt, args...); + detail::print(f, {buffer.data(), buffer.size()}); +} + +template ::value)> +void print(const S& fmt, const Args&... args) { + print(stdout, fmt, args...); +} + +#if FMT_USE_NONTYPE_TEMPLATE_ARGS +inline namespace literals { +template constexpr auto operator""_cf() { + using char_t = remove_cvref_t; + return detail::udl_compiled_string(); +} +} // namespace literals +#endif + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_COMPILE_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/core.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/core.h new file mode 100644 index 0000000..8ca735f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/core.h @@ -0,0 +1,5 @@ +// This file is only provided for compatibility and may be removed in future +// versions. Use fmt/base.h if you don't need fmt::format and fmt/format.h +// otherwise. + +#include "format.h" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/format-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/format-inl.h new file mode 100644 index 0000000..a887483 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/format-inl.h @@ -0,0 +1,1928 @@ +// Formatting library for C++ - implementation +// +// Copyright (c) 2012 - 2016, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_FORMAT_INL_H_ +#define FMT_FORMAT_INL_H_ + +#ifndef FMT_MODULE +# include +# include // errno +# include +# include +# include + +# if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) +# include +# endif +#endif + +#if defined(_WIN32) && !defined(FMT_USE_WRITE_CONSOLE) +# include // _isatty +#endif + +#include "format.h" + +FMT_BEGIN_NAMESPACE +namespace detail { + +FMT_FUNC void assert_fail(const char* file, int line, const char* message) { + // Use unchecked std::fprintf to avoid triggering another assertion when + // writing to stderr fails + std::fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message); + // Chosen instead of std::abort to satisfy Clang in CUDA mode during device + // code pass. + std::terminate(); +} + +FMT_FUNC void format_error_code(detail::buffer& out, int error_code, + string_view message) noexcept { + // Report error code making sure that the output fits into + // inline_buffer_size to avoid dynamic memory allocation and potential + // bad_alloc. + out.try_resize(0); + static const char SEP[] = ": "; + static const char ERROR_STR[] = "error "; + // Subtract 2 to account for terminating null characters in SEP and ERROR_STR. + size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2; + auto abs_value = static_cast>(error_code); + if (detail::is_negative(error_code)) { + abs_value = 0 - abs_value; + ++error_code_size; + } + error_code_size += detail::to_unsigned(detail::count_digits(abs_value)); + auto it = appender(out); + if (message.size() <= inline_buffer_size - error_code_size) + fmt::format_to(it, FMT_STRING("{}{}"), message, SEP); + fmt::format_to(it, FMT_STRING("{}{}"), ERROR_STR, error_code); + FMT_ASSERT(out.size() <= inline_buffer_size, ""); +} + +FMT_FUNC void report_error(format_func func, int error_code, + const char* message) noexcept { + memory_buffer full_message; + func(full_message, error_code, message); + // Don't use fwrite_fully because the latter may throw. + if (std::fwrite(full_message.data(), full_message.size(), 1, stderr) > 0) + std::fputc('\n', stderr); +} + +// A wrapper around fwrite that throws on error. +inline void fwrite_fully(const void* ptr, size_t count, FILE* stream) { + size_t written = std::fwrite(ptr, 1, count, stream); + if (written < count) + FMT_THROW(system_error(errno, FMT_STRING("cannot write to file"))); +} + +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR +template +locale_ref::locale_ref(const Locale& loc) : locale_(&loc) { + static_assert(std::is_same::value, ""); +} + +template auto locale_ref::get() const -> Locale { + static_assert(std::is_same::value, ""); + return locale_ ? *static_cast(locale_) : std::locale(); +} + +template +FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result { + auto& facet = std::use_facet>(loc.get()); + auto grouping = facet.grouping(); + auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep(); + return {std::move(grouping), thousands_sep}; +} +template +FMT_FUNC auto decimal_point_impl(locale_ref loc) -> Char { + return std::use_facet>(loc.get()) + .decimal_point(); +} +#else +template +FMT_FUNC auto thousands_sep_impl(locale_ref) -> thousands_sep_result { + return {"\03", FMT_STATIC_THOUSANDS_SEPARATOR}; +} +template FMT_FUNC Char decimal_point_impl(locale_ref) { + return '.'; +} +#endif + +FMT_FUNC auto write_loc(appender out, loc_value value, + const format_specs& specs, locale_ref loc) -> bool { +#ifdef FMT_STATIC_THOUSANDS_SEPARATOR + value.visit(loc_writer<>{ + out, specs, std::string(1, FMT_STATIC_THOUSANDS_SEPARATOR), "\3", "."}); + return true; +#else + auto locale = loc.get(); + // We cannot use the num_put facet because it may produce output in + // a wrong encoding. + using facet = format_facet; + if (std::has_facet(locale)) + return std::use_facet(locale).put(out, value, specs); + return facet(locale).put(out, value, specs); +#endif +} +} // namespace detail + +FMT_FUNC void report_error(const char* message) { + FMT_THROW(format_error(message)); +} + +template typename Locale::id format_facet::id; + +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR +template format_facet::format_facet(Locale& loc) { + auto& numpunct = std::use_facet>(loc); + grouping_ = numpunct.grouping(); + if (!grouping_.empty()) separator_ = std::string(1, numpunct.thousands_sep()); +} + +template <> +FMT_API FMT_FUNC auto format_facet::do_put( + appender out, loc_value val, const format_specs& specs) const -> bool { + return val.visit( + detail::loc_writer<>{out, specs, separator_, grouping_, decimal_point_}); +} +#endif + +FMT_FUNC auto vsystem_error(int error_code, string_view fmt, format_args args) + -> std::system_error { + auto ec = std::error_code(error_code, std::generic_category()); + return std::system_error(ec, vformat(fmt, args)); +} + +namespace detail { + +template +inline auto operator==(basic_fp x, basic_fp y) -> bool { + return x.f == y.f && x.e == y.e; +} + +// Compilers should be able to optimize this into the ror instruction. +FMT_CONSTEXPR inline auto rotr(uint32_t n, uint32_t r) noexcept -> uint32_t { + r &= 31; + return (n >> r) | (n << (32 - r)); +} +FMT_CONSTEXPR inline auto rotr(uint64_t n, uint32_t r) noexcept -> uint64_t { + r &= 63; + return (n >> r) | (n << (64 - r)); +} + +// Implementation of Dragonbox algorithm: https://github.com/jk-jeon/dragonbox. +namespace dragonbox { +// Computes upper 64 bits of multiplication of a 32-bit unsigned integer and a +// 64-bit unsigned integer. +inline auto umul96_upper64(uint32_t x, uint64_t y) noexcept -> uint64_t { + return umul128_upper64(static_cast(x) << 32, y); +} + +// Computes lower 128 bits of multiplication of a 64-bit unsigned integer and a +// 128-bit unsigned integer. +inline auto umul192_lower128(uint64_t x, uint128_fallback y) noexcept + -> uint128_fallback { + uint64_t high = x * y.high(); + uint128_fallback high_low = umul128(x, y.low()); + return {high + high_low.high(), high_low.low()}; +} + +// Computes lower 64 bits of multiplication of a 32-bit unsigned integer and a +// 64-bit unsigned integer. +inline auto umul96_lower64(uint32_t x, uint64_t y) noexcept -> uint64_t { + return x * y; +} + +// Various fast log computations. +inline auto floor_log10_pow2_minus_log10_4_over_3(int e) noexcept -> int { + FMT_ASSERT(e <= 2936 && e >= -2985, "too large exponent"); + return (e * 631305 - 261663) >> 21; +} + +FMT_INLINE_VARIABLE constexpr struct { + uint32_t divisor; + int shift_amount; +} div_small_pow10_infos[] = {{10, 16}, {100, 16}}; + +// Replaces n by floor(n / pow(10, N)) returning true if and only if n is +// divisible by pow(10, N). +// Precondition: n <= pow(10, N + 1). +template +auto check_divisibility_and_divide_by_pow10(uint32_t& n) noexcept -> bool { + // The numbers below are chosen such that: + // 1. floor(n/d) = floor(nm / 2^k) where d=10 or d=100, + // 2. nm mod 2^k < m if and only if n is divisible by d, + // where m is magic_number, k is shift_amount + // and d is divisor. + // + // Item 1 is a common technique of replacing division by a constant with + // multiplication, see e.g. "Division by Invariant Integers Using + // Multiplication" by Granlund and Montgomery (1994). magic_number (m) is set + // to ceil(2^k/d) for large enough k. + // The idea for item 2 originates from Schubfach. + constexpr auto info = div_small_pow10_infos[N - 1]; + FMT_ASSERT(n <= info.divisor * 10, "n is too large"); + constexpr uint32_t magic_number = + (1u << info.shift_amount) / info.divisor + 1; + n *= magic_number; + const uint32_t comparison_mask = (1u << info.shift_amount) - 1; + bool result = (n & comparison_mask) < magic_number; + n >>= info.shift_amount; + return result; +} + +// Computes floor(n / pow(10, N)) for small n and N. +// Precondition: n <= pow(10, N + 1). +template auto small_division_by_pow10(uint32_t n) noexcept -> uint32_t { + constexpr auto info = div_small_pow10_infos[N - 1]; + FMT_ASSERT(n <= info.divisor * 10, "n is too large"); + constexpr uint32_t magic_number = + (1u << info.shift_amount) / info.divisor + 1; + return (n * magic_number) >> info.shift_amount; +} + +// Computes floor(n / 10^(kappa + 1)) (float) +inline auto divide_by_10_to_kappa_plus_1(uint32_t n) noexcept -> uint32_t { + // 1374389535 = ceil(2^37/100) + return static_cast((static_cast(n) * 1374389535) >> 37); +} +// Computes floor(n / 10^(kappa + 1)) (double) +inline auto divide_by_10_to_kappa_plus_1(uint64_t n) noexcept -> uint64_t { + // 2361183241434822607 = ceil(2^(64+7)/1000) + return umul128_upper64(n, 2361183241434822607ull) >> 7; +} + +// Various subroutines using pow10 cache +template struct cache_accessor; + +template <> struct cache_accessor { + using carrier_uint = float_info::carrier_uint; + using cache_entry_type = uint64_t; + + static auto get_cached_power(int k) noexcept -> uint64_t { + FMT_ASSERT(k >= float_info::min_k && k <= float_info::max_k, + "k is out of range"); + static constexpr const uint64_t pow10_significands[] = { + 0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f, + 0xfd87b5f28300ca0e, 0x9e74d1b791e07e49, 0xc612062576589ddb, + 0xf79687aed3eec552, 0x9abe14cd44753b53, 0xc16d9a0095928a28, + 0xf1c90080baf72cb2, 0x971da05074da7bef, 0xbce5086492111aeb, + 0xec1e4a7db69561a6, 0x9392ee8e921d5d08, 0xb877aa3236a4b44a, + 0xe69594bec44de15c, 0x901d7cf73ab0acda, 0xb424dc35095cd810, + 0xe12e13424bb40e14, 0x8cbccc096f5088cc, 0xafebff0bcb24aaff, + 0xdbe6fecebdedd5bf, 0x89705f4136b4a598, 0xabcc77118461cefd, + 0xd6bf94d5e57a42bd, 0x8637bd05af6c69b6, 0xa7c5ac471b478424, + 0xd1b71758e219652c, 0x83126e978d4fdf3c, 0xa3d70a3d70a3d70b, + 0xcccccccccccccccd, 0x8000000000000000, 0xa000000000000000, + 0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000, + 0xc350000000000000, 0xf424000000000000, 0x9896800000000000, + 0xbebc200000000000, 0xee6b280000000000, 0x9502f90000000000, + 0xba43b74000000000, 0xe8d4a51000000000, 0x9184e72a00000000, + 0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000, + 0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000, + 0xad78ebc5ac620000, 0xd8d726b7177a8000, 0x878678326eac9000, + 0xa968163f0a57b400, 0xd3c21bcecceda100, 0x84595161401484a0, + 0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940985, + 0xa18f07d736b90be6, 0xc9f2c9cd04674edf, 0xfc6f7c4045812297, + 0x9dc5ada82b70b59e, 0xc5371912364ce306, 0xf684df56c3e01bc7, + 0x9a130b963a6c115d, 0xc097ce7bc90715b4, 0xf0bdc21abb48db21, + 0x96769950b50d88f5, 0xbc143fa4e250eb32, 0xeb194f8e1ae525fe, + 0x92efd1b8d0cf37bf, 0xb7abc627050305ae, 0xe596b7b0c643c71a, + 0x8f7e32ce7bea5c70, 0xb35dbf821ae4f38c, 0xe0352f62a19e306f}; + return pow10_significands[k - float_info::min_k]; + } + + struct compute_mul_result { + carrier_uint result; + bool is_integer; + }; + struct compute_mul_parity_result { + bool parity; + bool is_integer; + }; + + static auto compute_mul(carrier_uint u, + const cache_entry_type& cache) noexcept + -> compute_mul_result { + auto r = umul96_upper64(u, cache); + return {static_cast(r >> 32), + static_cast(r) == 0}; + } + + static auto compute_delta(const cache_entry_type& cache, int beta) noexcept + -> uint32_t { + return static_cast(cache >> (64 - 1 - beta)); + } + + static auto compute_mul_parity(carrier_uint two_f, + const cache_entry_type& cache, + int beta) noexcept + -> compute_mul_parity_result { + FMT_ASSERT(beta >= 1, ""); + FMT_ASSERT(beta < 64, ""); + + auto r = umul96_lower64(two_f, cache); + return {((r >> (64 - beta)) & 1) != 0, + static_cast(r >> (32 - beta)) == 0}; + } + + static auto compute_left_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept -> carrier_uint { + return static_cast( + (cache - (cache >> (num_significand_bits() + 2))) >> + (64 - num_significand_bits() - 1 - beta)); + } + + static auto compute_right_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept -> carrier_uint { + return static_cast( + (cache + (cache >> (num_significand_bits() + 1))) >> + (64 - num_significand_bits() - 1 - beta)); + } + + static auto compute_round_up_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept -> carrier_uint { + return (static_cast( + cache >> (64 - num_significand_bits() - 2 - beta)) + + 1) / + 2; + } +}; + +template <> struct cache_accessor { + using carrier_uint = float_info::carrier_uint; + using cache_entry_type = uint128_fallback; + + static auto get_cached_power(int k) noexcept -> uint128_fallback { + FMT_ASSERT(k >= float_info::min_k && k <= float_info::max_k, + "k is out of range"); + + static constexpr const uint128_fallback pow10_significands[] = { +#if FMT_USE_FULL_CACHE_DRAGONBOX + {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, + {0x9faacf3df73609b1, 0x77b191618c54e9ad}, + {0xc795830d75038c1d, 0xd59df5b9ef6a2418}, + {0xf97ae3d0d2446f25, 0x4b0573286b44ad1e}, + {0x9becce62836ac577, 0x4ee367f9430aec33}, + {0xc2e801fb244576d5, 0x229c41f793cda740}, + {0xf3a20279ed56d48a, 0x6b43527578c11110}, + {0x9845418c345644d6, 0x830a13896b78aaaa}, + {0xbe5691ef416bd60c, 0x23cc986bc656d554}, + {0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9}, + {0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa}, + {0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54}, + {0xe858ad248f5c22c9, 0xd1b3400f8f9cff69}, + {0x91376c36d99995be, 0x23100809b9c21fa2}, + {0xb58547448ffffb2d, 0xabd40a0c2832a78b}, + {0xe2e69915b3fff9f9, 0x16c90c8f323f516d}, + {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4}, + {0xb1442798f49ffb4a, 0x99cd11cfdf41779d}, + {0xdd95317f31c7fa1d, 0x40405643d711d584}, + {0x8a7d3eef7f1cfc52, 0x482835ea666b2573}, + {0xad1c8eab5ee43b66, 0xda3243650005eed0}, + {0xd863b256369d4a40, 0x90bed43e40076a83}, + {0x873e4f75e2224e68, 0x5a7744a6e804a292}, + {0xa90de3535aaae202, 0x711515d0a205cb37}, + {0xd3515c2831559a83, 0x0d5a5b44ca873e04}, + {0x8412d9991ed58091, 0xe858790afe9486c3}, + {0xa5178fff668ae0b6, 0x626e974dbe39a873}, + {0xce5d73ff402d98e3, 0xfb0a3d212dc81290}, + {0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a}, + {0xa139029f6a239f72, 0x1c1fffc1ebc44e81}, + {0xc987434744ac874e, 0xa327ffb266b56221}, + {0xfbe9141915d7a922, 0x4bf1ff9f0062baa9}, + {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa}, + {0xc4ce17b399107c22, 0xcb550fb4384d21d4}, + {0xf6019da07f549b2b, 0x7e2a53a146606a49}, + {0x99c102844f94e0fb, 0x2eda7444cbfc426e}, + {0xc0314325637a1939, 0xfa911155fefb5309}, + {0xf03d93eebc589f88, 0x793555ab7eba27cb}, + {0x96267c7535b763b5, 0x4bc1558b2f3458df}, + {0xbbb01b9283253ca2, 0x9eb1aaedfb016f17}, + {0xea9c227723ee8bcb, 0x465e15a979c1cadd}, + {0x92a1958a7675175f, 0x0bfacd89ec191eca}, + {0xb749faed14125d36, 0xcef980ec671f667c}, + {0xe51c79a85916f484, 0x82b7e12780e7401b}, + {0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811}, + {0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16}, + {0xdfbdcece67006ac9, 0x67a791e093e1d49b}, + {0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1}, + {0xaecc49914078536d, 0x58fae9f773886e19}, + {0xda7f5bf590966848, 0xaf39a475506a899f}, + {0x888f99797a5e012d, 0x6d8406c952429604}, + {0xaab37fd7d8f58178, 0xc8e5087ba6d33b84}, + {0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65}, + {0x855c3be0a17fcd26, 0x5cf2eea09a550680}, + {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, + {0xd0601d8efc57b08b, 0xf13b94daf124da27}, + {0x823c12795db6ce57, 0x76c53d08d6b70859}, + {0xa2cb1717b52481ed, 0x54768c4b0c64ca6f}, + {0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a}, + {0xfe5d54150b090b02, 0xd3f93b35435d7c4d}, + {0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0}, + {0xc6b8e9b0709f109a, 0x359ab6419ca1091c}, + {0xf867241c8cc6d4c0, 0xc30163d203c94b63}, + {0x9b407691d7fc44f8, 0x79e0de63425dcf1e}, + {0xc21094364dfb5636, 0x985915fc12f542e5}, + {0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e}, + {0x979cf3ca6cec5b5a, 0xa705992ceecf9c43}, + {0xbd8430bd08277231, 0x50c6ff782a838354}, + {0xece53cec4a314ebd, 0xa4f8bf5635246429}, + {0x940f4613ae5ed136, 0x871b7795e136be9a}, + {0xb913179899f68584, 0x28e2557b59846e40}, + {0xe757dd7ec07426e5, 0x331aeada2fe589d0}, + {0x9096ea6f3848984f, 0x3ff0d2c85def7622}, + {0xb4bca50b065abe63, 0x0fed077a756b53aa}, + {0xe1ebce4dc7f16dfb, 0xd3e8495912c62895}, + {0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d}, + {0xb080392cc4349dec, 0xbd8d794d96aacfb4}, + {0xdca04777f541c567, 0xecf0d7a0fc5583a1}, + {0x89e42caaf9491b60, 0xf41686c49db57245}, + {0xac5d37d5b79b6239, 0x311c2875c522ced6}, + {0xd77485cb25823ac7, 0x7d633293366b828c}, + {0x86a8d39ef77164bc, 0xae5dff9c02033198}, + {0xa8530886b54dbdeb, 0xd9f57f830283fdfd}, + {0xd267caa862a12d66, 0xd072df63c324fd7c}, + {0x8380dea93da4bc60, 0x4247cb9e59f71e6e}, + {0xa46116538d0deb78, 0x52d9be85f074e609}, + {0xcd795be870516656, 0x67902e276c921f8c}, + {0x806bd9714632dff6, 0x00ba1cd8a3db53b7}, + {0xa086cfcd97bf97f3, 0x80e8a40eccd228a5}, + {0xc8a883c0fdaf7df0, 0x6122cd128006b2ce}, + {0xfad2a4b13d1b5d6c, 0x796b805720085f82}, + {0x9cc3a6eec6311a63, 0xcbe3303674053bb1}, + {0xc3f490aa77bd60fc, 0xbedbfc4411068a9d}, + {0xf4f1b4d515acb93b, 0xee92fb5515482d45}, + {0x991711052d8bf3c5, 0x751bdd152d4d1c4b}, + {0xbf5cd54678eef0b6, 0xd262d45a78a0635e}, + {0xef340a98172aace4, 0x86fb897116c87c35}, + {0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1}, + {0xbae0a846d2195712, 0x8974836059cca10a}, + {0xe998d258869facd7, 0x2bd1a438703fc94c}, + {0x91ff83775423cc06, 0x7b6306a34627ddd0}, + {0xb67f6455292cbf08, 0x1a3bc84c17b1d543}, + {0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94}, + {0x8e938662882af53e, 0x547eb47b7282ee9d}, + {0xb23867fb2a35b28d, 0xe99e619a4f23aa44}, + {0xdec681f9f4c31f31, 0x6405fa00e2ec94d5}, + {0x8b3c113c38f9f37e, 0xde83bc408dd3dd05}, + {0xae0b158b4738705e, 0x9624ab50b148d446}, + {0xd98ddaee19068c76, 0x3badd624dd9b0958}, + {0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7}, + {0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d}, + {0xd47487cc8470652b, 0x7647c32000696720}, + {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074}, + {0xa5fb0a17c777cf09, 0xf468107100525891}, + {0xcf79cc9db955c2cc, 0x7182148d4066eeb5}, + {0x81ac1fe293d599bf, 0xc6f14cd848405531}, + {0xa21727db38cb002f, 0xb8ada00e5a506a7d}, + {0xca9cf1d206fdc03b, 0xa6d90811f0e4851d}, + {0xfd442e4688bd304a, 0x908f4a166d1da664}, + {0x9e4a9cec15763e2e, 0x9a598e4e043287ff}, + {0xc5dd44271ad3cdba, 0x40eff1e1853f29fe}, + {0xf7549530e188c128, 0xd12bee59e68ef47d}, + {0x9a94dd3e8cf578b9, 0x82bb74f8301958cf}, + {0xc13a148e3032d6e7, 0xe36a52363c1faf02}, + {0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2}, + {0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba}, + {0xbcb2b812db11a5de, 0x7415d448f6b6f0e8}, + {0xebdf661791d60f56, 0x111b495b3464ad22}, + {0x936b9fcebb25c995, 0xcab10dd900beec35}, + {0xb84687c269ef3bfb, 0x3d5d514f40eea743}, + {0xe65829b3046b0afa, 0x0cb4a5a3112a5113}, + {0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac}, + {0xb3f4e093db73a093, 0x59ed216765690f57}, + {0xe0f218b8d25088b8, 0x306869c13ec3532d}, + {0x8c974f7383725573, 0x1e414218c73a13fc}, + {0xafbd2350644eeacf, 0xe5d1929ef90898fb}, + {0xdbac6c247d62a583, 0xdf45f746b74abf3a}, + {0x894bc396ce5da772, 0x6b8bba8c328eb784}, + {0xab9eb47c81f5114f, 0x066ea92f3f326565}, + {0xd686619ba27255a2, 0xc80a537b0efefebe}, + {0x8613fd0145877585, 0xbd06742ce95f5f37}, + {0xa798fc4196e952e7, 0x2c48113823b73705}, + {0xd17f3b51fca3a7a0, 0xf75a15862ca504c6}, + {0x82ef85133de648c4, 0x9a984d73dbe722fc}, + {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb}, + {0xcc963fee10b7d1b3, 0x318df905079926a9}, + {0xffbbcfe994e5c61f, 0xfdf17746497f7053}, + {0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634}, + {0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1}, + {0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1}, + {0x9c1661a651213e2d, 0x06bea10ca65c084f}, + {0xc31bfa0fe5698db8, 0x486e494fcff30a63}, + {0xf3e2f893dec3f126, 0x5a89dba3c3efccfb}, + {0x986ddb5c6b3a76b7, 0xf89629465a75e01d}, + {0xbe89523386091465, 0xf6bbb397f1135824}, + {0xee2ba6c0678b597f, 0x746aa07ded582e2d}, + {0x94db483840b717ef, 0xa8c2a44eb4571cdd}, + {0xba121a4650e4ddeb, 0x92f34d62616ce414}, + {0xe896a0d7e51e1566, 0x77b020baf9c81d18}, + {0x915e2486ef32cd60, 0x0ace1474dc1d122f}, + {0xb5b5ada8aaff80b8, 0x0d819992132456bb}, + {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a}, + {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, + {0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3}, + {0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf}, + {0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c}, + {0xad4ab7112eb3929d, 0x86c16c98d2c953c7}, + {0xd89d64d57a607744, 0xe871c7bf077ba8b8}, + {0x87625f056c7c4a8b, 0x11471cd764ad4973}, + {0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0}, + {0xd389b47879823479, 0x4aff1d108d4ec2c4}, + {0x843610cb4bf160cb, 0xcedf722a585139bb}, + {0xa54394fe1eedb8fe, 0xc2974eb4ee658829}, + {0xce947a3da6a9273e, 0x733d226229feea33}, + {0x811ccc668829b887, 0x0806357d5a3f5260}, + {0xa163ff802a3426a8, 0xca07c2dcb0cf26f8}, + {0xc9bcff6034c13052, 0xfc89b393dd02f0b6}, + {0xfc2c3f3841f17c67, 0xbbac2078d443ace3}, + {0x9d9ba7832936edc0, 0xd54b944b84aa4c0e}, + {0xc5029163f384a931, 0x0a9e795e65d4df12}, + {0xf64335bcf065d37d, 0x4d4617b5ff4a16d6}, + {0x99ea0196163fa42e, 0x504bced1bf8e4e46}, + {0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7}, + {0xf07da27a82c37088, 0x5d767327bb4e5a4d}, + {0x964e858c91ba2655, 0x3a6a07f8d510f870}, + {0xbbe226efb628afea, 0x890489f70a55368c}, + {0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f}, + {0x92c8ae6b464fc96f, 0x3b0b8bc90012929e}, + {0xb77ada0617e3bbcb, 0x09ce6ebb40173745}, + {0xe55990879ddcaabd, 0xcc420a6a101d0516}, + {0x8f57fa54c2a9eab6, 0x9fa946824a12232e}, + {0xb32df8e9f3546564, 0x47939822dc96abfa}, + {0xdff9772470297ebd, 0x59787e2b93bc56f8}, + {0x8bfbea76c619ef36, 0x57eb4edb3c55b65b}, + {0xaefae51477a06b03, 0xede622920b6b23f2}, + {0xdab99e59958885c4, 0xe95fab368e45ecee}, + {0x88b402f7fd75539b, 0x11dbcb0218ebb415}, + {0xaae103b5fcd2a881, 0xd652bdc29f26a11a}, + {0xd59944a37c0752a2, 0x4be76d3346f04960}, + {0x857fcae62d8493a5, 0x6f70a4400c562ddc}, + {0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953}, + {0xd097ad07a71f26b2, 0x7e2000a41346a7a8}, + {0x825ecc24c873782f, 0x8ed400668c0c28c9}, + {0xa2f67f2dfa90563b, 0x728900802f0f32fb}, + {0xcbb41ef979346bca, 0x4f2b40a03ad2ffba}, + {0xfea126b7d78186bc, 0xe2f610c84987bfa9}, + {0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca}, + {0xc6ede63fa05d3143, 0x91503d1c79720dbc}, + {0xf8a95fcf88747d94, 0x75a44c6397ce912b}, + {0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb}, + {0xc24452da229b021b, 0xfbe85badce996169}, + {0xf2d56790ab41c2a2, 0xfae27299423fb9c4}, + {0x97c560ba6b0919a5, 0xdccd879fc967d41b}, + {0xbdb6b8e905cb600f, 0x5400e987bbc1c921}, + {0xed246723473e3813, 0x290123e9aab23b69}, + {0x9436c0760c86e30b, 0xf9a0b6720aaf6522}, + {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, + {0xe7958cb87392c2c2, 0xb60b1d1230b20e05}, + {0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3}, + {0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4}, + {0xe2280b6c20dd5232, 0x25c6da63c38de1b1}, + {0x8d590723948a535f, 0x579c487e5a38ad0f}, + {0xb0af48ec79ace837, 0x2d835a9df0c6d852}, + {0xdcdb1b2798182244, 0xf8e431456cf88e66}, + {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900}, + {0xac8b2d36eed2dac5, 0xe272467e3d222f40}, + {0xd7adf884aa879177, 0x5b0ed81dcc6abb10}, + {0x86ccbb52ea94baea, 0x98e947129fc2b4ea}, + {0xa87fea27a539e9a5, 0x3f2398d747b36225}, + {0xd29fe4b18e88640e, 0x8eec7f0d19a03aae}, + {0x83a3eeeef9153e89, 0x1953cf68300424ad}, + {0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8}, + {0xcdb02555653131b6, 0x3792f412cb06794e}, + {0x808e17555f3ebf11, 0xe2bbd88bbee40bd1}, + {0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5}, + {0xc8de047564d20a8b, 0xf245825a5a445276}, + {0xfb158592be068d2e, 0xeed6e2f0f0d56713}, + {0x9ced737bb6c4183d, 0x55464dd69685606c}, + {0xc428d05aa4751e4c, 0xaa97e14c3c26b887}, + {0xf53304714d9265df, 0xd53dd99f4b3066a9}, + {0x993fe2c6d07b7fab, 0xe546a8038efe402a}, + {0xbf8fdb78849a5f96, 0xde98520472bdd034}, + {0xef73d256a5c0f77c, 0x963e66858f6d4441}, + {0x95a8637627989aad, 0xdde7001379a44aa9}, + {0xbb127c53b17ec159, 0x5560c018580d5d53}, + {0xe9d71b689dde71af, 0xaab8f01e6e10b4a7}, + {0x9226712162ab070d, 0xcab3961304ca70e9}, + {0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23}, + {0xe45c10c42a2b3b05, 0x8cb89a7db77c506b}, + {0x8eb98a7a9a5b04e3, 0x77f3608e92adb243}, + {0xb267ed1940f1c61c, 0x55f038b237591ed4}, + {0xdf01e85f912e37a3, 0x6b6c46dec52f6689}, + {0x8b61313bbabce2c6, 0x2323ac4b3b3da016}, + {0xae397d8aa96c1b77, 0xabec975e0a0d081b}, + {0xd9c7dced53c72255, 0x96e7bd358c904a22}, + {0x881cea14545c7575, 0x7e50d64177da2e55}, + {0xaa242499697392d2, 0xdde50bd1d5d0b9ea}, + {0xd4ad2dbfc3d07787, 0x955e4ec64b44e865}, + {0x84ec3c97da624ab4, 0xbd5af13bef0b113f}, + {0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f}, + {0xcfb11ead453994ba, 0x67de18eda5814af3}, + {0x81ceb32c4b43fcf4, 0x80eacf948770ced8}, + {0xa2425ff75e14fc31, 0xa1258379a94d028e}, + {0xcad2f7f5359a3b3e, 0x096ee45813a04331}, + {0xfd87b5f28300ca0d, 0x8bca9d6e188853fd}, + {0x9e74d1b791e07e48, 0x775ea264cf55347e}, + {0xc612062576589dda, 0x95364afe032a819e}, + {0xf79687aed3eec551, 0x3a83ddbd83f52205}, + {0x9abe14cd44753b52, 0xc4926a9672793543}, + {0xc16d9a0095928a27, 0x75b7053c0f178294}, + {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, + {0x971da05074da7bee, 0xd3f6fc16ebca5e04}, + {0xbce5086492111aea, 0x88f4bb1ca6bcf585}, + {0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6}, + {0x9392ee8e921d5d07, 0x3aff322e62439fd0}, + {0xb877aa3236a4b449, 0x09befeb9fad487c3}, + {0xe69594bec44de15b, 0x4c2ebe687989a9b4}, + {0x901d7cf73ab0acd9, 0x0f9d37014bf60a11}, + {0xb424dc35095cd80f, 0x538484c19ef38c95}, + {0xe12e13424bb40e13, 0x2865a5f206b06fba}, + {0x8cbccc096f5088cb, 0xf93f87b7442e45d4}, + {0xafebff0bcb24aafe, 0xf78f69a51539d749}, + {0xdbe6fecebdedd5be, 0xb573440e5a884d1c}, + {0x89705f4136b4a597, 0x31680a88f8953031}, + {0xabcc77118461cefc, 0xfdc20d2b36ba7c3e}, + {0xd6bf94d5e57a42bc, 0x3d32907604691b4d}, + {0x8637bd05af6c69b5, 0xa63f9a49c2c1b110}, + {0xa7c5ac471b478423, 0x0fcf80dc33721d54}, + {0xd1b71758e219652b, 0xd3c36113404ea4a9}, + {0x83126e978d4fdf3b, 0x645a1cac083126ea}, + {0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4}, + {0xcccccccccccccccc, 0xcccccccccccccccd}, + {0x8000000000000000, 0x0000000000000000}, + {0xa000000000000000, 0x0000000000000000}, + {0xc800000000000000, 0x0000000000000000}, + {0xfa00000000000000, 0x0000000000000000}, + {0x9c40000000000000, 0x0000000000000000}, + {0xc350000000000000, 0x0000000000000000}, + {0xf424000000000000, 0x0000000000000000}, + {0x9896800000000000, 0x0000000000000000}, + {0xbebc200000000000, 0x0000000000000000}, + {0xee6b280000000000, 0x0000000000000000}, + {0x9502f90000000000, 0x0000000000000000}, + {0xba43b74000000000, 0x0000000000000000}, + {0xe8d4a51000000000, 0x0000000000000000}, + {0x9184e72a00000000, 0x0000000000000000}, + {0xb5e620f480000000, 0x0000000000000000}, + {0xe35fa931a0000000, 0x0000000000000000}, + {0x8e1bc9bf04000000, 0x0000000000000000}, + {0xb1a2bc2ec5000000, 0x0000000000000000}, + {0xde0b6b3a76400000, 0x0000000000000000}, + {0x8ac7230489e80000, 0x0000000000000000}, + {0xad78ebc5ac620000, 0x0000000000000000}, + {0xd8d726b7177a8000, 0x0000000000000000}, + {0x878678326eac9000, 0x0000000000000000}, + {0xa968163f0a57b400, 0x0000000000000000}, + {0xd3c21bcecceda100, 0x0000000000000000}, + {0x84595161401484a0, 0x0000000000000000}, + {0xa56fa5b99019a5c8, 0x0000000000000000}, + {0xcecb8f27f4200f3a, 0x0000000000000000}, + {0x813f3978f8940984, 0x4000000000000000}, + {0xa18f07d736b90be5, 0x5000000000000000}, + {0xc9f2c9cd04674ede, 0xa400000000000000}, + {0xfc6f7c4045812296, 0x4d00000000000000}, + {0x9dc5ada82b70b59d, 0xf020000000000000}, + {0xc5371912364ce305, 0x6c28000000000000}, + {0xf684df56c3e01bc6, 0xc732000000000000}, + {0x9a130b963a6c115c, 0x3c7f400000000000}, + {0xc097ce7bc90715b3, 0x4b9f100000000000}, + {0xf0bdc21abb48db20, 0x1e86d40000000000}, + {0x96769950b50d88f4, 0x1314448000000000}, + {0xbc143fa4e250eb31, 0x17d955a000000000}, + {0xeb194f8e1ae525fd, 0x5dcfab0800000000}, + {0x92efd1b8d0cf37be, 0x5aa1cae500000000}, + {0xb7abc627050305ad, 0xf14a3d9e40000000}, + {0xe596b7b0c643c719, 0x6d9ccd05d0000000}, + {0x8f7e32ce7bea5c6f, 0xe4820023a2000000}, + {0xb35dbf821ae4f38b, 0xdda2802c8a800000}, + {0xe0352f62a19e306e, 0xd50b2037ad200000}, + {0x8c213d9da502de45, 0x4526f422cc340000}, + {0xaf298d050e4395d6, 0x9670b12b7f410000}, + {0xdaf3f04651d47b4c, 0x3c0cdd765f114000}, + {0x88d8762bf324cd0f, 0xa5880a69fb6ac800}, + {0xab0e93b6efee0053, 0x8eea0d047a457a00}, + {0xd5d238a4abe98068, 0x72a4904598d6d880}, + {0x85a36366eb71f041, 0x47a6da2b7f864750}, + {0xa70c3c40a64e6c51, 0x999090b65f67d924}, + {0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d}, + {0x82818f1281ed449f, 0xbff8f10e7a8921a5}, + {0xa321f2d7226895c7, 0xaff72d52192b6a0e}, + {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764491}, + {0xfee50b7025c36a08, 0x02f236d04753d5b5}, + {0x9f4f2726179a2245, 0x01d762422c946591}, + {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef6}, + {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb3}, + {0x9b934c3b330c8577, 0x63cc55f49f88eb30}, + {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fc}, + {0xf316271c7fc3908a, 0x8bef464e3945ef7b}, + {0x97edd871cfda3a56, 0x97758bf0e3cbb5ad}, + {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea318}, + {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bde}, + {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6b}, + {0xb975d6b6ee39e436, 0xb3e2fd538e122b45}, + {0xe7d34c64a9c85d44, 0x60dbbca87196b617}, + {0x90e40fbeea1d3a4a, 0xbc8955e946fe31ce}, + {0xb51d13aea4a488dd, 0x6babab6398bdbe42}, + {0xe264589a4dcdab14, 0xc696963c7eed2dd2}, + {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca3}, + {0xb0de65388cc8ada8, 0x3b25a55f43294bcc}, + {0xdd15fe86affad912, 0x49ef0eb713f39ebf}, + {0x8a2dbf142dfcc7ab, 0x6e3569326c784338}, + {0xacb92ed9397bf996, 0x49c2c37f07965405}, + {0xd7e77a8f87daf7fb, 0xdc33745ec97be907}, + {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a4}, + {0xa8acd7c0222311bc, 0xc40832ea0d68ce0d}, + {0xd2d80db02aabd62b, 0xf50a3fa490c30191}, + {0x83c7088e1aab65db, 0x792667c6da79e0fb}, + {0xa4b8cab1a1563f52, 0x577001b891185939}, + {0xcde6fd5e09abcf26, 0xed4c0226b55e6f87}, + {0x80b05e5ac60b6178, 0x544f8158315b05b5}, + {0xa0dc75f1778e39d6, 0x696361ae3db1c722}, + {0xc913936dd571c84c, 0x03bc3a19cd1e38ea}, + {0xfb5878494ace3a5f, 0x04ab48a04065c724}, + {0x9d174b2dcec0e47b, 0x62eb0d64283f9c77}, + {0xc45d1df942711d9a, 0x3ba5d0bd324f8395}, + {0xf5746577930d6500, 0xca8f44ec7ee3647a}, + {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecc}, + {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67f}, + {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101f}, + {0x95d04aee3b80ece5, 0xbba1f1d158724a13}, + {0xbb445da9ca61281f, 0x2a8a6e45ae8edc98}, + {0xea1575143cf97226, 0xf52d09d71a3293be}, + {0x924d692ca61be758, 0x593c2626705f9c57}, + {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836d}, + {0xe498f455c38b997a, 0x0b6dfb9c0f956448}, + {0x8edf98b59a373fec, 0x4724bd4189bd5ead}, + {0xb2977ee300c50fe7, 0x58edec91ec2cb658}, + {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ee}, + {0x8b865b215899f46c, 0xbd79e0d20082ee75}, + {0xae67f1e9aec07187, 0xecd8590680a3aa12}, + {0xda01ee641a708de9, 0xe80e6f4820cc9496}, + {0x884134fe908658b2, 0x3109058d147fdcde}, + {0xaa51823e34a7eede, 0xbd4b46f0599fd416}, + {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91b}, + {0x850fadc09923329e, 0x03e2cf6bc604ddb1}, + {0xa6539930bf6bff45, 0x84db8346b786151d}, + {0xcfe87f7cef46ff16, 0xe612641865679a64}, + {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07f}, + {0xa26da3999aef7749, 0xe3be5e330f38f09e}, + {0xcb090c8001ab551c, 0x5cadf5bfd3072cc6}, + {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f7}, + {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afb}, + {0xc646d63501a1511d, 0xb281e1fd541501b9}, + {0xf7d88bc24209a565, 0x1f225a7ca91a4227}, + {0x9ae757596946075f, 0x3375788de9b06959}, + {0xc1a12d2fc3978937, 0x0052d6b1641c83af}, + {0xf209787bb47d6b84, 0xc0678c5dbd23a49b}, + {0x9745eb4d50ce6332, 0xf840b7ba963646e1}, + {0xbd176620a501fbff, 0xb650e5a93bc3d899}, + {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebf}, + {0x93ba47c980e98cdf, 0xc66f336c36b10138}, + {0xb8a8d9bbe123f017, 0xb80b0047445d4185}, + {0xe6d3102ad96cec1d, 0xa60dc059157491e6}, + {0x9043ea1ac7e41392, 0x87c89837ad68db30}, + {0xb454e4a179dd1877, 0x29babe4598c311fc}, + {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67b}, + {0x8ce2529e2734bb1d, 0x1899e4a65f58660d}, + {0xb01ae745b101e9e4, 0x5ec05dcff72e7f90}, + {0xdc21a1171d42645d, 0x76707543f4fa1f74}, + {0x899504ae72497eba, 0x6a06494a791c53a9}, + {0xabfa45da0edbde69, 0x0487db9d17636893}, + {0xd6f8d7509292d603, 0x45a9d2845d3c42b7}, + {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b3}, + {0xa7f26836f282b732, 0x8e6cac7768d7141f}, + {0xd1ef0244af2364ff, 0x3207d795430cd927}, + {0x8335616aed761f1f, 0x7f44e6bd49e807b9}, + {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a7}, + {0xcd036837130890a1, 0x36dba887c37a8c10}, + {0x802221226be55a64, 0xc2494954da2c978a}, + {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6d}, + {0xc83553c5c8965d3d, 0x6f92829494e5acc8}, + {0xfa42a8b73abbf48c, 0xcb772339ba1f17fa}, + {0x9c69a97284b578d7, 0xff2a760414536efc}, + {0xc38413cf25e2d70d, 0xfef5138519684abb}, + {0xf46518c2ef5b8cd1, 0x7eb258665fc25d6a}, + {0x98bf2f79d5993802, 0xef2f773ffbd97a62}, + {0xbeeefb584aff8603, 0xaafb550ffacfd8fb}, + {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf39}, + {0x952ab45cfa97a0b2, 0xdd945a747bf26184}, + {0xba756174393d88df, 0x94f971119aeef9e5}, + {0xe912b9d1478ceb17, 0x7a37cd5601aab85e}, + {0x91abb422ccb812ee, 0xac62e055c10ab33b}, + {0xb616a12b7fe617aa, 0x577b986b314d600a}, + {0xe39c49765fdf9d94, 0xed5a7e85fda0b80c}, + {0x8e41ade9fbebc27d, 0x14588f13be847308}, + {0xb1d219647ae6b31c, 0x596eb2d8ae258fc9}, + {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bc}, + {0x8aec23d680043bee, 0x25de7bb9480d5855}, + {0xada72ccc20054ae9, 0xaf561aa79a10ae6b}, + {0xd910f7ff28069da4, 0x1b2ba1518094da05}, + {0x87aa9aff79042286, 0x90fb44d2f05d0843}, + {0xa99541bf57452b28, 0x353a1607ac744a54}, + {0xd3fa922f2d1675f2, 0x42889b8997915ce9}, + {0x847c9b5d7c2e09b7, 0x69956135febada12}, + {0xa59bc234db398c25, 0x43fab9837e699096}, + {0xcf02b2c21207ef2e, 0x94f967e45e03f4bc}, + {0x8161afb94b44f57d, 0x1d1be0eebac278f6}, + {0xa1ba1ba79e1632dc, 0x6462d92a69731733}, + {0xca28a291859bbf93, 0x7d7b8f7503cfdcff}, + {0xfcb2cb35e702af78, 0x5cda735244c3d43f}, + {0x9defbf01b061adab, 0x3a0888136afa64a8}, + {0xc56baec21c7a1916, 0x088aaa1845b8fdd1}, + {0xf6c69a72a3989f5b, 0x8aad549e57273d46}, + {0x9a3c2087a63f6399, 0x36ac54e2f678864c}, + {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7de}, + {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d6}, + {0x969eb7c47859e743, 0x9f644ae5a4b1b326}, + {0xbc4665b596706114, 0x873d5d9f0dde1fef}, + {0xeb57ff22fc0c7959, 0xa90cb506d155a7eb}, + {0x9316ff75dd87cbd8, 0x09a7f12442d588f3}, + {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb30}, + {0xe5d3ef282a242e81, 0x8f1668c8a86da5fb}, + {0x8fa475791a569d10, 0xf96e017d694487bd}, + {0xb38d92d760ec4455, 0x37c981dcc395a9ad}, + {0xe070f78d3927556a, 0x85bbe253f47b1418}, + {0x8c469ab843b89562, 0x93956d7478ccec8f}, + {0xaf58416654a6babb, 0x387ac8d1970027b3}, + {0xdb2e51bfe9d0696a, 0x06997b05fcc0319f}, + {0x88fcf317f22241e2, 0x441fece3bdf81f04}, + {0xab3c2fddeeaad25a, 0xd527e81cad7626c4}, + {0xd60b3bd56a5586f1, 0x8a71e223d8d3b075}, + {0x85c7056562757456, 0xf6872d5667844e4a}, + {0xa738c6bebb12d16c, 0xb428f8ac016561dc}, + {0xd106f86e69d785c7, 0xe13336d701beba53}, + {0x82a45b450226b39c, 0xecc0024661173474}, + {0xa34d721642b06084, 0x27f002d7f95d0191}, + {0xcc20ce9bd35c78a5, 0x31ec038df7b441f5}, + {0xff290242c83396ce, 0x7e67047175a15272}, + {0x9f79a169bd203e41, 0x0f0062c6e984d387}, + {0xc75809c42c684dd1, 0x52c07b78a3e60869}, + {0xf92e0c3537826145, 0xa7709a56ccdf8a83}, + {0x9bbcc7a142b17ccb, 0x88a66076400bb692}, + {0xc2abf989935ddbfe, 0x6acff893d00ea436}, + {0xf356f7ebf83552fe, 0x0583f6b8c4124d44}, + {0x98165af37b2153de, 0xc3727a337a8b704b}, + {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5d}, + {0xeda2ee1c7064130c, 0x1162def06f79df74}, + {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba9}, + {0xb9a74a0637ce2ee1, 0x6d953e2bd7173693}, + {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0438}, + {0x910ab1d4db9914a0, 0x1d9c9892400a22a3}, + {0xb54d5e4a127f59c8, 0x2503beb6d00cab4c}, + {0xe2a0b5dc971f303a, 0x2e44ae64840fd61e}, + {0x8da471a9de737e24, 0x5ceaecfed289e5d3}, + {0xb10d8e1456105dad, 0x7425a83e872c5f48}, + {0xdd50f1996b947518, 0xd12f124e28f7771a}, + {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa70}, + {0xace73cbfdc0bfb7b, 0x636cc64d1001550c}, + {0xd8210befd30efa5a, 0x3c47f7e05401aa4f}, + {0x8714a775e3e95c78, 0x65acfaec34810a72}, + {0xa8d9d1535ce3b396, 0x7f1839a741a14d0e}, + {0xd31045a8341ca07c, 0x1ede48111209a051}, + {0x83ea2b892091e44d, 0x934aed0aab460433}, + {0xa4e4b66b68b65d60, 0xf81da84d56178540}, + {0xce1de40642e3f4b9, 0x36251260ab9d668f}, + {0x80d2ae83e9ce78f3, 0xc1d72b7c6b42601a}, + {0xa1075a24e4421730, 0xb24cf65b8612f820}, + {0xc94930ae1d529cfc, 0xdee033f26797b628}, + {0xfb9b7cd9a4a7443c, 0x169840ef017da3b2}, + {0x9d412e0806e88aa5, 0x8e1f289560ee864f}, + {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e3}, + {0xf5b5d7ec8acb58a2, 0xae10af696774b1dc}, + {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef2a}, + {0xbff610b0cc6edd3f, 0x17fd090a58d32af4}, + {0xeff394dcff8a948e, 0xddfc4b4cef07f5b1}, + {0x95f83d0a1fb69cd9, 0x4abdaf101564f98f}, + {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f2}, + {0xea53df5fd18d5513, 0x84c86189216dc5ee}, + {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb5}, + {0xb7118682dbb66a77, 0x3fbc8c33221dc2a2}, + {0xe4d5e82392a40515, 0x0fabaf3feaa5334b}, + {0x8f05b1163ba6832d, 0x29cb4d87f2a7400f}, + {0xb2c71d5bca9023f8, 0x743e20e9ef511013}, + {0xdf78e4b2bd342cf6, 0x914da9246b255417}, + {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548f}, + {0xae9672aba3d0c320, 0xa184ac2473b529b2}, + {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741f}, + {0x8865899617fb1871, 0x7e2fa67c7a658893}, + {0xaa7eebfb9df9de8d, 0xddbb901b98feeab8}, + {0xd51ea6fa85785631, 0x552a74227f3ea566}, + {0x8533285c936b35de, 0xd53a88958f872760}, + {0xa67ff273b8460356, 0x8a892abaf368f138}, + {0xd01fef10a657842c, 0x2d2b7569b0432d86}, + {0x8213f56a67f6b29b, 0x9c3b29620e29fc74}, + {0xa298f2c501f45f42, 0x8349f3ba91b47b90}, + {0xcb3f2f7642717713, 0x241c70a936219a74}, + {0xfe0efb53d30dd4d7, 0xed238cd383aa0111}, + {0x9ec95d1463e8a506, 0xf4363804324a40ab}, + {0xc67bb4597ce2ce48, 0xb143c6053edcd0d6}, + {0xf81aa16fdc1b81da, 0xdd94b7868e94050b}, + {0x9b10a4e5e9913128, 0xca7cf2b4191c8327}, + {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f1}, + {0xf24a01a73cf2dccf, 0xbc633b39673c8ced}, + {0x976e41088617ca01, 0xd5be0503e085d814}, + {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e19}, + {0xec9c459d51852ba2, 0xddf8e7d60ed1219f}, + {0x93e1ab8252f33b45, 0xcabb90e5c942b504}, + {0xb8da1662e7b00a17, 0x3d6a751f3b936244}, + {0xe7109bfba19c0c9d, 0x0cc512670a783ad5}, + {0x906a617d450187e2, 0x27fb2b80668b24c6}, + {0xb484f9dc9641e9da, 0xb1f9f660802dedf7}, + {0xe1a63853bbd26451, 0x5e7873f8a0396974}, + {0x8d07e33455637eb2, 0xdb0b487b6423e1e9}, + {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda63}, + {0xdc5c5301c56b75f7, 0x7641a140cc7810fc}, + {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9e}, + {0xac2820d9623bf429, 0x546345fa9fbdcd45}, + {0xd732290fbacaf133, 0xa97c177947ad4096}, + {0x867f59a9d4bed6c0, 0x49ed8eabcccc485e}, + {0xa81f301449ee8c70, 0x5c68f256bfff5a75}, + {0xd226fc195c6a2f8c, 0x73832eec6fff3112}, + {0x83585d8fd9c25db7, 0xc831fd53c5ff7eac}, + {0xa42e74f3d032f525, 0xba3e7ca8b77f5e56}, + {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35ec}, + {0x80444b5e7aa7cf85, 0x7980d163cf5b81b4}, + {0xa0555e361951c366, 0xd7e105bcc3326220}, + {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa8}, + {0xfa856334878fc150, 0xb14f98f6f0feb952}, + {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d4}, + {0xc3b8358109e84f07, 0x0a862f80ec4700c9}, + {0xf4a642e14c6262c8, 0xcd27bb612758c0fb}, + {0x98e7e9cccfbd7dbd, 0x8038d51cb897789d}, + {0xbf21e44003acdd2c, 0xe0470a63e6bd56c4}, + {0xeeea5d5004981478, 0x1858ccfce06cac75}, + {0x95527a5202df0ccb, 0x0f37801e0c43ebc9}, + {0xbaa718e68396cffd, 0xd30560258f54e6bb}, + {0xe950df20247c83fd, 0x47c6b82ef32a206a}, + {0x91d28b7416cdd27e, 0x4cdc331d57fa5442}, + {0xb6472e511c81471d, 0xe0133fe4adf8e953}, + {0xe3d8f9e563a198e5, 0x58180fddd97723a7}, + {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7649}, + {0xb201833b35d63f73, 0x2cd2cc6551e513db}, + {0xde81e40a034bcf4f, 0xf8077f7ea65e58d2}, + {0x8b112e86420f6191, 0xfb04afaf27faf783}, + {0xadd57a27d29339f6, 0x79c5db9af1f9b564}, + {0xd94ad8b1c7380874, 0x18375281ae7822bd}, + {0x87cec76f1c830548, 0x8f2293910d0b15b6}, + {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb23}, + {0xd433179d9c8cb841, 0x5fa60692a46151ec}, + {0x849feec281d7f328, 0xdbc7c41ba6bcd334}, + {0xa5c7ea73224deff3, 0x12b9b522906c0801}, + {0xcf39e50feae16bef, 0xd768226b34870a01}, + {0x81842f29f2cce375, 0xe6a1158300d46641}, + {0xa1e53af46f801c53, 0x60495ae3c1097fd1}, + {0xca5e89b18b602368, 0x385bb19cb14bdfc5}, + {0xfcf62c1dee382c42, 0x46729e03dd9ed7b6}, + {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d2}, + {0xc5a05277621be293, 0xc7098b7305241886}, + {0xf70867153aa2db38, 0xb8cbee4fc66d1ea8}, + {0x9a65406d44a5c903, 0x737f74f1dc043329}, + {0xc0fe908895cf3b44, 0x505f522e53053ff3}, + {0xf13e34aabb430a15, 0x647726b9e7c68ff0}, + {0x96c6e0eab509e64d, 0x5eca783430dc19f6}, + {0xbc789925624c5fe0, 0xb67d16413d132073}, + {0xeb96bf6ebadf77d8, 0xe41c5bd18c57e890}, + {0x933e37a534cbaae7, 0x8e91b962f7b6f15a}, + {0xb80dc58e81fe95a1, 0x723627bbb5a4adb1}, + {0xe61136f2227e3b09, 0xcec3b1aaa30dd91d}, + {0x8fcac257558ee4e6, 0x213a4f0aa5e8a7b2}, + {0xb3bd72ed2af29e1f, 0xa988e2cd4f62d19e}, + {0xe0accfa875af45a7, 0x93eb1b80a33b8606}, + {0x8c6c01c9498d8b88, 0xbc72f130660533c4}, + {0xaf87023b9bf0ee6a, 0xeb8fad7c7f8680b5}, + {0xdb68c2ca82ed2a05, 0xa67398db9f6820e2}, +#else + {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, + {0xce5d73ff402d98e3, 0xfb0a3d212dc81290}, + {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, + {0x86a8d39ef77164bc, 0xae5dff9c02033198}, + {0xd98ddaee19068c76, 0x3badd624dd9b0958}, + {0xafbd2350644eeacf, 0xe5d1929ef90898fb}, + {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, + {0xe55990879ddcaabd, 0xcc420a6a101d0516}, + {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, + {0x95a8637627989aad, 0xdde7001379a44aa9}, + {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, + {0xc350000000000000, 0x0000000000000000}, + {0x9dc5ada82b70b59d, 0xf020000000000000}, + {0xfee50b7025c36a08, 0x02f236d04753d5b5}, + {0xcde6fd5e09abcf26, 0xed4c0226b55e6f87}, + {0xa6539930bf6bff45, 0x84db8346b786151d}, + {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b3}, + {0xd910f7ff28069da4, 0x1b2ba1518094da05}, + {0xaf58416654a6babb, 0x387ac8d1970027b3}, + {0x8da471a9de737e24, 0x5ceaecfed289e5d3}, + {0xe4d5e82392a40515, 0x0fabaf3feaa5334b}, + {0xb8da1662e7b00a17, 0x3d6a751f3b936244}, + {0x95527a5202df0ccb, 0x0f37801e0c43ebc9}, + {0xf13e34aabb430a15, 0x647726b9e7c68ff0} +#endif + }; + +#if FMT_USE_FULL_CACHE_DRAGONBOX + return pow10_significands[k - float_info::min_k]; +#else + static constexpr const uint64_t powers_of_5_64[] = { + 0x0000000000000001, 0x0000000000000005, 0x0000000000000019, + 0x000000000000007d, 0x0000000000000271, 0x0000000000000c35, + 0x0000000000003d09, 0x000000000001312d, 0x000000000005f5e1, + 0x00000000001dcd65, 0x00000000009502f9, 0x0000000002e90edd, + 0x000000000e8d4a51, 0x0000000048c27395, 0x000000016bcc41e9, + 0x000000071afd498d, 0x0000002386f26fc1, 0x000000b1a2bc2ec5, + 0x000003782dace9d9, 0x00001158e460913d, 0x000056bc75e2d631, + 0x0001b1ae4d6e2ef5, 0x000878678326eac9, 0x002a5a058fc295ed, + 0x00d3c21bcecceda1, 0x0422ca8b0a00a425, 0x14adf4b7320334b9}; + + static const int compression_ratio = 27; + + // Compute base index. + int cache_index = (k - float_info::min_k) / compression_ratio; + int kb = cache_index * compression_ratio + float_info::min_k; + int offset = k - kb; + + // Get base cache. + uint128_fallback base_cache = pow10_significands[cache_index]; + if (offset == 0) return base_cache; + + // Compute the required amount of bit-shift. + int alpha = floor_log2_pow10(kb + offset) - floor_log2_pow10(kb) - offset; + FMT_ASSERT(alpha > 0 && alpha < 64, "shifting error detected"); + + // Try to recover the real cache. + uint64_t pow5 = powers_of_5_64[offset]; + uint128_fallback recovered_cache = umul128(base_cache.high(), pow5); + uint128_fallback middle_low = umul128(base_cache.low(), pow5); + + recovered_cache += middle_low.high(); + + uint64_t high_to_middle = recovered_cache.high() << (64 - alpha); + uint64_t middle_to_low = recovered_cache.low() << (64 - alpha); + + recovered_cache = + uint128_fallback{(recovered_cache.low() >> alpha) | high_to_middle, + ((middle_low.low() >> alpha) | middle_to_low)}; + FMT_ASSERT(recovered_cache.low() + 1 != 0, ""); + return {recovered_cache.high(), recovered_cache.low() + 1}; +#endif + } + + struct compute_mul_result { + carrier_uint result; + bool is_integer; + }; + struct compute_mul_parity_result { + bool parity; + bool is_integer; + }; + + static auto compute_mul(carrier_uint u, + const cache_entry_type& cache) noexcept + -> compute_mul_result { + auto r = umul192_upper128(u, cache); + return {r.high(), r.low() == 0}; + } + + static auto compute_delta(cache_entry_type const& cache, int beta) noexcept + -> uint32_t { + return static_cast(cache.high() >> (64 - 1 - beta)); + } + + static auto compute_mul_parity(carrier_uint two_f, + const cache_entry_type& cache, + int beta) noexcept + -> compute_mul_parity_result { + FMT_ASSERT(beta >= 1, ""); + FMT_ASSERT(beta < 64, ""); + + auto r = umul192_lower128(two_f, cache); + return {((r.high() >> (64 - beta)) & 1) != 0, + ((r.high() << beta) | (r.low() >> (64 - beta))) == 0}; + } + + static auto compute_left_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept -> carrier_uint { + return (cache.high() - + (cache.high() >> (num_significand_bits() + 2))) >> + (64 - num_significand_bits() - 1 - beta); + } + + static auto compute_right_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept -> carrier_uint { + return (cache.high() + + (cache.high() >> (num_significand_bits() + 1))) >> + (64 - num_significand_bits() - 1 - beta); + } + + static auto compute_round_up_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept -> carrier_uint { + return ((cache.high() >> (64 - num_significand_bits() - 2 - beta)) + + 1) / + 2; + } +}; + +FMT_FUNC auto get_cached_power(int k) noexcept -> uint128_fallback { + return cache_accessor::get_cached_power(k); +} + +// Various integer checks +template +auto is_left_endpoint_integer_shorter_interval(int exponent) noexcept -> bool { + const int case_shorter_interval_left_endpoint_lower_threshold = 2; + const int case_shorter_interval_left_endpoint_upper_threshold = 3; + return exponent >= case_shorter_interval_left_endpoint_lower_threshold && + exponent <= case_shorter_interval_left_endpoint_upper_threshold; +} + +// Remove trailing zeros from n and return the number of zeros removed (float) +FMT_INLINE int remove_trailing_zeros(uint32_t& n, int s = 0) noexcept { + FMT_ASSERT(n != 0, ""); + // Modular inverse of 5 (mod 2^32): (mod_inv_5 * 5) mod 2^32 = 1. + constexpr uint32_t mod_inv_5 = 0xcccccccd; + constexpr uint32_t mod_inv_25 = 0xc28f5c29; // = mod_inv_5 * mod_inv_5 + + while (true) { + auto q = rotr(n * mod_inv_25, 2); + if (q > max_value() / 100) break; + n = q; + s += 2; + } + auto q = rotr(n * mod_inv_5, 1); + if (q <= max_value() / 10) { + n = q; + s |= 1; + } + return s; +} + +// Removes trailing zeros and returns the number of zeros removed (double) +FMT_INLINE int remove_trailing_zeros(uint64_t& n) noexcept { + FMT_ASSERT(n != 0, ""); + + // This magic number is ceil(2^90 / 10^8). + constexpr uint64_t magic_number = 12379400392853802749ull; + auto nm = umul128(n, magic_number); + + // Is n is divisible by 10^8? + if ((nm.high() & ((1ull << (90 - 64)) - 1)) == 0 && nm.low() < magic_number) { + // If yes, work with the quotient... + auto n32 = static_cast(nm.high() >> (90 - 64)); + // ... and use the 32 bit variant of the function + int s = remove_trailing_zeros(n32, 8); + n = n32; + return s; + } + + // If n is not divisible by 10^8, work with n itself. + constexpr uint64_t mod_inv_5 = 0xcccccccccccccccd; + constexpr uint64_t mod_inv_25 = 0x8f5c28f5c28f5c29; // mod_inv_5 * mod_inv_5 + + int s = 0; + while (true) { + auto q = rotr(n * mod_inv_25, 2); + if (q > max_value() / 100) break; + n = q; + s += 2; + } + auto q = rotr(n * mod_inv_5, 1); + if (q <= max_value() / 10) { + n = q; + s |= 1; + } + + return s; +} + +// The main algorithm for shorter interval case +template +FMT_INLINE decimal_fp shorter_interval_case(int exponent) noexcept { + decimal_fp ret_value; + // Compute k and beta + const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent); + const int beta = exponent + floor_log2_pow10(-minus_k); + + // Compute xi and zi + using cache_entry_type = typename cache_accessor::cache_entry_type; + const cache_entry_type cache = cache_accessor::get_cached_power(-minus_k); + + auto xi = cache_accessor::compute_left_endpoint_for_shorter_interval_case( + cache, beta); + auto zi = cache_accessor::compute_right_endpoint_for_shorter_interval_case( + cache, beta); + + // If the left endpoint is not an integer, increase it + if (!is_left_endpoint_integer_shorter_interval(exponent)) ++xi; + + // Try bigger divisor + ret_value.significand = zi / 10; + + // If succeed, remove trailing zeros if necessary and return + if (ret_value.significand * 10 >= xi) { + ret_value.exponent = minus_k + 1; + ret_value.exponent += remove_trailing_zeros(ret_value.significand); + return ret_value; + } + + // Otherwise, compute the round-up of y + ret_value.significand = + cache_accessor::compute_round_up_for_shorter_interval_case(cache, + beta); + ret_value.exponent = minus_k; + + // When tie occurs, choose one of them according to the rule + if (exponent >= float_info::shorter_interval_tie_lower_threshold && + exponent <= float_info::shorter_interval_tie_upper_threshold) { + ret_value.significand = ret_value.significand % 2 == 0 + ? ret_value.significand + : ret_value.significand - 1; + } else if (ret_value.significand < xi) { + ++ret_value.significand; + } + return ret_value; +} + +template auto to_decimal(T x) noexcept -> decimal_fp { + // Step 1: integer promotion & Schubfach multiplier calculation. + + using carrier_uint = typename float_info::carrier_uint; + using cache_entry_type = typename cache_accessor::cache_entry_type; + auto br = bit_cast(x); + + // Extract significand bits and exponent bits. + const carrier_uint significand_mask = + (static_cast(1) << num_significand_bits()) - 1; + carrier_uint significand = (br & significand_mask); + int exponent = + static_cast((br & exponent_mask()) >> num_significand_bits()); + + if (exponent != 0) { // Check if normal. + exponent -= exponent_bias() + num_significand_bits(); + + // Shorter interval case; proceed like Schubfach. + // In fact, when exponent == 1 and significand == 0, the interval is + // regular. However, it can be shown that the end-results are anyway same. + if (significand == 0) return shorter_interval_case(exponent); + + significand |= (static_cast(1) << num_significand_bits()); + } else { + // Subnormal case; the interval is always regular. + if (significand == 0) return {0, 0}; + exponent = + std::numeric_limits::min_exponent - num_significand_bits() - 1; + } + + const bool include_left_endpoint = (significand % 2 == 0); + const bool include_right_endpoint = include_left_endpoint; + + // Compute k and beta. + const int minus_k = floor_log10_pow2(exponent) - float_info::kappa; + const cache_entry_type cache = cache_accessor::get_cached_power(-minus_k); + const int beta = exponent + floor_log2_pow10(-minus_k); + + // Compute zi and deltai. + // 10^kappa <= deltai < 10^(kappa + 1) + const uint32_t deltai = cache_accessor::compute_delta(cache, beta); + const carrier_uint two_fc = significand << 1; + + // For the case of binary32, the result of integer check is not correct for + // 29711844 * 2^-82 + // = 6.1442653300000000008655037797566933477355632930994033813476... * 10^-18 + // and 29711844 * 2^-81 + // = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17, + // and they are the unique counterexamples. However, since 29711844 is even, + // this does not cause any problem for the endpoints calculations; it can only + // cause a problem when we need to perform integer check for the center. + // Fortunately, with these inputs, that branch is never executed, so we are + // fine. + const typename cache_accessor::compute_mul_result z_mul = + cache_accessor::compute_mul((two_fc | 1) << beta, cache); + + // Step 2: Try larger divisor; remove trailing zeros if necessary. + + // Using an upper bound on zi, we might be able to optimize the division + // better than the compiler; we are computing zi / big_divisor here. + decimal_fp ret_value; + ret_value.significand = divide_by_10_to_kappa_plus_1(z_mul.result); + uint32_t r = static_cast(z_mul.result - float_info::big_divisor * + ret_value.significand); + + if (r < deltai) { + // Exclude the right endpoint if necessary. + if (r == 0 && (z_mul.is_integer & !include_right_endpoint)) { + --ret_value.significand; + r = float_info::big_divisor; + goto small_divisor_case_label; + } + } else if (r > deltai) { + goto small_divisor_case_label; + } else { + // r == deltai; compare fractional parts. + const typename cache_accessor::compute_mul_parity_result x_mul = + cache_accessor::compute_mul_parity(two_fc - 1, cache, beta); + + if (!(x_mul.parity | (x_mul.is_integer & include_left_endpoint))) + goto small_divisor_case_label; + } + ret_value.exponent = minus_k + float_info::kappa + 1; + + // We may need to remove trailing zeros. + ret_value.exponent += remove_trailing_zeros(ret_value.significand); + return ret_value; + + // Step 3: Find the significand with the smaller divisor. + +small_divisor_case_label: + ret_value.significand *= 10; + ret_value.exponent = minus_k + float_info::kappa; + + uint32_t dist = r - (deltai / 2) + (float_info::small_divisor / 2); + const bool approx_y_parity = + ((dist ^ (float_info::small_divisor / 2)) & 1) != 0; + + // Is dist divisible by 10^kappa? + const bool divisible_by_small_divisor = + check_divisibility_and_divide_by_pow10::kappa>(dist); + + // Add dist / 10^kappa to the significand. + ret_value.significand += dist; + + if (!divisible_by_small_divisor) return ret_value; + + // Check z^(f) >= epsilon^(f). + // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1, + // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f). + // Since there are only 2 possibilities, we only need to care about the + // parity. Also, zi and r should have the same parity since the divisor + // is an even number. + const auto y_mul = cache_accessor::compute_mul_parity(two_fc, cache, beta); + + // If z^(f) >= epsilon^(f), we might have a tie when z^(f) == epsilon^(f), + // or equivalently, when y is an integer. + if (y_mul.parity != approx_y_parity) + --ret_value.significand; + else if (y_mul.is_integer & (ret_value.significand % 2 != 0)) + --ret_value.significand; + return ret_value; +} +} // namespace dragonbox +} // namespace detail + +template <> struct formatter { + FMT_CONSTEXPR auto parse(format_parse_context& ctx) + -> format_parse_context::iterator { + return ctx.begin(); + } + + auto format(const detail::bigint& n, format_context& ctx) const + -> format_context::iterator { + auto out = ctx.out(); + bool first = true; + for (auto i = n.bigits_.size(); i > 0; --i) { + auto value = n.bigits_[i - 1u]; + if (first) { + out = fmt::format_to(out, FMT_STRING("{:x}"), value); + first = false; + continue; + } + out = fmt::format_to(out, FMT_STRING("{:08x}"), value); + } + if (n.exp_ > 0) + out = fmt::format_to(out, FMT_STRING("p{}"), + n.exp_ * detail::bigint::bigit_bits); + return out; + } +}; + +FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) { + for_each_codepoint(s, [this](uint32_t cp, string_view) { + if (cp == invalid_code_point) FMT_THROW(std::runtime_error("invalid utf8")); + if (cp <= 0xFFFF) { + buffer_.push_back(static_cast(cp)); + } else { + cp -= 0x10000; + buffer_.push_back(static_cast(0xD800 + (cp >> 10))); + buffer_.push_back(static_cast(0xDC00 + (cp & 0x3FF))); + } + return true; + }); + buffer_.push_back(0); +} + +FMT_FUNC void format_system_error(detail::buffer& out, int error_code, + const char* message) noexcept { + FMT_TRY { + auto ec = std::error_code(error_code, std::generic_category()); + detail::write(appender(out), std::system_error(ec, message).what()); + return; + } + FMT_CATCH(...) {} + format_error_code(out, error_code, message); +} + +FMT_FUNC void report_system_error(int error_code, + const char* message) noexcept { + report_error(format_system_error, error_code, message); +} + +FMT_FUNC auto vformat(string_view fmt, format_args args) -> std::string { + // Don't optimize the "{}" case to keep the binary size small and because it + // can be better optimized in fmt::format anyway. + auto buffer = memory_buffer(); + detail::vformat_to(buffer, fmt, args); + return to_string(buffer); +} + +namespace detail { + +template struct span { + T* data; + size_t size; +}; + +template auto flockfile(F* f) -> decltype(_lock_file(f)) { + _lock_file(f); +} +template auto funlockfile(F* f) -> decltype(_unlock_file(f)) { + _unlock_file(f); +} + +#ifndef getc_unlocked +template auto getc_unlocked(F* f) -> decltype(_fgetc_nolock(f)) { + return _fgetc_nolock(f); +} +#endif + +template +struct has_flockfile : std::false_type {}; + +template +struct has_flockfile()))>> + : std::true_type {}; + +// A FILE wrapper. F is FILE defined as a template parameter to make system API +// detection work. +template class file_base { + public: + F* file_; + + public: + file_base(F* file) : file_(file) {} + operator F*() const { return file_; } + + // Reads a code unit from the stream. + auto get() -> int { + int result = getc_unlocked(file_); + if (result == EOF && ferror(file_) != 0) + FMT_THROW(system_error(errno, FMT_STRING("getc failed"))); + return result; + } + + // Puts the code unit back into the stream buffer. + void unget(char c) { + if (ungetc(c, file_) == EOF) + FMT_THROW(system_error(errno, FMT_STRING("ungetc failed"))); + } + + void flush() { fflush(this->file_); } +}; + +// A FILE wrapper for glibc. +template class glibc_file : public file_base { + private: + enum { + line_buffered = 0x200, // _IO_LINE_BUF + unbuffered = 2 // _IO_UNBUFFERED + }; + + public: + using file_base::file_base; + + auto is_buffered() const -> bool { + return (this->file_->_flags & unbuffered) == 0; + } + + void init_buffer() { + if (this->file_->_IO_write_ptr) return; + // Force buffer initialization by placing and removing a char in a buffer. + putc_unlocked(0, this->file_); + --this->file_->_IO_write_ptr; + } + + // Returns the file's read buffer. + auto get_read_buffer() const -> span { + auto ptr = this->file_->_IO_read_ptr; + return {ptr, to_unsigned(this->file_->_IO_read_end - ptr)}; + } + + // Returns the file's write buffer. + auto get_write_buffer() const -> span { + auto ptr = this->file_->_IO_write_ptr; + return {ptr, to_unsigned(this->file_->_IO_buf_end - ptr)}; + } + + void advance_write_buffer(size_t size) { this->file_->_IO_write_ptr += size; } + + bool needs_flush() const { + if ((this->file_->_flags & line_buffered) == 0) return false; + char* end = this->file_->_IO_write_end; + return memchr(end, '\n', to_unsigned(this->file_->_IO_write_ptr - end)); + } + + void flush() { fflush_unlocked(this->file_); } +}; + +// A FILE wrapper for Apple's libc. +template class apple_file : public file_base { + private: + enum { + line_buffered = 1, // __SNBF + unbuffered = 2 // __SLBF + }; + + public: + using file_base::file_base; + + auto is_buffered() const -> bool { + return (this->file_->_flags & unbuffered) == 0; + } + + void init_buffer() { + if (this->file_->_p) return; + // Force buffer initialization by placing and removing a char in a buffer. + putc_unlocked(0, this->file_); + --this->file_->_p; + ++this->file_->_w; + } + + auto get_read_buffer() const -> span { + return {reinterpret_cast(this->file_->_p), + to_unsigned(this->file_->_r)}; + } + + auto get_write_buffer() const -> span { + return {reinterpret_cast(this->file_->_p), + to_unsigned(this->file_->_bf._base + this->file_->_bf._size - + this->file_->_p)}; + } + + void advance_write_buffer(size_t size) { + this->file_->_p += size; + this->file_->_w -= size; + } + + bool needs_flush() const { + if ((this->file_->_flags & line_buffered) == 0) return false; + return memchr(this->file_->_p + this->file_->_w, '\n', + to_unsigned(-this->file_->_w)); + } +}; + +// A fallback FILE wrapper. +template class fallback_file : public file_base { + private: + char next_; // The next unconsumed character in the buffer. + bool has_next_ = false; + + public: + using file_base::file_base; + + auto is_buffered() const -> bool { return false; } + auto needs_flush() const -> bool { return false; } + void init_buffer() {} + + auto get_read_buffer() const -> span { + return {&next_, has_next_ ? 1u : 0u}; + } + + auto get_write_buffer() const -> span { return {nullptr, 0}; } + + void advance_write_buffer(size_t) {} + + auto get() -> int { + has_next_ = false; + return file_base::get(); + } + + void unget(char c) { + file_base::unget(c); + next_ = c; + has_next_ = true; + } +}; + +#ifndef FMT_USE_FALLBACK_FILE +# define FMT_USE_FALLBACK_FILE 1 +#endif + +template +auto get_file(F* f, int) -> apple_file { + return f; +} +template +inline auto get_file(F* f, int) -> glibc_file { + return f; +} + +inline auto get_file(FILE* f, ...) -> fallback_file { return f; } + +using file_ref = decltype(get_file(static_cast(nullptr), 0)); + +template +class file_print_buffer : public buffer { + public: + explicit file_print_buffer(F*) : buffer(nullptr, size_t()) {} +}; + +template +class file_print_buffer::value>> + : public buffer { + private: + file_ref file_; + + static void grow(buffer& base, size_t) { + auto& self = static_cast(base); + self.file_.advance_write_buffer(self.size()); + if (self.file_.get_write_buffer().size == 0) self.file_.flush(); + auto buf = self.file_.get_write_buffer(); + FMT_ASSERT(buf.size > 0, ""); + self.set(buf.data, buf.size); + self.clear(); + } + + public: + explicit file_print_buffer(F* f) : buffer(grow, size_t()), file_(f) { + flockfile(f); + file_.init_buffer(); + auto buf = file_.get_write_buffer(); + set(buf.data, buf.size); + } + ~file_print_buffer() { + file_.advance_write_buffer(size()); + bool flush = file_.needs_flush(); + F* f = file_; // Make funlockfile depend on the template parameter F + funlockfile(f); // for the system API detection to work. + if (flush) fflush(file_); + } +}; + +#if !defined(_WIN32) || defined(FMT_USE_WRITE_CONSOLE) +FMT_FUNC auto write_console(int, string_view) -> bool { return false; } +#else +using dword = conditional_t; +extern "C" __declspec(dllimport) int __stdcall WriteConsoleW( // + void*, const void*, dword, dword*, void*); + +FMT_FUNC bool write_console(int fd, string_view text) { + auto u16 = utf8_to_utf16(text); + return WriteConsoleW(reinterpret_cast(_get_osfhandle(fd)), u16.c_str(), + static_cast(u16.size()), nullptr, nullptr) != 0; +} +#endif + +#ifdef _WIN32 +// Print assuming legacy (non-Unicode) encoding. +FMT_FUNC void vprint_mojibake(std::FILE* f, string_view fmt, format_args args, + bool newline) { + auto buffer = memory_buffer(); + detail::vformat_to(buffer, fmt, args); + if (newline) buffer.push_back('\n'); + fwrite_fully(buffer.data(), buffer.size(), f); +} +#endif + +FMT_FUNC void print(std::FILE* f, string_view text) { +#if defined(_WIN32) && !defined(FMT_USE_WRITE_CONSOLE) + int fd = _fileno(f); + if (_isatty(fd)) { + std::fflush(f); + if (write_console(fd, text)) return; + } +#endif + fwrite_fully(text.data(), text.size(), f); +} +} // namespace detail + +FMT_FUNC void vprint_buffered(std::FILE* f, string_view fmt, format_args args) { + auto buffer = memory_buffer(); + detail::vformat_to(buffer, fmt, args); + detail::print(f, {buffer.data(), buffer.size()}); +} + +FMT_FUNC void vprint(std::FILE* f, string_view fmt, format_args args) { + if (!detail::file_ref(f).is_buffered() || !detail::has_flockfile<>()) + return vprint_buffered(f, fmt, args); + auto&& buffer = detail::file_print_buffer<>(f); + return detail::vformat_to(buffer, fmt, args); +} + +FMT_FUNC void vprintln(std::FILE* f, string_view fmt, format_args args) { + auto buffer = memory_buffer(); + detail::vformat_to(buffer, fmt, args); + buffer.push_back('\n'); + detail::print(f, {buffer.data(), buffer.size()}); +} + +FMT_FUNC void vprint(string_view fmt, format_args args) { + vprint(stdout, fmt, args); +} + +namespace detail { + +struct singleton { + unsigned char upper; + unsigned char lower_count; +}; + +inline auto is_printable(uint16_t x, const singleton* singletons, + size_t singletons_size, + const unsigned char* singleton_lowers, + const unsigned char* normal, size_t normal_size) + -> bool { + auto upper = x >> 8; + auto lower_start = 0; + for (size_t i = 0; i < singletons_size; ++i) { + auto s = singletons[i]; + auto lower_end = lower_start + s.lower_count; + if (upper < s.upper) break; + if (upper == s.upper) { + for (auto j = lower_start; j < lower_end; ++j) { + if (singleton_lowers[j] == (x & 0xff)) return false; + } + } + lower_start = lower_end; + } + + auto xsigned = static_cast(x); + auto current = true; + for (size_t i = 0; i < normal_size; ++i) { + auto v = static_cast(normal[i]); + auto len = (v & 0x80) != 0 ? (v & 0x7f) << 8 | normal[++i] : v; + xsigned -= len; + if (xsigned < 0) break; + current = !current; + } + return current; +} + +// This code is generated by support/printable.py. +FMT_FUNC auto is_printable(uint32_t cp) -> bool { + static constexpr singleton singletons0[] = { + {0x00, 1}, {0x03, 5}, {0x05, 6}, {0x06, 3}, {0x07, 6}, {0x08, 8}, + {0x09, 17}, {0x0a, 28}, {0x0b, 25}, {0x0c, 20}, {0x0d, 16}, {0x0e, 13}, + {0x0f, 4}, {0x10, 3}, {0x12, 18}, {0x13, 9}, {0x16, 1}, {0x17, 5}, + {0x18, 2}, {0x19, 3}, {0x1a, 7}, {0x1c, 2}, {0x1d, 1}, {0x1f, 22}, + {0x20, 3}, {0x2b, 3}, {0x2c, 2}, {0x2d, 11}, {0x2e, 1}, {0x30, 3}, + {0x31, 2}, {0x32, 1}, {0xa7, 2}, {0xa9, 2}, {0xaa, 4}, {0xab, 8}, + {0xfa, 2}, {0xfb, 5}, {0xfd, 4}, {0xfe, 3}, {0xff, 9}, + }; + static constexpr unsigned char singletons0_lower[] = { + 0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, 0x58, 0x8b, 0x8c, 0x90, + 0x1c, 0x1d, 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f, + 0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91, 0x92, 0xa9, 0xb1, + 0xba, 0xbb, 0xc5, 0xc6, 0xc9, 0xca, 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04, + 0x11, 0x12, 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a, 0x5d, + 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf, + 0xe4, 0xe5, 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, + 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d, + 0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65, 0x8d, + 0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d, + 0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, + 0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7, + 0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, + 0x4e, 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7, + 0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, + 0xfe, 0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e, + 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf, 0xbb, 0xbc, 0xfa, 0x16, + 0x17, 0x1e, 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e, + 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f, + 0x74, 0x75, 0x96, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf, + 0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98, 0x30, 0x8f, 0x1f, 0xc0, + 0xc1, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27, + 0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91, + 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, + 0xfe, 0xff, + }; + static constexpr singleton singletons1[] = { + {0x00, 6}, {0x01, 1}, {0x03, 1}, {0x04, 2}, {0x08, 8}, {0x09, 2}, + {0x0a, 5}, {0x0b, 2}, {0x0e, 4}, {0x10, 1}, {0x11, 2}, {0x12, 5}, + {0x13, 17}, {0x14, 1}, {0x15, 2}, {0x17, 2}, {0x19, 13}, {0x1c, 5}, + {0x1d, 8}, {0x24, 1}, {0x6a, 3}, {0x6b, 2}, {0xbc, 2}, {0xd1, 2}, + {0xd4, 12}, {0xd5, 9}, {0xd6, 2}, {0xd7, 2}, {0xda, 1}, {0xe0, 5}, + {0xe1, 2}, {0xe8, 2}, {0xee, 32}, {0xf0, 4}, {0xf8, 2}, {0xf9, 2}, + {0xfa, 2}, {0xfb, 1}, + }; + static constexpr unsigned char singletons1_lower[] = { + 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, 0x9e, 0x9f, 0x06, 0x07, + 0x09, 0x36, 0x3d, 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36, + 0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd, 0x35, 0xe0, 0x12, 0x87, + 0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, + 0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5c, 0xb6, 0xb7, 0x1b, + 0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9, + 0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66, + 0x69, 0x8f, 0x92, 0x6f, 0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, + 0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, 0xba, 0xbc, + 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, + 0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, 0xc5, 0xc6, + 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c, + 0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66, + 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, + 0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93, + }; + static constexpr unsigned char normal0[] = { + 0x00, 0x20, 0x5f, 0x22, 0x82, 0xdf, 0x04, 0x82, 0x44, 0x08, 0x1b, 0x04, + 0x06, 0x11, 0x81, 0xac, 0x0e, 0x80, 0xab, 0x35, 0x28, 0x0b, 0x80, 0xe0, + 0x03, 0x19, 0x08, 0x01, 0x04, 0x2f, 0x04, 0x34, 0x04, 0x07, 0x03, 0x01, + 0x07, 0x06, 0x07, 0x11, 0x0a, 0x50, 0x0f, 0x12, 0x07, 0x55, 0x07, 0x03, + 0x04, 0x1c, 0x0a, 0x09, 0x03, 0x08, 0x03, 0x07, 0x03, 0x02, 0x03, 0x03, + 0x03, 0x0c, 0x04, 0x05, 0x03, 0x0b, 0x06, 0x01, 0x0e, 0x15, 0x05, 0x3a, + 0x03, 0x11, 0x07, 0x06, 0x05, 0x10, 0x07, 0x57, 0x07, 0x02, 0x07, 0x15, + 0x0d, 0x50, 0x04, 0x43, 0x03, 0x2d, 0x03, 0x01, 0x04, 0x11, 0x06, 0x0f, + 0x0c, 0x3a, 0x04, 0x1d, 0x25, 0x5f, 0x20, 0x6d, 0x04, 0x6a, 0x25, 0x80, + 0xc8, 0x05, 0x82, 0xb0, 0x03, 0x1a, 0x06, 0x82, 0xfd, 0x03, 0x59, 0x07, + 0x15, 0x0b, 0x17, 0x09, 0x14, 0x0c, 0x14, 0x0c, 0x6a, 0x06, 0x0a, 0x06, + 0x1a, 0x06, 0x59, 0x07, 0x2b, 0x05, 0x46, 0x0a, 0x2c, 0x04, 0x0c, 0x04, + 0x01, 0x03, 0x31, 0x0b, 0x2c, 0x04, 0x1a, 0x06, 0x0b, 0x03, 0x80, 0xac, + 0x06, 0x0a, 0x06, 0x21, 0x3f, 0x4c, 0x04, 0x2d, 0x03, 0x74, 0x08, 0x3c, + 0x03, 0x0f, 0x03, 0x3c, 0x07, 0x38, 0x08, 0x2b, 0x05, 0x82, 0xff, 0x11, + 0x18, 0x08, 0x2f, 0x11, 0x2d, 0x03, 0x20, 0x10, 0x21, 0x0f, 0x80, 0x8c, + 0x04, 0x82, 0x97, 0x19, 0x0b, 0x15, 0x88, 0x94, 0x05, 0x2f, 0x05, 0x3b, + 0x07, 0x02, 0x0e, 0x18, 0x09, 0x80, 0xb3, 0x2d, 0x74, 0x0c, 0x80, 0xd6, + 0x1a, 0x0c, 0x05, 0x80, 0xff, 0x05, 0x80, 0xdf, 0x0c, 0xee, 0x0d, 0x03, + 0x84, 0x8d, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, 0x80, + 0xcb, 0x2a, 0x38, 0x03, 0x0a, 0x06, 0x38, 0x08, 0x46, 0x08, 0x0c, 0x06, + 0x74, 0x0b, 0x1e, 0x03, 0x5a, 0x04, 0x59, 0x09, 0x80, 0x83, 0x18, 0x1c, + 0x0a, 0x16, 0x09, 0x4c, 0x04, 0x80, 0x8a, 0x06, 0xab, 0xa4, 0x0c, 0x17, + 0x04, 0x31, 0xa1, 0x04, 0x81, 0xda, 0x26, 0x07, 0x0c, 0x05, 0x05, 0x80, + 0xa5, 0x11, 0x81, 0x6d, 0x10, 0x78, 0x28, 0x2a, 0x06, 0x4c, 0x04, 0x80, + 0x8d, 0x04, 0x80, 0xbe, 0x03, 0x1b, 0x03, 0x0f, 0x0d, + }; + static constexpr unsigned char normal1[] = { + 0x5e, 0x22, 0x7b, 0x05, 0x03, 0x04, 0x2d, 0x03, 0x66, 0x03, 0x01, 0x2f, + 0x2e, 0x80, 0x82, 0x1d, 0x03, 0x31, 0x0f, 0x1c, 0x04, 0x24, 0x09, 0x1e, + 0x05, 0x2b, 0x05, 0x44, 0x04, 0x0e, 0x2a, 0x80, 0xaa, 0x06, 0x24, 0x04, + 0x24, 0x04, 0x28, 0x08, 0x34, 0x0b, 0x01, 0x80, 0x90, 0x81, 0x37, 0x09, + 0x16, 0x0a, 0x08, 0x80, 0x98, 0x39, 0x03, 0x63, 0x08, 0x09, 0x30, 0x16, + 0x05, 0x21, 0x03, 0x1b, 0x05, 0x01, 0x40, 0x38, 0x04, 0x4b, 0x05, 0x2f, + 0x04, 0x0a, 0x07, 0x09, 0x07, 0x40, 0x20, 0x27, 0x04, 0x0c, 0x09, 0x36, + 0x03, 0x3a, 0x05, 0x1a, 0x07, 0x04, 0x0c, 0x07, 0x50, 0x49, 0x37, 0x33, + 0x0d, 0x33, 0x07, 0x2e, 0x08, 0x0a, 0x81, 0x26, 0x52, 0x4e, 0x28, 0x08, + 0x2a, 0x56, 0x1c, 0x14, 0x17, 0x09, 0x4e, 0x04, 0x1e, 0x0f, 0x43, 0x0e, + 0x19, 0x07, 0x0a, 0x06, 0x48, 0x08, 0x27, 0x09, 0x75, 0x0b, 0x3f, 0x41, + 0x2a, 0x06, 0x3b, 0x05, 0x0a, 0x06, 0x51, 0x06, 0x01, 0x05, 0x10, 0x03, + 0x05, 0x80, 0x8b, 0x62, 0x1e, 0x48, 0x08, 0x0a, 0x80, 0xa6, 0x5e, 0x22, + 0x45, 0x0b, 0x0a, 0x06, 0x0d, 0x13, 0x39, 0x07, 0x0a, 0x36, 0x2c, 0x04, + 0x10, 0x80, 0xc0, 0x3c, 0x64, 0x53, 0x0c, 0x48, 0x09, 0x0a, 0x46, 0x45, + 0x1b, 0x48, 0x08, 0x53, 0x1d, 0x39, 0x81, 0x07, 0x46, 0x0a, 0x1d, 0x03, + 0x47, 0x49, 0x37, 0x03, 0x0e, 0x08, 0x0a, 0x06, 0x39, 0x07, 0x0a, 0x81, + 0x36, 0x19, 0x80, 0xb7, 0x01, 0x0f, 0x32, 0x0d, 0x83, 0x9b, 0x66, 0x75, + 0x0b, 0x80, 0xc4, 0x8a, 0xbc, 0x84, 0x2f, 0x8f, 0xd1, 0x82, 0x47, 0xa1, + 0xb9, 0x82, 0x39, 0x07, 0x2a, 0x04, 0x02, 0x60, 0x26, 0x0a, 0x46, 0x0a, + 0x28, 0x05, 0x13, 0x82, 0xb0, 0x5b, 0x65, 0x4b, 0x04, 0x39, 0x07, 0x11, + 0x40, 0x05, 0x0b, 0x02, 0x0e, 0x97, 0xf8, 0x08, 0x84, 0xd6, 0x2a, 0x09, + 0xa2, 0xf7, 0x81, 0x1f, 0x31, 0x03, 0x11, 0x04, 0x08, 0x81, 0x8c, 0x89, + 0x04, 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, 0x10, 0x93, 0x60, 0x80, 0xf6, + 0x0a, 0x73, 0x08, 0x6e, 0x17, 0x46, 0x80, 0x9a, 0x14, 0x0c, 0x57, 0x09, + 0x19, 0x80, 0x87, 0x81, 0x47, 0x03, 0x85, 0x42, 0x0f, 0x15, 0x85, 0x50, + 0x2b, 0x80, 0xd5, 0x2d, 0x03, 0x1a, 0x04, 0x02, 0x81, 0x70, 0x3a, 0x05, + 0x01, 0x85, 0x00, 0x80, 0xd7, 0x29, 0x4c, 0x04, 0x0a, 0x04, 0x02, 0x83, + 0x11, 0x44, 0x4c, 0x3d, 0x80, 0xc2, 0x3c, 0x06, 0x01, 0x04, 0x55, 0x05, + 0x1b, 0x34, 0x02, 0x81, 0x0e, 0x2c, 0x04, 0x64, 0x0c, 0x56, 0x0a, 0x80, + 0xae, 0x38, 0x1d, 0x0d, 0x2c, 0x04, 0x09, 0x07, 0x02, 0x0e, 0x06, 0x80, + 0x9a, 0x83, 0xd8, 0x08, 0x0d, 0x03, 0x0d, 0x03, 0x74, 0x0c, 0x59, 0x07, + 0x0c, 0x14, 0x0c, 0x04, 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, 0x22, 0x4e, + 0x81, 0x54, 0x0c, 0x15, 0x03, 0x03, 0x05, 0x07, 0x09, 0x19, 0x07, 0x07, + 0x09, 0x03, 0x0d, 0x07, 0x29, 0x80, 0xcb, 0x25, 0x0a, 0x84, 0x06, + }; + auto lower = static_cast(cp); + if (cp < 0x10000) { + return is_printable(lower, singletons0, + sizeof(singletons0) / sizeof(*singletons0), + singletons0_lower, normal0, sizeof(normal0)); + } + if (cp < 0x20000) { + return is_printable(lower, singletons1, + sizeof(singletons1) / sizeof(*singletons1), + singletons1_lower, normal1, sizeof(normal1)); + } + if (0x2a6de <= cp && cp < 0x2a700) return false; + if (0x2b735 <= cp && cp < 0x2b740) return false; + if (0x2b81e <= cp && cp < 0x2b820) return false; + if (0x2cea2 <= cp && cp < 0x2ceb0) return false; + if (0x2ebe1 <= cp && cp < 0x2f800) return false; + if (0x2fa1e <= cp && cp < 0x30000) return false; + if (0x3134b <= cp && cp < 0xe0100) return false; + if (0xe01f0 <= cp && cp < 0x110000) return false; + return cp < 0x110000; +} + +} // namespace detail + +FMT_END_NAMESPACE + +#endif // FMT_FORMAT_INL_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/format.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/format.h new file mode 100644 index 0000000..67f0ab7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/format.h @@ -0,0 +1,4427 @@ +/* + Formatting library for C++ + + Copyright (c) 2012 - present, Victor Zverovich + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + --- Optional exception to the license --- + + As an exception, if, as a result of your compiling your source code, portions + of this Software are embedded into a machine-executable object form of such + source code, you may redistribute such embedded portions in such object form + without including the above copyright and permission notices. + */ + +#ifndef FMT_FORMAT_H_ +#define FMT_FORMAT_H_ + +#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES +# define _LIBCPP_REMOVE_TRANSITIVE_INCLUDES +# define FMT_REMOVE_TRANSITIVE_INCLUDES +#endif + +#include "base.h" + +#ifndef FMT_MODULE +# include // std::signbit +# include // uint32_t +# include // std::memcpy +# include // std::initializer_list +# include // std::numeric_limits +# if defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI) +// Workaround for pre gcc 5 libstdc++. +# include // std::allocator_traits +# endif +# include // std::runtime_error +# include // std::string +# include // std::system_error + +// Checking FMT_CPLUSPLUS for warning suppression in MSVC. +# if FMT_HAS_INCLUDE() && FMT_CPLUSPLUS > 201703L +# include // std::bit_cast +# endif + +// libc++ supports string_view in pre-c++17. +# if FMT_HAS_INCLUDE() && \ + (FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION)) +# include +# define FMT_USE_STRING_VIEW +# endif +#endif // FMT_MODULE + +#if defined __cpp_inline_variables && __cpp_inline_variables >= 201606L +# define FMT_INLINE_VARIABLE inline +#else +# define FMT_INLINE_VARIABLE +#endif + +#ifndef FMT_NO_UNIQUE_ADDRESS +# if FMT_CPLUSPLUS >= 202002L +# if FMT_HAS_CPP_ATTRIBUTE(no_unique_address) +# define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]] +// VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485). +# elif (FMT_MSC_VERSION >= 1929) && !FMT_CLANG_VERSION +# define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] +# endif +# endif +#endif +#ifndef FMT_NO_UNIQUE_ADDRESS +# define FMT_NO_UNIQUE_ADDRESS +#endif + +// Visibility when compiled as a shared library/object. +#if defined(FMT_LIB_EXPORT) || defined(FMT_SHARED) +# define FMT_SO_VISIBILITY(value) FMT_VISIBILITY(value) +#else +# define FMT_SO_VISIBILITY(value) +#endif + +#ifdef __has_builtin +# define FMT_HAS_BUILTIN(x) __has_builtin(x) +#else +# define FMT_HAS_BUILTIN(x) 0 +#endif + +#if FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_NOINLINE __attribute__((noinline)) +#else +# define FMT_NOINLINE +#endif + +namespace std { +template <> struct iterator_traits { + using iterator_category = output_iterator_tag; + using value_type = char; +}; +} // namespace std + +#ifndef FMT_THROW +# if FMT_EXCEPTIONS +# if FMT_MSC_VERSION || defined(__NVCC__) +FMT_BEGIN_NAMESPACE +namespace detail { +template inline void do_throw(const Exception& x) { + // Silence unreachable code warnings in MSVC and NVCC because these + // are nearly impossible to fix in a generic code. + volatile bool b = true; + if (b) throw x; +} +} // namespace detail +FMT_END_NAMESPACE +# define FMT_THROW(x) detail::do_throw(x) +# else +# define FMT_THROW(x) throw x +# endif +# else +# define FMT_THROW(x) \ + ::fmt::detail::assert_fail(__FILE__, __LINE__, (x).what()) +# endif +#endif + +#ifndef FMT_MAYBE_UNUSED +# if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused) +# define FMT_MAYBE_UNUSED [[maybe_unused]] +# else +# define FMT_MAYBE_UNUSED +# endif +#endif + +#ifndef FMT_USE_USER_DEFINED_LITERALS +// EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs. +// +// GCC before 4.9 requires a space in `operator"" _a` which is invalid in later +// compiler versions. +# if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 409 || \ + FMT_MSC_VERSION >= 1900) && \ + (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480) +# define FMT_USE_USER_DEFINED_LITERALS 1 +# else +# define FMT_USE_USER_DEFINED_LITERALS 0 +# endif +#endif + +// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of +// integer formatter template instantiations to just one by only using the +// largest integer type. This results in a reduction in binary size but will +// cause a decrease in integer formatting performance. +#if !defined(FMT_REDUCE_INT_INSTANTIATIONS) +# define FMT_REDUCE_INT_INSTANTIATIONS 0 +#endif + +// __builtin_clz is broken in clang with Microsoft CodeGen: +// https://github.com/fmtlib/fmt/issues/519. +#if !FMT_MSC_VERSION +# if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION +# define FMT_BUILTIN_CLZ(n) __builtin_clz(n) +# endif +# if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION +# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) +# endif +#endif + +// __builtin_ctz is broken in Intel Compiler Classic on Windows: +// https://github.com/fmtlib/fmt/issues/2510. +#ifndef __ICL +# if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \ + defined(__NVCOMPILER) +# define FMT_BUILTIN_CTZ(n) __builtin_ctz(n) +# endif +# if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || \ + FMT_ICC_VERSION || defined(__NVCOMPILER) +# define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n) +# endif +#endif + +#if FMT_MSC_VERSION +# include // _BitScanReverse[64], _BitScanForward[64], _umul128 +#endif + +// Some compilers masquerade as both MSVC and GCC-likes or otherwise support +// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the +// MSVC intrinsics if the clz and clzll builtins are not available. +#if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \ + !defined(FMT_BUILTIN_CTZLL) +FMT_BEGIN_NAMESPACE +namespace detail { +// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning. +# if !defined(__clang__) +# pragma intrinsic(_BitScanForward) +# pragma intrinsic(_BitScanReverse) +# if defined(_WIN64) +# pragma intrinsic(_BitScanForward64) +# pragma intrinsic(_BitScanReverse64) +# endif +# endif + +inline auto clz(uint32_t x) -> int { + unsigned long r = 0; + _BitScanReverse(&r, x); + FMT_ASSERT(x != 0, ""); + // Static analysis complains about using uninitialized data + // "r", but the only way that can happen is if "x" is 0, + // which the callers guarantee to not happen. + FMT_MSC_WARNING(suppress : 6102) + return 31 ^ static_cast(r); +} +# define FMT_BUILTIN_CLZ(n) detail::clz(n) + +inline auto clzll(uint64_t x) -> int { + unsigned long r = 0; +# ifdef _WIN64 + _BitScanReverse64(&r, x); +# else + // Scan the high 32 bits. + if (_BitScanReverse(&r, static_cast(x >> 32))) + return 63 ^ static_cast(r + 32); + // Scan the low 32 bits. + _BitScanReverse(&r, static_cast(x)); +# endif + FMT_ASSERT(x != 0, ""); + FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. + return 63 ^ static_cast(r); +} +# define FMT_BUILTIN_CLZLL(n) detail::clzll(n) + +inline auto ctz(uint32_t x) -> int { + unsigned long r = 0; + _BitScanForward(&r, x); + FMT_ASSERT(x != 0, ""); + FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. + return static_cast(r); +} +# define FMT_BUILTIN_CTZ(n) detail::ctz(n) + +inline auto ctzll(uint64_t x) -> int { + unsigned long r = 0; + FMT_ASSERT(x != 0, ""); + FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. +# ifdef _WIN64 + _BitScanForward64(&r, x); +# else + // Scan the low 32 bits. + if (_BitScanForward(&r, static_cast(x))) return static_cast(r); + // Scan the high 32 bits. + _BitScanForward(&r, static_cast(x >> 32)); + r += 32; +# endif + return static_cast(r); +} +# define FMT_BUILTIN_CTZLL(n) detail::ctzll(n) +} // namespace detail +FMT_END_NAMESPACE +#endif + +FMT_BEGIN_NAMESPACE + +template +struct is_contiguous> + : std::true_type {}; + +namespace detail { + +FMT_CONSTEXPR inline void abort_fuzzing_if(bool condition) { + ignore_unused(condition); +#ifdef FMT_FUZZ + if (condition) throw std::runtime_error("fuzzing limit reached"); +#endif +} + +#if defined(FMT_USE_STRING_VIEW) +template using std_string_view = std::basic_string_view; +#else +template struct std_string_view {}; +#endif + +// Implementation of std::bit_cast for pre-C++20. +template +FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To { +#ifdef __cpp_lib_bit_cast + if (is_constant_evaluated()) return std::bit_cast(from); +#endif + auto to = To(); + // The cast suppresses a bogus -Wclass-memaccess on GCC. + std::memcpy(static_cast(&to), &from, sizeof(to)); + return to; +} + +inline auto is_big_endian() -> bool { +#ifdef _WIN32 + return false; +#elif defined(__BIG_ENDIAN__) + return true; +#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) + return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; +#else + struct bytes { + char data[sizeof(int)]; + }; + return bit_cast(1).data[0] == 0; +#endif +} + +class uint128_fallback { + private: + uint64_t lo_, hi_; + + public: + constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {} + constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {} + + constexpr auto high() const noexcept -> uint64_t { return hi_; } + constexpr auto low() const noexcept -> uint64_t { return lo_; } + + template ::value)> + constexpr explicit operator T() const { + return static_cast(lo_); + } + + friend constexpr auto operator==(const uint128_fallback& lhs, + const uint128_fallback& rhs) -> bool { + return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_; + } + friend constexpr auto operator!=(const uint128_fallback& lhs, + const uint128_fallback& rhs) -> bool { + return !(lhs == rhs); + } + friend constexpr auto operator>(const uint128_fallback& lhs, + const uint128_fallback& rhs) -> bool { + return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_; + } + friend constexpr auto operator|(const uint128_fallback& lhs, + const uint128_fallback& rhs) + -> uint128_fallback { + return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_}; + } + friend constexpr auto operator&(const uint128_fallback& lhs, + const uint128_fallback& rhs) + -> uint128_fallback { + return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_}; + } + friend constexpr auto operator~(const uint128_fallback& n) + -> uint128_fallback { + return {~n.hi_, ~n.lo_}; + } + friend auto operator+(const uint128_fallback& lhs, + const uint128_fallback& rhs) -> uint128_fallback { + auto result = uint128_fallback(lhs); + result += rhs; + return result; + } + friend auto operator*(const uint128_fallback& lhs, uint32_t rhs) + -> uint128_fallback { + FMT_ASSERT(lhs.hi_ == 0, ""); + uint64_t hi = (lhs.lo_ >> 32) * rhs; + uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs; + uint64_t new_lo = (hi << 32) + lo; + return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo}; + } + friend auto operator-(const uint128_fallback& lhs, uint64_t rhs) + -> uint128_fallback { + return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs}; + } + FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback { + if (shift == 64) return {0, hi_}; + if (shift > 64) return uint128_fallback(0, hi_) >> (shift - 64); + return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)}; + } + FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback { + if (shift == 64) return {lo_, 0}; + if (shift > 64) return uint128_fallback(lo_, 0) << (shift - 64); + return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)}; + } + FMT_CONSTEXPR auto operator>>=(int shift) -> uint128_fallback& { + return *this = *this >> shift; + } + FMT_CONSTEXPR void operator+=(uint128_fallback n) { + uint64_t new_lo = lo_ + n.lo_; + uint64_t new_hi = hi_ + n.hi_ + (new_lo < lo_ ? 1 : 0); + FMT_ASSERT(new_hi >= hi_, ""); + lo_ = new_lo; + hi_ = new_hi; + } + FMT_CONSTEXPR void operator&=(uint128_fallback n) { + lo_ &= n.lo_; + hi_ &= n.hi_; + } + + FMT_CONSTEXPR20 auto operator+=(uint64_t n) noexcept -> uint128_fallback& { + if (is_constant_evaluated()) { + lo_ += n; + hi_ += (lo_ < n ? 1 : 0); + return *this; + } +#if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__) + unsigned long long carry; + lo_ = __builtin_addcll(lo_, n, 0, &carry); + hi_ += carry; +#elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__) + unsigned long long result; + auto carry = __builtin_ia32_addcarryx_u64(0, lo_, n, &result); + lo_ = result; + hi_ += carry; +#elif defined(_MSC_VER) && defined(_M_X64) + auto carry = _addcarry_u64(0, lo_, n, &lo_); + _addcarry_u64(carry, hi_, 0, &hi_); +#else + lo_ += n; + hi_ += (lo_ < n ? 1 : 0); +#endif + return *this; + } +}; + +using uint128_t = conditional_t; + +#ifdef UINTPTR_MAX +using uintptr_t = ::uintptr_t; +#else +using uintptr_t = uint128_t; +#endif + +// Returns the largest possible value for type T. Same as +// std::numeric_limits::max() but shorter and not affected by the max macro. +template constexpr auto max_value() -> T { + return (std::numeric_limits::max)(); +} +template constexpr auto num_bits() -> int { + return std::numeric_limits::digits; +} +// std::numeric_limits::digits may return 0 for 128-bit ints. +template <> constexpr auto num_bits() -> int { return 128; } +template <> constexpr auto num_bits() -> int { return 128; } +template <> constexpr auto num_bits() -> int { return 128; } + +// A heterogeneous bit_cast used for converting 96-bit long double to uint128_t +// and 128-bit pointers to uint128_fallback. +template sizeof(From))> +inline auto bit_cast(const From& from) -> To { + constexpr auto size = static_cast(sizeof(From) / sizeof(unsigned)); + struct data_t { + unsigned value[static_cast(size)]; + } data = bit_cast(from); + auto result = To(); + if (const_check(is_big_endian())) { + for (int i = 0; i < size; ++i) + result = (result << num_bits()) | data.value[i]; + } else { + for (int i = size - 1; i >= 0; --i) + result = (result << num_bits()) | data.value[i]; + } + return result; +} + +template +FMT_CONSTEXPR20 inline auto countl_zero_fallback(UInt n) -> int { + int lz = 0; + constexpr UInt msb_mask = static_cast(1) << (num_bits() - 1); + for (; (n & msb_mask) == 0; n <<= 1) lz++; + return lz; +} + +FMT_CONSTEXPR20 inline auto countl_zero(uint32_t n) -> int { +#ifdef FMT_BUILTIN_CLZ + if (!is_constant_evaluated()) return FMT_BUILTIN_CLZ(n); +#endif + return countl_zero_fallback(n); +} + +FMT_CONSTEXPR20 inline auto countl_zero(uint64_t n) -> int { +#ifdef FMT_BUILTIN_CLZLL + if (!is_constant_evaluated()) return FMT_BUILTIN_CLZLL(n); +#endif + return countl_zero_fallback(n); +} + +FMT_INLINE void assume(bool condition) { + (void)condition; +#if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION + __builtin_assume(condition); +#elif FMT_GCC_VERSION + if (!condition) __builtin_unreachable(); +#endif +} + +// An approximation of iterator_t for pre-C++20 systems. +template +using iterator_t = decltype(std::begin(std::declval())); +template using sentinel_t = decltype(std::end(std::declval())); + +// A workaround for std::string not having mutable data() until C++17. +template +inline auto get_data(std::basic_string& s) -> Char* { + return &s[0]; +} +template +inline auto get_data(Container& c) -> typename Container::value_type* { + return c.data(); +} + +// Attempts to reserve space for n extra characters in the output range. +// Returns a pointer to the reserved range or a reference to it. +template ::value&& + is_contiguous::value)> +#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION +__attribute__((no_sanitize("undefined"))) +#endif +inline auto +reserve(OutputIt it, size_t n) -> typename OutputIt::value_type* { + auto& c = get_container(it); + size_t size = c.size(); + c.resize(size + n); + return get_data(c) + size; +} + +template +inline auto reserve(basic_appender it, size_t n) -> basic_appender { + buffer& buf = get_container(it); + buf.try_reserve(buf.size() + n); + return it; +} + +template +constexpr auto reserve(Iterator& it, size_t) -> Iterator& { + return it; +} + +template +using reserve_iterator = + remove_reference_t(), 0))>; + +template +constexpr auto to_pointer(OutputIt, size_t) -> T* { + return nullptr; +} +template auto to_pointer(basic_appender it, size_t n) -> T* { + buffer& buf = get_container(it); + auto size = buf.size(); + buf.try_reserve(size + n); + if (buf.capacity() < size + n) return nullptr; + buf.try_resize(size + n); + return buf.data() + size; +} + +template ::value&& + is_contiguous::value)> +inline auto base_iterator(OutputIt it, + typename OutputIt::container_type::value_type*) + -> OutputIt { + return it; +} + +template +constexpr auto base_iterator(Iterator, Iterator it) -> Iterator { + return it; +} + +// is spectacularly slow to compile in C++20 so use a simple fill_n +// instead (#1998). +template +FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T& value) + -> OutputIt { + for (Size i = 0; i < count; ++i) *out++ = value; + return out; +} +template +FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* { + if (is_constant_evaluated()) { + return fill_n(out, count, value); + } + std::memset(out, value, to_unsigned(count)); + return out + count; +} + +template +FMT_CONSTEXPR FMT_NOINLINE auto copy_noinline(InputIt begin, InputIt end, + OutputIt out) -> OutputIt { + return copy(begin, end, out); +} + +// A public domain branchless UTF-8 decoder by Christopher Wellons: +// https://github.com/skeeto/branchless-utf8 +/* Decode the next character, c, from s, reporting errors in e. + * + * Since this is a branchless decoder, four bytes will be read from the + * buffer regardless of the actual length of the next character. This + * means the buffer _must_ have at least three bytes of zero padding + * following the end of the data stream. + * + * Errors are reported in e, which will be non-zero if the parsed + * character was somehow invalid: invalid byte sequence, non-canonical + * encoding, or a surrogate half. + * + * The function returns a pointer to the next character. When an error + * occurs, this pointer will be a guess that depends on the particular + * error, but it will always advance at least one byte. + */ +FMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e) + -> const char* { + constexpr const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07}; + constexpr const uint32_t mins[] = {4194304, 0, 128, 2048, 65536}; + constexpr const int shiftc[] = {0, 18, 12, 6, 0}; + constexpr const int shifte[] = {0, 6, 4, 2, 0}; + + int len = "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4" + [static_cast(*s) >> 3]; + // Compute the pointer to the next character early so that the next + // iteration can start working on the next character. Neither Clang + // nor GCC figure out this reordering on their own. + const char* next = s + len + !len; + + using uchar = unsigned char; + + // Assume a four-byte character and load four bytes. Unused bits are + // shifted out. + *c = uint32_t(uchar(s[0]) & masks[len]) << 18; + *c |= uint32_t(uchar(s[1]) & 0x3f) << 12; + *c |= uint32_t(uchar(s[2]) & 0x3f) << 6; + *c |= uint32_t(uchar(s[3]) & 0x3f) << 0; + *c >>= shiftc[len]; + + // Accumulate the various error conditions. + *e = (*c < mins[len]) << 6; // non-canonical encoding + *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half? + *e |= (*c > 0x10FFFF) << 8; // out of range? + *e |= (uchar(s[1]) & 0xc0) >> 2; + *e |= (uchar(s[2]) & 0xc0) >> 4; + *e |= uchar(s[3]) >> 6; + *e ^= 0x2a; // top two bits of each tail byte correct? + *e >>= shifte[len]; + + return next; +} + +constexpr FMT_INLINE_VARIABLE uint32_t invalid_code_point = ~uint32_t(); + +// Invokes f(cp, sv) for every code point cp in s with sv being the string view +// corresponding to the code point. cp is invalid_code_point on error. +template +FMT_CONSTEXPR void for_each_codepoint(string_view s, F f) { + auto decode = [f](const char* buf_ptr, const char* ptr) { + auto cp = uint32_t(); + auto error = 0; + auto end = utf8_decode(buf_ptr, &cp, &error); + bool result = f(error ? invalid_code_point : cp, + string_view(ptr, error ? 1 : to_unsigned(end - buf_ptr))); + return result ? (error ? buf_ptr + 1 : end) : nullptr; + }; + auto p = s.data(); + const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars. + if (s.size() >= block_size) { + for (auto end = p + s.size() - block_size + 1; p < end;) { + p = decode(p, p); + if (!p) return; + } + } + if (auto num_chars_left = s.data() + s.size() - p) { + char buf[2 * block_size - 1] = {}; + copy(p, p + num_chars_left, buf); + const char* buf_ptr = buf; + do { + auto end = decode(buf_ptr, p); + if (!end) return; + p += end - buf_ptr; + buf_ptr = end; + } while (buf_ptr - buf < num_chars_left); + } +} + +template +inline auto compute_width(basic_string_view s) -> size_t { + return s.size(); +} + +// Computes approximate display width of a UTF-8 string. +FMT_CONSTEXPR inline auto compute_width(string_view s) -> size_t { + size_t num_code_points = 0; + // It is not a lambda for compatibility with C++14. + struct count_code_points { + size_t* count; + FMT_CONSTEXPR auto operator()(uint32_t cp, string_view) const -> bool { + *count += detail::to_unsigned( + 1 + + (cp >= 0x1100 && + (cp <= 0x115f || // Hangul Jamo init. consonants + cp == 0x2329 || // LEFT-POINTING ANGLE BRACKET + cp == 0x232a || // RIGHT-POINTING ANGLE BRACKET + // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE: + (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) || + (cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables + (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs + (cp >= 0xfe10 && cp <= 0xfe19) || // Vertical Forms + (cp >= 0xfe30 && cp <= 0xfe6f) || // CJK Compatibility Forms + (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms + (cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Forms + (cp >= 0x20000 && cp <= 0x2fffd) || // CJK + (cp >= 0x30000 && cp <= 0x3fffd) || + // Miscellaneous Symbols and Pictographs + Emoticons: + (cp >= 0x1f300 && cp <= 0x1f64f) || + // Supplemental Symbols and Pictographs: + (cp >= 0x1f900 && cp <= 0x1f9ff)))); + return true; + } + }; + // We could avoid branches by using utf8_decode directly. + for_each_codepoint(s, count_code_points{&num_code_points}); + return num_code_points; +} + +template +inline auto code_point_index(basic_string_view s, size_t n) -> size_t { + size_t size = s.size(); + return n < size ? n : size; +} + +// Calculates the index of the nth code point in a UTF-8 string. +inline auto code_point_index(string_view s, size_t n) -> size_t { + size_t result = s.size(); + const char* begin = s.begin(); + for_each_codepoint(s, [begin, &n, &result](uint32_t, string_view sv) { + if (n != 0) { + --n; + return true; + } + result = to_unsigned(sv.begin() - begin); + return false; + }); + return result; +} + +template struct is_integral : std::is_integral {}; +template <> struct is_integral : std::true_type {}; +template <> struct is_integral : std::true_type {}; + +template +using is_signed = + std::integral_constant::is_signed || + std::is_same::value>; + +template +using is_integer = + bool_constant::value && !std::is_same::value && + !std::is_same::value && + !std::is_same::value>; + +#ifndef FMT_USE_FLOAT +# define FMT_USE_FLOAT 1 +#endif +#ifndef FMT_USE_DOUBLE +# define FMT_USE_DOUBLE 1 +#endif +#ifndef FMT_USE_LONG_DOUBLE +# define FMT_USE_LONG_DOUBLE 1 +#endif + +#if defined(FMT_USE_FLOAT128) +// Use the provided definition. +#elif FMT_CLANG_VERSION && FMT_HAS_INCLUDE() +# define FMT_USE_FLOAT128 1 +#elif FMT_GCC_VERSION && defined(_GLIBCXX_USE_FLOAT128) && \ + !defined(__STRICT_ANSI__) +# define FMT_USE_FLOAT128 1 +#else +# define FMT_USE_FLOAT128 0 +#endif +#if FMT_USE_FLOAT128 +using float128 = __float128; +#else +using float128 = void; +#endif + +template using is_float128 = std::is_same; + +template +using is_floating_point = + bool_constant::value || is_float128::value>; + +template ::value> +struct is_fast_float : bool_constant::is_iec559 && + sizeof(T) <= sizeof(double)> {}; +template struct is_fast_float : std::false_type {}; + +template +using is_double_double = bool_constant::digits == 106>; + +#ifndef FMT_USE_FULL_CACHE_DRAGONBOX +# define FMT_USE_FULL_CACHE_DRAGONBOX 0 +#endif + +template +struct is_locale : std::false_type {}; +template +struct is_locale> : std::true_type {}; +} // namespace detail + +FMT_BEGIN_EXPORT + +// The number of characters to store in the basic_memory_buffer object itself +// to avoid dynamic memory allocation. +enum { inline_buffer_size = 500 }; + +/** + * A dynamically growing memory buffer for trivially copyable/constructible + * types with the first `SIZE` elements stored in the object itself. Most + * commonly used via the `memory_buffer` alias for `char`. + * + * **Example**: + * + * auto out = fmt::memory_buffer(); + * fmt::format_to(std::back_inserter(out), "The answer is {}.", 42); + * + * This will append "The answer is 42." to `out`. The buffer content can be + * converted to `std::string` with `to_string(out)`. + */ +template > +class basic_memory_buffer : public detail::buffer { + private: + T store_[SIZE]; + + // Don't inherit from Allocator to avoid generating type_info for it. + FMT_NO_UNIQUE_ADDRESS Allocator alloc_; + + // Deallocate memory allocated by the buffer. + FMT_CONSTEXPR20 void deallocate() { + T* data = this->data(); + if (data != store_) alloc_.deallocate(data, this->capacity()); + } + + static FMT_CONSTEXPR20 void grow(detail::buffer& buf, size_t size) { + detail::abort_fuzzing_if(size > 5000); + auto& self = static_cast(buf); + const size_t max_size = + std::allocator_traits::max_size(self.alloc_); + size_t old_capacity = buf.capacity(); + size_t new_capacity = old_capacity + old_capacity / 2; + if (size > new_capacity) + new_capacity = size; + else if (new_capacity > max_size) + new_capacity = size > max_size ? size : max_size; + T* old_data = buf.data(); + T* new_data = self.alloc_.allocate(new_capacity); + // Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481). + detail::assume(buf.size() <= new_capacity); + // The following code doesn't throw, so the raw pointer above doesn't leak. + memcpy(new_data, old_data, buf.size() * sizeof(T)); + self.set(new_data, new_capacity); + // deallocate must not throw according to the standard, but even if it does, + // the buffer already uses the new storage and will deallocate it in + // destructor. + if (old_data != self.store_) self.alloc_.deallocate(old_data, old_capacity); + } + + public: + using value_type = T; + using const_reference = const T&; + + FMT_CONSTEXPR20 explicit basic_memory_buffer( + const Allocator& alloc = Allocator()) + : detail::buffer(grow), alloc_(alloc) { + this->set(store_, SIZE); + if (detail::is_constant_evaluated()) detail::fill_n(store_, SIZE, T()); + } + FMT_CONSTEXPR20 ~basic_memory_buffer() { deallocate(); } + + private: + // Move data from other to this buffer. + FMT_CONSTEXPR20 void move(basic_memory_buffer& other) { + alloc_ = std::move(other.alloc_); + T* data = other.data(); + size_t size = other.size(), capacity = other.capacity(); + if (data == other.store_) { + this->set(store_, capacity); + detail::copy(other.store_, other.store_ + size, store_); + } else { + this->set(data, capacity); + // Set pointer to the inline array so that delete is not called + // when deallocating. + other.set(other.store_, 0); + other.clear(); + } + this->resize(size); + } + + public: + /// Constructs a `basic_memory_buffer` object moving the content of the other + /// object to it. + FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other) noexcept + : detail::buffer(grow) { + move(other); + } + + /// Moves the content of the other `basic_memory_buffer` object to this one. + auto operator=(basic_memory_buffer&& other) noexcept -> basic_memory_buffer& { + FMT_ASSERT(this != &other, ""); + deallocate(); + move(other); + return *this; + } + + // Returns a copy of the allocator associated with this buffer. + auto get_allocator() const -> Allocator { return alloc_; } + + /// Resizes the buffer to contain `count` elements. If T is a POD type new + /// elements may not be initialized. + FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); } + + /// Increases the buffer capacity to `new_capacity`. + void reserve(size_t new_capacity) { this->try_reserve(new_capacity); } + + using detail::buffer::append; + template + void append(const ContiguousRange& range) { + append(range.data(), range.data() + range.size()); + } +}; + +using memory_buffer = basic_memory_buffer; + +template +struct is_contiguous> : std::true_type { +}; + +FMT_END_EXPORT +namespace detail { +FMT_API auto write_console(int fd, string_view text) -> bool; +FMT_API void print(std::FILE*, string_view); +} // namespace detail + +FMT_BEGIN_EXPORT + +// Suppress a misleading warning in older versions of clang. +#if FMT_CLANG_VERSION +# pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +/// An error reported from a formatting function. +class FMT_SO_VISIBILITY("default") format_error : public std::runtime_error { + public: + using std::runtime_error::runtime_error; +}; + +namespace detail_exported { +#if FMT_USE_NONTYPE_TEMPLATE_ARGS +template struct fixed_string { + constexpr fixed_string(const Char (&str)[N]) { + detail::copy(static_cast(str), + str + N, data); + } + Char data[N] = {}; +}; +#endif + +// Converts a compile-time string to basic_string_view. +template +constexpr auto compile_string_to_view(const Char (&s)[N]) + -> basic_string_view { + // Remove trailing NUL character if needed. Won't be present if this is used + // with a raw character array (i.e. not defined as a string). + return {s, N - (std::char_traits::to_int_type(s[N - 1]) == 0 ? 1 : 0)}; +} +template +constexpr auto compile_string_to_view(basic_string_view s) + -> basic_string_view { + return s; +} +} // namespace detail_exported + +// A generic formatting context with custom output iterator and character +// (code unit) support. Char is the format string code unit type which can be +// different from OutputIt::value_type. +template class generic_context { + private: + OutputIt out_; + basic_format_args args_; + detail::locale_ref loc_; + + public: + using char_type = Char; + using iterator = OutputIt; + using parse_context_type = basic_format_parse_context; + template using formatter_type = formatter; + + constexpr generic_context(OutputIt out, + basic_format_args ctx_args, + detail::locale_ref loc = {}) + : out_(out), args_(ctx_args), loc_(loc) {} + generic_context(generic_context&&) = default; + generic_context(const generic_context&) = delete; + void operator=(const generic_context&) = delete; + + constexpr auto arg(int id) const -> basic_format_arg { + return args_.get(id); + } + auto arg(basic_string_view name) -> basic_format_arg { + return args_.get(name); + } + FMT_CONSTEXPR auto arg_id(basic_string_view name) -> int { + return args_.get_id(name); + } + auto args() const -> const basic_format_args& { + return args_; + } + + FMT_CONSTEXPR auto out() -> iterator { return out_; } + + void advance_to(iterator it) { + if (!detail::is_back_insert_iterator()) out_ = it; + } + + FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; } +}; + +class loc_value { + private: + basic_format_arg value_; + + public: + template ::value)> + loc_value(T value) : value_(detail::make_arg(value)) {} + + template ::value)> + loc_value(T) {} + + template auto visit(Visitor&& vis) -> decltype(vis(0)) { + return value_.visit(vis); + } +}; + +// A locale facet that formats values in UTF-8. +// It is parameterized on the locale to avoid the heavy include. +template class format_facet : public Locale::facet { + private: + std::string separator_; + std::string grouping_; + std::string decimal_point_; + + protected: + virtual auto do_put(appender out, loc_value val, + const format_specs& specs) const -> bool; + + public: + static FMT_API typename Locale::id id; + + explicit format_facet(Locale& loc); + explicit format_facet(string_view sep = "", + std::initializer_list g = {3}, + std::string decimal_point = ".") + : separator_(sep.data(), sep.size()), + grouping_(g.begin(), g.end()), + decimal_point_(decimal_point) {} + + auto put(appender out, loc_value val, const format_specs& specs) const + -> bool { + return do_put(out, val, specs); + } +}; + +FMT_END_EXPORT + +namespace detail { + +// Returns true if value is negative, false otherwise. +// Same as `value < 0` but doesn't produce warnings if T is an unsigned type. +template ::value)> +constexpr auto is_negative(T value) -> bool { + return value < 0; +} +template ::value)> +constexpr auto is_negative(T) -> bool { + return false; +} + +template +FMT_CONSTEXPR auto is_supported_floating_point(T) -> bool { + if (std::is_same()) return FMT_USE_FLOAT; + if (std::is_same()) return FMT_USE_DOUBLE; + if (std::is_same()) return FMT_USE_LONG_DOUBLE; + return true; +} + +// Smallest of uint32_t, uint64_t, uint128_t that is large enough to +// represent all values of an integral type T. +template +using uint32_or_64_or_128_t = + conditional_t() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS, + uint32_t, + conditional_t() <= 64, uint64_t, uint128_t>>; +template +using uint64_or_128_t = conditional_t() <= 64, uint64_t, uint128_t>; + +#define FMT_POWERS_OF_10(factor) \ + factor * 10, (factor) * 100, (factor) * 1000, (factor) * 10000, \ + (factor) * 100000, (factor) * 1000000, (factor) * 10000000, \ + (factor) * 100000000, (factor) * 1000000000 + +// Converts value in the range [0, 100) to a string. +constexpr auto digits2(size_t value) -> const char* { + // GCC generates slightly better code when value is pointer-size. + return &"0001020304050607080910111213141516171819" + "2021222324252627282930313233343536373839" + "4041424344454647484950515253545556575859" + "6061626364656667686970717273747576777879" + "8081828384858687888990919293949596979899"[value * 2]; +} + +// Sign is a template parameter to workaround a bug in gcc 4.8. +template constexpr auto sign(Sign s) -> Char { +#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604 + static_assert(std::is_same::value, ""); +#endif + return static_cast(((' ' << 24) | ('+' << 16) | ('-' << 8)) >> (s * 8)); +} + +template FMT_CONSTEXPR auto count_digits_fallback(T n) -> int { + int count = 1; + for (;;) { + // Integer division is slow so do it for a group of four digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + if (n < 10) return count; + if (n < 100) return count + 1; + if (n < 1000) return count + 2; + if (n < 10000) return count + 3; + n /= 10000u; + count += 4; + } +} +#if FMT_USE_INT128 +FMT_CONSTEXPR inline auto count_digits(uint128_opt n) -> int { + return count_digits_fallback(n); +} +#endif + +#ifdef FMT_BUILTIN_CLZLL +// It is a separate function rather than a part of count_digits to workaround +// the lack of static constexpr in constexpr functions. +inline auto do_count_digits(uint64_t n) -> int { + // This has comparable performance to the version by Kendall Willets + // (https://github.com/fmtlib/format-benchmark/blob/master/digits10) + // but uses smaller tables. + // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)). + static constexpr uint8_t bsr2log10[] = { + 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, + 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, + 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, + 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20}; + auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63]; + static constexpr const uint64_t zero_or_powers_of_10[] = { + 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL), + 10000000000000000000ULL}; + return t - (n < zero_or_powers_of_10[t]); +} +#endif + +// Returns the number of decimal digits in n. Leading zeros are not counted +// except for n == 0 in which case count_digits returns 1. +FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int { +#ifdef FMT_BUILTIN_CLZLL + if (!is_constant_evaluated()) return do_count_digits(n); +#endif + return count_digits_fallback(n); +} + +// Counts the number of digits in n. BITS = log2(radix). +template +FMT_CONSTEXPR auto count_digits(UInt n) -> int { +#ifdef FMT_BUILTIN_CLZ + if (!is_constant_evaluated() && num_bits() == 32) + return (FMT_BUILTIN_CLZ(static_cast(n) | 1) ^ 31) / BITS + 1; +#endif + // Lambda avoids unreachable code warnings from NVHPC. + return [](UInt m) { + int num_digits = 0; + do { + ++num_digits; + } while ((m >>= BITS) != 0); + return num_digits; + }(n); +} + +#ifdef FMT_BUILTIN_CLZ +// It is a separate function rather than a part of count_digits to workaround +// the lack of static constexpr in constexpr functions. +FMT_INLINE auto do_count_digits(uint32_t n) -> int { +// An optimization by Kendall Willets from https://bit.ly/3uOIQrB. +// This increments the upper 32 bits (log10(T) - 1) when >= T is added. +# define FMT_INC(T) (((sizeof(#T) - 1ull) << 32) - T) + static constexpr uint64_t table[] = { + FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8 + FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64 + FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512 + FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096 + FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k + FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k + FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k + FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M + FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M + FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M + FMT_INC(1000000000), FMT_INC(1000000000) // 4B + }; + auto inc = table[FMT_BUILTIN_CLZ(n | 1) ^ 31]; + return static_cast((n + inc) >> 32); +} +#endif + +// Optional version of count_digits for better performance on 32-bit platforms. +FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int { +#ifdef FMT_BUILTIN_CLZ + if (!is_constant_evaluated()) { + return do_count_digits(n); + } +#endif + return count_digits_fallback(n); +} + +template constexpr auto digits10() noexcept -> int { + return std::numeric_limits::digits10; +} +template <> constexpr auto digits10() noexcept -> int { return 38; } +template <> constexpr auto digits10() noexcept -> int { return 38; } + +template struct thousands_sep_result { + std::string grouping; + Char thousands_sep; +}; + +template +FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result; +template +inline auto thousands_sep(locale_ref loc) -> thousands_sep_result { + auto result = thousands_sep_impl(loc); + return {result.grouping, Char(result.thousands_sep)}; +} +template <> +inline auto thousands_sep(locale_ref loc) -> thousands_sep_result { + return thousands_sep_impl(loc); +} + +template +FMT_API auto decimal_point_impl(locale_ref loc) -> Char; +template inline auto decimal_point(locale_ref loc) -> Char { + return Char(decimal_point_impl(loc)); +} +template <> inline auto decimal_point(locale_ref loc) -> wchar_t { + return decimal_point_impl(loc); +} + +// Compares two characters for equality. +template auto equal2(const Char* lhs, const char* rhs) -> bool { + return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]); +} +inline auto equal2(const char* lhs, const char* rhs) -> bool { + return memcmp(lhs, rhs, 2) == 0; +} + +// Copies two characters from src to dst. +template +FMT_CONSTEXPR20 FMT_INLINE void copy2(Char* dst, const char* src) { + if (!is_constant_evaluated() && sizeof(Char) == sizeof(char)) { + memcpy(dst, src, 2); + return; + } + *dst++ = static_cast(*src++); + *dst = static_cast(*src); +} + +template struct format_decimal_result { + Iterator begin; + Iterator end; +}; + +// Formats a decimal unsigned integer value writing into out pointing to a +// buffer of specified size. The caller must ensure that the buffer is large +// enough. +template +FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size) + -> format_decimal_result { + FMT_ASSERT(size >= count_digits(value), "invalid digit count"); + out += size; + Char* end = out; + while (value >= 100) { + // Integer division is slow so do it for a group of two digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + out -= 2; + copy2(out, digits2(static_cast(value % 100))); + value /= 100; + } + if (value < 10) { + *--out = static_cast('0' + value); + return {out, end}; + } + out -= 2; + copy2(out, digits2(static_cast(value))); + return {out, end}; +} + +template >::value)> +FMT_CONSTEXPR inline auto format_decimal(Iterator out, UInt value, int size) + -> format_decimal_result { + // Buffer is large enough to hold all digits (digits10 + 1). + Char buffer[digits10() + 1] = {}; + auto end = format_decimal(buffer, value, size).end; + return {out, detail::copy_noinline(buffer, end, out)}; +} + +template +FMT_CONSTEXPR auto format_uint(Char* buffer, UInt value, int num_digits, + bool upper = false) -> Char* { + buffer += num_digits; + Char* end = buffer; + do { + const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef"; + unsigned digit = static_cast(value & ((1 << BASE_BITS) - 1)); + *--buffer = static_cast(BASE_BITS < 4 ? static_cast('0' + digit) + : digits[digit]); + } while ((value >>= BASE_BITS) != 0); + return end; +} + +template +FMT_CONSTEXPR inline auto format_uint(It out, UInt value, int num_digits, + bool upper = false) -> It { + if (auto ptr = to_pointer(out, to_unsigned(num_digits))) { + format_uint(ptr, value, num_digits, upper); + return out; + } + // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1). + char buffer[num_bits() / BASE_BITS + 1] = {}; + format_uint(buffer, value, num_digits, upper); + return detail::copy_noinline(buffer, buffer + num_digits, out); +} + +// A converter from UTF-8 to UTF-16. +class utf8_to_utf16 { + private: + basic_memory_buffer buffer_; + + public: + FMT_API explicit utf8_to_utf16(string_view s); + operator basic_string_view() const { return {&buffer_[0], size()}; } + auto size() const -> size_t { return buffer_.size() - 1; } + auto c_str() const -> const wchar_t* { return &buffer_[0]; } + auto str() const -> std::wstring { return {&buffer_[0], size()}; } +}; + +enum class to_utf8_error_policy { abort, replace }; + +// A converter from UTF-16/UTF-32 (host endian) to UTF-8. +template class to_utf8 { + private: + Buffer buffer_; + + public: + to_utf8() {} + explicit to_utf8(basic_string_view s, + to_utf8_error_policy policy = to_utf8_error_policy::abort) { + static_assert(sizeof(WChar) == 2 || sizeof(WChar) == 4, + "Expect utf16 or utf32"); + if (!convert(s, policy)) + FMT_THROW(std::runtime_error(sizeof(WChar) == 2 ? "invalid utf16" + : "invalid utf32")); + } + operator string_view() const { return string_view(&buffer_[0], size()); } + auto size() const -> size_t { return buffer_.size() - 1; } + auto c_str() const -> const char* { return &buffer_[0]; } + auto str() const -> std::string { return std::string(&buffer_[0], size()); } + + // Performs conversion returning a bool instead of throwing exception on + // conversion error. This method may still throw in case of memory allocation + // error. + auto convert(basic_string_view s, + to_utf8_error_policy policy = to_utf8_error_policy::abort) + -> bool { + if (!convert(buffer_, s, policy)) return false; + buffer_.push_back(0); + return true; + } + static auto convert(Buffer& buf, basic_string_view s, + to_utf8_error_policy policy = to_utf8_error_policy::abort) + -> bool { + for (auto p = s.begin(); p != s.end(); ++p) { + uint32_t c = static_cast(*p); + if (sizeof(WChar) == 2 && c >= 0xd800 && c <= 0xdfff) { + // Handle a surrogate pair. + ++p; + if (p == s.end() || (c & 0xfc00) != 0xd800 || (*p & 0xfc00) != 0xdc00) { + if (policy == to_utf8_error_policy::abort) return false; + buf.append(string_view("\xEF\xBF\xBD")); + --p; + } else { + c = (c << 10) + static_cast(*p) - 0x35fdc00; + } + } else if (c < 0x80) { + buf.push_back(static_cast(c)); + } else if (c < 0x800) { + buf.push_back(static_cast(0xc0 | (c >> 6))); + buf.push_back(static_cast(0x80 | (c & 0x3f))); + } else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) { + buf.push_back(static_cast(0xe0 | (c >> 12))); + buf.push_back(static_cast(0x80 | ((c & 0xfff) >> 6))); + buf.push_back(static_cast(0x80 | (c & 0x3f))); + } else if (c >= 0x10000 && c <= 0x10ffff) { + buf.push_back(static_cast(0xf0 | (c >> 18))); + buf.push_back(static_cast(0x80 | ((c & 0x3ffff) >> 12))); + buf.push_back(static_cast(0x80 | ((c & 0xfff) >> 6))); + buf.push_back(static_cast(0x80 | (c & 0x3f))); + } else { + return false; + } + } + return true; + } +}; + +// Computes 128-bit result of multiplication of two 64-bit unsigned integers. +inline auto umul128(uint64_t x, uint64_t y) noexcept -> uint128_fallback { +#if FMT_USE_INT128 + auto p = static_cast(x) * static_cast(y); + return {static_cast(p >> 64), static_cast(p)}; +#elif defined(_MSC_VER) && defined(_M_X64) + auto hi = uint64_t(); + auto lo = _umul128(x, y, &hi); + return {hi, lo}; +#else + const uint64_t mask = static_cast(max_value()); + + uint64_t a = x >> 32; + uint64_t b = x & mask; + uint64_t c = y >> 32; + uint64_t d = y & mask; + + uint64_t ac = a * c; + uint64_t bc = b * c; + uint64_t ad = a * d; + uint64_t bd = b * d; + + uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask); + + return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32), + (intermediate << 32) + (bd & mask)}; +#endif +} + +namespace dragonbox { +// Computes floor(log10(pow(2, e))) for e in [-2620, 2620] using the method from +// https://fmt.dev/papers/Dragonbox.pdf#page=28, section 6.1. +inline auto floor_log10_pow2(int e) noexcept -> int { + FMT_ASSERT(e <= 2620 && e >= -2620, "too large exponent"); + static_assert((-1 >> 1) == -1, "right shift is not arithmetic"); + return (e * 315653) >> 20; +} + +inline auto floor_log2_pow10(int e) noexcept -> int { + FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent"); + return (e * 1741647) >> 19; +} + +// Computes upper 64 bits of multiplication of two 64-bit unsigned integers. +inline auto umul128_upper64(uint64_t x, uint64_t y) noexcept -> uint64_t { +#if FMT_USE_INT128 + auto p = static_cast(x) * static_cast(y); + return static_cast(p >> 64); +#elif defined(_MSC_VER) && defined(_M_X64) + return __umulh(x, y); +#else + return umul128(x, y).high(); +#endif +} + +// Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a +// 128-bit unsigned integer. +inline auto umul192_upper128(uint64_t x, uint128_fallback y) noexcept + -> uint128_fallback { + uint128_fallback r = umul128(x, y.high()); + r += umul128_upper64(x, y.low()); + return r; +} + +FMT_API auto get_cached_power(int k) noexcept -> uint128_fallback; + +// Type-specific information that Dragonbox uses. +template struct float_info; + +template <> struct float_info { + using carrier_uint = uint32_t; + static const int exponent_bits = 8; + static const int kappa = 1; + static const int big_divisor = 100; + static const int small_divisor = 10; + static const int min_k = -31; + static const int max_k = 46; + static const int shorter_interval_tie_lower_threshold = -35; + static const int shorter_interval_tie_upper_threshold = -35; +}; + +template <> struct float_info { + using carrier_uint = uint64_t; + static const int exponent_bits = 11; + static const int kappa = 2; + static const int big_divisor = 1000; + static const int small_divisor = 100; + static const int min_k = -292; + static const int max_k = 341; + static const int shorter_interval_tie_lower_threshold = -77; + static const int shorter_interval_tie_upper_threshold = -77; +}; + +// An 80- or 128-bit floating point number. +template +struct float_info::digits == 64 || + std::numeric_limits::digits == 113 || + is_float128::value>> { + using carrier_uint = detail::uint128_t; + static const int exponent_bits = 15; +}; + +// A double-double floating point number. +template +struct float_info::value>> { + using carrier_uint = detail::uint128_t; +}; + +template struct decimal_fp { + using significand_type = typename float_info::carrier_uint; + significand_type significand; + int exponent; +}; + +template FMT_API auto to_decimal(T x) noexcept -> decimal_fp; +} // namespace dragonbox + +// Returns true iff Float has the implicit bit which is not stored. +template constexpr auto has_implicit_bit() -> bool { + // An 80-bit FP number has a 64-bit significand an no implicit bit. + return std::numeric_limits::digits != 64; +} + +// Returns the number of significand bits stored in Float. The implicit bit is +// not counted since it is not stored. +template constexpr auto num_significand_bits() -> int { + // std::numeric_limits may not support __float128. + return is_float128() ? 112 + : (std::numeric_limits::digits - + (has_implicit_bit() ? 1 : 0)); +} + +template +constexpr auto exponent_mask() -> + typename dragonbox::float_info::carrier_uint { + using float_uint = typename dragonbox::float_info::carrier_uint; + return ((float_uint(1) << dragonbox::float_info::exponent_bits) - 1) + << num_significand_bits(); +} +template constexpr auto exponent_bias() -> int { + // std::numeric_limits may not support __float128. + return is_float128() ? 16383 + : std::numeric_limits::max_exponent - 1; +} + +// Writes the exponent exp in the form "[+-]d{2,3}" to buffer. +template +FMT_CONSTEXPR auto write_exponent(int exp, It it) -> It { + FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range"); + if (exp < 0) { + *it++ = static_cast('-'); + exp = -exp; + } else { + *it++ = static_cast('+'); + } + if (exp >= 100) { + const char* top = digits2(to_unsigned(exp / 100)); + if (exp >= 1000) *it++ = static_cast(top[0]); + *it++ = static_cast(top[1]); + exp %= 100; + } + const char* d = digits2(to_unsigned(exp)); + *it++ = static_cast(d[0]); + *it++ = static_cast(d[1]); + return it; +} + +// A floating-point number f * pow(2, e) where F is an unsigned type. +template struct basic_fp { + F f; + int e; + + static constexpr const int num_significand_bits = + static_cast(sizeof(F) * num_bits()); + + constexpr basic_fp() : f(0), e(0) {} + constexpr basic_fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {} + + // Constructs fp from an IEEE754 floating-point number. + template FMT_CONSTEXPR basic_fp(Float n) { assign(n); } + + // Assigns n to this and return true iff predecessor is closer than successor. + template ::value)> + FMT_CONSTEXPR auto assign(Float n) -> bool { + static_assert(std::numeric_limits::digits <= 113, "unsupported FP"); + // Assume Float is in the format [sign][exponent][significand]. + using carrier_uint = typename dragonbox::float_info::carrier_uint; + const auto num_float_significand_bits = + detail::num_significand_bits(); + const auto implicit_bit = carrier_uint(1) << num_float_significand_bits; + const auto significand_mask = implicit_bit - 1; + auto u = bit_cast(n); + f = static_cast(u & significand_mask); + auto biased_e = static_cast((u & exponent_mask()) >> + num_float_significand_bits); + // The predecessor is closer if n is a normalized power of 2 (f == 0) + // other than the smallest normalized number (biased_e > 1). + auto is_predecessor_closer = f == 0 && biased_e > 1; + if (biased_e == 0) + biased_e = 1; // Subnormals use biased exponent 1 (min exponent). + else if (has_implicit_bit()) + f += static_cast(implicit_bit); + e = biased_e - exponent_bias() - num_float_significand_bits; + if (!has_implicit_bit()) ++e; + return is_predecessor_closer; + } + + template ::value)> + FMT_CONSTEXPR auto assign(Float n) -> bool { + static_assert(std::numeric_limits::is_iec559, "unsupported FP"); + return assign(static_cast(n)); + } +}; + +using fp = basic_fp; + +// Normalizes the value converted from double and multiplied by (1 << SHIFT). +template +FMT_CONSTEXPR auto normalize(basic_fp value) -> basic_fp { + // Handle subnormals. + const auto implicit_bit = F(1) << num_significand_bits(); + const auto shifted_implicit_bit = implicit_bit << SHIFT; + while ((value.f & shifted_implicit_bit) == 0) { + value.f <<= 1; + --value.e; + } + // Subtract 1 to account for hidden bit. + const auto offset = basic_fp::num_significand_bits - + num_significand_bits() - SHIFT - 1; + value.f <<= offset; + value.e -= offset; + return value; +} + +// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking. +FMT_CONSTEXPR inline auto multiply(uint64_t lhs, uint64_t rhs) -> uint64_t { +#if FMT_USE_INT128 + auto product = static_cast<__uint128_t>(lhs) * rhs; + auto f = static_cast(product >> 64); + return (static_cast(product) & (1ULL << 63)) != 0 ? f + 1 : f; +#else + // Multiply 32-bit parts of significands. + uint64_t mask = (1ULL << 32) - 1; + uint64_t a = lhs >> 32, b = lhs & mask; + uint64_t c = rhs >> 32, d = rhs & mask; + uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d; + // Compute mid 64-bit of result and round. + uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31); + return ac + (ad >> 32) + (bc >> 32) + (mid >> 32); +#endif +} + +FMT_CONSTEXPR inline auto operator*(fp x, fp y) -> fp { + return {multiply(x.f, y.f), x.e + y.e + 64}; +} + +template () == num_bits()> +using convert_float_result = + conditional_t::value || doublish, double, T>; + +template +constexpr auto convert_float(T value) -> convert_float_result { + return static_cast>(value); +} + +template +FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, const fill_t& fill) + -> OutputIt { + auto fill_size = fill.size(); + if (fill_size == 1) return detail::fill_n(it, n, fill.template get()); + if (const Char* data = fill.template data()) { + for (size_t i = 0; i < n; ++i) it = copy(data, data + fill_size, it); + } + return it; +} + +// Writes the output of f, padded according to format specifications in specs. +// size: output size in code units. +// width: output display width in (terminal) column positions. +template +FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs& specs, + size_t size, size_t width, F&& f) -> OutputIt { + static_assert(align == align::left || align == align::right, ""); + unsigned spec_width = to_unsigned(specs.width); + size_t padding = spec_width > width ? spec_width - width : 0; + // Shifts are encoded as string literals because static constexpr is not + // supported in constexpr functions. + auto* shifts = align == align::left ? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01"; + size_t left_padding = padding >> shifts[specs.align]; + size_t right_padding = padding - left_padding; + auto it = reserve(out, size + padding * specs.fill.size()); + if (left_padding != 0) it = fill(it, left_padding, specs.fill); + it = f(it); + if (right_padding != 0) it = fill(it, right_padding, specs.fill); + return base_iterator(out, it); +} + +template +constexpr auto write_padded(OutputIt out, const format_specs& specs, + size_t size, F&& f) -> OutputIt { + return write_padded(out, specs, size, size, f); +} + +template +FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes, + const format_specs& specs = {}) -> OutputIt { + return write_padded( + out, specs, bytes.size(), [bytes](reserve_iterator it) { + const char* data = bytes.data(); + return copy(data, data + bytes.size(), it); + }); +} + +template +auto write_ptr(OutputIt out, UIntPtr value, const format_specs* specs) + -> OutputIt { + int num_digits = count_digits<4>(value); + auto size = to_unsigned(num_digits) + size_t(2); + auto write = [=](reserve_iterator it) { + *it++ = static_cast('0'); + *it++ = static_cast('x'); + return format_uint<4, Char>(it, value, num_digits); + }; + return specs ? write_padded(out, *specs, size, write) + : base_iterator(out, write(reserve(out, size))); +} + +// Returns true iff the code point cp is printable. +FMT_API auto is_printable(uint32_t cp) -> bool; + +inline auto needs_escape(uint32_t cp) -> bool { + return cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\' || + !is_printable(cp); +} + +template struct find_escape_result { + const Char* begin; + const Char* end; + uint32_t cp; +}; + +template +auto find_escape(const Char* begin, const Char* end) + -> find_escape_result { + for (; begin != end; ++begin) { + uint32_t cp = static_cast>(*begin); + if (const_check(sizeof(Char) == 1) && cp >= 0x80) continue; + if (needs_escape(cp)) return {begin, begin + 1, cp}; + } + return {begin, nullptr, 0}; +} + +inline auto find_escape(const char* begin, const char* end) + -> find_escape_result { + if (!use_utf8()) return find_escape(begin, end); + auto result = find_escape_result{end, nullptr, 0}; + for_each_codepoint(string_view(begin, to_unsigned(end - begin)), + [&](uint32_t cp, string_view sv) { + if (needs_escape(cp)) { + result = {sv.begin(), sv.end(), cp}; + return false; + } + return true; + }); + return result; +} + +#define FMT_STRING_IMPL(s, base, explicit) \ + [] { \ + /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \ + /* Use a macro-like name to avoid shadowing warnings. */ \ + struct FMT_VISIBILITY("hidden") FMT_COMPILE_STRING : base { \ + using char_type FMT_MAYBE_UNUSED = fmt::remove_cvref_t; \ + FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \ + operator fmt::basic_string_view() const { \ + return fmt::detail_exported::compile_string_to_view(s); \ + } \ + }; \ + return FMT_COMPILE_STRING(); \ + }() + +/** + * Constructs a compile-time format string from a string literal `s`. + * + * **Example**: + * + * // A compile-time error because 'd' is an invalid specifier for strings. + * std::string s = fmt::format(FMT_STRING("{:d}"), "foo"); + */ +#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, ) + +template +auto write_codepoint(OutputIt out, char prefix, uint32_t cp) -> OutputIt { + *out++ = static_cast('\\'); + *out++ = static_cast(prefix); + Char buf[width]; + fill_n(buf, width, static_cast('0')); + format_uint<4>(buf, cp, width); + return copy(buf, buf + width, out); +} + +template +auto write_escaped_cp(OutputIt out, const find_escape_result& escape) + -> OutputIt { + auto c = static_cast(escape.cp); + switch (escape.cp) { + case '\n': + *out++ = static_cast('\\'); + c = static_cast('n'); + break; + case '\r': + *out++ = static_cast('\\'); + c = static_cast('r'); + break; + case '\t': + *out++ = static_cast('\\'); + c = static_cast('t'); + break; + case '"': + FMT_FALLTHROUGH; + case '\'': + FMT_FALLTHROUGH; + case '\\': + *out++ = static_cast('\\'); + break; + default: + if (escape.cp < 0x100) return write_codepoint<2, Char>(out, 'x', escape.cp); + if (escape.cp < 0x10000) + return write_codepoint<4, Char>(out, 'u', escape.cp); + if (escape.cp < 0x110000) + return write_codepoint<8, Char>(out, 'U', escape.cp); + for (Char escape_char : basic_string_view( + escape.begin, to_unsigned(escape.end - escape.begin))) { + out = write_codepoint<2, Char>(out, 'x', + static_cast(escape_char) & 0xFF); + } + return out; + } + *out++ = c; + return out; +} + +template +auto write_escaped_string(OutputIt out, basic_string_view str) + -> OutputIt { + *out++ = static_cast('"'); + auto begin = str.begin(), end = str.end(); + do { + auto escape = find_escape(begin, end); + out = copy(begin, escape.begin, out); + begin = escape.end; + if (!begin) break; + out = write_escaped_cp(out, escape); + } while (begin != end); + *out++ = static_cast('"'); + return out; +} + +template +auto write_escaped_char(OutputIt out, Char v) -> OutputIt { + Char v_array[1] = {v}; + *out++ = static_cast('\''); + if ((needs_escape(static_cast(v)) && v != static_cast('"')) || + v == static_cast('\'')) { + out = write_escaped_cp(out, + find_escape_result{v_array, v_array + 1, + static_cast(v)}); + } else { + *out++ = v; + } + *out++ = static_cast('\''); + return out; +} + +template +FMT_CONSTEXPR auto write_char(OutputIt out, Char value, + const format_specs& specs) -> OutputIt { + bool is_debug = specs.type == presentation_type::debug; + return write_padded(out, specs, 1, [=](reserve_iterator it) { + if (is_debug) return write_escaped_char(it, value); + *it++ = value; + return it; + }); +} +template +FMT_CONSTEXPR auto write(OutputIt out, Char value, const format_specs& specs, + locale_ref loc = {}) -> OutputIt { + // char is formatted as unsigned char for consistency across platforms. + using unsigned_type = + conditional_t::value, unsigned char, unsigned>; + return check_char_specs(specs) + ? write_char(out, value, specs) + : write(out, static_cast(value), specs, loc); +} + +// Data for write_int that doesn't depend on output iterator type. It is used to +// avoid template code bloat. +template struct write_int_data { + size_t size; + size_t padding; + + FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix, + const format_specs& specs) + : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) { + if (specs.align == align::numeric) { + auto width = to_unsigned(specs.width); + if (width > size) { + padding = width - size; + size = width; + } + } else if (specs.precision > num_digits) { + size = (prefix >> 24) + to_unsigned(specs.precision); + padding = to_unsigned(specs.precision - num_digits); + } + } +}; + +// Writes an integer in the format +// +// where are written by write_digits(it). +// prefix contains chars in three lower bytes and the size in the fourth byte. +template +FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits, + unsigned prefix, + const format_specs& specs, + W write_digits) -> OutputIt { + // Slightly faster check for specs.width == 0 && specs.precision == -1. + if ((specs.width | (specs.precision + 1)) == 0) { + auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24)); + if (prefix != 0) { + for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) + *it++ = static_cast(p & 0xff); + } + return base_iterator(out, write_digits(it)); + } + auto data = write_int_data(num_digits, prefix, specs); + return write_padded( + out, specs, data.size, [=](reserve_iterator it) { + for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) + *it++ = static_cast(p & 0xff); + it = detail::fill_n(it, data.padding, static_cast('0')); + return write_digits(it); + }); +} + +template class digit_grouping { + private: + std::string grouping_; + std::basic_string thousands_sep_; + + struct next_state { + std::string::const_iterator group; + int pos; + }; + auto initial_state() const -> next_state { return {grouping_.begin(), 0}; } + + // Returns the next digit group separator position. + auto next(next_state& state) const -> int { + if (thousands_sep_.empty()) return max_value(); + if (state.group == grouping_.end()) return state.pos += grouping_.back(); + if (*state.group <= 0 || *state.group == max_value()) + return max_value(); + state.pos += *state.group++; + return state.pos; + } + + public: + explicit digit_grouping(locale_ref loc, bool localized = true) { + if (!localized) return; + auto sep = thousands_sep(loc); + grouping_ = sep.grouping; + if (sep.thousands_sep) thousands_sep_.assign(1, sep.thousands_sep); + } + digit_grouping(std::string grouping, std::basic_string sep) + : grouping_(std::move(grouping)), thousands_sep_(std::move(sep)) {} + + auto has_separator() const -> bool { return !thousands_sep_.empty(); } + + auto count_separators(int num_digits) const -> int { + int count = 0; + auto state = initial_state(); + while (num_digits > next(state)) ++count; + return count; + } + + // Applies grouping to digits and write the output to out. + template + auto apply(Out out, basic_string_view digits) const -> Out { + auto num_digits = static_cast(digits.size()); + auto separators = basic_memory_buffer(); + separators.push_back(0); + auto state = initial_state(); + while (int i = next(state)) { + if (i >= num_digits) break; + separators.push_back(i); + } + for (int i = 0, sep_index = static_cast(separators.size() - 1); + i < num_digits; ++i) { + if (num_digits - i == separators[sep_index]) { + out = copy(thousands_sep_.data(), + thousands_sep_.data() + thousands_sep_.size(), out); + --sep_index; + } + *out++ = static_cast(digits[to_unsigned(i)]); + } + return out; + } +}; + +FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) { + prefix |= prefix != 0 ? value << 8 : value; + prefix += (1u + (value > 0xff ? 1 : 0)) << 24; +} + +// Writes a decimal integer with digit grouping. +template +auto write_int(OutputIt out, UInt value, unsigned prefix, + const format_specs& specs, const digit_grouping& grouping) + -> OutputIt { + static_assert(std::is_same, UInt>::value, ""); + int num_digits = 0; + auto buffer = memory_buffer(); + switch (specs.type) { + default: + FMT_ASSERT(false, ""); + FMT_FALLTHROUGH; + case presentation_type::none: + case presentation_type::dec: + num_digits = count_digits(value); + format_decimal(appender(buffer), value, num_digits); + break; + case presentation_type::hex: + if (specs.alt) + prefix_append(prefix, unsigned(specs.upper ? 'X' : 'x') << 8 | '0'); + num_digits = count_digits<4>(value); + format_uint<4, char>(appender(buffer), value, num_digits, specs.upper); + break; + case presentation_type::oct: + num_digits = count_digits<3>(value); + // Octal prefix '0' is counted as a digit, so only add it if precision + // is not greater than the number of digits. + if (specs.alt && specs.precision <= num_digits && value != 0) + prefix_append(prefix, '0'); + format_uint<3, char>(appender(buffer), value, num_digits); + break; + case presentation_type::bin: + if (specs.alt) + prefix_append(prefix, unsigned(specs.upper ? 'B' : 'b') << 8 | '0'); + num_digits = count_digits<1>(value); + format_uint<1, char>(appender(buffer), value, num_digits); + break; + case presentation_type::chr: + return write_char(out, static_cast(value), specs); + } + + unsigned size = (prefix != 0 ? prefix >> 24 : 0) + to_unsigned(num_digits) + + to_unsigned(grouping.count_separators(num_digits)); + return write_padded( + out, specs, size, size, [&](reserve_iterator it) { + for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) + *it++ = static_cast(p & 0xff); + return grouping.apply(it, string_view(buffer.data(), buffer.size())); + }); +} + +// Writes a localized value. +FMT_API auto write_loc(appender out, loc_value value, const format_specs& specs, + locale_ref loc) -> bool; +template +inline auto write_loc(OutputIt, loc_value, const format_specs&, locale_ref) + -> bool { + return false; +} + +template struct write_int_arg { + UInt abs_value; + unsigned prefix; +}; + +template +FMT_CONSTEXPR auto make_write_int_arg(T value, sign_t sign) + -> write_int_arg> { + auto prefix = 0u; + auto abs_value = static_cast>(value); + if (is_negative(value)) { + prefix = 0x01000000 | '-'; + abs_value = 0 - abs_value; + } else { + constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+', + 0x1000000u | ' '}; + prefix = prefixes[sign]; + } + return {abs_value, prefix}; +} + +template struct loc_writer { + basic_appender out; + const format_specs& specs; + std::basic_string sep; + std::string grouping; + std::basic_string decimal_point; + + template ::value)> + auto operator()(T value) -> bool { + auto arg = make_write_int_arg(value, specs.sign); + write_int(out, static_cast>(arg.abs_value), arg.prefix, + specs, digit_grouping(grouping, sep)); + return true; + } + + template ::value)> + auto operator()(T) -> bool { + return false; + } +}; + +template +FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg arg, + const format_specs& specs, locale_ref) + -> OutputIt { + static_assert(std::is_same>::value, ""); + auto abs_value = arg.abs_value; + auto prefix = arg.prefix; + switch (specs.type) { + default: + FMT_ASSERT(false, ""); + FMT_FALLTHROUGH; + case presentation_type::none: + case presentation_type::dec: { + int num_digits = count_digits(abs_value); + return write_int( + out, num_digits, prefix, specs, [=](reserve_iterator it) { + return format_decimal(it, abs_value, num_digits).end; + }); + } + case presentation_type::hex: { + if (specs.alt) + prefix_append(prefix, unsigned(specs.upper ? 'X' : 'x') << 8 | '0'); + int num_digits = count_digits<4>(abs_value); + return write_int( + out, num_digits, prefix, specs, [=](reserve_iterator it) { + return format_uint<4, Char>(it, abs_value, num_digits, specs.upper); + }); + } + case presentation_type::oct: { + int num_digits = count_digits<3>(abs_value); + // Octal prefix '0' is counted as a digit, so only add it if precision + // is not greater than the number of digits. + if (specs.alt && specs.precision <= num_digits && abs_value != 0) + prefix_append(prefix, '0'); + return write_int( + out, num_digits, prefix, specs, [=](reserve_iterator it) { + return format_uint<3, Char>(it, abs_value, num_digits); + }); + } + case presentation_type::bin: { + if (specs.alt) + prefix_append(prefix, unsigned(specs.upper ? 'B' : 'b') << 8 | '0'); + int num_digits = count_digits<1>(abs_value); + return write_int( + out, num_digits, prefix, specs, [=](reserve_iterator it) { + return format_uint<1, Char>(it, abs_value, num_digits); + }); + } + case presentation_type::chr: + return write_char(out, static_cast(abs_value), specs); + } +} +template +FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline(OutputIt out, + write_int_arg arg, + const format_specs& specs, + locale_ref loc) -> OutputIt { + return write_int(out, arg, specs, loc); +} +template ::value && + !std::is_same::value && + !std::is_same::value)> +FMT_CONSTEXPR FMT_INLINE auto write(basic_appender out, T value, + const format_specs& specs, locale_ref loc) + -> basic_appender { + if (specs.localized && write_loc(out, value, specs, loc)) return out; + return write_int_noinline(out, make_write_int_arg(value, specs.sign), + specs, loc); +} +// An inlined version of write used in format string compilation. +template ::value && + !std::is_same::value && + !std::is_same::value && + !std::is_same>::value)> +FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value, + const format_specs& specs, locale_ref loc) + -> OutputIt { + if (specs.localized && write_loc(out, value, specs, loc)) return out; + return write_int(out, make_write_int_arg(value, specs.sign), specs, + loc); +} + +// An output iterator that counts the number of objects written to it and +// discards them. +class counting_iterator { + private: + size_t count_; + + public: + using iterator_category = std::output_iterator_tag; + using difference_type = std::ptrdiff_t; + using pointer = void; + using reference = void; + FMT_UNCHECKED_ITERATOR(counting_iterator); + + struct value_type { + template FMT_CONSTEXPR void operator=(const T&) {} + }; + + FMT_CONSTEXPR counting_iterator() : count_(0) {} + + FMT_CONSTEXPR auto count() const -> size_t { return count_; } + + FMT_CONSTEXPR auto operator++() -> counting_iterator& { + ++count_; + return *this; + } + FMT_CONSTEXPR auto operator++(int) -> counting_iterator { + auto it = *this; + ++*this; + return it; + } + + FMT_CONSTEXPR friend auto operator+(counting_iterator it, difference_type n) + -> counting_iterator { + it.count_ += static_cast(n); + return it; + } + + FMT_CONSTEXPR auto operator*() const -> value_type { return {}; } +}; + +template +FMT_CONSTEXPR auto write(OutputIt out, basic_string_view s, + const format_specs& specs) -> OutputIt { + auto data = s.data(); + auto size = s.size(); + if (specs.precision >= 0 && to_unsigned(specs.precision) < size) + size = code_point_index(s, to_unsigned(specs.precision)); + bool is_debug = specs.type == presentation_type::debug; + size_t width = 0; + + if (is_debug) size = write_escaped_string(counting_iterator{}, s).count(); + + if (specs.width != 0) { + if (is_debug) + width = size; + else + width = compute_width(basic_string_view(data, size)); + } + return write_padded(out, specs, size, width, + [=](reserve_iterator it) { + if (is_debug) return write_escaped_string(it, s); + return copy(data, data + size, it); + }); +} +template +FMT_CONSTEXPR auto write(OutputIt out, + basic_string_view> s, + const format_specs& specs, locale_ref) -> OutputIt { + return write(out, s, specs); +} +template +FMT_CONSTEXPR auto write(OutputIt out, const Char* s, const format_specs& specs, + locale_ref) -> OutputIt { + if (specs.type == presentation_type::pointer) + return write_ptr(out, bit_cast(s), &specs); + if (!s) report_error("string pointer is null"); + return write(out, basic_string_view(s), specs, {}); +} + +template ::value && + !std::is_same::value && + !std::is_same::value)> +FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { + auto abs_value = static_cast>(value); + bool negative = is_negative(value); + // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer. + if (negative) abs_value = ~abs_value + 1; + int num_digits = count_digits(abs_value); + auto size = (negative ? 1 : 0) + static_cast(num_digits); + if (auto ptr = to_pointer(out, size)) { + if (negative) *ptr++ = static_cast('-'); + format_decimal(ptr, abs_value, num_digits); + return out; + } + if (negative) *out++ = static_cast('-'); + return format_decimal(out, abs_value, num_digits).end; +} + +// DEPRECATED! +template +FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end, + format_specs& specs) -> const Char* { + FMT_ASSERT(begin != end, ""); + auto align = align::none; + auto p = begin + code_point_length(begin); + if (end - p <= 0) p = begin; + for (;;) { + switch (to_ascii(*p)) { + case '<': + align = align::left; + break; + case '>': + align = align::right; + break; + case '^': + align = align::center; + break; + } + if (align != align::none) { + if (p != begin) { + auto c = *begin; + if (c == '}') return begin; + if (c == '{') { + report_error("invalid fill character '{'"); + return begin; + } + specs.fill = basic_string_view(begin, to_unsigned(p - begin)); + begin = p + 1; + } else { + ++begin; + } + break; + } else if (p == begin) { + break; + } + p = begin; + } + specs.align = align; + return begin; +} + +// A floating-point presentation format. +enum class float_format : unsigned char { + general, // General: exponent notation or fixed point based on magnitude. + exp, // Exponent notation with the default precision of 6, e.g. 1.2e-3. + fixed // Fixed point with the default precision of 6, e.g. 0.0012. +}; + +struct float_specs { + int precision; + float_format format : 8; + sign_t sign : 8; + bool locale : 1; + bool binary32 : 1; + bool showpoint : 1; +}; + +// DEPRECATED! +FMT_CONSTEXPR inline auto parse_float_type_spec(const format_specs& specs) + -> float_specs { + auto result = float_specs(); + result.showpoint = specs.alt; + result.locale = specs.localized; + switch (specs.type) { + default: + FMT_FALLTHROUGH; + case presentation_type::none: + result.format = float_format::general; + break; + case presentation_type::exp: + result.format = float_format::exp; + result.showpoint |= specs.precision != 0; + break; + case presentation_type::fixed: + result.format = float_format::fixed; + result.showpoint |= specs.precision != 0; + break; + case presentation_type::general: + result.format = float_format::general; + break; + } + return result; +} + +template +FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan, + format_specs specs, sign_t sign) + -> OutputIt { + auto str = + isnan ? (specs.upper ? "NAN" : "nan") : (specs.upper ? "INF" : "inf"); + constexpr size_t str_size = 3; + auto size = str_size + (sign ? 1 : 0); + // Replace '0'-padding with space for non-finite values. + const bool is_zero_fill = + specs.fill.size() == 1 && specs.fill.template get() == '0'; + if (is_zero_fill) specs.fill = ' '; + return write_padded(out, specs, size, + [=](reserve_iterator it) { + if (sign) *it++ = detail::sign(sign); + return copy(str, str + str_size, it); + }); +} + +// A decimal floating-point number significand * pow(10, exp). +struct big_decimal_fp { + const char* significand; + int significand_size; + int exponent; +}; + +constexpr auto get_significand_size(const big_decimal_fp& f) -> int { + return f.significand_size; +} +template +inline auto get_significand_size(const dragonbox::decimal_fp& f) -> int { + return count_digits(f.significand); +} + +template +constexpr auto write_significand(OutputIt out, const char* significand, + int significand_size) -> OutputIt { + return copy(significand, significand + significand_size, out); +} +template +inline auto write_significand(OutputIt out, UInt significand, + int significand_size) -> OutputIt { + return format_decimal(out, significand, significand_size).end; +} +template +FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, + int significand_size, int exponent, + const Grouping& grouping) -> OutputIt { + if (!grouping.has_separator()) { + out = write_significand(out, significand, significand_size); + return detail::fill_n(out, exponent, static_cast('0')); + } + auto buffer = memory_buffer(); + write_significand(appender(buffer), significand, significand_size); + detail::fill_n(appender(buffer), exponent, '0'); + return grouping.apply(out, string_view(buffer.data(), buffer.size())); +} + +template ::value)> +inline auto write_significand(Char* out, UInt significand, int significand_size, + int integral_size, Char decimal_point) -> Char* { + if (!decimal_point) + return format_decimal(out, significand, significand_size).end; + out += significand_size + 1; + Char* end = out; + int floating_size = significand_size - integral_size; + for (int i = floating_size / 2; i > 0; --i) { + out -= 2; + copy2(out, digits2(static_cast(significand % 100))); + significand /= 100; + } + if (floating_size % 2 != 0) { + *--out = static_cast('0' + significand % 10); + significand /= 10; + } + *--out = decimal_point; + format_decimal(out - integral_size, significand, integral_size); + return end; +} + +template >::value)> +inline auto write_significand(OutputIt out, UInt significand, + int significand_size, int integral_size, + Char decimal_point) -> OutputIt { + // Buffer is large enough to hold digits (digits10 + 1) and a decimal point. + Char buffer[digits10() + 2]; + auto end = write_significand(buffer, significand, significand_size, + integral_size, decimal_point); + return detail::copy_noinline(buffer, end, out); +} + +template +FMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand, + int significand_size, int integral_size, + Char decimal_point) -> OutputIt { + out = detail::copy_noinline(significand, significand + integral_size, + out); + if (!decimal_point) return out; + *out++ = decimal_point; + return detail::copy_noinline(significand + integral_size, + significand + significand_size, out); +} + +template +FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, + int significand_size, int integral_size, + Char decimal_point, + const Grouping& grouping) -> OutputIt { + if (!grouping.has_separator()) { + return write_significand(out, significand, significand_size, integral_size, + decimal_point); + } + auto buffer = basic_memory_buffer(); + write_significand(basic_appender(buffer), significand, significand_size, + integral_size, decimal_point); + grouping.apply( + out, basic_string_view(buffer.data(), to_unsigned(integral_size))); + return detail::copy_noinline(buffer.data() + integral_size, + buffer.end(), out); +} + +template > +FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f, + const format_specs& specs, + float_specs fspecs, locale_ref loc) + -> OutputIt { + auto significand = f.significand; + int significand_size = get_significand_size(f); + const Char zero = static_cast('0'); + auto sign = fspecs.sign; + size_t size = to_unsigned(significand_size) + (sign ? 1 : 0); + using iterator = reserve_iterator; + + Char decimal_point = + fspecs.locale ? detail::decimal_point(loc) : static_cast('.'); + + int output_exp = f.exponent + significand_size - 1; + auto use_exp_format = [=]() { + if (fspecs.format == float_format::exp) return true; + if (fspecs.format != float_format::general) return false; + // Use the fixed notation if the exponent is in [exp_lower, exp_upper), + // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation. + const int exp_lower = -4, exp_upper = 16; + return output_exp < exp_lower || + output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper); + }; + if (use_exp_format()) { + int num_zeros = 0; + if (fspecs.showpoint) { + num_zeros = fspecs.precision - significand_size; + if (num_zeros < 0) num_zeros = 0; + size += to_unsigned(num_zeros); + } else if (significand_size == 1) { + decimal_point = Char(); + } + auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp; + int exp_digits = 2; + if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3; + + size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits); + char exp_char = specs.upper ? 'E' : 'e'; + auto write = [=](iterator it) { + if (sign) *it++ = detail::sign(sign); + // Insert a decimal point after the first digit and add an exponent. + it = write_significand(it, significand, significand_size, 1, + decimal_point); + if (num_zeros > 0) it = detail::fill_n(it, num_zeros, zero); + *it++ = static_cast(exp_char); + return write_exponent(output_exp, it); + }; + return specs.width > 0 + ? write_padded(out, specs, size, write) + : base_iterator(out, write(reserve(out, size))); + } + + int exp = f.exponent + significand_size; + if (f.exponent >= 0) { + // 1234e5 -> 123400000[.0+] + size += to_unsigned(f.exponent); + int num_zeros = fspecs.precision - exp; + abort_fuzzing_if(num_zeros > 5000); + if (fspecs.showpoint) { + ++size; + if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 0; + if (num_zeros > 0) size += to_unsigned(num_zeros); + } + auto grouping = Grouping(loc, fspecs.locale); + size += to_unsigned(grouping.count_separators(exp)); + return write_padded(out, specs, size, [&](iterator it) { + if (sign) *it++ = detail::sign(sign); + it = write_significand(it, significand, significand_size, + f.exponent, grouping); + if (!fspecs.showpoint) return it; + *it++ = decimal_point; + return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it; + }); + } else if (exp > 0) { + // 1234e-2 -> 12.34[0+] + int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0; + size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0); + auto grouping = Grouping(loc, fspecs.locale); + size += to_unsigned(grouping.count_separators(exp)); + return write_padded(out, specs, size, [&](iterator it) { + if (sign) *it++ = detail::sign(sign); + it = write_significand(it, significand, significand_size, exp, + decimal_point, grouping); + return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it; + }); + } + // 1234e-6 -> 0.001234 + int num_zeros = -exp; + if (significand_size == 0 && fspecs.precision >= 0 && + fspecs.precision < num_zeros) { + num_zeros = fspecs.precision; + } + bool pointy = num_zeros != 0 || significand_size != 0 || fspecs.showpoint; + size += 1 + (pointy ? 1 : 0) + to_unsigned(num_zeros); + return write_padded(out, specs, size, [&](iterator it) { + if (sign) *it++ = detail::sign(sign); + *it++ = zero; + if (!pointy) return it; + *it++ = decimal_point; + it = detail::fill_n(it, num_zeros, zero); + return write_significand(it, significand, significand_size); + }); +} + +template class fallback_digit_grouping { + public: + constexpr fallback_digit_grouping(locale_ref, bool) {} + + constexpr auto has_separator() const -> bool { return false; } + + constexpr auto count_separators(int) const -> int { return 0; } + + template + constexpr auto apply(Out out, basic_string_view) const -> Out { + return out; + } +}; + +template +FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& f, + const format_specs& specs, float_specs fspecs, + locale_ref loc) -> OutputIt { + if (is_constant_evaluated()) { + return do_write_float>(out, f, specs, fspecs, + loc); + } else { + return do_write_float(out, f, specs, fspecs, loc); + } +} + +template constexpr auto isnan(T value) -> bool { + return value != value; // std::isnan doesn't support __float128. +} + +template +struct has_isfinite : std::false_type {}; + +template +struct has_isfinite> + : std::true_type {}; + +template ::value&& + has_isfinite::value)> +FMT_CONSTEXPR20 auto isfinite(T value) -> bool { + constexpr T inf = T(std::numeric_limits::infinity()); + if (is_constant_evaluated()) + return !detail::isnan(value) && value < inf && value > -inf; + return std::isfinite(value); +} +template ::value)> +FMT_CONSTEXPR auto isfinite(T value) -> bool { + T inf = T(std::numeric_limits::infinity()); + // std::isfinite doesn't support __float128. + return !detail::isnan(value) && value < inf && value > -inf; +} + +template ::value)> +FMT_INLINE FMT_CONSTEXPR bool signbit(T value) { + if (is_constant_evaluated()) { +#ifdef __cpp_if_constexpr + if constexpr (std::numeric_limits::is_iec559) { + auto bits = detail::bit_cast(static_cast(value)); + return (bits >> (num_bits() - 1)) != 0; + } +#endif + } + return std::signbit(static_cast(value)); +} + +inline FMT_CONSTEXPR20 void adjust_precision(int& precision, int exp10) { + // Adjust fixed precision by exponent because it is relative to decimal + // point. + if (exp10 > 0 && precision > max_value() - exp10) + FMT_THROW(format_error("number is too big")); + precision += exp10; +} + +class bigint { + private: + // A bigint is stored as an array of bigits (big digits), with bigit at index + // 0 being the least significant one. + using bigit = uint32_t; + using double_bigit = uint64_t; + enum { bigits_capacity = 32 }; + basic_memory_buffer bigits_; + int exp_; + + FMT_CONSTEXPR20 auto operator[](int index) const -> bigit { + return bigits_[to_unsigned(index)]; + } + FMT_CONSTEXPR20 auto operator[](int index) -> bigit& { + return bigits_[to_unsigned(index)]; + } + + static constexpr const int bigit_bits = num_bits(); + + friend struct formatter; + + FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) { + auto result = static_cast((*this)[index]) - other - borrow; + (*this)[index] = static_cast(result); + borrow = static_cast(result >> (bigit_bits * 2 - 1)); + } + + FMT_CONSTEXPR20 void remove_leading_zeros() { + int num_bigits = static_cast(bigits_.size()) - 1; + while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits; + bigits_.resize(to_unsigned(num_bigits + 1)); + } + + // Computes *this -= other assuming aligned bigints and *this >= other. + FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) { + FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints"); + FMT_ASSERT(compare(*this, other) >= 0, ""); + bigit borrow = 0; + int i = other.exp_ - exp_; + for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j) + subtract_bigits(i, other.bigits_[j], borrow); + while (borrow > 0) subtract_bigits(i, 0, borrow); + remove_leading_zeros(); + } + + FMT_CONSTEXPR20 void multiply(uint32_t value) { + const double_bigit wide_value = value; + bigit carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + double_bigit result = bigits_[i] * wide_value + carry; + bigits_[i] = static_cast(result); + carry = static_cast(result >> bigit_bits); + } + if (carry != 0) bigits_.push_back(carry); + } + + template ::value || + std::is_same::value)> + FMT_CONSTEXPR20 void multiply(UInt value) { + using half_uint = + conditional_t::value, uint64_t, uint32_t>; + const int shift = num_bits() - bigit_bits; + const UInt lower = static_cast(value); + const UInt upper = value >> num_bits(); + UInt carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + UInt result = lower * bigits_[i] + static_cast(carry); + carry = (upper * bigits_[i] << shift) + (result >> bigit_bits) + + (carry >> bigit_bits); + bigits_[i] = static_cast(result); + } + while (carry != 0) { + bigits_.push_back(static_cast(carry)); + carry >>= bigit_bits; + } + } + + template ::value || + std::is_same::value)> + FMT_CONSTEXPR20 void assign(UInt n) { + size_t num_bigits = 0; + do { + bigits_[num_bigits++] = static_cast(n); + n >>= bigit_bits; + } while (n != 0); + bigits_.resize(num_bigits); + exp_ = 0; + } + + public: + FMT_CONSTEXPR20 bigint() : exp_(0) {} + explicit bigint(uint64_t n) { assign(n); } + + bigint(const bigint&) = delete; + void operator=(const bigint&) = delete; + + FMT_CONSTEXPR20 void assign(const bigint& other) { + auto size = other.bigits_.size(); + bigits_.resize(size); + auto data = other.bigits_.data(); + copy(data, data + size, bigits_.data()); + exp_ = other.exp_; + } + + template FMT_CONSTEXPR20 void operator=(Int n) { + FMT_ASSERT(n > 0, ""); + assign(uint64_or_128_t(n)); + } + + FMT_CONSTEXPR20 auto num_bigits() const -> int { + return static_cast(bigits_.size()) + exp_; + } + + FMT_NOINLINE FMT_CONSTEXPR20 auto operator<<=(int shift) -> bigint& { + FMT_ASSERT(shift >= 0, ""); + exp_ += shift / bigit_bits; + shift %= bigit_bits; + if (shift == 0) return *this; + bigit carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + bigit c = bigits_[i] >> (bigit_bits - shift); + bigits_[i] = (bigits_[i] << shift) + carry; + carry = c; + } + if (carry != 0) bigits_.push_back(carry); + return *this; + } + + template + FMT_CONSTEXPR20 auto operator*=(Int value) -> bigint& { + FMT_ASSERT(value > 0, ""); + multiply(uint32_or_64_or_128_t(value)); + return *this; + } + + friend FMT_CONSTEXPR20 auto compare(const bigint& lhs, const bigint& rhs) + -> int { + int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits(); + if (num_lhs_bigits != num_rhs_bigits) + return num_lhs_bigits > num_rhs_bigits ? 1 : -1; + int i = static_cast(lhs.bigits_.size()) - 1; + int j = static_cast(rhs.bigits_.size()) - 1; + int end = i - j; + if (end < 0) end = 0; + for (; i >= end; --i, --j) { + bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j]; + if (lhs_bigit != rhs_bigit) return lhs_bigit > rhs_bigit ? 1 : -1; + } + if (i != j) return i > j ? 1 : -1; + return 0; + } + + // Returns compare(lhs1 + lhs2, rhs). + friend FMT_CONSTEXPR20 auto add_compare(const bigint& lhs1, + const bigint& lhs2, const bigint& rhs) + -> int { + auto minimum = [](int a, int b) { return a < b ? a : b; }; + auto maximum = [](int a, int b) { return a > b ? a : b; }; + int max_lhs_bigits = maximum(lhs1.num_bigits(), lhs2.num_bigits()); + int num_rhs_bigits = rhs.num_bigits(); + if (max_lhs_bigits + 1 < num_rhs_bigits) return -1; + if (max_lhs_bigits > num_rhs_bigits) return 1; + auto get_bigit = [](const bigint& n, int i) -> bigit { + return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0; + }; + double_bigit borrow = 0; + int min_exp = minimum(minimum(lhs1.exp_, lhs2.exp_), rhs.exp_); + for (int i = num_rhs_bigits - 1; i >= min_exp; --i) { + double_bigit sum = + static_cast(get_bigit(lhs1, i)) + get_bigit(lhs2, i); + bigit rhs_bigit = get_bigit(rhs, i); + if (sum > rhs_bigit + borrow) return 1; + borrow = rhs_bigit + borrow - sum; + if (borrow > 1) return -1; + borrow <<= bigit_bits; + } + return borrow != 0 ? -1 : 0; + } + + // Assigns pow(10, exp) to this bigint. + FMT_CONSTEXPR20 void assign_pow10(int exp) { + FMT_ASSERT(exp >= 0, ""); + if (exp == 0) return *this = 1; + // Find the top bit. + int bitmask = 1; + while (exp >= bitmask) bitmask <<= 1; + bitmask >>= 1; + // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by + // repeated squaring and multiplication. + *this = 5; + bitmask >>= 1; + while (bitmask != 0) { + square(); + if ((exp & bitmask) != 0) *this *= 5; + bitmask >>= 1; + } + *this <<= exp; // Multiply by pow(2, exp) by shifting. + } + + FMT_CONSTEXPR20 void square() { + int num_bigits = static_cast(bigits_.size()); + int num_result_bigits = 2 * num_bigits; + basic_memory_buffer n(std::move(bigits_)); + bigits_.resize(to_unsigned(num_result_bigits)); + auto sum = uint128_t(); + for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) { + // Compute bigit at position bigit_index of the result by adding + // cross-product terms n[i] * n[j] such that i + j == bigit_index. + for (int i = 0, j = bigit_index; j >= 0; ++i, --j) { + // Most terms are multiplied twice which can be optimized in the future. + sum += static_cast(n[i]) * n[j]; + } + (*this)[bigit_index] = static_cast(sum); + sum >>= num_bits(); // Compute the carry. + } + // Do the same for the top half. + for (int bigit_index = num_bigits; bigit_index < num_result_bigits; + ++bigit_index) { + for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;) + sum += static_cast(n[i++]) * n[j--]; + (*this)[bigit_index] = static_cast(sum); + sum >>= num_bits(); + } + remove_leading_zeros(); + exp_ *= 2; + } + + // If this bigint has a bigger exponent than other, adds trailing zero to make + // exponents equal. This simplifies some operations such as subtraction. + FMT_CONSTEXPR20 void align(const bigint& other) { + int exp_difference = exp_ - other.exp_; + if (exp_difference <= 0) return; + int num_bigits = static_cast(bigits_.size()); + bigits_.resize(to_unsigned(num_bigits + exp_difference)); + for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j) + bigits_[j] = bigits_[i]; + memset(bigits_.data(), 0, to_unsigned(exp_difference) * sizeof(bigit)); + exp_ -= exp_difference; + } + + // Divides this bignum by divisor, assigning the remainder to this and + // returning the quotient. + FMT_CONSTEXPR20 auto divmod_assign(const bigint& divisor) -> int { + FMT_ASSERT(this != &divisor, ""); + if (compare(*this, divisor) < 0) return 0; + FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, ""); + align(divisor); + int quotient = 0; + do { + subtract_aligned(divisor); + ++quotient; + } while (compare(*this, divisor) >= 0); + return quotient; + } +}; + +// format_dragon flags. +enum dragon { + predecessor_closer = 1, + fixup = 2, // Run fixup to correct exp10 which can be off by one. + fixed = 4, +}; + +// Formats a floating-point number using a variation of the Fixed-Precision +// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White: +// https://fmt.dev/papers/p372-steele.pdf. +FMT_CONSTEXPR20 inline void format_dragon(basic_fp value, + unsigned flags, int num_digits, + buffer& buf, int& exp10) { + bigint numerator; // 2 * R in (FPP)^2. + bigint denominator; // 2 * S in (FPP)^2. + // lower and upper are differences between value and corresponding boundaries. + bigint lower; // (M^- in (FPP)^2). + bigint upper_store; // upper's value if different from lower. + bigint* upper = nullptr; // (M^+ in (FPP)^2). + // Shift numerator and denominator by an extra bit or two (if lower boundary + // is closer) to make lower and upper integers. This eliminates multiplication + // by 2 during later computations. + bool is_predecessor_closer = (flags & dragon::predecessor_closer) != 0; + int shift = is_predecessor_closer ? 2 : 1; + if (value.e >= 0) { + numerator = value.f; + numerator <<= value.e + shift; + lower = 1; + lower <<= value.e; + if (is_predecessor_closer) { + upper_store = 1; + upper_store <<= value.e + 1; + upper = &upper_store; + } + denominator.assign_pow10(exp10); + denominator <<= shift; + } else if (exp10 < 0) { + numerator.assign_pow10(-exp10); + lower.assign(numerator); + if (is_predecessor_closer) { + upper_store.assign(numerator); + upper_store <<= 1; + upper = &upper_store; + } + numerator *= value.f; + numerator <<= shift; + denominator = 1; + denominator <<= shift - value.e; + } else { + numerator = value.f; + numerator <<= shift; + denominator.assign_pow10(exp10); + denominator <<= shift - value.e; + lower = 1; + if (is_predecessor_closer) { + upper_store = 1ULL << 1; + upper = &upper_store; + } + } + int even = static_cast((value.f & 1) == 0); + if (!upper) upper = &lower; + bool shortest = num_digits < 0; + if ((flags & dragon::fixup) != 0) { + if (add_compare(numerator, *upper, denominator) + even <= 0) { + --exp10; + numerator *= 10; + if (num_digits < 0) { + lower *= 10; + if (upper != &lower) *upper *= 10; + } + } + if ((flags & dragon::fixed) != 0) adjust_precision(num_digits, exp10 + 1); + } + // Invariant: value == (numerator / denominator) * pow(10, exp10). + if (shortest) { + // Generate the shortest representation. + num_digits = 0; + char* data = buf.data(); + for (;;) { + int digit = numerator.divmod_assign(denominator); + bool low = compare(numerator, lower) - even < 0; // numerator <[=] lower. + // numerator + upper >[=] pow10: + bool high = add_compare(numerator, *upper, denominator) + even > 0; + data[num_digits++] = static_cast('0' + digit); + if (low || high) { + if (!low) { + ++data[num_digits - 1]; + } else if (high) { + int result = add_compare(numerator, numerator, denominator); + // Round half to even. + if (result > 0 || (result == 0 && (digit % 2) != 0)) + ++data[num_digits - 1]; + } + buf.try_resize(to_unsigned(num_digits)); + exp10 -= num_digits - 1; + return; + } + numerator *= 10; + lower *= 10; + if (upper != &lower) *upper *= 10; + } + } + // Generate the given number of digits. + exp10 -= num_digits - 1; + if (num_digits <= 0) { + auto digit = '0'; + if (num_digits == 0) { + denominator *= 10; + digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0'; + } + buf.push_back(digit); + return; + } + buf.try_resize(to_unsigned(num_digits)); + for (int i = 0; i < num_digits - 1; ++i) { + int digit = numerator.divmod_assign(denominator); + buf[i] = static_cast('0' + digit); + numerator *= 10; + } + int digit = numerator.divmod_assign(denominator); + auto result = add_compare(numerator, numerator, denominator); + if (result > 0 || (result == 0 && (digit % 2) != 0)) { + if (digit == 9) { + const auto overflow = '0' + 10; + buf[num_digits - 1] = overflow; + // Propagate the carry. + for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) { + buf[i] = '0'; + ++buf[i - 1]; + } + if (buf[0] == overflow) { + buf[0] = '1'; + if ((flags & dragon::fixed) != 0) + buf.push_back('0'); + else + ++exp10; + } + return; + } + ++digit; + } + buf[num_digits - 1] = static_cast('0' + digit); +} + +// Formats a floating-point number using the hexfloat format. +template ::value)> +FMT_CONSTEXPR20 void format_hexfloat(Float value, format_specs specs, + buffer& buf) { + // float is passed as double to reduce the number of instantiations and to + // simplify implementation. + static_assert(!std::is_same::value, ""); + + using info = dragonbox::float_info; + + // Assume Float is in the format [sign][exponent][significand]. + using carrier_uint = typename info::carrier_uint; + + constexpr auto num_float_significand_bits = + detail::num_significand_bits(); + + basic_fp f(value); + f.e += num_float_significand_bits; + if (!has_implicit_bit()) --f.e; + + constexpr auto num_fraction_bits = + num_float_significand_bits + (has_implicit_bit() ? 1 : 0); + constexpr auto num_xdigits = (num_fraction_bits + 3) / 4; + + constexpr auto leading_shift = ((num_xdigits - 1) * 4); + const auto leading_mask = carrier_uint(0xF) << leading_shift; + const auto leading_xdigit = + static_cast((f.f & leading_mask) >> leading_shift); + if (leading_xdigit > 1) f.e -= (32 - countl_zero(leading_xdigit) - 1); + + int print_xdigits = num_xdigits - 1; + if (specs.precision >= 0 && print_xdigits > specs.precision) { + const int shift = ((print_xdigits - specs.precision - 1) * 4); + const auto mask = carrier_uint(0xF) << shift; + const auto v = static_cast((f.f & mask) >> shift); + + if (v >= 8) { + const auto inc = carrier_uint(1) << (shift + 4); + f.f += inc; + f.f &= ~(inc - 1); + } + + // Check long double overflow + if (!has_implicit_bit()) { + const auto implicit_bit = carrier_uint(1) << num_float_significand_bits; + if ((f.f & implicit_bit) == implicit_bit) { + f.f >>= 4; + f.e += 4; + } + } + + print_xdigits = specs.precision; + } + + char xdigits[num_bits() / 4]; + detail::fill_n(xdigits, sizeof(xdigits), '0'); + format_uint<4>(xdigits, f.f, num_xdigits, specs.upper); + + // Remove zero tail + while (print_xdigits > 0 && xdigits[print_xdigits] == '0') --print_xdigits; + + buf.push_back('0'); + buf.push_back(specs.upper ? 'X' : 'x'); + buf.push_back(xdigits[0]); + if (specs.alt || print_xdigits > 0 || print_xdigits < specs.precision) + buf.push_back('.'); + buf.append(xdigits + 1, xdigits + 1 + print_xdigits); + for (; print_xdigits < specs.precision; ++print_xdigits) buf.push_back('0'); + + buf.push_back(specs.upper ? 'P' : 'p'); + + uint32_t abs_e; + if (f.e < 0) { + buf.push_back('-'); + abs_e = static_cast(-f.e); + } else { + buf.push_back('+'); + abs_e = static_cast(f.e); + } + format_decimal(appender(buf), abs_e, detail::count_digits(abs_e)); +} + +template ::value)> +FMT_CONSTEXPR20 void format_hexfloat(Float value, format_specs specs, + buffer& buf) { + format_hexfloat(static_cast(value), specs, buf); +} + +constexpr auto fractional_part_rounding_thresholds(int index) -> uint32_t { + // For checking rounding thresholds. + // The kth entry is chosen to be the smallest integer such that the + // upper 32-bits of 10^(k+1) times it is strictly bigger than 5 * 10^k. + // It is equal to ceil(2^31 + 2^32/10^(k + 1)). + // These are stored in a string literal because we cannot have static arrays + // in constexpr functions and non-static ones are poorly optimized. + return U"\x9999999a\x828f5c29\x80418938\x80068db9\x8000a7c6\x800010c7" + U"\x800001ae\x8000002b"[index]; +} + +template +FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs, + buffer& buf) -> int { + // float is passed as double to reduce the number of instantiations. + static_assert(!std::is_same::value, ""); + FMT_ASSERT(value >= 0, "value is negative"); + auto converted_value = convert_float(value); + + const bool fixed = specs.format == float_format::fixed; + if (value <= 0) { // <= instead of == to silence a warning. + if (precision <= 0 || !fixed) { + buf.push_back('0'); + return 0; + } + buf.try_resize(to_unsigned(precision)); + fill_n(buf.data(), precision, '0'); + return -precision; + } + + int exp = 0; + bool use_dragon = true; + unsigned dragon_flags = 0; + if (!is_fast_float() || is_constant_evaluated()) { + const auto inv_log2_10 = 0.3010299956639812; // 1 / log2(10) + using info = dragonbox::float_info; + const auto f = basic_fp(converted_value); + // Compute exp, an approximate power of 10, such that + // 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1). + // This is based on log10(value) == log2(value) / log2(10) and approximation + // of log2(value) by e + num_fraction_bits idea from double-conversion. + auto e = (f.e + count_digits<1>(f.f) - 1) * inv_log2_10 - 1e-10; + exp = static_cast(e); + if (e > exp) ++exp; // Compute ceil. + dragon_flags = dragon::fixup; + } else if (precision < 0) { + // Use Dragonbox for the shortest format. + if (specs.binary32) { + auto dec = dragonbox::to_decimal(static_cast(value)); + write(appender(buf), dec.significand); + return dec.exponent; + } + auto dec = dragonbox::to_decimal(static_cast(value)); + write(appender(buf), dec.significand); + return dec.exponent; + } else { + // Extract significand bits and exponent bits. + using info = dragonbox::float_info; + auto br = bit_cast(static_cast(value)); + + const uint64_t significand_mask = + (static_cast(1) << num_significand_bits()) - 1; + uint64_t significand = (br & significand_mask); + int exponent = static_cast((br & exponent_mask()) >> + num_significand_bits()); + + if (exponent != 0) { // Check if normal. + exponent -= exponent_bias() + num_significand_bits(); + significand |= + (static_cast(1) << num_significand_bits()); + significand <<= 1; + } else { + // Normalize subnormal inputs. + FMT_ASSERT(significand != 0, "zeros should not appear here"); + int shift = countl_zero(significand); + FMT_ASSERT(shift >= num_bits() - num_significand_bits(), + ""); + shift -= (num_bits() - num_significand_bits() - 2); + exponent = (std::numeric_limits::min_exponent - + num_significand_bits()) - + shift; + significand <<= shift; + } + + // Compute the first several nonzero decimal significand digits. + // We call the number we get the first segment. + const int k = info::kappa - dragonbox::floor_log10_pow2(exponent); + exp = -k; + const int beta = exponent + dragonbox::floor_log2_pow10(k); + uint64_t first_segment; + bool has_more_segments; + int digits_in_the_first_segment; + { + const auto r = dragonbox::umul192_upper128( + significand << beta, dragonbox::get_cached_power(k)); + first_segment = r.high(); + has_more_segments = r.low() != 0; + + // The first segment can have 18 ~ 19 digits. + if (first_segment >= 1000000000000000000ULL) { + digits_in_the_first_segment = 19; + } else { + // When it is of 18-digits, we align it to 19-digits by adding a bogus + // zero at the end. + digits_in_the_first_segment = 18; + first_segment *= 10; + } + } + + // Compute the actual number of decimal digits to print. + if (fixed) adjust_precision(precision, exp + digits_in_the_first_segment); + + // Use Dragon4 only when there might be not enough digits in the first + // segment. + if (digits_in_the_first_segment > precision) { + use_dragon = false; + + if (precision <= 0) { + exp += digits_in_the_first_segment; + + if (precision < 0) { + // Nothing to do, since all we have are just leading zeros. + buf.try_resize(0); + } else { + // We may need to round-up. + buf.try_resize(1); + if ((first_segment | static_cast(has_more_segments)) > + 5000000000000000000ULL) { + buf[0] = '1'; + } else { + buf[0] = '0'; + } + } + } // precision <= 0 + else { + exp += digits_in_the_first_segment - precision; + + // When precision > 0, we divide the first segment into three + // subsegments, each with 9, 9, and 0 ~ 1 digits so that each fits + // in 32-bits which usually allows faster calculation than in + // 64-bits. Since some compiler (e.g. MSVC) doesn't know how to optimize + // division-by-constant for large 64-bit divisors, we do it here + // manually. The magic number 7922816251426433760 below is equal to + // ceil(2^(64+32) / 10^10). + const uint32_t first_subsegment = static_cast( + dragonbox::umul128_upper64(first_segment, 7922816251426433760ULL) >> + 32); + const uint64_t second_third_subsegments = + first_segment - first_subsegment * 10000000000ULL; + + uint64_t prod; + uint32_t digits; + bool should_round_up; + int number_of_digits_to_print = precision > 9 ? 9 : precision; + + // Print a 9-digits subsegment, either the first or the second. + auto print_subsegment = [&](uint32_t subsegment, char* buffer) { + int number_of_digits_printed = 0; + + // If we want to print an odd number of digits from the subsegment, + if ((number_of_digits_to_print & 1) != 0) { + // Convert to 64-bit fixed-point fractional form with 1-digit + // integer part. The magic number 720575941 is a good enough + // approximation of 2^(32 + 24) / 10^8; see + // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case + // for details. + prod = ((subsegment * static_cast(720575941)) >> 24) + 1; + digits = static_cast(prod >> 32); + *buffer = static_cast('0' + digits); + number_of_digits_printed++; + } + // If we want to print an even number of digits from the + // first_subsegment, + else { + // Convert to 64-bit fixed-point fractional form with 2-digits + // integer part. The magic number 450359963 is a good enough + // approximation of 2^(32 + 20) / 10^7; see + // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case + // for details. + prod = ((subsegment * static_cast(450359963)) >> 20) + 1; + digits = static_cast(prod >> 32); + copy2(buffer, digits2(digits)); + number_of_digits_printed += 2; + } + + // Print all digit pairs. + while (number_of_digits_printed < number_of_digits_to_print) { + prod = static_cast(prod) * static_cast(100); + digits = static_cast(prod >> 32); + copy2(buffer + number_of_digits_printed, digits2(digits)); + number_of_digits_printed += 2; + } + }; + + // Print first subsegment. + print_subsegment(first_subsegment, buf.data()); + + // Perform rounding if the first subsegment is the last subsegment to + // print. + if (precision <= 9) { + // Rounding inside the subsegment. + // We round-up if: + // - either the fractional part is strictly larger than 1/2, or + // - the fractional part is exactly 1/2 and the last digit is odd. + // We rely on the following observations: + // - If fractional_part >= threshold, then the fractional part is + // strictly larger than 1/2. + // - If the MSB of fractional_part is set, then the fractional part + // must be at least 1/2. + // - When the MSB of fractional_part is set, either + // second_third_subsegments being nonzero or has_more_segments + // being true means there are further digits not printed, so the + // fractional part is strictly larger than 1/2. + if (precision < 9) { + uint32_t fractional_part = static_cast(prod); + should_round_up = + fractional_part >= fractional_part_rounding_thresholds( + 8 - number_of_digits_to_print) || + ((fractional_part >> 31) & + ((digits & 1) | (second_third_subsegments != 0) | + has_more_segments)) != 0; + } + // Rounding at the subsegment boundary. + // In this case, the fractional part is at least 1/2 if and only if + // second_third_subsegments >= 5000000000ULL, and is strictly larger + // than 1/2 if we further have either second_third_subsegments > + // 5000000000ULL or has_more_segments == true. + else { + should_round_up = second_third_subsegments > 5000000000ULL || + (second_third_subsegments == 5000000000ULL && + ((digits & 1) != 0 || has_more_segments)); + } + } + // Otherwise, print the second subsegment. + else { + // Compilers are not aware of how to leverage the maximum value of + // second_third_subsegments to find out a better magic number which + // allows us to eliminate an additional shift. 1844674407370955162 = + // ceil(2^64/10) < ceil(2^64*(10^9/(10^10 - 1))). + const uint32_t second_subsegment = + static_cast(dragonbox::umul128_upper64( + second_third_subsegments, 1844674407370955162ULL)); + const uint32_t third_subsegment = + static_cast(second_third_subsegments) - + second_subsegment * 10; + + number_of_digits_to_print = precision - 9; + print_subsegment(second_subsegment, buf.data() + 9); + + // Rounding inside the subsegment. + if (precision < 18) { + // The condition third_subsegment != 0 implies that the segment was + // of 19 digits, so in this case the third segment should be + // consisting of a genuine digit from the input. + uint32_t fractional_part = static_cast(prod); + should_round_up = + fractional_part >= fractional_part_rounding_thresholds( + 8 - number_of_digits_to_print) || + ((fractional_part >> 31) & + ((digits & 1) | (third_subsegment != 0) | + has_more_segments)) != 0; + } + // Rounding at the subsegment boundary. + else { + // In this case, the segment must be of 19 digits, thus + // the third subsegment should be consisting of a genuine digit from + // the input. + should_round_up = third_subsegment > 5 || + (third_subsegment == 5 && + ((digits & 1) != 0 || has_more_segments)); + } + } + + // Round-up if necessary. + if (should_round_up) { + ++buf[precision - 1]; + for (int i = precision - 1; i > 0 && buf[i] > '9'; --i) { + buf[i] = '0'; + ++buf[i - 1]; + } + if (buf[0] > '9') { + buf[0] = '1'; + if (fixed) + buf[precision++] = '0'; + else + ++exp; + } + } + buf.try_resize(to_unsigned(precision)); + } + } // if (digits_in_the_first_segment > precision) + else { + // Adjust the exponent for its use in Dragon4. + exp += digits_in_the_first_segment - 1; + } + } + if (use_dragon) { + auto f = basic_fp(); + bool is_predecessor_closer = specs.binary32 + ? f.assign(static_cast(value)) + : f.assign(converted_value); + if (is_predecessor_closer) dragon_flags |= dragon::predecessor_closer; + if (fixed) dragon_flags |= dragon::fixed; + // Limit precision to the maximum possible number of significant digits in + // an IEEE754 double because we don't need to generate zeros. + const int max_double_digits = 767; + if (precision > max_double_digits) precision = max_double_digits; + format_dragon(f, dragon_flags, precision, buf, exp); + } + if (!fixed && !specs.showpoint) { + // Remove trailing zeros. + auto num_digits = buf.size(); + while (num_digits > 0 && buf[num_digits - 1] == '0') { + --num_digits; + ++exp; + } + buf.try_resize(num_digits); + } + return exp; +} + +template +FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, format_specs specs, + locale_ref loc) -> OutputIt { + sign_t sign = specs.sign; + if (detail::signbit(value)) { // value < 0 is false for NaN so use signbit. + sign = sign::minus; + value = -value; + } else if (sign == sign::minus) { + sign = sign::none; + } + + if (!detail::isfinite(value)) + return write_nonfinite(out, detail::isnan(value), specs, sign); + + if (specs.align == align::numeric && sign) { + auto it = reserve(out, 1); + *it++ = detail::sign(sign); + out = base_iterator(out, it); + sign = sign::none; + if (specs.width != 0) --specs.width; + } + + memory_buffer buffer; + if (specs.type == presentation_type::hexfloat) { + if (sign) buffer.push_back(detail::sign(sign)); + format_hexfloat(convert_float(value), specs, buffer); + return write_bytes(out, {buffer.data(), buffer.size()}, + specs); + } + + int precision = specs.precision >= 0 || specs.type == presentation_type::none + ? specs.precision + : 6; + if (specs.type == presentation_type::exp) { + if (precision == max_value()) + report_error("number is too big"); + else + ++precision; + } else if (specs.type != presentation_type::fixed && precision == 0) { + precision = 1; + } + float_specs fspecs = parse_float_type_spec(specs); + fspecs.sign = sign; + if (const_check(std::is_same())) fspecs.binary32 = true; + int exp = format_float(convert_float(value), precision, fspecs, buffer); + fspecs.precision = precision; + auto f = big_decimal_fp{buffer.data(), static_cast(buffer.size()), exp}; + return write_float(out, f, specs, fspecs, loc); +} + +template ::value)> +FMT_CONSTEXPR20 auto write(OutputIt out, T value, format_specs specs, + locale_ref loc = {}) -> OutputIt { + if (const_check(!is_supported_floating_point(value))) return out; + return specs.localized && write_loc(out, value, specs, loc) + ? out + : write_float(out, value, specs, loc); +} + +template ::value)> +FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt { + if (is_constant_evaluated()) return write(out, value, format_specs()); + if (const_check(!is_supported_floating_point(value))) return out; + + auto sign = sign_t::none; + if (detail::signbit(value)) { + sign = sign::minus; + value = -value; + } + + constexpr auto specs = format_specs(); + using floaty = conditional_t::value, double, T>; + using floaty_uint = typename dragonbox::float_info::carrier_uint; + floaty_uint mask = exponent_mask(); + if ((bit_cast(value) & mask) == mask) + return write_nonfinite(out, std::isnan(value), specs, sign); + + auto fspecs = float_specs(); + fspecs.sign = sign; + auto dec = dragonbox::to_decimal(static_cast(value)); + return write_float(out, dec, specs, fspecs, {}); +} + +template ::value && + !is_fast_float::value)> +inline auto write(OutputIt out, T value) -> OutputIt { + return write(out, value, format_specs()); +} + +template +auto write(OutputIt out, monostate, format_specs = {}, locale_ref = {}) + -> OutputIt { + FMT_ASSERT(false, ""); + return out; +} + +template +FMT_CONSTEXPR auto write(OutputIt out, basic_string_view value) + -> OutputIt { + return copy_noinline(value.begin(), value.end(), out); +} + +template ::value)> +constexpr auto write(OutputIt out, const T& value) -> OutputIt { + return write(out, to_string_view(value)); +} + +// FMT_ENABLE_IF() condition separated to workaround an MSVC bug. +template < + typename Char, typename OutputIt, typename T, + bool check = + std::is_enum::value && !std::is_same::value && + mapped_type_constant>::value != + type::custom_type, + FMT_ENABLE_IF(check)> +FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { + return write(out, static_cast>(value)); +} + +template ::value)> +FMT_CONSTEXPR auto write(OutputIt out, T value, const format_specs& specs = {}, + locale_ref = {}) -> OutputIt { + return specs.type != presentation_type::none && + specs.type != presentation_type::string + ? write(out, value ? 1 : 0, specs, {}) + : write_bytes(out, value ? "true" : "false", specs); +} + +template +FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt { + auto it = reserve(out, 1); + *it++ = value; + return base_iterator(out, it); +} + +template +FMT_CONSTEXPR20 auto write(OutputIt out, const Char* value) -> OutputIt { + if (value) return write(out, basic_string_view(value)); + report_error("string pointer is null"); + return out; +} + +template ::value)> +auto write(OutputIt out, const T* value, const format_specs& specs = {}, + locale_ref = {}) -> OutputIt { + return write_ptr(out, bit_cast(value), &specs); +} + +// A write overload that handles implicit conversions. +template > +FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t< + std::is_class::value && !has_to_string_view::value && + !is_floating_point::value && !std::is_same::value && + !std::is_same().map( + value))>>::value, + OutputIt> { + return write(out, arg_mapper().map(value)); +} + +template > +FMT_CONSTEXPR auto write(OutputIt out, const T& value) + -> enable_if_t::value == + type::custom_type && + !std::is_fundamental::value, + OutputIt> { + auto formatter = typename Context::template formatter_type(); + auto parse_ctx = typename Context::parse_context_type({}); + formatter.parse(parse_ctx); + auto ctx = Context(out, {}, {}); + return formatter.format(value, ctx); +} + +// An argument visitor that formats the argument and writes it via the output +// iterator. It's a class and not a generic lambda for compatibility with C++11. +template struct default_arg_formatter { + using iterator = basic_appender; + using context = buffered_context; + + iterator out; + basic_format_args args; + locale_ref loc; + + template auto operator()(T value) -> iterator { + return write(out, value); + } + auto operator()(typename basic_format_arg::handle h) -> iterator { + basic_format_parse_context parse_ctx({}); + context format_ctx(out, args, loc); + h.format(parse_ctx, format_ctx); + return format_ctx.out(); + } +}; + +template struct arg_formatter { + using iterator = basic_appender; + using context = buffered_context; + + iterator out; + const format_specs& specs; + locale_ref locale; + + template + FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator { + return detail::write(out, value, specs, locale); + } + auto operator()(typename basic_format_arg::handle) -> iterator { + // User-defined types are handled separately because they require access + // to the parse context. + return out; + } +}; + +struct width_checker { + template ::value)> + FMT_CONSTEXPR auto operator()(T value) -> unsigned long long { + if (is_negative(value)) report_error("negative width"); + return static_cast(value); + } + + template ::value)> + FMT_CONSTEXPR auto operator()(T) -> unsigned long long { + report_error("width is not integer"); + return 0; + } +}; + +struct precision_checker { + template ::value)> + FMT_CONSTEXPR auto operator()(T value) -> unsigned long long { + if (is_negative(value)) report_error("negative precision"); + return static_cast(value); + } + + template ::value)> + FMT_CONSTEXPR auto operator()(T) -> unsigned long long { + report_error("precision is not integer"); + return 0; + } +}; + +template +FMT_CONSTEXPR auto get_dynamic_spec(FormatArg arg) -> int { + unsigned long long value = arg.visit(Handler()); + if (value > to_unsigned(max_value())) report_error("number is too big"); + return static_cast(value); +} + +template +FMT_CONSTEXPR auto get_arg(Context& ctx, ID id) -> decltype(ctx.arg(id)) { + auto arg = ctx.arg(id); + if (!arg) report_error("argument not found"); + return arg; +} + +template +FMT_CONSTEXPR void handle_dynamic_spec(int& value, + arg_ref ref, + Context& ctx) { + switch (ref.kind) { + case arg_id_kind::none: + break; + case arg_id_kind::index: + value = detail::get_dynamic_spec(get_arg(ctx, ref.val.index)); + break; + case arg_id_kind::name: + value = detail::get_dynamic_spec(get_arg(ctx, ref.val.name)); + break; + } +} + +#if FMT_USE_USER_DEFINED_LITERALS +# if FMT_USE_NONTYPE_TEMPLATE_ARGS +template Str> +struct statically_named_arg : view { + static constexpr auto name = Str.data; + + const T& value; + statically_named_arg(const T& v) : value(v) {} +}; + +template Str> +struct is_named_arg> : std::true_type {}; + +template Str> +struct is_statically_named_arg> + : std::true_type {}; + +template Str> +struct udl_arg { + template auto operator=(T&& value) const { + return statically_named_arg(std::forward(value)); + } +}; +# else +template struct udl_arg { + const Char* str; + + template auto operator=(T&& value) const -> named_arg { + return {str, std::forward(value)}; + } +}; +# endif +#endif // FMT_USE_USER_DEFINED_LITERALS + +template +auto vformat(const Locale& loc, basic_string_view fmt, + typename detail::vformat_args::type args) + -> std::basic_string { + auto buf = basic_memory_buffer(); + detail::vformat_to(buf, fmt, args, detail::locale_ref(loc)); + return {buf.data(), buf.size()}; +} + +using format_func = void (*)(detail::buffer&, int, const char*); + +FMT_API void format_error_code(buffer& out, int error_code, + string_view message) noexcept; + +using fmt::report_error; +FMT_API void report_error(format_func func, int error_code, + const char* message) noexcept; +} // namespace detail + +FMT_BEGIN_EXPORT +FMT_API auto vsystem_error(int error_code, string_view format_str, + format_args args) -> std::system_error; + +/** + * Constructs `std::system_error` with a message formatted with + * `fmt::format(fmt, args...)`. + * `error_code` is a system error code as given by `errno`. + * + * **Example**: + * + * // This throws std::system_error with the description + * // cannot open file 'madeup': No such file or directory + * // or similar (system message may vary). + * const char* filename = "madeup"; + * std::FILE* file = std::fopen(filename, "r"); + * if (!file) + * throw fmt::system_error(errno, "cannot open file '{}'", filename); + */ +template +auto system_error(int error_code, format_string fmt, T&&... args) + -> std::system_error { + return vsystem_error(error_code, fmt, fmt::make_format_args(args...)); +} + +/** + * Formats an error message for an error returned by an operating system or a + * language runtime, for example a file opening error, and writes it to `out`. + * The format is the same as the one used by `std::system_error(ec, message)` + * where `ec` is `std::error_code(error_code, std::generic_category())`. + * It is implementation-defined but normally looks like: + * + * : + * + * where `` is the passed message and `` is the system + * message corresponding to the error code. + * `error_code` is a system error code as given by `errno`. + */ +FMT_API void format_system_error(detail::buffer& out, int error_code, + const char* message) noexcept; + +// Reports a system error without throwing an exception. +// Can be used to report errors from destructors. +FMT_API void report_system_error(int error_code, const char* message) noexcept; + +/// A fast integer formatter. +class format_int { + private: + // Buffer should be large enough to hold all digits (digits10 + 1), + // a sign and a null character. + enum { buffer_size = std::numeric_limits::digits10 + 3 }; + mutable char buffer_[buffer_size]; + char* str_; + + template + FMT_CONSTEXPR20 auto format_unsigned(UInt value) -> char* { + auto n = static_cast>(value); + return detail::format_decimal(buffer_, n, buffer_size - 1).begin; + } + + template + FMT_CONSTEXPR20 auto format_signed(Int value) -> char* { + auto abs_value = static_cast>(value); + bool negative = value < 0; + if (negative) abs_value = 0 - abs_value; + auto begin = format_unsigned(abs_value); + if (negative) *--begin = '-'; + return begin; + } + + public: + explicit FMT_CONSTEXPR20 format_int(int value) : str_(format_signed(value)) {} + explicit FMT_CONSTEXPR20 format_int(long value) + : str_(format_signed(value)) {} + explicit FMT_CONSTEXPR20 format_int(long long value) + : str_(format_signed(value)) {} + explicit FMT_CONSTEXPR20 format_int(unsigned value) + : str_(format_unsigned(value)) {} + explicit FMT_CONSTEXPR20 format_int(unsigned long value) + : str_(format_unsigned(value)) {} + explicit FMT_CONSTEXPR20 format_int(unsigned long long value) + : str_(format_unsigned(value)) {} + + /// Returns the number of characters written to the output buffer. + FMT_CONSTEXPR20 auto size() const -> size_t { + return detail::to_unsigned(buffer_ - str_ + buffer_size - 1); + } + + /// Returns a pointer to the output buffer content. No terminating null + /// character is appended. + FMT_CONSTEXPR20 auto data() const -> const char* { return str_; } + + /// Returns a pointer to the output buffer content with terminating null + /// character appended. + FMT_CONSTEXPR20 auto c_str() const -> const char* { + buffer_[buffer_size - 1] = '\0'; + return str_; + } + + /// Returns the content of the output buffer as an `std::string`. + auto str() const -> std::string { return std::string(str_, size()); } +}; + +template +struct formatter::value>> + : formatter, Char> { + template + auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) { + auto&& val = format_as(value); // Make an lvalue reference for format. + return formatter, Char>::format(val, ctx); + } +}; + +#define FMT_FORMAT_AS(Type, Base) \ + template \ + struct formatter : formatter { \ + template \ + auto format(Type value, FormatContext& ctx) const -> decltype(ctx.out()) { \ + return formatter::format(value, ctx); \ + } \ + } + +FMT_FORMAT_AS(signed char, int); +FMT_FORMAT_AS(unsigned char, unsigned); +FMT_FORMAT_AS(short, int); +FMT_FORMAT_AS(unsigned short, unsigned); +FMT_FORMAT_AS(long, detail::long_type); +FMT_FORMAT_AS(unsigned long, detail::ulong_type); +FMT_FORMAT_AS(Char*, const Char*); +FMT_FORMAT_AS(std::nullptr_t, const void*); +FMT_FORMAT_AS(detail::std_string_view, basic_string_view); +FMT_FORMAT_AS(void*, const void*); + +template +class formatter, Char> + : public formatter, Char> {}; + +template +struct formatter : formatter, Char> {}; + +/** + * Converts `p` to `const void*` for pointer formatting. + * + * **Example**: + * + * auto s = fmt::format("{}", fmt::ptr(p)); + */ +template auto ptr(T p) -> const void* { + static_assert(std::is_pointer::value, ""); + return detail::bit_cast(p); +} + +/** + * Converts `e` to the underlying type. + * + * **Example**: + * + * enum class color { red, green, blue }; + * auto s = fmt::format("{}", fmt::underlying(color::red)); + */ +template +constexpr auto underlying(Enum e) noexcept -> underlying_t { + return static_cast>(e); +} + +namespace enums { +template ::value)> +constexpr auto format_as(Enum e) noexcept -> underlying_t { + return static_cast>(e); +} +} // namespace enums + +class bytes { + private: + string_view data_; + friend struct formatter; + + public: + explicit bytes(string_view data) : data_(data) {} +}; + +template <> struct formatter { + private: + detail::dynamic_format_specs<> specs_; + + public: + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const char* { + return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, + detail::type::string_type); + } + + template + auto format(bytes b, FormatContext& ctx) const -> decltype(ctx.out()) { + auto specs = specs_; + detail::handle_dynamic_spec(specs.width, + specs.width_ref, ctx); + detail::handle_dynamic_spec( + specs.precision, specs.precision_ref, ctx); + return detail::write_bytes(ctx.out(), b.data_, specs); + } +}; + +// group_digits_view is not derived from view because it copies the argument. +template struct group_digits_view { + T value; +}; + +/** + * Returns a view that formats an integer value using ',' as a + * locale-independent thousands separator. + * + * **Example**: + * + * fmt::print("{}", fmt::group_digits(12345)); + * // Output: "12,345" + */ +template auto group_digits(T value) -> group_digits_view { + return {value}; +} + +template struct formatter> : formatter { + private: + detail::dynamic_format_specs<> specs_; + + public: + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const char* { + return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, + detail::type::int_type); + } + + template + auto format(group_digits_view t, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto specs = specs_; + detail::handle_dynamic_spec(specs.width, + specs.width_ref, ctx); + detail::handle_dynamic_spec( + specs.precision, specs.precision_ref, ctx); + auto arg = detail::make_write_int_arg(t.value, specs.sign); + return detail::write_int( + ctx.out(), static_cast>(arg.abs_value), + arg.prefix, specs, detail::digit_grouping("\3", ",")); + } +}; + +template struct nested_view { + const formatter* fmt; + const T* value; +}; + +template +struct formatter, Char> { + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + template + auto format(nested_view view, FormatContext& ctx) const + -> decltype(ctx.out()) { + return view.fmt->format(*view.value, ctx); + } +}; + +template struct nested_formatter { + private: + int width_; + detail::fill_t fill_; + align_t align_ : 4; + formatter formatter_; + + public: + constexpr nested_formatter() : width_(0), align_(align_t::none) {} + + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + auto specs = detail::dynamic_format_specs(); + auto it = parse_format_specs(ctx.begin(), ctx.end(), specs, ctx, + detail::type::none_type); + width_ = specs.width; + fill_ = specs.fill; + align_ = specs.align; + ctx.advance_to(it); + return formatter_.parse(ctx); + } + + template + auto write_padded(FormatContext& ctx, F write) const -> decltype(ctx.out()) { + if (width_ == 0) return write(ctx.out()); + auto buf = basic_memory_buffer(); + write(basic_appender(buf)); + auto specs = format_specs(); + specs.width = width_; + specs.fill = fill_; + specs.align = align_; + return detail::write( + ctx.out(), basic_string_view(buf.data(), buf.size()), specs); + } + + auto nested(const T& value) const -> nested_view { + return nested_view{&formatter_, &value}; + } +}; + +/** + * Converts `value` to `std::string` using the default format for type `T`. + * + * **Example**: + * + * std::string answer = fmt::to_string(42); + */ +template ::value && + !detail::has_format_as::value)> +inline auto to_string(const T& value) -> std::string { + auto buffer = memory_buffer(); + detail::write(appender(buffer), value); + return {buffer.data(), buffer.size()}; +} + +template ::value)> +FMT_NODISCARD inline auto to_string(T value) -> std::string { + // The buffer should be large enough to store the number including the sign + // or "false" for bool. + constexpr int max_size = detail::digits10() + 2; + char buffer[max_size > 5 ? static_cast(max_size) : 5]; + char* begin = buffer; + return std::string(begin, detail::write(begin, value)); +} + +template +FMT_NODISCARD auto to_string(const basic_memory_buffer& buf) + -> std::basic_string { + auto size = buf.size(); + detail::assume(size < std::basic_string().max_size()); + return std::basic_string(buf.data(), size); +} + +template ::value && + detail::has_format_as::value)> +inline auto to_string(const T& value) -> std::string { + return to_string(format_as(value)); +} + +FMT_END_EXPORT + +namespace detail { + +template +void vformat_to(buffer& buf, basic_string_view fmt, + typename vformat_args::type args, locale_ref loc) { + auto out = basic_appender(buf); + if (fmt.size() == 2 && equal2(fmt.data(), "{}")) { + auto arg = args.get(0); + if (!arg) report_error("argument not found"); + arg.visit(default_arg_formatter{out, args, loc}); + return; + } + + struct format_handler { + basic_format_parse_context parse_context; + buffered_context context; + + format_handler(basic_appender p_out, basic_string_view str, + basic_format_args> p_args, + locale_ref p_loc) + : parse_context(str), context(p_out, p_args, p_loc) {} + + void on_text(const Char* begin, const Char* end) { + auto text = basic_string_view(begin, to_unsigned(end - begin)); + context.advance_to(write(context.out(), text)); + } + + FMT_CONSTEXPR auto on_arg_id() -> int { + return parse_context.next_arg_id(); + } + FMT_CONSTEXPR auto on_arg_id(int id) -> int { + parse_context.check_arg_id(id); + return id; + } + FMT_CONSTEXPR auto on_arg_id(basic_string_view id) -> int { + parse_context.check_arg_id(id); + int arg_id = context.arg_id(id); + if (arg_id < 0) report_error("argument not found"); + return arg_id; + } + + FMT_INLINE void on_replacement_field(int id, const Char*) { + auto arg = get_arg(context, id); + context.advance_to(arg.visit(default_arg_formatter{ + context.out(), context.args(), context.locale()})); + } + + auto on_format_specs(int id, const Char* begin, const Char* end) + -> const Char* { + auto arg = get_arg(context, id); + // Not using a visitor for custom types gives better codegen. + if (arg.format_custom(begin, parse_context, context)) + return parse_context.begin(); + auto specs = detail::dynamic_format_specs(); + begin = parse_format_specs(begin, end, specs, parse_context, arg.type()); + detail::handle_dynamic_spec( + specs.width, specs.width_ref, context); + detail::handle_dynamic_spec( + specs.precision, specs.precision_ref, context); + if (begin == end || *begin != '}') + report_error("missing '}' in format string"); + context.advance_to(arg.visit( + arg_formatter{context.out(), specs, context.locale()})); + return begin; + } + + FMT_NORETURN void on_error(const char* message) { report_error(message); } + }; + detail::parse_format_string(fmt, format_handler(out, fmt, args, loc)); +} + +FMT_BEGIN_EXPORT + +#ifndef FMT_HEADER_ONLY +extern template FMT_API void vformat_to(buffer&, string_view, + typename vformat_args<>::type, + locale_ref); +extern template FMT_API auto thousands_sep_impl(locale_ref) + -> thousands_sep_result; +extern template FMT_API auto thousands_sep_impl(locale_ref) + -> thousands_sep_result; +extern template FMT_API auto decimal_point_impl(locale_ref) -> char; +extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t; +#endif // FMT_HEADER_ONLY + +FMT_END_EXPORT + +template +template +FMT_CONSTEXPR FMT_INLINE auto native_formatter::format( + const T& val, FormatContext& ctx) const -> decltype(ctx.out()) { + if (specs_.width_ref.kind == arg_id_kind::none && + specs_.precision_ref.kind == arg_id_kind::none) { + return write(ctx.out(), val, specs_, ctx.locale()); + } + auto specs = specs_; + handle_dynamic_spec(specs.width, specs.width_ref, ctx); + handle_dynamic_spec(specs.precision, specs.precision_ref, + ctx); + return write(ctx.out(), val, specs, ctx.locale()); +} + +} // namespace detail + +FMT_BEGIN_EXPORT + +template +struct formatter + : detail::native_formatter {}; + +#if FMT_USE_USER_DEFINED_LITERALS +inline namespace literals { +/** + * User-defined literal equivalent of `fmt::arg`. + * + * **Example**: + * + * using namespace fmt::literals; + * fmt::print("The answer is {answer}.", "answer"_a=42); + */ +# if FMT_USE_NONTYPE_TEMPLATE_ARGS +template constexpr auto operator""_a() { + using char_t = remove_cvref_t; + return detail::udl_arg(); +} +# else +constexpr auto operator""_a(const char* s, size_t) -> detail::udl_arg { + return {s}; +} +# endif +} // namespace literals +#endif // FMT_USE_USER_DEFINED_LITERALS + +FMT_API auto vformat(string_view fmt, format_args args) -> std::string; + +/** + * Formats `args` according to specifications in `fmt` and returns the result + * as a string. + * + * **Example**: + * + * #include + * std::string message = fmt::format("The answer is {}.", 42); + */ +template +FMT_NODISCARD FMT_INLINE auto format(format_string fmt, T&&... args) + -> std::string { + return vformat(fmt, fmt::make_format_args(args...)); +} + +template ::value)> +inline auto vformat(const Locale& loc, string_view fmt, format_args args) + -> std::string { + return detail::vformat(loc, fmt, args); +} + +template ::value)> +inline auto format(const Locale& loc, format_string fmt, T&&... args) + -> std::string { + return fmt::vformat(loc, string_view(fmt), fmt::make_format_args(args...)); +} + +template ::value&& + detail::is_locale::value)> +auto vformat_to(OutputIt out, const Locale& loc, string_view fmt, + format_args args) -> OutputIt { + using detail::get_buffer; + auto&& buf = get_buffer(out); + detail::vformat_to(buf, fmt, args, detail::locale_ref(loc)); + return detail::get_iterator(buf, out); +} + +template ::value&& + detail::is_locale::value)> +FMT_INLINE auto format_to(OutputIt out, const Locale& loc, + format_string fmt, T&&... args) -> OutputIt { + return vformat_to(out, loc, fmt, fmt::make_format_args(args...)); +} + +template ::value)> +FMT_NODISCARD FMT_INLINE auto formatted_size(const Locale& loc, + format_string fmt, + T&&... args) -> size_t { + auto buf = detail::counting_buffer<>(); + detail::vformat_to(buf, fmt, fmt::make_format_args(args...), + detail::locale_ref(loc)); + return buf.count(); +} + +FMT_END_EXPORT + +FMT_END_NAMESPACE + +#ifdef FMT_HEADER_ONLY +# define FMT_FUNC inline +# include "format-inl.h" +#else +# define FMT_FUNC +#endif + +// Restore _LIBCPP_REMOVE_TRANSITIVE_INCLUDES. +#ifdef FMT_REMOVE_TRANSITIVE_INCLUDES +# undef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES +#endif + +#endif // FMT_FORMAT_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/os.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/os.h new file mode 100644 index 0000000..5c85ea0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/os.h @@ -0,0 +1,439 @@ +// Formatting library for C++ - optional OS-specific functionality +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_OS_H_ +#define FMT_OS_H_ + +#include "format.h" + +#ifndef FMT_MODULE +# include +# include +# include +# include // std::system_error + +# if FMT_HAS_INCLUDE() +# include // LC_NUMERIC_MASK on macOS +# endif +#endif // FMT_MODULE + +#ifndef FMT_USE_FCNTL +// UWP doesn't provide _pipe. +# if FMT_HAS_INCLUDE("winapifamily.h") +# include +# endif +# if (FMT_HAS_INCLUDE() || defined(__APPLE__) || \ + defined(__linux__)) && \ + (!defined(WINAPI_FAMILY) || \ + (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)) +# include // for O_RDONLY +# define FMT_USE_FCNTL 1 +# else +# define FMT_USE_FCNTL 0 +# endif +#endif + +#ifndef FMT_POSIX +# if defined(_WIN32) && !defined(__MINGW32__) +// Fix warnings about deprecated symbols. +# define FMT_POSIX(call) _##call +# else +# define FMT_POSIX(call) call +# endif +#endif + +// Calls to system functions are wrapped in FMT_SYSTEM for testability. +#ifdef FMT_SYSTEM +# define FMT_HAS_SYSTEM +# define FMT_POSIX_CALL(call) FMT_SYSTEM(call) +#else +# define FMT_SYSTEM(call) ::call +# ifdef _WIN32 +// Fix warnings about deprecated symbols. +# define FMT_POSIX_CALL(call) ::_##call +# else +# define FMT_POSIX_CALL(call) ::call +# endif +#endif + +// Retries the expression while it evaluates to error_result and errno +// equals to EINTR. +#ifndef _WIN32 +# define FMT_RETRY_VAL(result, expression, error_result) \ + do { \ + (result) = (expression); \ + } while ((result) == (error_result) && errno == EINTR) +#else +# define FMT_RETRY_VAL(result, expression, error_result) result = (expression) +#endif + +#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1) + +FMT_BEGIN_NAMESPACE +FMT_BEGIN_EXPORT + +/** + * A reference to a null-terminated string. It can be constructed from a C + * string or `std::string`. + * + * You can use one of the following type aliases for common character types: + * + * +---------------+-----------------------------+ + * | Type | Definition | + * +===============+=============================+ + * | cstring_view | basic_cstring_view | + * +---------------+-----------------------------+ + * | wcstring_view | basic_cstring_view | + * +---------------+-----------------------------+ + * + * This class is most useful as a parameter type for functions that wrap C APIs. + */ +template class basic_cstring_view { + private: + const Char* data_; + + public: + /// Constructs a string reference object from a C string. + basic_cstring_view(const Char* s) : data_(s) {} + + /// Constructs a string reference from an `std::string` object. + basic_cstring_view(const std::basic_string& s) : data_(s.c_str()) {} + + /// Returns the pointer to a C string. + auto c_str() const -> const Char* { return data_; } +}; + +using cstring_view = basic_cstring_view; +using wcstring_view = basic_cstring_view; + +#ifdef _WIN32 +FMT_API const std::error_category& system_category() noexcept; + +namespace detail { +FMT_API void format_windows_error(buffer& out, int error_code, + const char* message) noexcept; +} + +FMT_API std::system_error vwindows_error(int error_code, string_view format_str, + format_args args); + +/** + * Constructs a `std::system_error` object with the description of the form + * + * : + * + * where `` is the formatted message and `` is the + * system message corresponding to the error code. + * `error_code` is a Windows error code as given by `GetLastError`. + * If `error_code` is not a valid error code such as -1, the system message + * will look like "error -1". + * + * **Example**: + * + * // This throws a system_error with the description + * // cannot open file 'madeup': The system cannot find the file + * specified. + * // or similar (system message may vary). + * const char *filename = "madeup"; + * LPOFSTRUCT of = LPOFSTRUCT(); + * HFILE file = OpenFile(filename, &of, OF_READ); + * if (file == HFILE_ERROR) { + * throw fmt::windows_error(GetLastError(), + * "cannot open file '{}'", filename); + * } + */ +template +std::system_error windows_error(int error_code, string_view message, + const Args&... args) { + return vwindows_error(error_code, message, fmt::make_format_args(args...)); +} + +// Reports a Windows error without throwing an exception. +// Can be used to report errors from destructors. +FMT_API void report_windows_error(int error_code, const char* message) noexcept; +#else +inline auto system_category() noexcept -> const std::error_category& { + return std::system_category(); +} +#endif // _WIN32 + +// std::system is not available on some platforms such as iOS (#2248). +#ifdef __OSX__ +template > +void say(const S& format_str, Args&&... args) { + std::system(format("say \"{}\"", format(format_str, args...)).c_str()); +} +#endif + +// A buffered file. +class buffered_file { + private: + FILE* file_; + + friend class file; + + explicit buffered_file(FILE* f) : file_(f) {} + + public: + buffered_file(const buffered_file&) = delete; + void operator=(const buffered_file&) = delete; + + // Constructs a buffered_file object which doesn't represent any file. + buffered_file() noexcept : file_(nullptr) {} + + // Destroys the object closing the file it represents if any. + FMT_API ~buffered_file() noexcept; + + public: + buffered_file(buffered_file&& other) noexcept : file_(other.file_) { + other.file_ = nullptr; + } + + auto operator=(buffered_file&& other) -> buffered_file& { + close(); + file_ = other.file_; + other.file_ = nullptr; + return *this; + } + + // Opens a file. + FMT_API buffered_file(cstring_view filename, cstring_view mode); + + // Closes the file. + FMT_API void close(); + + // Returns the pointer to a FILE object representing this file. + auto get() const noexcept -> FILE* { return file_; } + + FMT_API auto descriptor() const -> int; + + template + inline void print(string_view fmt, const T&... args) { + const auto& vargs = fmt::make_format_args(args...); + detail::is_locking() ? fmt::vprint_buffered(file_, fmt, vargs) + : fmt::vprint(file_, fmt, vargs); + } +}; + +#if FMT_USE_FCNTL + +// A file. Closed file is represented by a file object with descriptor -1. +// Methods that are not declared with noexcept may throw +// fmt::system_error in case of failure. Note that some errors such as +// closing the file multiple times will cause a crash on Windows rather +// than an exception. You can get standard behavior by overriding the +// invalid parameter handler with _set_invalid_parameter_handler. +class FMT_API file { + private: + int fd_; // File descriptor. + + // Constructs a file object with a given descriptor. + explicit file(int fd) : fd_(fd) {} + + friend struct pipe; + + public: + // Possible values for the oflag argument to the constructor. + enum { + RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only. + WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only. + RDWR = FMT_POSIX(O_RDWR), // Open for reading and writing. + CREATE = FMT_POSIX(O_CREAT), // Create if the file doesn't exist. + APPEND = FMT_POSIX(O_APPEND), // Open in append mode. + TRUNC = FMT_POSIX(O_TRUNC) // Truncate the content of the file. + }; + + // Constructs a file object which doesn't represent any file. + file() noexcept : fd_(-1) {} + + // Opens a file and constructs a file object representing this file. + file(cstring_view path, int oflag); + + public: + file(const file&) = delete; + void operator=(const file&) = delete; + + file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; } + + // Move assignment is not noexcept because close may throw. + auto operator=(file&& other) -> file& { + close(); + fd_ = other.fd_; + other.fd_ = -1; + return *this; + } + + // Destroys the object closing the file it represents if any. + ~file() noexcept; + + // Returns the file descriptor. + auto descriptor() const noexcept -> int { return fd_; } + + // Closes the file. + void close(); + + // Returns the file size. The size has signed type for consistency with + // stat::st_size. + auto size() const -> long long; + + // Attempts to read count bytes from the file into the specified buffer. + auto read(void* buffer, size_t count) -> size_t; + + // Attempts to write count bytes from the specified buffer to the file. + auto write(const void* buffer, size_t count) -> size_t; + + // Duplicates a file descriptor with the dup function and returns + // the duplicate as a file object. + static auto dup(int fd) -> file; + + // Makes fd be the copy of this file descriptor, closing fd first if + // necessary. + void dup2(int fd); + + // Makes fd be the copy of this file descriptor, closing fd first if + // necessary. + void dup2(int fd, std::error_code& ec) noexcept; + + // Creates a buffered_file object associated with this file and detaches + // this file object from the file. + auto fdopen(const char* mode) -> buffered_file; + +# if defined(_WIN32) && !defined(__MINGW32__) + // Opens a file and constructs a file object representing this file by + // wcstring_view filename. Windows only. + static file open_windows_file(wcstring_view path, int oflag); +# endif +}; + +struct FMT_API pipe { + file read_end; + file write_end; + + // Creates a pipe setting up read_end and write_end file objects for reading + // and writing respectively. + pipe(); +}; + +// Returns the memory page size. +auto getpagesize() -> long; + +namespace detail { + +struct buffer_size { + buffer_size() = default; + size_t value = 0; + auto operator=(size_t val) const -> buffer_size { + auto bs = buffer_size(); + bs.value = val; + return bs; + } +}; + +struct ostream_params { + int oflag = file::WRONLY | file::CREATE | file::TRUNC; + size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768; + + ostream_params() {} + + template + ostream_params(T... params, int new_oflag) : ostream_params(params...) { + oflag = new_oflag; + } + + template + ostream_params(T... params, detail::buffer_size bs) + : ostream_params(params...) { + this->buffer_size = bs.value; + } + +// Intel has a bug that results in failure to deduce a constructor +// for empty parameter packs. +# if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 2000 + ostream_params(int new_oflag) : oflag(new_oflag) {} + ostream_params(detail::buffer_size bs) : buffer_size(bs.value) {} +# endif +}; + +class file_buffer final : public buffer { + private: + file file_; + + FMT_API static void grow(buffer& buf, size_t); + + public: + FMT_API file_buffer(cstring_view path, const ostream_params& params); + FMT_API file_buffer(file_buffer&& other) noexcept; + FMT_API ~file_buffer(); + + void flush() { + if (size() == 0) return; + file_.write(data(), size() * sizeof(data()[0])); + clear(); + } + + void close() { + flush(); + file_.close(); + } +}; + +} // namespace detail + +constexpr auto buffer_size = detail::buffer_size(); + +/// A fast output stream for writing from a single thread. Writing from +/// multiple threads without external synchronization may result in a data race. +class FMT_API ostream { + private: + FMT_MSC_WARNING(suppress : 4251) + detail::file_buffer buffer_; + + ostream(cstring_view path, const detail::ostream_params& params) + : buffer_(path, params) {} + + public: + ostream(ostream&& other) : buffer_(std::move(other.buffer_)) {} + + ~ostream(); + + void flush() { buffer_.flush(); } + + template + friend auto output_file(cstring_view path, T... params) -> ostream; + + void close() { buffer_.close(); } + + /// Formats `args` according to specifications in `fmt` and writes the + /// output to the file. + template void print(format_string fmt, T&&... args) { + vformat_to(appender(buffer_), fmt, fmt::make_format_args(args...)); + } +}; + +/** + * Opens a file for writing. Supported parameters passed in `params`: + * + * - ``: Flags passed to [open]( + * https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html) + * (`file::WRONLY | file::CREATE | file::TRUNC` by default) + * - `buffer_size=`: Output buffer size + * + * **Example**: + * + * auto out = fmt::output_file("guide.txt"); + * out.print("Don't {}", "Panic"); + */ +template +inline auto output_file(cstring_view path, T... params) -> ostream { + return {path, detail::ostream_params(params...)}; +} +#endif // FMT_USE_FCNTL + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_OS_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/ostream.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/ostream.h new file mode 100644 index 0000000..98faef6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/ostream.h @@ -0,0 +1,211 @@ +// Formatting library for C++ - std::ostream support +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_OSTREAM_H_ +#define FMT_OSTREAM_H_ + +#ifndef FMT_MODULE +# include // std::filebuf +#endif + +#ifdef _WIN32 +# ifdef __GLIBCXX__ +# include +# include +# endif +# include +#endif + +#include "chrono.h" // formatbuf + +FMT_BEGIN_NAMESPACE +namespace detail { + +// Generate a unique explicit instantion in every translation unit using a tag +// type in an anonymous namespace. +namespace { +struct file_access_tag {}; +} // namespace +template +class file_access { + friend auto get_file(BufType& obj) -> FILE* { return obj.*FileMemberPtr; } +}; + +#if FMT_MSC_VERSION +template class file_access; +auto get_file(std::filebuf&) -> FILE*; +#endif + +inline auto write_ostream_unicode(std::ostream& os, fmt::string_view data) + -> bool { + FILE* f = nullptr; +#if FMT_MSC_VERSION && FMT_USE_RTTI + if (auto* buf = dynamic_cast(os.rdbuf())) + f = get_file(*buf); + else + return false; +#elif defined(_WIN32) && defined(__GLIBCXX__) && FMT_USE_RTTI + auto* rdbuf = os.rdbuf(); + if (auto* sfbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf*>(rdbuf)) + f = sfbuf->file(); + else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf*>(rdbuf)) + f = fbuf->file(); + else + return false; +#else + ignore_unused(os, data, f); +#endif +#ifdef _WIN32 + if (f) { + int fd = _fileno(f); + if (_isatty(fd)) { + os.flush(); + return write_console(fd, data); + } + } +#endif + return false; +} +inline auto write_ostream_unicode(std::wostream&, + fmt::basic_string_view) -> bool { + return false; +} + +// Write the content of buf to os. +// It is a separate function rather than a part of vprint to simplify testing. +template +void write_buffer(std::basic_ostream& os, buffer& buf) { + const Char* buf_data = buf.data(); + using unsigned_streamsize = std::make_unsigned::type; + unsigned_streamsize size = buf.size(); + unsigned_streamsize max_size = to_unsigned(max_value()); + do { + unsigned_streamsize n = size <= max_size ? size : max_size; + os.write(buf_data, static_cast(n)); + buf_data += n; + size -= n; + } while (size != 0); +} + +template +void format_value(buffer& buf, const T& value) { + auto&& format_buf = formatbuf>(buf); + auto&& output = std::basic_ostream(&format_buf); +#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) + output.imbue(std::locale::classic()); // The default is always unlocalized. +#endif + output << value; + output.exceptions(std::ios_base::failbit | std::ios_base::badbit); +} + +template struct streamed_view { + const T& value; +}; + +} // namespace detail + +// Formats an object of type T that has an overloaded ostream operator<<. +template +struct basic_ostream_formatter : formatter, Char> { + void set_debug_format() = delete; + + template + auto format(const T& value, Context& ctx) const -> decltype(ctx.out()) { + auto buffer = basic_memory_buffer(); + detail::format_value(buffer, value); + return formatter, Char>::format( + {buffer.data(), buffer.size()}, ctx); + } +}; + +using ostream_formatter = basic_ostream_formatter; + +template +struct formatter, Char> + : basic_ostream_formatter { + template + auto format(detail::streamed_view view, Context& ctx) const + -> decltype(ctx.out()) { + return basic_ostream_formatter::format(view.value, ctx); + } +}; + +/** + * Returns a view that formats `value` via an ostream `operator<<`. + * + * **Example**: + * + * fmt::print("Current thread id: {}\n", + * fmt::streamed(std::this_thread::get_id())); + */ +template +constexpr auto streamed(const T& value) -> detail::streamed_view { + return {value}; +} + +namespace detail { + +inline void vprint_directly(std::ostream& os, string_view format_str, + format_args args) { + auto buffer = memory_buffer(); + detail::vformat_to(buffer, format_str, args); + detail::write_buffer(os, buffer); +} + +} // namespace detail + +FMT_EXPORT template +void vprint(std::basic_ostream& os, + basic_string_view> format_str, + typename detail::vformat_args::type args) { + auto buffer = basic_memory_buffer(); + detail::vformat_to(buffer, format_str, args); + if (detail::write_ostream_unicode(os, {buffer.data(), buffer.size()})) return; + detail::write_buffer(os, buffer); +} + +/** + * Prints formatted data to the stream `os`. + * + * **Example**: + * + * fmt::print(cerr, "Don't {}!", "panic"); + */ +FMT_EXPORT template +void print(std::ostream& os, format_string fmt, T&&... args) { + const auto& vargs = fmt::make_format_args(args...); + if (detail::use_utf8()) + vprint(os, fmt, vargs); + else + detail::vprint_directly(os, fmt, vargs); +} + +FMT_EXPORT +template +void print(std::wostream& os, + basic_format_string...> fmt, + Args&&... args) { + vprint(os, fmt, fmt::make_format_args>(args...)); +} + +FMT_EXPORT template +void println(std::ostream& os, format_string fmt, T&&... args) { + fmt::print(os, "{}\n", fmt::format(fmt, std::forward(args)...)); +} + +FMT_EXPORT +template +void println(std::wostream& os, + basic_format_string...> fmt, + Args&&... args) { + print(os, L"{}\n", fmt::format(fmt, std::forward(args)...)); +} + +FMT_END_NAMESPACE + +#endif // FMT_OSTREAM_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/printf.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/printf.h new file mode 100644 index 0000000..072cc6b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/printf.h @@ -0,0 +1,656 @@ +// Formatting library for C++ - legacy printf implementation +// +// Copyright (c) 2012 - 2016, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_PRINTF_H_ +#define FMT_PRINTF_H_ + +#ifndef FMT_MODULE +# include // std::max +# include // std::numeric_limits +#endif + +#include "format.h" + +FMT_BEGIN_NAMESPACE +FMT_BEGIN_EXPORT + +template struct printf_formatter { + printf_formatter() = delete; +}; + +template class basic_printf_context { + private: + basic_appender out_; + basic_format_args args_; + + static_assert(std::is_same::value || + std::is_same::value, + "Unsupported code unit type."); + + public: + using char_type = Char; + using parse_context_type = basic_format_parse_context; + template using formatter_type = printf_formatter; + + /// Constructs a `printf_context` object. References to the arguments are + /// stored in the context object so make sure they have appropriate lifetimes. + basic_printf_context(basic_appender out, + basic_format_args args) + : out_(out), args_(args) {} + + auto out() -> basic_appender { return out_; } + void advance_to(basic_appender) {} + + auto locale() -> detail::locale_ref { return {}; } + + auto arg(int id) const -> basic_format_arg { + return args_.get(id); + } +}; + +namespace detail { + +// Checks if a value fits in int - used to avoid warnings about comparing +// signed and unsigned integers. +template struct int_checker { + template static auto fits_in_int(T value) -> bool { + unsigned max = to_unsigned(max_value()); + return value <= max; + } + static auto fits_in_int(bool) -> bool { return true; } +}; + +template <> struct int_checker { + template static auto fits_in_int(T value) -> bool { + return value >= (std::numeric_limits::min)() && + value <= max_value(); + } + static auto fits_in_int(int) -> bool { return true; } +}; + +struct printf_precision_handler { + template ::value)> + auto operator()(T value) -> int { + if (!int_checker::is_signed>::fits_in_int(value)) + report_error("number is too big"); + return (std::max)(static_cast(value), 0); + } + + template ::value)> + auto operator()(T) -> int { + report_error("precision is not integer"); + return 0; + } +}; + +// An argument visitor that returns true iff arg is a zero integer. +struct is_zero_int { + template ::value)> + auto operator()(T value) -> bool { + return value == 0; + } + + template ::value)> + auto operator()(T) -> bool { + return false; + } +}; + +template struct make_unsigned_or_bool : std::make_unsigned {}; + +template <> struct make_unsigned_or_bool { + using type = bool; +}; + +template class arg_converter { + private: + using char_type = typename Context::char_type; + + basic_format_arg& arg_; + char_type type_; + + public: + arg_converter(basic_format_arg& arg, char_type type) + : arg_(arg), type_(type) {} + + void operator()(bool value) { + if (type_ != 's') operator()(value); + } + + template ::value)> + void operator()(U value) { + bool is_signed = type_ == 'd' || type_ == 'i'; + using target_type = conditional_t::value, U, T>; + if (const_check(sizeof(target_type) <= sizeof(int))) { + // Extra casts are used to silence warnings. + if (is_signed) { + auto n = static_cast(static_cast(value)); + arg_ = detail::make_arg(n); + } else { + using unsigned_type = typename make_unsigned_or_bool::type; + auto n = static_cast(static_cast(value)); + arg_ = detail::make_arg(n); + } + } else { + if (is_signed) { + // glibc's printf doesn't sign extend arguments of smaller types: + // std::printf("%lld", -42); // prints "4294967254" + // but we don't have to do the same because it's a UB. + auto n = static_cast(value); + arg_ = detail::make_arg(n); + } else { + auto n = static_cast::type>(value); + arg_ = detail::make_arg(n); + } + } + } + + template ::value)> + void operator()(U) {} // No conversion needed for non-integral types. +}; + +// Converts an integer argument to T for printf, if T is an integral type. +// If T is void, the argument is converted to corresponding signed or unsigned +// type depending on the type specifier: 'd' and 'i' - signed, other - +// unsigned). +template +void convert_arg(basic_format_arg& arg, Char type) { + arg.visit(arg_converter(arg, type)); +} + +// Converts an integer argument to char for printf. +template class char_converter { + private: + basic_format_arg& arg_; + + public: + explicit char_converter(basic_format_arg& arg) : arg_(arg) {} + + template ::value)> + void operator()(T value) { + auto c = static_cast(value); + arg_ = detail::make_arg(c); + } + + template ::value)> + void operator()(T) {} // No conversion needed for non-integral types. +}; + +// An argument visitor that return a pointer to a C string if argument is a +// string or null otherwise. +template struct get_cstring { + template auto operator()(T) -> const Char* { return nullptr; } + auto operator()(const Char* s) -> const Char* { return s; } +}; + +// Checks if an argument is a valid printf width specifier and sets +// left alignment if it is negative. +class printf_width_handler { + private: + format_specs& specs_; + + public: + explicit printf_width_handler(format_specs& specs) : specs_(specs) {} + + template ::value)> + auto operator()(T value) -> unsigned { + auto width = static_cast>(value); + if (detail::is_negative(value)) { + specs_.align = align::left; + width = 0 - width; + } + unsigned int_max = to_unsigned(max_value()); + if (width > int_max) report_error("number is too big"); + return static_cast(width); + } + + template ::value)> + auto operator()(T) -> unsigned { + report_error("width is not integer"); + return 0; + } +}; + +// Workaround for a bug with the XL compiler when initializing +// printf_arg_formatter's base class. +template +auto make_arg_formatter(basic_appender iter, format_specs& s) + -> arg_formatter { + return {iter, s, locale_ref()}; +} + +// The `printf` argument formatter. +template +class printf_arg_formatter : public arg_formatter { + private: + using base = arg_formatter; + using context_type = basic_printf_context; + + context_type& context_; + + void write_null_pointer(bool is_string = false) { + auto s = this->specs; + s.type = presentation_type::none; + write_bytes(this->out, is_string ? "(null)" : "(nil)", s); + } + + public: + printf_arg_formatter(basic_appender iter, format_specs& s, + context_type& ctx) + : base(make_arg_formatter(iter, s)), context_(ctx) {} + + void operator()(monostate value) { base::operator()(value); } + + template ::value)> + void operator()(T value) { + // MSVC2013 fails to compile separate overloads for bool and Char so use + // std::is_same instead. + if (!std::is_same::value) { + base::operator()(value); + return; + } + format_specs s = this->specs; + if (s.type != presentation_type::none && s.type != presentation_type::chr) { + return (*this)(static_cast(value)); + } + s.sign = sign::none; + s.alt = false; + s.fill = ' '; // Ignore '0' flag for char types. + // align::numeric needs to be overwritten here since the '0' flag is + // ignored for non-numeric types + if (s.align == align::none || s.align == align::numeric) + s.align = align::right; + write(this->out, static_cast(value), s); + } + + template ::value)> + void operator()(T value) { + base::operator()(value); + } + + void operator()(const char* value) { + if (value) + base::operator()(value); + else + write_null_pointer(this->specs.type != presentation_type::pointer); + } + + void operator()(const wchar_t* value) { + if (value) + base::operator()(value); + else + write_null_pointer(this->specs.type != presentation_type::pointer); + } + + void operator()(basic_string_view value) { base::operator()(value); } + + void operator()(const void* value) { + if (value) + base::operator()(value); + else + write_null_pointer(); + } + + void operator()(typename basic_format_arg::handle handle) { + auto parse_ctx = basic_format_parse_context({}); + handle.format(parse_ctx, context_); + } +}; + +template +void parse_flags(format_specs& specs, const Char*& it, const Char* end) { + for (; it != end; ++it) { + switch (*it) { + case '-': + specs.align = align::left; + break; + case '+': + specs.sign = sign::plus; + break; + case '0': + specs.fill = '0'; + break; + case ' ': + if (specs.sign != sign::plus) specs.sign = sign::space; + break; + case '#': + specs.alt = true; + break; + default: + return; + } + } +} + +template +auto parse_header(const Char*& it, const Char* end, format_specs& specs, + GetArg get_arg) -> int { + int arg_index = -1; + Char c = *it; + if (c >= '0' && c <= '9') { + // Parse an argument index (if followed by '$') or a width possibly + // preceded with '0' flag(s). + int value = parse_nonnegative_int(it, end, -1); + if (it != end && *it == '$') { // value is an argument index + ++it; + arg_index = value != -1 ? value : max_value(); + } else { + if (c == '0') specs.fill = '0'; + if (value != 0) { + // Nonzero value means that we parsed width and don't need to + // parse it or flags again, so return now. + if (value == -1) report_error("number is too big"); + specs.width = value; + return arg_index; + } + } + } + parse_flags(specs, it, end); + // Parse width. + if (it != end) { + if (*it >= '0' && *it <= '9') { + specs.width = parse_nonnegative_int(it, end, -1); + if (specs.width == -1) report_error("number is too big"); + } else if (*it == '*') { + ++it; + specs.width = static_cast( + get_arg(-1).visit(detail::printf_width_handler(specs))); + } + } + return arg_index; +} + +inline auto parse_printf_presentation_type(char c, type t, bool& upper) + -> presentation_type { + using pt = presentation_type; + constexpr auto integral_set = sint_set | uint_set | bool_set | char_set; + switch (c) { + case 'd': + return in(t, integral_set) ? pt::dec : pt::none; + case 'o': + return in(t, integral_set) ? pt::oct : pt::none; + case 'X': + upper = true; + FMT_FALLTHROUGH; + case 'x': + return in(t, integral_set) ? pt::hex : pt::none; + case 'E': + upper = true; + FMT_FALLTHROUGH; + case 'e': + return in(t, float_set) ? pt::exp : pt::none; + case 'F': + upper = true; + FMT_FALLTHROUGH; + case 'f': + return in(t, float_set) ? pt::fixed : pt::none; + case 'G': + upper = true; + FMT_FALLTHROUGH; + case 'g': + return in(t, float_set) ? pt::general : pt::none; + case 'A': + upper = true; + FMT_FALLTHROUGH; + case 'a': + return in(t, float_set) ? pt::hexfloat : pt::none; + case 'c': + return in(t, integral_set) ? pt::chr : pt::none; + case 's': + return in(t, string_set | cstring_set) ? pt::string : pt::none; + case 'p': + return in(t, pointer_set | cstring_set) ? pt::pointer : pt::none; + default: + return pt::none; + } +} + +template +void vprintf(buffer& buf, basic_string_view format, + basic_format_args args) { + using iterator = basic_appender; + auto out = iterator(buf); + auto context = basic_printf_context(out, args); + auto parse_ctx = basic_format_parse_context(format); + + // Returns the argument with specified index or, if arg_index is -1, the next + // argument. + auto get_arg = [&](int arg_index) { + if (arg_index < 0) + arg_index = parse_ctx.next_arg_id(); + else + parse_ctx.check_arg_id(--arg_index); + return detail::get_arg(context, arg_index); + }; + + const Char* start = parse_ctx.begin(); + const Char* end = parse_ctx.end(); + auto it = start; + while (it != end) { + if (!find(it, end, '%', it)) { + it = end; // find leaves it == nullptr if it doesn't find '%'. + break; + } + Char c = *it++; + if (it != end && *it == c) { + write(out, basic_string_view(start, to_unsigned(it - start))); + start = ++it; + continue; + } + write(out, basic_string_view(start, to_unsigned(it - 1 - start))); + + auto specs = format_specs(); + specs.align = align::right; + + // Parse argument index, flags and width. + int arg_index = parse_header(it, end, specs, get_arg); + if (arg_index == 0) report_error("argument not found"); + + // Parse precision. + if (it != end && *it == '.') { + ++it; + c = it != end ? *it : 0; + if ('0' <= c && c <= '9') { + specs.precision = parse_nonnegative_int(it, end, 0); + } else if (c == '*') { + ++it; + specs.precision = + static_cast(get_arg(-1).visit(printf_precision_handler())); + } else { + specs.precision = 0; + } + } + + auto arg = get_arg(arg_index); + // For d, i, o, u, x, and X conversion specifiers, if a precision is + // specified, the '0' flag is ignored + if (specs.precision >= 0 && arg.is_integral()) { + // Ignore '0' for non-numeric types or if '-' present. + specs.fill = ' '; + } + if (specs.precision >= 0 && arg.type() == type::cstring_type) { + auto str = arg.visit(get_cstring()); + auto str_end = str + specs.precision; + auto nul = std::find(str, str_end, Char()); + auto sv = basic_string_view( + str, to_unsigned(nul != str_end ? nul - str : specs.precision)); + arg = make_arg>(sv); + } + if (specs.alt && arg.visit(is_zero_int())) specs.alt = false; + if (specs.fill.template get() == '0') { + if (arg.is_arithmetic() && specs.align != align::left) + specs.align = align::numeric; + else + specs.fill = ' '; // Ignore '0' flag for non-numeric types or if '-' + // flag is also present. + } + + // Parse length and convert the argument to the required type. + c = it != end ? *it++ : 0; + Char t = it != end ? *it : 0; + switch (c) { + case 'h': + if (t == 'h') { + ++it; + t = it != end ? *it : 0; + convert_arg(arg, t); + } else { + convert_arg(arg, t); + } + break; + case 'l': + if (t == 'l') { + ++it; + t = it != end ? *it : 0; + convert_arg(arg, t); + } else { + convert_arg(arg, t); + } + break; + case 'j': + convert_arg(arg, t); + break; + case 'z': + convert_arg(arg, t); + break; + case 't': + convert_arg(arg, t); + break; + case 'L': + // printf produces garbage when 'L' is omitted for long double, no + // need to do the same. + break; + default: + --it; + convert_arg(arg, c); + } + + // Parse type. + if (it == end) report_error("invalid format string"); + char type = static_cast(*it++); + if (arg.is_integral()) { + // Normalize type. + switch (type) { + case 'i': + case 'u': + type = 'd'; + break; + case 'c': + arg.visit(char_converter>(arg)); + break; + } + } + bool upper = false; + specs.type = parse_printf_presentation_type(type, arg.type(), upper); + if (specs.type == presentation_type::none) + report_error("invalid format specifier"); + specs.upper = upper; + + start = it; + + // Format argument. + arg.visit(printf_arg_formatter(out, specs, context)); + } + write(out, basic_string_view(start, to_unsigned(it - start))); +} +} // namespace detail + +using printf_context = basic_printf_context; +using wprintf_context = basic_printf_context; + +using printf_args = basic_format_args; +using wprintf_args = basic_format_args; + +/// Constructs an `format_arg_store` object that contains references to +/// arguments and can be implicitly converted to `printf_args`. +template +inline auto make_printf_args(T&... args) + -> decltype(fmt::make_format_args>(args...)) { + return fmt::make_format_args>(args...); +} + +template struct vprintf_args { + using type = basic_format_args>; +}; + +template +inline auto vsprintf(basic_string_view fmt, + typename vprintf_args::type args) + -> std::basic_string { + auto buf = basic_memory_buffer(); + detail::vprintf(buf, fmt, args); + return to_string(buf); +} + +/** + * Formats `args` according to specifications in `fmt` and returns the result + * as as string. + * + * **Example**: + * + * std::string message = fmt::sprintf("The answer is %d", 42); + */ +template > +inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string { + return vsprintf(detail::to_string_view(fmt), + fmt::make_format_args>(args...)); +} + +template +inline auto vfprintf(std::FILE* f, basic_string_view fmt, + typename vprintf_args::type args) -> int { + auto buf = basic_memory_buffer(); + detail::vprintf(buf, fmt, args); + size_t size = buf.size(); + return std::fwrite(buf.data(), sizeof(Char), size, f) < size + ? -1 + : static_cast(size); +} + +/** + * Formats `args` according to specifications in `fmt` and writes the output + * to `f`. + * + * **Example**: + * + * fmt::fprintf(stderr, "Don't %s!", "panic"); + */ +template > +inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int { + return vfprintf(f, detail::to_string_view(fmt), + make_printf_args(args...)); +} + +template +FMT_DEPRECATED inline auto vprintf(basic_string_view fmt, + typename vprintf_args::type args) + -> int { + return vfprintf(stdout, fmt, args); +} + +/** + * Formats `args` according to specifications in `fmt` and writes the output + * to `stdout`. + * + * **Example**: + * + * fmt::printf("Elapsed time: %.2f seconds", 1.23); + */ +template +inline auto printf(string_view fmt, const T&... args) -> int { + return vfprintf(stdout, fmt, make_printf_args(args...)); +} +template +FMT_DEPRECATED inline auto printf(basic_string_view fmt, + const T&... args) -> int { + return vfprintf(stdout, fmt, make_printf_args(args...)); +} + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_PRINTF_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/ranges.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/ranges.h new file mode 100644 index 0000000..0d3dfbd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/ranges.h @@ -0,0 +1,882 @@ +// Formatting library for C++ - range and tuple support +// +// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_RANGES_H_ +#define FMT_RANGES_H_ + +#ifndef FMT_MODULE +# include +# include +# include +# include +# include +# include +#endif + +#include "format.h" + +FMT_BEGIN_NAMESPACE + +FMT_EXPORT +enum class range_format { disabled, map, set, sequence, string, debug_string }; + +namespace detail { + +template class is_map { + template static auto check(U*) -> typename U::mapped_type; + template static void check(...); + + public: + static constexpr const bool value = + !std::is_void(nullptr))>::value; +}; + +template class is_set { + template static auto check(U*) -> typename U::key_type; + template static void check(...); + + public: + static constexpr const bool value = + !std::is_void(nullptr))>::value && !is_map::value; +}; + +template struct conditional_helper {}; + +template struct is_range_ : std::false_type {}; + +#if !FMT_MSC_VERSION || FMT_MSC_VERSION > 1800 + +# define FMT_DECLTYPE_RETURN(val) \ + ->decltype(val) { return val; } \ + static_assert( \ + true, "") // This makes it so that a semicolon is required after the + // macro, which helps clang-format handle the formatting. + +// C array overload +template +auto range_begin(const T (&arr)[N]) -> const T* { + return arr; +} +template +auto range_end(const T (&arr)[N]) -> const T* { + return arr + N; +} + +template +struct has_member_fn_begin_end_t : std::false_type {}; + +template +struct has_member_fn_begin_end_t().begin()), + decltype(std::declval().end())>> + : std::true_type {}; + +// Member function overloads. +template +auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast(rng).begin()); +template +auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast(rng).end()); + +// ADL overloads. Only participate in overload resolution if member functions +// are not found. +template +auto range_begin(T&& rng) + -> enable_if_t::value, + decltype(begin(static_cast(rng)))> { + return begin(static_cast(rng)); +} +template +auto range_end(T&& rng) -> enable_if_t::value, + decltype(end(static_cast(rng)))> { + return end(static_cast(rng)); +} + +template +struct has_const_begin_end : std::false_type {}; +template +struct has_mutable_begin_end : std::false_type {}; + +template +struct has_const_begin_end< + T, void_t&>())), + decltype(detail::range_end( + std::declval&>()))>> + : std::true_type {}; + +template +struct has_mutable_begin_end< + T, void_t())), + decltype(detail::range_end(std::declval())), + // the extra int here is because older versions of MSVC don't + // SFINAE properly unless there are distinct types + int>> : std::true_type {}; + +template +struct is_range_ + : std::integral_constant::value || + has_mutable_begin_end::value)> {}; +# undef FMT_DECLTYPE_RETURN +#endif + +// tuple_size and tuple_element check. +template class is_tuple_like_ { + template + static auto check(U* p) -> decltype(std::tuple_size::value, int()); + template static void check(...); + + public: + static constexpr const bool value = + !std::is_void(nullptr))>::value; +}; + +// Check for integer_sequence +#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VERSION >= 1900 +template +using integer_sequence = std::integer_sequence; +template using index_sequence = std::index_sequence; +template using make_index_sequence = std::make_index_sequence; +#else +template struct integer_sequence { + using value_type = T; + + static FMT_CONSTEXPR auto size() -> size_t { return sizeof...(N); } +}; + +template using index_sequence = integer_sequence; + +template +struct make_integer_sequence : make_integer_sequence {}; +template +struct make_integer_sequence : integer_sequence {}; + +template +using make_index_sequence = make_integer_sequence; +#endif + +template +using tuple_index_sequence = make_index_sequence::value>; + +template ::value> +class is_tuple_formattable_ { + public: + static constexpr const bool value = false; +}; +template class is_tuple_formattable_ { + template + static auto all_true(index_sequence, + integer_sequence= 0)...>) -> std::true_type; + static auto all_true(...) -> std::false_type; + + template + static auto check(index_sequence) -> decltype(all_true( + index_sequence{}, + integer_sequence::type, + C>::value)...>{})); + + public: + static constexpr const bool value = + decltype(check(tuple_index_sequence{}))::value; +}; + +template +FMT_CONSTEXPR void for_each(index_sequence, Tuple&& t, F&& f) { + using std::get; + // Using a free function get(Tuple) now. + const int unused[] = {0, ((void)f(get(t)), 0)...}; + ignore_unused(unused); +} + +template +FMT_CONSTEXPR void for_each(Tuple&& t, F&& f) { + for_each(tuple_index_sequence>(), + std::forward(t), std::forward(f)); +} + +template +void for_each2(index_sequence, Tuple1&& t1, Tuple2&& t2, F&& f) { + using std::get; + const int unused[] = {0, ((void)f(get(t1), get(t2)), 0)...}; + ignore_unused(unused); +} + +template +void for_each2(Tuple1&& t1, Tuple2&& t2, F&& f) { + for_each2(tuple_index_sequence>(), + std::forward(t1), std::forward(t2), + std::forward(f)); +} + +namespace tuple { +// Workaround a bug in MSVC 2019 (v140). +template +using result_t = std::tuple, Char>...>; + +using std::get; +template +auto get_formatters(index_sequence) + -> result_t(std::declval()))...>; +} // namespace tuple + +#if FMT_MSC_VERSION && FMT_MSC_VERSION < 1920 +// Older MSVC doesn't get the reference type correctly for arrays. +template struct range_reference_type_impl { + using type = decltype(*detail::range_begin(std::declval())); +}; + +template struct range_reference_type_impl { + using type = T&; +}; + +template +using range_reference_type = typename range_reference_type_impl::type; +#else +template +using range_reference_type = + decltype(*detail::range_begin(std::declval())); +#endif + +// We don't use the Range's value_type for anything, but we do need the Range's +// reference type, with cv-ref stripped. +template +using uncvref_type = remove_cvref_t>; + +template +FMT_CONSTEXPR auto maybe_set_debug_format(Formatter& f, bool set) + -> decltype(f.set_debug_format(set)) { + f.set_debug_format(set); +} +template +FMT_CONSTEXPR void maybe_set_debug_format(Formatter&, ...) {} + +template +struct range_format_kind_ + : std::integral_constant, T>::value + ? range_format::disabled + : is_map::value ? range_format::map + : is_set::value ? range_format::set + : range_format::sequence> {}; + +template +using range_format_constant = std::integral_constant; + +// These are not generic lambdas for compatibility with C++11. +template struct parse_empty_specs { + template FMT_CONSTEXPR void operator()(Formatter& f) { + f.parse(ctx); + detail::maybe_set_debug_format(f, true); + } + ParseContext& ctx; +}; +template struct format_tuple_element { + using char_type = typename FormatContext::char_type; + + template + void operator()(const formatter& f, const T& v) { + if (i > 0) ctx.advance_to(detail::copy(separator, ctx.out())); + ctx.advance_to(f.format(v, ctx)); + ++i; + } + + int i; + FormatContext& ctx; + basic_string_view separator; +}; + +} // namespace detail + +template struct is_tuple_like { + static constexpr const bool value = + detail::is_tuple_like_::value && !detail::is_range_::value; +}; + +template struct is_tuple_formattable { + static constexpr const bool value = + detail::is_tuple_formattable_::value; +}; + +template +struct formatter::value && + fmt::is_tuple_formattable::value>> { + private: + decltype(detail::tuple::get_formatters( + detail::tuple_index_sequence())) formatters_; + + basic_string_view separator_ = detail::string_literal{}; + basic_string_view opening_bracket_ = + detail::string_literal{}; + basic_string_view closing_bracket_ = + detail::string_literal{}; + + public: + FMT_CONSTEXPR formatter() {} + + FMT_CONSTEXPR void set_separator(basic_string_view sep) { + separator_ = sep; + } + + FMT_CONSTEXPR void set_brackets(basic_string_view open, + basic_string_view close) { + opening_bracket_ = open; + closing_bracket_ = close; + } + + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + auto it = ctx.begin(); + if (it != ctx.end() && *it != '}') report_error("invalid format specifier"); + detail::for_each(formatters_, detail::parse_empty_specs{ctx}); + return it; + } + + template + auto format(const Tuple& value, FormatContext& ctx) const + -> decltype(ctx.out()) { + ctx.advance_to(detail::copy(opening_bracket_, ctx.out())); + detail::for_each2( + formatters_, value, + detail::format_tuple_element{0, ctx, separator_}); + return detail::copy(closing_bracket_, ctx.out()); + } +}; + +template struct is_range { + static constexpr const bool value = + detail::is_range_::value && !detail::has_to_string_view::value; +}; + +namespace detail { +template struct range_mapper { + using mapper = arg_mapper; + + template , Context>::value)> + static auto map(T&& value) -> T&& { + return static_cast(value); + } + template , Context>::value)> + static auto map(T&& value) + -> decltype(mapper().map(static_cast(value))) { + return mapper().map(static_cast(value)); + } +}; + +template +using range_formatter_type = + formatter>{} + .map(std::declval()))>, + Char>; + +template +using maybe_const_range = + conditional_t::value, const R, R>; + +// Workaround a bug in MSVC 2015 and earlier. +#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910 +template +struct is_formattable_delayed + : is_formattable>, Char> {}; +#endif +} // namespace detail + +template struct conjunction : std::true_type {}; +template struct conjunction

: P {}; +template +struct conjunction + : conditional_t, P1> {}; + +template +struct range_formatter; + +template +struct range_formatter< + T, Char, + enable_if_t>, + is_formattable>::value>> { + private: + detail::range_formatter_type underlying_; + basic_string_view separator_ = detail::string_literal{}; + basic_string_view opening_bracket_ = + detail::string_literal{}; + basic_string_view closing_bracket_ = + detail::string_literal{}; + bool is_debug = false; + + template ::value)> + auto write_debug_string(Output& out, It it, Sentinel end) const -> Output { + auto buf = basic_memory_buffer(); + for (; it != end; ++it) buf.push_back(*it); + auto specs = format_specs(); + specs.type = presentation_type::debug; + return detail::write( + out, basic_string_view(buf.data(), buf.size()), specs); + } + + template ::value)> + auto write_debug_string(Output& out, It, Sentinel) const -> Output { + return out; + } + + public: + FMT_CONSTEXPR range_formatter() {} + + FMT_CONSTEXPR auto underlying() -> detail::range_formatter_type& { + return underlying_; + } + + FMT_CONSTEXPR void set_separator(basic_string_view sep) { + separator_ = sep; + } + + FMT_CONSTEXPR void set_brackets(basic_string_view open, + basic_string_view close) { + opening_bracket_ = open; + closing_bracket_ = close; + } + + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + auto it = ctx.begin(); + auto end = ctx.end(); + detail::maybe_set_debug_format(underlying_, true); + if (it == end) return underlying_.parse(ctx); + + switch (detail::to_ascii(*it)) { + case 'n': + set_brackets({}, {}); + ++it; + break; + case '?': + is_debug = true; + set_brackets({}, {}); + ++it; + if (it == end || *it != 's') report_error("invalid format specifier"); + FMT_FALLTHROUGH; + case 's': + if (!std::is_same::value) + report_error("invalid format specifier"); + if (!is_debug) { + set_brackets(detail::string_literal{}, + detail::string_literal{}); + set_separator({}); + detail::maybe_set_debug_format(underlying_, false); + } + ++it; + return it; + } + + if (it != end && *it != '}') { + if (*it != ':') report_error("invalid format specifier"); + detail::maybe_set_debug_format(underlying_, false); + ++it; + } + + ctx.advance_to(it); + return underlying_.parse(ctx); + } + + template + auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) { + auto mapper = detail::range_mapper>(); + auto out = ctx.out(); + auto it = detail::range_begin(range); + auto end = detail::range_end(range); + if (is_debug) return write_debug_string(out, std::move(it), end); + + out = detail::copy(opening_bracket_, out); + int i = 0; + for (; it != end; ++it) { + if (i > 0) out = detail::copy(separator_, out); + ctx.advance_to(out); + auto&& item = *it; // Need an lvalue + out = underlying_.format(mapper.map(item), ctx); + ++i; + } + out = detail::copy(closing_bracket_, out); + return out; + } +}; + +FMT_EXPORT +template +struct range_format_kind + : conditional_t< + is_range::value, detail::range_format_kind_, + std::integral_constant> {}; + +template +struct formatter< + R, Char, + enable_if_t::value != range_format::disabled && + range_format_kind::value != range_format::map && + range_format_kind::value != range_format::string && + range_format_kind::value != range_format::debug_string> +// Workaround a bug in MSVC 2015 and earlier. +#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910 + , + detail::is_formattable_delayed +#endif + >::value>> { + private: + using range_type = detail::maybe_const_range; + range_formatter, Char> range_formatter_; + + public: + using nonlocking = void; + + FMT_CONSTEXPR formatter() { + if (detail::const_check(range_format_kind::value != + range_format::set)) + return; + range_formatter_.set_brackets(detail::string_literal{}, + detail::string_literal{}); + } + + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return range_formatter_.parse(ctx); + } + + template + auto format(range_type& range, FormatContext& ctx) const + -> decltype(ctx.out()) { + return range_formatter_.format(range, ctx); + } +}; + +// A map formatter. +template +struct formatter< + R, Char, + enable_if_t::value == range_format::map>> { + private: + using map_type = detail::maybe_const_range; + using element_type = detail::uncvref_type; + + decltype(detail::tuple::get_formatters( + detail::tuple_index_sequence())) formatters_; + bool no_delimiters_ = false; + + public: + FMT_CONSTEXPR formatter() {} + + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + auto it = ctx.begin(); + auto end = ctx.end(); + if (it != end) { + if (detail::to_ascii(*it) == 'n') { + no_delimiters_ = true; + ++it; + } + if (it != end && *it != '}') { + if (*it != ':') report_error("invalid format specifier"); + ++it; + } + ctx.advance_to(it); + } + detail::for_each(formatters_, detail::parse_empty_specs{ctx}); + return it; + } + + template + auto format(map_type& map, FormatContext& ctx) const -> decltype(ctx.out()) { + auto out = ctx.out(); + basic_string_view open = detail::string_literal{}; + if (!no_delimiters_) out = detail::copy(open, out); + int i = 0; + auto mapper = detail::range_mapper>(); + basic_string_view sep = detail::string_literal{}; + for (auto&& value : map) { + if (i > 0) out = detail::copy(sep, out); + ctx.advance_to(out); + detail::for_each2(formatters_, mapper.map(value), + detail::format_tuple_element{ + 0, ctx, detail::string_literal{}}); + ++i; + } + basic_string_view close = detail::string_literal{}; + if (!no_delimiters_) out = detail::copy(close, out); + return out; + } +}; + +// A (debug_)string formatter. +template +struct formatter< + R, Char, + enable_if_t::value == range_format::string || + range_format_kind::value == + range_format::debug_string>> { + private: + using range_type = detail::maybe_const_range; + using string_type = + conditional_t, + decltype(detail::range_begin(std::declval())), + decltype(detail::range_end(std::declval()))>::value, + detail::std_string_view, std::basic_string>; + + formatter underlying_; + + public: + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return underlying_.parse(ctx); + } + + template + auto format(range_type& range, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); + if (detail::const_check(range_format_kind::value == + range_format::debug_string)) + *out++ = '"'; + out = underlying_.format( + string_type{detail::range_begin(range), detail::range_end(range)}, ctx); + if (detail::const_check(range_format_kind::value == + range_format::debug_string)) + *out++ = '"'; + return out; + } +}; + +template +struct join_view : detail::view { + It begin; + Sentinel end; + basic_string_view sep; + + join_view(It b, Sentinel e, basic_string_view s) + : begin(std::move(b)), end(e), sep(s) {} +}; + +template +struct formatter, Char> { + private: + using value_type = +#ifdef __cpp_lib_ranges + std::iter_value_t; +#else + typename std::iterator_traits::value_type; +#endif + formatter, Char> value_formatter_; + + using view_ref = conditional_t::value, + const join_view&, + join_view&&>; + + public: + using nonlocking = void; + + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const Char* { + return value_formatter_.parse(ctx); + } + + template + auto format(view_ref& value, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto it = std::forward(value).begin; + auto out = ctx.out(); + if (it == value.end) return out; + out = value_formatter_.format(*it, ctx); + ++it; + while (it != value.end) { + out = detail::copy(value.sep.begin(), value.sep.end(), out); + ctx.advance_to(out); + out = value_formatter_.format(*it, ctx); + ++it; + } + return out; + } +}; + +/// Returns a view that formats the iterator range `[begin, end)` with elements +/// separated by `sep`. +template +auto join(It begin, Sentinel end, string_view sep) -> join_view { + return {std::move(begin), end, sep}; +} + +/** + * Returns a view that formats `range` with elements separated by `sep`. + * + * **Example**: + * + * auto v = std::vector{1, 2, 3}; + * fmt::print("{}", fmt::join(v, ", ")); + * // Output: 1, 2, 3 + * + * `fmt::join` applies passed format specifiers to the range elements: + * + * fmt::print("{:02}", fmt::join(v, ", ")); + * // Output: 01, 02, 03 + */ +template +auto join(Range&& r, string_view sep) + -> join_view { + return {detail::range_begin(r), detail::range_end(r), sep}; +} + +template struct tuple_join_view : detail::view { + const std::tuple& tuple; + basic_string_view sep; + + tuple_join_view(const std::tuple& t, basic_string_view s) + : tuple(t), sep{s} {} +}; + +// Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers +// support in tuple_join. It is disabled by default because of issues with +// the dynamic width and precision. +#ifndef FMT_TUPLE_JOIN_SPECIFIERS +# define FMT_TUPLE_JOIN_SPECIFIERS 0 +#endif + +template +struct formatter, Char> { + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return do_parse(ctx, std::integral_constant()); + } + + template + auto format(const tuple_join_view& value, + FormatContext& ctx) const -> typename FormatContext::iterator { + return do_format(value, ctx, + std::integral_constant()); + } + + private: + std::tuple::type, Char>...> formatters_; + + template + FMT_CONSTEXPR auto do_parse(ParseContext& ctx, + std::integral_constant) + -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template + FMT_CONSTEXPR auto do_parse(ParseContext& ctx, + std::integral_constant) + -> decltype(ctx.begin()) { + auto end = ctx.begin(); +#if FMT_TUPLE_JOIN_SPECIFIERS + end = std::get(formatters_).parse(ctx); + if (N > 1) { + auto end1 = do_parse(ctx, std::integral_constant()); + if (end != end1) + report_error("incompatible format specs for tuple elements"); + } +#endif + return end; + } + + template + auto do_format(const tuple_join_view&, FormatContext& ctx, + std::integral_constant) const -> + typename FormatContext::iterator { + return ctx.out(); + } + + template + auto do_format(const tuple_join_view& value, FormatContext& ctx, + std::integral_constant) const -> + typename FormatContext::iterator { + auto out = std::get(formatters_) + .format(std::get(value.tuple), ctx); + if (N <= 1) return out; + out = detail::copy(value.sep, out); + ctx.advance_to(out); + return do_format(value, ctx, std::integral_constant()); + } +}; + +namespace detail { +// Check if T has an interface like a container adaptor (e.g. std::stack, +// std::queue, std::priority_queue). +template class is_container_adaptor_like { + template static auto check(U* p) -> typename U::container_type; + template static void check(...); + + public: + static constexpr const bool value = + !std::is_void(nullptr))>::value; +}; + +template struct all { + const Container& c; + auto begin() const -> typename Container::const_iterator { return c.begin(); } + auto end() const -> typename Container::const_iterator { return c.end(); } +}; +} // namespace detail + +template +struct formatter< + T, Char, + enable_if_t, + bool_constant::value == + range_format::disabled>>::value>> + : formatter, Char> { + using all = detail::all; + template + auto format(const T& t, FormatContext& ctx) const -> decltype(ctx.out()) { + struct getter : T { + static auto get(const T& t) -> all { + return {t.*(&getter::c)}; // Access c through the derived class. + } + }; + return formatter::format(getter::get(t), ctx); + } +}; + +FMT_BEGIN_EXPORT + +/** + * Returns an object that formats `std::tuple` with elements separated by `sep`. + * + * **Example**: + * + * auto t = std::tuple{1, 'a'}; + * fmt::print("{}", fmt::join(t, ", ")); + * // Output: 1, a + */ +template +FMT_CONSTEXPR auto join(const std::tuple& tuple, string_view sep) + -> tuple_join_view { + return {tuple, sep}; +} + +/** + * Returns an object that formats `std::initializer_list` with elements + * separated by `sep`. + * + * **Example**: + * + * fmt::print("{}", fmt::join({1, 2, 3}, ", ")); + * // Output: "1, 2, 3" + */ +template +auto join(std::initializer_list list, string_view sep) + -> join_view { + return join(std::begin(list), std::end(list), sep); +} + +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_RANGES_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/std.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/std.h new file mode 100644 index 0000000..fb43940 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/std.h @@ -0,0 +1,699 @@ +// Formatting library for C++ - formatters for standard library types +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_STD_H_ +#define FMT_STD_H_ + +#include "format.h" +#include "ostream.h" + +#ifndef FMT_MODULE +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +// Check FMT_CPLUSPLUS to suppress a bogus warning in MSVC. +# if FMT_CPLUSPLUS >= 201703L +# if FMT_HAS_INCLUDE() +# include +# endif +# if FMT_HAS_INCLUDE() +# include +# endif +# if FMT_HAS_INCLUDE() +# include +# endif +# endif +// Use > instead of >= in the version check because may be +// available after C++17 but before C++20 is marked as implemented. +# if FMT_CPLUSPLUS > 201703L && FMT_HAS_INCLUDE() +# include +# endif +# if FMT_CPLUSPLUS > 202002L && FMT_HAS_INCLUDE() +# include +# endif +#endif // FMT_MODULE + +#if FMT_HAS_INCLUDE() +# include +#endif + +// GCC 4 does not support FMT_HAS_INCLUDE. +#if FMT_HAS_INCLUDE() || defined(__GLIBCXX__) +# include +// Android NDK with gabi++ library on some architectures does not implement +// abi::__cxa_demangle(). +# ifndef __GABIXX_CXXABI_H__ +# define FMT_HAS_ABI_CXA_DEMANGLE +# endif +#endif + +// For older Xcode versions, __cpp_lib_xxx flags are inaccurately defined. +#ifndef FMT_CPP_LIB_FILESYSTEM +# ifdef __cpp_lib_filesystem +# define FMT_CPP_LIB_FILESYSTEM __cpp_lib_filesystem +# else +# define FMT_CPP_LIB_FILESYSTEM 0 +# endif +#endif + +#ifndef FMT_CPP_LIB_VARIANT +# ifdef __cpp_lib_variant +# define FMT_CPP_LIB_VARIANT __cpp_lib_variant +# else +# define FMT_CPP_LIB_VARIANT 0 +# endif +#endif + +#if FMT_CPP_LIB_FILESYSTEM +FMT_BEGIN_NAMESPACE + +namespace detail { + +template +auto get_path_string(const std::filesystem::path& p, + const std::basic_string& native) { + if constexpr (std::is_same_v && std::is_same_v) + return to_utf8(native, to_utf8_error_policy::replace); + else + return p.string(); +} + +template +void write_escaped_path(basic_memory_buffer& quoted, + const std::filesystem::path& p, + const std::basic_string& native) { + if constexpr (std::is_same_v && + std::is_same_v) { + auto buf = basic_memory_buffer(); + write_escaped_string(std::back_inserter(buf), native); + bool valid = to_utf8::convert(quoted, {buf.data(), buf.size()}); + FMT_ASSERT(valid, "invalid utf16"); + } else if constexpr (std::is_same_v) { + write_escaped_string( + std::back_inserter(quoted), native); + } else { + write_escaped_string(std::back_inserter(quoted), p.string()); + } +} + +} // namespace detail + +FMT_EXPORT +template struct formatter { + private: + format_specs specs_; + detail::arg_ref width_ref_; + bool debug_ = false; + char path_type_ = 0; + + public: + FMT_CONSTEXPR void set_debug_format(bool set = true) { debug_ = set; } + + template FMT_CONSTEXPR auto parse(ParseContext& ctx) { + auto it = ctx.begin(), end = ctx.end(); + if (it == end) return it; + + it = detail::parse_align(it, end, specs_); + if (it == end) return it; + + it = detail::parse_dynamic_spec(it, end, specs_.width, width_ref_, ctx); + if (it != end && *it == '?') { + debug_ = true; + ++it; + } + if (it != end && (*it == 'g')) path_type_ = detail::to_ascii(*it++); + return it; + } + + template + auto format(const std::filesystem::path& p, FormatContext& ctx) const { + auto specs = specs_; + auto path_string = + !path_type_ ? p.native() + : p.generic_string(); + + detail::handle_dynamic_spec(specs.width, width_ref_, + ctx); + if (!debug_) { + auto s = detail::get_path_string(p, path_string); + return detail::write(ctx.out(), basic_string_view(s), specs); + } + auto quoted = basic_memory_buffer(); + detail::write_escaped_path(quoted, p, path_string); + return detail::write(ctx.out(), + basic_string_view(quoted.data(), quoted.size()), + specs); + } +}; + +class path : public std::filesystem::path { + public: + auto display_string() const -> std::string { + const std::filesystem::path& base = *this; + return fmt::format(FMT_STRING("{}"), base); + } + auto system_string() const -> std::string { return string(); } + + auto generic_display_string() const -> std::string { + const std::filesystem::path& base = *this; + return fmt::format(FMT_STRING("{:g}"), base); + } + auto generic_system_string() const -> std::string { return generic_string(); } +}; + +FMT_END_NAMESPACE +#endif // FMT_CPP_LIB_FILESYSTEM + +FMT_BEGIN_NAMESPACE +FMT_EXPORT +template +struct formatter, Char> : nested_formatter { + private: + // Functor because C++11 doesn't support generic lambdas. + struct writer { + const std::bitset& bs; + + template + FMT_CONSTEXPR auto operator()(OutputIt out) -> OutputIt { + for (auto pos = N; pos > 0; --pos) { + out = detail::write(out, bs[pos - 1] ? Char('1') : Char('0')); + } + + return out; + } + }; + + public: + template + auto format(const std::bitset& bs, FormatContext& ctx) const + -> decltype(ctx.out()) { + return write_padded(ctx, writer{bs}); + } +}; + +FMT_EXPORT +template +struct formatter : basic_ostream_formatter {}; +FMT_END_NAMESPACE + +#ifdef __cpp_lib_optional +FMT_BEGIN_NAMESPACE +FMT_EXPORT +template +struct formatter, Char, + std::enable_if_t::value>> { + private: + formatter underlying_; + static constexpr basic_string_view optional = + detail::string_literal{}; + static constexpr basic_string_view none = + detail::string_literal{}; + + template + FMT_CONSTEXPR static auto maybe_set_debug_format(U& u, bool set) + -> decltype(u.set_debug_format(set)) { + u.set_debug_format(set); + } + + template + FMT_CONSTEXPR static void maybe_set_debug_format(U&, ...) {} + + public: + template FMT_CONSTEXPR auto parse(ParseContext& ctx) { + maybe_set_debug_format(underlying_, true); + return underlying_.parse(ctx); + } + + template + auto format(const std::optional& opt, FormatContext& ctx) const + -> decltype(ctx.out()) { + if (!opt) return detail::write(ctx.out(), none); + + auto out = ctx.out(); + out = detail::write(out, optional); + ctx.advance_to(out); + out = underlying_.format(*opt, ctx); + return detail::write(out, ')'); + } +}; +FMT_END_NAMESPACE +#endif // __cpp_lib_optional + +#if defined(__cpp_lib_expected) || FMT_CPP_LIB_VARIANT + +FMT_BEGIN_NAMESPACE +namespace detail { + +template +auto write_escaped_alternative(OutputIt out, const T& v) -> OutputIt { + if constexpr (has_to_string_view::value) + return write_escaped_string(out, detail::to_string_view(v)); + if constexpr (std::is_same_v) return write_escaped_char(out, v); + return write(out, v); +} + +} // namespace detail + +FMT_END_NAMESPACE +#endif + +#ifdef __cpp_lib_expected +FMT_BEGIN_NAMESPACE + +FMT_EXPORT +template +struct formatter, Char, + std::enable_if_t::value && + is_formattable::value>> { + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template + auto format(const std::expected& value, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); + + if (value.has_value()) { + out = detail::write(out, "expected("); + out = detail::write_escaped_alternative(out, *value); + } else { + out = detail::write(out, "unexpected("); + out = detail::write_escaped_alternative(out, value.error()); + } + *out++ = ')'; + return out; + } +}; +FMT_END_NAMESPACE +#endif // __cpp_lib_expected + +#ifdef __cpp_lib_source_location +FMT_BEGIN_NAMESPACE +FMT_EXPORT +template <> struct formatter { + template FMT_CONSTEXPR auto parse(ParseContext& ctx) { + return ctx.begin(); + } + + template + auto format(const std::source_location& loc, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); + out = detail::write(out, loc.file_name()); + out = detail::write(out, ':'); + out = detail::write(out, loc.line()); + out = detail::write(out, ':'); + out = detail::write(out, loc.column()); + out = detail::write(out, ": "); + out = detail::write(out, loc.function_name()); + return out; + } +}; +FMT_END_NAMESPACE +#endif + +#if FMT_CPP_LIB_VARIANT +FMT_BEGIN_NAMESPACE +namespace detail { + +template +using variant_index_sequence = + std::make_index_sequence::value>; + +template struct is_variant_like_ : std::false_type {}; +template +struct is_variant_like_> : std::true_type {}; + +// formattable element check. +template class is_variant_formattable_ { + template + static std::conjunction< + is_formattable, C>...> + check(std::index_sequence); + + public: + static constexpr const bool value = + decltype(check(variant_index_sequence{}))::value; +}; + +} // namespace detail + +template struct is_variant_like { + static constexpr const bool value = detail::is_variant_like_::value; +}; + +template struct is_variant_formattable { + static constexpr const bool value = + detail::is_variant_formattable_::value; +}; + +FMT_EXPORT +template struct formatter { + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template + auto format(const std::monostate&, FormatContext& ctx) const + -> decltype(ctx.out()) { + return detail::write(ctx.out(), "monostate"); + } +}; + +FMT_EXPORT +template +struct formatter< + Variant, Char, + std::enable_if_t, is_variant_formattable>>> { + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template + auto format(const Variant& value, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); + + out = detail::write(out, "variant("); + FMT_TRY { + std::visit( + [&](const auto& v) { + out = detail::write_escaped_alternative(out, v); + }, + value); + } + FMT_CATCH(const std::bad_variant_access&) { + detail::write(out, "valueless by exception"); + } + *out++ = ')'; + return out; + } +}; +FMT_END_NAMESPACE +#endif // FMT_CPP_LIB_VARIANT + +FMT_BEGIN_NAMESPACE +FMT_EXPORT +template struct formatter { + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template + FMT_CONSTEXPR auto format(const std::error_code& ec, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); + out = detail::write_bytes(out, ec.category().name(), format_specs()); + out = detail::write(out, Char(':')); + out = detail::write(out, ec.value()); + return out; + } +}; + +#if FMT_USE_RTTI +namespace detail { + +template +auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt { +# ifdef FMT_HAS_ABI_CXA_DEMANGLE + int status = 0; + std::size_t size = 0; + std::unique_ptr demangled_name_ptr( + abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free); + + string_view demangled_name_view; + if (demangled_name_ptr) { + demangled_name_view = demangled_name_ptr.get(); + + // Normalization of stdlib inline namespace names. + // libc++ inline namespaces. + // std::__1::* -> std::* + // std::__1::__fs::* -> std::* + // libstdc++ inline namespaces. + // std::__cxx11::* -> std::* + // std::filesystem::__cxx11::* -> std::filesystem::* + if (demangled_name_view.starts_with("std::")) { + char* begin = demangled_name_ptr.get(); + char* to = begin + 5; // std:: + for (char *from = to, *end = begin + demangled_name_view.size(); + from < end;) { + // This is safe, because demangled_name is NUL-terminated. + if (from[0] == '_' && from[1] == '_') { + char* next = from + 1; + while (next < end && *next != ':') next++; + if (next[0] == ':' && next[1] == ':') { + from = next + 2; + continue; + } + } + *to++ = *from++; + } + demangled_name_view = {begin, detail::to_unsigned(to - begin)}; + } + } else { + demangled_name_view = string_view(ti.name()); + } + return detail::write_bytes(out, demangled_name_view); +# elif FMT_MSC_VERSION + const string_view demangled_name(ti.name()); + for (std::size_t i = 0; i < demangled_name.size(); ++i) { + auto sub = demangled_name; + sub.remove_prefix(i); + if (sub.starts_with("enum ")) { + i += 4; + continue; + } + if (sub.starts_with("class ") || sub.starts_with("union ")) { + i += 5; + continue; + } + if (sub.starts_with("struct ")) { + i += 6; + continue; + } + if (*sub.begin() != ' ') *out++ = *sub.begin(); + } + return out; +# else + return detail::write_bytes(out, string_view(ti.name())); +# endif +} + +} // namespace detail + +FMT_EXPORT +template +struct formatter { + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template + auto format(const std::type_info& ti, Context& ctx) const + -> decltype(ctx.out()) { + return detail::write_demangled_name(ctx.out(), ti); + } +}; +#endif + +FMT_EXPORT +template +struct formatter< + T, Char, // DEPRECATED! Mixing code unit types. + typename std::enable_if::value>::type> { + private: + bool with_typename_ = false; + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + auto it = ctx.begin(); + auto end = ctx.end(); + if (it == end || *it == '}') return it; + if (*it == 't') { + ++it; + with_typename_ = FMT_USE_RTTI != 0; + } + return it; + } + + template + auto format(const std::exception& ex, Context& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); +#if FMT_USE_RTTI + if (with_typename_) { + out = detail::write_demangled_name(out, typeid(ex)); + *out++ = ':'; + *out++ = ' '; + } +#endif + return detail::write_bytes(out, string_view(ex.what())); + } +}; + +namespace detail { + +template +struct has_flip : std::false_type {}; + +template +struct has_flip().flip())>> + : std::true_type {}; + +template struct is_bit_reference_like { + static constexpr const bool value = + std::is_convertible::value && + std::is_nothrow_assignable::value && has_flip::value; +}; + +#ifdef _LIBCPP_VERSION + +// Workaround for libc++ incompatibility with C++ standard. +// According to the Standard, `bitset::operator[] const` returns bool. +template +struct is_bit_reference_like> { + static constexpr const bool value = true; +}; + +#endif + +} // namespace detail + +// We can't use std::vector::reference and +// std::bitset::reference because the compiler can't deduce Allocator and N +// in partial specialization. +FMT_EXPORT +template +struct formatter::value>> + : formatter { + template + FMT_CONSTEXPR auto format(const BitRef& v, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter::format(v, ctx); + } +}; + +template +auto ptr(const std::unique_ptr& p) -> const void* { + return p.get(); +} +template auto ptr(const std::shared_ptr& p) -> const void* { + return p.get(); +} + +FMT_EXPORT +template +struct formatter, Char, + enable_if_t::value>> + : formatter { + template + auto format(const std::atomic& v, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter::format(v.load(), ctx); + } +}; + +#ifdef __cpp_lib_atomic_flag_test +FMT_EXPORT +template +struct formatter : formatter { + template + auto format(const std::atomic_flag& v, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter::format(v.test(), ctx); + } +}; +#endif // __cpp_lib_atomic_flag_test + +FMT_EXPORT +template struct formatter, Char> { + private: + detail::dynamic_format_specs specs_; + + template + FMT_CONSTEXPR auto do_format(const std::complex& c, + detail::dynamic_format_specs& specs, + FormatContext& ctx, OutputIt out) const + -> OutputIt { + if (c.real() != 0) { + *out++ = Char('('); + out = detail::write(out, c.real(), specs, ctx.locale()); + specs.sign = sign::plus; + out = detail::write(out, c.imag(), specs, ctx.locale()); + if (!detail::isfinite(c.imag())) *out++ = Char(' '); + *out++ = Char('i'); + *out++ = Char(')'); + return out; + } + out = detail::write(out, c.imag(), specs, ctx.locale()); + if (!detail::isfinite(c.imag())) *out++ = Char(' '); + *out++ = Char('i'); + return out; + } + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + if (ctx.begin() == ctx.end() || *ctx.begin() == '}') return ctx.begin(); + return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, + detail::type_constant::value); + } + + template + auto format(const std::complex& c, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto specs = specs_; + if (specs.width_ref.kind != detail::arg_id_kind::none || + specs.precision_ref.kind != detail::arg_id_kind::none) { + detail::handle_dynamic_spec(specs.width, + specs.width_ref, ctx); + detail::handle_dynamic_spec( + specs.precision, specs.precision_ref, ctx); + } + + if (specs.width == 0) return do_format(c, specs, ctx, ctx.out()); + auto buf = basic_memory_buffer(); + + auto outer_specs = format_specs(); + outer_specs.width = specs.width; + outer_specs.fill = specs.fill; + outer_specs.align = specs.align; + + specs.width = 0; + specs.fill = {}; + specs.align = align::none; + + do_format(c, specs, ctx, basic_appender(buf)); + return detail::write(ctx.out(), + basic_string_view(buf.data(), buf.size()), + outer_specs); + } +}; + +FMT_END_NAMESPACE +#endif // FMT_STD_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/xchar.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/xchar.h new file mode 100644 index 0000000..b1f39ed --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/fmt/xchar.h @@ -0,0 +1,322 @@ +// Formatting library for C++ - optional wchar_t and exotic character support +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_XCHAR_H_ +#define FMT_XCHAR_H_ + +#include "color.h" +#include "format.h" +#include "ranges.h" + +#ifndef FMT_MODULE +# include +# if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) +# include +# endif +#endif + +FMT_BEGIN_NAMESPACE +namespace detail { + +template +using is_exotic_char = bool_constant::value>; + +template struct format_string_char {}; + +template +struct format_string_char< + S, void_t())))>> { + using type = char_t; +}; + +template +struct format_string_char::value>> { + using type = typename S::char_type; +}; + +template +using format_string_char_t = typename format_string_char::type; + +inline auto write_loc(basic_appender out, loc_value value, + const format_specs& specs, locale_ref loc) -> bool { +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR + auto& numpunct = + std::use_facet>(loc.get()); + auto separator = std::wstring(); + auto grouping = numpunct.grouping(); + if (!grouping.empty()) separator = std::wstring(1, numpunct.thousands_sep()); + return value.visit(loc_writer{out, specs, separator, grouping, {}}); +#endif + return false; +} +} // namespace detail + +FMT_BEGIN_EXPORT + +using wstring_view = basic_string_view; +using wformat_parse_context = basic_format_parse_context; +using wformat_context = buffered_context; +using wformat_args = basic_format_args; +using wmemory_buffer = basic_memory_buffer; + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 +// Workaround broken conversion on older gcc. +template using wformat_string = wstring_view; +inline auto runtime(wstring_view s) -> wstring_view { return s; } +#else +template +using wformat_string = basic_format_string...>; +inline auto runtime(wstring_view s) -> runtime_format_string { + return {{s}}; +} +#endif + +template <> struct is_char : std::true_type {}; +template <> struct is_char : std::true_type {}; +template <> struct is_char : std::true_type {}; + +#ifdef __cpp_char8_t +template <> +struct is_char : bool_constant {}; +#endif + +template +constexpr auto make_wformat_args(T&... args) + -> decltype(fmt::make_format_args(args...)) { + return fmt::make_format_args(args...); +} + +inline namespace literals { +#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_ARGS +constexpr auto operator""_a(const wchar_t* s, size_t) + -> detail::udl_arg { + return {s}; +} +#endif +} // namespace literals + +template +auto join(It begin, Sentinel end, wstring_view sep) + -> join_view { + return {begin, end, sep}; +} + +template +auto join(Range&& range, wstring_view sep) + -> join_view, detail::sentinel_t, + wchar_t> { + return join(std::begin(range), std::end(range), sep); +} + +template +auto join(std::initializer_list list, wstring_view sep) + -> join_view { + return join(std::begin(list), std::end(list), sep); +} + +template +auto join(const std::tuple& tuple, basic_string_view sep) + -> tuple_join_view { + return {tuple, sep}; +} + +template ::value)> +auto vformat(basic_string_view format_str, + typename detail::vformat_args::type args) + -> std::basic_string { + auto buf = basic_memory_buffer(); + detail::vformat_to(buf, format_str, args); + return to_string(buf); +} + +template +auto format(wformat_string fmt, T&&... args) -> std::wstring { + return vformat(fmt::wstring_view(fmt), fmt::make_wformat_args(args...)); +} + +template +auto format_to(OutputIt out, wformat_string fmt, T&&... args) + -> OutputIt { + return vformat_to(out, fmt::wstring_view(fmt), + fmt::make_wformat_args(args...)); +} + +// Pass char_t as a default template parameter instead of using +// std::basic_string> to reduce the symbol size. +template , + FMT_ENABLE_IF(!std::is_same::value && + !std::is_same::value)> +auto format(const S& format_str, T&&... args) -> std::basic_string { + return vformat(detail::to_string_view(format_str), + fmt::make_format_args>(args...)); +} + +template , + FMT_ENABLE_IF(detail::is_locale::value&& + detail::is_exotic_char::value)> +inline auto vformat(const Locale& loc, const S& format_str, + typename detail::vformat_args::type args) + -> std::basic_string { + return detail::vformat(loc, detail::to_string_view(format_str), args); +} + +template , + FMT_ENABLE_IF(detail::is_locale::value&& + detail::is_exotic_char::value)> +inline auto format(const Locale& loc, const S& format_str, T&&... args) + -> std::basic_string { + return detail::vformat( + loc, detail::to_string_view(format_str), + fmt::make_format_args>(args...)); +} + +template , + FMT_ENABLE_IF(detail::is_output_iterator::value&& + detail::is_exotic_char::value)> +auto vformat_to(OutputIt out, const S& format_str, + typename detail::vformat_args::type args) -> OutputIt { + auto&& buf = detail::get_buffer(out); + detail::vformat_to(buf, detail::to_string_view(format_str), args); + return detail::get_iterator(buf, out); +} + +template , + FMT_ENABLE_IF(detail::is_output_iterator::value && + !std::is_same::value && + !std::is_same::value)> +inline auto format_to(OutputIt out, const S& fmt, T&&... args) -> OutputIt { + return vformat_to(out, detail::to_string_view(fmt), + fmt::make_format_args>(args...)); +} + +template , + FMT_ENABLE_IF(detail::is_output_iterator::value&& + detail::is_locale::value&& + detail::is_exotic_char::value)> +inline auto vformat_to(OutputIt out, const Locale& loc, const S& format_str, + typename detail::vformat_args::type args) + -> OutputIt { + auto&& buf = detail::get_buffer(out); + vformat_to(buf, detail::to_string_view(format_str), args, + detail::locale_ref(loc)); + return detail::get_iterator(buf, out); +} + +template , + bool enable = detail::is_output_iterator::value && + detail::is_locale::value && + detail::is_exotic_char::value> +inline auto format_to(OutputIt out, const Locale& loc, const S& format_str, + T&&... args) -> + typename std::enable_if::type { + return vformat_to(out, loc, detail::to_string_view(format_str), + fmt::make_format_args>(args...)); +} + +template ::value&& + detail::is_exotic_char::value)> +inline auto vformat_to_n(OutputIt out, size_t n, + basic_string_view format_str, + typename detail::vformat_args::type args) + -> format_to_n_result { + using traits = detail::fixed_buffer_traits; + auto buf = detail::iterator_buffer(out, n); + detail::vformat_to(buf, format_str, args); + return {buf.out(), buf.count()}; +} + +template , + FMT_ENABLE_IF(detail::is_output_iterator::value&& + detail::is_exotic_char::value)> +inline auto format_to_n(OutputIt out, size_t n, const S& fmt, T&&... args) + -> format_to_n_result { + return vformat_to_n(out, n, fmt::basic_string_view(fmt), + fmt::make_format_args>(args...)); +} + +template , + FMT_ENABLE_IF(detail::is_exotic_char::value)> +inline auto formatted_size(const S& fmt, T&&... args) -> size_t { + auto buf = detail::counting_buffer(); + detail::vformat_to(buf, detail::to_string_view(fmt), + fmt::make_format_args>(args...)); + return buf.count(); +} + +inline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) { + auto buf = wmemory_buffer(); + detail::vformat_to(buf, fmt, args); + buf.push_back(L'\0'); + if (std::fputws(buf.data(), f) == -1) + FMT_THROW(system_error(errno, FMT_STRING("cannot write to file"))); +} + +inline void vprint(wstring_view fmt, wformat_args args) { + vprint(stdout, fmt, args); +} + +template +void print(std::FILE* f, wformat_string fmt, T&&... args) { + return vprint(f, wstring_view(fmt), fmt::make_wformat_args(args...)); +} + +template void print(wformat_string fmt, T&&... args) { + return vprint(wstring_view(fmt), fmt::make_wformat_args(args...)); +} + +template +void println(std::FILE* f, wformat_string fmt, T&&... args) { + return print(f, L"{}\n", fmt::format(fmt, std::forward(args)...)); +} + +template void println(wformat_string fmt, T&&... args) { + return print(L"{}\n", fmt::format(fmt, std::forward(args)...)); +} + +inline auto vformat(const text_style& ts, wstring_view fmt, wformat_args args) + -> std::wstring { + auto buf = wmemory_buffer(); + detail::vformat_to(buf, ts, fmt, args); + return fmt::to_string(buf); +} + +template +inline auto format(const text_style& ts, wformat_string fmt, T&&... args) + -> std::wstring { + return fmt::vformat(ts, fmt, fmt::make_wformat_args(args...)); +} + +template +FMT_DEPRECATED void print(std::FILE* f, const text_style& ts, + wformat_string fmt, const T&... args) { + vprint(f, ts, fmt, fmt::make_wformat_args(args...)); +} + +template +FMT_DEPRECATED void print(const text_style& ts, wformat_string fmt, + const T&... args) { + return print(stdout, ts, fmt, args...); +} + +/// Converts `value` to `std::wstring` using the default format for type `T`. +template inline auto to_wstring(const T& value) -> std::wstring { + return format(FMT_STRING(L"{}"), value); +} +FMT_END_EXPORT +FMT_END_NAMESPACE + +#endif // FMT_XCHAR_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/common.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/common.hpp new file mode 100644 index 0000000..b59657d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/common.hpp @@ -0,0 +1,539 @@ +/// @ref core +/// @file glm/common.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.3 Common Functions +/// +/// @defgroup core_func_common Common functions +/// @ingroup core +/// +/// Provides GLSL common functions +/// +/// These all operate component-wise. The description is per component. +/// +/// Include to use these core features. + +#pragma once + +#include "detail/qualifier.hpp" +#include "detail/_fixes.hpp" + +namespace glm +{ + /// @addtogroup core_func_common + /// @{ + + /// Returns x if x >= 0; otherwise, it returns -x. + /// + /// @tparam genType floating-point or signed integer; scalar or vector types. + /// + /// @see GLSL abs man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR genType abs(genType x); + + /// Returns x if x >= 0; otherwise, it returns -x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL abs man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec abs(vec const& x); + + /// Returns 1.0 if x > 0, 0.0 if x == 0, or -1.0 if x < 0. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL sign man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec sign(vec const& x); + + /// Returns a value equal to the nearest integer that is less then or equal to x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL floor man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec floor(vec const& x); + + /// Returns a value equal to the nearest integer to x + /// whose absolute value is not larger than the absolute value of x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL trunc man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec trunc(vec const& x); + + /// Returns a value equal to the nearest integer to x. + /// The fraction 0.5 will round in a direction chosen by the + /// implementation, presumably the direction that is fastest. + /// This includes the possibility that round(x) returns the + /// same value as roundEven(x) for all values of x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL round man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec round(vec const& x); + + /// Returns a value equal to the nearest integer to x. + /// A fractional part of 0.5 will round toward the nearest even + /// integer. (Both 3.5 and 4.5 for x will return 4.0.) + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL roundEven man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + /// @see New round to even technique + template + GLM_FUNC_DECL vec roundEven(vec const& x); + + /// Returns a value equal to the nearest integer + /// that is greater than or equal to x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL ceil man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec ceil(vec const& x); + + /// Return x - floor(x). + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL fract man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType fract(genType x); + + /// Return x - floor(x). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL fract man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec fract(vec const& x); + + template + GLM_FUNC_DECL genType mod(genType x, genType y); + + template + GLM_FUNC_DECL vec mod(vec const& x, T y); + + /// Modulus. Returns x - y * floor(x / y) + /// for each component in x using the floating point value y. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types, include glm/gtc/integer for integer scalar types support + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL mod man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec mod(vec const& x, vec const& y); + + /// Returns the fractional part of x and sets i to the integer + /// part (as a whole number floating point value). Both the + /// return value and the output parameter will have the same + /// sign as x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL modf man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType modf(genType x, genType& i); + + /// Returns y if y < x; otherwise, it returns x. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see GLSL min man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR genType min(genType x, genType y); + + /// Returns y if y < x; otherwise, it returns x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL min man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec min(vec const& x, T y); + + /// Returns y if y < x; otherwise, it returns x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL min man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec min(vec const& x, vec const& y); + + /// Returns y if x < y; otherwise, it returns x. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see GLSL max man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR genType max(genType x, genType y); + + /// Returns y if x < y; otherwise, it returns x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL max man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec max(vec const& x, T y); + + /// Returns y if x < y; otherwise, it returns x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL max man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec max(vec const& x, vec const& y); + + /// Returns min(max(x, minVal), maxVal) for each component in x + /// using the floating-point values minVal and maxVal. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see GLSL clamp man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR genType clamp(genType x, genType minVal, genType maxVal); + + /// Returns min(max(x, minVal), maxVal) for each component in x + /// using the floating-point values minVal and maxVal. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL clamp man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec clamp(vec const& x, T minVal, T maxVal); + + /// Returns min(max(x, minVal), maxVal) for each component in x + /// using the floating-point values minVal and maxVal. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL clamp man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec clamp(vec const& x, vec const& minVal, vec const& maxVal); + + /// If genTypeU is a floating scalar or vector: + /// Returns x * (1.0 - a) + y * a, i.e., the linear blend of + /// x and y using the floating-point value a. + /// The value for a is not restricted to the range [0, 1]. + /// + /// If genTypeU is a boolean scalar or vector: + /// Selects which vector each returned component comes + /// from. For a component of 'a' that is false, the + /// corresponding component of 'x' is returned. For a + /// component of 'a' that is true, the corresponding + /// component of 'y' is returned. Components of 'x' and 'y' that + /// are not selected are allowed to be invalid floating point + /// values and will have no effect on the results. Thus, this + /// provides different functionality than + /// genType mix(genType x, genType y, genType(a)) + /// where a is a Boolean vector. + /// + /// @see GLSL mix man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + /// + /// @param[in] x Value to interpolate. + /// @param[in] y Value to interpolate. + /// @param[in] a Interpolant. + /// + /// @tparam genTypeT Floating point scalar or vector. + /// @tparam genTypeU Floating point or boolean scalar or vector. It can't be a vector if it is the length of genTypeT. + /// + /// @code + /// #include + /// ... + /// float a; + /// bool b; + /// glm::dvec3 e; + /// glm::dvec3 f; + /// glm::vec4 g; + /// glm::vec4 h; + /// ... + /// glm::vec4 r = glm::mix(g, h, a); // Interpolate with a floating-point scalar two vectors. + /// glm::vec4 s = glm::mix(g, h, b); // Returns g or h; + /// glm::dvec3 t = glm::mix(e, f, a); // Types of the third parameter is not required to match with the first and the second. + /// glm::vec4 u = glm::mix(g, h, r); // Interpolations can be perform per component with a vector for the last parameter. + /// @endcode + template + GLM_FUNC_DECL GLM_CONSTEXPR genTypeT mix(genTypeT x, genTypeT y, genTypeU a); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec mix(vec const& x, vec const& y, vec const& a); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec mix(vec const& x, vec const& y, U a); + + /// Returns 0.0 if x < edge, otherwise it returns 1.0 for each component of a genType. + /// + /// @see GLSL step man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType step(genType edge, genType x); + + /// Returns 0.0 if x < edge, otherwise it returns 1.0. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL step man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec step(T edge, vec const& x); + + /// Returns 0.0 if x < edge, otherwise it returns 1.0. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL step man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec step(vec const& edge, vec const& x); + + /// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and + /// performs smooth Hermite interpolation between 0 and 1 + /// when edge0 < x < edge1. This is useful in cases where + /// you would want a threshold function with a smooth + /// transition. This is equivalent to: + /// genType t; + /// t = clamp ((x - edge0) / (edge1 - edge0), 0, 1); + /// return t * t * (3 - 2 * t); + /// Results are undefined if edge0 >= edge1. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL smoothstep man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType smoothstep(genType edge0, genType edge1, genType x); + + template + GLM_FUNC_DECL vec smoothstep(T edge0, T edge1, vec const& x); + + template + GLM_FUNC_DECL vec smoothstep(vec const& edge0, vec const& edge1, vec const& x); + + /// Returns true if x holds a NaN (not a number) + /// representation in the underlying implementation's set of + /// floating point representations. Returns false otherwise, + /// including for implementations with no NaN + /// representations. + /// + /// /!\ When using compiler fast math, this function may fail. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL isnan man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec isnan(vec const& x); + + /// Returns true if x holds a positive infinity or negative + /// infinity representation in the underlying implementation's + /// set of floating point representations. Returns false + /// otherwise, including for implementations with no infinity + /// representations. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL isinf man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec isinf(vec const& x); + + /// Returns a signed integer value representing + /// the encoding of a floating-point value. The floating-point + /// value's bit-level representation is preserved. + /// + /// @see GLSL floatBitsToInt man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + GLM_FUNC_DECL int floatBitsToInt(float v); + + /// Returns a signed integer value representing + /// the encoding of a floating-point value. The floatingpoint + /// value's bit-level representation is preserved. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL floatBitsToInt man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec floatBitsToInt(vec const& v); + + /// Returns a unsigned integer value representing + /// the encoding of a floating-point value. The floatingpoint + /// value's bit-level representation is preserved. + /// + /// @see GLSL floatBitsToUint man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + GLM_FUNC_DECL uint floatBitsToUint(float v); + + /// Returns a unsigned integer value representing + /// the encoding of a floating-point value. The floatingpoint + /// value's bit-level representation is preserved. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL floatBitsToUint man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec floatBitsToUint(vec const& v); + + /// Returns a floating-point value corresponding to a signed + /// integer encoding of a floating-point value. + /// If an inf or NaN is passed in, it will not signal, and the + /// resulting floating point value is unspecified. Otherwise, + /// the bit-level representation is preserved. + /// + /// @see GLSL intBitsToFloat man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + GLM_FUNC_DECL float intBitsToFloat(int v); + + /// Returns a floating-point value corresponding to a signed + /// integer encoding of a floating-point value. + /// If an inf or NaN is passed in, it will not signal, and the + /// resulting floating point value is unspecified. Otherwise, + /// the bit-level representation is preserved. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL intBitsToFloat man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec intBitsToFloat(vec const& v); + + /// Returns a floating-point value corresponding to a + /// unsigned integer encoding of a floating-point value. + /// If an inf or NaN is passed in, it will not signal, and the + /// resulting floating point value is unspecified. Otherwise, + /// the bit-level representation is preserved. + /// + /// @see GLSL uintBitsToFloat man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + GLM_FUNC_DECL float uintBitsToFloat(uint v); + + /// Returns a floating-point value corresponding to a + /// unsigned integer encoding of a floating-point value. + /// If an inf or NaN is passed in, it will not signal, and the + /// resulting floating point value is unspecified. Otherwise, + /// the bit-level representation is preserved. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL uintBitsToFloat man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec uintBitsToFloat(vec const& v); + + /// Computes and returns a * b + c. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL fma man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType fma(genType const& a, genType const& b, genType const& c); + + /// Splits x into a floating-point significand in the range + /// [0.5, 1.0) and an integral exponent of two, such that: + /// x = significand * exp(2, exponent) + /// + /// The significand is returned by the function and the + /// exponent is returned in the parameter exp. For a + /// floating-point value of zero, the significant and exponent + /// are both zero. For a floating-point value that is an + /// infinity or is not a number, the results are undefined. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL frexp man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType frexp(genType x, int& exp); + + template + GLM_FUNC_DECL vec frexp(vec const& v, vec& exp); + + /// Builds a floating-point number from x and the + /// corresponding integral exponent of two in exp, returning: + /// significand * exp(2, exponent) + /// + /// If this product is too large to be represented in the + /// floating-point type, the result is undefined. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL ldexp man page; + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType ldexp(genType const& x, int const& exp); + + template + GLM_FUNC_DECL vec ldexp(vec const& v, vec const& exp); + + /// @} +}//namespace glm + +#include "detail/func_common.inl" + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_features.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_features.hpp new file mode 100644 index 0000000..b0cbe9f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_features.hpp @@ -0,0 +1,394 @@ +#pragma once + +// #define GLM_CXX98_EXCEPTIONS +// #define GLM_CXX98_RTTI + +// #define GLM_CXX11_RVALUE_REFERENCES +// Rvalue references - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html + +// GLM_CXX11_TRAILING_RETURN +// Rvalue references for *this - GCC not supported +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm + +// GLM_CXX11_NONSTATIC_MEMBER_INIT +// Initialization of class objects by rvalues - GCC any +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1610.html + +// GLM_CXX11_NONSTATIC_MEMBER_INIT +// Non-static data member initializers - GCC 4.7 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2756.htm + +// #define GLM_CXX11_VARIADIC_TEMPLATE +// Variadic templates - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf + +// +// Extending variadic template template parameters - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf + +// #define GLM_CXX11_GENERALIZED_INITIALIZERS +// Initializer lists - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm + +// #define GLM_CXX11_STATIC_ASSERT +// Static assertions - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html + +// #define GLM_CXX11_AUTO_TYPE +// auto-typed variables - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf + +// #define GLM_CXX11_AUTO_TYPE +// Multi-declarator auto - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1737.pdf + +// #define GLM_CXX11_AUTO_TYPE +// Removal of auto as a storage-class specifier - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2546.htm + +// #define GLM_CXX11_AUTO_TYPE +// New function declarator syntax - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm + +// #define GLM_CXX11_LAMBDAS +// New wording for C++0x lambdas - GCC 4.5 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2927.pdf + +// #define GLM_CXX11_DECLTYPE +// Declared type of an expression - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf + +// +// Right angle brackets - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html + +// +// Default template arguments for function templates DR226 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226 + +// +// Solving the SFINAE problem for expressions DR339 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html + +// #define GLM_CXX11_ALIAS_TEMPLATE +// Template aliases N2258 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf + +// +// Extern templates N1987 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm + +// #define GLM_CXX11_NULLPTR +// Null pointer constant N2431 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf + +// #define GLM_CXX11_STRONG_ENUMS +// Strongly-typed enums N2347 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf + +// +// Forward declarations for enums N2764 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf + +// +// Generalized attributes N2761 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf + +// +// Generalized constant expressions N2235 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf + +// +// Alignment support N2341 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf + +// #define GLM_CXX11_DELEGATING_CONSTRUCTORS +// Delegating constructors N1986 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf + +// +// Inheriting constructors N2540 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm + +// #define GLM_CXX11_EXPLICIT_CONVERSIONS +// Explicit conversion operators N2437 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf + +// +// New character types N2249 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2249.html + +// +// Unicode string literals N2442 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm + +// +// Raw string literals N2442 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm + +// +// Universal character name literals N2170 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2170.html + +// #define GLM_CXX11_USER_LITERALS +// User-defined literals N2765 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf + +// +// Standard Layout Types N2342 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm + +// #define GLM_CXX11_DEFAULTED_FUNCTIONS +// #define GLM_CXX11_DELETED_FUNCTIONS +// Defaulted and deleted functions N2346 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm + +// +// Extended friend declarations N1791 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf + +// +// Extending sizeof N2253 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html + +// #define GLM_CXX11_INLINE_NAMESPACES +// Inline namespaces N2535 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm + +// #define GLM_CXX11_UNRESTRICTED_UNIONS +// Unrestricted unions N2544 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf + +// #define GLM_CXX11_LOCAL_TYPE_TEMPLATE_ARGS +// Local and unnamed types as template arguments N2657 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm + +// #define GLM_CXX11_RANGE_FOR +// Range-based for N2930 GCC 4.6 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2930.html + +// #define GLM_CXX11_OVERRIDE_CONTROL +// Explicit virtual overrides N2928 N3206 N3272 GCC 4.7 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm + +// +// Minimal support for garbage collection and reachability-based leak detection N2670 No +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2670.htm + +// #define GLM_CXX11_NOEXCEPT +// Allowing move constructors to throw [noexcept] N3050 GCC 4.6 (core language only) +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3050.html + +// +// Defining move special member functions N3053 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3053.html + +// +// Sequence points N2239 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2239.html + +// +// Atomic operations N2427 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2239.html + +// +// Strong Compare and Exchange N2748 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html + +// +// Bidirectional Fences N2752 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2752.htm + +// +// Memory model N2429 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2429.htm + +// +// Data-dependency ordering: atomics and memory model N2664 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2664.htm + +// +// Propagating exceptions N2179 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html + +// +// Abandoning a process and at_quick_exit N2440 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2440.htm + +// +// Allow atomics use in signal handlers N2547 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2547.htm + +// +// Thread-local storage N2659 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2659.htm + +// +// Dynamic initialization and destruction with concurrency N2660 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm + +// +// __func__ predefined identifier N2340 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2340.htm + +// +// C99 preprocessor N1653 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1653.htm + +// +// long long N1811 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1811.pdf + +// +// Extended integral types N1988 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1988.pdf + +#if(GLM_COMPILER & GLM_COMPILER_GCC) + +# define GLM_CXX11_STATIC_ASSERT + +#elif(GLM_COMPILER & GLM_COMPILER_CLANG) +# if(__has_feature(cxx_exceptions)) +# define GLM_CXX98_EXCEPTIONS +# endif + +# if(__has_feature(cxx_rtti)) +# define GLM_CXX98_RTTI +# endif + +# if(__has_feature(cxx_access_control_sfinae)) +# define GLM_CXX11_ACCESS_CONTROL_SFINAE +# endif + +# if(__has_feature(cxx_alias_templates)) +# define GLM_CXX11_ALIAS_TEMPLATE +# endif + +# if(__has_feature(cxx_alignas)) +# define GLM_CXX11_ALIGNAS +# endif + +# if(__has_feature(cxx_attributes)) +# define GLM_CXX11_ATTRIBUTES +# endif + +# if(__has_feature(cxx_constexpr)) +# define GLM_CXX11_CONSTEXPR +# endif + +# if(__has_feature(cxx_decltype)) +# define GLM_CXX11_DECLTYPE +# endif + +# if(__has_feature(cxx_default_function_template_args)) +# define GLM_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS +# endif + +# if(__has_feature(cxx_defaulted_functions)) +# define GLM_CXX11_DEFAULTED_FUNCTIONS +# endif + +# if(__has_feature(cxx_delegating_constructors)) +# define GLM_CXX11_DELEGATING_CONSTRUCTORS +# endif + +# if(__has_feature(cxx_deleted_functions)) +# define GLM_CXX11_DELETED_FUNCTIONS +# endif + +# if(__has_feature(cxx_explicit_conversions)) +# define GLM_CXX11_EXPLICIT_CONVERSIONS +# endif + +# if(__has_feature(cxx_generalized_initializers)) +# define GLM_CXX11_GENERALIZED_INITIALIZERS +# endif + +# if(__has_feature(cxx_implicit_moves)) +# define GLM_CXX11_IMPLICIT_MOVES +# endif + +# if(__has_feature(cxx_inheriting_constructors)) +# define GLM_CXX11_INHERITING_CONSTRUCTORS +# endif + +# if(__has_feature(cxx_inline_namespaces)) +# define GLM_CXX11_INLINE_NAMESPACES +# endif + +# if(__has_feature(cxx_lambdas)) +# define GLM_CXX11_LAMBDAS +# endif + +# if(__has_feature(cxx_local_type_template_args)) +# define GLM_CXX11_LOCAL_TYPE_TEMPLATE_ARGS +# endif + +# if(__has_feature(cxx_noexcept)) +# define GLM_CXX11_NOEXCEPT +# endif + +# if(__has_feature(cxx_nonstatic_member_init)) +# define GLM_CXX11_NONSTATIC_MEMBER_INIT +# endif + +# if(__has_feature(cxx_nullptr)) +# define GLM_CXX11_NULLPTR +# endif + +# if(__has_feature(cxx_override_control)) +# define GLM_CXX11_OVERRIDE_CONTROL +# endif + +# if(__has_feature(cxx_reference_qualified_functions)) +# define GLM_CXX11_REFERENCE_QUALIFIED_FUNCTIONS +# endif + +# if(__has_feature(cxx_range_for)) +# define GLM_CXX11_RANGE_FOR +# endif + +# if(__has_feature(cxx_raw_string_literals)) +# define GLM_CXX11_RAW_STRING_LITERALS +# endif + +# if(__has_feature(cxx_rvalue_references)) +# define GLM_CXX11_RVALUE_REFERENCES +# endif + +# if(__has_feature(cxx_static_assert)) +# define GLM_CXX11_STATIC_ASSERT +# endif + +# if(__has_feature(cxx_auto_type)) +# define GLM_CXX11_AUTO_TYPE +# endif + +# if(__has_feature(cxx_strong_enums)) +# define GLM_CXX11_STRONG_ENUMS +# endif + +# if(__has_feature(cxx_trailing_return)) +# define GLM_CXX11_TRAILING_RETURN +# endif + +# if(__has_feature(cxx_unicode_literals)) +# define GLM_CXX11_UNICODE_LITERALS +# endif + +# if(__has_feature(cxx_unrestricted_unions)) +# define GLM_CXX11_UNRESTRICTED_UNIONS +# endif + +# if(__has_feature(cxx_user_literals)) +# define GLM_CXX11_USER_LITERALS +# endif + +# if(__has_feature(cxx_variadic_templates)) +# define GLM_CXX11_VARIADIC_TEMPLATES +# endif + +#endif//(GLM_COMPILER & GLM_COMPILER_CLANG) diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_fixes.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_fixes.hpp new file mode 100644 index 0000000..a503c7c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_fixes.hpp @@ -0,0 +1,27 @@ +#include + +//! Workaround for compatibility with other libraries +#ifdef max +#undef max +#endif + +//! Workaround for compatibility with other libraries +#ifdef min +#undef min +#endif + +//! Workaround for Android +#ifdef isnan +#undef isnan +#endif + +//! Workaround for Android +#ifdef isinf +#undef isinf +#endif + +//! Workaround for Chrone Native Client +#ifdef log2 +#undef log2 +#endif + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_noise.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_noise.hpp new file mode 100644 index 0000000..5a874a0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_noise.hpp @@ -0,0 +1,81 @@ +#pragma once + +#include "../common.hpp" + +namespace glm{ +namespace detail +{ + template + GLM_FUNC_QUALIFIER T mod289(T const& x) + { + return x - floor(x * (static_cast(1.0) / static_cast(289.0))) * static_cast(289.0); + } + + template + GLM_FUNC_QUALIFIER T permute(T const& x) + { + return mod289(((x * static_cast(34)) + static_cast(1)) * x); + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> permute(vec<2, T, Q> const& x) + { + return mod289(((x * static_cast(34)) + static_cast(1)) * x); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> permute(vec<3, T, Q> const& x) + { + return mod289(((x * static_cast(34)) + static_cast(1)) * x); + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> permute(vec<4, T, Q> const& x) + { + return mod289(((x * static_cast(34)) + static_cast(1)) * x); + } + + template + GLM_FUNC_QUALIFIER T taylorInvSqrt(T const& r) + { + return static_cast(1.79284291400159) - static_cast(0.85373472095314) * r; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> taylorInvSqrt(vec<2, T, Q> const& r) + { + return static_cast(1.79284291400159) - static_cast(0.85373472095314) * r; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> taylorInvSqrt(vec<3, T, Q> const& r) + { + return static_cast(1.79284291400159) - static_cast(0.85373472095314) * r; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> taylorInvSqrt(vec<4, T, Q> const& r) + { + return static_cast(1.79284291400159) - static_cast(0.85373472095314) * r; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> fade(vec<2, T, Q> const& t) + { + return (t * t * t) * (t * (t * static_cast(6) - static_cast(15)) + static_cast(10)); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> fade(vec<3, T, Q> const& t) + { + return (t * t * t) * (t * (t * static_cast(6) - static_cast(15)) + static_cast(10)); + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> fade(vec<4, T, Q> const& t) + { + return (t * t * t) * (t * (t * static_cast(6) - static_cast(15)) + static_cast(10)); + } +}//namespace detail +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_swizzle.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_swizzle.hpp new file mode 100644 index 0000000..e1f57cc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_swizzle.hpp @@ -0,0 +1,804 @@ +#pragma once + +namespace glm{ +namespace detail +{ + // Internal class for implementing swizzle operators + template + struct _swizzle_base0 + { + protected: + GLM_FUNC_QUALIFIER T& elem(int i){ return (reinterpret_cast(_buffer))[i]; } + GLM_FUNC_QUALIFIER T const& elem(int i) const{ return (reinterpret_cast(_buffer))[i]; } + + // Use an opaque buffer to *ensure* the compiler doesn't call a constructor. + // The size 1 buffer is assumed to aligned to the actual members so that the + // elem() + char _buffer[1]; + }; + + template + struct _swizzle_base1 : public _swizzle_base0 + { + }; + + template + struct _swizzle_base1<2, T, Q, E0,E1,-1,-2, Aligned> : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER vec<2, T, Q> operator ()() const { return vec<2, T, Q>(this->elem(E0), this->elem(E1)); } + }; + + template + struct _swizzle_base1<3, T, Q, E0,E1,E2,-1, Aligned> : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER vec<3, T, Q> operator ()() const { return vec<3, T, Q>(this->elem(E0), this->elem(E1), this->elem(E2)); } + }; + + template + struct _swizzle_base1<4, T, Q, E0,E1,E2,E3, Aligned> : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER vec<4, T, Q> operator ()() const { return vec<4, T, Q>(this->elem(E0), this->elem(E1), this->elem(E2), this->elem(E3)); } + }; + + // Internal class for implementing swizzle operators + /* + Template parameters: + + T = type of scalar values (e.g. float, double) + N = number of components in the vector (e.g. 3) + E0...3 = what index the n-th element of this swizzle refers to in the unswizzled vec + + DUPLICATE_ELEMENTS = 1 if there is a repeated element, 0 otherwise (used to specialize swizzles + containing duplicate elements so that they cannot be used as r-values). + */ + template + struct _swizzle_base2 : public _swizzle_base1::value> + { + struct op_equal + { + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) const{ e = t; } + }; + + struct op_minus + { + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) const{ e -= t; } + }; + + struct op_plus + { + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) const{ e += t; } + }; + + struct op_mul + { + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) const{ e *= t; } + }; + + struct op_div + { + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) const{ e /= t; } + }; + + public: + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (const T& t) + { + for (int i = 0; i < N; ++i) + (*this)[i] = t; + return *this; + } + + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (vec const& that) + { + _apply_op(that, op_equal()); + return *this; + } + + GLM_FUNC_QUALIFIER void operator -= (vec const& that) + { + _apply_op(that, op_minus()); + } + + GLM_FUNC_QUALIFIER void operator += (vec const& that) + { + _apply_op(that, op_plus()); + } + + GLM_FUNC_QUALIFIER void operator *= (vec const& that) + { + _apply_op(that, op_mul()); + } + + GLM_FUNC_QUALIFIER void operator /= (vec const& that) + { + _apply_op(that, op_div()); + } + + GLM_FUNC_QUALIFIER T& operator[](int i) + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + GLM_FUNC_QUALIFIER T operator[](int i) const + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + + protected: + template + GLM_FUNC_QUALIFIER void _apply_op(vec const& that, const U& op) + { + // Make a copy of the data in this == &that. + // The copier should optimize out the copy in cases where the function is + // properly inlined and the copy is not necessary. + T t[N]; + for (int i = 0; i < N; ++i) + t[i] = that[i]; + for (int i = 0; i < N; ++i) + op( (*this)[i], t[i] ); + } + }; + + // Specialization for swizzles containing duplicate elements. These cannot be modified. + template + struct _swizzle_base2 : public _swizzle_base1::value> + { + struct Stub {}; + + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (Stub const&) { return *this; } + + GLM_FUNC_QUALIFIER T operator[] (int i) const + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + }; + + template + struct _swizzle : public _swizzle_base2 + { + typedef _swizzle_base2 base_type; + + using base_type::operator=; + + GLM_FUNC_QUALIFIER operator vec () const { return (*this)(); } + }; + +// +// To prevent the C++ syntax from getting entirely overwhelming, define some alias macros +// +#define GLM_SWIZZLE_TEMPLATE1 template +#define GLM_SWIZZLE_TEMPLATE2 template +#define GLM_SWIZZLE_TYPE1 _swizzle +#define GLM_SWIZZLE_TYPE2 _swizzle + +// +// Wrapper for a binary operator (e.g. u.yy + v.zy) +// +#define GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \ + GLM_SWIZZLE_TEMPLATE2 \ + GLM_FUNC_QUALIFIER vec operator OPERAND ( const GLM_SWIZZLE_TYPE1& a, const GLM_SWIZZLE_TYPE2& b) \ + { \ + return a() OPERAND b(); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER vec operator OPERAND ( const GLM_SWIZZLE_TYPE1& a, const vec& b) \ + { \ + return a() OPERAND b; \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER vec operator OPERAND ( const vec& a, const GLM_SWIZZLE_TYPE1& b) \ + { \ + return a OPERAND b(); \ + } + +// +// Wrapper for a operand between a swizzle and a binary (e.g. 1.0f - u.xyz) +// +#define GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER vec operator OPERAND ( const GLM_SWIZZLE_TYPE1& a, const T& b) \ + { \ + return a() OPERAND b; \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER vec operator OPERAND ( const T& a, const GLM_SWIZZLE_TYPE1& b) \ + { \ + return a OPERAND b(); \ + } + +// +// Macro for wrapping a function taking one argument (e.g. abs()) +// +#define GLM_SWIZZLE_FUNCTION_1_ARGS(RETURN_TYPE,FUNCTION) \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a) \ + { \ + return FUNCTION(a()); \ + } + +// +// Macro for wrapping a function taking two vector arguments (e.g. dot()). +// +#define GLM_SWIZZLE_FUNCTION_2_ARGS(RETURN_TYPE,FUNCTION) \ + GLM_SWIZZLE_TEMPLATE2 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a, const GLM_SWIZZLE_TYPE2& b) \ + { \ + return FUNCTION(a(), b()); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a, const GLM_SWIZZLE_TYPE1& b) \ + { \ + return FUNCTION(a(), b()); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a, const typename V& b) \ + { \ + return FUNCTION(a(), b); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const V& a, const GLM_SWIZZLE_TYPE1& b) \ + { \ + return FUNCTION(a, b()); \ + } + +// +// Macro for wrapping a function take 2 vec arguments followed by a scalar (e.g. mix()). +// +#define GLM_SWIZZLE_FUNCTION_2_ARGS_SCALAR(RETURN_TYPE,FUNCTION) \ + GLM_SWIZZLE_TEMPLATE2 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a, const GLM_SWIZZLE_TYPE2& b, const T& c) \ + { \ + return FUNCTION(a(), b(), c); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a, const GLM_SWIZZLE_TYPE1& b, const T& c) \ + { \ + return FUNCTION(a(), b(), c); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a, const typename S0::vec_type& b, const T& c)\ + { \ + return FUNCTION(a(), b, c); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const typename V& a, const GLM_SWIZZLE_TYPE1& b, const T& c) \ + { \ + return FUNCTION(a, b(), c); \ + } + +}//namespace detail +}//namespace glm + +namespace glm +{ + namespace detail + { + GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(-) + GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(*) + GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(+) + GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(-) + GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(*) + GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(/) + } + + // + // Swizzles are distinct types from the unswizzled type. The below macros will + // provide template specializations for the swizzle types for the given functions + // so that the compiler does not have any ambiguity to choosing how to handle + // the function. + // + // The alternative is to use the operator()() when calling the function in order + // to explicitly convert the swizzled type to the unswizzled type. + // + + //GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, abs); + //GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, acos); + //GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, acosh); + //GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, all); + //GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, any); + + //GLM_SWIZZLE_FUNCTION_2_ARGS(value_type, dot); + //GLM_SWIZZLE_FUNCTION_2_ARGS(vec_type, cross); + //GLM_SWIZZLE_FUNCTION_2_ARGS(vec_type, step); + //GLM_SWIZZLE_FUNCTION_2_ARGS_SCALAR(vec_type, mix); +} + +#define GLM_SWIZZLE2_2_MEMBERS(T, Q, E0,E1) \ + struct { detail::_swizzle<2, T, Q, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2, T, Q, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2, T, Q, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2, T, Q, 1,1,-1,-2> E1 ## E1; }; + +#define GLM_SWIZZLE2_3_MEMBERS(T, Q, E0,E1) \ + struct { detail::_swizzle<3,T, Q, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T, Q, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T, Q, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T, Q, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T, Q, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T, Q, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T, Q, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T, Q, 1,1,1,-1> E1 ## E1 ## E1; }; + +#define GLM_SWIZZLE2_4_MEMBERS(T, Q, E0,E1) \ + struct { detail::_swizzle<4,T, Q, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; + +#define GLM_SWIZZLE3_2_MEMBERS(T, Q, E0,E1,E2) \ + struct { detail::_swizzle<2,T, Q, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 0,2,-1,-2> E0 ## E2; }; \ + struct { detail::_swizzle<2,T, Q, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 1,1,-1,-2> E1 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 1,2,-1,-2> E1 ## E2; }; \ + struct { detail::_swizzle<2,T, Q, 2,0,-1,-2> E2 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 2,1,-1,-2> E2 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 2,2,-1,-2> E2 ## E2; }; + +#define GLM_SWIZZLE3_3_MEMBERS(T, Q ,E0,E1,E2) \ + struct { detail::_swizzle<3, T, Q, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,0,2,-1> E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,2,-1> E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,0,-1> E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,1,-1> E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,2,-1> E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,2,-1> E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,1,-1> E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,2,-1> E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,0,-1> E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,1,-1> E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,2,-1> E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,0,-1> E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,1,-1> E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,2,-1> E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,0,-1> E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,1,-1> E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,2,-1> E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,0,-1> E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,1,-1> E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,2,-1> E2 ## E2 ## E2; }; + +#define GLM_SWIZZLE3_4_MEMBERS(T, Q, E0,E1,E2) \ + struct { detail::_swizzle<4,T, Q, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; + +#define GLM_SWIZZLE4_2_MEMBERS(T, Q, E0,E1,E2,E3) \ + struct { detail::_swizzle<2,T, Q, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 0,2,-1,-2> E0 ## E2; }; \ + struct { detail::_swizzle<2,T, Q, 0,3,-1,-2> E0 ## E3; }; \ + struct { detail::_swizzle<2,T, Q, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 1,1,-1,-2> E1 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 1,2,-1,-2> E1 ## E2; }; \ + struct { detail::_swizzle<2,T, Q, 1,3,-1,-2> E1 ## E3; }; \ + struct { detail::_swizzle<2,T, Q, 2,0,-1,-2> E2 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 2,1,-1,-2> E2 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 2,2,-1,-2> E2 ## E2; }; \ + struct { detail::_swizzle<2,T, Q, 2,3,-1,-2> E2 ## E3; }; \ + struct { detail::_swizzle<2,T, Q, 3,0,-1,-2> E3 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 3,1,-1,-2> E3 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 3,2,-1,-2> E3 ## E2; }; \ + struct { detail::_swizzle<2,T, Q, 3,3,-1,-2> E3 ## E3; }; + +#define GLM_SWIZZLE4_3_MEMBERS(T, Q, E0,E1,E2,E3) \ + struct { detail::_swizzle<3, T, Q, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,0,2,-1> E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 0,0,3,-1> E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,2,-1> E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,3,-1> E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,0,-1> E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,1,-1> E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,2,-1> E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,3,-1> E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 0,3,0,-1> E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,3,1,-1> E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,3,2,-1> E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 0,3,3,-1> E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,2,-1> E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,3,-1> E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,1,-1> E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,2,-1> E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,3,-1> E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,0,-1> E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,1,-1> E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,2,-1> E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,3,-1> E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 1,3,0,-1> E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,3,1,-1> E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,3,2,-1> E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,3,3,-1> E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,0,-1> E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,1,-1> E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,2,-1> E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,3,-1> E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,0,-1> E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,1,-1> E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,2,-1> E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,3,-1> E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,0,-1> E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,1,-1> E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,2,-1> E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,3,-1> E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 2,3,0,-1> E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,3,1,-1> E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,3,2,-1> E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,3,3,-1> E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 3,0,0,-1> E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 3,0,1,-1> E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 3,0,2,-1> E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 3,0,3,-1> E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 3,1,0,-1> E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 3,1,1,-1> E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 3,1,2,-1> E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 3,1,3,-1> E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 3,2,0,-1> E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 3,2,1,-1> E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 3,2,2,-1> E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 3,2,3,-1> E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 3,3,0,-1> E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 3,3,1,-1> E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 3,3,2,-1> E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 3,3,3,-1> E3 ## E3 ## E3; }; + +#define GLM_SWIZZLE4_4_MEMBERS(T, Q, E0,E1,E2,E3) \ + struct { detail::_swizzle<4, T, Q, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,0,3> E0 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,1,3> E0 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,2,3> E0 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,3,0> E0 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,3,1> E0 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,3,2> E0 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,3,3> E0 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,0,3> E0 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,1,3> E0 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,2,3> E0 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,3,0> E0 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,3,1> E0 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,3,2> E0 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,3,3> E0 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,0,3> E0 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,1,3> E0 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,2,3> E0 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,3,0> E0 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,3,1> E0 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,3,2> E0 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,3,3> E0 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,0,0> E0 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,0,1> E0 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,0,2> E0 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,0,3> E0 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,1,0> E0 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,1,1> E0 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,1,2> E0 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,1,3> E0 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,2,0> E0 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,2,1> E0 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,2,2> E0 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,2,3> E0 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,3,0> E0 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,3,1> E0 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,3,2> E0 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,3,3> E0 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,0,3> E1 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,1,3> E1 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,2,3> E1 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,3,0> E1 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,3,1> E1 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,3,2> E1 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,3,3> E1 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,0,3> E1 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,1,3> E1 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,2,3> E1 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,3,0> E1 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,3,1> E1 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,3,2> E1 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,3,3> E1 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,0,3> E1 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,1,3> E1 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,2,3> E1 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,3,0> E1 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,3,1> E1 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,3,2> E1 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,3,3> E1 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,0,0> E1 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,0,1> E1 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,0,2> E1 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,0,3> E1 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,1,0> E1 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,1,1> E1 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,1,2> E1 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,1,3> E1 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,2,0> E1 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,2,1> E1 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,2,2> E1 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,2,3> E1 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,3,0> E1 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,3,1> E1 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,3,2> E1 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,3,3> E1 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,0,3> E2 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,1,3> E2 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,2,3> E2 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,3,0> E2 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,3,1> E2 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,3,2> E2 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,3,3> E2 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,0,3> E2 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,1,3> E2 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,2,3> E2 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,3,0> E2 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,3,1> E2 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,3,2> E2 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,3,3> E2 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,0,3> E2 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,1,3> E2 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,2,3> E2 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,3,0> E2 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,3,1> E2 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,3,2> E2 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,3,3> E2 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,0,0> E2 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,0,1> E2 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,0,2> E2 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,0,3> E2 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,1,0> E2 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,1,1> E2 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,1,2> E2 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,1,3> E2 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,2,0> E2 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,2,1> E2 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,2,2> E2 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,2,3> E2 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,3,0> E2 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,3,1> E2 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,3,2> E2 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,3,3> E2 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,0,0> E3 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,0,1> E3 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,0,2> E3 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,0,3> E3 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,1,0> E3 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,1,1> E3 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,1,2> E3 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,1,3> E3 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,2,0> E3 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,2,1> E3 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,2,2> E3 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,2,3> E3 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,3,0> E3 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,3,1> E3 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,3,2> E3 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,3,3> E3 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,0,0> E3 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,0,1> E3 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,0,2> E3 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,0,3> E3 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,1,0> E3 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,1,1> E3 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,1,2> E3 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,1,3> E3 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,2,0> E3 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,2,1> E3 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,2,2> E3 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,2,3> E3 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,3,0> E3 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,3,1> E3 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,3,2> E3 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,3,3> E3 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,0,0> E3 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,0,1> E3 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,0,2> E3 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,0,3> E3 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,1,0> E3 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,1,1> E3 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,1,2> E3 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,1,3> E3 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,2,0> E3 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,2,1> E3 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,2,2> E3 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,2,3> E3 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,3,0> E3 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,3,1> E3 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,3,2> E3 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,3,3> E3 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,0,0> E3 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,0,1> E3 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,0,2> E3 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,0,3> E3 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,1,0> E3 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,1,1> E3 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,1,2> E3 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,1,3> E3 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,2,0> E3 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,2,1> E3 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,2,2> E3 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,2,3> E3 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,3,0> E3 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,3,1> E3 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,3,2> E3 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,3,3> E3 ## E3 ## E3 ## E3; }; diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_swizzle_func.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_swizzle_func.hpp new file mode 100644 index 0000000..a264ae9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_swizzle_func.hpp @@ -0,0 +1,682 @@ +#pragma once + +#define GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, CONST, A, B) \ + GLM_FUNC_QUALIFIER vec<2, T, Q> A ## B() CONST \ + { \ + return vec<2, T, Q>(this->A, this->B); \ + } + +#define GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, CONST, A, B, C) \ + GLM_FUNC_QUALIFIER vec<3, T, Q> A ## B ## C() CONST \ + { \ + return vec<3, T, Q>(this->A, this->B, this->C); \ + } + +#define GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, CONST, A, B, C, D) \ + GLM_FUNC_QUALIFIER vec<4, T, Q> A ## B ## C ## D() CONST \ + { \ + return vec<4, T, Q>(this->A, this->B, this->C, this->D); \ + } + +#define GLM_SWIZZLE_GEN_VEC2_ENTRY_DEF(T, P, L, CONST, A, B) \ + template \ + GLM_FUNC_QUALIFIER vec vec::A ## B() CONST \ + { \ + return vec<2, T, Q>(this->A, this->B); \ + } + +#define GLM_SWIZZLE_GEN_VEC3_ENTRY_DEF(T, P, L, CONST, A, B, C) \ + template \ + GLM_FUNC_QUALIFIER vec<3, T, Q> vec::A ## B ## C() CONST \ + { \ + return vec<3, T, Q>(this->A, this->B, this->C); \ + } + +#define GLM_SWIZZLE_GEN_VEC4_ENTRY_DEF(T, P, L, CONST, A, B, C, D) \ + template \ + GLM_FUNC_QUALIFIER vec<4, T, Q> vec::A ## B ## C ## D() CONST \ + { \ + return vec<4, T, Q>(this->A, this->B, this->C, this->D); \ + } + +#define GLM_MUTABLE + +#define GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, 2, GLM_MUTABLE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, 2, GLM_MUTABLE, B, A) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC2(T, P) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(T, P, x, y) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(T, P, r, g) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(T, P, s, t) + +#define GLM_SWIZZLE_GEN_REF2_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, C, B) + +#define GLM_SWIZZLE_GEN_REF3_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, GLM_MUTABLE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, GLM_MUTABLE, A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, GLM_MUTABLE, B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, GLM_MUTABLE, B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, GLM_MUTABLE, C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, GLM_MUTABLE, C, B, A) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_REF3_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC3_SWIZZLE(T, P, A, B, C) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC3(T, P) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(T, P, x, y, z) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(T, P, r, g, b) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(T, P, s, t, p) + +#define GLM_SWIZZLE_GEN_REF2_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, A, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, B, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, C, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, D, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, D, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, D, C) + +#define GLM_SWIZZLE_GEN_REF3_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , A, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , A, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , A, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , A, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , B, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , B, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , B, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , C, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , C, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , C, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , C, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , C, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , D, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , D, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , D, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , D, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , D, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , D, C, B) + +#define GLM_SWIZZLE_GEN_REF4_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , A, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , A, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , A, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , A, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , A, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , B, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , B, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , B, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , B, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , B, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , B, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , C, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , C, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , C, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , C, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , C, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , C, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , D, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , D, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , D, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , D, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , D, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , D, B, C, A) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_REF3_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_REF4_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC4(T, P) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(T, P, x, y, z, w) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(T, P, r, g, b, a) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(T, P, s, t, p, q) + +#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC2_SWIZZLE(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, B) + +#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC2_SWIZZLE(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, B) + +#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC2_SWIZZLE(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, B) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC2_FROM_VEC2_SWIZZLE(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC3_FROM_VEC2_SWIZZLE(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC4_FROM_VEC2_SWIZZLE(T, P, A, B) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC2(T, P) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(T, P, x, y) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(T, P, r, g) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(T, P, s, t) + +#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, C) + +#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, C) + +#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, C) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC2_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_FROM_VEC3_SWIZZLE(T, P, A, B, C) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC3(T, P) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(T, P, x, y, z) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(T, P, r, g, b) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(T, P, s, t, p) + +#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, D, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, D, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, D, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, D, D) + +#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, D, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, D, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, D, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, D, D) + +#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, D, D) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC2_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC4(T, P) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(T, P, x, y, z, w) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(T, P, r, g, b, a) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(T, P, s, t, p, q) + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_vectorize.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_vectorize.hpp new file mode 100644 index 0000000..1fcaec3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_vectorize.hpp @@ -0,0 +1,162 @@ +#pragma once + +namespace glm{ +namespace detail +{ + template class vec, length_t L, typename R, typename T, qualifier Q> + struct functor1{}; + + template class vec, typename R, typename T, qualifier Q> + struct functor1 + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<1, R, Q> call(R (*Func) (T x), vec<1, T, Q> const& v) + { + return vec<1, R, Q>(Func(v.x)); + } + }; + + template class vec, typename R, typename T, qualifier Q> + struct functor1 + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<2, R, Q> call(R (*Func) (T x), vec<2, T, Q> const& v) + { + return vec<2, R, Q>(Func(v.x), Func(v.y)); + } + }; + + template class vec, typename R, typename T, qualifier Q> + struct functor1 + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<3, R, Q> call(R (*Func) (T x), vec<3, T, Q> const& v) + { + return vec<3, R, Q>(Func(v.x), Func(v.y), Func(v.z)); + } + }; + + template class vec, typename R, typename T, qualifier Q> + struct functor1 + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, R, Q> call(R (*Func) (T x), vec<4, T, Q> const& v) + { + return vec<4, R, Q>(Func(v.x), Func(v.y), Func(v.z), Func(v.w)); + } + }; + + template class vec, length_t L, typename T, qualifier Q> + struct functor2{}; + + template class vec, typename T, qualifier Q> + struct functor2 + { + GLM_FUNC_QUALIFIER static vec<1, T, Q> call(T (*Func) (T x, T y), vec<1, T, Q> const& a, vec<1, T, Q> const& b) + { + return vec<1, T, Q>(Func(a.x, b.x)); + } + }; + + template class vec, typename T, qualifier Q> + struct functor2 + { + GLM_FUNC_QUALIFIER static vec<2, T, Q> call(T (*Func) (T x, T y), vec<2, T, Q> const& a, vec<2, T, Q> const& b) + { + return vec<2, T, Q>(Func(a.x, b.x), Func(a.y, b.y)); + } + }; + + template class vec, typename T, qualifier Q> + struct functor2 + { + GLM_FUNC_QUALIFIER static vec<3, T, Q> call(T (*Func) (T x, T y), vec<3, T, Q> const& a, vec<3, T, Q> const& b) + { + return vec<3, T, Q>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z)); + } + }; + + template class vec, typename T, qualifier Q> + struct functor2 + { + GLM_FUNC_QUALIFIER static vec<4, T, Q> call(T (*Func) (T x, T y), vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z), Func(a.w, b.w)); + } + }; + + template class vec, length_t L, typename T, qualifier Q> + struct functor2_vec_sca{}; + + template class vec, typename T, qualifier Q> + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static vec<1, T, Q> call(T (*Func) (T x, T y), vec<1, T, Q> const& a, T b) + { + return vec<1, T, Q>(Func(a.x, b)); + } + }; + + template class vec, typename T, qualifier Q> + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static vec<2, T, Q> call(T (*Func) (T x, T y), vec<2, T, Q> const& a, T b) + { + return vec<2, T, Q>(Func(a.x, b), Func(a.y, b)); + } + }; + + template class vec, typename T, qualifier Q> + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static vec<3, T, Q> call(T (*Func) (T x, T y), vec<3, T, Q> const& a, T b) + { + return vec<3, T, Q>(Func(a.x, b), Func(a.y, b), Func(a.z, b)); + } + }; + + template class vec, typename T, qualifier Q> + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static vec<4, T, Q> call(T (*Func) (T x, T y), vec<4, T, Q> const& a, T b) + { + return vec<4, T, Q>(Func(a.x, b), Func(a.y, b), Func(a.z, b), Func(a.w, b)); + } + }; + + template + struct functor2_vec_int {}; + + template + struct functor2_vec_int<1, T, Q> + { + GLM_FUNC_QUALIFIER static vec<1, int, Q> call(int (*Func) (T x, int y), vec<1, T, Q> const& a, vec<1, int, Q> const& b) + { + return vec<1, int, Q>(Func(a.x, b.x)); + } + }; + + template + struct functor2_vec_int<2, T, Q> + { + GLM_FUNC_QUALIFIER static vec<2, int, Q> call(int (*Func) (T x, int y), vec<2, T, Q> const& a, vec<2, int, Q> const& b) + { + return vec<2, int, Q>(Func(a.x, b.x), Func(a.y, b.y)); + } + }; + + template + struct functor2_vec_int<3, T, Q> + { + GLM_FUNC_QUALIFIER static vec<3, int, Q> call(int (*Func) (T x, int y), vec<3, T, Q> const& a, vec<3, int, Q> const& b) + { + return vec<3, int, Q>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z)); + } + }; + + template + struct functor2_vec_int<4, T, Q> + { + GLM_FUNC_QUALIFIER static vec<4, int, Q> call(int (*Func) (T x, int y), vec<4, T, Q> const& a, vec<4, int, Q> const& b) + { + return vec<4, int, Q>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z), Func(a.w, b.w)); + } + }; +}//namespace detail +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/compute_common.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/compute_common.hpp new file mode 100644 index 0000000..83362bc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/compute_common.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "setup.hpp" +#include + +namespace glm{ +namespace detail +{ + template + struct compute_abs + {}; + + template + struct compute_abs + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static genFIType call(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits::is_signed, + "'abs' only accept floating-point and integer scalar or vector inputs"); + + return x >= genFIType(0) ? x : -x; + // TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff; + } + }; + +#if (GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP) + template<> + struct compute_abs + { + GLM_FUNC_QUALIFIER static float call(float x) + { + return fabsf(x); + } + }; +#endif + + template + struct compute_abs + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static genFIType call(genFIType x) + { + GLM_STATIC_ASSERT( + (!std::numeric_limits::is_signed && std::numeric_limits::is_integer), + "'abs' only accept floating-point and integer scalar or vector inputs"); + return x; + } + }; +}//namespace detail +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/compute_vector_decl.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/compute_vector_decl.hpp new file mode 100644 index 0000000..00d7de5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/compute_vector_decl.hpp @@ -0,0 +1,190 @@ + +#pragma once +#include +#include "_vectorize.hpp" + +namespace glm { + namespace detail + { + template + struct compute_vec_add {}; + + template + struct compute_vec_sub {}; + + template + struct compute_vec_mul {}; + + template + struct compute_vec_div {}; + + template + struct compute_vec_mod {}; + + template + struct compute_splat {}; + + template + struct compute_vec_and {}; + + template + struct compute_vec_or {}; + + template + struct compute_vec_xor {}; + + template + struct compute_vec_shift_left {}; + + template + struct compute_vec_shift_right {}; + + template + struct compute_vec_equal {}; + + template + struct compute_vec_nequal {}; + + template + struct compute_vec_bitwise_not {}; + + template + struct compute_vec_add + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + return detail::functor2::call(std::plus(), a, b); + } + }; + + template + struct compute_vec_sub + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + return detail::functor2::call(std::minus(), a, b); + } + }; + + template + struct compute_vec_mul + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + return detail::functor2::call(std::multiplies(), a, b); + } + }; + + template + struct compute_vec_div + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + return detail::functor2::call(std::divides(), a, b); + } + }; + + template + struct compute_vec_mod + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + return detail::functor2::call(std::modulus(), a, b); + } + }; + + template + struct compute_vec_and + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + vec v(a); + for (length_t i = 0; i < L; ++i) + v[i] &= static_cast(b[i]); + return v; + } + }; + + template + struct compute_vec_or + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + vec v(a); + for (length_t i = 0; i < L; ++i) + v[i] |= static_cast(b[i]); + return v; + } + }; + + template + struct compute_vec_xor + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + vec v(a); + for (length_t i = 0; i < L; ++i) + v[i] ^= static_cast(b[i]); + return v; + } + }; + + template + struct compute_vec_shift_left + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + vec v(a); + for (length_t i = 0; i < L; ++i) + v[i] <<= static_cast(b[i]); + return v; + } + }; + + template + struct compute_vec_shift_right + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + vec v(a); + for (length_t i = 0; i < L; ++i) + v[i] >>= static_cast(b[i]); + return v; + } + }; + + template + struct compute_vec_equal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(vec const& v1, vec const& v2) + { + bool b = true; + for (length_t i = 0; i < L; ++i) + b = b && detail::compute_equal::is_iec559>::call(v1.x, v2.x); + return b; + } + }; + + template + struct compute_vec_nequal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return !compute_vec_equal::value, sizeof(T) * 8, detail::is_aligned::value>::call(v1, v2); + } + }; + + template + struct compute_vec_bitwise_not + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a) + { + vec v(a); + for (length_t i = 0; i < L; ++i) + v[i] = ~v[i]; + return v; + } + }; + + } +} diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/compute_vector_relational.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/compute_vector_relational.hpp new file mode 100644 index 0000000..167b634 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/compute_vector_relational.hpp @@ -0,0 +1,30 @@ +#pragma once + +//#include "compute_common.hpp" +#include "setup.hpp" +#include + +namespace glm{ +namespace detail +{ + template + struct compute_equal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(T a, T b) + { + return a == b; + } + }; +/* + template + struct compute_equal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(T a, T b) + { + return detail::compute_abs::is_signed>::call(b - a) <= static_cast(0); + //return std::memcmp(&a, &b, sizeof(T)) == 0; + } + }; +*/ +}//namespace detail +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_common.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_common.inl new file mode 100644 index 0000000..f8584c9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_common.inl @@ -0,0 +1,792 @@ +/// @ref core +/// @file glm/detail/func_common.inl + +#include "../vector_relational.hpp" +#include "compute_common.hpp" +#include "type_vec1.hpp" +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include "type_vec4.hpp" +#include "_vectorize.hpp" +#include + +namespace glm +{ + // min + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType min(genType x, genType y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits::is_integer, "'min' only accept floating-point or integer inputs"); + return (y < x) ? y : x; + } + + // max + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType max(genType x, genType y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits::is_integer, "'max' only accept floating-point or integer inputs"); + + return (x < y) ? y : x; + } + + // abs + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR int abs(int x) + { + int const y = x >> (sizeof(int) * 8 - 1); + return (x ^ y) - y; + } + + // round +# if GLM_HAS_CXX11_STL + using ::std::round; +# else + template + GLM_FUNC_QUALIFIER genType round(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'round' only accept floating-point inputs"); + + return x < static_cast(0) ? static_cast(int(x - static_cast(0.5))) : static_cast(int(x + static_cast(0.5))); + } +# endif + + // trunc +# if GLM_HAS_CXX11_STL + using ::std::trunc; +# else + template + GLM_FUNC_QUALIFIER genType trunc(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'trunc' only accept floating-point inputs"); + + return x < static_cast(0) ? -std::floor(-x) : std::floor(x); + } +# endif + +}//namespace glm + +namespace glm{ +namespace detail +{ + template + struct compute_abs_vector + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& x) + { + return detail::functor1::call(abs, x); + } + }; + + template + struct compute_mix_vector + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& x, vec const& y, vec const& a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); + + return vec(vec(x) * (static_cast(1) - a) + vec(y) * a); + } + }; + + template + struct compute_mix_vector + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& x, vec const& y, vec const& a) + { + vec Result(0); + for(length_t i = 0; i < x.length(); ++i) + Result[i] = a[i] ? y[i] : x[i]; + return Result; + } + }; + + template + struct compute_mix_scalar + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& x, vec const& y, U const& a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); + + return vec(vec(x) * (static_cast(1) - a) + vec(y) * a); + } + }; + + template + struct compute_mix_scalar + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& x, vec const& y, bool const& a) + { + return a ? y : x; + } + }; + + template + struct compute_mix + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(T const& x, T const& y, U const& a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); + + return static_cast(static_cast(x) * (static_cast(1) - a) + static_cast(y) * a); + } + }; + + template + struct compute_mix + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(T const& x, T const& y, bool const& a) + { + return a ? y : x; + } + }; + + template + struct compute_sign + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& x) + { + return vec(glm::lessThan(vec(0), x)) - vec(glm::lessThan(x, vec(0))); + } + }; + +# if GLM_ARCH == GLM_ARCH_X86 + template + struct compute_sign + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& x) + { + T const Shift(static_cast(sizeof(T) * 8 - 1)); + vec const y(vec::type, Q>(-x) >> typename detail::make_unsigned::type(Shift)); + + return (x >> Shift) | y; + } + }; +# endif + + template + struct compute_floor + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(std::floor, x); + } + }; + + template + struct compute_ceil + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(std::ceil, x); + } + }; + + template + struct compute_fract + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return x - floor(x); + } + }; + + template + struct compute_trunc + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(trunc, x); + } + }; + + template + struct compute_round + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(round, x); + } + }; + + template + struct compute_mod + { + GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'mod' only accept floating-point inputs. Include for integer inputs."); + return a - b * floor(a / b); + } + }; + + template + struct compute_min_vector + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, vec const& y) + { + return detail::functor2::call(min, x, y); + } + }; + + template + struct compute_max_vector + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, vec const& y) + { + return detail::functor2::call(max, x, y); + } + }; + + template + struct compute_clamp_vector + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, vec const& minVal, vec const& maxVal) + { + return min(max(x, minVal), maxVal); + } + }; + + template + struct compute_step_vector + { + GLM_FUNC_QUALIFIER static vec call(vec const& edge, vec const& x) + { + return mix(vec(1), vec(0), glm::lessThan(x, edge)); + } + }; + + template + struct compute_smoothstep_vector + { + GLM_FUNC_QUALIFIER static vec call(vec const& edge0, vec const& edge1, vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'smoothstep' only accept floating-point inputs"); + vec const tmp(clamp((x - edge0) / (edge1 - edge0), static_cast(0), static_cast(1))); + return tmp * tmp * (static_cast(3) - static_cast(2) * tmp); + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genFIType abs(genFIType x) + { + return detail::compute_abs::is_signed>::call(x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec abs(vec const& x) + { + return detail::compute_abs_vector::value>::call(x); + } + + // sign + // fast and works for any type + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genFIType sign(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || (std::numeric_limits::is_signed && std::numeric_limits::is_integer), + "'sign' only accept signed inputs"); + + return detail::compute_sign<1, genFIType, defaultp, + std::numeric_limits::is_iec559, detail::is_aligned::value>::call(vec<1, genFIType>(x)).x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec sign(vec const& x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || (std::numeric_limits::is_signed && std::numeric_limits::is_integer), + "'sign' only accept signed inputs"); + + return detail::compute_sign::is_iec559, detail::is_aligned::value>::call(x); + } + + // floor + using ::std::floor; + template + GLM_FUNC_QUALIFIER vec floor(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'floor' only accept floating-point inputs."); + return detail::compute_floor::value>::call(x); + } + + template + GLM_FUNC_QUALIFIER vec trunc(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'trunc' only accept floating-point inputs"); + return detail::compute_trunc::value>::call(x); + } + + template + GLM_FUNC_QUALIFIER vec round(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'round' only accept floating-point inputs"); + return detail::compute_round::value>::call(x); + } + +/* + // roundEven + template + GLM_FUNC_QUALIFIER genType roundEven(genType const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'roundEven' only accept floating-point inputs"); + + return genType(int(x + genType(int(x) % 2))); + } +*/ + + // roundEven + template + GLM_FUNC_QUALIFIER genType roundEven(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'roundEven' only accept floating-point inputs"); + + int Integer = static_cast(x); + genType IntegerPart = static_cast(Integer); + genType FractionalPart = fract(x); + + if(FractionalPart > static_cast(0.5) || FractionalPart < static_cast(0.5)) + { + return round(x); + } + else if((Integer % 2) == 0) + { + return IntegerPart; + } + else if(x <= static_cast(0)) // Work around... + { + return IntegerPart - static_cast(1); + } + else + { + return IntegerPart + static_cast(1); + } + //else // Bug on MinGW 4.5.2 + //{ + // return mix(IntegerPart + genType(-1), IntegerPart + genType(1), x <= genType(0)); + //} + } + + template + GLM_FUNC_QUALIFIER vec roundEven(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'roundEven' only accept floating-point inputs"); + return detail::functor1::call(roundEven, x); + } + + // ceil + using ::std::ceil; + template + GLM_FUNC_QUALIFIER vec ceil(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'ceil' only accept floating-point inputs"); + return detail::compute_ceil::value>::call(x); + } + + // fract + template + GLM_FUNC_QUALIFIER genType fract(genType x) + { + return fract(vec<1, genType>(x)).x; + } + + template + GLM_FUNC_QUALIFIER vec fract(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'fract' only accept floating-point inputs"); + return detail::compute_fract::value>::call(x); + } + + // mod + template + GLM_FUNC_QUALIFIER genType mod(genType x, genType y) + { +# if (GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP) + // Another Cuda compiler bug https://github.com/g-truc/glm/issues/530 + vec<1, genType, defaultp> Result(mod(vec<1, genType, defaultp>(x), y)); + return Result.x; +# else + return mod(vec<1, genType, defaultp>(x), y).x; +# endif + } + + template + GLM_FUNC_QUALIFIER vec mod(vec const& x, T y) + { + return detail::compute_mod::value>::call(x, vec(y)); + } + + template + GLM_FUNC_QUALIFIER vec mod(vec const& x, vec const& y) + { + return detail::compute_mod::value>::call(x, y); + } + + // modf + template + GLM_FUNC_QUALIFIER genType modf(genType x, genType & i) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'modf' only accept floating-point inputs"); + return std::modf(x, &i); + } + + template + GLM_FUNC_QUALIFIER vec<1, T, Q> modf(vec<1, T, Q> const& x, vec<1, T, Q> & i) + { + return vec<1, T, Q>( + modf(x.x, i.x)); + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> modf(vec<2, T, Q> const& x, vec<2, T, Q> & i) + { + return vec<2, T, Q>( + modf(x.x, i.x), + modf(x.y, i.y)); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> modf(vec<3, T, Q> const& x, vec<3, T, Q> & i) + { + return vec<3, T, Q>( + modf(x.x, i.x), + modf(x.y, i.y), + modf(x.z, i.z)); + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> modf(vec<4, T, Q> const& x, vec<4, T, Q> & i) + { + return vec<4, T, Q>( + modf(x.x, i.x), + modf(x.y, i.y), + modf(x.z, i.z), + modf(x.w, i.w)); + } + + //// Only valid if (INT_MIN <= x-y <= INT_MAX) + //// min(x,y) + //r = y + ((x - y) & ((x - y) >> (sizeof(int) * + //CHAR_BIT - 1))); + //// max(x,y) + //r = x - ((x - y) & ((x - y) >> (sizeof(int) * + //CHAR_BIT - 1))); + + // min + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec min(vec const& a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits::is_integer, "'min' only accept floating-point or integer inputs"); + return detail::compute_min_vector::value>::call(a, vec(b)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec min(vec const& a, vec const& b) + { + return detail::compute_min_vector::value>::call(a, b); + } + + // max + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec max(vec const& a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits::is_integer, "'max' only accept floating-point or integer inputs"); + return detail::compute_max_vector::value>::call(a, vec(b)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec max(vec const& a, vec const& b) + { + return detail::compute_max_vector::value>::call(a, b); + } + + // clamp + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType clamp(genType x, genType minVal, genType maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits::is_integer, "'clamp' only accept floating-point or integer inputs"); + return min(max(x, minVal), maxVal); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec clamp(vec const& x, T minVal, T maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits::is_integer, "'clamp' only accept floating-point or integer inputs"); + return detail::compute_clamp_vector::value>::call(x, vec(minVal), vec(maxVal)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec clamp(vec const& x, vec const& minVal, vec const& maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits::is_integer, "'clamp' only accept floating-point or integer inputs"); + return detail::compute_clamp_vector::value>::call(x, minVal, maxVal); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genTypeT mix(genTypeT x, genTypeT y, genTypeU a) + { + return detail::compute_mix::call(x, y, a); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec mix(vec const& x, vec const& y, U a) + { + return detail::compute_mix_scalar::value>::call(x, y, a); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec mix(vec const& x, vec const& y, vec const& a) + { + return detail::compute_mix_vector::value>::call(x, y, a); + } + + // step + template + GLM_FUNC_QUALIFIER genType step(genType edge, genType x) + { + return mix(static_cast(1), static_cast(0), x < edge); + } + + template + GLM_FUNC_QUALIFIER vec step(T edge, vec const& x) + { + return detail::compute_step_vector::value>::call(vec(edge), x); + } + + template + GLM_FUNC_QUALIFIER vec step(vec const& edge, vec const& x) + { + return detail::compute_step_vector::value>::call(edge, x); + } + + // smoothstep + template + GLM_FUNC_QUALIFIER genType smoothstep(genType edge0, genType edge1, genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'smoothstep' only accept floating-point inputs"); + + genType const tmp(clamp((x - edge0) / (edge1 - edge0), genType(0), genType(1))); + return tmp * tmp * (genType(3) - genType(2) * tmp); + } + + template + GLM_FUNC_QUALIFIER vec smoothstep(T edge0, T edge1, vec const& x) + { + return detail::compute_smoothstep_vector::value>::call(vec(edge0), vec(edge1), x); + } + + template + GLM_FUNC_QUALIFIER vec smoothstep(vec const& edge0, vec const& edge1, vec const& x) + { + return detail::compute_smoothstep_vector::value>::call(edge0, edge1, x); + } + +# if GLM_HAS_CXX11_STL + using std::isnan; +# else + template + GLM_FUNC_QUALIFIER bool isnan(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isnan' only accept floating-point inputs"); + +# if GLM_HAS_CXX11_STL + return std::isnan(x); +# elif GLM_COMPILER & GLM_COMPILER_VC + return _isnan(x) != 0; +# elif GLM_COMPILER & GLM_COMPILER_INTEL +# if GLM_PLATFORM & GLM_PLATFORM_WINDOWS + return _isnan(x) != 0; +# else + return ::isnan(x) != 0; +# endif +# elif (GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)) && (GLM_PLATFORM & GLM_PLATFORM_ANDROID) && __cplusplus < 201103L + return _isnan(x) != 0; +# elif (GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP) + return ::isnan(x) != 0; +# else + return std::isnan(x); +# endif + } +# endif + + template + GLM_FUNC_QUALIFIER vec isnan(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isnan' only accept floating-point inputs"); + + vec Result(0); + for (length_t l = 0; l < v.length(); ++l) + Result[l] = glm::isnan(v[l]); + return Result; + } + +# if GLM_HAS_CXX11_STL + using std::isinf; +# else + template + GLM_FUNC_QUALIFIER bool isinf(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isinf' only accept floating-point inputs"); + +# if GLM_HAS_CXX11_STL + return std::isinf(x); +# elif GLM_COMPILER & (GLM_COMPILER_INTEL | GLM_COMPILER_VC) +# if(GLM_PLATFORM & GLM_PLATFORM_WINDOWS) + return _fpclass(x) == _FPCLASS_NINF || _fpclass(x) == _FPCLASS_PINF; +# else + return ::isinf(x); +# endif +# elif GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG) +# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID && __cplusplus < 201103L) + return _isinf(x) != 0; +# else + return std::isinf(x); +# endif +# elif (GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP) + // http://developer.download.nvidia.com/compute/cuda/4_2/rel/toolkit/docs/online/group__CUDA__MATH__DOUBLE_g13431dd2b40b51f9139cbb7f50c18fab.html#g13431dd2b40b51f9139cbb7f50c18fab + return ::isinf(double(x)) != 0; +# else + return std::isinf(x); +# endif + } +# endif + + template + GLM_FUNC_QUALIFIER vec isinf(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isinf' only accept floating-point inputs"); + + vec Result(0); + for (length_t l = 0; l < v.length(); ++l) + Result[l] = glm::isinf(v[l]); + return Result; + } + + GLM_FUNC_QUALIFIER int floatBitsToInt(float v) + { + union + { + float in; + int out; + } u; + + u.in = v; + + return u.out; + } + + template + GLM_FUNC_QUALIFIER vec floatBitsToInt(vec const& v) + { + return detail::functor1::call(floatBitsToInt, v); + } + + GLM_FUNC_QUALIFIER uint floatBitsToUint(float v) + { + union + { + float in; + uint out; + } u; + + u.in = v; + + return u.out; + } + + template + GLM_FUNC_QUALIFIER vec floatBitsToUint(vec const& v) + { + return detail::functor1::call(floatBitsToUint, v); + } + + GLM_FUNC_QUALIFIER float intBitsToFloat(int v) + { + union + { + int in; + float out; + } u; + + u.in = v; + + return u.out; + } + + template + GLM_FUNC_QUALIFIER vec intBitsToFloat(vec const& v) + { + return detail::functor1::call(intBitsToFloat, v); + } + + GLM_FUNC_QUALIFIER float uintBitsToFloat(uint v) + { + union + { + uint in; + float out; + } u; + + u.in = v; + + return u.out; + } + + template + GLM_FUNC_QUALIFIER vec uintBitsToFloat(vec const& v) + { + return reinterpret_cast&>(const_cast&>(v)); + } + +# if GLM_HAS_CXX11_STL + using std::fma; +# else + template + GLM_FUNC_QUALIFIER genType fma(genType const& a, genType const& b, genType const& c) + { + return a * b + c; + } +# endif + + template + GLM_FUNC_QUALIFIER genType frexp(genType x, int& exp) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'frexp' only accept floating-point inputs"); + + return std::frexp(x, &exp); + } + + template + GLM_FUNC_QUALIFIER vec frexp(vec const& v, vec& exp) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'frexp' only accept floating-point inputs"); + + vec Result(0); + for (length_t l = 0; l < v.length(); ++l) + Result[l] = std::frexp(v[l], &exp[l]); + return Result; + } + + template + GLM_FUNC_QUALIFIER genType ldexp(genType const& x, int const& exp) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'ldexp' only accept floating-point inputs"); + + return std::ldexp(x, exp); + } + + template + GLM_FUNC_QUALIFIER vec ldexp(vec const& v, vec const& exp) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'ldexp' only accept floating-point inputs"); + + vec Result(0); + for (length_t l = 0; l < v.length(); ++l) + Result[l] = std::ldexp(v[l], exp[l]); + return Result; + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_common_simd.inl" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_common_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_common_simd.inl new file mode 100644 index 0000000..ce0032d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_common_simd.inl @@ -0,0 +1,231 @@ +/// @ref core +/// @file glm/detail/func_common_simd.inl + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +#include "../simd/common.h" + +#include + +namespace glm{ +namespace detail +{ + template + struct compute_abs_vector<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> result; + result.data = glm_vec4_abs(v.data); + return result; + } + }; + + template + struct compute_abs_vector<4, int, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, int, Q> call(vec<4, int, Q> const& v) + { + vec<4, int, Q> result; + result.data = glm_ivec4_abs(v.data); + return result; + } + }; + + template + struct compute_floor<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> result; + result.data = glm_vec4_floor(v.data); + return result; + } + }; + + template + struct compute_ceil<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> result; + result.data = glm_vec4_ceil(v.data); + return result; + } + }; + + template + struct compute_fract<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> result; + result.data = glm_vec4_fract(v.data); + return result; + } + }; + + template + struct compute_round<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> result; + result.data = glm_vec4_round(v.data); + return result; + } + }; + + template + struct compute_mod<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& x, vec<4, float, Q> const& y) + { + vec<4, float, Q> result; + result.data = glm_vec4_mod(x.data, y.data); + return result; + } + }; + + template + struct compute_min_vector<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + vec<4, float, Q> result; + result.data = _mm_min_ps(v1.data, v2.data); + return result; + } + }; + + template + struct compute_min_vector<4, int, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, int, Q> call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + vec<4, int, Q> result; + result.data = _mm_min_epi32(v1.data, v2.data); + return result; + } + }; + + template + struct compute_min_vector<4, uint, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, uint, Q> call(vec<4, uint, Q> const& v1, vec<4, uint, Q> const& v2) + { + vec<4, uint, Q> result; + result.data = _mm_min_epu32(v1.data, v2.data); + return result; + } + }; + + template + struct compute_max_vector<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + vec<4, float, Q> result; + result.data = _mm_max_ps(v1.data, v2.data); + return result; + } + }; + + template + struct compute_max_vector<4, int, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, int, Q> call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + vec<4, int, Q> result; + result.data = _mm_max_epi32(v1.data, v2.data); + return result; + } + }; + + template + struct compute_max_vector<4, uint, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, uint, Q> call(vec<4, uint, Q> const& v1, vec<4, uint, Q> const& v2) + { + vec<4, uint, Q> result; + result.data = _mm_max_epu32(v1.data, v2.data); + return result; + } + }; + + template + struct compute_clamp_vector<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& x, vec<4, float, Q> const& minVal, vec<4, float, Q> const& maxVal) + { + vec<4, float, Q> result; + result.data = _mm_min_ps(_mm_max_ps(x.data, minVal.data), maxVal.data); + return result; + } + }; + + template + struct compute_clamp_vector<4, int, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, int, Q> call(vec<4, int, Q> const& x, vec<4, int, Q> const& minVal, vec<4, int, Q> const& maxVal) + { + vec<4, int, Q> result; + result.data = _mm_min_epi32(_mm_max_epi32(x.data, minVal.data), maxVal.data); + return result; + } + }; + + template + struct compute_clamp_vector<4, uint, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, uint, Q> call(vec<4, uint, Q> const& x, vec<4, uint, Q> const& minVal, vec<4, uint, Q> const& maxVal) + { + vec<4, uint, Q> result; + result.data = _mm_min_epu32(_mm_max_epu32(x.data, minVal.data), maxVal.data); + return result; + } + }; + + template + struct compute_mix_vector<4, float, bool, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& x, vec<4, float, Q> const& y, vec<4, bool, Q> const& a) + { + __m128i const Load = _mm_set_epi32(-static_cast(a.w), -static_cast(a.z), -static_cast(a.y), -static_cast(a.x)); + __m128 const Mask = _mm_castsi128_ps(Load); + + vec<4, float, Q> Result; +# if 0 && GLM_ARCH & GLM_ARCH_AVX + Result.data = _mm_blendv_ps(x.data, y.data, Mask); +# else + Result.data = _mm_or_ps(_mm_and_ps(Mask, y.data), _mm_andnot_ps(Mask, x.data)); +# endif + return Result; + } + }; +/* FIXME + template + struct compute_step_vector + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& edge, vec<4, float, Q> const& x) + { + vec<4, float, Q> Result; + result.data = glm_vec4_step(edge.data, x.data); + return result; + } + }; +*/ + template + struct compute_smoothstep_vector<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& edge0, vec<4, float, Q> const& edge1, vec<4, float, Q> const& x) + { + vec<4, float, Q> Result; + Result.data = glm_vec4_smoothstep(edge0.data, edge1.data, x.data); + return Result; + } + }; +}//namespace detail +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_exponential.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_exponential.inl new file mode 100644 index 0000000..2efcdc6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_exponential.inl @@ -0,0 +1,152 @@ +/// @ref core +/// @file glm/detail/func_exponential.inl + +#include "../vector_relational.hpp" +#include "_vectorize.hpp" +#include +#include +#include + +namespace glm{ +namespace detail +{ +# if GLM_HAS_CXX11_STL + using std::log2; +# else + template + genType log2(genType Value) + { + return std::log(Value) * static_cast(1.4426950408889634073599246810019); + } +# endif + + template + struct compute_log2 + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'log2' only accept floating-point inputs. Include for integer inputs."); + + return detail::functor1::call(log2, v); + } + }; + + template + struct compute_sqrt + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(std::sqrt, x); + } + }; + + template + struct compute_inversesqrt + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return static_cast(1) / sqrt(x); + } + }; + + template + struct compute_inversesqrt + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + vec tmp(x); + vec xhalf(tmp * 0.5f); + vec* p = reinterpret_cast*>(const_cast*>(&x)); + vec i = vec(0x5f375a86) - (*p >> vec(1)); + vec* ptmp = reinterpret_cast*>(&i); + tmp = *ptmp; + tmp = tmp * (1.5f - xhalf * tmp * tmp); + return tmp; + } + }; +}//namespace detail + + // pow + using std::pow; + template + GLM_FUNC_QUALIFIER vec pow(vec const& base, vec const& exponent) + { + return detail::functor2::call(pow, base, exponent); + } + + // exp + using std::exp; + template + GLM_FUNC_QUALIFIER vec exp(vec const& x) + { + return detail::functor1::call(exp, x); + } + + // log + using std::log; + template + GLM_FUNC_QUALIFIER vec log(vec const& x) + { + return detail::functor1::call(log, x); + } + +# if GLM_HAS_CXX11_STL + using std::exp2; +# else + //exp2, ln2 = 0.69314718055994530941723212145818f + template + GLM_FUNC_QUALIFIER genType exp2(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'exp2' only accept floating-point inputs"); + + return std::exp(static_cast(0.69314718055994530941723212145818) * x); + } +# endif + + template + GLM_FUNC_QUALIFIER vec exp2(vec const& x) + { + return detail::functor1::call(exp2, x); + } + + // log2, ln2 = 0.69314718055994530941723212145818f + template + GLM_FUNC_QUALIFIER genType log2(genType x) + { + return log2(vec<1, genType>(x)).x; + } + + template + GLM_FUNC_QUALIFIER vec log2(vec const& x) + { + return detail::compute_log2::is_iec559, detail::is_aligned::value>::call(x); + } + + // sqrt + using std::sqrt; + template + GLM_FUNC_QUALIFIER vec sqrt(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'sqrt' only accept floating-point inputs"); + return detail::compute_sqrt::value>::call(x); + } + + // inversesqrt + template + GLM_FUNC_QUALIFIER genType inversesqrt(genType x) + { + return static_cast(1) / sqrt(x); + } + + template + GLM_FUNC_QUALIFIER vec inversesqrt(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'inversesqrt' only accept floating-point inputs"); + return detail::compute_inversesqrt::value>::call(x); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_exponential_simd.inl" +#endif + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_exponential_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_exponential_simd.inl new file mode 100644 index 0000000..fb78951 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_exponential_simd.inl @@ -0,0 +1,37 @@ +/// @ref core +/// @file glm/detail/func_exponential_simd.inl + +#include "../simd/exponential.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ + template + struct compute_sqrt<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> Result; + Result.data = _mm_sqrt_ps(v.data); + return Result; + } + }; + +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + template<> + struct compute_sqrt<4, float, aligned_lowp, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, aligned_lowp> call(vec<4, float, aligned_lowp> const& v) + { + vec<4, float, aligned_lowp> Result; + Result.data = glm_vec4_sqrt_lowp(v.data); + return Result; + } + }; +# endif +}//namespace detail +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_geometric.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_geometric.inl new file mode 100644 index 0000000..404c990 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_geometric.inl @@ -0,0 +1,243 @@ +#include "../exponential.hpp" +#include "../common.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_length + { + GLM_FUNC_QUALIFIER static T call(vec const& v) + { + return sqrt(dot(v, v)); + } + }; + + template + struct compute_distance + { + GLM_FUNC_QUALIFIER static T call(vec const& p0, vec const& p1) + { + return length(p1 - p0); + } + }; + + template + struct compute_dot{}; + + template + struct compute_dot, T, Aligned> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(vec<1, T, Q> const& a, vec<1, T, Q> const& b) + { + return a.x * b.x; + } + }; + + template + struct compute_dot, T, Aligned> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(vec<2, T, Q> const& a, vec<2, T, Q> const& b) + { + vec<2, T, Q> tmp(a * b); + return tmp.x + tmp.y; + } + }; + + template + struct compute_dot, T, Aligned> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(vec<3, T, Q> const& a, vec<3, T, Q> const& b) + { + vec<3, T, Q> tmp(a * b); + return tmp.x + tmp.y + tmp.z; + } + }; + + template + struct compute_dot, T, Aligned> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> tmp(a * b); + return (tmp.x + tmp.y) + (tmp.z + tmp.w); + } + }; + + template + struct compute_cross + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<3, T, Q> call(vec<3, T, Q> const& x, vec<3, T, Q> const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'cross' accepts only floating-point inputs"); + + return vec<3, T, Q>( + x.y * y.z - y.y * x.z, + x.z * y.x - y.z * x.x, + x.x * y.y - y.x * x.y); + } + }; + + template + struct compute_normalize + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'normalize' accepts only floating-point inputs"); + + return v * inversesqrt(dot(v, v)); + } + }; + + template + struct compute_faceforward + { + GLM_FUNC_QUALIFIER static vec call(vec const& N, vec const& I, vec const& Nref) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'normalize' accepts only floating-point inputs"); + + return dot(Nref, I) < static_cast(0) ? N : -N; + } + }; + + template + struct compute_reflect + { + GLM_FUNC_QUALIFIER static vec call(vec const& I, vec const& N) + { + return I - N * dot(N, I) * static_cast(2); + } + }; + + template + struct compute_refract + { + GLM_FUNC_QUALIFIER static vec call(vec const& I, vec const& N, T eta) + { + T const dotValue(dot(N, I)); + T const k(static_cast(1) - eta * eta * (static_cast(1) - dotValue * dotValue)); + vec const Result = + (k >= static_cast(0)) ? (eta * I - (eta * dotValue + std::sqrt(k)) * N) : vec(0); + return Result; + } + }; +}//namespace detail + + // length + template + GLM_FUNC_QUALIFIER genType length(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'length' accepts only floating-point inputs"); + + return abs(x); + } + + template + GLM_FUNC_QUALIFIER T length(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'length' accepts only floating-point inputs"); + + return detail::compute_length::value>::call(v); + } + + // distance + template + GLM_FUNC_QUALIFIER genType distance(genType const& p0, genType const& p1) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'distance' accepts only floating-point inputs"); + + return length(p1 - p0); + } + + template + GLM_FUNC_QUALIFIER T distance(vec const& p0, vec const& p1) + { + return detail::compute_distance::value>::call(p0, p1); + } + + // dot + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T dot(T x, T y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'dot' accepts only floating-point inputs"); + return x * y; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T dot(vec const& x, vec const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'dot' accepts only floating-point inputs"); + return detail::compute_dot, T, detail::is_aligned::value>::call(x, y); + } + + // cross + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> cross(vec<3, T, Q> const& x, vec<3, T, Q> const& y) + { + return detail::compute_cross::value>::call(x, y); + } +/* + // normalize + template + GLM_FUNC_QUALIFIER genType normalize(genType const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'normalize' accepts only floating-point inputs"); + + return x < genType(0) ? genType(-1) : genType(1); + } +*/ + template + GLM_FUNC_QUALIFIER vec normalize(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'normalize' accepts only floating-point inputs"); + + return detail::compute_normalize::value>::call(x); + } + + // faceforward + template + GLM_FUNC_QUALIFIER genType faceforward(genType const& N, genType const& I, genType const& Nref) + { + return dot(Nref, I) < static_cast(0) ? N : -N; + } + + template + GLM_FUNC_QUALIFIER vec faceforward(vec const& N, vec const& I, vec const& Nref) + { + return detail::compute_faceforward::value>::call(N, I, Nref); + } + + // reflect + template + GLM_FUNC_QUALIFIER genType reflect(genType const& I, genType const& N) + { + return I - N * dot(N, I) * genType(2); + } + + template + GLM_FUNC_QUALIFIER vec reflect(vec const& I, vec const& N) + { + return detail::compute_reflect::value>::call(I, N); + } + + // refract + template + GLM_FUNC_QUALIFIER genType refract(genType const& I, genType const& N, genType eta) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'refract' accepts only floating-point inputs"); + genType const dotValue(dot(N, I)); + genType const k(static_cast(1) - eta * eta * (static_cast(1) - dotValue * dotValue)); + return (eta * I - (eta * dotValue + sqrt(k)) * N) * static_cast(k >= static_cast(0)); + } + + template + GLM_FUNC_QUALIFIER vec refract(vec const& I, vec const& N, T eta) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'refract' accepts only floating-point inputs"); + return detail::compute_refract::value>::call(I, N, eta); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_geometric_simd.inl" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_geometric_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_geometric_simd.inl new file mode 100644 index 0000000..2076dae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_geometric_simd.inl @@ -0,0 +1,163 @@ +/// @ref core +/// @file glm/detail/func_geometric_simd.inl + +#include "../simd/geometric.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ + template + struct compute_length<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& v) + { + return _mm_cvtss_f32(glm_vec4_length(v.data)); + } + }; + + template + struct compute_distance<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& p0, vec<4, float, Q> const& p1) + { + return _mm_cvtss_f32(glm_vec4_distance(p0.data, p1.data)); + } + }; + + template + struct compute_dot, float, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& x, vec<4, float, Q> const& y) + { + return _mm_cvtss_f32(glm_vec1_dot(x.data, y.data)); + } + }; + + template + struct compute_cross + { + GLM_FUNC_QUALIFIER static vec<3, float, Q> call(vec<3, float, Q> const& a, vec<3, float, Q> const& b) + { + __m128 const set0 = _mm_set_ps(0.0f, a.z, a.y, a.x); + __m128 const set1 = _mm_set_ps(0.0f, b.z, b.y, b.x); + __m128 const xpd0 = glm_vec4_cross(set0, set1); + + vec<4, float, Q> Result; + Result.data = xpd0; + return vec<3, float, Q>(Result); + } + }; + + template + struct compute_normalize<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> Result; + Result.data = glm_vec4_normalize(v.data); + return Result; + } + }; + + template + struct compute_faceforward<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& N, vec<4, float, Q> const& I, vec<4, float, Q> const& Nref) + { + vec<4, float, Q> Result; + Result.data = glm_vec4_faceforward(N.data, I.data, Nref.data); + return Result; + } + }; + + template + struct compute_reflect<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& I, vec<4, float, Q> const& N) + { + vec<4, float, Q> Result; + Result.data = glm_vec4_reflect(I.data, N.data); + return Result; + } + }; + + template + struct compute_refract<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& I, vec<4, float, Q> const& N, float eta) + { + vec<4, float, Q> Result; + Result.data = glm_vec4_refract(I.data, N.data, _mm_set1_ps(eta)); + return Result; + } + }; +}//namespace detail +}//namespace glm + +#elif GLM_ARCH & GLM_ARCH_NEON_BIT +namespace glm{ +namespace detail +{ + template + struct compute_length<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& v) + { + return sqrt(compute_dot, float, true>::call(v, v)); + } + }; + + template + struct compute_distance<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& p0, vec<4, float, Q> const& p1) + { + return compute_length<4, float, Q, true>::call(p1 - p0); + } + }; + + + template + struct compute_dot, float, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& x, vec<4, float, Q> const& y) + { +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + float32x4_t v = vmulq_f32(x.data, y.data); + return vaddvq_f32(v); +#else // Armv7a with Neon + float32x4_t p = vmulq_f32(x.data, y.data); + float32x2_t v = vpadd_f32(vget_low_f32(p), vget_high_f32(p)); + v = vpadd_f32(v, v); + return vget_lane_f32(v, 0); +#endif + } + }; + + template + struct compute_normalize<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + float32x4_t p = vmulq_f32(v.data, v.data); +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + p = vpaddq_f32(p, p); + p = vpaddq_f32(p, p); +#else + float32x2_t t = vpadd_f32(vget_low_f32(p), vget_high_f32(p)); + t = vpadd_f32(t, t); + p = vcombine_f32(t, t); +#endif + + float32x4_t vd = vrsqrteq_f32(p); + vec<4, float, Q> Result; + Result.data = vmulq_f32(v.data, vd); + return Result; + } + }; +}//namespace detail +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_integer.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_integer.inl new file mode 100644 index 0000000..67177a0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_integer.inl @@ -0,0 +1,392 @@ +/// @ref core + +#include "_vectorize.hpp" +#if(GLM_ARCH & GLM_ARCH_X86 && GLM_COMPILER & GLM_COMPILER_VC) +# include +# pragma intrinsic(_BitScanReverse) +#endif//(GLM_ARCH & GLM_ARCH_X86 && GLM_COMPILER & GLM_COMPILER_VC) +#include + +#if !GLM_HAS_EXTENDED_INTEGER_TYPE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wlong-long" +# endif +# if (GLM_COMPILER & GLM_COMPILER_CLANG) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wc++11-long-long" +# endif +#endif + +namespace glm{ +namespace detail +{ + template + GLM_FUNC_QUALIFIER T mask(T Bits) + { + return Bits >= static_cast(sizeof(T) * 8) ? ~static_cast(0) : (static_cast(1) << Bits) - static_cast(1); + } + + template + struct compute_bitfieldReverseStep + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T, T) + { + return v; + } + }; + + template + struct compute_bitfieldReverseStep + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T Mask, T Shift) + { + return (v & Mask) << Shift | (v & (~Mask)) >> Shift; + } + }; + + template + struct compute_bitfieldBitCountStep + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T, T) + { + return v; + } + }; + + template + struct compute_bitfieldBitCountStep + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T Mask, T Shift) + { + return (v & Mask) + ((v >> Shift) & Mask); + } + }; + + template + struct compute_findLSB + { + GLM_FUNC_QUALIFIER static int call(genIUType Value) + { + if(Value == 0) + return -1; + + return glm::bitCount(~Value & (Value - static_cast(1))); + } + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template + struct compute_findLSB + { + GLM_FUNC_QUALIFIER static int call(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanForward(&Result, *reinterpret_cast(&Value)); + return IsNotNull ? int(Result) : -1; + } + }; + +# if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_MODEL == GLM_MODEL_32)) + template + struct compute_findLSB + { + GLM_FUNC_QUALIFIER static int call(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanForward64(&Result, *reinterpret_cast(&Value)); + return IsNotNull ? int(Result) : -1; + } + }; +# endif +# endif//GLM_HAS_BITSCAN_WINDOWS + + template + struct compute_findMSB_step_vec + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, T Shift) + { + return x | (x >> Shift); + } + }; + + template + struct compute_findMSB_step_vec + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, T) + { + return x; + } + }; + + template + struct compute_findMSB_vec + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + vec x(v); + x = compute_findMSB_step_vec= 8>::call(x, static_cast( 1)); + x = compute_findMSB_step_vec= 8>::call(x, static_cast( 2)); + x = compute_findMSB_step_vec= 8>::call(x, static_cast( 4)); + x = compute_findMSB_step_vec= 16>::call(x, static_cast( 8)); + x = compute_findMSB_step_vec= 32>::call(x, static_cast(16)); + x = compute_findMSB_step_vec= 64>::call(x, static_cast(32)); + return vec(sizeof(T) * 8 - 1) - glm::bitCount(~x); + } + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template + GLM_FUNC_QUALIFIER int compute_findMSB_32(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanReverse(&Result, *reinterpret_cast(&Value)); + return IsNotNull ? int(Result) : -1; + } + + template + struct compute_findMSB_vec + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(compute_findMSB_32, x); + } + }; + +# if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_MODEL == GLM_MODEL_32)) + template + GLM_FUNC_QUALIFIER int compute_findMSB_64(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanReverse64(&Result, *reinterpret_cast(&Value)); + return IsNotNull ? int(Result) : -1; + } + + template + struct compute_findMSB_vec + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(compute_findMSB_64, x); + } + }; +# endif +# endif//GLM_HAS_BITSCAN_WINDOWS +}//namespace detail + + // uaddCarry + GLM_FUNC_QUALIFIER uint uaddCarry(uint const& x, uint const& y, uint & Carry) + { + detail::uint64 const Value64(static_cast(x) + static_cast(y)); + detail::uint64 const Max32((static_cast(1) << static_cast(32)) - static_cast(1)); + Carry = Value64 > Max32 ? 1u : 0u; + return static_cast(Value64 % (Max32 + static_cast(1))); + } + + template + GLM_FUNC_QUALIFIER vec uaddCarry(vec const& x, vec const& y, vec& Carry) + { + vec Value64(vec(x) + vec(y)); + vec Max32((static_cast(1) << static_cast(32)) - static_cast(1)); + Carry = mix(vec(0), vec(1), greaterThan(Value64, Max32)); + return vec(Value64 % (Max32 + static_cast(1))); + } + + // usubBorrow + GLM_FUNC_QUALIFIER uint usubBorrow(uint const& x, uint const& y, uint & Borrow) + { + Borrow = x >= y ? static_cast(0) : static_cast(1); + if(y >= x) + return y - x; + else + return static_cast((static_cast(1) << static_cast(32)) + (static_cast(y) - static_cast(x))); + } + + template + GLM_FUNC_QUALIFIER vec usubBorrow(vec const& x, vec const& y, vec& Borrow) + { + Borrow = mix(vec(1), vec(0), greaterThanEqual(x, y)); + vec const YgeX(y - x); + vec const XgeY(vec((static_cast(1) << static_cast(32)) + (vec(y) - vec(x)))); + return mix(XgeY, YgeX, greaterThanEqual(y, x)); + } + + // umulExtended + GLM_FUNC_QUALIFIER void umulExtended(uint const& x, uint const& y, uint & msb, uint & lsb) + { + detail::uint64 Value64 = static_cast(x) * static_cast(y); + msb = static_cast(Value64 >> static_cast(32)); + lsb = static_cast(Value64); + } + + template + GLM_FUNC_QUALIFIER void umulExtended(vec const& x, vec const& y, vec& msb, vec& lsb) + { + vec Value64(vec(x) * vec(y)); + msb = vec(Value64 >> static_cast(32)); + lsb = vec(Value64); + } + + // imulExtended + GLM_FUNC_QUALIFIER void imulExtended(int x, int y, int& msb, int& lsb) + { + detail::int64 Value64 = static_cast(x) * static_cast(y); + msb = static_cast(Value64 >> static_cast(32)); + lsb = static_cast(Value64); + } + + template + GLM_FUNC_QUALIFIER void imulExtended(vec const& x, vec const& y, vec& msb, vec& lsb) + { + vec Value64(vec(x) * vec(y)); + lsb = vec(Value64 & static_cast(0xFFFFFFFF)); + msb = vec((Value64 >> static_cast(32)) & static_cast(0xFFFFFFFF)); + } + + // bitfieldExtract + template + GLM_FUNC_QUALIFIER genIUType bitfieldExtract(genIUType Value, int Offset, int Bits) + { + return bitfieldExtract(vec<1, genIUType>(Value), Offset, Bits).x; + } + + template + GLM_FUNC_QUALIFIER vec bitfieldExtract(vec const& Value, int Offset, int Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldExtract' only accept integer inputs"); + + return (Value >> static_cast(Offset)) & static_cast(detail::mask(Bits)); + } + + // bitfieldInsert + template + GLM_FUNC_QUALIFIER genIUType bitfieldInsert(genIUType const& Base, genIUType const& Insert, int Offset, int Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldInsert' only accept integer values"); + + return bitfieldInsert(vec<1, genIUType>(Base), vec<1, genIUType>(Insert), Offset, Bits).x; + } + + template + GLM_FUNC_QUALIFIER vec bitfieldInsert(vec const& Base, vec const& Insert, int Offset, int Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldInsert' only accept integer values"); + + T const Mask = detail::mask(static_cast(Bits)) << Offset; + return (Base & ~Mask) | ((Insert << static_cast(Offset)) & Mask); + } + +#if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable : 4309) +#endif + + // bitfieldReverse + template + GLM_FUNC_QUALIFIER genIUType bitfieldReverse(genIUType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldReverse' only accept integer values"); + + return bitfieldReverse(glm::vec<1, genIUType, glm::defaultp>(x)).x; + } + + template + GLM_FUNC_QUALIFIER vec bitfieldReverse(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldReverse' only accept integer values"); + + vec x(v); + x = detail::compute_bitfieldReverseStep::value, sizeof(T) * 8>= 2>::call(x, static_cast(0x5555555555555555ull), static_cast( 1)); + x = detail::compute_bitfieldReverseStep::value, sizeof(T) * 8>= 4>::call(x, static_cast(0x3333333333333333ull), static_cast( 2)); + x = detail::compute_bitfieldReverseStep::value, sizeof(T) * 8>= 8>::call(x, static_cast(0x0F0F0F0F0F0F0F0Full), static_cast( 4)); + x = detail::compute_bitfieldReverseStep::value, sizeof(T) * 8>= 16>::call(x, static_cast(0x00FF00FF00FF00FFull), static_cast( 8)); + x = detail::compute_bitfieldReverseStep::value, sizeof(T) * 8>= 32>::call(x, static_cast(0x0000FFFF0000FFFFull), static_cast(16)); + x = detail::compute_bitfieldReverseStep::value, sizeof(T) * 8>= 64>::call(x, static_cast(0x00000000FFFFFFFFull), static_cast(32)); + return x; + } + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif + + // bitCount + template + GLM_FUNC_QUALIFIER int bitCount(genIUType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitCount' only accept integer values"); + + return bitCount(glm::vec<1, genIUType, glm::defaultp>(x)).x; + } + + template + GLM_FUNC_QUALIFIER vec bitCount(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitCount' only accept integer values"); + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable : 4310) //cast truncates constant value +# endif + + vec::type, Q> x(v); + x = detail::compute_bitfieldBitCountStep::type, Q, detail::is_aligned::value, sizeof(T) * 8>= 2>::call(x, typename detail::make_unsigned::type(0x5555555555555555ull), typename detail::make_unsigned::type( 1)); + x = detail::compute_bitfieldBitCountStep::type, Q, detail::is_aligned::value, sizeof(T) * 8>= 4>::call(x, typename detail::make_unsigned::type(0x3333333333333333ull), typename detail::make_unsigned::type( 2)); + x = detail::compute_bitfieldBitCountStep::type, Q, detail::is_aligned::value, sizeof(T) * 8>= 8>::call(x, typename detail::make_unsigned::type(0x0F0F0F0F0F0F0F0Full), typename detail::make_unsigned::type( 4)); + x = detail::compute_bitfieldBitCountStep::type, Q, detail::is_aligned::value, sizeof(T) * 8>= 16>::call(x, typename detail::make_unsigned::type(0x00FF00FF00FF00FFull), typename detail::make_unsigned::type( 8)); + x = detail::compute_bitfieldBitCountStep::type, Q, detail::is_aligned::value, sizeof(T) * 8>= 32>::call(x, typename detail::make_unsigned::type(0x0000FFFF0000FFFFull), typename detail::make_unsigned::type(16)); + x = detail::compute_bitfieldBitCountStep::type, Q, detail::is_aligned::value, sizeof(T) * 8>= 64>::call(x, typename detail::make_unsigned::type(0x00000000FFFFFFFFull), typename detail::make_unsigned::type(32)); + return vec(x); + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif + } + + // findLSB + template + GLM_FUNC_QUALIFIER int findLSB(genIUType Value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findLSB' only accept integer values"); + + return detail::compute_findLSB::call(Value); + } + + template + GLM_FUNC_QUALIFIER vec findLSB(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findLSB' only accept integer values"); + + return detail::functor1::call(findLSB, x); + } + + // findMSB + template + GLM_FUNC_QUALIFIER int findMSB(genIUType v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); + + return findMSB(vec<1, genIUType>(v)).x; + } + + template + GLM_FUNC_QUALIFIER vec findMSB(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); + + return detail::compute_findMSB_vec(sizeof(T) * 8)>::call(v); + } +}//namespace glm + +#if !GLM_HAS_EXTENDED_INTEGER_TYPE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic pop +# endif +# if (GLM_COMPILER & GLM_COMPILER_CLANG) +# pragma clang diagnostic pop +# endif +#endif + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_integer_simd.inl" +#endif + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_integer_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_integer_simd.inl new file mode 100644 index 0000000..5600c84 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_integer_simd.inl @@ -0,0 +1,65 @@ +#include "../simd/integer.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ + template + struct compute_bitfieldReverseStep<4, uint, Q, true, true> + { + GLM_FUNC_QUALIFIER static vec<4, uint, Q> call(vec<4, uint, Q> const& v, uint Mask, uint Shift) + { + __m128i const set0 = v.data; + + __m128i const set1 = _mm_set1_epi32(static_cast(Mask)); + __m128i const and1 = _mm_and_si128(set0, set1); + __m128i const sft1 = _mm_slli_epi32(and1, static_cast(Shift)); + + __m128i const set2 = _mm_andnot_si128(set0, _mm_set1_epi32(-1)); + __m128i const and2 = _mm_and_si128(set0, set2); + __m128i const sft2 = _mm_srai_epi32(and2, static_cast(Shift)); + + __m128i const or0 = _mm_or_si128(sft1, sft2); + + return or0; + } + }; + + template + struct compute_bitfieldBitCountStep<4, uint, Q, true, true> + { + GLM_FUNC_QUALIFIER static vec<4, uint, Q> call(vec<4, uint, Q> const& v, uint Mask, uint Shift) + { + __m128i const set0 = v.data; + + __m128i const set1 = _mm_set1_epi32(static_cast(Mask)); + __m128i const and0 = _mm_and_si128(set0, set1); + __m128i const sft0 = _mm_slli_epi32(set0, static_cast(Shift)); + __m128i const and1 = _mm_and_si128(sft0, set1); + __m128i const add0 = _mm_add_epi32(and0, and1); + + return add0; + } + }; +}//namespace detail + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template<> + GLM_FUNC_QUALIFIER int bitCount(uint x) + { + return _mm_popcnt_u32(x); + } + +# if(GLM_MODEL == GLM_MODEL_64) + template<> + GLM_FUNC_QUALIFIER int bitCount(detail::uint64 x) + { + return static_cast(_mm_popcnt_u64(x)); + } +# endif//GLM_MODEL +# endif//GLM_ARCH + +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_matrix.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_matrix.inl new file mode 100644 index 0000000..081761f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_matrix.inl @@ -0,0 +1,443 @@ +#include "../geometric.hpp" +#include + +namespace glm{ +namespace detail +{ + template + struct compute_matrixCompMult + { + GLM_FUNC_QUALIFIER static mat call(mat const& x, mat const& y) + { + mat Result(1); + for(length_t i = 0; i < Result.length(); ++i) + Result[i] = x[i] * y[i]; + return Result; + } + }; + + template + struct compute_matrixCompMult_type { + GLM_FUNC_QUALIFIER static mat call(mat const& x, mat const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, + "'matrixCompMult' only accept floating-point inputs, include to discard this restriction."); + return detail::compute_matrixCompMult::value>::call(x, y); + } + }; + + template + struct compute_outerProduct { + GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait::type call(vec const& c, vec const& r) + { + typename detail::outerProduct_trait::type m(0); + for(length_t i = 0; i < m.length(); ++i) + m[i] = c * r[i]; + return m; + } + }; + + template + struct compute_outerProduct_type { + GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait::type call(vec const& c, vec const& r) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, + "'outerProduct' only accept floating-point inputs, include to discard this restriction."); + + return detail::compute_outerProduct::call(c, r); + } + }; + + template + struct compute_transpose{}; + + template + struct compute_transpose<2, 2, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<2, 2, T, Q> call(mat<2, 2, T, Q> const& m) + { + mat<2, 2, T, Q> Result(1); + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + return Result; + } + }; + + template + struct compute_transpose<2, 3, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<3, 2, T, Q> call(mat<2, 3, T, Q> const& m) + { + mat<3,2, T, Q> Result(1); + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + return Result; + } + }; + + template + struct compute_transpose<2, 4, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<4, 2, T, Q> call(mat<2, 4, T, Q> const& m) + { + mat<4, 2, T, Q> Result(1); + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[3][0] = m[0][3]; + Result[3][1] = m[1][3]; + return Result; + } + }; + + template + struct compute_transpose<3, 2, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<2, 3, T, Q> call(mat<3, 2, T, Q> const& m) + { + mat<2, 3, T, Q> Result(1); + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + return Result; + } + }; + + template + struct compute_transpose<3, 3, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<3, 3, T, Q> call(mat<3, 3, T, Q> const& m) + { + mat<3, 3, T, Q> Result(1); + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + return Result; + } + }; + + template + struct compute_transpose<3, 4, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<4, 3, T, Q> call(mat<3, 4, T, Q> const& m) + { + mat<4, 3, T, Q> Result(1); + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + Result[3][0] = m[0][3]; + Result[3][1] = m[1][3]; + Result[3][2] = m[2][3]; + return Result; + } + }; + + template + struct compute_transpose<4, 2, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<2, 4, T, Q> call(mat<4, 2, T, Q> const& m) + { + mat<2, 4, T, Q> Result(1); + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[0][3] = m[3][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[1][3] = m[3][1]; + return Result; + } + }; + + template + struct compute_transpose<4, 3, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<3, 4, T, Q> call(mat<4, 3, T, Q> const& m) + { + mat<3, 4, T, Q> Result(1); + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[0][3] = m[3][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[1][3] = m[3][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + Result[2][3] = m[3][2]; + return Result; + } + }; + + template + struct compute_transpose<4, 4, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<4, 4, T, Q> call(mat<4, 4, T, Q> const& m) + { + mat<4, 4, T, Q> Result(1); + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[0][3] = m[3][0]; + + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[1][3] = m[3][1]; + + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + Result[2][3] = m[3][2]; + + Result[3][0] = m[0][3]; + Result[3][1] = m[1][3]; + Result[3][2] = m[2][3]; + Result[3][3] = m[3][3]; + return Result; + } + }; + + template + struct compute_transpose_type { + GLM_FUNC_QUALIFIER static mat call(mat const& m) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, + "'transpose' only accept floating-point inputs, include to discard this restriction."); + return detail::compute_transpose::value>::call(m); + } + }; + + template + struct compute_determinant{}; + + template + struct compute_determinant<2, 2, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static T call(mat<2, 2, T, Q> const& m) + { + return m[0][0] * m[1][1] - m[1][0] * m[0][1]; + } + }; + + template + struct compute_determinant<3, 3, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static T call(mat<3, 3, T, Q> const& m) + { + return + + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); + } + }; + + template + struct compute_determinant<4, 4, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static T call(mat<4, 4, T, Q> const& m) + { + T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + + vec<4, T, Q> DetCof( + + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), + - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), + + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), + - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05)); + + return + m[0][0] * DetCof[0] + m[0][1] * DetCof[1] + + m[0][2] * DetCof[2] + m[0][3] * DetCof[3]; + } + }; + + template + struct compute_determinant_type{ + + GLM_FUNC_QUALIFIER static T call(mat const& m) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, + "'determinant' only accept floating-point inputs, include to discard this restriction."); + return detail::compute_determinant::value>::call(m); + } + }; + + template + struct compute_inverse{}; + + template + struct compute_inverse<2, 2, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<2, 2, T, Q> call(mat<2, 2, T, Q> const& m) + { + T OneOverDeterminant = static_cast(1) / ( + + m[0][0] * m[1][1] + - m[1][0] * m[0][1]); + + mat<2, 2, T, Q> Inverse( + + m[1][1] * OneOverDeterminant, + - m[0][1] * OneOverDeterminant, + - m[1][0] * OneOverDeterminant, + + m[0][0] * OneOverDeterminant); + + return Inverse; + } + }; + + template + struct compute_inverse<3, 3, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<3, 3, T, Q> call(mat<3, 3, T, Q> const& m) + { + T OneOverDeterminant = static_cast(1) / ( + + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2])); + + mat<3, 3, T, Q> Inverse; + Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDeterminant; + Inverse[1][0] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDeterminant; + Inverse[2][0] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDeterminant; + Inverse[0][1] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDeterminant; + Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDeterminant; + Inverse[2][1] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDeterminant; + Inverse[0][2] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDeterminant; + Inverse[1][2] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDeterminant; + Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDeterminant; + + return Inverse; + } + }; + + template + struct compute_inverse<4, 4, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<4, 4, T, Q> call(mat<4, 4, T, Q> const& m) + { + T Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + T Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + T Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + T Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + T Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + T Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + T Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + T Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + T Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + T Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + T Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + T Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + T Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + T Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + T Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + T Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + T Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + T Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + vec<4, T, Q> Fac0(Coef00, Coef00, Coef02, Coef03); + vec<4, T, Q> Fac1(Coef04, Coef04, Coef06, Coef07); + vec<4, T, Q> Fac2(Coef08, Coef08, Coef10, Coef11); + vec<4, T, Q> Fac3(Coef12, Coef12, Coef14, Coef15); + vec<4, T, Q> Fac4(Coef16, Coef16, Coef18, Coef19); + vec<4, T, Q> Fac5(Coef20, Coef20, Coef22, Coef23); + + vec<4, T, Q> Vec0(m[1][0], m[0][0], m[0][0], m[0][0]); + vec<4, T, Q> Vec1(m[1][1], m[0][1], m[0][1], m[0][1]); + vec<4, T, Q> Vec2(m[1][2], m[0][2], m[0][2], m[0][2]); + vec<4, T, Q> Vec3(m[1][3], m[0][3], m[0][3], m[0][3]); + + vec<4, T, Q> Inv0(Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2); + vec<4, T, Q> Inv1(Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4); + vec<4, T, Q> Inv2(Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5); + vec<4, T, Q> Inv3(Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5); + + vec<4, T, Q> SignA(+1, -1, +1, -1); + vec<4, T, Q> SignB(-1, +1, -1, +1); + mat<4, 4, T, Q> Inverse(Inv0 * SignA, Inv1 * SignB, Inv2 * SignA, Inv3 * SignB); + + vec<4, T, Q> Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]); + + vec<4, T, Q> Dot0(m[0] * Row0); + T Dot1 = (Dot0.x + Dot0.y) + (Dot0.z + Dot0.w); + + T OneOverDeterminant = static_cast(1) / Dot1; + + return Inverse * OneOverDeterminant; + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER mat matrixCompMult(mat const& x, mat const& y) + { + return detail::compute_matrixCompMult_type::is_iec559, detail::is_aligned::value>::call(x, y); + } + + template + GLM_FUNC_QUALIFIER typename detail::outerProduct_trait::type outerProduct(vec const& c, vec const& r) + { + return detail::compute_outerProduct_type::is_iec559>::call(c, r); + } + + template + GLM_FUNC_QUALIFIER typename mat::transpose_type transpose(mat const& m) + { + return detail::compute_transpose_type::is_iec559, detail::is_aligned::value>::call(m); + } + + template + GLM_FUNC_QUALIFIER T determinant(mat const& m) + { + return detail::compute_determinant_type::is_iec559, detail::is_aligned::value>::call(m); + } + + template + GLM_FUNC_QUALIFIER mat inverse(mat const& m) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'inverse' only accept floating-point inputs"); + return detail::compute_inverse::value>::call(m); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_matrix_simd.inl" +#endif + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_matrix_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_matrix_simd.inl new file mode 100644 index 0000000..b9bb461 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_matrix_simd.inl @@ -0,0 +1,252 @@ +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +#include "type_mat4x4.hpp" +#include "../geometric.hpp" +#include "../simd/matrix.h" +#include + +namespace glm{ +namespace detail +{ +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + template + struct compute_matrixCompMult<4, 4, float, Q, true> + { + GLM_STATIC_ASSERT(detail::is_aligned::value, "Specialization requires aligned"); + + GLM_FUNC_QUALIFIER static mat<4, 4, float, Q> call(mat<4, 4, float, Q> const& x, mat<4, 4, float, Q> const& y) + { + mat<4, 4, float, Q> Result; + glm_mat4_matrixCompMult( + &x[0].data, + &y[0].data, + &Result[0].data); + return Result; + } + }; +# endif + + template + struct compute_transpose<4, 4, float, Q, true> + { + GLM_FUNC_QUALIFIER static mat<4, 4, float, Q> call(mat<4, 4, float, Q> const& m) + { + mat<4, 4, float, Q> Result; + glm_mat4_transpose(&m[0].data, &Result[0].data); + return Result; + } + }; + + template + struct compute_determinant<4, 4, float, Q, true> + { + GLM_FUNC_QUALIFIER static float call(mat<4, 4, float, Q> const& m) + { + return _mm_cvtss_f32(glm_mat4_determinant(&m[0].data)); + } + }; + + template + struct compute_inverse<4, 4, float, Q, true> + { + GLM_FUNC_QUALIFIER static mat<4, 4, float, Q> call(mat<4, 4, float, Q> const& m) + { + mat<4, 4, float, Q> Result; + glm_mat4_inverse(&m[0].data, &Result[0].data); + return Result; + } + }; +}//namespace detail + +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + template<> + GLM_FUNC_QUALIFIER mat<4, 4, float, aligned_lowp> outerProduct<4, 4, float, aligned_lowp>(vec<4, float, aligned_lowp> const& c, vec<4, float, aligned_lowp> const& r) + { + __m128 NativeResult[4]; + glm_mat4_outerProduct(c.data, r.data, NativeResult); + mat<4, 4, float, aligned_lowp> Result; + std::memcpy(&Result[0], &NativeResult[0], sizeof(Result)); + return Result; + } + + template<> + GLM_FUNC_QUALIFIER mat<4, 4, float, aligned_mediump> outerProduct<4, 4, float, aligned_mediump>(vec<4, float, aligned_mediump> const& c, vec<4, float, aligned_mediump> const& r) + { + __m128 NativeResult[4]; + glm_mat4_outerProduct(c.data, r.data, NativeResult); + mat<4, 4, float, aligned_mediump> Result; + std::memcpy(&Result[0], &NativeResult[0], sizeof(Result)); + return Result; + } + + template<> + GLM_FUNC_QUALIFIER mat<4, 4, float, aligned_highp> outerProduct<4, 4, float, aligned_highp>(vec<4, float, aligned_highp> const& c, vec<4, float, aligned_highp> const& r) + { + __m128 NativeResult[4]; + glm_mat4_outerProduct(c.data, r.data, NativeResult); + mat<4, 4, float, aligned_highp> Result; + std::memcpy(&Result[0], &NativeResult[0], sizeof(Result)); + return Result; + } +# endif +}//namespace glm + +#elif GLM_ARCH & GLM_ARCH_NEON_BIT + +namespace glm { +#if GLM_LANG & GLM_LANG_CXX11_FLAG + template + GLM_FUNC_QUALIFIER + typename std::enable_if::value, mat<4, 4, float, Q>>::type + operator*(mat<4, 4, float, Q> const & m1, mat<4, 4, float, Q> const & m2) + { + auto MulRow = [&](int l) { + float32x4_t const SrcA = m2[l].data; + + float32x4_t r = neon::mul_lane(m1[0].data, SrcA, 0); + r = neon::madd_lane(r, m1[1].data, SrcA, 1); + r = neon::madd_lane(r, m1[2].data, SrcA, 2); + r = neon::madd_lane(r, m1[3].data, SrcA, 3); + + return r; + }; + + mat<4, 4, float, aligned_highp> Result; + Result[0].data = MulRow(0); + Result[1].data = MulRow(1); + Result[2].data = MulRow(2); + Result[3].data = MulRow(3); + + return Result; + } +#endif // CXX11 + +namespace detail +{ + template + struct compute_inverse<4, 4, float, Q, true> + { + GLM_FUNC_QUALIFIER static mat<4, 4, float, Q> call(mat<4, 4, float, Q> const& m) + { + float32x4_t const& m0 = m[0].data; + float32x4_t const& m1 = m[1].data; + float32x4_t const& m2 = m[2].data; + float32x4_t const& m3 = m[3].data; + + // m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // m[1][2] * m[3][3] - m[3][2] * m[1][3]; + // m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + float32x4_t Fac0; + { + float32x4_t w0 = vcombine_f32(neon::dup_lane(m2, 2), neon::dup_lane(m1, 2)); + float32x4_t w1 = neon::copy_lane(neon::dupq_lane(m3, 3), 3, m2, 3); + float32x4_t w2 = neon::copy_lane(neon::dupq_lane(m3, 2), 3, m2, 2); + float32x4_t w3 = vcombine_f32(neon::dup_lane(m2, 3), neon::dup_lane(m1, 3)); + Fac0 = w0 * w1 - w2 * w3; + } + + // m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // m[1][1] * m[3][3] - m[3][1] * m[1][3]; + // m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + float32x4_t Fac1; + { + float32x4_t w0 = vcombine_f32(neon::dup_lane(m2, 1), neon::dup_lane(m1, 1)); + float32x4_t w1 = neon::copy_lane(neon::dupq_lane(m3, 3), 3, m2, 3); + float32x4_t w2 = neon::copy_lane(neon::dupq_lane(m3, 1), 3, m2, 1); + float32x4_t w3 = vcombine_f32(neon::dup_lane(m2, 3), neon::dup_lane(m1, 3)); + Fac1 = w0 * w1 - w2 * w3; + } + + // m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // m[1][1] * m[3][2] - m[3][1] * m[1][2]; + // m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + float32x4_t Fac2; + { + float32x4_t w0 = vcombine_f32(neon::dup_lane(m2, 1), neon::dup_lane(m1, 1)); + float32x4_t w1 = neon::copy_lane(neon::dupq_lane(m3, 2), 3, m2, 2); + float32x4_t w2 = neon::copy_lane(neon::dupq_lane(m3, 1), 3, m2, 1); + float32x4_t w3 = vcombine_f32(neon::dup_lane(m2, 2), neon::dup_lane(m1, 2)); + Fac2 = w0 * w1 - w2 * w3; + } + + // m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // m[1][0] * m[3][3] - m[3][0] * m[1][3]; + // m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + float32x4_t Fac3; + { + float32x4_t w0 = vcombine_f32(neon::dup_lane(m2, 0), neon::dup_lane(m1, 0)); + float32x4_t w1 = neon::copy_lane(neon::dupq_lane(m3, 3), 3, m2, 3); + float32x4_t w2 = neon::copy_lane(neon::dupq_lane(m3, 0), 3, m2, 0); + float32x4_t w3 = vcombine_f32(neon::dup_lane(m2, 3), neon::dup_lane(m1, 3)); + Fac3 = w0 * w1 - w2 * w3; + } + + // m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // m[1][0] * m[3][2] - m[3][0] * m[1][2]; + // m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + float32x4_t Fac4; + { + float32x4_t w0 = vcombine_f32(neon::dup_lane(m2, 0), neon::dup_lane(m1, 0)); + float32x4_t w1 = neon::copy_lane(neon::dupq_lane(m3, 2), 3, m2, 2); + float32x4_t w2 = neon::copy_lane(neon::dupq_lane(m3, 0), 3, m2, 0); + float32x4_t w3 = vcombine_f32(neon::dup_lane(m2, 2), neon::dup_lane(m1, 2)); + Fac4 = w0 * w1 - w2 * w3; + } + + // m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // m[1][0] * m[3][1] - m[3][0] * m[1][1]; + // m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + float32x4_t Fac5; + { + float32x4_t w0 = vcombine_f32(neon::dup_lane(m2, 0), neon::dup_lane(m1, 0)); + float32x4_t w1 = neon::copy_lane(neon::dupq_lane(m3, 1), 3, m2, 1); + float32x4_t w2 = neon::copy_lane(neon::dupq_lane(m3, 0), 3, m2, 0); + float32x4_t w3 = vcombine_f32(neon::dup_lane(m2, 1), neon::dup_lane(m1, 1)); + Fac5 = w0 * w1 - w2 * w3; + } + + float32x4_t Vec0 = neon::copy_lane(neon::dupq_lane(m0, 0), 0, m1, 0); // (m[1][0], m[0][0], m[0][0], m[0][0]); + float32x4_t Vec1 = neon::copy_lane(neon::dupq_lane(m0, 1), 0, m1, 1); // (m[1][1], m[0][1], m[0][1], m[0][1]); + float32x4_t Vec2 = neon::copy_lane(neon::dupq_lane(m0, 2), 0, m1, 2); // (m[1][2], m[0][2], m[0][2], m[0][2]); + float32x4_t Vec3 = neon::copy_lane(neon::dupq_lane(m0, 3), 0, m1, 3); // (m[1][3], m[0][3], m[0][3], m[0][3]); + + float32x4_t Inv0 = Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2; + float32x4_t Inv1 = Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4; + float32x4_t Inv2 = Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5; + float32x4_t Inv3 = Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5; + + float32x4_t r0 = float32x4_t{-1, +1, -1, +1} * Inv0; + float32x4_t r1 = float32x4_t{+1, -1, +1, -1} * Inv1; + float32x4_t r2 = float32x4_t{-1, +1, -1, +1} * Inv2; + float32x4_t r3 = float32x4_t{+1, -1, +1, -1} * Inv3; + + float32x4_t det = neon::mul_lane(r0, m0, 0); + det = neon::madd_lane(det, r1, m0, 1); + det = neon::madd_lane(det, r2, m0, 2); + det = neon::madd_lane(det, r3, m0, 3); + + float32x4_t rdet = vdupq_n_f32(1 / vgetq_lane_f32(det, 0)); + + mat<4, 4, float, Q> r; + r[0].data = vmulq_f32(r0, rdet); + r[1].data = vmulq_f32(r1, rdet); + r[2].data = vmulq_f32(r2, rdet); + r[3].data = vmulq_f32(r3, rdet); + return r; + } + }; +}//namespace detail +}//namespace glm +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_packing.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_packing.inl new file mode 100644 index 0000000..234b093 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_packing.inl @@ -0,0 +1,189 @@ +/// @ref core +/// @file glm/detail/func_packing.inl + +#include "../common.hpp" +#include "type_half.hpp" + +namespace glm +{ + GLM_FUNC_QUALIFIER uint packUnorm2x16(vec2 const& v) + { + union + { + unsigned short in[2]; + uint out; + } u; + + vec<2, unsigned short, defaultp> result(round(clamp(v, 0.0f, 1.0f) * 65535.0f)); + + u.in[0] = result[0]; + u.in[1] = result[1]; + + return u.out; + } + + GLM_FUNC_QUALIFIER vec2 unpackUnorm2x16(uint p) + { + union + { + uint in; + unsigned short out[2]; + } u; + + u.in = p; + + return vec2(u.out[0], u.out[1]) * 1.5259021896696421759365224689097e-5f; + } + + GLM_FUNC_QUALIFIER uint packSnorm2x16(vec2 const& v) + { + union + { + signed short in[2]; + uint out; + } u; + + vec<2, short, defaultp> result(round(clamp(v, -1.0f, 1.0f) * 32767.0f)); + + u.in[0] = result[0]; + u.in[1] = result[1]; + + return u.out; + } + + GLM_FUNC_QUALIFIER vec2 unpackSnorm2x16(uint p) + { + union + { + uint in; + signed short out[2]; + } u; + + u.in = p; + + return clamp(vec2(u.out[0], u.out[1]) * 3.0518509475997192297128208258309e-5f, -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint packUnorm4x8(vec4 const& v) + { + union + { + unsigned char in[4]; + uint out; + } u; + + vec<4, unsigned char, defaultp> result(round(clamp(v, 0.0f, 1.0f) * 255.0f)); + + u.in[0] = result[0]; + u.in[1] = result[1]; + u.in[2] = result[2]; + u.in[3] = result[3]; + + return u.out; + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm4x8(uint p) + { + union + { + uint in; + unsigned char out[4]; + } u; + + u.in = p; + + return vec4(u.out[0], u.out[1], u.out[2], u.out[3]) * 0.0039215686274509803921568627451f; + } + + GLM_FUNC_QUALIFIER uint packSnorm4x8(vec4 const& v) + { + union + { + signed char in[4]; + uint out; + } u; + + vec<4, signed char, defaultp> result(round(clamp(v, -1.0f, 1.0f) * 127.0f)); + + u.in[0] = result[0]; + u.in[1] = result[1]; + u.in[2] = result[2]; + u.in[3] = result[3]; + + return u.out; + } + + GLM_FUNC_QUALIFIER glm::vec4 unpackSnorm4x8(uint p) + { + union + { + uint in; + signed char out[4]; + } u; + + u.in = p; + + return clamp(vec4(u.out[0], u.out[1], u.out[2], u.out[3]) * 0.0078740157480315f, -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER double packDouble2x32(uvec2 const& v) + { + union + { + uint in[2]; + double out; + } u; + + u.in[0] = v[0]; + u.in[1] = v[1]; + + return u.out; + } + + GLM_FUNC_QUALIFIER uvec2 unpackDouble2x32(double v) + { + union + { + double in; + uint out[2]; + } u; + + u.in = v; + + return uvec2(u.out[0], u.out[1]); + } + + GLM_FUNC_QUALIFIER uint packHalf2x16(vec2 const& v) + { + union + { + signed short in[2]; + uint out; + } u; + + u.in[0] = detail::toFloat16(v.x); + u.in[1] = detail::toFloat16(v.y); + + return u.out; + } + + GLM_FUNC_QUALIFIER vec2 unpackHalf2x16(uint v) + { + union + { + uint in; + signed short out[2]; + } u; + + u.in = v; + + return vec2( + detail::toFloat32(u.out[0]), + detail::toFloat32(u.out[1])); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_packing_simd.inl" +#endif + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_packing_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_packing_simd.inl new file mode 100644 index 0000000..fd0fe8b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_packing_simd.inl @@ -0,0 +1,6 @@ +namespace glm{ +namespace detail +{ + +}//namespace detail +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_trigonometric.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_trigonometric.inl new file mode 100644 index 0000000..9e6d9cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_trigonometric.inl @@ -0,0 +1,197 @@ +#include "_vectorize.hpp" +#include +#include + +namespace glm +{ + // radians + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType radians(genType degrees) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'radians' only accept floating-point input"); + + return degrees * static_cast(0.01745329251994329576923690768489); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec radians(vec const& v) + { + return detail::functor1::call(radians, v); + } + + // degrees + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType degrees(genType radians) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'degrees' only accept floating-point input"); + + return radians * static_cast(57.295779513082320876798154814105); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec degrees(vec const& v) + { + return detail::functor1::call(degrees, v); + } + + // sin + using ::std::sin; + + template + GLM_FUNC_QUALIFIER vec sin(vec const& v) + { + return detail::functor1::call(sin, v); + } + + // cos + using std::cos; + + template + GLM_FUNC_QUALIFIER vec cos(vec const& v) + { + return detail::functor1::call(cos, v); + } + + // tan + using std::tan; + + template + GLM_FUNC_QUALIFIER vec tan(vec const& v) + { + return detail::functor1::call(tan, v); + } + + // asin + using std::asin; + + template + GLM_FUNC_QUALIFIER vec asin(vec const& v) + { + return detail::functor1::call(asin, v); + } + + // acos + using std::acos; + + template + GLM_FUNC_QUALIFIER vec acos(vec const& v) + { + return detail::functor1::call(acos, v); + } + + // atan + template + GLM_FUNC_QUALIFIER genType atan(genType y, genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'atan' only accept floating-point input"); + + return ::std::atan2(y, x); + } + + template + GLM_FUNC_QUALIFIER vec atan(vec const& y, vec const& x) + { + return detail::functor2::call(::std::atan2, y, x); + } + + using std::atan; + + template + GLM_FUNC_QUALIFIER vec atan(vec const& v) + { + return detail::functor1::call(atan, v); + } + + // sinh + using std::sinh; + + template + GLM_FUNC_QUALIFIER vec sinh(vec const& v) + { + return detail::functor1::call(sinh, v); + } + + // cosh + using std::cosh; + + template + GLM_FUNC_QUALIFIER vec cosh(vec const& v) + { + return detail::functor1::call(cosh, v); + } + + // tanh + using std::tanh; + + template + GLM_FUNC_QUALIFIER vec tanh(vec const& v) + { + return detail::functor1::call(tanh, v); + } + + // asinh +# if GLM_HAS_CXX11_STL + using std::asinh; +# else + template + GLM_FUNC_QUALIFIER genType asinh(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'asinh' only accept floating-point input"); + + return (x < static_cast(0) ? static_cast(-1) : (x > static_cast(0) ? static_cast(1) : static_cast(0))) * log(std::abs(x) + sqrt(static_cast(1) + x * x)); + } +# endif + + template + GLM_FUNC_QUALIFIER vec asinh(vec const& v) + { + return detail::functor1::call(asinh, v); + } + + // acosh +# if GLM_HAS_CXX11_STL + using std::acosh; +# else + template + GLM_FUNC_QUALIFIER genType acosh(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acosh' only accept floating-point input"); + + if(x < static_cast(1)) + return static_cast(0); + return log(x + sqrt(x * x - static_cast(1))); + } +# endif + + template + GLM_FUNC_QUALIFIER vec acosh(vec const& v) + { + return detail::functor1::call(acosh, v); + } + + // atanh +# if GLM_HAS_CXX11_STL + using std::atanh; +# else + template + GLM_FUNC_QUALIFIER genType atanh(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'atanh' only accept floating-point input"); + + if(std::abs(x) >= static_cast(1)) + return 0; + return static_cast(0.5) * log((static_cast(1) + x) / (static_cast(1) - x)); + } +# endif + + template + GLM_FUNC_QUALIFIER vec atanh(vec const& v) + { + return detail::functor1::call(atanh, v); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_trigonometric_simd.inl" +#endif + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_trigonometric_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_trigonometric_simd.inl new file mode 100644 index 0000000..e69de29 diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_vector_relational.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_vector_relational.inl new file mode 100644 index 0000000..80c9e87 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_vector_relational.inl @@ -0,0 +1,87 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec lessThan(vec const& x, vec const& y) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] < y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec lessThanEqual(vec const& x, vec const& y) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] <= y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec greaterThan(vec const& x, vec const& y) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] > y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec greaterThanEqual(vec const& x, vec const& y) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] >= y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(vec const& x, vec const& y) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] == y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] != y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool any(vec const& v) + { + bool Result = false; + for(length_t i = 0; i < L; ++i) + Result = Result || v[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool all(vec const& v) + { + bool Result = true; + for(length_t i = 0; i < L; ++i) + Result = Result && v[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec not_(vec const& v) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = !v[i]; + return Result; + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_vector_relational_simd.inl" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_vector_relational_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_vector_relational_simd.inl new file mode 100644 index 0000000..fd0fe8b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_vector_relational_simd.inl @@ -0,0 +1,6 @@ +namespace glm{ +namespace detail +{ + +}//namespace detail +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/glm.cpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/glm.cpp new file mode 100644 index 0000000..e0755bd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/glm.cpp @@ -0,0 +1,263 @@ +/// @ref core +/// @file glm/glm.cpp + +#ifndef GLM_ENABLE_EXPERIMENTAL +#define GLM_ENABLE_EXPERIMENTAL +#endif +#include +#include +#include +#include +#include +#include + +namespace glm +{ +// tvec1 type explicit instantiation +template struct vec<1, uint8, lowp>; +template struct vec<1, uint16, lowp>; +template struct vec<1, uint32, lowp>; +template struct vec<1, uint64, lowp>; +template struct vec<1, int8, lowp>; +template struct vec<1, int16, lowp>; +template struct vec<1, int32, lowp>; +template struct vec<1, int64, lowp>; +template struct vec<1, float32, lowp>; +template struct vec<1, float64, lowp>; + +template struct vec<1, uint8, mediump>; +template struct vec<1, uint16, mediump>; +template struct vec<1, uint32, mediump>; +template struct vec<1, uint64, mediump>; +template struct vec<1, int8, mediump>; +template struct vec<1, int16, mediump>; +template struct vec<1, int32, mediump>; +template struct vec<1, int64, mediump>; +template struct vec<1, float32, mediump>; +template struct vec<1, float64, mediump>; + +template struct vec<1, uint8, highp>; +template struct vec<1, uint16, highp>; +template struct vec<1, uint32, highp>; +template struct vec<1, uint64, highp>; +template struct vec<1, int8, highp>; +template struct vec<1, int16, highp>; +template struct vec<1, int32, highp>; +template struct vec<1, int64, highp>; +template struct vec<1, float32, highp>; +template struct vec<1, float64, highp>; + +// tvec2 type explicit instantiation +template struct vec<2, uint8, lowp>; +template struct vec<2, uint16, lowp>; +template struct vec<2, uint32, lowp>; +template struct vec<2, uint64, lowp>; +template struct vec<2, int8, lowp>; +template struct vec<2, int16, lowp>; +template struct vec<2, int32, lowp>; +template struct vec<2, int64, lowp>; +template struct vec<2, float32, lowp>; +template struct vec<2, float64, lowp>; + +template struct vec<2, uint8, mediump>; +template struct vec<2, uint16, mediump>; +template struct vec<2, uint32, mediump>; +template struct vec<2, uint64, mediump>; +template struct vec<2, int8, mediump>; +template struct vec<2, int16, mediump>; +template struct vec<2, int32, mediump>; +template struct vec<2, int64, mediump>; +template struct vec<2, float32, mediump>; +template struct vec<2, float64, mediump>; + +template struct vec<2, uint8, highp>; +template struct vec<2, uint16, highp>; +template struct vec<2, uint32, highp>; +template struct vec<2, uint64, highp>; +template struct vec<2, int8, highp>; +template struct vec<2, int16, highp>; +template struct vec<2, int32, highp>; +template struct vec<2, int64, highp>; +template struct vec<2, float32, highp>; +template struct vec<2, float64, highp>; + +// tvec3 type explicit instantiation +template struct vec<3, uint8, lowp>; +template struct vec<3, uint16, lowp>; +template struct vec<3, uint32, lowp>; +template struct vec<3, uint64, lowp>; +template struct vec<3, int8, lowp>; +template struct vec<3, int16, lowp>; +template struct vec<3, int32, lowp>; +template struct vec<3, int64, lowp>; +template struct vec<3, float32, lowp>; +template struct vec<3, float64, lowp>; + +template struct vec<3, uint8, mediump>; +template struct vec<3, uint16, mediump>; +template struct vec<3, uint32, mediump>; +template struct vec<3, uint64, mediump>; +template struct vec<3, int8, mediump>; +template struct vec<3, int16, mediump>; +template struct vec<3, int32, mediump>; +template struct vec<3, int64, mediump>; +template struct vec<3, float32, mediump>; +template struct vec<3, float64, mediump>; + +template struct vec<3, uint8, highp>; +template struct vec<3, uint16, highp>; +template struct vec<3, uint32, highp>; +template struct vec<3, uint64, highp>; +template struct vec<3, int8, highp>; +template struct vec<3, int16, highp>; +template struct vec<3, int32, highp>; +template struct vec<3, int64, highp>; +template struct vec<3, float32, highp>; +template struct vec<3, float64, highp>; + +// tvec4 type explicit instantiation +template struct vec<4, uint8, lowp>; +template struct vec<4, uint16, lowp>; +template struct vec<4, uint32, lowp>; +template struct vec<4, uint64, lowp>; +template struct vec<4, int8, lowp>; +template struct vec<4, int16, lowp>; +template struct vec<4, int32, lowp>; +template struct vec<4, int64, lowp>; +template struct vec<4, float32, lowp>; +template struct vec<4, float64, lowp>; + +template struct vec<4, uint8, mediump>; +template struct vec<4, uint16, mediump>; +template struct vec<4, uint32, mediump>; +template struct vec<4, uint64, mediump>; +template struct vec<4, int8, mediump>; +template struct vec<4, int16, mediump>; +template struct vec<4, int32, mediump>; +template struct vec<4, int64, mediump>; +template struct vec<4, float32, mediump>; +template struct vec<4, float64, mediump>; + +template struct vec<4, uint8, highp>; +template struct vec<4, uint16, highp>; +template struct vec<4, uint32, highp>; +template struct vec<4, uint64, highp>; +template struct vec<4, int8, highp>; +template struct vec<4, int16, highp>; +template struct vec<4, int32, highp>; +template struct vec<4, int64, highp>; +template struct vec<4, float32, highp>; +template struct vec<4, float64, highp>; + +// tmat2x2 type explicit instantiation +template struct mat<2, 2, float32, lowp>; +template struct mat<2, 2, float64, lowp>; + +template struct mat<2, 2, float32, mediump>; +template struct mat<2, 2, float64, mediump>; + +template struct mat<2, 2, float32, highp>; +template struct mat<2, 2, float64, highp>; + +// tmat2x3 type explicit instantiation +template struct mat<2, 3, float32, lowp>; +template struct mat<2, 3, float64, lowp>; + +template struct mat<2, 3, float32, mediump>; +template struct mat<2, 3, float64, mediump>; + +template struct mat<2, 3, float32, highp>; +template struct mat<2, 3, float64, highp>; + +// tmat2x4 type explicit instantiation +template struct mat<2, 4, float32, lowp>; +template struct mat<2, 4, float64, lowp>; + +template struct mat<2, 4, float32, mediump>; +template struct mat<2, 4, float64, mediump>; + +template struct mat<2, 4, float32, highp>; +template struct mat<2, 4, float64, highp>; + +// tmat3x2 type explicit instantiation +template struct mat<3, 2, float32, lowp>; +template struct mat<3, 2, float64, lowp>; + +template struct mat<3, 2, float32, mediump>; +template struct mat<3, 2, float64, mediump>; + +template struct mat<3, 2, float32, highp>; +template struct mat<3, 2, float64, highp>; + +// tmat3x3 type explicit instantiation +template struct mat<3, 3, float32, lowp>; +template struct mat<3, 3, float64, lowp>; + +template struct mat<3, 3, float32, mediump>; +template struct mat<3, 3, float64, mediump>; + +template struct mat<3, 3, float32, highp>; +template struct mat<3, 3, float64, highp>; + +// tmat3x4 type explicit instantiation +template struct mat<3, 4, float32, lowp>; +template struct mat<3, 4, float64, lowp>; + +template struct mat<3, 4, float32, mediump>; +template struct mat<3, 4, float64, mediump>; + +template struct mat<3, 4, float32, highp>; +template struct mat<3, 4, float64, highp>; + +// tmat4x2 type explicit instantiation +template struct mat<4, 2, float32, lowp>; +template struct mat<4, 2, float64, lowp>; + +template struct mat<4, 2, float32, mediump>; +template struct mat<4, 2, float64, mediump>; + +template struct mat<4, 2, float32, highp>; +template struct mat<4, 2, float64, highp>; + +// tmat4x3 type explicit instantiation +template struct mat<4, 3, float32, lowp>; +template struct mat<4, 3, float64, lowp>; + +template struct mat<4, 3, float32, mediump>; +template struct mat<4, 3, float64, mediump>; + +template struct mat<4, 3, float32, highp>; +template struct mat<4, 3, float64, highp>; + +// tmat4x4 type explicit instantiation +template struct mat<4, 4, float32, lowp>; +template struct mat<4, 4, float64, lowp>; + +template struct mat<4, 4, float32, mediump>; +template struct mat<4, 4, float64, mediump>; + +template struct mat<4, 4, float32, highp>; +template struct mat<4, 4, float64, highp>; + +// tquat type explicit instantiation +template struct qua; +template struct qua; + +template struct qua; +template struct qua; + +template struct qua; +template struct qua; + +//tdualquat type explicit instantiation +template struct tdualquat; +template struct tdualquat; + +template struct tdualquat; +template struct tdualquat; + +template struct tdualquat; +template struct tdualquat; + +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/qualifier.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/qualifier.hpp new file mode 100644 index 0000000..a6c96cc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/qualifier.hpp @@ -0,0 +1,229 @@ +#pragma once + +#include "setup.hpp" + +namespace glm +{ + /// Qualify GLM types in term of alignment (packed, aligned) and precision in term of ULPs (lowp, mediump, highp) + enum qualifier + { + packed_highp, ///< Typed data is tightly packed in memory and operations are executed with high precision in term of ULPs + packed_mediump, ///< Typed data is tightly packed in memory and operations are executed with medium precision in term of ULPs for higher performance + packed_lowp, ///< Typed data is tightly packed in memory and operations are executed with low precision in term of ULPs to maximize performance + +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + aligned_highp, ///< Typed data is aligned in memory allowing SIMD optimizations and operations are executed with high precision in term of ULPs + aligned_mediump, ///< Typed data is aligned in memory allowing SIMD optimizations and operations are executed with high precision in term of ULPs for higher performance + aligned_lowp, // ///< Typed data is aligned in memory allowing SIMD optimizations and operations are executed with high precision in term of ULPs to maximize performance + aligned = aligned_highp, ///< By default aligned qualifier is also high precision +# endif + + highp = packed_highp, ///< By default highp qualifier is also packed + mediump = packed_mediump, ///< By default mediump qualifier is also packed + lowp = packed_lowp, ///< By default lowp qualifier is also packed + packed = packed_highp, ///< By default packed qualifier is also high precision + +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE && defined(GLM_FORCE_DEFAULT_ALIGNED_GENTYPES) + defaultp = aligned_highp +# else + defaultp = highp +# endif + }; + + typedef qualifier precision; + + template struct vec; + template struct mat; + template struct qua; + +# if GLM_HAS_TEMPLATE_ALIASES + template using tvec1 = vec<1, T, Q>; + template using tvec2 = vec<2, T, Q>; + template using tvec3 = vec<3, T, Q>; + template using tvec4 = vec<4, T, Q>; + template using tmat2x2 = mat<2, 2, T, Q>; + template using tmat2x3 = mat<2, 3, T, Q>; + template using tmat2x4 = mat<2, 4, T, Q>; + template using tmat3x2 = mat<3, 2, T, Q>; + template using tmat3x3 = mat<3, 3, T, Q>; + template using tmat3x4 = mat<3, 4, T, Q>; + template using tmat4x2 = mat<4, 2, T, Q>; + template using tmat4x3 = mat<4, 3, T, Q>; + template using tmat4x4 = mat<4, 4, T, Q>; + template using tquat = qua; +# endif + +namespace detail +{ + template + struct is_aligned + { + static const bool value = false; + }; + +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + template<> + struct is_aligned + { + static const bool value = true; + }; + + template<> + struct is_aligned + { + static const bool value = true; + }; + + template<> + struct is_aligned + { + static const bool value = true; + }; +# endif + + template + struct storage + { + typedef struct type { + T data[L]; + } type; + }; + +# if GLM_HAS_ALIGNOF + template + struct storage + { + typedef struct alignas(L * sizeof(T)) type { + T data[L]; + } type; + }; + + template + struct storage<3, T, true> + { + typedef struct alignas(4 * sizeof(T)) type { + T data[4]; + } type; + }; +# endif + +# if GLM_ARCH & GLM_ARCH_SSE2_BIT + template<> + struct storage<4, float, true> + { + typedef glm_f32vec4 type; + }; + + template<> + struct storage<4, int, true> + { + typedef glm_i32vec4 type; + }; + + template<> + struct storage<4, unsigned int, true> + { + typedef glm_u32vec4 type; + }; + + template<> + struct storage<2, double, true> + { + typedef glm_f64vec2 type; + }; + + template<> + struct storage<2, detail::int64, true> + { + typedef glm_i64vec2 type; + }; + + template<> + struct storage<2, detail::uint64, true> + { + typedef glm_u64vec2 type; + }; +# endif +# if (GLM_ARCH & GLM_ARCH_AVX_BIT) + template<> + struct storage<4, double, true> + { + typedef glm_f64vec4 type; + }; +# endif + +# if (GLM_ARCH & GLM_ARCH_AVX2_BIT) + template<> + struct storage<4, detail::int64, true> + { + typedef glm_i64vec4 type; + }; + + template<> + struct storage<4, detail::uint64, true> + { + typedef glm_u64vec4 type; + }; +# endif + +# if GLM_ARCH & GLM_ARCH_NEON_BIT + template<> + struct storage<4, float, true> + { + typedef glm_f32vec4 type; + }; + + template<> + struct storage<4, int, true> + { + typedef glm_i32vec4 type; + }; + + template<> + struct storage<4, unsigned int, true> + { + typedef glm_u32vec4 type; + }; +# endif + + enum genTypeEnum + { + GENTYPE_VEC, + GENTYPE_MAT, + GENTYPE_QUAT + }; + + template + struct genTypeTrait + {}; + + template + struct genTypeTrait > + { + static const genTypeEnum GENTYPE = GENTYPE_MAT; + }; + + template + struct init_gentype + { + }; + + template + struct init_gentype + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static genType identity() + { + return genType(1, 0, 0, 0); + } + }; + + template + struct init_gentype + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static genType identity() + { + return genType(1); + } + }; +}//namespace detail +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/setup.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/setup.hpp new file mode 100644 index 0000000..21ccebf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/setup.hpp @@ -0,0 +1,1192 @@ +#ifndef GLM_SETUP_INCLUDED + +#include +#include + +#define GLM_VERSION_MAJOR 1 +#define GLM_VERSION_MINOR 0 +#define GLM_VERSION_PATCH 1 +#define GLM_VERSION_REVISION 0 // Deprecated +#define GLM_VERSION 1000 // Deprecated +#define GLM_VERSION_MESSAGE "GLM: version 1.0.1" + +#define GLM_MAKE_API_VERSION(variant, major, minor, patch) \ + ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) + +#define GLM_VERSION_COMPLETE GLM_MAKE_API_VERSION(0, GLM_VERSION_MAJOR, GLM_VERSION_MINOR, GLM_VERSION_PATCH) + +#define GLM_SETUP_INCLUDED GLM_VERSION + +#define GLM_GET_VERSION_VARIANT(version) ((uint32_t)(version) >> 29U) +#define GLM_GET_VERSION_MAJOR(version) (((uint32_t)(version) >> 22U) & 0x7FU) +#define GLM_GET_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU) +#define GLM_GET_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) + +/////////////////////////////////////////////////////////////////////////////////// +// Active states + +#define GLM_DISABLE 0 +#define GLM_ENABLE 1 + +/////////////////////////////////////////////////////////////////////////////////// +// Messages + +#if defined(GLM_FORCE_MESSAGES) +# define GLM_MESSAGES GLM_ENABLE +#else +# define GLM_MESSAGES GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Detect the platform + +#include "../simd/platform.h" + +/////////////////////////////////////////////////////////////////////////////////// +// Build model + +#if defined(_M_ARM64) || defined(__LP64__) || defined(_M_X64) || defined(__ppc64__) || defined(__x86_64__) +# define GLM_MODEL GLM_MODEL_64 +#elif defined(__i386__) || defined(__ppc__) || defined(__ILP32__) || defined(_M_ARM) +# define GLM_MODEL GLM_MODEL_32 +#else +# define GLM_MODEL GLM_MODEL_32 +#endif// + +#if !defined(GLM_MODEL) && GLM_COMPILER != 0 +# error "GLM_MODEL undefined, your compiler may not be supported by GLM. Add #define GLM_MODEL 0 to ignore this message." +#endif//GLM_MODEL + +/////////////////////////////////////////////////////////////////////////////////// +// C++ Version + +// User defines: GLM_FORCE_CXX98, GLM_FORCE_CXX03, GLM_FORCE_CXX11, GLM_FORCE_CXX14, GLM_FORCE_CXX17, GLM_FORCE_CXX2A + +#define GLM_LANG_CXX98_FLAG (1 << 1) +#define GLM_LANG_CXX03_FLAG (1 << 2) +#define GLM_LANG_CXX0X_FLAG (1 << 3) +#define GLM_LANG_CXX11_FLAG (1 << 4) +#define GLM_LANG_CXX14_FLAG (1 << 5) +#define GLM_LANG_CXX17_FLAG (1 << 6) +#define GLM_LANG_CXX20_FLAG (1 << 7) +#define GLM_LANG_CXXMS_FLAG (1 << 8) +#define GLM_LANG_CXXGNU_FLAG (1 << 9) + +#define GLM_LANG_CXX98 GLM_LANG_CXX98_FLAG +#define GLM_LANG_CXX03 (GLM_LANG_CXX98 | GLM_LANG_CXX03_FLAG) +#define GLM_LANG_CXX0X (GLM_LANG_CXX03 | GLM_LANG_CXX0X_FLAG) +#define GLM_LANG_CXX11 (GLM_LANG_CXX0X | GLM_LANG_CXX11_FLAG) +#define GLM_LANG_CXX14 (GLM_LANG_CXX11 | GLM_LANG_CXX14_FLAG) +#define GLM_LANG_CXX17 (GLM_LANG_CXX14 | GLM_LANG_CXX17_FLAG) +#define GLM_LANG_CXX20 (GLM_LANG_CXX17 | GLM_LANG_CXX20_FLAG) +#define GLM_LANG_CXXMS GLM_LANG_CXXMS_FLAG +#define GLM_LANG_CXXGNU GLM_LANG_CXXGNU_FLAG + +#if (defined(_MSC_EXTENSIONS)) +# define GLM_LANG_EXT GLM_LANG_CXXMS_FLAG +#elif ((GLM_COMPILER & (GLM_COMPILER_CLANG | GLM_COMPILER_GCC)) && (GLM_ARCH & GLM_ARCH_SIMD_BIT)) +# define GLM_LANG_EXT GLM_LANG_CXXMS_FLAG +#else +# define GLM_LANG_EXT 0 +#endif + +#if (defined(GLM_FORCE_CXX_UNKNOWN)) +# define GLM_LANG 0 +#elif defined(GLM_FORCE_CXX20) +# define GLM_LANG (GLM_LANG_CXX20 | GLM_LANG_EXT) +# define GLM_LANG_STL11_FORCED +#elif defined(GLM_FORCE_CXX17) +# define GLM_LANG (GLM_LANG_CXX17 | GLM_LANG_EXT) +# define GLM_LANG_STL11_FORCED +#elif defined(GLM_FORCE_CXX14) +# define GLM_LANG (GLM_LANG_CXX14 | GLM_LANG_EXT) +# define GLM_LANG_STL11_FORCED +#elif defined(GLM_FORCE_CXX11) +# define GLM_LANG (GLM_LANG_CXX11 | GLM_LANG_EXT) +# define GLM_LANG_STL11_FORCED +#elif defined(GLM_FORCE_CXX03) +# define GLM_LANG (GLM_LANG_CXX03 | GLM_LANG_EXT) +#elif defined(GLM_FORCE_CXX98) +# define GLM_LANG (GLM_LANG_CXX98 | GLM_LANG_EXT) +#else +# if GLM_COMPILER & GLM_COMPILER_VC && defined(_MSVC_LANG) +# if GLM_COMPILER >= GLM_COMPILER_VC15_7 +# define GLM_LANG_PLATFORM _MSVC_LANG +# elif GLM_COMPILER >= GLM_COMPILER_VC15 +# if _MSVC_LANG > 201402L +# define GLM_LANG_PLATFORM 201402L +# else +# define GLM_LANG_PLATFORM _MSVC_LANG +# endif +# else +# define GLM_LANG_PLATFORM 0 +# endif +# else +# define GLM_LANG_PLATFORM 0 +# endif + +# if __cplusplus > 201703L || GLM_LANG_PLATFORM > 201703L +# define GLM_LANG (GLM_LANG_CXX20 | GLM_LANG_EXT) +# elif __cplusplus == 201703L || GLM_LANG_PLATFORM == 201703L +# define GLM_LANG (GLM_LANG_CXX17 | GLM_LANG_EXT) +# elif __cplusplus == 201402L || __cplusplus == 201406L || __cplusplus == 201500L || GLM_LANG_PLATFORM == 201402L +# define GLM_LANG (GLM_LANG_CXX14 | GLM_LANG_EXT) +# elif __cplusplus == 201103L || GLM_LANG_PLATFORM == 201103L +# define GLM_LANG (GLM_LANG_CXX11 | GLM_LANG_EXT) +# elif defined(__INTEL_CXX11_MODE__) || defined(_MSC_VER) || defined(__GXX_EXPERIMENTAL_CXX0X__) +# define GLM_LANG (GLM_LANG_CXX0X | GLM_LANG_EXT) +# elif __cplusplus == 199711L +# define GLM_LANG (GLM_LANG_CXX98 | GLM_LANG_EXT) +# else +# define GLM_LANG (0 | GLM_LANG_EXT) +# endif +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Has of C++ features + +// http://clang.llvm.org/cxx_status.html +// http://gcc.gnu.org/projects/cxx0x.html +// http://msdn.microsoft.com/en-us/library/vstudio/hh567368(v=vs.120).aspx + +// Android has multiple STLs but C++11 STL detection doesn't always work #284 #564 +#if GLM_PLATFORM == GLM_PLATFORM_ANDROID && !defined(GLM_LANG_STL11_FORCED) +# define GLM_HAS_CXX11_STL 0 +#elif (GLM_COMPILER & GLM_COMPILER_CUDA_RTC) == GLM_COMPILER_CUDA_RTC +# define GLM_HAS_CXX11_STL 0 +#elif (GLM_COMPILER & GLM_COMPILER_HIP) +# define GLM_HAS_CXX11_STL 0 +#elif GLM_COMPILER & GLM_COMPILER_CLANG +# if (defined(_LIBCPP_VERSION) || (GLM_LANG & GLM_LANG_CXX11_FLAG) || defined(GLM_LANG_STL11_FORCED)) +# define GLM_HAS_CXX11_STL 1 +# else +# define GLM_HAS_CXX11_STL 0 +# endif +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_CXX11_STL 1 +#else +# define GLM_HAS_CXX11_STL ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC48)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC12)) || \ + ((GLM_PLATFORM != GLM_PLATFORM_WINDOWS) && (GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL15)))) +#endif + +// N1720 +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_STATIC_ASSERT __has_feature(cxx_static_assert) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_STATIC_ASSERT 1 +#else +# define GLM_HAS_STATIC_ASSERT ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#endif + +// N1988 +#if GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_EXTENDED_INTEGER_TYPE 1 +#else +# define GLM_HAS_EXTENDED_INTEGER_TYPE (\ + ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (GLM_COMPILER & GLM_COMPILER_VC)) || \ + ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (GLM_COMPILER & GLM_COMPILER_CLANG)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP))) +#endif + +// N2672 Initializer lists http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_INITIALIZER_LISTS __has_feature(cxx_generalized_initializers) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_INITIALIZER_LISTS 1 +#else +# define GLM_HAS_INITIALIZER_LISTS ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC15)) || \ + ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL14)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#endif + +// N2544 Unrestricted unions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_UNRESTRICTED_UNIONS __has_feature(cxx_unrestricted_unions) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_UNRESTRICTED_UNIONS 1 +#else +# define GLM_HAS_UNRESTRICTED_UNIONS (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + (GLM_COMPILER & GLM_COMPILER_VC) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP))) +#endif + +// N2346 +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_DEFAULTED_FUNCTIONS __has_feature(cxx_defaulted_functions) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_DEFAULTED_FUNCTIONS 1 +#else +# define GLM_HAS_DEFAULTED_FUNCTIONS ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC12)) || \ + ((GLM_COMPILER & GLM_COMPILER_INTEL)) || \ + (GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP))) +#endif + +// N2118 +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_RVALUE_REFERENCES __has_feature(cxx_rvalue_references) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_RVALUE_REFERENCES 1 +#else +# define GLM_HAS_RVALUE_REFERENCES ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_VC)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#endif + +// N2437 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_EXPLICIT_CONVERSION_OPERATORS __has_feature(cxx_explicit_conversions) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_EXPLICIT_CONVERSION_OPERATORS 1 +#else +# define GLM_HAS_EXPLICIT_CONVERSION_OPERATORS ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL14)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC12)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#endif + +// N2258 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_TEMPLATE_ALIASES __has_feature(cxx_alias_templates) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_TEMPLATE_ALIASES 1 +#else +# define GLM_HAS_TEMPLATE_ALIASES ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC12)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#endif + +// N2930 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2930.html +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_RANGE_FOR __has_feature(cxx_range_for) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_RANGE_FOR 1 +#else +# define GLM_HAS_RANGE_FOR ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#endif + +// N2341 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_ALIGNOF __has_feature(cxx_alignas) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_ALIGNOF 1 +#else +# define GLM_HAS_ALIGNOF ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL15)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC14)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#endif + +// N2235 Generalized Constant Expressions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf +// N3652 Extended Constant Expressions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3652.html +#if (GLM_ARCH & GLM_ARCH_SIMD_BIT) // Compiler SIMD intrinsics don't support constexpr... +# define GLM_HAS_CONSTEXPR 0 +#elif (GLM_COMPILER & GLM_COMPILER_CLANG) +# define GLM_HAS_CONSTEXPR __has_feature(cxx_relaxed_constexpr) +#elif (GLM_LANG & GLM_LANG_CXX14_FLAG) +# define GLM_HAS_CONSTEXPR 1 +#else +# define GLM_HAS_CONSTEXPR ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && GLM_HAS_INITIALIZER_LISTS && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL17)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC15)))) +#endif + +#if GLM_HAS_CONSTEXPR +# define GLM_CONSTEXPR constexpr +#else +# define GLM_CONSTEXPR +#endif + +// +#if GLM_HAS_CONSTEXPR +# if (GLM_COMPILER & GLM_COMPILER_CLANG) +# if __has_feature(cxx_if_constexpr) +# define GLM_HAS_IF_CONSTEXPR 1 +# else +# define GLM_HAS_IF_CONSTEXPR 0 +# endif +# elif (GLM_LANG & GLM_LANG_CXX17_FLAG) +# define GLM_HAS_IF_CONSTEXPR 1 +# else +# define GLM_HAS_IF_CONSTEXPR 0 +# endif +#else +# define GLM_HAS_IF_CONSTEXPR 0 +#endif + +#if GLM_HAS_IF_CONSTEXPR +# define GLM_IF_CONSTEXPR if constexpr +#else +# define GLM_IF_CONSTEXPR if +#endif + +// [nodiscard] +#if GLM_LANG & GLM_LANG_CXX17_FLAG +# define GLM_NODISCARD [[nodiscard]] +#else +# define GLM_NODISCARD +#endif + +// +#if GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_ASSIGNABLE 1 +#else +# define GLM_HAS_ASSIGNABLE ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC15)) || \ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC49)))) +#endif + +// +#define GLM_HAS_TRIVIAL_QUERIES 0 + +// +#if GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_MAKE_SIGNED 1 +#else +# define GLM_HAS_MAKE_SIGNED ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC12)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#endif + +// +#if defined(GLM_FORCE_INTRINSICS) +# define GLM_HAS_BITSCAN_WINDOWS ((GLM_PLATFORM & GLM_PLATFORM_WINDOWS) && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC14) && (GLM_ARCH & GLM_ARCH_X86_BIT)))) +#else +# define GLM_HAS_BITSCAN_WINDOWS 0 +#endif + +#if GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_NOEXCEPT 1 +#else +# define GLM_HAS_NOEXCEPT 0 +#endif + +#if GLM_HAS_NOEXCEPT +# define GLM_NOEXCEPT noexcept +#else +# define GLM_NOEXCEPT +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// OpenMP +#ifdef _OPENMP +# if GLM_COMPILER & GLM_COMPILER_GCC +# if GLM_COMPILER >= GLM_COMPILER_GCC61 +# define GLM_HAS_OPENMP 45 +# elif GLM_COMPILER >= GLM_COMPILER_GCC49 +# define GLM_HAS_OPENMP 40 +# elif GLM_COMPILER >= GLM_COMPILER_GCC47 +# define GLM_HAS_OPENMP 31 +# else +# define GLM_HAS_OPENMP 0 +# endif +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# if GLM_COMPILER >= GLM_COMPILER_CLANG38 +# define GLM_HAS_OPENMP 31 +# else +# define GLM_HAS_OPENMP 0 +# endif +# elif GLM_COMPILER & GLM_COMPILER_VC +# define GLM_HAS_OPENMP 20 +# elif GLM_COMPILER & GLM_COMPILER_INTEL +# if GLM_COMPILER >= GLM_COMPILER_INTEL16 +# define GLM_HAS_OPENMP 40 +# else +# define GLM_HAS_OPENMP 0 +# endif +# else +# define GLM_HAS_OPENMP 0 +# endif +#else +# define GLM_HAS_OPENMP 0 +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// nullptr + +#if GLM_LANG & GLM_LANG_CXX0X_FLAG +# define GLM_CONFIG_NULLPTR GLM_ENABLE +#else +# define GLM_CONFIG_NULLPTR GLM_DISABLE +#endif + +#if GLM_CONFIG_NULLPTR == GLM_ENABLE +# define GLM_NULLPTR nullptr +#else +# define GLM_NULLPTR 0 +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Static assert + +#if GLM_HAS_STATIC_ASSERT +# define GLM_STATIC_ASSERT(x, message) static_assert(x, message) +#elif GLM_COMPILER & GLM_COMPILER_VC +# define GLM_STATIC_ASSERT(x, message) typedef char __CASSERT__##__LINE__[(x) ? 1 : -1] +#else +# define GLM_STATIC_ASSERT(x, message) assert(x) +#endif//GLM_LANG + +/////////////////////////////////////////////////////////////////////////////////// +// Qualifiers + +// User defines: GLM_CUDA_FORCE_DEVICE_FUNC, GLM_CUDA_FORCE_HOST_FUNC + +#if (GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP) +# if defined(GLM_CUDA_FORCE_DEVICE_FUNC) && defined(GLM_CUDA_FORCE_HOST_FUNC) +# error "GLM error: GLM_CUDA_FORCE_DEVICE_FUNC and GLM_CUDA_FORCE_HOST_FUNC should not be defined at the same time, GLM by default generates both device and host code for CUDA compiler." +# endif//defined(GLM_CUDA_FORCE_DEVICE_FUNC) && defined(GLM_CUDA_FORCE_HOST_FUNC) + +# if defined(GLM_CUDA_FORCE_DEVICE_FUNC) +# define GLM_CUDA_FUNC_DEF __device__ +# define GLM_CUDA_FUNC_DECL __device__ +# elif defined(GLM_CUDA_FORCE_HOST_FUNC) +# define GLM_CUDA_FUNC_DEF __host__ +# define GLM_CUDA_FUNC_DECL __host__ +# else +# define GLM_CUDA_FUNC_DEF __device__ __host__ +# define GLM_CUDA_FUNC_DECL __device__ __host__ +# endif//defined(GLM_CUDA_FORCE_XXXX_FUNC) +#else +# define GLM_CUDA_FUNC_DEF +# define GLM_CUDA_FUNC_DECL +#endif + +#if defined(GLM_FORCE_INLINE) +# if GLM_COMPILER & GLM_COMPILER_VC +# define GLM_INLINE __forceinline +# define GLM_NEVER_INLINE __declspec(noinline) +# elif GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG) +# define GLM_INLINE inline __attribute__((__always_inline__)) +# define GLM_NEVER_INLINE __attribute__((__noinline__)) +# elif (GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP) +# define GLM_INLINE __forceinline__ +# define GLM_NEVER_INLINE __noinline__ +# else +# define GLM_INLINE inline +# define GLM_NEVER_INLINE +# endif//GLM_COMPILER +#else +# define GLM_INLINE inline +# define GLM_NEVER_INLINE +#endif//defined(GLM_FORCE_INLINE) + +#define GLM_CTOR_DECL GLM_CUDA_FUNC_DECL GLM_CONSTEXPR +#define GLM_FUNC_DISCARD_DECL GLM_CUDA_FUNC_DECL +#define GLM_FUNC_DECL GLM_NODISCARD GLM_CUDA_FUNC_DECL +#define GLM_FUNC_QUALIFIER GLM_CUDA_FUNC_DEF GLM_INLINE + +// Do not use CUDA function qualifiers on CUDA compiler when functions are made default +#if GLM_HAS_DEFAULTED_FUNCTIONS +# define GLM_DEFAULTED_FUNC_DECL +# define GLM_DEFAULTED_FUNC_QUALIFIER GLM_INLINE +#else +# define GLM_DEFAULTED_FUNC_DECL GLM_FUNC_DISCARD_DECL +# define GLM_DEFAULTED_FUNC_QUALIFIER GLM_FUNC_QUALIFIER +#endif//GLM_HAS_DEFAULTED_FUNCTIONS +#if !defined(GLM_FORCE_CTOR_INIT) +# define GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CUDA_FUNC_DECL +# define GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_DEFAULTED_FUNC_QUALIFIER +#else +# define GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_FUNC_DISCARD_DECL +# define GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_FUNC_QUALIFIER +#endif//GLM_FORCE_CTOR_INIT + +/////////////////////////////////////////////////////////////////////////////////// +// Swizzle operators + +// User defines: GLM_FORCE_SWIZZLE + +#define GLM_SWIZZLE_DISABLED 0 +#define GLM_SWIZZLE_OPERATOR 1 +#define GLM_SWIZZLE_FUNCTION 2 + +#if defined(GLM_SWIZZLE) +# pragma message("GLM: GLM_SWIZZLE is deprecated, use GLM_FORCE_SWIZZLE instead.") +# define GLM_FORCE_SWIZZLE +#endif + +#if defined(GLM_FORCE_SWIZZLE) && (GLM_LANG & GLM_LANG_CXXMS_FLAG) && !defined(GLM_FORCE_XYZW_ONLY) +# define GLM_CONFIG_SWIZZLE GLM_SWIZZLE_OPERATOR +#elif defined(GLM_FORCE_SWIZZLE) +# define GLM_CONFIG_SWIZZLE GLM_SWIZZLE_FUNCTION +#else +# define GLM_CONFIG_SWIZZLE GLM_SWIZZLE_DISABLED +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Allows using not basic types as genType + +// #define GLM_FORCE_UNRESTRICTED_GENTYPE + +#ifdef GLM_FORCE_UNRESTRICTED_GENTYPE +# define GLM_CONFIG_UNRESTRICTED_GENTYPE GLM_ENABLE +#else +# define GLM_CONFIG_UNRESTRICTED_GENTYPE GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Allows using any scaler as float + +// #define GLM_FORCE_UNRESTRICTED_FLOAT + +#ifdef GLM_FORCE_UNRESTRICTED_FLOAT +# define GLM_CONFIG_UNRESTRICTED_FLOAT GLM_ENABLE +#else +# define GLM_CONFIG_UNRESTRICTED_FLOAT GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Clip control, define GLM_FORCE_DEPTH_ZERO_TO_ONE before including GLM +// to use a clip space between 0 to 1. +// Coordinate system, define GLM_FORCE_LEFT_HANDED before including GLM +// to use left handed coordinate system by default. + +#define GLM_CLIP_CONTROL_ZO_BIT (1 << 0) // ZERO_TO_ONE +#define GLM_CLIP_CONTROL_NO_BIT (1 << 1) // NEGATIVE_ONE_TO_ONE +#define GLM_CLIP_CONTROL_LH_BIT (1 << 2) // LEFT_HANDED, For DirectX, Metal, Vulkan +#define GLM_CLIP_CONTROL_RH_BIT (1 << 3) // RIGHT_HANDED, For OpenGL, default in GLM + +#define GLM_CLIP_CONTROL_LH_ZO (GLM_CLIP_CONTROL_LH_BIT | GLM_CLIP_CONTROL_ZO_BIT) +#define GLM_CLIP_CONTROL_LH_NO (GLM_CLIP_CONTROL_LH_BIT | GLM_CLIP_CONTROL_NO_BIT) +#define GLM_CLIP_CONTROL_RH_ZO (GLM_CLIP_CONTROL_RH_BIT | GLM_CLIP_CONTROL_ZO_BIT) +#define GLM_CLIP_CONTROL_RH_NO (GLM_CLIP_CONTROL_RH_BIT | GLM_CLIP_CONTROL_NO_BIT) + +#ifdef GLM_FORCE_DEPTH_ZERO_TO_ONE +# ifdef GLM_FORCE_LEFT_HANDED +# define GLM_CONFIG_CLIP_CONTROL GLM_CLIP_CONTROL_LH_ZO +# else +# define GLM_CONFIG_CLIP_CONTROL GLM_CLIP_CONTROL_RH_ZO +# endif +#else +# ifdef GLM_FORCE_LEFT_HANDED +# define GLM_CONFIG_CLIP_CONTROL GLM_CLIP_CONTROL_LH_NO +# else +# define GLM_CONFIG_CLIP_CONTROL GLM_CLIP_CONTROL_RH_NO +# endif +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Qualifiers + +#if (GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS)) +# define GLM_DEPRECATED __declspec(deprecated) +# define GLM_ALIGNED_TYPEDEF(type, name, alignment) typedef __declspec(align(alignment)) type name +#elif GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG | GLM_COMPILER_INTEL) +# if GLM_LANG & GLM_LANG_CXX14_FLAG +# define GLM_DEPRECATED [[deprecated]] +# else +# define GLM_DEPRECATED __attribute__((__deprecated__)) +# endif +# define GLM_ALIGNED_TYPEDEF(type, name, alignment) typedef type name __attribute__((aligned(alignment))) +#elif (GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP) +# define GLM_DEPRECATED +# define GLM_ALIGNED_TYPEDEF(type, name, alignment) typedef type name __align__(x) +#else +# define GLM_DEPRECATED +# define GLM_ALIGNED_TYPEDEF(type, name, alignment) typedef type name +#endif + +/////////////////////////////////////////////////////////////////////////////////// + +#ifdef GLM_FORCE_EXPLICIT_CTOR +# define GLM_EXPLICIT explicit +#else +# define GLM_EXPLICIT +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Length type: all length functions returns a length_t type. +// When GLM_FORCE_SIZE_T_LENGTH is defined, length_t is a typedef of size_t otherwise +// length_t is a typedef of int like GLSL defines it. + +#define GLM_LENGTH_INT 1 +#define GLM_LENGTH_SIZE_T 2 + +#ifdef GLM_FORCE_SIZE_T_LENGTH +# define GLM_CONFIG_LENGTH_TYPE GLM_LENGTH_SIZE_T +# define GLM_ASSERT_LENGTH(l, max) (assert ((l) < (max))) +#else +# define GLM_CONFIG_LENGTH_TYPE GLM_LENGTH_INT +# define GLM_ASSERT_LENGTH(l, max) (assert ((l) >= 0 && (l) < (max))) +#endif + +namespace glm +{ + using std::size_t; +# if GLM_CONFIG_LENGTH_TYPE == GLM_LENGTH_SIZE_T + typedef size_t length_t; +# else + typedef int length_t; +# endif +}//namespace glm + +/////////////////////////////////////////////////////////////////////////////////// +// constexpr + +#if GLM_HAS_CONSTEXPR +# define GLM_CONFIG_CONSTEXP GLM_ENABLE + + namespace glm + { + template + constexpr std::size_t countof(T const (&)[N]) + { + return N; + } + }//namespace glm +# define GLM_COUNTOF(arr) glm::countof(arr) +#elif defined(_MSC_VER) +# define GLM_CONFIG_CONSTEXP GLM_DISABLE + +# define GLM_COUNTOF(arr) _countof(arr) +#else +# define GLM_CONFIG_CONSTEXP GLM_DISABLE + +# define GLM_COUNTOF(arr) sizeof(arr) / sizeof(arr[0]) +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// uint + +namespace glm{ +namespace detail +{ + template + struct is_int + { + enum test {value = 0}; + }; + + template<> + struct is_int + { + enum test {value = ~0}; + }; + + template<> + struct is_int + { + enum test {value = ~0}; + }; +}//namespace detail + + typedef unsigned int uint; +}//namespace glm + +/////////////////////////////////////////////////////////////////////////////////// +// 64-bit int + +#if GLM_HAS_EXTENDED_INTEGER_TYPE +# include +#endif + +namespace glm{ +namespace detail +{ +# if GLM_HAS_EXTENDED_INTEGER_TYPE + typedef std::uint64_t uint64; + typedef std::int64_t int64; +# elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) // C99 detected, 64 bit types available + typedef uint64_t uint64; + typedef int64_t int64; +# elif GLM_COMPILER & GLM_COMPILER_VC + typedef unsigned __int64 uint64; + typedef signed __int64 int64; +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic ignored "-Wlong-long" + __extension__ typedef unsigned long long uint64; + __extension__ typedef signed long long int64; +# elif (GLM_COMPILER & GLM_COMPILER_CLANG) +# pragma clang diagnostic ignored "-Wc++11-long-long" + typedef unsigned long long uint64; + typedef signed long long int64; +# else//unknown compiler + typedef unsigned long long uint64; + typedef signed long long int64; +# endif +}//namespace detail +}//namespace glm + +/////////////////////////////////////////////////////////////////////////////////// +// make_unsigned + +#if GLM_HAS_MAKE_SIGNED +# include + +namespace glm{ +namespace detail +{ + using std::make_unsigned; +}//namespace detail +}//namespace glm + +#else + +namespace glm{ +namespace detail +{ + template + struct make_unsigned + {}; + + template<> + struct make_unsigned + { + typedef unsigned char type; + }; + + template<> + struct make_unsigned + { + typedef unsigned char type; + }; + + template<> + struct make_unsigned + { + typedef unsigned short type; + }; + + template<> + struct make_unsigned + { + typedef unsigned int type; + }; + + template<> + struct make_unsigned + { + typedef unsigned long type; + }; + + template<> + struct make_unsigned + { + typedef uint64 type; + }; + + template<> + struct make_unsigned + { + typedef unsigned char type; + }; + + template<> + struct make_unsigned + { + typedef unsigned short type; + }; + + template<> + struct make_unsigned + { + typedef unsigned int type; + }; + + template<> + struct make_unsigned + { + typedef unsigned long type; + }; + + template<> + struct make_unsigned + { + typedef uint64 type; + }; +}//namespace detail +}//namespace glm +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Only use x, y, z, w as vector type components + +#ifdef GLM_FORCE_XYZW_ONLY +# define GLM_CONFIG_XYZW_ONLY GLM_ENABLE +#else +# define GLM_CONFIG_XYZW_ONLY GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Configure the use of defaulted initialized types + +#define GLM_CTOR_INIT_DISABLE 0 +#define GLM_CTOR_INITIALIZER_LIST 1 +#define GLM_CTOR_INITIALISATION 2 + +#if defined(GLM_FORCE_CTOR_INIT) && GLM_HAS_INITIALIZER_LISTS +# define GLM_CONFIG_CTOR_INIT GLM_CTOR_INITIALIZER_LIST +#elif defined(GLM_FORCE_CTOR_INIT) && !GLM_HAS_INITIALIZER_LISTS +# define GLM_CONFIG_CTOR_INIT GLM_CTOR_INITIALISATION +#else +# define GLM_CONFIG_CTOR_INIT GLM_CTOR_INIT_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Use SIMD instruction sets + +#if GLM_HAS_ALIGNOF && (GLM_LANG & GLM_LANG_CXXMS_FLAG) && (GLM_ARCH & GLM_ARCH_SIMD_BIT) +# define GLM_CONFIG_SIMD GLM_ENABLE +#else +# define GLM_CONFIG_SIMD GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Configure the use of defaulted function + +#if GLM_HAS_DEFAULTED_FUNCTIONS +# define GLM_CONFIG_DEFAULTED_FUNCTIONS GLM_ENABLE +# define GLM_DEFAULT = default +#else +# define GLM_CONFIG_DEFAULTED_FUNCTIONS GLM_DISABLE +# define GLM_DEFAULT +#endif + +#if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INIT_DISABLE && GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_ENABLE +# define GLM_CONFIG_DEFAULTED_DEFAULT_CTOR GLM_ENABLE +# define GLM_DEFAULT_CTOR GLM_DEFAULT +#else +# define GLM_CONFIG_DEFAULTED_DEFAULT_CTOR GLM_DISABLE +# define GLM_DEFAULT_CTOR +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Configure the use of aligned gentypes + +#ifdef GLM_FORCE_ALIGNED // Legacy define +# define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES +#endif + +#ifdef GLM_FORCE_DEFAULT_ALIGNED_GENTYPES +# define GLM_FORCE_ALIGNED_GENTYPES +#endif + +#if GLM_HAS_ALIGNOF && (GLM_LANG & GLM_LANG_CXXMS_FLAG) && (defined(GLM_FORCE_ALIGNED_GENTYPES) || (GLM_CONFIG_SIMD == GLM_ENABLE)) +# define GLM_CONFIG_ALIGNED_GENTYPES GLM_ENABLE +#else +# define GLM_CONFIG_ALIGNED_GENTYPES GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Configure the use of anonymous structure as implementation detail + +#if ((GLM_CONFIG_SIMD == GLM_ENABLE) || (GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR) || (GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE)) +# define GLM_CONFIG_ANONYMOUS_STRUCT GLM_ENABLE +#else +# define GLM_CONFIG_ANONYMOUS_STRUCT GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Silent warnings + +#ifdef GLM_FORCE_WARNINGS +# define GLM_SILENT_WARNINGS GLM_DISABLE +#else +# define GLM_SILENT_WARNINGS GLM_ENABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Precision + +#define GLM_HIGHP 1 +#define GLM_MEDIUMP 2 +#define GLM_LOWP 3 + +#if defined(GLM_FORCE_PRECISION_HIGHP_BOOL) || defined(GLM_PRECISION_HIGHP_BOOL) +# define GLM_CONFIG_PRECISION_BOOL GLM_HIGHP +#elif defined(GLM_FORCE_PRECISION_MEDIUMP_BOOL) || defined(GLM_PRECISION_MEDIUMP_BOOL) +# define GLM_CONFIG_PRECISION_BOOL GLM_MEDIUMP +#elif defined(GLM_FORCE_PRECISION_LOWP_BOOL) || defined(GLM_PRECISION_LOWP_BOOL) +# define GLM_CONFIG_PRECISION_BOOL GLM_LOWP +#else +# define GLM_CONFIG_PRECISION_BOOL GLM_HIGHP +#endif + +#if defined(GLM_FORCE_PRECISION_HIGHP_INT) || defined(GLM_PRECISION_HIGHP_INT) +# define GLM_CONFIG_PRECISION_INT GLM_HIGHP +#elif defined(GLM_FORCE_PRECISION_MEDIUMP_INT) || defined(GLM_PRECISION_MEDIUMP_INT) +# define GLM_CONFIG_PRECISION_INT GLM_MEDIUMP +#elif defined(GLM_FORCE_PRECISION_LOWP_INT) || defined(GLM_PRECISION_LOWP_INT) +# define GLM_CONFIG_PRECISION_INT GLM_LOWP +#else +# define GLM_CONFIG_PRECISION_INT GLM_HIGHP +#endif + +#if defined(GLM_FORCE_PRECISION_HIGHP_UINT) || defined(GLM_PRECISION_HIGHP_UINT) +# define GLM_CONFIG_PRECISION_UINT GLM_HIGHP +#elif defined(GLM_FORCE_PRECISION_MEDIUMP_UINT) || defined(GLM_PRECISION_MEDIUMP_UINT) +# define GLM_CONFIG_PRECISION_UINT GLM_MEDIUMP +#elif defined(GLM_FORCE_PRECISION_LOWP_UINT) || defined(GLM_PRECISION_LOWP_UINT) +# define GLM_CONFIG_PRECISION_UINT GLM_LOWP +#else +# define GLM_CONFIG_PRECISION_UINT GLM_HIGHP +#endif + +#if defined(GLM_FORCE_PRECISION_HIGHP_FLOAT) || defined(GLM_PRECISION_HIGHP_FLOAT) +# define GLM_CONFIG_PRECISION_FLOAT GLM_HIGHP +#elif defined(GLM_FORCE_PRECISION_MEDIUMP_FLOAT) || defined(GLM_PRECISION_MEDIUMP_FLOAT) +# define GLM_CONFIG_PRECISION_FLOAT GLM_MEDIUMP +#elif defined(GLM_FORCE_PRECISION_LOWP_FLOAT) || defined(GLM_PRECISION_LOWP_FLOAT) +# define GLM_CONFIG_PRECISION_FLOAT GLM_LOWP +#else +# define GLM_CONFIG_PRECISION_FLOAT GLM_HIGHP +#endif + +#if defined(GLM_FORCE_PRECISION_HIGHP_DOUBLE) || defined(GLM_PRECISION_HIGHP_DOUBLE) +# define GLM_CONFIG_PRECISION_DOUBLE GLM_HIGHP +#elif defined(GLM_FORCE_PRECISION_MEDIUMP_DOUBLE) || defined(GLM_PRECISION_MEDIUMP_DOUBLE) +# define GLM_CONFIG_PRECISION_DOUBLE GLM_MEDIUMP +#elif defined(GLM_FORCE_PRECISION_LOWP_DOUBLE) || defined(GLM_PRECISION_LOWP_DOUBLE) +# define GLM_CONFIG_PRECISION_DOUBLE GLM_LOWP +#else +# define GLM_CONFIG_PRECISION_DOUBLE GLM_HIGHP +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Check inclusions of different versions of GLM + +#elif ((GLM_SETUP_INCLUDED != GLM_VERSION) && !defined(GLM_FORCE_IGNORE_VERSION)) +# error "GLM error: A different version of GLM is already included. Define GLM_FORCE_IGNORE_VERSION before including GLM headers to ignore this error." +#elif GLM_SETUP_INCLUDED == GLM_VERSION + +/////////////////////////////////////////////////////////////////////////////////// +// Messages + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_MESSAGE_DISPLAYED) +# define GLM_MESSAGE_DISPLAYED +# define GLM_STR_HELPER(x) #x +# define GLM_STR(x) GLM_STR_HELPER(x) + + // Report GLM version +# pragma message (GLM_STR(GLM_VERSION_MESSAGE)) + + // Report C++ language +# if (GLM_LANG & GLM_LANG_CXX20_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 20 with extensions") +# elif (GLM_LANG & GLM_LANG_CXX20_FLAG) +# pragma message("GLM: C++ 2A") +# elif (GLM_LANG & GLM_LANG_CXX17_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 17 with extensions") +# elif (GLM_LANG & GLM_LANG_CXX17_FLAG) +# pragma message("GLM: C++ 17") +# elif (GLM_LANG & GLM_LANG_CXX14_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 14 with extensions") +# elif (GLM_LANG & GLM_LANG_CXX14_FLAG) +# pragma message("GLM: C++ 14") +# elif (GLM_LANG & GLM_LANG_CXX11_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 11 with extensions") +# elif (GLM_LANG & GLM_LANG_CXX11_FLAG) +# pragma message("GLM: C++ 11") +# elif (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 0x with extensions") +# elif (GLM_LANG & GLM_LANG_CXX0X_FLAG) +# pragma message("GLM: C++ 0x") +# elif (GLM_LANG & GLM_LANG_CXX03_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 03 with extensions") +# elif (GLM_LANG & GLM_LANG_CXX03_FLAG) +# pragma message("GLM: C++ 03") +# elif (GLM_LANG & GLM_LANG_CXX98_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 98 with extensions") +# elif (GLM_LANG & GLM_LANG_CXX98_FLAG) +# pragma message("GLM: C++ 98") +# else +# pragma message("GLM: C++ language undetected") +# endif//GLM_LANG + + // Report compiler detection +# if GLM_COMPILER & GLM_COMPILER_CUDA +# pragma message("GLM: CUDA compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_HIP +# pragma message("GLM: HIP compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma message("GLM: Visual C++ compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma message("GLM: Clang compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_INTEL +# pragma message("GLM: Intel Compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma message("GLM: GCC compiler detected") +# else +# pragma message("GLM: Compiler not detected") +# endif + + // Report build target +# if (GLM_ARCH & GLM_ARCH_AVX2_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with AVX2 instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_AVX2_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with AVX2 instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_AVX_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with AVX instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_AVX_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with AVX instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_SSE42_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with SSE4.2 instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_SSE42_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with SSE4.2 instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_SSE41_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with SSE4.1 instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_SSE41_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with SSE4.1 instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_SSSE3_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with SSSE3 instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_SSSE3_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with SSSE3 instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_SSE3_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with SSE3 instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_SSE3_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with SSE3 instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_SSE2_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with SSE2 instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_SSE2_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with SSE2 instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_X86_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits build target") +# elif (GLM_ARCH & GLM_ARCH_X86_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits build target") + +# elif (GLM_ARCH & GLM_ARCH_NEON_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: ARM 64 bits with Neon instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_NEON_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: ARM 32 bits with Neon instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_ARM_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: ARM 64 bits build target") +# elif (GLM_ARCH & GLM_ARCH_ARM_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: ARM 32 bits build target") + +# elif (GLM_ARCH & GLM_ARCH_MIPS_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: MIPS 64 bits build target") +# elif (GLM_ARCH & GLM_ARCH_MIPS_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: MIPS 32 bits build target") + +# elif (GLM_ARCH & GLM_ARCH_PPC_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: PowerPC 64 bits build target") +# elif (GLM_ARCH & GLM_ARCH_PPC_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: PowerPC 32 bits build target") +# else +# pragma message("GLM: Unknown build target") +# endif//GLM_ARCH + + // Report platform name +# if(GLM_PLATFORM & GLM_PLATFORM_QNXNTO) +# pragma message("GLM: QNX platform detected") +//# elif(GLM_PLATFORM & GLM_PLATFORM_IOS) +//# pragma message("GLM: iOS platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_APPLE) +# pragma message("GLM: Apple platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_WINCE) +# pragma message("GLM: WinCE platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_WINDOWS) +# pragma message("GLM: Windows platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_CHROME_NACL) +# pragma message("GLM: Native Client detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) +# pragma message("GLM: Android platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_LINUX) +# pragma message("GLM: Linux platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_UNIX) +# pragma message("GLM: UNIX platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_UNKNOWN) +# pragma message("GLM: platform unknown") +# else +# pragma message("GLM: platform not detected") +# endif + + // Report whether only xyzw component are used +# if defined GLM_FORCE_XYZW_ONLY +# pragma message("GLM: GLM_FORCE_XYZW_ONLY is defined. Only x, y, z and w component are available in vector type. This define disables swizzle operators and SIMD instruction sets.") +# endif + + // Report swizzle operator support +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR +# pragma message("GLM: GLM_FORCE_SWIZZLE is defined, swizzling operators enabled.") +# elif GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION +# pragma message("GLM: GLM_FORCE_SWIZZLE is defined, swizzling functions enabled. Enable compiler C++ language extensions to enable swizzle operators.") +# else +# pragma message("GLM: GLM_FORCE_SWIZZLE is undefined. swizzling functions or operators are disabled.") +# endif + + // Report .length() type +# if GLM_CONFIG_LENGTH_TYPE == GLM_LENGTH_SIZE_T +# pragma message("GLM: GLM_FORCE_SIZE_T_LENGTH is defined. .length() returns a glm::length_t, a typedef of std::size_t.") +# else +# pragma message("GLM: GLM_FORCE_SIZE_T_LENGTH is undefined. .length() returns a glm::length_t, a typedef of int following GLSL.") +# endif + +# if GLM_CONFIG_UNRESTRICTED_GENTYPE == GLM_ENABLE +# pragma message("GLM: GLM_FORCE_UNRESTRICTED_GENTYPE is defined. Removes GLSL restrictions on valid function genTypes.") +# else +# pragma message("GLM: GLM_FORCE_UNRESTRICTED_GENTYPE is undefined. Follows strictly GLSL on valid function genTypes.") +# endif + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# pragma message("GLM: GLM_FORCE_SILENT_WARNINGS is defined. Ignores C++ warnings from using C++ language extensions.") +# else +# pragma message("GLM: GLM_FORCE_SILENT_WARNINGS is undefined. Shows C++ warnings from using C++ language extensions.") +# endif + +# ifdef GLM_FORCE_SINGLE_ONLY +# pragma message("GLM: GLM_FORCE_SINGLE_ONLY is defined. Using only single precision floating-point types.") +# endif + +# if defined(GLM_FORCE_ALIGNED_GENTYPES) && (GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE) +# undef GLM_FORCE_ALIGNED_GENTYPES +# pragma message("GLM: GLM_FORCE_ALIGNED_GENTYPES is defined, allowing aligned types. This prevents the use of C++ constexpr.") +# elif defined(GLM_FORCE_ALIGNED_GENTYPES) && (GLM_CONFIG_ALIGNED_GENTYPES == GLM_DISABLE) +# undef GLM_FORCE_ALIGNED_GENTYPES +# pragma message("GLM: GLM_FORCE_ALIGNED_GENTYPES is defined but is disabled. It requires C++11 and language extensions.") +# endif + +# if defined(GLM_FORCE_DEFAULT_ALIGNED_GENTYPES) +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_DISABLE +# undef GLM_FORCE_DEFAULT_ALIGNED_GENTYPES +# pragma message("GLM: GLM_FORCE_DEFAULT_ALIGNED_GENTYPES is defined but is disabled. It requires C++11 and language extensions.") +# elif GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE +# pragma message("GLM: GLM_FORCE_DEFAULT_ALIGNED_GENTYPES is defined. All gentypes (e.g. vec3) will be aligned and padded by default.") +# endif +# endif + +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT +# pragma message("GLM: GLM_FORCE_DEPTH_ZERO_TO_ONE is defined. Using zero to one depth clip space.") +# else +# pragma message("GLM: GLM_FORCE_DEPTH_ZERO_TO_ONE is undefined. Using negative one to one depth clip space.") +# endif + +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT +# pragma message("GLM: GLM_FORCE_LEFT_HANDED is defined. Using left handed coordinate system.") +# else +# pragma message("GLM: GLM_FORCE_LEFT_HANDED is undefined. Using right handed coordinate system.") +# endif +#endif//GLM_MESSAGES + +#endif//GLM_SETUP_INCLUDED diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_float.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_float.hpp new file mode 100644 index 0000000..c8037eb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_float.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include "setup.hpp" + +#if GLM_COMPILER == GLM_COMPILER_VC12 +# pragma warning(push) +# pragma warning(disable: 4512) // assignment operator could not be generated +#endif + +namespace glm{ +namespace detail +{ + template + union float_t + {}; + + // https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ + template <> + union float_t + { + typedef int int_type; + typedef float float_type; + + GLM_CONSTEXPR float_t(float_type Num = 0.0f) : f(Num) {} + + GLM_CONSTEXPR float_t& operator=(float_t const& x) + { + f = x.f; + return *this; + } + + // Portable extraction of components. + GLM_CONSTEXPR bool negative() const { return i < 0; } + GLM_CONSTEXPR int_type mantissa() const { return i & ((1 << 23) - 1); } + GLM_CONSTEXPR int_type exponent() const { return (i >> 23) & ((1 << 8) - 1); } + + int_type i; + float_type f; + }; + + template <> + union float_t + { + typedef detail::int64 int_type; + typedef double float_type; + + GLM_CONSTEXPR float_t(float_type Num = static_cast(0)) : f(Num) {} + + GLM_CONSTEXPR float_t& operator=(float_t const& x) + { + f = x.f; + return *this; + } + + // Portable extraction of components. + GLM_CONSTEXPR bool negative() const { return i < 0; } + GLM_CONSTEXPR int_type mantissa() const { return i & ((int_type(1) << 52) - 1); } + GLM_CONSTEXPR int_type exponent() const { return (i >> 52) & ((int_type(1) << 11) - 1); } + + int_type i; + float_type f; + }; +}//namespace detail +}//namespace glm + +#if GLM_COMPILER == GLM_COMPILER_VC12 +# pragma warning(pop) +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_half.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_half.hpp new file mode 100644 index 0000000..40b8bec --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_half.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "setup.hpp" + +namespace glm{ +namespace detail +{ + typedef short hdata; + + GLM_FUNC_DECL float toFloat32(hdata value); + GLM_FUNC_DECL hdata toFloat16(float const& value); + +}//namespace detail +}//namespace glm + +#include "type_half.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_half.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_half.inl new file mode 100644 index 0000000..5d239cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_half.inl @@ -0,0 +1,241 @@ +namespace glm{ +namespace detail +{ + GLM_FUNC_QUALIFIER float overflow() + { + volatile float f = 1e10; + + for(int i = 0; i < 10; ++i) + f = f * f; // this will overflow before the for loop terminates + return f; + } + + union uif32 + { + GLM_FUNC_QUALIFIER uif32() : + i(0) + {} + + GLM_FUNC_QUALIFIER uif32(float f_) : + f(f_) + {} + + GLM_FUNC_QUALIFIER uif32(unsigned int i_) : + i(i_) + {} + + float f; + unsigned int i; + }; + + GLM_FUNC_QUALIFIER float toFloat32(hdata value) + { + int s = (value >> 15) & 0x00000001; + int e = (value >> 10) & 0x0000001f; + int m = value & 0x000003ff; + + if(e == 0) + { + if(m == 0) + { + // + // Plus or minus zero + // + + detail::uif32 result; + result.i = static_cast(s << 31); + return result.f; + } + else + { + // + // Denormalized number -- renormalize it + // + + while(!(m & 0x00000400)) + { + m <<= 1; + e -= 1; + } + + e += 1; + m &= ~0x00000400; + } + } + else if(e == 31) + { + if(m == 0) + { + // + // Positive or negative infinity + // + + uif32 result; + result.i = static_cast((s << 31) | 0x7f800000); + return result.f; + } + else + { + // + // Nan -- preserve sign and significand bits + // + + uif32 result; + result.i = static_cast((s << 31) | 0x7f800000 | (m << 13)); + return result.f; + } + } + + // + // Normalized number + // + + e = e + (127 - 15); + m = m << 13; + + // + // Assemble s, e and m. + // + + uif32 Result; + Result.i = static_cast((s << 31) | (e << 23) | m); + return Result.f; + } + + GLM_FUNC_QUALIFIER hdata toFloat16(float const& f) + { + uif32 Entry; + Entry.f = f; + int i = static_cast(Entry.i); + + // + // Our floating point number, f, is represented by the bit + // pattern in integer i. Disassemble that bit pattern into + // the sign, s, the exponent, e, and the significand, m. + // Shift s into the position where it will go in the + // resulting half number. + // Adjust e, accounting for the different exponent bias + // of float and half (127 versus 15). + // + + int s = (i >> 16) & 0x00008000; + int e = ((i >> 23) & 0x000000ff) - (127 - 15); + int m = i & 0x007fffff; + + // + // Now reassemble s, e and m into a half: + // + + if(e <= 0) + { + if(e < -10) + { + // + // E is less than -10. The absolute value of f is + // less than half_MIN (f may be a small normalized + // float, a denormalized float or a zero). + // + // We convert f to a half zero. + // + + return hdata(s); + } + + // + // E is between -10 and 0. F is a normalized float, + // whose magnitude is less than __half_NRM_MIN. + // + // We convert f to a denormalized half. + // + + m = (m | 0x00800000) >> (1 - e); + + // + // Round to nearest, round "0.5" up. + // + // Rounding may cause the significand to overflow and make + // our number normalized. Because of the way a half's bits + // are laid out, we don't have to treat this case separately; + // the code below will handle it correctly. + // + + if(m & 0x00001000) + m += 0x00002000; + + // + // Assemble the half from s, e (zero) and m. + // + + return hdata(s | (m >> 13)); + } + else if(e == 0xff - (127 - 15)) + { + if(m == 0) + { + // + // F is an infinity; convert f to a half + // infinity with the same sign as f. + // + + return hdata(s | 0x7c00); + } + else + { + // + // F is a NAN; we produce a half NAN that preserves + // the sign bit and the 10 leftmost bits of the + // significand of f, with one exception: If the 10 + // leftmost bits are all zero, the NAN would turn + // into an infinity, so we have to set at least one + // bit in the significand. + // + + m >>= 13; + + return hdata(s | 0x7c00 | m | (m == 0)); + } + } + else + { + // + // E is greater than zero. F is a normalized float. + // We try to convert f to a normalized half. + // + + // + // Round to nearest, round "0.5" up + // + + if(m & 0x00001000) + { + m += 0x00002000; + + if(m & 0x00800000) + { + m = 0; // overflow in significand, + e += 1; // adjust exponent + } + } + + // + // Handle exponent overflow + // + + if (e > 30) + { + overflow(); // Cause a hardware floating point overflow; + + return hdata(s | 0x7c00); + // if this returns, the half becomes an + } // infinity with the same sign as f. + + // + // Assemble the half from s, e and m. + // + + return hdata(s | (e << 10) | (m >> 13)); + } + } + +}//namespace detail +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x2.hpp new file mode 100644 index 0000000..82e9f66 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x2.hpp @@ -0,0 +1,177 @@ +/// @ref core +/// @file glm/detail/type_mat2x2.hpp + +#pragma once + +#include "type_vec2.hpp" +#include +#include + +namespace glm +{ + template + struct mat<2, 2, T, Q> + { + typedef vec<2, T, Q> col_type; + typedef vec<2, T, Q> row_type; + typedef mat<2, 2, T, Q> type; + typedef mat<2, 2, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[2]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 2; } + + GLM_FUNC_DECL GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<2, 2, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T scalar); + GLM_CTOR_DECL mat( + T const& x1, T const& y1, + T const& x2, T const& y2); + GLM_CTOR_DECL mat( + col_type const& v1, + col_type const& v2); + + // -- Conversions -- + + template + GLM_CTOR_DECL mat( + U const& x1, V const& y1, + M const& x2, N const& y2); + + template + GLM_CTOR_DECL mat( + vec<2, U, Q> const& v1, + vec<2, V, Q> const& v2); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator=(mat<2, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator+=(mat<2, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator-=(mat<2, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator*=(mat<2, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator/=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator/=(mat<2, 2, U, Q> const& m); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator++ (); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator-- (); + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator+(T scalar, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator-(T scalar, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator*(mat<2, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator*(T scalar, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<2, 2, T, Q>::col_type operator*(mat<2, 2, T, Q> const& m, typename mat<2, 2, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<2, 2, T, Q>::row_type operator*(typename mat<2, 2, T, Q>::col_type const& v, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator/(mat<2, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator/(T scalar, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<2, 2, T, Q>::col_type operator/(mat<2, 2, T, Q> const& m, typename mat<2, 2, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<2, 2, T, Q>::row_type operator/(typename mat<2, 2, T, Q>::col_type const& v, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator/(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); +} //namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat2x2.inl" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x2.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x2.inl new file mode 100644 index 0000000..afb2b31 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x2.inl @@ -0,0 +1,536 @@ +#include "../matrix.hpp" + +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0), col_type(0, 1)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0); + this->value[1] = col_type(0, 1); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<2, 2, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(T scalar) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(scalar, 0), col_type(0, scalar)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(scalar, 0); + this->value[1] = col_type(0, scalar); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat + ( + T const& x0, T const& y0, + T const& x1, T const& y1 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0), col_type(x1, y1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(col_type const& v0, col_type const& v1) +# if GLM_HAS_INITIALIZER_LISTS + : value{v0, v1} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; +# endif + } + + // -- Conversion constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat + ( + X1 const& x1, Y1 const& y1, + X2 const& x2, Y2 const& y2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(static_cast(x1), value_type(y1)), col_type(static_cast(x2), value_type(y2)) } +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(static_cast(x1), value_type(y1)); + this->value[1] = col_type(static_cast(x2), value_type(y2)); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(vec<2, V1, Q> const& v1, vec<2, V2, Q> const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); +# endif + } + + // -- mat2x2 matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<2, 2, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 2, T, Q>::col_type& mat<2, 2, T, Q>::operator[](typename mat<2, 2, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 2, T, Q>::col_type const& mat<2, 2, T, Q>::operator[](typename mat<2, 2, T, Q>::length_type i) const GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator=(mat<2, 2, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator+=(U scalar) + { + this->value[0] += scalar; + this->value[1] += scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator+=(mat<2, 2, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator-=(U scalar) + { + this->value[0] -= scalar; + this->value[1] -= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator-=(mat<2, 2, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator*=(U scalar) + { + this->value[0] *= scalar; + this->value[1] *= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator*=(mat<2, 2, U, Q> const& m) + { + return (*this = *this * m); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator/=(U scalar) + { + this->value[0] /= scalar; + this->value[1] /= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator/=(mat<2, 2, U, Q> const& m) + { + return *this *= inverse(m); + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> mat<2, 2, T, Q>::operator++(int) + { + mat<2, 2, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> mat<2, 2, T, Q>::operator--(int) + { + mat<2, 2, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m) + { + return mat<2, 2, T, Q>( + -m[0], + -m[1]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m, T scalar) + { + return mat<2, 2, T, Q>( + m[0] + scalar, + m[1] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator+(T scalar, mat<2, 2, T, Q> const& m) + { + return mat<2, 2, T, Q>( + m[0] + scalar, + m[1] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return mat<2, 2, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m, T scalar) + { + return mat<2, 2, T, Q>( + m[0] - scalar, + m[1] - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator-(T scalar, mat<2, 2, T, Q> const& m) + { + return mat<2, 2, T, Q>( + scalar - m[0], + scalar - m[1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return mat<2, 2, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator*(mat<2, 2, T, Q> const& m, T scalar) + { + return mat<2, 2, T, Q>( + m[0] * scalar, + m[1] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator*(T scalar, mat<2, 2, T, Q> const& m) + { + return mat<2, 2, T, Q>( + m[0] * scalar, + m[1] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 2, T, Q>::col_type operator* + ( + mat<2, 2, T, Q> const& m, + typename mat<2, 2, T, Q>::row_type const& v + ) + { + return vec<2, T, Q>( + m[0][0] * v.x + m[1][0] * v.y, + m[0][1] * v.x + m[1][1] * v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 2, T, Q>::row_type operator* + ( + typename mat<2, 2, T, Q>::col_type const& v, + mat<2, 2, T, Q> const& m + ) + { + return vec<2, T, Q>( + v.x * m[0][0] + v.y * m[0][1], + v.x * m[1][0] + v.y * m[1][1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return mat<2, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + return mat<3, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + return mat<4, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator/(mat<2, 2, T, Q> const& m, T scalar) + { + return mat<2, 2, T, Q>( + m[0] / scalar, + m[1] / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator/(T scalar, mat<2, 2, T, Q> const& m) + { + return mat<2, 2, T, Q>( + scalar / m[0], + scalar / m[1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 2, T, Q>::col_type operator/(mat<2, 2, T, Q> const& m, typename mat<2, 2, T, Q>::row_type const& v) + { + return inverse(m) * v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 2, T, Q>::row_type operator/(typename mat<2, 2, T, Q>::col_type const& v, mat<2, 2, T, Q> const& m) + { + return v * inverse(m); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator/(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + mat<2, 2, T, Q> m1_copy(m1); + return m1_copy /= m2; + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]); + } +} //namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x3.hpp new file mode 100644 index 0000000..b65d1c5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x3.hpp @@ -0,0 +1,159 @@ +/// @ref core +/// @file glm/detail/type_mat2x3.hpp + +#pragma once + +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include +#include + +namespace glm +{ + template + struct mat<2, 3, T, Q> + { + typedef vec<3, T, Q> col_type; + typedef vec<2, T, Q> row_type; + typedef mat<2, 3, T, Q> type; + typedef mat<3, 2, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[2]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 2; } + + GLM_FUNC_DECL GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<2, 3, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T scalar); + GLM_CTOR_DECL mat( + T x0, T y0, T z0, + T x1, T y1, T z1); + GLM_CTOR_DECL mat( + col_type const& v0, + col_type const& v1); + + // -- Conversions -- + + template + GLM_CTOR_DECL mat( + X1 x1, Y1 y1, Z1 z1, + X2 x2, Y2 y2, Z2 z2); + + template + GLM_CTOR_DECL mat( + vec<3, U, Q> const& v1, + vec<3, V, Q> const& v2); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator=(mat<2, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator+=(mat<2, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator-=(mat<2, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator++ (); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator-- (); + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator*(mat<2, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator*(T scalar, mat<2, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<2, 3, T, Q>::col_type operator*(mat<2, 3, T, Q> const& m, typename mat<2, 3, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<2, 3, T, Q>::row_type operator*(typename mat<2, 3, T, Q>::col_type const& v, mat<2, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator/(mat<2, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator/(T scalar, mat<2, 3, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat2x3.inl" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x3.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x3.inl new file mode 100644 index 0000000..345ac8a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x3.inl @@ -0,0 +1,510 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0, 0), col_type(0, 1, 0)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0, 0); + this->value[1] = col_type(0, 1, 0); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<2, 3, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(T scalar) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(scalar, 0, 0), col_type(0, scalar, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(scalar, 0, 0); + this->value[1] = col_type(0, scalar, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat + ( + T x0, T y0, T z0, + T x1, T y1, T z1 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0, z0), col_type(x1, y1, z1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0); + this->value[1] = col_type(x1, y1, z1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(col_type const& v0, col_type const& v1) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v0); + this->value[1] = col_type(v1); +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat + ( + X1 x1, Y1 y1, Z1 z1, + X2 x2, Y2 y2, Z2 z2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x1, y1, z1), col_type(x2, y2, z2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x1, y1, z1); + this->value[1] = col_type(x2, y2, z2); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(vec<3, V1, Q> const& v1, vec<3, V2, Q> const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); +# endif + } + + // -- Matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<2, 3, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 3, T, Q>::col_type & mat<2, 3, T, Q>::operator[](typename mat<2, 3, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 3, T, Q>::col_type const& mat<2, 3, T, Q>::operator[](typename mat<2, 3, T, Q>::length_type i) const GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>& mat<2, 3, T, Q>::operator=(mat<2, 3, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>& mat<2, 3, T, Q>::operator+=(mat<2, 3, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>& mat<2, 3, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>& mat<2, 3, T, Q>::operator-=(mat<2, 3, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>& mat<2, 3, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> mat<2, 3, T, Q>::operator++(int) + { + mat<2, 3, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> mat<2, 3, T, Q>::operator--(int) + { + mat<2, 3, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m) + { + return mat<2, 3, T, Q>( + -m[0], + -m[1]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m, T scalar) + { + return mat<2, 3, T, Q>( + m[0] + scalar, + m[1] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + return mat<2, 3, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m, T scalar) + { + return mat<2, 3, T, Q>( + m[0] - scalar, + m[1] - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + return mat<2, 3, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator*(mat<2, 3, T, Q> const& m, T scalar) + { + return mat<2, 3, T, Q>( + m[0] * scalar, + m[1] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator*(T scalar, mat<2, 3, T, Q> const& m) + { + return mat<2, 3, T, Q>( + m[0] * scalar, + m[1] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 3, T, Q>::col_type operator* + ( + mat<2, 3, T, Q> const& m, + typename mat<2, 3, T, Q>::row_type const& v) + { + return typename mat<2, 3, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y, + m[0][1] * v.x + m[1][1] * v.y, + m[0][2] * v.x + m[1][2] * v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 3, T, Q>::row_type operator* + ( + typename mat<2, 3, T, Q>::col_type const& v, + mat<2, 3, T, Q> const& m) + { + return typename mat<2, 3, T, Q>::row_type( + v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return mat<2, 3, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + T SrcA00 = m1[0][0]; + T SrcA01 = m1[0][1]; + T SrcA02 = m1[0][2]; + T SrcA10 = m1[1][0]; + T SrcA11 = m1[1][1]; + T SrcA12 = m1[1][2]; + + T SrcB00 = m2[0][0]; + T SrcB01 = m2[0][1]; + T SrcB10 = m2[1][0]; + T SrcB11 = m2[1][1]; + T SrcB20 = m2[2][0]; + T SrcB21 = m2[2][1]; + + mat<3, 3, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + return mat<4, 3, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1], + m1[0][2] * m2[3][0] + m1[1][2] * m2[3][1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator/(mat<2, 3, T, Q> const& m, T scalar) + { + return mat<2, 3, T, Q>( + m[0] / scalar, + m[1] / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator/(T scalar, mat<2, 3, T, Q> const& m) + { + return mat<2, 3, T, Q>( + scalar / m[0], + scalar / m[1]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]); + } +} //namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x4.hpp new file mode 100644 index 0000000..7ca43e5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x4.hpp @@ -0,0 +1,161 @@ +/// @ref core +/// @file glm/detail/type_mat2x4.hpp + +#pragma once + +#include "type_vec2.hpp" +#include "type_vec4.hpp" +#include +#include + +namespace glm +{ + template + struct mat<2, 4, T, Q> + { + typedef vec<4, T, Q> col_type; + typedef vec<2, T, Q> row_type; + typedef mat<2, 4, T, Q> type; + typedef mat<4, 2, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[2]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 2; } + + GLM_FUNC_DECL GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<2, 4, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T scalar); + GLM_CTOR_DECL mat( + T x0, T y0, T z0, T w0, + T x1, T y1, T z1, T w1); + GLM_CTOR_DECL mat( + col_type const& v0, + col_type const& v1); + + // -- Conversions -- + + template< + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2> + GLM_CTOR_DECL mat( + X1 x1, Y1 y1, Z1 z1, W1 w1, + X2 x2, Y2 y2, Z2 z2, W2 w2); + + template + GLM_CTOR_DECL mat( + vec<4, U, Q> const& v1, + vec<4, V, Q> const& v2); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator=(mat<2, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator+=(mat<2, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator-=(mat<2, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator++ (); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator-- (); + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator*(mat<2, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator*(T scalar, mat<2, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<2, 4, T, Q>::col_type operator*(mat<2, 4, T, Q> const& m, typename mat<2, 4, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<2, 4, T, Q>::row_type operator*(typename mat<2, 4, T, Q>::col_type const& v, mat<2, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator/(mat<2, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator/(T scalar, mat<2, 4, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat2x4.inl" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x4.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x4.inl new file mode 100644 index 0000000..1c182c9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x4.inl @@ -0,0 +1,520 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0, 0, 0), col_type(0, 1, 0, 0)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<2, 4, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(T s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0, 0, 0), col_type(0, s, 0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0, 0, 0); + this->value[1] = col_type(0, s, 0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat + ( + T x0, T y0, T z0, T w0, + T x1, T y1, T z1, T w1 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0, z0, w0), col_type(x1, y1, z1, w1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0, w0); + this->value[1] = col_type(x1, y1, z1, w1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(col_type const& v0, col_type const& v1) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat + ( + X1 x1, Y1 y1, Z1 z1, W1 w1, + X2 x2, Y2 y2, Z2 z2, W2 w2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{ + col_type(x1, y1, z1, w1), + col_type(x2, y2, z2, w2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x1, y1, z1, w1); + this->value[1] = col_type(x2, y2, z2, w2); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(vec<4, V1, Q> const& v1, vec<4, V2, Q> const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); +# endif + } + + // -- Matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<2, 4, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 4, T, Q>::col_type & mat<2, 4, T, Q>::operator[](typename mat<2, 4, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 4, T, Q>::col_type const& mat<2, 4, T, Q>::operator[](typename mat<2, 4, T, Q>::length_type i) const GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator=(mat<2, 4, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator+=(mat<2, 4, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator-=(mat<2, 4, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> & mat<2, 4, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> mat<2, 4, T, Q>::operator++(int) + { + mat<2, 4, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> mat<2, 4, T, Q>::operator--(int) + { + mat<2, 4, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m) + { + return mat<2, 4, T, Q>( + -m[0], + -m[1]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m, T scalar) + { + return mat<2, 4, T, Q>( + m[0] + scalar, + m[1] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + return mat<2, 4, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m, T scalar) + { + return mat<2, 4, T, Q>( + m[0] - scalar, + m[1] - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + return mat<2, 4, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator*(mat<2, 4, T, Q> const& m, T scalar) + { + return mat<2, 4, T, Q>( + m[0] * scalar, + m[1] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator*(T scalar, mat<2, 4, T, Q> const& m) + { + return mat<2, 4, T, Q>( + m[0] * scalar, + m[1] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 4, T, Q>::col_type operator*(mat<2, 4, T, Q> const& m, typename mat<2, 4, T, Q>::row_type const& v) + { + return typename mat<2, 4, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y, + m[0][1] * v.x + m[1][1] * v.y, + m[0][2] * v.x + m[1][2] * v.y, + m[0][3] * v.x + m[1][3] * v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 4, T, Q>::row_type operator*(typename mat<2, 4, T, Q>::col_type const& v, mat<2, 4, T, Q> const& m) + { + return typename mat<2, 4, T, Q>::row_type( + v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2] + v.w * m[0][3], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2] + v.w * m[1][3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + T SrcA00 = m1[0][0]; + T SrcA01 = m1[0][1]; + T SrcA02 = m1[0][2]; + T SrcA03 = m1[0][3]; + T SrcA10 = m1[1][0]; + T SrcA11 = m1[1][1]; + T SrcA12 = m1[1][2]; + T SrcA13 = m1[1][3]; + + T SrcB00 = m2[0][0]; + T SrcB01 = m2[0][1]; + T SrcB10 = m2[1][0]; + T SrcB11 = m2[1][1]; + T SrcB20 = m2[2][0]; + T SrcB21 = m2[2][1]; + T SrcB30 = m2[3][0]; + T SrcB31 = m2[3][1]; + + mat<4, 4, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01; + Result[0][3] = SrcA03 * SrcB00 + SrcA13 * SrcB01; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11; + Result[1][3] = SrcA03 * SrcB10 + SrcA13 * SrcB11; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21; + Result[2][3] = SrcA03 * SrcB20 + SrcA13 * SrcB21; + Result[3][0] = SrcA00 * SrcB30 + SrcA10 * SrcB31; + Result[3][1] = SrcA01 * SrcB30 + SrcA11 * SrcB31; + Result[3][2] = SrcA02 * SrcB30 + SrcA12 * SrcB31; + Result[3][3] = SrcA03 * SrcB30 + SrcA13 * SrcB31; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return mat<2, 4, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + return mat<3, 4, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1], + m1[0][3] * m2[2][0] + m1[1][3] * m2[2][1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator/(mat<2, 4, T, Q> const& m, T scalar) + { + return mat<2, 4, T, Q>( + m[0] / scalar, + m[1] / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator/(T scalar, mat<2, 4, T, Q> const& m) + { + return mat<2, 4, T, Q>( + scalar / m[0], + scalar / m[1]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]); + } +} //namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x2.hpp new file mode 100644 index 0000000..0249bef --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x2.hpp @@ -0,0 +1,167 @@ +/// @ref core +/// @file glm/detail/type_mat3x2.hpp + +#pragma once + +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include +#include + +namespace glm +{ + template + struct mat<3, 2, T, Q> + { + typedef vec<2, T, Q> col_type; + typedef vec<3, T, Q> row_type; + typedef mat<3, 2, T, Q> type; + typedef mat<2, 3, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[3]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 3; } + + GLM_FUNC_DECL GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<3, 2, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T scalar); + GLM_CTOR_DECL mat( + T x0, T y0, + T x1, T y1, + T x2, T y2); + GLM_CTOR_DECL mat( + col_type const& v0, + col_type const& v1, + col_type const& v2); + + // -- Conversions -- + + template< + typename X1, typename Y1, + typename X2, typename Y2, + typename X3, typename Y3> + GLM_CTOR_DECL mat( + X1 x1, Y1 y1, + X2 x2, Y2 y2, + X3 x3, Y3 y3); + + template + GLM_CTOR_DECL mat( + vec<2, V1, Q> const& v1, + vec<2, V2, Q> const& v2, + vec<2, V3, Q> const& v3); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator=(mat<3, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator+=(mat<3, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator-=(mat<3, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator++ (); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator-- (); + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator*(mat<3, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator*(T scalar, mat<3, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<3, 2, T, Q>::col_type operator*(mat<3, 2, T, Q> const& m, typename mat<3, 2, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<3, 2, T, Q>::row_type operator*(typename mat<3, 2, T, Q>::col_type const& v, mat<3, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator/(mat<3, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator/(T scalar, mat<3, 2, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat3x2.inl" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x2.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x2.inl new file mode 100644 index 0000000..cd9f46c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x2.inl @@ -0,0 +1,532 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0), col_type(0, 1), col_type(0, 0)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0); + this->value[1] = col_type(0, 1); + this->value[2] = col_type(0, 0); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<3, 2, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(T s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0), col_type(0, s), col_type(0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0); + this->value[1] = col_type(0, s); + this->value[2] = col_type(0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat + ( + T x0, T y0, + T x1, T y1, + T x2, T y2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0), col_type(x1, y1), col_type(x2, y2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); + this->value[2] = col_type(x2, y2); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(col_type const& v0, col_type const& v1, col_type const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X0, typename Y0, + typename X1, typename Y1, + typename X2, typename Y2> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat + ( + X0 x0, Y0 y0, + X1 x1, Y1 y1, + X2 x2, Y2 y2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0), col_type(x1, y1), col_type(x2, y2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); + this->value[2] = col_type(x2, y2); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(vec<2, V0, Q> const& v0, vec<2, V1, Q> const& v1, vec<2, V2, Q> const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v0); + this->value[1] = col_type(v1); + this->value[2] = col_type(v2); +# endif + } + + // -- Matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<3, 2, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 2, T, Q>::col_type & mat<3, 2, T, Q>::operator[](typename mat<3, 2, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 2, T, Q>::col_type const& mat<3, 2, T, Q>::operator[](typename mat<3, 2, T, Q>::length_type i) const GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator=(mat<3, 2, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator+=(mat<3, 2, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator-=(mat<3, 2, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> & mat<3, 2, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> mat<3, 2, T, Q>::operator++(int) + { + mat<3, 2, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> mat<3, 2, T, Q>::operator--(int) + { + mat<3, 2, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m) + { + return mat<3, 2, T, Q>( + -m[0], + -m[1], + -m[2]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m, T scalar) + { + return mat<3, 2, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + return mat<3, 2, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m, T scalar) + { + return mat<3, 2, T, Q>( + m[0] - scalar, + m[1] - scalar, + m[2] - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + return mat<3, 2, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator*(mat<3, 2, T, Q> const& m, T scalar) + { + return mat<3, 2, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator*(T scalar, mat<3, 2, T, Q> const& m) + { + return mat<3, 2, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 2, T, Q>::col_type operator*(mat<3, 2, T, Q> const& m, typename mat<3, 2, T, Q>::row_type const& v) + { + return typename mat<3, 2, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 2, T, Q>::row_type operator*(typename mat<3, 2, T, Q>::col_type const& v, mat<3, 2, T, Q> const& m) + { + return typename mat<3, 2, T, Q>::row_type( + v.x * m[0][0] + v.y * m[0][1], + v.x * m[1][0] + v.y * m[1][1], + v.x * m[2][0] + v.y * m[2][1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + const T SrcA00 = m1[0][0]; + const T SrcA01 = m1[0][1]; + const T SrcA10 = m1[1][0]; + const T SrcA11 = m1[1][1]; + const T SrcA20 = m1[2][0]; + const T SrcA21 = m1[2][1]; + + const T SrcB00 = m2[0][0]; + const T SrcB01 = m2[0][1]; + const T SrcB02 = m2[0][2]; + const T SrcB10 = m2[1][0]; + const T SrcB11 = m2[1][1]; + const T SrcB12 = m2[1][2]; + + mat<2, 2, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + return mat<3, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + return mat<4, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1] + m1[2][0] * m2[3][2], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1] + m1[2][1] * m2[3][2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator/(mat<3, 2, T, Q> const& m, T scalar) + { + return mat<3, 2, T, Q>( + m[0] / scalar, + m[1] / scalar, + m[2] / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator/(T scalar, mat<3, 2, T, Q> const& m) + { + return mat<3, 2, T, Q>( + scalar / m[0], + scalar / m[1], + scalar / m[2]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]); + } +} //namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x3.hpp new file mode 100644 index 0000000..e4cbbdc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x3.hpp @@ -0,0 +1,184 @@ +/// @ref core +/// @file glm/detail/type_mat3x3.hpp + +#pragma once + +#include "type_vec3.hpp" +#include +#include + +namespace glm +{ + template + struct mat<3, 3, T, Q> + { + typedef vec<3, T, Q> col_type; + typedef vec<3, T, Q> row_type; + typedef mat<3, 3, T, Q> type; + typedef mat<3, 3, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[3]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 3; } + + GLM_FUNC_DECL GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<3, 3, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T scalar); + GLM_CTOR_DECL mat( + T x0, T y0, T z0, + T x1, T y1, T z1, + T x2, T y2, T z2); + GLM_CTOR_DECL mat( + col_type const& v0, + col_type const& v1, + col_type const& v2); + + // -- Conversions -- + + template< + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3> + GLM_CTOR_DECL mat( + X1 x1, Y1 y1, Z1 z1, + X2 x2, Y2 y2, Z2 z2, + X3 x3, Y3 y3, Z3 z3); + + template + GLM_CTOR_DECL mat( + vec<3, V1, Q> const& v1, + vec<3, V2, Q> const& v2, + vec<3, V3, Q> const& v3); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator=(mat<3, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator+=(mat<3, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator-=(mat<3, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator*=(mat<3, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator/=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator/=(mat<3, 3, U, Q> const& m); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator++(); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator+(T scalar, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator-(T scalar, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator*(mat<3, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator*(T scalar, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<3, 3, T, Q>::col_type operator*(mat<3, 3, T, Q> const& m, typename mat<3, 3, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<3, 3, T, Q>::row_type operator*(typename mat<3, 3, T, Q>::col_type const& v, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator/(mat<3, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator/(T scalar, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<3, 3, T, Q>::col_type operator/(mat<3, 3, T, Q> const& m, typename mat<3, 3, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<3, 3, T, Q>::row_type operator/(typename mat<3, 3, T, Q>::col_type const& v, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator/(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat3x3.inl" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x3.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x3.inl new file mode 100644 index 0000000..a9b633a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x3.inl @@ -0,0 +1,601 @@ +#include "../matrix.hpp" + +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0, 0), col_type(0, 1, 0), col_type(0, 0, 1)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0, 0); + this->value[1] = col_type(0, 1, 0); + this->value[2] = col_type(0, 0, 1); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<3, 3, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(T s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0, 0), col_type(0, s, 0), col_type(0, 0, s)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0, 0); + this->value[1] = col_type(0, s, 0); + this->value[2] = col_type(0, 0, s); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat + ( + T x0, T y0, T z0, + T x1, T y1, T z1, + T x2, T y2, T z2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0, z0), col_type(x1, y1, z1), col_type(x2, y2, z2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0); + this->value[1] = col_type(x1, y1, z1); + this->value[2] = col_type(x2, y2, z2); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(col_type const& v0, col_type const& v1, col_type const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v0); + this->value[1] = col_type(v1); + this->value[2] = col_type(v2); +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat + ( + X1 x1, Y1 y1, Z1 z1, + X2 x2, Y2 y2, Z2 z2, + X3 x3, Y3 y3, Z3 z3 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x1, y1, z1), col_type(x2, y2, z2), col_type(x3, y3, z3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x1, y1, z1); + this->value[1] = col_type(x2, y2, z2); + this->value[2] = col_type(x3, y3, z3); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(vec<3, V1, Q> const& v1, vec<3, V2, Q> const& v2, vec<3, V3, Q> const& v3) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v1), col_type(v2), col_type(v3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); +# endif + } + + // -- Matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<3, 3, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 3, T, Q>::col_type & mat<3, 3, T, Q>::operator[](typename mat<3, 3, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 3, T, Q>::col_type const& mat<3, 3, T, Q>::operator[](typename mat<3, 3, T, Q>::length_type i) const GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator=(mat<3, 3, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator+=(mat<3, 3, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator-=(mat<3, 3, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator*=(mat<3, 3, U, Q> const& m) + { + return (*this = *this * m); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator/=(mat<3, 3, U, Q> const& m) + { + return *this *= inverse(m); + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> mat<3, 3, T, Q>::operator++(int) + { + mat<3, 3, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> mat<3, 3, T, Q>::operator--(int) + { + mat<3, 3, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m) + { + return mat<3, 3, T, Q>( + -m[0], + -m[1], + -m[2]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m, T scalar) + { + return mat<3, 3, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator+(T scalar, mat<3, 3, T, Q> const& m) + { + return mat<3, 3, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + return mat<3, 3, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m, T scalar) + { + return mat<3, 3, T, Q>( + m[0] - scalar, + m[1] - scalar, + m[2] - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator-(T scalar, mat<3, 3, T, Q> const& m) + { + return mat<3, 3, T, Q>( + scalar - m[0], + scalar - m[1], + scalar - m[2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + return mat<3, 3, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator*(mat<3, 3, T, Q> const& m, T scalar) + { + return mat<3, 3, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator*(T scalar, mat<3, 3, T, Q> const& m) + { + return mat<3, 3, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 3, T, Q>::col_type operator*(mat<3, 3, T, Q> const& m, typename mat<3, 3, T, Q>::row_type const& v) + { + return typename mat<3, 3, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z, + m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 3, T, Q>::row_type operator*(typename mat<3, 3, T, Q>::col_type const& v, mat<3, 3, T, Q> const& m) + { + return typename mat<3, 3, T, Q>::row_type( + m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z, + m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z, + m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + T const SrcA00 = m1[0][0]; + T const SrcA01 = m1[0][1]; + T const SrcA02 = m1[0][2]; + T const SrcA10 = m1[1][0]; + T const SrcA11 = m1[1][1]; + T const SrcA12 = m1[1][2]; + T const SrcA20 = m1[2][0]; + T const SrcA21 = m1[2][1]; + T const SrcA22 = m1[2][2]; + + T const SrcB00 = m2[0][0]; + T const SrcB01 = m2[0][1]; + T const SrcB02 = m2[0][2]; + T const SrcB10 = m2[1][0]; + T const SrcB11 = m2[1][1]; + T const SrcB12 = m2[1][2]; + T const SrcB20 = m2[2][0]; + T const SrcB21 = m2[2][1]; + T const SrcB22 = m2[2][2]; + + mat<3, 3, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01 + SrcA22 * SrcB02; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11 + SrcA22 * SrcB12; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21 + SrcA20 * SrcB22; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21 + SrcA21 * SrcB22; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21 + SrcA22 * SrcB22; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + return mat<2, 3, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + return mat<4, 3, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1] + m1[2][0] * m2[3][2], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1] + m1[2][1] * m2[3][2], + m1[0][2] * m2[3][0] + m1[1][2] * m2[3][1] + m1[2][2] * m2[3][2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator/(mat<3, 3, T, Q> const& m, T scalar) + { + return mat<3, 3, T, Q>( + m[0] / scalar, + m[1] / scalar, + m[2] / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator/(T scalar, mat<3, 3, T, Q> const& m) + { + return mat<3, 3, T, Q>( + scalar / m[0], + scalar / m[1], + scalar / m[2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 3, T, Q>::col_type operator/(mat<3, 3, T, Q> const& m, typename mat<3, 3, T, Q>::row_type const& v) + { + return inverse(m) * v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 3, T, Q>::row_type operator/(typename mat<3, 3, T, Q>::col_type const& v, mat<3, 3, T, Q> const& m) + { + return v * inverse(m); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator/(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + mat<3, 3, T, Q> m1_copy(m1); + return m1_copy /= m2; + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]); + } +} //namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x4.hpp new file mode 100644 index 0000000..f9913d2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x4.hpp @@ -0,0 +1,166 @@ +/// @ref core +/// @file glm/detail/type_mat3x4.hpp + +#pragma once + +#include "type_vec3.hpp" +#include "type_vec4.hpp" +#include +#include + +namespace glm +{ + template + struct mat<3, 4, T, Q> + { + typedef vec<4, T, Q> col_type; + typedef vec<3, T, Q> row_type; + typedef mat<3, 4, T, Q> type; + typedef mat<4, 3, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[3]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 3; } + + GLM_FUNC_DECL GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<3, 4, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T scalar); + GLM_CTOR_DECL mat( + T x0, T y0, T z0, T w0, + T x1, T y1, T z1, T w1, + T x2, T y2, T z2, T w2); + GLM_CTOR_DECL mat( + col_type const& v0, + col_type const& v1, + col_type const& v2); + + // -- Conversions -- + + template< + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2, + typename X3, typename Y3, typename Z3, typename W3> + GLM_CTOR_DECL mat( + X1 x1, Y1 y1, Z1 z1, W1 w1, + X2 x2, Y2 y2, Z2 z2, W2 w2, + X3 x3, Y3 y3, Z3 z3, W3 w3); + + template + GLM_CTOR_DECL mat( + vec<4, V1, Q> const& v1, + vec<4, V2, Q> const& v2, + vec<4, V3, Q> const& v3); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator=(mat<3, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator+=(mat<3, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator-=(mat<3, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator++(); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator*(mat<3, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator*(T scalar, mat<3, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<3, 4, T, Q>::col_type operator*(mat<3, 4, T, Q> const& m, typename mat<3, 4, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<3, 4, T, Q>::row_type operator*(typename mat<3, 4, T, Q>::col_type const& v, mat<3, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator/(mat<3, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator/(T scalar, mat<3, 4, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat3x4.inl" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x4.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x4.inl new file mode 100644 index 0000000..209e9d9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x4.inl @@ -0,0 +1,578 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0, 0, 0), col_type(0, 1, 0, 0), col_type(0, 0, 1, 0)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(0, 0, 1, 0); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<3, 4, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(T s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0, 0, 0), col_type(0, s, 0, 0), col_type(0, 0, s, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0, 0, 0); + this->value[1] = col_type(0, s, 0, 0); + this->value[2] = col_type(0, 0, s, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat + ( + T x0, T y0, T z0, T w0, + T x1, T y1, T z1, T w1, + T x2, T y2, T z2, T w2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{ + col_type(x0, y0, z0, w0), + col_type(x1, y1, z1, w1), + col_type(x2, y2, z2, w2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0, w0); + this->value[1] = col_type(x1, y1, z1, w1); + this->value[2] = col_type(x2, y2, z2, w2); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(col_type const& v0, col_type const& v1, col_type const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X0, typename Y0, typename Z0, typename W0, + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat + ( + X0 x0, Y0 y0, Z0 z0, W0 w0, + X1 x1, Y1 y1, Z1 z1, W1 w1, + X2 x2, Y2 y2, Z2 z2, W2 w2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{ + col_type(x0, y0, z0, w0), + col_type(x1, y1, z1, w1), + col_type(x2, y2, z2, w2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0, w0); + this->value[1] = col_type(x1, y1, z1, w1); + this->value[2] = col_type(x2, y2, z2, w2); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(vec<4, V1, Q> const& v0, vec<4, V2, Q> const& v1, vec<4, V3, Q> const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v0); + this->value[1] = col_type(v1); + this->value[2] = col_type(v2); +# endif + } + + // -- Matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<3, 4, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0), col_type(0, 0, 1, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(0, 0, 1, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(0, 0, 1, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(0, 0, 1, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0), col_type(m[2], 1, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(m[2], 1, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0, 0, 1, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0), col_type(m[2], 1, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(m[2], 1, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 0); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 4, T, Q>::col_type & mat<3, 4, T, Q>::operator[](typename mat<3, 4, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 4, T, Q>::col_type const& mat<3, 4, T, Q>::operator[](typename mat<3, 4, T, Q>::length_type i) const GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator=(mat<3, 4, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator+=(mat<3, 4, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator-=(mat<3, 4, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> & mat<3, 4, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> mat<3, 4, T, Q>::operator++(int) + { + mat<3, 4, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> mat<3, 4, T, Q>::operator--(int) + { + mat<3, 4, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m) + { + return mat<3, 4, T, Q>( + -m[0], + -m[1], + -m[2]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m, T scalar) + { + return mat<3, 4, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + return mat<3, 4, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m, T scalar) + { + return mat<3, 4, T, Q>( + m[0] - scalar, + m[1] - scalar, + m[2] - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + return mat<3, 4, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator*(mat<3, 4, T, Q> const& m, T scalar) + { + return mat<3, 4, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator*(T scalar, mat<3, 4, T, Q> const& m) + { + return mat<3, 4, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 4, T, Q>::col_type operator* + ( + mat<3, 4, T, Q> const& m, + typename mat<3, 4, T, Q>::row_type const& v + ) + { + return typename mat<3, 4, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z, + m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z, + m[0][3] * v.x + m[1][3] * v.y + m[2][3] * v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 4, T, Q>::row_type operator* + ( + typename mat<3, 4, T, Q>::col_type const& v, + mat<3, 4, T, Q> const& m + ) + { + return typename mat<3, 4, T, Q>::row_type( + v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2] + v.w * m[0][3], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2] + v.w * m[1][3], + v.x * m[2][0] + v.y * m[2][1] + v.z * m[2][2] + v.w * m[2][3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + const T SrcA00 = m1[0][0]; + const T SrcA01 = m1[0][1]; + const T SrcA02 = m1[0][2]; + const T SrcA03 = m1[0][3]; + const T SrcA10 = m1[1][0]; + const T SrcA11 = m1[1][1]; + const T SrcA12 = m1[1][2]; + const T SrcA13 = m1[1][3]; + const T SrcA20 = m1[2][0]; + const T SrcA21 = m1[2][1]; + const T SrcA22 = m1[2][2]; + const T SrcA23 = m1[2][3]; + + const T SrcB00 = m2[0][0]; + const T SrcB01 = m2[0][1]; + const T SrcB02 = m2[0][2]; + const T SrcB10 = m2[1][0]; + const T SrcB11 = m2[1][1]; + const T SrcB12 = m2[1][2]; + const T SrcB20 = m2[2][0]; + const T SrcB21 = m2[2][1]; + const T SrcB22 = m2[2][2]; + const T SrcB30 = m2[3][0]; + const T SrcB31 = m2[3][1]; + const T SrcB32 = m2[3][2]; + + mat<4, 4, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01 + SrcA22 * SrcB02; + Result[0][3] = SrcA03 * SrcB00 + SrcA13 * SrcB01 + SrcA23 * SrcB02; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11 + SrcA22 * SrcB12; + Result[1][3] = SrcA03 * SrcB10 + SrcA13 * SrcB11 + SrcA23 * SrcB12; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21 + SrcA20 * SrcB22; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21 + SrcA21 * SrcB22; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21 + SrcA22 * SrcB22; + Result[2][3] = SrcA03 * SrcB20 + SrcA13 * SrcB21 + SrcA23 * SrcB22; + Result[3][0] = SrcA00 * SrcB30 + SrcA10 * SrcB31 + SrcA20 * SrcB32; + Result[3][1] = SrcA01 * SrcB30 + SrcA11 * SrcB31 + SrcA21 * SrcB32; + Result[3][2] = SrcA02 * SrcB30 + SrcA12 * SrcB31 + SrcA22 * SrcB32; + Result[3][3] = SrcA03 * SrcB30 + SrcA13 * SrcB31 + SrcA23 * SrcB32; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + return mat<2, 4, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + return mat<3, 4, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2], + m1[0][3] * m2[2][0] + m1[1][3] * m2[2][1] + m1[2][3] * m2[2][2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator/(mat<3, 4, T, Q> const& m, T scalar) + { + return mat<3, 4, T, Q>( + m[0] / scalar, + m[1] / scalar, + m[2] / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator/(T scalar, mat<3, 4, T, Q> const& m) + { + return mat<3, 4, T, Q>( + scalar / m[0], + scalar / m[1], + scalar / m[2]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]); + } +} //namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x2.hpp new file mode 100644 index 0000000..7057d4c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x2.hpp @@ -0,0 +1,171 @@ +/// @ref core +/// @file glm/detail/type_mat4x2.hpp + +#pragma once + +#include "type_vec2.hpp" +#include "type_vec4.hpp" +#include +#include + +namespace glm +{ + template + struct mat<4, 2, T, Q> + { + typedef vec<2, T, Q> col_type; + typedef vec<4, T, Q> row_type; + typedef mat<4, 2, T, Q> type; + typedef mat<2, 4, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[4]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 4; } + + GLM_FUNC_DECL GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<4, 2, T, P> const& m); + + GLM_CTOR_DECL mat(T scalar); + GLM_CTOR_DECL mat( + T x0, T y0, + T x1, T y1, + T x2, T y2, + T x3, T y3); + GLM_CTOR_DECL mat( + col_type const& v0, + col_type const& v1, + col_type const& v2, + col_type const& v3); + + // -- Conversions -- + + template< + typename X0, typename Y0, + typename X1, typename Y1, + typename X2, typename Y2, + typename X3, typename Y3> + GLM_CTOR_DECL mat( + X0 x0, Y0 y0, + X1 x1, Y1 y1, + X2 x2, Y2 y2, + X3 x3, Y3 y3); + + template + GLM_CTOR_DECL mat( + vec<2, V1, Q> const& v1, + vec<2, V2, Q> const& v2, + vec<2, V3, Q> const& v3, + vec<2, V4, Q> const& v4); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL mat(mat<4, 2, U, P> const& m); + + GLM_CTOR_DECL mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL mat(mat<4, 3, T, Q> const& x); + GLM_CTOR_DECL mat(mat<3, 4, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator=(mat<4, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator+=(mat<4, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator-=(mat<4, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator++ (); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator-- (); + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator*(mat<4, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator*(T scalar, mat<4, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<4, 2, T, Q>::col_type operator*(mat<4, 2, T, Q> const& m, typename mat<4, 2, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<4, 2, T, Q>::row_type operator*(typename mat<4, 2, T, Q>::col_type const& v, mat<4, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator/(mat<4, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator/(T scalar, mat<4, 2, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat4x2.inl" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x2.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x2.inl new file mode 100644 index 0000000..2b9b617 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x2.inl @@ -0,0 +1,574 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0), col_type(0, 1), col_type(0, 0), col_type(0, 0)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0); + this->value[1] = col_type(0, 1); + this->value[2] = col_type(0, 0); + this->value[3] = col_type(0, 0); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<4, 2, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(T s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0), col_type(0, s), col_type(0, 0), col_type(0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0); + this->value[1] = col_type(0, s); + this->value[2] = col_type(0, 0); + this->value[3] = col_type(0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat + ( + T x0, T y0, + T x1, T y1, + T x2, T y2, + T x3, T y3 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0), col_type(x1, y1), col_type(x2, y2), col_type(x3, y3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); + this->value[2] = col_type(x2, y2); + this->value[3] = col_type(x3, y3); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(col_type const& v0, col_type const& v1, col_type const& v2, col_type const& v3) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2), col_type(v3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + this->value[3] = v3; +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X0, typename Y0, + typename X1, typename Y1, + typename X2, typename Y2, + typename X3, typename Y3> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat + ( + X0 x0, Y0 y0, + X1 x1, Y1 y1, + X2 x2, Y2 y2, + X3 x3, Y3 y3 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0), col_type(x1, y1), col_type(x2, y2), col_type(x3, y3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); + this->value[2] = col_type(x2, y2); + this->value[3] = col_type(x3, y3); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(vec<2, V0, Q> const& v0, vec<2, V1, Q> const& v1, vec<2, V2, Q> const& v2, vec<2, V3, Q> const& v3) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2), col_type(v3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v0); + this->value[1] = col_type(v1); + this->value[2] = col_type(v2); + this->value[3] = col_type(v3); +# endif + } + + // -- Conversion -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<4, 2, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 2, T, Q>::col_type & mat<4, 2, T, Q>::operator[](typename mat<4, 2, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 2, T, Q>::col_type const& mat<4, 2, T, Q>::operator[](typename mat<4, 2, T, Q>::length_type i) const GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>& mat<4, 2, T, Q>::operator=(mat<4, 2, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + this->value[3] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator+=(mat<4, 2, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + this->value[3] += m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + this->value[3] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator-=(mat<4, 2, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + this->value[3] -= m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + this->value[3] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + this->value[3] /= s; + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + ++this->value[3]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + --this->value[3]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> mat<4, 2, T, Q>::operator++(int) + { + mat<4, 2, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> mat<4, 2, T, Q>::operator--(int) + { + mat<4, 2, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m) + { + return mat<4, 2, T, Q>( + -m[0], + -m[1], + -m[2], + -m[3]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m, T scalar) + { + return mat<4, 2, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar, + m[3] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + return mat<4, 2, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2], + m1[3] + m2[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m, T scalar) + { + return mat<4, 2, T, Q>( + m[0] - scalar, + m[1] - scalar, + m[2] - scalar, + m[3] - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + return mat<4, 2, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2], + m1[3] - m2[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator*(mat<4, 2, T, Q> const& m, T scalar) + { + return mat<4, 2, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar, + m[3] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator*(T scalar, mat<4, 2, T, Q> const& m) + { + return mat<4, 2, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar, + m[3] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 2, T, Q>::col_type operator*(mat<4, 2, T, Q> const& m, typename mat<4, 2, T, Q>::row_type const& v) + { + return typename mat<4, 2, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z + m[3][0] * v.w, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z + m[3][1] * v.w); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 2, T, Q>::row_type operator*(typename mat<4, 2, T, Q>::col_type const& v, mat<4, 2, T, Q> const& m) + { + return typename mat<4, 2, T, Q>::row_type( + v.x * m[0][0] + v.y * m[0][1], + v.x * m[1][0] + v.y * m[1][1], + v.x * m[2][0] + v.y * m[2][1], + v.x * m[3][0] + v.y * m[3][1]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + T const SrcA00 = m1[0][0]; + T const SrcA01 = m1[0][1]; + T const SrcA10 = m1[1][0]; + T const SrcA11 = m1[1][1]; + T const SrcA20 = m1[2][0]; + T const SrcA21 = m1[2][1]; + T const SrcA30 = m1[3][0]; + T const SrcA31 = m1[3][1]; + + T const SrcB00 = m2[0][0]; + T const SrcB01 = m2[0][1]; + T const SrcB02 = m2[0][2]; + T const SrcB03 = m2[0][3]; + T const SrcB10 = m2[1][0]; + T const SrcB11 = m2[1][1]; + T const SrcB12 = m2[1][2]; + T const SrcB13 = m2[1][3]; + + mat<2, 2, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02 + SrcA30 * SrcB03; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02 + SrcA31 * SrcB03; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12 + SrcA30 * SrcB13; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12 + SrcA31 * SrcB13; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + return mat<3, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + return mat<4, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1] + m1[2][0] * m2[3][2] + m1[3][0] * m2[3][3], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1] + m1[2][1] * m2[3][2] + m1[3][1] * m2[3][3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator/(mat<4, 2, T, Q> const& m, T scalar) + { + return mat<4, 2, T, Q>( + m[0] / scalar, + m[1] / scalar, + m[2] / scalar, + m[3] / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q> operator/(T scalar, mat<4, 2, T, Q> const& m) + { + return mat<4, 2, T, Q>( + scalar / m[0], + scalar / m[1], + scalar / m[2], + scalar / m[3]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]) && (m1[3] == m2[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]) || (m1[3] != m2[3]); + } +} //namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x3.hpp new file mode 100644 index 0000000..52a38d8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x3.hpp @@ -0,0 +1,171 @@ +/// @ref core +/// @file glm/detail/type_mat4x3.hpp + +#pragma once + +#include "type_vec3.hpp" +#include "type_vec4.hpp" +#include +#include + +namespace glm +{ + template + struct mat<4, 3, T, Q> + { + typedef vec<3, T, Q> col_type; + typedef vec<4, T, Q> row_type; + typedef mat<4, 3, T, Q> type; + typedef mat<3, 4, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[4]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 4; } + + GLM_FUNC_DECL GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<4, 3, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T s); + GLM_CTOR_DECL mat( + T const& x0, T const& y0, T const& z0, + T const& x1, T const& y1, T const& z1, + T const& x2, T const& y2, T const& z2, + T const& x3, T const& y3, T const& z3); + GLM_CTOR_DECL mat( + col_type const& v0, + col_type const& v1, + col_type const& v2, + col_type const& v3); + + // -- Conversions -- + + template< + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3, + typename X4, typename Y4, typename Z4> + GLM_CTOR_DECL mat( + X1 const& x1, Y1 const& y1, Z1 const& z1, + X2 const& x2, Y2 const& y2, Z2 const& z2, + X3 const& x3, Y3 const& y3, Z3 const& z3, + X4 const& x4, Y4 const& y4, Z4 const& z4); + + template + GLM_CTOR_DECL mat( + vec<3, V1, Q> const& v1, + vec<3, V2, Q> const& v2, + vec<3, V3, Q> const& v3, + vec<3, V4, Q> const& v4); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL mat(mat<4, 3, U, P> const& m); + + GLM_CTOR_DECL mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL mat(mat<3, 4, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator=(mat<4, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator+=(mat<4, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator-=(mat<4, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q>& operator++(); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q>& operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator*(T scalar, mat<4, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<4, 3, T, Q>::col_type operator*(mat<4, 3, T, Q> const& m, typename mat<4, 3, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<4, 3, T, Q>::row_type operator*(typename mat<4, 3, T, Q>::col_type const& v, mat<4, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator/(mat<4, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator/(T scalar, mat<4, 3, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat4x3.inl" +#endif //GLM_EXTERNAL_TEMPLATE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x3.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x3.inl new file mode 100644 index 0000000..8430bc0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x3.inl @@ -0,0 +1,598 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0, 0), col_type(0, 1, 0), col_type(0, 0, 1), col_type(0, 0, 0)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0, 0); + this->value[1] = col_type(0, 1, 0); + this->value[2] = col_type(0, 0, 1); + this->value[3] = col_type(0, 0, 0); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<4, 3, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(T s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0, 0), col_type(0, s, 0), col_type(0, 0, s), col_type(0, 0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0, 0); + this->value[1] = col_type(0, s, 0); + this->value[2] = col_type(0, 0, s); + this->value[3] = col_type(0, 0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat + ( + T const& x0, T const& y0, T const& z0, + T const& x1, T const& y1, T const& z1, + T const& x2, T const& y2, T const& z2, + T const& x3, T const& y3, T const& z3 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0, z0), col_type(x1, y1, z1), col_type(x2, y2, z2), col_type(x3, y3, z3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0); + this->value[1] = col_type(x1, y1, z1); + this->value[2] = col_type(x2, y2, z2); + this->value[3] = col_type(x3, y3, z3); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(col_type const& v0, col_type const& v1, col_type const& v2, col_type const& v3) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2), col_type(v3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + this->value[3] = v3; +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X0, typename Y0, typename Z0, + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat + ( + X0 const& x0, Y0 const& y0, Z0 const& z0, + X1 const& x1, Y1 const& y1, Z1 const& z1, + X2 const& x2, Y2 const& y2, Z2 const& z2, + X3 const& x3, Y3 const& y3, Z3 const& z3 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0, z0), col_type(x1, y1, z1), col_type(x2, y2, z2), col_type(x3, y3, z3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0); + this->value[1] = col_type(x1, y1, z1); + this->value[2] = col_type(x2, y2, z2); + this->value[3] = col_type(x3, y3, z3); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(vec<3, V1, Q> const& v1, vec<3, V2, Q> const& v2, vec<3, V3, Q> const& v3, vec<3, V4, Q> const& v4) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v1), col_type(v2), col_type(v3), col_type(v4)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); + this->value[3] = col_type(v4); +# endif + } + + // -- Matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<4, 3, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(0, 0, 1), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(0, 0, 1); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0, 0, 1), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 1), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0, 0, 1), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 1), col_type(m[3], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); + this->value[3] = col_type(m[3], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 3, T, Q>::col_type & mat<4, 3, T, Q>::operator[](typename mat<4, 3, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 3, T, Q>::col_type const& mat<4, 3, T, Q>::operator[](typename mat<4, 3, T, Q>::length_type i) const GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>& mat<4, 3, T, Q>::operator=(mat<4, 3, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + this->value[3] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator+=(mat<4, 3, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + this->value[3] += m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + this->value[3] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator-=(mat<4, 3, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + this->value[3] -= m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + this->value[3] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + this->value[3] /= s; + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + ++this->value[3]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + --this->value[3]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> mat<4, 3, T, Q>::operator++(int) + { + mat<4, 3, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> mat<4, 3, T, Q>::operator--(int) + { + mat<4, 3, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m) + { + return mat<4, 3, T, Q>( + -m[0], + -m[1], + -m[2], + -m[3]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m, T scalar) + { + return mat<4, 3, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar, + m[3] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + return mat<4, 3, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2], + m1[3] + m2[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m, T scalar) + { + return mat<4, 3, T, Q>( + m[0] - scalar, + m[1] - scalar, + m[2] - scalar, + m[3] - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + return mat<4, 3, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2], + m1[3] - m2[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m, T scalar) + { + return mat<4, 3, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar, + m[3] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator*(T scalar, mat<4, 3, T, Q> const& m) + { + return mat<4, 3, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar, + m[3] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 3, T, Q>::col_type operator* + ( + mat<4, 3, T, Q> const& m, + typename mat<4, 3, T, Q>::row_type const& v) + { + return typename mat<4, 3, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z + m[3][0] * v.w, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z + m[3][1] * v.w, + m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z + m[3][2] * v.w); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 3, T, Q>::row_type operator* + ( + typename mat<4, 3, T, Q>::col_type const& v, + mat<4, 3, T, Q> const& m) + { + return typename mat<4, 3, T, Q>::row_type( + v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2], + v.x * m[2][0] + v.y * m[2][1] + v.z * m[2][2], + v.x * m[3][0] + v.y * m[3][1] + v.z * m[3][2]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + return mat<2, 3, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + T const SrcA00 = m1[0][0]; + T const SrcA01 = m1[0][1]; + T const SrcA02 = m1[0][2]; + T const SrcA10 = m1[1][0]; + T const SrcA11 = m1[1][1]; + T const SrcA12 = m1[1][2]; + T const SrcA20 = m1[2][0]; + T const SrcA21 = m1[2][1]; + T const SrcA22 = m1[2][2]; + T const SrcA30 = m1[3][0]; + T const SrcA31 = m1[3][1]; + T const SrcA32 = m1[3][2]; + + T const SrcB00 = m2[0][0]; + T const SrcB01 = m2[0][1]; + T const SrcB02 = m2[0][2]; + T const SrcB03 = m2[0][3]; + T const SrcB10 = m2[1][0]; + T const SrcB11 = m2[1][1]; + T const SrcB12 = m2[1][2]; + T const SrcB13 = m2[1][3]; + T const SrcB20 = m2[2][0]; + T const SrcB21 = m2[2][1]; + T const SrcB22 = m2[2][2]; + T const SrcB23 = m2[2][3]; + + mat<3, 3, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02 + SrcA30 * SrcB03; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02 + SrcA31 * SrcB03; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01 + SrcA22 * SrcB02 + SrcA32 * SrcB03; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12 + SrcA30 * SrcB13; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12 + SrcA31 * SrcB13; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11 + SrcA22 * SrcB12 + SrcA32 * SrcB13; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21 + SrcA20 * SrcB22 + SrcA30 * SrcB23; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21 + SrcA21 * SrcB22 + SrcA31 * SrcB23; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21 + SrcA22 * SrcB22 + SrcA32 * SrcB23; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + return mat<4, 3, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2] + m1[3][2] * m2[2][3], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1] + m1[2][0] * m2[3][2] + m1[3][0] * m2[3][3], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1] + m1[2][1] * m2[3][2] + m1[3][1] * m2[3][3], + m1[0][2] * m2[3][0] + m1[1][2] * m2[3][1] + m1[2][2] * m2[3][2] + m1[3][2] * m2[3][3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator/(mat<4, 3, T, Q> const& m, T scalar) + { + return mat<4, 3, T, Q>( + m[0] / scalar, + m[1] / scalar, + m[2] / scalar, + m[3] / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator/(T scalar, mat<4, 3, T, Q> const& m) + { + return mat<4, 3, T, Q>( + scalar / m[0], + scalar / m[1], + scalar / m[2], + scalar / m[3]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]) && (m1[3] == m2[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]) || (m1[3] != m2[3]); + } +} //namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x4.hpp new file mode 100644 index 0000000..ad7597b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x4.hpp @@ -0,0 +1,189 @@ +/// @ref core +/// @file glm/detail/type_mat4x4.hpp + +#pragma once + +#include "type_vec4.hpp" +#include +#include + +namespace glm +{ + template + struct mat<4, 4, T, Q> + { + typedef vec<4, T, Q> col_type; + typedef vec<4, T, Q> row_type; + typedef mat<4, 4, T, Q> type; + typedef mat<4, 4, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[4]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 4;} + + GLM_FUNC_DECL GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<4, 4, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T s); + GLM_CTOR_DECL mat( + T const& x0, T const& y0, T const& z0, T const& w0, + T const& x1, T const& y1, T const& z1, T const& w1, + T const& x2, T const& y2, T const& z2, T const& w2, + T const& x3, T const& y3, T const& z3, T const& w3); + GLM_CTOR_DECL mat( + col_type const& v0, + col_type const& v1, + col_type const& v2, + col_type const& v3); + + // -- Conversions -- + + template< + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2, + typename X3, typename Y3, typename Z3, typename W3, + typename X4, typename Y4, typename Z4, typename W4> + GLM_CTOR_DECL mat( + X1 const& x1, Y1 const& y1, Z1 const& z1, W1 const& w1, + X2 const& x2, Y2 const& y2, Z2 const& z2, W2 const& w2, + X3 const& x3, Y3 const& y3, Z3 const& z3, W3 const& w3, + X4 const& x4, Y4 const& y4, Z4 const& z4, W4 const& w4); + + template + GLM_CTOR_DECL mat( + vec<4, V1, Q> const& v1, + vec<4, V2, Q> const& v2, + vec<4, V3, Q> const& v3, + vec<4, V4, Q> const& v4); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator=(mat<4, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator+=(mat<4, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator-=(mat<4, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator*=(mat<4, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator/=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator/=(mat<4, 4, U, Q> const& m); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator++(); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator+(T scalar, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator-(T scalar, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator*(T scalar, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<4, 4, T, Q>::col_type operator*(mat<4, 4, T, Q> const& m, typename mat<4, 4, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<4, 4, T, Q>::row_type operator*(typename mat<4, 4, T, Q>::col_type const& v, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator/(T scalar, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<4, 4, T, Q>::col_type operator/(mat<4, 4, T, Q> const& m, typename mat<4, 4, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR typename mat<4, 4, T, Q>::row_type operator/(typename mat<4, 4, T, Q>::col_type const& v, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat4x4.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x4.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x4.inl new file mode 100644 index 0000000..116731d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x4.inl @@ -0,0 +1,706 @@ +#include "../matrix.hpp" + +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0, 0, 0), col_type(0, 1, 0, 0), col_type(0, 0, 1, 0), col_type(0, 0, 0, 1)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<4, 4, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(T s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0, 0, 0), col_type(0, s, 0, 0), col_type(0, 0, s, 0), col_type(0, 0, 0, s)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0, 0, 0); + this->value[1] = col_type(0, s, 0, 0); + this->value[2] = col_type(0, 0, s, 0); + this->value[3] = col_type(0, 0, 0, s); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat + ( + T const& x0, T const& y0, T const& z0, T const& w0, + T const& x1, T const& y1, T const& z1, T const& w1, + T const& x2, T const& y2, T const& z2, T const& w2, + T const& x3, T const& y3, T const& z3, T const& w3 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{ + col_type(x0, y0, z0, w0), + col_type(x1, y1, z1, w1), + col_type(x2, y2, z2, w2), + col_type(x3, y3, z3, w3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0, w0); + this->value[1] = col_type(x1, y1, z1, w1); + this->value[2] = col_type(x2, y2, z2, w2); + this->value[3] = col_type(x3, y3, z3, w3); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(col_type const& v0, col_type const& v1, col_type const& v2, col_type const& v3) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2), col_type(v3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + this->value[3] = v3; +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<4, 4, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); +# endif + } + + // -- Conversions -- + + template + template< + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2, + typename X3, typename Y3, typename Z3, typename W3, + typename X4, typename Y4, typename Z4, typename W4> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat + ( + X1 const& x1, Y1 const& y1, Z1 const& z1, W1 const& w1, + X2 const& x2, Y2 const& y2, Z2 const& z2, W2 const& w2, + X3 const& x3, Y3 const& y3, Z3 const& z3, W3 const& w3, + X4 const& x4, Y4 const& y4, Z4 const& z4, W4 const& w4 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x1, y1, z1, w1), col_type(x2, y2, z2, w2), col_type(x3, y3, z3, w3), col_type(x4, y4, z4, w4)} +# endif + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 1st parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 2nd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 3rd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 4th parameter type invalid."); + + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 5th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 6th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 7th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 8th parameter type invalid."); + + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 9th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 10th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 11th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 12th parameter type invalid."); + + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 13th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 14th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 15th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 16th parameter type invalid."); + +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x1, y1, z1, w1); + this->value[1] = col_type(x2, y2, z2, w2); + this->value[2] = col_type(x3, y3, z3, w3); + this->value[3] = col_type(x4, y4, z4, w4); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(vec<4, V1, Q> const& v1, vec<4, V2, Q> const& v2, vec<4, V3, Q> const& v3, vec<4, V4, Q> const& v4) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v1), col_type(v2), col_type(v3), col_type(v4)} +# endif + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 1st parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 2nd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 3rd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 4th parameter type invalid."); + +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); + this->value[3] = col_type(v4); +# endif + } + + // -- Matrix conversions -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0), col_type(0, 0, 1, 0), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 0), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(0, 0, 1, 0), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0), col_type(m[2], 1, 0), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(m[2], 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0, 0, 1, 0), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0), col_type(0, 0, 1, 0), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 0), col_type(m[3], 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 0); + this->value[3] = col_type(m[3], 1); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 4, T, Q>::col_type & mat<4, 4, T, Q>::operator[](typename mat<4, 4, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 4, T, Q>::col_type const& mat<4, 4, T, Q>::operator[](typename mat<4, 4, T, Q>::length_type i) const GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary arithmetic operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>& mat<4, 4, T, Q>::operator=(mat<4, 4, U, Q> const& m) + { + //memcpy could be faster + //memcpy(&this->value, &m.value, 16 * sizeof(valType)); + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>& mat<4, 4, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + this->value[3] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>& mat<4, 4, T, Q>::operator+=(mat<4, 4, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + this->value[3] += m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + this->value[3] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator-=(mat<4, 4, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + this->value[3] -= m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + this->value[3] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator*=(mat<4, 4, U, Q> const& m) + { + return (*this = *this * m); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + this->value[3] /= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator/=(mat<4, 4, U, Q> const& m) + { + return *this *= inverse(m); + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + ++this->value[3]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + --this->value[3]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> mat<4, 4, T, Q>::operator++(int) + { + mat<4, 4, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> mat<4, 4, T, Q>::operator--(int) + { + mat<4, 4, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary constant operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + -m[0], + -m[1], + -m[2], + -m[3]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m, T scalar) + { + return mat<4, 4, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar, + m[3] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator+(T scalar, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar, + m[3] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + return mat<4, 4, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2], + m1[3] + m2[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m, T scalar) + { + return mat<4, 4, T, Q>( + m[0] - scalar, + m[1] - scalar, + m[2] - scalar, + m[3] - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator-(T scalar, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + scalar - m[0], + scalar - m[1], + scalar - m[2], + scalar - m[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + return mat<4, 4, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2], + m1[3] - m2[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m, T scalar) + { + return mat<4, 4, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar, + m[3] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator*(T scalar, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar, + m[3] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 4, T, Q>::col_type operator* + ( + mat<4, 4, T, Q> const& m, + typename mat<4, 4, T, Q>::row_type const& v + ) + { +/* + __m128 v0 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 v1 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 v2 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 v3 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(m[0].data, v0); + __m128 m1 = _mm_mul_ps(m[1].data, v1); + __m128 a0 = _mm_add_ps(m0, m1); + + __m128 m2 = _mm_mul_ps(m[2].data, v2); + __m128 m3 = _mm_mul_ps(m[3].data, v3); + __m128 a1 = _mm_add_ps(m2, m3); + + __m128 a2 = _mm_add_ps(a0, a1); + + return typename mat<4, 4, T, Q>::col_type(a2); +*/ + + typename mat<4, 4, T, Q>::col_type const Mov0(v[0]); + typename mat<4, 4, T, Q>::col_type const Mov1(v[1]); + typename mat<4, 4, T, Q>::col_type const Mul0 = m[0] * Mov0; + typename mat<4, 4, T, Q>::col_type const Mul1 = m[1] * Mov1; + typename mat<4, 4, T, Q>::col_type const Add0 = Mul0 + Mul1; + typename mat<4, 4, T, Q>::col_type const Mov2(v[2]); + typename mat<4, 4, T, Q>::col_type const Mov3(v[3]); + typename mat<4, 4, T, Q>::col_type const Mul2 = m[2] * Mov2; + typename mat<4, 4, T, Q>::col_type const Mul3 = m[3] * Mov3; + typename mat<4, 4, T, Q>::col_type const Add1 = Mul2 + Mul3; + typename mat<4, 4, T, Q>::col_type const Add2 = Add0 + Add1; + return Add2; + +/* + return typename mat<4, 4, T, Q>::col_type( + m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3], + m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3], + m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3], + m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3]); +*/ + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 4, T, Q>::row_type operator* + ( + typename mat<4, 4, T, Q>::col_type const& v, + mat<4, 4, T, Q> const& m + ) + { + return typename mat<4, 4, T, Q>::row_type( + m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3], + m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3], + m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3], + m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + return mat<2, 4, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2] + m1[3][3] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2] + m1[3][3] * m2[1][3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + return mat<3, 4, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2] + m1[3][3] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2] + m1[3][3] * m2[1][3], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2] + m1[3][2] * m2[2][3], + m1[0][3] * m2[2][0] + m1[1][3] * m2[2][1] + m1[2][3] * m2[2][2] + m1[3][3] * m2[2][3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + typename mat<4, 4, T, Q>::col_type const SrcA0 = m1[0]; + typename mat<4, 4, T, Q>::col_type const SrcA1 = m1[1]; + typename mat<4, 4, T, Q>::col_type const SrcA2 = m1[2]; + typename mat<4, 4, T, Q>::col_type const SrcA3 = m1[3]; + + typename mat<4, 4, T, Q>::col_type const SrcB0 = m2[0]; + typename mat<4, 4, T, Q>::col_type const SrcB1 = m2[1]; + typename mat<4, 4, T, Q>::col_type const SrcB2 = m2[2]; + typename mat<4, 4, T, Q>::col_type const SrcB3 = m2[3]; + + mat<4, 4, T, Q> Result; + Result[0] = SrcA0 * SrcB0[0] + SrcA1 * SrcB0[1] + SrcA2 * SrcB0[2] + SrcA3 * SrcB0[3]; + Result[1] = SrcA0 * SrcB1[0] + SrcA1 * SrcB1[1] + SrcA2 * SrcB1[2] + SrcA3 * SrcB1[3]; + Result[2] = SrcA0 * SrcB2[0] + SrcA1 * SrcB2[1] + SrcA2 * SrcB2[2] + SrcA3 * SrcB2[3]; + Result[3] = SrcA0 * SrcB3[0] + SrcA1 * SrcB3[1] + SrcA2 * SrcB3[2] + SrcA3 * SrcB3[3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m, T scalar) + { + return mat<4, 4, T, Q>( + m[0] / scalar, + m[1] / scalar, + m[2] / scalar, + m[3] / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator/(T scalar, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + scalar / m[0], + scalar / m[1], + scalar / m[2], + scalar / m[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 4, T, Q>::col_type operator/(mat<4, 4, T, Q> const& m, typename mat<4, 4, T, Q>::row_type const& v) + { + return inverse(m) * v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 4, T, Q>::row_type operator/(typename mat<4, 4, T, Q>::col_type const& v, mat<4, 4, T, Q> const& m) + { + return v * inverse(m); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + mat<4, 4, T, Q> m1_copy(m1); + return m1_copy /= m2; + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]) && (m1[3] == m2[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]) || (m1[3] != m2[3]); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "type_mat4x4_simd.inl" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x4_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x4_simd.inl new file mode 100644 index 0000000..fb3a16f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x4_simd.inl @@ -0,0 +1,6 @@ +/// @ref core + +namespace glm +{ + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_quat.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_quat.hpp new file mode 100644 index 0000000..1b41e15 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_quat.hpp @@ -0,0 +1,193 @@ +/// @ref core +/// @file glm/detail/type_quat.hpp + +#pragma once + +// Dependency: +#include "../detail/type_mat3x3.hpp" +#include "../detail/type_mat4x4.hpp" +#include "../detail/type_vec3.hpp" +#include "../detail/type_vec4.hpp" +#include "../ext/vector_relational.hpp" +#include "../ext/quaternion_relational.hpp" +#include "../gtc/constants.hpp" +#include "../gtc/matrix_transform.hpp" + +namespace glm +{ +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +# pragma clang diagnostic ignored "-Wnested-anon-types" +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union +# endif +# endif + + template + struct qua + { + // -- Implementation detail -- + + typedef qua type; + typedef T value_type; + + // -- Data -- + +# if GLM_LANG & GLM_LANG_CXXMS_FLAG + union + { +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + struct { T w, x, y, z; }; +# else + struct { T x, y, z, w; }; +# endif + + typename detail::storage<4, T, detail::is_aligned::value>::type data; + }; +# else +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + T w, x, y, z; +# else + T x, y, z, w; +# endif +# endif + + // -- Component accesses -- + + typedef length_t length_type; + + /// Return the count of components of a quaternion + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 4;} + + GLM_FUNC_DECL GLM_CONSTEXPR T & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR T const& operator[](length_type i) const; + + // -- Implicit basic constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR qua() GLM_DEFAULT_CTOR; + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR qua(qua const& q) GLM_DEFAULT; + template + GLM_CTOR_DECL qua(qua const& q); + + // -- Explicit basic constructors -- + + GLM_CTOR_DECL qua(T s, vec<3, T, Q> const& v); + +# ifdef GLM_FORCE_QUAT_DATA_XYZW + GLM_CTOR_DECL qua(T x, T y, T z, T w); +# else + GLM_CTOR_DECL qua(T w, T x, T y, T z); +# endif + + GLM_FUNC_DECL static GLM_CONSTEXPR qua wxyz(T w, T x, T y, T z); + + // -- Conversion constructors -- + + template + GLM_CTOR_DECL GLM_EXPLICIT qua(qua const& q); + + /// Explicit conversion operators +# if GLM_HAS_EXPLICIT_CONVERSION_OPERATORS + GLM_FUNC_DECL explicit operator mat<3, 3, T, Q>() const; + GLM_FUNC_DECL explicit operator mat<4, 4, T, Q>() const; +# endif + + /// Create a quaternion from two normalized axis + /// + /// @param u A first normalized axis + /// @param v A second normalized axis + /// @see gtc_quaternion + /// @see http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors + GLM_FUNC_DISCARD_DECL qua(vec<3, T, Q> const& u, vec<3, T, Q> const& v); + + /// Build a quaternion from euler angles (pitch, yaw, roll), in radians. + GLM_CTOR_DECL GLM_EXPLICIT qua(vec<3, T, Q> const& eulerAngles); + GLM_CTOR_DECL GLM_EXPLICIT qua(mat<3, 3, T, Q> const& q); + GLM_CTOR_DECL GLM_EXPLICIT qua(mat<4, 4, T, Q> const& q); + + // -- Unary arithmetic operators -- + + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR qua& operator=(qua const& q) GLM_DEFAULT; + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR qua& operator=(qua const& q); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR qua& operator+=(qua const& q); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR qua& operator-=(qua const& q); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR qua& operator*=(qua const& q); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR qua& operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR qua& operator/=(U s); + }; + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif +# endif + + // -- Unary bit operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator+(qua const& q); + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator-(qua const& q); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator+(qua const& q, qua const& p); + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator-(qua const& q, qua const& p); + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator*(qua const& q, qua const& p); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(qua const& q, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, qua const& q); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(qua const& q, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, qua const& q); + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator*(qua const& q, T const& s); + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator*(T const& s, qua const& q); + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator/(qua const& q, T const& s); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(qua const& q1, qua const& q2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(qua const& q1, qua const& q2); +} //namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_quat.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_quat.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_quat.inl new file mode 100644 index 0000000..6a8f987 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_quat.inl @@ -0,0 +1,424 @@ +#include "../trigonometric.hpp" +#include "../exponential.hpp" +#include "../ext/quaternion_common.hpp" +#include "../ext/quaternion_geometric.hpp" +#include + +namespace glm{ +namespace detail +{ + template + struct genTypeTrait > + { + static const genTypeEnum GENTYPE = GENTYPE_QUAT; + }; + + template + struct compute_dot, T, Aligned> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(qua const& a, qua const& b) + { + vec<4, T, Q> tmp(a.w * b.w, a.x * b.x, a.y * b.y, a.z * b.z); + return (tmp.x + tmp.y) + (tmp.z + tmp.w); + } + }; + + template + struct compute_quat_add + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua call(qua const& q, qua const& p) + { + return qua::wxyz(q.w + p.w, q.x + p.x, q.y + p.y, q.z + p.z); + } + }; + + template + struct compute_quat_sub + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua call(qua const& q, qua const& p) + { + return qua::wxyz(q.w - p.w, q.x - p.x, q.y - p.y, q.z - p.z); + } + }; + + template + struct compute_quat_mul_scalar + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua call(qua const& q, T s) + { + return qua::wxyz(q.w * s, q.x * s, q.y * s, q.z * s); + } + }; + + template + struct compute_quat_div_scalar + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua call(qua const& q, T s) + { + return qua::wxyz(q.w / s, q.x / s, q.y / s, q.z / s); + } + }; + + template + struct compute_quat_mul_vec4 + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(qua const& q, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(q * vec<3, T, Q>(v), v.w); + } + }; +}//namespace detail + + // -- Component accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & qua::operator[](typename qua::length_type i) + { + GLM_ASSERT_LENGTH(i, this->length()); +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + return (&w)[i]; +# else + return (&x)[i]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& qua::operator[](typename qua::length_type i) const + { + GLM_ASSERT_LENGTH(i, this->length()); +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + return (&w)[i]; +# else + return (&x)[i]; +# endif + } + + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR qua::qua() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(1), x(0), y(0), z(0) +# else + : x(0), y(0), z(0), w(1) +# endif +# endif + {} +# endif + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(qua const& q) +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(q.w), x(q.x), y(q.y), z(q.z) +# else + : x(q.x), y(q.y), z(q.z), w(q.w) +# endif + {} +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(qua const& q) +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(q.w), x(q.x), y(q.y), z(q.z) +# else + : x(q.x), y(q.y), z(q.z), w(q.w) +# endif + {} + + // -- Explicit basic constructors -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(T s, vec<3, T, Q> const& v) +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(s), x(v.x), y(v.y), z(v.z) +# else + : x(v.x), y(v.y), z(v.z), w(s) +# endif + {} + + template +# ifdef GLM_FORCE_QUAT_DATA_XYZW + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(T _x, T _y, T _z, T _w) +# else + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(T _w, T _x, T _y, T _z) +# endif +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(_w), x(_x), y(_y), z(_z) +# else + : x(_x), y(_y), z(_z), w(_w) +# endif + {} + + template + GLM_CONSTEXPR qua qua::wxyz(T w, T x, T y, T z) { +# ifdef GLM_FORCE_QUAT_DATA_XYZW + return qua(x, y, z, w); +# else + return qua(w, x, y, z); +# endif + } + + // -- Conversion constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(qua const& q) +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(static_cast(q.w)), x(static_cast(q.x)), y(static_cast(q.y)), z(static_cast(q.z)) +# else + : x(static_cast(q.x)), y(static_cast(q.y)), z(static_cast(q.z)), w(static_cast(q.w)) +# endif + {} + + //template + //GLM_FUNC_QUALIFIER qua::qua + //( + // valType const& pitch, + // valType const& yaw, + // valType const& roll + //) + //{ + // vec<3, valType> eulerAngle(pitch * valType(0.5), yaw * valType(0.5), roll * valType(0.5)); + // vec<3, valType> c = glm::cos(eulerAngle * valType(0.5)); + // vec<3, valType> s = glm::sin(eulerAngle * valType(0.5)); + // + // this->w = c.x * c.y * c.z + s.x * s.y * s.z; + // this->x = s.x * c.y * c.z - c.x * s.y * s.z; + // this->y = c.x * s.y * c.z + s.x * c.y * s.z; + // this->z = c.x * c.y * s.z - s.x * s.y * c.z; + //} + + template + GLM_FUNC_QUALIFIER qua::qua(vec<3, T, Q> const& u, vec<3, T, Q> const& v) + { + T norm_u_norm_v = sqrt(dot(u, u) * dot(v, v)); + T real_part = norm_u_norm_v + dot(u, v); + vec<3, T, Q> t; + + if(real_part < static_cast(1.e-6f) * norm_u_norm_v) + { + // If u and v are exactly opposite, rotate 180 degrees + // around an arbitrary orthogonal axis. Axis normalisation + // can happen later, when we normalise the quaternion. + real_part = static_cast(0); + t = abs(u.x) > abs(u.z) ? vec<3, T, Q>(-u.y, u.x, static_cast(0)) : vec<3, T, Q>(static_cast(0), -u.z, u.y); + } + else + { + // Otherwise, build quaternion the standard way. + t = cross(u, v); + } + + *this = normalize(qua::wxyz(real_part, t.x, t.y, t.z)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(vec<3, T, Q> const& eulerAngle) + { + vec<3, T, Q> c = glm::cos(eulerAngle * T(0.5)); + vec<3, T, Q> s = glm::sin(eulerAngle * T(0.5)); + + this->w = c.x * c.y * c.z + s.x * s.y * s.z; + this->x = s.x * c.y * c.z - c.x * s.y * s.z; + this->y = c.x * s.y * c.z + s.x * c.y * s.z; + this->z = c.x * c.y * s.z - s.x * s.y * c.z; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(mat<3, 3, T, Q> const& m) + { + *this = quat_cast(m); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(mat<4, 4, T, Q> const& m) + { + *this = quat_cast(m); + } + +# if GLM_HAS_EXPLICIT_CONVERSION_OPERATORS + template + GLM_FUNC_QUALIFIER qua::operator mat<3, 3, T, Q>() const + { + return mat3_cast(*this); + } + + template + GLM_FUNC_QUALIFIER qua::operator mat<4, 4, T, Q>() const + { + return mat4_cast(*this); + } +# endif//GLM_HAS_EXPLICIT_CONVERSION_OPERATORS + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator=(qua const& q) + { + this->w = q.w; + this->x = q.x; + this->y = q.y; + this->z = q.z; + return *this; + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator=(qua const& q) + { + this->w = static_cast(q.w); + this->x = static_cast(q.x); + this->y = static_cast(q.y); + this->z = static_cast(q.z); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator+=(qua const& q) + { + return (*this = detail::compute_quat_add::value>::call(*this, qua(q))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator-=(qua const& q) + { + return (*this = detail::compute_quat_sub::value>::call(*this, qua(q))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator*=(qua const& r) + { + qua const p(*this); + qua const q(r); + + this->w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z; + this->x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y; + this->y = p.w * q.y + p.y * q.w + p.z * q.x - p.x * q.z; + this->z = p.w * q.z + p.z * q.w + p.x * q.y - p.y * q.x; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator*=(U s) + { + return (*this = detail::compute_quat_mul_scalar::value>::call(*this, static_cast(s))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator/=(U s) + { + return (*this = detail::compute_quat_div_scalar::value>::call(*this, static_cast(s))); + } + + // -- Unary bit operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator+(qua const& q) + { + return q; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator-(qua const& q) + { + return qua::wxyz(-q.w, -q.x, -q.y, -q.z); + } + + // -- Binary operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator+(qua const& q, qua const& p) + { + return qua(q) += p; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator-(qua const& q, qua const& p) + { + return qua(q) -= p; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator*(qua const& q, qua const& p) + { + return qua(q) *= p; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(qua const& q, vec<3, T, Q> const& v) + { + vec<3, T, Q> const QuatVector(q.x, q.y, q.z); + vec<3, T, Q> const uv(glm::cross(QuatVector, v)); + vec<3, T, Q> const uuv(glm::cross(QuatVector, uv)); + + return v + ((uv * q.w) + uuv) * static_cast(2); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, qua const& q) + { + return glm::inverse(q) * v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(qua const& q, vec<4, T, Q> const& v) + { + return detail::compute_quat_mul_vec4::value>::call(q, v); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, qua const& q) + { + return glm::inverse(q) * v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator*(qua const& q, T const& s) + { + return qua::wxyz( + q.w * s, q.x * s, q.y * s, q.z * s); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator*(T const& s, qua const& q) + { + return q * s; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator/(qua const& q, T const& s) + { + return qua::wxyz( + q.w / s, q.x / s, q.y / s, q.z / s); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(qua const& q1, qua const& q2) + { + return q1.x == q2.x && q1.y == q2.y && q1.z == q2.z && q1.w == q2.w; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(qua const& q1, qua const& q2) + { + return q1.x != q2.x || q1.y != q2.y || q1.z != q2.z || q1.w != q2.w; + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "type_quat_simd.inl" +#endif + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_quat_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_quat_simd.inl new file mode 100644 index 0000000..fa6da19 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_quat_simd.inl @@ -0,0 +1,208 @@ +/// @ref core + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ +/* + template + struct compute_quat_mul + { + static qua call(qua const& q1, qua const& q2) + { + // SSE2 STATS: 11 shuffle, 8 mul, 8 add + // SSE4 STATS: 3 shuffle, 4 mul, 4 dpps + + __m128 const mul0 = _mm_mul_ps(q1.data, _mm_shuffle_ps(q2.data, q2.data, _MM_SHUFFLE(0, 1, 2, 3))); + __m128 const mul1 = _mm_mul_ps(q1.data, _mm_shuffle_ps(q2.data, q2.data, _MM_SHUFFLE(1, 0, 3, 2))); + __m128 const mul2 = _mm_mul_ps(q1.data, _mm_shuffle_ps(q2.data, q2.data, _MM_SHUFFLE(2, 3, 0, 1))); + __m128 const mul3 = _mm_mul_ps(q1.data, q2.data); + +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + __m128 const add0 = _mm_dp_ps(mul0, _mm_set_ps(1.0f, -1.0f, 1.0f, 1.0f), 0xff); + __m128 const add1 = _mm_dp_ps(mul1, _mm_set_ps(1.0f, 1.0f, 1.0f, -1.0f), 0xff); + __m128 const add2 = _mm_dp_ps(mul2, _mm_set_ps(1.0f, 1.0f, -1.0f, 1.0f), 0xff); + __m128 const add3 = _mm_dp_ps(mul3, _mm_set_ps(1.0f, -1.0f, -1.0f, -1.0f), 0xff); +# else + __m128 const mul4 = _mm_mul_ps(mul0, _mm_set_ps(1.0f, -1.0f, 1.0f, 1.0f)); + __m128 const add0 = _mm_add_ps(mul0, _mm_movehl_ps(mul4, mul4)); + __m128 const add4 = _mm_add_ss(add0, _mm_shuffle_ps(add0, add0, 1)); + + __m128 const mul5 = _mm_mul_ps(mul1, _mm_set_ps(1.0f, 1.0f, 1.0f, -1.0f)); + __m128 const add1 = _mm_add_ps(mul1, _mm_movehl_ps(mul5, mul5)); + __m128 const add5 = _mm_add_ss(add1, _mm_shuffle_ps(add1, add1, 1)); + + __m128 const mul6 = _mm_mul_ps(mul2, _mm_set_ps(1.0f, 1.0f, -1.0f, 1.0f)); + __m128 const add2 = _mm_add_ps(mul6, _mm_movehl_ps(mul6, mul6)); + __m128 const add6 = _mm_add_ss(add2, _mm_shuffle_ps(add2, add2, 1)); + + __m128 const mul7 = _mm_mul_ps(mul3, _mm_set_ps(1.0f, -1.0f, -1.0f, -1.0f)); + __m128 const add3 = _mm_add_ps(mul3, _mm_movehl_ps(mul7, mul7)); + __m128 const add7 = _mm_add_ss(add3, _mm_shuffle_ps(add3, add3, 1)); + #endif + + // This SIMD code is a politically correct way of doing this, but in every test I've tried it has been slower than + // the final code below. I'll keep this here for reference - maybe somebody else can do something better... + // + //__m128 xxyy = _mm_shuffle_ps(add4, add5, _MM_SHUFFLE(0, 0, 0, 0)); + //__m128 zzww = _mm_shuffle_ps(add6, add7, _MM_SHUFFLE(0, 0, 0, 0)); + // + //return _mm_shuffle_ps(xxyy, zzww, _MM_SHUFFLE(2, 0, 2, 0)); + + qua Result; + _mm_store_ss(&Result.x, add4); + _mm_store_ss(&Result.y, add5); + _mm_store_ss(&Result.z, add6); + _mm_store_ss(&Result.w, add7); + return Result; + } + }; +*/ + + template + struct compute_quat_add + { + static qua call(qua const& q, qua const& p) + { + qua Result; + Result.data = _mm_add_ps(q.data, p.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_quat_add + { + static qua call(qua const& a, qua const& b) + { + qua Result; + Result.data = _mm256_add_pd(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_quat_sub + { + static qua call(qua const& q, qua const& p) + { + qua Result; + Result.data = _mm_sub_ps(q.data, p.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_quat_sub + { + static qua call(qua const& a, qua const& b) + { + qua Result; + Result.data = _mm256_sub_pd(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_quat_mul_scalar + { + static qua call(qua const& q, float s) + { + vec<4, float, Q> Result; + Result.data = _mm_mul_ps(q.data, _mm_set_ps1(s)); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_quat_mul_scalar + { + static qua call(qua const& q, double s) + { + qua Result; + Result.data = _mm256_mul_pd(q.data, _mm_set_ps1(s)); + return Result; + } + }; +# endif + + template + struct compute_quat_div_scalar + { + static qua call(qua const& q, float s) + { + vec<4, float, Q> Result; + Result.data = _mm_div_ps(q.data, _mm_set_ps1(s)); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_quat_div_scalar + { + static qua call(qua const& q, double s) + { + qua Result; + Result.data = _mm256_div_pd(q.data, _mm_set_ps1(s)); + return Result; + } + }; +# endif + + template + struct compute_quat_mul_vec4 + { + static vec<4, float, Q> call(qua const& q, vec<4, float, Q> const& v) + { +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + __m128 const q_wwww = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 const q_swp0 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(0, 1, 3, 2)); + __m128 const q_swp1 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(0, 2, 1, 3)); + __m128 const v_swp0 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 const v_swp1 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 1, 0, 2)); + + __m128 uv = _mm_sub_ps(_mm_mul_ps(q_swp0, v_swp1), _mm_mul_ps(q_swp1, v_swp0)); + __m128 uv_swp0 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 uv_swp1 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 uuv = _mm_sub_ps(_mm_mul_ps(q_swp0, uv_swp1), _mm_mul_ps(q_swp1, uv_swp0)); + + __m128 const two = _mm_set1_ps(2.0f); + uv = _mm_mul_ps(uv, _mm_mul_ps(q_wwww, two)); + uuv = _mm_mul_ps(uuv, two); + + vec<4, float, Q> Result; + Result.data = _mm_add_ps(v.data, _mm_add_ps(uv, uuv)); + return Result; +# else + __m128 const q_wwww = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(3, 3, 3, 3)); + __m128 const q_swp0 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 const q_swp1 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 const v_swp0 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 const v_swp1 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 1, 0, 2)); + + __m128 uv = _mm_sub_ps(_mm_mul_ps(q_swp0, v_swp1), _mm_mul_ps(q_swp1, v_swp0)); + __m128 uv_swp0 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 uv_swp1 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 uuv = _mm_sub_ps(_mm_mul_ps(q_swp0, uv_swp1), _mm_mul_ps(q_swp1, uv_swp0)); + + __m128 const two = _mm_set1_ps(2.0f); + uv = _mm_mul_ps(uv, _mm_mul_ps(q_wwww, two)); + uuv = _mm_mul_ps(uuv, two); + + vec<4, float, Q> Result; + Result.data = _mm_add_ps(v.data, _mm_add_ps(uv, uuv)); + return Result; +# endif + } + }; +}//namespace detail +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec1.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec1.hpp new file mode 100644 index 0000000..0cc7b5d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec1.hpp @@ -0,0 +1,308 @@ +/// @ref core +/// @file glm/detail/type_vec1.hpp + +#pragma once + +#include "qualifier.hpp" +#if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR +# include "_swizzle.hpp" +#elif GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION +# include "_swizzle_func.hpp" +#endif +#include + +namespace glm +{ + template + struct vec<1, T, Q> + { + // -- Implementation detail -- + + typedef T value_type; + typedef vec<1, T, Q> type; + typedef vec<1, bool, Q> bool_type; + + // -- Data -- + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +# pragma clang diagnostic ignored "-Wnested-anon-types" +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union +# endif +# endif + +# if GLM_CONFIG_XYZW_ONLY + T x; +# elif GLM_CONFIG_ANONYMOUS_STRUCT == GLM_ENABLE + union + { + T x; + T r; + T s; + + typename detail::storage<1, T, detail::is_aligned::value>::type data; +/* +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + _GLM_SWIZZLE1_2_MEMBERS(T, Q, x) + _GLM_SWIZZLE1_2_MEMBERS(T, Q, r) + _GLM_SWIZZLE1_2_MEMBERS(T, Q, s) + _GLM_SWIZZLE1_3_MEMBERS(T, Q, x) + _GLM_SWIZZLE1_3_MEMBERS(T, Q, r) + _GLM_SWIZZLE1_3_MEMBERS(T, Q, s) + _GLM_SWIZZLE1_4_MEMBERS(T, Q, x) + _GLM_SWIZZLE1_4_MEMBERS(T, Q, r) + _GLM_SWIZZLE1_4_MEMBERS(T, Q, s) +# endif +*/ + }; +# else + union {T x, r, s;}; +/* +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC1(T, Q) +# endif +*/ +# endif + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif +# endif + + // -- Component accesses -- + + /// Return the count of components of the vector + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 1;} + + GLM_FUNC_DECL GLM_CONSTEXPR T & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR T const& operator[](length_type i) const; + + // -- Implicit basic constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR vec() GLM_DEFAULT_CTOR; + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec(vec const& v) GLM_DEFAULT; + template + GLM_CTOR_DECL vec(vec<1, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_CTOR_DECL explicit vec(T scalar); + + // -- Conversion vector constructors -- + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL GLM_EXPLICIT vec(vec<2, U, P> const& v); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL GLM_EXPLICIT vec(vec<3, U, P> const& v); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL GLM_EXPLICIT vec(vec<4, U, P> const& v); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL GLM_EXPLICIT vec(vec<1, U, P> const& v); + + // -- Swizzle constructors -- +/* +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec(detail::_swizzle<1, T, Q, E0, -1,-2,-3> const& that) + { + *this = that(); + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR +*/ + // -- Unary arithmetic operators -- + + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator=(vec const& v) GLM_DEFAULT; + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator+=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator+=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator-=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator-=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator*=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator*=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator/=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator/=(vec<1, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator++(); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator--(int); + + // -- Unary bit operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator%=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator%=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator&=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator&=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator|=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator|=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator^=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator^=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator<<=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator<<=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator>>=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator>>=(vec<1, U, Q> const& v); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator+(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator-(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator*(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator*(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator*(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator/(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator/(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator/(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator%(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator%(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator%(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator&(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator&(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator&(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator|(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator|(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator|(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator^(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator^(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator^(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator<<(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator<<(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator<<(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator>>(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator>>(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator>>(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator~(vec<1, T, Q> const& v); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, bool, Q> operator&&(vec<1, bool, Q> const& v1, vec<1, bool, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, bool, Q> operator||(vec<1, bool, Q> const& v1, vec<1, bool, Q> const& v2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_vec1.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec1.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec1.inl new file mode 100644 index 0000000..18411e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec1.inl @@ -0,0 +1,553 @@ +/// @ref core + +#include "./compute_vector_relational.hpp" + +namespace glm +{ + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0) +# endif + {} +# endif + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<1, T, Q> const& v) + : x(v.x) + {} +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<1, T, P> const& v) + : x(v.x) + {} + + // -- Explicit basic constructors -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(T scalar) + : x(scalar) + {} + + // -- Conversion vector constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<1, U, P> const& v) + : x(static_cast(v.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<2, U, P> const& v) + : x(static_cast(v.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<3, U, P> const& v) + : x(static_cast(v.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<4, U, P> const& v) + : x(static_cast(v.x)) + {} + + // -- Component accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & vec<1, T, Q>::operator[](typename vec<1, T, Q>::length_type) + { + return x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& vec<1, T, Q>::operator[](typename vec<1, T, Q>::length_type) const + { + return x; + } + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator=(vec<1, T, Q> const& v) + { + this->x = v.x; + return *this; + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator=(vec<1, U, Q> const& v) + { + this->x = static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator+=(U scalar) + { + this->x += static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator+=(vec<1, U, Q> const& v) + { + this->x += static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator-=(U scalar) + { + this->x -= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator-=(vec<1, U, Q> const& v) + { + this->x -= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator*=(U scalar) + { + this->x *= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator*=(vec<1, U, Q> const& v) + { + this->x *= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator/=(U scalar) + { + this->x /= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator/=(vec<1, U, Q> const& v) + { + this->x /= static_cast(v.x); + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator++() + { + ++this->x; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator--() + { + --this->x; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> vec<1, T, Q>::operator++(int) + { + vec<1, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> vec<1, T, Q>::operator--(int) + { + vec<1, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary bit operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator%=(U scalar) + { + this->x %= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator%=(vec<1, U, Q> const& v) + { + this->x %= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator&=(U scalar) + { + this->x &= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator&=(vec<1, U, Q> const& v) + { + this->x &= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator|=(U scalar) + { + this->x |= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator|=(vec<1, U, Q> const& v) + { + this->x |= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator^=(U scalar) + { + this->x ^= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator^=(vec<1, U, Q> const& v) + { + this->x ^= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator<<=(U scalar) + { + this->x <<= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator<<=(vec<1, U, Q> const& v) + { + this->x <<= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator>>=(U scalar) + { + this->x >>= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator>>=(vec<1, U, Q> const& v) + { + this->x >>= static_cast(v.x); + return *this; + } + + // -- Unary constant operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + -v.x); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator+(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar + v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x + v2.x); + } + + //operator- + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator-(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar - v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x - v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator*(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator*(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar * v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator*(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x * v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator/(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator/(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar / v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator/(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x / v2.x); + } + + // -- Binary bit operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator%(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x % scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator%(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar % v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator%(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x % v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator&(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x & scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator&(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar & v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator&(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x & v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator|(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x | scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator|(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar | v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator|(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x | v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator^(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x ^ scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator^(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar ^ v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator^(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x ^ v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator<<(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + static_cast(v.x << scalar)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator<<(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + static_cast(scalar << v.x)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator<<(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + static_cast(v1.x << v2.x)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator>>(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + static_cast(v.x >> scalar)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator>>(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + static_cast(scalar >> v.x)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator>>(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + static_cast(v1.x >> v2.x)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator~(vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + ~v.x); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return detail::compute_equal::is_iec559>::call(v1.x, v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return !(v1 == v2); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, bool, Q> operator&&(vec<1, bool, Q> const& v1, vec<1, bool, Q> const& v2) + { + return vec<1, bool, Q>(v1.x && v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, bool, Q> operator||(vec<1, bool, Q> const& v1, vec<1, bool, Q> const& v2) + { + return vec<1, bool, Q>(v1.x || v2.x); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec2.hpp new file mode 100644 index 0000000..2ddfb43 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec2.hpp @@ -0,0 +1,402 @@ +/// @ref core +/// @file glm/detail/type_vec2.hpp + +#pragma once + +#include "qualifier.hpp" +#if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR +# include "_swizzle.hpp" +#elif GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION +# include "_swizzle_func.hpp" +#endif +#include + +namespace glm +{ + template + struct vec<2, T, Q> + { + // -- Implementation detail -- + + typedef T value_type; + typedef vec<2, T, Q> type; + typedef vec<2, bool, Q> bool_type; + + // -- Data -- + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +# pragma clang diagnostic ignored "-Wnested-anon-types" +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union +# endif +# endif + +# if GLM_CONFIG_XYZW_ONLY + T x, y; +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(T, Q, x, y) +# endif//GLM_CONFIG_SWIZZLE +# elif GLM_CONFIG_ANONYMOUS_STRUCT == GLM_ENABLE + union + { + struct{ T x, y; }; + struct{ T r, g; }; + struct{ T s, t; }; + + typename detail::storage<2, T, detail::is_aligned::value>::type data; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + GLM_SWIZZLE2_2_MEMBERS(T, Q, x, y) + GLM_SWIZZLE2_2_MEMBERS(T, Q, r, g) + GLM_SWIZZLE2_2_MEMBERS(T, Q, s, t) + GLM_SWIZZLE2_3_MEMBERS(T, Q, x, y) + GLM_SWIZZLE2_3_MEMBERS(T, Q, r, g) + GLM_SWIZZLE2_3_MEMBERS(T, Q, s, t) + GLM_SWIZZLE2_4_MEMBERS(T, Q, x, y) + GLM_SWIZZLE2_4_MEMBERS(T, Q, r, g) + GLM_SWIZZLE2_4_MEMBERS(T, Q, s, t) +# endif + }; +# else + union {T x, r, s;}; + union {T y, g, t;}; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC2(T, Q) +# endif//GLM_CONFIG_SWIZZLE +# endif + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif +# endif + + // -- Component accesses -- + + /// Return the count of components of the vector + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 2;} + + GLM_FUNC_DECL GLM_CONSTEXPR T& operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR T const& operator[](length_type i) const; + + // -- Implicit basic constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR vec() GLM_DEFAULT_CTOR; + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec(vec const& v) GLM_DEFAULT; + template + GLM_CTOR_DECL vec(vec<2, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_CTOR_DECL explicit vec(T scalar); + GLM_CTOR_DECL vec(T x, T y); + + // -- Conversion constructors -- + + template + GLM_CTOR_DECL explicit vec(vec<1, U, P> const& v); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(A x, B y); + template + GLM_CTOR_DECL vec(vec<1, A, Q> const& x, B y); + template + GLM_CTOR_DECL vec(A x, vec<1, B, Q> const& y); + template + GLM_CTOR_DECL vec(vec<1, A, Q> const& x, vec<1, B, Q> const& y); + + // -- Conversion vector constructors -- + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL GLM_EXPLICIT vec(vec<3, U, P> const& v); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL GLM_EXPLICIT vec(vec<4, U, P> const& v); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL GLM_EXPLICIT vec(vec<2, U, P> const& v); + + // -- Swizzle constructors -- +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + GLM_FUNC_DISCARD_DECL vec(detail::_swizzle<2, T, Q, E0, E1,-1,-2> const& that) + { + *this = that(); + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + + // -- Unary arithmetic operators -- + + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator=(vec const& v) GLM_DEFAULT; + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator+=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator+=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator+=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator-=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator-=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator-=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator*=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator*=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator*=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator/=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator/=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator/=(vec<2, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator++(); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator--(int); + + // -- Unary bit operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator%=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator%=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator%=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator&=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator&=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator&=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator|=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator|=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator|=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator^=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator^=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator^=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator<<=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator<<=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator<<=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator>>=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator>>=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator>>=(vec<2, U, Q> const& v); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator~(vec<2, T, Q> const& v); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, bool, Q> operator&&(vec<2, bool, Q> const& v1, vec<2, bool, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, bool, Q> operator||(vec<2, bool, Q> const& v1, vec<2, bool, Q> const& v2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_vec2.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec2.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec2.inl new file mode 100644 index 0000000..e840899 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec2.inl @@ -0,0 +1,915 @@ +/// @ref core + +#include "./compute_vector_relational.hpp" + +namespace glm +{ + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0), y(0) +# endif + {} +# endif + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<2, T, Q> const& v) + : x(v.x), y(v.y) + {} +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<2, T, P> const& v) + : x(v.x), y(v.y) + {} + + // -- Explicit basic constructors -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(T scalar) + : x(scalar), y(scalar) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(T _x, T _y) + : x(_x), y(_y) + {} + + // -- Conversion scalar constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<1, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(A _x, B _y) + : x(static_cast(_x)) + , y(static_cast(_y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<1, A, Q> const& _x, B _y) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(A _x, vec<1, B, Q> const& _y) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<1, A, Q> const& _x, vec<1, B, Q> const& _y) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + {} + + // -- Conversion vector constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<2, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<3, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<4, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.y)) + {} + + // -- Component accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & vec<2, T, Q>::operator[](typename vec<2, T, Q>::length_type i) + { + GLM_ASSERT_LENGTH(i, this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + } + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& vec<2, T, Q>::operator[](typename vec<2, T, Q>::length_type i) const + { + GLM_ASSERT_LENGTH(i, this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + } + } + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator=(vec<2, T, Q> const& v) + { + this->x = v.x; + this->y = v.y; + return *this; + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator=(vec<2, U, Q> const& v) + { + this->x = static_cast(v.x); + this->y = static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator+=(U scalar) + { + this->x += static_cast(scalar); + this->y += static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator+=(vec<1, U, Q> const& v) + { + this->x += static_cast(v.x); + this->y += static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator+=(vec<2, U, Q> const& v) + { + this->x += static_cast(v.x); + this->y += static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator-=(U scalar) + { + this->x -= static_cast(scalar); + this->y -= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator-=(vec<1, U, Q> const& v) + { + this->x -= static_cast(v.x); + this->y -= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator-=(vec<2, U, Q> const& v) + { + this->x -= static_cast(v.x); + this->y -= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator*=(U scalar) + { + this->x *= static_cast(scalar); + this->y *= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator*=(vec<1, U, Q> const& v) + { + this->x *= static_cast(v.x); + this->y *= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator*=(vec<2, U, Q> const& v) + { + this->x *= static_cast(v.x); + this->y *= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator/=(U scalar) + { + this->x /= static_cast(scalar); + this->y /= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator/=(vec<1, U, Q> const& v) + { + this->x /= static_cast(v.x); + this->y /= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator/=(vec<2, U, Q> const& v) + { + this->x /= static_cast(v.x); + this->y /= static_cast(v.y); + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator++() + { + ++this->x; + ++this->y; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator--() + { + --this->x; + --this->y; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> vec<2, T, Q>::operator++(int) + { + vec<2, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> vec<2, T, Q>::operator--(int) + { + vec<2, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary bit operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator%=(U scalar) + { + this->x %= static_cast(scalar); + this->y %= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator%=(vec<1, U, Q> const& v) + { + this->x %= static_cast(v.x); + this->y %= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator%=(vec<2, U, Q> const& v) + { + this->x %= static_cast(v.x); + this->y %= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator&=(U scalar) + { + this->x &= static_cast(scalar); + this->y &= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator&=(vec<1, U, Q> const& v) + { + this->x &= static_cast(v.x); + this->y &= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator&=(vec<2, U, Q> const& v) + { + this->x &= static_cast(v.x); + this->y &= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator|=(U scalar) + { + this->x |= static_cast(scalar); + this->y |= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator|=(vec<1, U, Q> const& v) + { + this->x |= static_cast(v.x); + this->y |= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator|=(vec<2, U, Q> const& v) + { + this->x |= static_cast(v.x); + this->y |= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator^=(U scalar) + { + this->x ^= static_cast(scalar); + this->y ^= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator^=(vec<1, U, Q> const& v) + { + this->x ^= static_cast(v.x); + this->y ^= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator^=(vec<2, U, Q> const& v) + { + this->x ^= static_cast(v.x); + this->y ^= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator<<=(U scalar) + { + this->x <<= static_cast(scalar); + this->y <<= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator<<=(vec<1, U, Q> const& v) + { + this->x <<= static_cast(v.x); + this->y <<= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator<<=(vec<2, U, Q> const& v) + { + this->x <<= static_cast(v.x); + this->y <<= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator>>=(U scalar) + { + this->x >>= static_cast(scalar); + this->y >>= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator>>=(vec<1, U, Q> const& v) + { + this->x >>= static_cast(v.x); + this->y >>= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator>>=(vec<2, U, Q> const& v) + { + this->x >>= static_cast(v.x); + this->y >>= static_cast(v.y); + return *this; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + -v.x, + -v.y); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x + scalar, + v.y + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x + v2.x, + v1.y + v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar + v.x, + scalar + v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x + v2.x, + v1.x + v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x + v2.x, + v1.y + v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x - scalar, + v.y - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x - v2.x, + v1.y - v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator-(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar - v.x, + scalar - v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator-(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x - v2.x, + v1.x - v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x - v2.x, + v1.y - v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x * scalar, + v.y * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x * v2.x, + v1.y * v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator*(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar * v.x, + scalar * v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator*(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x * v2.x, + v1.x * v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x * v2.x, + v1.y * v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x / scalar, + v.y / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x / v2.x, + v1.y / v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator/(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar / v.x, + scalar / v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator/(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x / v2.x, + v1.x / v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x / v2.x, + v1.y / v2.y); + } + + // -- Binary bit operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x % scalar, + v.y % scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x % v2.x, + v1.y % v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator%(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar % v.x, + scalar % v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator%(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x % v2.x, + v1.x % v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x % v2.x, + v1.y % v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x & scalar, + v.y & scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x & v2.x, + v1.y & v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator&(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar & v.x, + scalar & v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator&(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x & v2.x, + v1.x & v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x & v2.x, + v1.y & v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x | scalar, + v.y | scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x | v2.x, + v1.y | v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator|(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar | v.x, + scalar | v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator|(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x | v2.x, + v1.x | v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x | v2.x, + v1.y | v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x ^ scalar, + v.y ^ scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x ^ v2.x, + v1.y ^ v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator^(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar ^ v.x, + scalar ^ v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator^(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x ^ v2.x, + v1.x ^ v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x ^ v2.x, + v1.y ^ v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x << scalar, + v.y << scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x << v2.x, + v1.y << v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator<<(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar << v.x, + scalar << v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x << v2.x, + v1.x << v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x << v2.x, + v1.y << v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x >> scalar, + v.y >> scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x >> v2.x, + v1.y >> v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator>>(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar >> v.x, + scalar >> v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x >> v2.x, + v1.x >> v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x >> v2.x, + v1.y >> v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator~(vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + ~v.x, + ~v.y); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return + detail::compute_equal::is_iec559>::call(v1.x, v2.x) && + detail::compute_equal::is_iec559>::call(v1.y, v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return !(v1 == v2); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, bool, Q> operator&&(vec<2, bool, Q> const& v1, vec<2, bool, Q> const& v2) + { + return vec<2, bool, Q>(v1.x && v2.x, v1.y && v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, bool, Q> operator||(vec<2, bool, Q> const& v1, vec<2, bool, Q> const& v2) + { + return vec<2, bool, Q>(v1.x || v2.x, v1.y || v2.y); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec3.hpp new file mode 100644 index 0000000..4bf8395 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec3.hpp @@ -0,0 +1,436 @@ +/// @ref core +/// @file glm/detail/type_vec3.hpp + +#pragma once + +#include "qualifier.hpp" +#if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR +# include "_swizzle.hpp" +#elif GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION +# include "_swizzle_func.hpp" +#endif +#include + +namespace glm +{ + template + struct vec<3, T, Q> + { + // -- Implementation detail -- + + typedef T value_type; + typedef vec<3, T, Q> type; + typedef vec<3, bool, Q> bool_type; + + // -- Data -- + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +# pragma clang diagnostic ignored "-Wnested-anon-types" +# pragma clang diagnostic ignored "-Wpadded" +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE +# pragma warning(disable: 4324) // structure was padded due to alignment specifier +# endif +# endif +# endif + +# if GLM_CONFIG_XYZW_ONLY + T x, y, z; +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(T, Q, x, y, z) +# endif//GLM_CONFIG_SWIZZLE +# elif GLM_CONFIG_ANONYMOUS_STRUCT == GLM_ENABLE + union + { + struct{ T x, y, z; }; + struct{ T r, g, b; }; + struct{ T s, t, p; }; + + typename detail::storage<3, T, detail::is_aligned::value>::type data; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + GLM_SWIZZLE3_2_MEMBERS(T, Q, x, y, z) + GLM_SWIZZLE3_2_MEMBERS(T, Q, r, g, b) + GLM_SWIZZLE3_2_MEMBERS(T, Q, s, t, p) + GLM_SWIZZLE3_3_MEMBERS(T, Q, x, y, z) + GLM_SWIZZLE3_3_MEMBERS(T, Q, r, g, b) + GLM_SWIZZLE3_3_MEMBERS(T, Q, s, t, p) + GLM_SWIZZLE3_4_MEMBERS(T, Q, x, y, z) + GLM_SWIZZLE3_4_MEMBERS(T, Q, r, g, b) + GLM_SWIZZLE3_4_MEMBERS(T, Q, s, t, p) +# endif + }; +# else + union { T x, r, s; }; + union { T y, g, t; }; + union { T z, b, p; }; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC3(T, Q) +# endif//GLM_CONFIG_SWIZZLE +# endif//GLM_LANG + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif +# endif + + // -- Component accesses -- + + /// Return the count of components of the vector + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 3;} + + GLM_FUNC_DECL GLM_CONSTEXPR T & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR T const& operator[](length_type i) const; + + // -- Implicit basic constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR vec() GLM_DEFAULT_CTOR; + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec(vec const& v) GLM_DEFAULT; + template + GLM_CTOR_DECL vec(vec<3, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_CTOR_DECL explicit vec(T scalar); + GLM_CTOR_DECL vec(T a, T b, T c); + + // -- Conversion scalar constructors -- + + template + GLM_CTOR_DECL explicit vec(vec<1, U, P> const& v); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(X x, Y y, Z z); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, Y _y, Z _z); + template + GLM_CTOR_DECL vec(X _x, vec<1, Y, Q> const& _y, Z _z); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z); + template + GLM_CTOR_DECL vec(X _x, Y _y, vec<1, Z, Q> const& _z); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z); + template + GLM_CTOR_DECL vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z); + + // -- Conversion vector constructors -- + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<2, A, P> const& _xy, B _z); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<2, A, P> const& _xy, vec<1, B, P> const& _z); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(A _x, vec<2, B, P> const& _yz); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<1, A, P> const& _x, vec<2, B, P> const& _yz); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL GLM_EXPLICIT vec(vec<4, U, P> const& v); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL GLM_EXPLICIT vec(vec<3, U, P> const& v); + + // -- Swizzle constructors -- +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec(detail::_swizzle<3, T, Q, E0, E1, E2, -1> const& that) + { + *this = that(); + } + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec(detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v, T const& scalar) + { + *this = vec(v(), scalar); + } + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec(T const& scalar, detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v) + { + *this = vec(scalar, v()); + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + + // -- Unary arithmetic operators -- + + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q>& operator=(vec<3, T, Q> const& v) GLM_DEFAULT; + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator+=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator+=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator+=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator-=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator-=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator-=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator*=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator*=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator*=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator/=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator/=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator/=(vec<3, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator++(); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator--(int); + + // -- Unary bit operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator%=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator%=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator%=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator&=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator&=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator&=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator|=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator|=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator|=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator^=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator^=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator^=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator<<=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator<<=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator<<=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator>>=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator>>=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator>>=(vec<3, U, Q> const& v); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v1, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator~(vec<3, T, Q> const& v); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, bool, Q> operator&&(vec<3, bool, Q> const& v1, vec<3, bool, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, bool, Q> operator||(vec<3, bool, Q> const& v1, vec<3, bool, Q> const& v2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_vec3.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec3.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec3.inl new file mode 100644 index 0000000..4e44047 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec3.inl @@ -0,0 +1,1070 @@ +/// @ref core + +#include "compute_vector_relational.hpp" + +namespace glm +{ + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0), y(0), z(0) +# endif + {} +# endif + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<3, T, Q> const& v) + : x(v.x), y(v.y), z(v.z) + {} +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<3, T, P> const& v) + : x(v.x), y(v.y), z(v.z) + {} + + // -- Explicit basic constructors -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(T scalar) + : x(scalar), y(scalar), z(scalar) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(T _x, T _y, T _z) + : x(_x), y(_y), z(_z) + {} + + // -- Conversion scalar constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.x)) + , z(static_cast(v.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(X _x, Y _y, Z _z) + : x(static_cast(_x)) + , y(static_cast(_y)) + , z(static_cast(_z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, Z _z) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, Z _z) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(X _x, Y _y, vec<1, Z, Q> const& _z) + : x(static_cast(_x)) + , y(static_cast(_y)) + , z(static_cast(_z.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_z.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_z.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_z.x)) + {} + + // -- Conversion vector constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<2, A, P> const& _xy, B _z) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<2, A, P> const& _xy, vec<1, B, P> const& _z) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_z.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(A _x, vec<2, B, P> const& _yz) + : x(static_cast(_x)) + , y(static_cast(_yz.x)) + , z(static_cast(_yz.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, A, P> const& _x, vec<2, B, P> const& _yz) + : x(static_cast(_x.x)) + , y(static_cast(_yz.x)) + , z(static_cast(_yz.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<3, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.y)) + , z(static_cast(v.z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<4, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.y)) + , z(static_cast(v.z)) + {} + + // -- Component accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & vec<3, T, Q>::operator[](typename vec<3, T, Q>::length_type i) + { + GLM_ASSERT_LENGTH(i, this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + case 2: + return z; + } + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& vec<3, T, Q>::operator[](typename vec<3, T, Q>::length_type i) const + { + GLM_ASSERT_LENGTH(i, this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + case 2: + return z; + } + } + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>& vec<3, T, Q>::operator=(vec<3, T, Q> const& v) + { + this->x = v.x; + this->y = v.y; + this->z = v.z; + return *this; + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>& vec<3, T, Q>::operator=(vec<3, U, Q> const& v) + { + this->x = static_cast(v.x); + this->y = static_cast(v.y); + this->z = static_cast(v.z); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator+=(U scalar) + { + this->x += static_cast(scalar); + this->y += static_cast(scalar); + this->z += static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator+=(vec<1, U, Q> const& v) + { + this->x += static_cast(v.x); + this->y += static_cast(v.x); + this->z += static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator+=(vec<3, U, Q> const& v) + { + this->x += static_cast(v.x); + this->y += static_cast(v.y); + this->z += static_cast(v.z); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator-=(U scalar) + { + this->x -= static_cast(scalar); + this->y -= static_cast(scalar); + this->z -= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator-=(vec<1, U, Q> const& v) + { + this->x -= static_cast(v.x); + this->y -= static_cast(v.x); + this->z -= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator-=(vec<3, U, Q> const& v) + { + this->x -= static_cast(v.x); + this->y -= static_cast(v.y); + this->z -= static_cast(v.z); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator*=(U scalar) + { + this->x *= static_cast(scalar); + this->y *= static_cast(scalar); + this->z *= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator*=(vec<1, U, Q> const& v) + { + this->x *= static_cast(v.x); + this->y *= static_cast(v.x); + this->z *= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator*=(vec<3, U, Q> const& v) + { + this->x *= static_cast(v.x); + this->y *= static_cast(v.y); + this->z *= static_cast(v.z); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator/=(U v) + { + this->x /= static_cast(v); + this->y /= static_cast(v); + this->z /= static_cast(v); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator/=(vec<1, U, Q> const& v) + { + this->x /= static_cast(v.x); + this->y /= static_cast(v.x); + this->z /= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator/=(vec<3, U, Q> const& v) + { + this->x /= static_cast(v.x); + this->y /= static_cast(v.y); + this->z /= static_cast(v.z); + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator++() + { + ++this->x; + ++this->y; + ++this->z; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator--() + { + --this->x; + --this->y; + --this->z; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> vec<3, T, Q>::operator++(int) + { + vec<3, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> vec<3, T, Q>::operator--(int) + { + vec<3, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary bit operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator%=(U scalar) + { + this->x %= scalar; + this->y %= scalar; + this->z %= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator%=(vec<1, U, Q> const& v) + { + this->x %= v.x; + this->y %= v.x; + this->z %= v.x; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator%=(vec<3, U, Q> const& v) + { + this->x %= v.x; + this->y %= v.y; + this->z %= v.z; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator&=(U scalar) + { + this->x &= scalar; + this->y &= scalar; + this->z &= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator&=(vec<1, U, Q> const& v) + { + this->x &= v.x; + this->y &= v.x; + this->z &= v.x; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator&=(vec<3, U, Q> const& v) + { + this->x &= v.x; + this->y &= v.y; + this->z &= v.z; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator|=(U scalar) + { + this->x |= scalar; + this->y |= scalar; + this->z |= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator|=(vec<1, U, Q> const& v) + { + this->x |= v.x; + this->y |= v.x; + this->z |= v.x; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator|=(vec<3, U, Q> const& v) + { + this->x |= v.x; + this->y |= v.y; + this->z |= v.z; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator^=(U scalar) + { + this->x ^= scalar; + this->y ^= scalar; + this->z ^= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator^=(vec<1, U, Q> const& v) + { + this->x ^= v.x; + this->y ^= v.x; + this->z ^= v.x; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator^=(vec<3, U, Q> const& v) + { + this->x ^= v.x; + this->y ^= v.y; + this->z ^= v.z; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator<<=(U scalar) + { + this->x <<= scalar; + this->y <<= scalar; + this->z <<= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator<<=(vec<1, U, Q> const& v) + { + this->x <<= static_cast(v.x); + this->y <<= static_cast(v.x); + this->z <<= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator<<=(vec<3, U, Q> const& v) + { + this->x <<= static_cast(v.x); + this->y <<= static_cast(v.y); + this->z <<= static_cast(v.z); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator>>=(U scalar) + { + this->x >>= static_cast(scalar); + this->y >>= static_cast(scalar); + this->z >>= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator>>=(vec<1, U, Q> const& v) + { + this->x >>= static_cast(v.x); + this->y >>= static_cast(v.x); + this->z >>= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator>>=(vec<3, U, Q> const& v) + { + this->x >>= static_cast(v.x); + this->y >>= static_cast(v.y); + this->z >>= static_cast(v.z); + return *this; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + -v.x, + -v.y, + -v.z); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x + scalar, + v.y + scalar, + v.z + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x + scalar.x, + v.y + scalar.x, + v.z + scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar + v.x, + scalar + v.y, + scalar + v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x + v.x, + scalar.x + v.y, + scalar.x + v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x + v2.x, + v1.y + v2.y, + v1.z + v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x - scalar, + v.y - scalar, + v.z - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x - scalar.x, + v.y - scalar.x, + v.z - scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator-(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar - v.x, + scalar - v.y, + scalar - v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator-(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x - v.x, + scalar.x - v.y, + scalar.x - v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x - v2.x, + v1.y - v2.y, + v1.z - v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x * scalar, + v.y * scalar, + v.z * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x * scalar.x, + v.y * scalar.x, + v.z * scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar * v.x, + scalar * v.y, + scalar * v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x * v.x, + scalar.x * v.y, + scalar.x * v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x * v2.x, + v1.y * v2.y, + v1.z * v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x / scalar, + v.y / scalar, + v.z / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x / scalar.x, + v.y / scalar.x, + v.z / scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator/(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar / v.x, + scalar / v.y, + scalar / v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator/(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x / v.x, + scalar.x / v.y, + scalar.x / v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x / v2.x, + v1.y / v2.y, + v1.z / v2.z); + } + + // -- Binary bit operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x % scalar, + v.y % scalar, + v.z % scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x % scalar.x, + v.y % scalar.x, + v.z % scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator%(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar % v.x, + scalar % v.y, + scalar % v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator%(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x % v.x, + scalar.x % v.y, + scalar.x % v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x % v2.x, + v1.y % v2.y, + v1.z % v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x & scalar, + v.y & scalar, + v.z & scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x & scalar.x, + v.y & scalar.x, + v.z & scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator&(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar & v.x, + scalar & v.y, + scalar & v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator&(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x & v.x, + scalar.x & v.y, + scalar.x & v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x & v2.x, + v1.y & v2.y, + v1.z & v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x | scalar, + v.y | scalar, + v.z | scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x | scalar.x, + v.y | scalar.x, + v.z | scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator|(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar | v.x, + scalar | v.y, + scalar | v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator|(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x | v.x, + scalar.x | v.y, + scalar.x | v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x | v2.x, + v1.y | v2.y, + v1.z | v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x ^ scalar, + v.y ^ scalar, + v.z ^ scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x ^ scalar.x, + v.y ^ scalar.x, + v.z ^ scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator^(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar ^ v.x, + scalar ^ v.y, + scalar ^ v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator^(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x ^ v.x, + scalar.x ^ v.y, + scalar.x ^ v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x ^ v2.x, + v1.y ^ v2.y, + v1.z ^ v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x << scalar, + v.y << scalar, + v.z << scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x << scalar.x, + v.y << scalar.x, + v.z << scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator<<(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar << v.x, + scalar << v.y, + scalar << v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x << v.x, + scalar.x << v.y, + scalar.x << v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x << v2.x, + v1.y << v2.y, + v1.z << v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x >> scalar, + v.y >> scalar, + v.z >> scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x >> scalar.x, + v.y >> scalar.x, + v.z >> scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator>>(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar >> v.x, + scalar >> v.y, + scalar >> v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x >> v.x, + scalar.x >> v.y, + scalar.x >> v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x >> v2.x, + v1.y >> v2.y, + v1.z >> v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator~(vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + ~v.x, + ~v.y, + ~v.z); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return + detail::compute_equal::is_iec559>::call(v1.x, v2.x) && + detail::compute_equal::is_iec559>::call(v1.y, v2.y) && + detail::compute_equal::is_iec559>::call(v1.z, v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return !(v1 == v2); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, bool, Q> operator&&(vec<3, bool, Q> const& v1, vec<3, bool, Q> const& v2) + { + return vec<3, bool, Q>(v1.x && v2.x, v1.y && v2.y, v1.z && v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, bool, Q> operator||(vec<3, bool, Q> const& v1, vec<3, bool, Q> const& v2) + { + return vec<3, bool, Q>(v1.x || v2.x, v1.y || v2.y, v1.z || v2.z); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec4.hpp new file mode 100644 index 0000000..15f122f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec4.hpp @@ -0,0 +1,508 @@ +/// @ref core +/// @file glm/detail/type_vec4.hpp + +#pragma once + +#include "qualifier.hpp" +#if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR +# include "_swizzle.hpp" +#elif GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION +# include "_swizzle_func.hpp" +#endif +#include + +namespace glm +{ + template + struct vec<4, T, Q> + { + // -- Implementation detail -- + + typedef T value_type; + typedef vec<4, T, Q> type; + typedef vec<4, bool, Q> bool_type; + + // -- Data -- + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +# pragma clang diagnostic ignored "-Wnested-anon-types" +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union +# endif +# endif + +# if GLM_CONFIG_XYZW_ONLY + T x, y, z, w; +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(T, Q, x, y, z, w) +# endif//GLM_CONFIG_SWIZZLE +# elif GLM_CONFIG_ANONYMOUS_STRUCT == GLM_ENABLE + union + { + struct { T x, y, z, w; }; + struct { T r, g, b, a; }; + struct { T s, t, p, q; }; + + typename detail::storage<4, T, detail::is_aligned::value>::type data; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + GLM_SWIZZLE4_2_MEMBERS(T, Q, x, y, z, w) + GLM_SWIZZLE4_2_MEMBERS(T, Q, r, g, b, a) + GLM_SWIZZLE4_2_MEMBERS(T, Q, s, t, p, q) + GLM_SWIZZLE4_3_MEMBERS(T, Q, x, y, z, w) + GLM_SWIZZLE4_3_MEMBERS(T, Q, r, g, b, a) + GLM_SWIZZLE4_3_MEMBERS(T, Q, s, t, p, q) + GLM_SWIZZLE4_4_MEMBERS(T, Q, x, y, z, w) + GLM_SWIZZLE4_4_MEMBERS(T, Q, r, g, b, a) + GLM_SWIZZLE4_4_MEMBERS(T, Q, s, t, p, q) +# endif + }; +# else + union { T x, r, s; }; + union { T y, g, t; }; + union { T z, b, p; }; + union { T w, a, q; }; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC4(T, Q) +# endif +# endif + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif +# endif + + // -- Component accesses -- + + typedef length_t length_type; + + /// Return the count of components of the vector + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 4;} + + GLM_FUNC_DECL GLM_CONSTEXPR T & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR T const& operator[](length_type i) const; + + // -- Implicit basic constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR vec() GLM_DEFAULT_CTOR; + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec(vec<4, T, Q> const& v) GLM_DEFAULT; + template + GLM_CTOR_DECL vec(vec<4, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_CTOR_DECL explicit vec(T scalar); + GLM_CTOR_DECL vec(T x, T y, T z, T w); + + // -- Conversion scalar constructors -- + + template + GLM_CTOR_DECL explicit vec(vec<1, U, P> const& v); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(X _x, Y _y, Z _z, W _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, Y _y, Z _z, W _w); + template + GLM_CTOR_DECL vec(X _x, vec<1, Y, Q> const& _y, Z _z, W _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z, W _w); + template + GLM_CTOR_DECL vec(X _x, Y _y, vec<1, Z, Q> const& _z, W _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z, W _w); + template + GLM_CTOR_DECL vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, W _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, W _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, Y _y, Z _z, vec<1, W, Q> const& _w); + template + GLM_CTOR_DECL vec(X _x, vec<1, Y, Q> const& _y, Z _z, vec<1, W, Q> const& _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z, vec<1, W, Q> const& _w); + template + GLM_CTOR_DECL vec(X _x, Y _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + template + GLM_CTOR_DECL vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + + // -- Conversion vector constructors -- + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<2, A, P> const& _xy, B _z, C _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<2, A, P> const& _xy, vec<1, B, P> const& _z, C _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<2, A, P> const& _xy, B _z, vec<1, C, P> const& _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<2, A, P> const& _xy, vec<1, B, P> const& _z, vec<1, C, P> const& _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(A _x, vec<2, B, P> const& _yz, C _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<1, A, P> const& _x, vec<2, B, P> const& _yz, C _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(A _x, vec<2, B, P> const& _yz, vec<1, C, P> const& _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<1, A, P> const& _x, vec<2, B, P> const& _yz, vec<1, C, P> const& _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(A _x, B _y, vec<2, C, P> const& _zw); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<1, A, P> const& _x, B _y, vec<2, C, P> const& _zw); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(A _x, vec<1, B, P> const& _y, vec<2, C, P> const& _zw); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<1, A, P> const& _x, vec<1, B, P> const& _y, vec<2, C, P> const& _zw); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<3, A, P> const& _xyz, B _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<3, A, P> const& _xyz, vec<1, B, P> const& _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(A _x, vec<3, B, P> const& _yzw); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<1, A, P> const& _x, vec<3, B, P> const& _yzw); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL vec(vec<2, A, P> const& _xy, vec<2, B, P> const& _zw); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_CTOR_DECL GLM_EXPLICIT vec(vec<4, U, P> const& v); + + // -- Swizzle constructors -- +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + GLM_FUNC_DISCARD_DECL vec(detail::_swizzle<4, T, Q, E0, E1, E2, E3> const& that) + { + *this = that(); + } + + template + GLM_FUNC_DISCARD_DECL vec(detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v, detail::_swizzle<2, T, Q, F0, F1, -1, -2> const& u) + { + *this = vec<4, T, Q>(v(), u()); + } + + template + GLM_FUNC_DISCARD_DECL vec(T const& x, T const& y, detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v) + { + *this = vec<4, T, Q>(x, y, v()); + } + + template + GLM_FUNC_DISCARD_DECL vec(T const& x, detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v, T const& w) + { + *this = vec<4, T, Q>(x, v(), w); + } + + template + GLM_FUNC_DISCARD_DECL vec(detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v, T const& z, T const& w) + { + *this = vec<4, T, Q>(v(), z, w); + } + + template + GLM_FUNC_DISCARD_DECL vec(detail::_swizzle<3, T, Q, E0, E1, E2, -1> const& v, T const& w) + { + *this = vec<4, T, Q>(v(), w); + } + + template + GLM_FUNC_DISCARD_DECL vec(T const& x, detail::_swizzle<3, T, Q, E0, E1, E2, -1> const& v) + { + *this = vec<4, T, Q>(x, v()); + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + + // -- Unary arithmetic operators -- + + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator=(vec<4, T, Q> const& v) GLM_DEFAULT; + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator=(vec<4, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator+=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator+=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator+=(vec<4, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator-=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator-=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator-=(vec<4, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator*=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator*=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator*=(vec<4, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator/=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator/=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator/=(vec<4, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q> & operator++(); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator--(int); + + // -- Unary bit operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator%=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator%=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator%=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator&=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator&=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator&=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator|=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator|=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator|=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator^=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator^=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator^=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator<<=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator<<=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator<<=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator>>=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator>>=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator>>=(vec<4, U, Q> const& v); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator~(vec<4, T, Q> const& v); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, bool, Q> operator&&(vec<4, bool, Q> const& v1, vec<4, bool, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, bool, Q> operator||(vec<4, bool, Q> const& v1, vec<4, bool, Q> const& v2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_vec4.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec4.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec4.inl new file mode 100644 index 0000000..d48fae7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec4.inl @@ -0,0 +1,1142 @@ +/// @ref core + +#include "compute_vector_relational.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_vec4_add + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); + } + }; + + template + struct compute_vec4_sub + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); + } + }; + + template + struct compute_vec4_mul + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); + } + }; + + template + struct compute_vec4_div + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); + } + }; + + template + struct compute_vec4_mod + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x % b.x, a.y % b.y, a.z % b.z, a.w % b.w); + } + }; + + template + struct compute_vec4_and + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x & b.x, a.y & b.y, a.z & b.z, a.w & b.w); + } + }; + + template + struct compute_vec4_or + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x | b.x, a.y | b.y, a.z | b.z, a.w | b.w); + } + }; + + template + struct compute_vec4_xor + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x ^ b.x, a.y ^ b.y, a.z ^ b.z, a.w ^ b.w); + } + }; + + template + struct compute_vec4_shift_left + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x << b.x, a.y << b.y, a.z << b.z, a.w << b.w); + } + }; + + template + struct compute_vec4_shift_right + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x >> b.x, a.y >> b.y, a.z >> b.z, a.w >> b.w); + } + }; + + template + struct compute_vec4_equal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return + detail::compute_equal::is_iec559>::call(v1.x, v2.x) && + detail::compute_equal::is_iec559>::call(v1.y, v2.y) && + detail::compute_equal::is_iec559>::call(v1.z, v2.z) && + detail::compute_equal::is_iec559>::call(v1.w, v2.w); + } + }; + + template + struct compute_vec4_nequal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return !compute_vec4_equal::value, sizeof(T) * 8, detail::is_aligned::value>::call(v1, v2); + } + }; + + template + struct compute_vec4_bitwise_not + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& v) + { + return vec<4, T, Q>(~v.x, ~v.y, ~v.z, ~v.w); + } + }; +}//namespace detail + + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0), y(0), z(0), w(0) +# endif + {} +# endif + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<4, T, Q> const& v) + : x(v.x), y(v.y), z(v.z), w(v.w) + {} +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<4, T, P> const& v) + : x(v.x), y(v.y), z(v.z), w(v.w) + {} + + // -- Explicit basic constructors -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(T scalar) + : x(scalar), y(scalar), z(scalar), w(scalar) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(T _x, T _y, T _z, T _w) + : x(_x), y(_y), z(_z), w(_w) + {} + + // -- Conversion scalar constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.x)) + , z(static_cast(v.x)) + , w(static_cast(v.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, Y _y, Z _z, W _w) + : x(static_cast(_x)) + , y(static_cast(_y)) + , z(static_cast(_z)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, Z _z, W _w) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_z)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, Z _z, W _w) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_z)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z, W _w) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_z)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, Y _y, vec<1, Z, Q> const& _z, W _w) + : x(static_cast(_x)) + , y(static_cast(_y)) + , z(static_cast(_z.x)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z, W _w) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_z.x)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, W _w) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_z.x)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, W _w) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_z.x)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, Z _z, vec<1, W, Q> const& _w) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_z)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, Z _z, vec<1, W, Q> const& _w) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_z)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z, vec<1, W, Q> const& _w) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_z)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, Y _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w) + : x(static_cast(_x)) + , y(static_cast(_y)) + , z(static_cast(_z.x)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_z.x)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_z.x)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_z.x)) + , w(static_cast(_w.x)) + {} + + // -- Conversion vector constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<2, A, P> const& _xy, B _z, C _w) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_z)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<2, A, P> const& _xy, vec<1, B, P> const& _z, C _w) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_z.x)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<2, A, P> const& _xy, B _z, vec<1, C, P> const& _w) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_z)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<2, A, P> const& _xy, vec<1, B, P> const& _z, vec<1, C, P> const& _w) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_z.x)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, vec<2, B, P> const& _yz, C _w) + : x(static_cast(_x)) + , y(static_cast(_yz.x)) + , z(static_cast(_yz.y)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, A, P> const& _x, vec<2, B, P> const& _yz, C _w) + : x(static_cast(_x.x)) + , y(static_cast(_yz.x)) + , z(static_cast(_yz.y)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, vec<2, B, P> const& _yz, vec<1, C, P> const& _w) + : x(static_cast(_x)) + , y(static_cast(_yz.x)) + , z(static_cast(_yz.y)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, A, P> const& _x, vec<2, B, P> const& _yz, vec<1, C, P> const& _w) + : x(static_cast(_x.x)) + , y(static_cast(_yz.x)) + , z(static_cast(_yz.y)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, B _y, vec<2, C, P> const& _zw) + : x(static_cast(_x)) + , y(static_cast(_y)) + , z(static_cast(_zw.x)) + , w(static_cast(_zw.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, A, P> const& _x, B _y, vec<2, C, P> const& _zw) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_zw.x)) + , w(static_cast(_zw.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, vec<1, B, P> const& _y, vec<2, C, P> const& _zw) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_zw.x)) + , w(static_cast(_zw.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, A, P> const& _x, vec<1, B, P> const& _y, vec<2, C, P> const& _zw) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_zw.x)) + , w(static_cast(_zw.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<3, A, P> const& _xyz, B _w) + : x(static_cast(_xyz.x)) + , y(static_cast(_xyz.y)) + , z(static_cast(_xyz.z)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<3, A, P> const& _xyz, vec<1, B, P> const& _w) + : x(static_cast(_xyz.x)) + , y(static_cast(_xyz.y)) + , z(static_cast(_xyz.z)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, vec<3, B, P> const& _yzw) + : x(static_cast(_x)) + , y(static_cast(_yzw.x)) + , z(static_cast(_yzw.y)) + , w(static_cast(_yzw.z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, A, P> const& _x, vec<3, B, P> const& _yzw) + : x(static_cast(_x.x)) + , y(static_cast(_yzw.x)) + , z(static_cast(_yzw.y)) + , w(static_cast(_yzw.z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<2, A, P> const& _xy, vec<2, B, P> const& _zw) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_zw.x)) + , w(static_cast(_zw.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<4, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.y)) + , z(static_cast(v.z)) + , w(static_cast(v.w)) + {} + + // -- Component accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T& vec<4, T, Q>::operator[](typename vec<4, T, Q>::length_type i) + { + GLM_ASSERT_LENGTH(i, this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + case 2: + return z; + case 3: + return w; + } + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& vec<4, T, Q>::operator[](typename vec<4, T, Q>::length_type i) const + { + GLM_ASSERT_LENGTH(i, this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + case 2: + return z; + case 3: + return w; + } + } + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>& vec<4, T, Q>::operator=(vec<4, T, Q> const& v) + { + this->x = v.x; + this->y = v.y; + this->z = v.z; + this->w = v.w; + return *this; + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>& vec<4, T, Q>::operator=(vec<4, U, Q> const& v) + { + this->x = static_cast(v.x); + this->y = static_cast(v.y); + this->z = static_cast(v.z); + this->w = static_cast(v.w); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator+=(U scalar) + { + return (*this = detail::compute_vec4_add::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator+=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_add::value>::call(*this, vec<4, T, Q>(v.x))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator+=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_add::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator-=(U scalar) + { + return (*this = detail::compute_vec4_sub::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator-=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_sub::value>::call(*this, vec<4, T, Q>(v.x))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator-=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_sub::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator*=(U scalar) + { + return (*this = detail::compute_vec4_mul::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator*=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_mul::value>::call(*this, vec<4, T, Q>(v.x))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator*=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_mul::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator/=(U scalar) + { + return (*this = detail::compute_vec4_div::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator/=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_div::value>::call(*this, vec<4, T, Q>(v.x))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator/=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_div::value>::call(*this, vec<4, T, Q>(v))); + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator++() + { + ++this->x; + ++this->y; + ++this->z; + ++this->w; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator--() + { + --this->x; + --this->y; + --this->z; + --this->w; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> vec<4, T, Q>::operator++(int) + { + vec<4, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> vec<4, T, Q>::operator--(int) + { + vec<4, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary bit operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator%=(U scalar) + { + return (*this = detail::compute_vec4_mod::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator%=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_mod::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator%=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_mod::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator&=(U scalar) + { + return (*this = detail::compute_vec4_and::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator&=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_and::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator&=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_and::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator|=(U scalar) + { + return (*this = detail::compute_vec4_or::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator|=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_or::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator|=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_or::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator^=(U scalar) + { + return (*this = detail::compute_vec4_xor::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator^=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_xor::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator^=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_xor::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator<<=(U scalar) + { + return (*this = detail::compute_vec4_shift_left::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator<<=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_shift_left::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator<<=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_shift_left::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator>>=(U scalar) + { + return (*this = detail::compute_vec4_shift_right::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator>>=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_shift_right::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator>>=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_shift_right::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + // -- Unary constant operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v) + { + return vec<4, T, Q>(0) -= v; + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) += scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) += v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(v) += scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v2) += v1; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) += v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) -= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) -= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) -= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) -= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) -= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) *= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) *= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(v) *= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v2) *= v1; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) *= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) /= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) /= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator/(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) /= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator/(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) /= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) /= v2; + } + + // -- Binary bit operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) %= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) %= v2.x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator%(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) %= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator%(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar.x) %= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) %= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) &= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<4, T, Q>(v) &= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator&(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) &= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator&(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) &= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) &= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) |= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) |= v2.x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator|(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) |= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator|(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) |= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) |= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) ^= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) ^= v2.x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator^(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) ^= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator^(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) ^= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) ^= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) <<= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) <<= v2.x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator<<(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) <<= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) <<= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) <<= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) >>= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) >>= v2.x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator>>(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) >>= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) >>= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) >>= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator~(vec<4, T, Q> const& v) + { + return detail::compute_vec4_bitwise_not::value, sizeof(T) * 8, detail::is_aligned::value>::call(v); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return detail::compute_vec4_equal::value, sizeof(T) * 8, detail::is_aligned::value>::call(v1, v2); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return detail::compute_vec4_nequal::value, sizeof(T) * 8, detail::is_aligned::value>::call(v1, v2); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> operator&&(vec<4, bool, Q> const& v1, vec<4, bool, Q> const& v2) + { + return vec<4, bool, Q>(v1.x && v2.x, v1.y && v2.y, v1.z && v2.z, v1.w && v2.w); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> operator||(vec<4, bool, Q> const& v1, vec<4, bool, Q> const& v2) + { + return vec<4, bool, Q>(v1.x || v2.x, v1.y || v2.y, v1.z || v2.z, v1.w || v2.w); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "type_vec4_simd.inl" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec4_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec4_simd.inl new file mode 100644 index 0000000..816ef45 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec4_simd.inl @@ -0,0 +1,788 @@ +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm { + namespace detail + { +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + struct _swizzle_base1<4, float, Q, E0, E1, E2, E3, true> : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER vec<4, float, Q> operator ()() const + { + __m128 data = *reinterpret_cast<__m128 const*>(&this->_buffer); + + vec<4, float, Q> Result; +# if GLM_ARCH & GLM_ARCH_AVX_BIT + Result.data = _mm_permute_ps(data, _MM_SHUFFLE(E3, E2, E1, E0)); +# else + Result.data = _mm_shuffle_ps(data, data, _MM_SHUFFLE(E3, E2, E1, E0)); +# endif + return Result; + } + }; + + template + struct _swizzle_base1<4, int, Q, E0, E1, E2, E3, true> : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER vec<4, int, Q> operator ()() const + { + __m128i data = *reinterpret_cast<__m128i const*>(&this->_buffer); + + vec<4, int, Q> Result; + Result.data = _mm_shuffle_epi32(data, _MM_SHUFFLE(E3, E2, E1, E0)); + return Result; + } + }; + + template + struct _swizzle_base1<4, uint, Q, E0, E1, E2, E3, true> : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER vec<4, uint, Q> operator ()() const + { + __m128i data = *reinterpret_cast<__m128i const*>(&this->_buffer); + + vec<4, uint, Q> Result; + Result.data = _mm_shuffle_epi32(data, _MM_SHUFFLE(E3, E2, E1, E0)); + return Result; + } + }; +# endif// GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + + template + struct compute_vec4_add + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = _mm_add_ps(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_vec4_add + { + static vec<4, double, Q> call(vec<4, double, Q> const& a, vec<4, double, Q> const& b) + { + vec<4, double, Q> Result; + Result.data = _mm256_add_pd(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_sub + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = _mm_sub_ps(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_vec4_sub + { + static vec<4, double, Q> call(vec<4, double, Q> const& a, vec<4, double, Q> const& b) + { + vec<4, double, Q> Result; + Result.data = _mm256_sub_pd(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_mul + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = _mm_mul_ps(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_vec4_mul + { + static vec<4, double, Q> call(vec<4, double, Q> const& a, vec<4, double, Q> const& b) + { + vec<4, double, Q> Result; + Result.data = _mm256_mul_pd(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_div + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = _mm_div_ps(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_vec4_div + { + static vec<4, double, Q> call(vec<4, double, Q> const& a, vec<4, double, Q> const& b) + { + vec<4, double, Q> Result; + Result.data = _mm256_div_pd(a.data, b.data); + return Result; + } + }; +# endif + + template<> + struct compute_vec4_div + { + static vec<4, float, aligned_lowp> call(vec<4, float, aligned_lowp> const& a, vec<4, float, aligned_lowp> const& b) + { + vec<4, float, aligned_lowp> Result; + Result.data = _mm_mul_ps(a.data, _mm_rcp_ps(b.data)); + return Result; + } + }; + + template + struct compute_vec4_and + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm_and_si128(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template + struct compute_vec4_and + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm256_and_si256(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_or + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm_or_si128(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template + struct compute_vec4_or + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm256_or_si256(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_xor + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm_xor_si128(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template + struct compute_vec4_xor + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm256_xor_si256(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_shift_left + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm_sll_epi32(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template + struct compute_vec4_shift_left + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm256_sll_epi64(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_shift_right + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm_srl_epi32(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template + struct compute_vec4_shift_right + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm256_srl_epi64(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_bitwise_not + { + static vec<4, T, Q> call(vec<4, T, Q> const& v) + { + vec<4, T, Q> Result; + Result.data = _mm_xor_si128(v.data, _mm_set1_epi32(-1)); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template + struct compute_vec4_bitwise_not + { + static vec<4, T, Q> call(vec<4, T, Q> const& v) + { + vec<4, T, Q> Result; + Result.data = _mm256_xor_si256(v.data, _mm_set1_epi32(-1)); + return Result; + } + }; +# endif + + template + struct compute_vec4_equal + { + static bool call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + return _mm_movemask_ps(_mm_cmpneq_ps(v1.data, v2.data)) == 0; + } + }; + +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + template + struct compute_vec4_equal + { + static bool call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + //return _mm_movemask_epi8(_mm_cmpeq_epi32(v1.data, v2.data)) != 0; + __m128i neq = _mm_xor_si128(v1.data, v2.data); + return _mm_test_all_zeros(neq, neq) == 0; + } + }; +# endif + + template + struct compute_vec4_nequal + { + static bool call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + return _mm_movemask_ps(_mm_cmpneq_ps(v1.data, v2.data)) != 0; + } + }; + +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + template + struct compute_vec4_nequal + { + static bool call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + //return _mm_movemask_epi8(_mm_cmpneq_epi32(v1.data, v2.data)) != 0; + __m128i neq = _mm_xor_si128(v1.data, v2.data); + return _mm_test_all_zeros(neq, neq) != 0; + } + }; +# endif + }//namespace detail + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_lowp>::vec(float _s) : + data(_mm_set1_ps(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_mediump>::vec(float _s) : + data(_mm_set1_ps(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(float _s) : + data(_mm_set1_ps(_s)) + {} + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, double, aligned_lowp>::vec(double _s) : + data(_mm256_set1_pd(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, double, aligned_mediump>::vec(double _s) : + data(_mm256_set1_pd(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, double, aligned_highp>::vec(double _s) : + data(_mm256_set1_pd(_s)) + {} +# endif + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_lowp>::vec(int _s) : + data(_mm_set1_epi32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_mediump>::vec(int _s) : + data(_mm_set1_epi32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_highp>::vec(int _s) : + data(_mm_set1_epi32(_s)) + {} + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, detail::int64, aligned_lowp>::vec(detail::int64 _s) : + data(_mm256_set1_epi64x(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, detail::int64, aligned_mediump>::vec(detail::int64 _s) : + data(_mm256_set1_epi64x(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, detail::int64, aligned_highp>::vec(detail::int64 _s) : + data(_mm256_set1_epi64x(_s)) + {} +# endif + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_lowp>::vec(float _x, float _y, float _z, float _w) : + data(_mm_set_ps(_w, _z, _y, _x)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_mediump>::vec(float _x, float _y, float _z, float _w) : + data(_mm_set_ps(_w, _z, _y, _x)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(float _x, float _y, float _z, float _w) : + data(_mm_set_ps(_w, _z, _y, _x)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_lowp>::vec(int _x, int _y, int _z, int _w) : + data(_mm_set_epi32(_w, _z, _y, _x)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_mediump>::vec(int _x, int _y, int _z, int _w) : + data(_mm_set_epi32(_w, _z, _y, _x)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_highp>::vec(int _x, int _y, int _z, int _w) : + data(_mm_set_epi32(_w, _z, _y, _x)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_lowp>::vec(int _x, int _y, int _z, int _w) : + data(_mm_cvtepi32_ps(_mm_set_epi32(_w, _z, _y, _x))) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_mediump>::vec(int _x, int _y, int _z, int _w) : + data(_mm_cvtepi32_ps(_mm_set_epi32(_w, _z, _y, _x))) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(int _x, int _y, int _z, int _w) : + data(_mm_cvtepi32_ps(_mm_set_epi32(_w, _z, _y, _x))) + {} +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT + +#if GLM_ARCH & GLM_ARCH_NEON_BIT +namespace glm { + namespace detail { + + template + struct compute_vec4_add + { + static + vec<4, float, Q> + call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = vaddq_f32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_add + { + static + vec<4, uint, Q> + call(vec<4, uint, Q> const& a, vec<4, uint, Q> const& b) + { + vec<4, uint, Q> Result; + Result.data = vaddq_u32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_add + { + static + vec<4, int, Q> + call(vec<4, int, Q> const& a, vec<4, int, Q> const& b) + { + vec<4, int, Q> Result; + Result.data = vaddq_s32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_sub + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = vsubq_f32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_sub + { + static vec<4, uint, Q> call(vec<4, uint, Q> const& a, vec<4, uint, Q> const& b) + { + vec<4, uint, Q> Result; + Result.data = vsubq_u32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_sub + { + static vec<4, int, Q> call(vec<4, int, Q> const& a, vec<4, int, Q> const& b) + { + vec<4, int, Q> Result; + Result.data = vsubq_s32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_mul + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = vmulq_f32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_mul + { + static vec<4, uint, Q> call(vec<4, uint, Q> const& a, vec<4, uint, Q> const& b) + { + vec<4, uint, Q> Result; + Result.data = vmulq_u32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_mul + { + static vec<4, int, Q> call(vec<4, int, Q> const& a, vec<4, int, Q> const& b) + { + vec<4, int, Q> Result; + Result.data = vmulq_s32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_div + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + Result.data = vdivq_f32(a.data, b.data); +#else + /* Arm assembler reference: + * + * The Newton-Raphson iteration: x[n+1] = x[n] * (2 - d * x[n]) + * converges to (1/d) if x0 is the result of VRECPE applied to d. + * + * Note: The precision usually improves with two interactions, but more than two iterations are not helpful. */ + float32x4_t x = vrecpeq_f32(b.data); + x = vmulq_f32(vrecpsq_f32(b.data, x), x); + x = vmulq_f32(vrecpsq_f32(b.data, x), x); + Result.data = vmulq_f32(a.data, x); +#endif + return Result; + } + }; + + template + struct compute_vec4_equal + { + static bool call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + uint32x4_t cmp = vceqq_f32(v1.data, v2.data); +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + cmp = vpminq_u32(cmp, cmp); + cmp = vpminq_u32(cmp, cmp); + uint32_t r = cmp[0]; +#else + uint32x2_t cmpx2 = vpmin_u32(vget_low_u32(cmp), vget_high_u32(cmp)); + cmpx2 = vpmin_u32(cmpx2, cmpx2); + uint32_t r = cmpx2[0]; +#endif + return r == ~0u; + } + }; + + template + struct compute_vec4_equal + { + static bool call(vec<4, uint, Q> const& v1, vec<4, uint, Q> const& v2) + { + uint32x4_t cmp = vceqq_u32(v1.data, v2.data); +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + cmp = vpminq_u32(cmp, cmp); + cmp = vpminq_u32(cmp, cmp); + uint32_t r = cmp[0]; +#else + uint32x2_t cmpx2 = vpmin_u32(vget_low_u32(cmp), vget_high_u32(cmp)); + cmpx2 = vpmin_u32(cmpx2, cmpx2); + uint32_t r = cmpx2[0]; +#endif + return r == ~0u; + } + }; + + template + struct compute_vec4_equal + { + static bool call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + uint32x4_t cmp = vceqq_s32(v1.data, v2.data); +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + cmp = vpminq_u32(cmp, cmp); + cmp = vpminq_u32(cmp, cmp); + uint32_t r = cmp[0]; +#else + uint32x2_t cmpx2 = vpmin_u32(vget_low_u32(cmp), vget_high_u32(cmp)); + cmpx2 = vpmin_u32(cmpx2, cmpx2); + uint32_t r = cmpx2[0]; +#endif + return r == ~0u; + } + }; + + template + struct compute_vec4_nequal + { + static bool call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + return !compute_vec4_equal::call(v1, v2); + } + }; + + template + struct compute_vec4_nequal + { + static bool call(vec<4, uint, Q> const& v1, vec<4, uint, Q> const& v2) + { + return !compute_vec4_equal::call(v1, v2); + } + }; + + template + struct compute_vec4_nequal + { + static bool call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + return !compute_vec4_equal::call(v1, v2); + } + }; + + }//namespace detail + +#if !GLM_CONFIG_XYZW_ONLY + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_lowp>::vec(float _s) : + data(vdupq_n_f32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_mediump>::vec(float _s) : + data(vdupq_n_f32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(float _s) : + data(vdupq_n_f32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_lowp>::vec(int _s) : + data(vdupq_n_s32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_mediump>::vec(int _s) : + data(vdupq_n_s32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_highp>::vec(int _s) : + data(vdupq_n_s32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, uint, aligned_lowp>::vec(uint _s) : + data(vdupq_n_u32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, uint, aligned_mediump>::vec(uint _s) : + data(vdupq_n_u32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, uint, aligned_highp>::vec(uint _s) : + data(vdupq_n_u32(_s)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(const vec<4, float, aligned_highp>& rhs) : + data(rhs.data) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(const vec<4, int, aligned_highp>& rhs) : + data(vcvtq_f32_s32(rhs.data)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(const vec<4, uint, aligned_highp>& rhs) : + data(vcvtq_f32_u32(rhs.data)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_lowp>::vec(int _x, int _y, int _z, int _w) : + data(vcvtq_f32_s32(vec<4, int, aligned_lowp>(_x, _y, _z, _w).data)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_mediump>::vec(int _x, int _y, int _z, int _w) : + data(vcvtq_f32_s32(vec<4, int, aligned_mediump>(_x, _y, _z, _w).data)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(int _x, int _y, int _z, int _w) : + data(vcvtq_f32_s32(vec<4, int, aligned_highp>(_x, _y, _z, _w).data)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_lowp>::vec(uint _x, uint _y, uint _z, uint _w) : + data(vcvtq_f32_u32(vec<4, uint, aligned_lowp>(_x, _y, _z, _w).data)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_mediump>::vec(uint _x, uint _y, uint _z, uint _w) : + data(vcvtq_f32_u32(vec<4, uint, aligned_mediump>(_x, _y, _z, _w).data)) + {} + + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(uint _x, uint _y, uint _z, uint _w) : + data(vcvtq_f32_u32(vec<4, uint, aligned_highp>(_x, _y, _z, _w).data)) + {} + +#endif +}//namespace glm + +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/exponential.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/exponential.hpp new file mode 100644 index 0000000..1614f76 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/exponential.hpp @@ -0,0 +1,110 @@ +/// @ref core +/// @file glm/exponential.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions +/// +/// @defgroup core_func_exponential Exponential functions +/// @ingroup core +/// +/// Provides GLSL exponential functions +/// +/// These all operate component-wise. The description is per component. +/// +/// Include to use these core features. + +#pragma once + +#include "detail/type_vec1.hpp" +#include "detail/type_vec2.hpp" +#include "detail/type_vec3.hpp" +#include "detail/type_vec4.hpp" +#include + +namespace glm +{ + /// @addtogroup core_func_exponential + /// @{ + + /// Returns 'base' raised to the power 'exponent'. + /// + /// @param base Floating point value. pow function is defined for input values of 'base' defined in the range (inf-, inf+) in the limit of the type qualifier. + /// @param exponent Floating point value representing the 'exponent'. + /// + /// @see GLSL pow man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec pow(vec const& base, vec const& exponent); + + /// Returns the natural exponentiation of v, i.e., e^v. + /// + /// @param v exp function is defined for input values of v defined in the range (inf-, inf+) in the limit of the type qualifier. + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL exp man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec exp(vec const& v); + + /// Returns the natural logarithm of v, i.e., + /// returns the value y which satisfies the equation x = e^y. + /// Results are undefined if v <= 0. + /// + /// @param v log function is defined for input values of v defined in the range (0, inf+) in the limit of the type qualifier. + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL log man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec log(vec const& v); + + /// Returns 2 raised to the v power. + /// + /// @param v exp2 function is defined for input values of v defined in the range (inf-, inf+) in the limit of the type qualifier. + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL exp2 man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec exp2(vec const& v); + + /// Returns the base 2 log of x, i.e., returns the value y, + /// which satisfies the equation x = 2 ^ y. + /// + /// @param v log2 function is defined for input values of v defined in the range (0, inf+) in the limit of the type qualifier. + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL log2 man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec log2(vec const& v); + + /// Returns the positive square root of v. + /// + /// @param v sqrt function is defined for input values of v defined in the range [0, inf+) in the limit of the type qualifier. + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL sqrt man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec sqrt(vec const& v); + + /// Returns the reciprocal of the positive square root of v. + /// + /// @param v inversesqrt function is defined for input values of v defined in the range [0, inf+) in the limit of the type qualifier. + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL inversesqrt man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec inversesqrt(vec const& v); + + /// @} +}//namespace glm + +#include "detail/func_exponential.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext.hpp new file mode 100644 index 0000000..f9ac369 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext.hpp @@ -0,0 +1,267 @@ +/// @file glm/ext.hpp +/// +/// @ref core (Dependence) + +#include "detail/setup.hpp" + +#pragma once + +#include "glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_MESSAGE_EXT_INCLUDED_DISPLAYED) +# define GLM_MESSAGE_EXT_INCLUDED_DISPLAYED +# pragma message("GLM: All extensions included (not recommended)") +#endif//GLM_MESSAGES + +#include "./ext/matrix_clip_space.hpp" +#include "./ext/matrix_common.hpp" + +#include "./ext/matrix_double2x2.hpp" +#include "./ext/matrix_double2x2_precision.hpp" +#include "./ext/matrix_double2x3.hpp" +#include "./ext/matrix_double2x3_precision.hpp" +#include "./ext/matrix_double2x4.hpp" +#include "./ext/matrix_double2x4_precision.hpp" +#include "./ext/matrix_double3x2.hpp" +#include "./ext/matrix_double3x2_precision.hpp" +#include "./ext/matrix_double3x3.hpp" +#include "./ext/matrix_double3x3_precision.hpp" +#include "./ext/matrix_double3x4.hpp" +#include "./ext/matrix_double3x4_precision.hpp" +#include "./ext/matrix_double4x2.hpp" +#include "./ext/matrix_double4x2_precision.hpp" +#include "./ext/matrix_double4x3.hpp" +#include "./ext/matrix_double4x3_precision.hpp" +#include "./ext/matrix_double4x4.hpp" +#include "./ext/matrix_double4x4_precision.hpp" + +#include "./ext/matrix_float2x2.hpp" +#include "./ext/matrix_float2x2_precision.hpp" +#include "./ext/matrix_float2x3.hpp" +#include "./ext/matrix_float2x3_precision.hpp" +#include "./ext/matrix_float2x4.hpp" +#include "./ext/matrix_float2x4_precision.hpp" +#include "./ext/matrix_float3x2.hpp" +#include "./ext/matrix_float3x2_precision.hpp" +#include "./ext/matrix_float3x3.hpp" +#include "./ext/matrix_float3x3_precision.hpp" +#include "./ext/matrix_float3x4.hpp" +#include "./ext/matrix_float3x4_precision.hpp" +#include "./ext/matrix_float4x2.hpp" +#include "./ext/matrix_float4x2_precision.hpp" +#include "./ext/matrix_float4x3.hpp" +#include "./ext/matrix_float4x3_precision.hpp" +#include "./ext/matrix_float4x4.hpp" +#include "./ext/matrix_float4x4_precision.hpp" + +#include "./ext/matrix_int2x2.hpp" +#include "./ext/matrix_int2x2_sized.hpp" +#include "./ext/matrix_int2x3.hpp" +#include "./ext/matrix_int2x3_sized.hpp" +#include "./ext/matrix_int2x4.hpp" +#include "./ext/matrix_int2x4_sized.hpp" +#include "./ext/matrix_int3x2.hpp" +#include "./ext/matrix_int3x2_sized.hpp" +#include "./ext/matrix_int3x3.hpp" +#include "./ext/matrix_int3x3_sized.hpp" +#include "./ext/matrix_int3x4.hpp" +#include "./ext/matrix_int3x4_sized.hpp" +#include "./ext/matrix_int4x2.hpp" +#include "./ext/matrix_int4x2_sized.hpp" +#include "./ext/matrix_int4x3.hpp" +#include "./ext/matrix_int4x3_sized.hpp" +#include "./ext/matrix_int4x4.hpp" +#include "./ext/matrix_int4x4_sized.hpp" + +#include "./ext/matrix_uint2x2.hpp" +#include "./ext/matrix_uint2x2_sized.hpp" +#include "./ext/matrix_uint2x3.hpp" +#include "./ext/matrix_uint2x3_sized.hpp" +#include "./ext/matrix_uint2x4.hpp" +#include "./ext/matrix_uint2x4_sized.hpp" +#include "./ext/matrix_uint3x2.hpp" +#include "./ext/matrix_uint3x2_sized.hpp" +#include "./ext/matrix_uint3x3.hpp" +#include "./ext/matrix_uint3x3_sized.hpp" +#include "./ext/matrix_uint3x4.hpp" +#include "./ext/matrix_uint3x4_sized.hpp" +#include "./ext/matrix_uint4x2.hpp" +#include "./ext/matrix_uint4x2_sized.hpp" +#include "./ext/matrix_uint4x3.hpp" +#include "./ext/matrix_uint4x3_sized.hpp" +#include "./ext/matrix_uint4x4.hpp" +#include "./ext/matrix_uint4x4_sized.hpp" + +#include "./ext/matrix_projection.hpp" +#include "./ext/matrix_relational.hpp" +#include "./ext/matrix_transform.hpp" + +#include "./ext/quaternion_common.hpp" +#include "./ext/quaternion_double.hpp" +#include "./ext/quaternion_double_precision.hpp" +#include "./ext/quaternion_float.hpp" +#include "./ext/quaternion_float_precision.hpp" +#include "./ext/quaternion_exponential.hpp" +#include "./ext/quaternion_geometric.hpp" +#include "./ext/quaternion_relational.hpp" +#include "./ext/quaternion_transform.hpp" +#include "./ext/quaternion_trigonometric.hpp" + +#include "./ext/scalar_common.hpp" +#include "./ext/scalar_constants.hpp" +#include "./ext/scalar_integer.hpp" +#include "./ext/scalar_packing.hpp" +#include "./ext/scalar_reciprocal.hpp" +#include "./ext/scalar_relational.hpp" +#include "./ext/scalar_ulp.hpp" + +#include "./ext/scalar_int_sized.hpp" +#include "./ext/scalar_uint_sized.hpp" + +#include "./ext/vector_common.hpp" +#include "./ext/vector_integer.hpp" +#include "./ext/vector_packing.hpp" +#include "./ext/vector_reciprocal.hpp" +#include "./ext/vector_relational.hpp" +#include "./ext/vector_ulp.hpp" + +#include "./ext/vector_bool1.hpp" +#include "./ext/vector_bool1_precision.hpp" +#include "./ext/vector_bool2.hpp" +#include "./ext/vector_bool2_precision.hpp" +#include "./ext/vector_bool3.hpp" +#include "./ext/vector_bool3_precision.hpp" +#include "./ext/vector_bool4.hpp" +#include "./ext/vector_bool4_precision.hpp" + +#include "./ext/vector_double1.hpp" +#include "./ext/vector_double1_precision.hpp" +#include "./ext/vector_double2.hpp" +#include "./ext/vector_double2_precision.hpp" +#include "./ext/vector_double3.hpp" +#include "./ext/vector_double3_precision.hpp" +#include "./ext/vector_double4.hpp" +#include "./ext/vector_double4_precision.hpp" + +#include "./ext/vector_float1.hpp" +#include "./ext/vector_float1_precision.hpp" +#include "./ext/vector_float2.hpp" +#include "./ext/vector_float2_precision.hpp" +#include "./ext/vector_float3.hpp" +#include "./ext/vector_float3_precision.hpp" +#include "./ext/vector_float4.hpp" +#include "./ext/vector_float4_precision.hpp" + +#include "./ext/vector_int1.hpp" +#include "./ext/vector_int1_sized.hpp" +#include "./ext/vector_int2.hpp" +#include "./ext/vector_int2_sized.hpp" +#include "./ext/vector_int3.hpp" +#include "./ext/vector_int3_sized.hpp" +#include "./ext/vector_int4.hpp" +#include "./ext/vector_int4_sized.hpp" + +#include "./ext/vector_uint1.hpp" +#include "./ext/vector_uint1_sized.hpp" +#include "./ext/vector_uint2.hpp" +#include "./ext/vector_uint2_sized.hpp" +#include "./ext/vector_uint3.hpp" +#include "./ext/vector_uint3_sized.hpp" +#include "./ext/vector_uint4.hpp" +#include "./ext/vector_uint4_sized.hpp" + +#include "./gtc/bitfield.hpp" +#include "./gtc/color_space.hpp" +#include "./gtc/constants.hpp" +#include "./gtc/epsilon.hpp" +#include "./gtc/integer.hpp" +#include "./gtc/matrix_access.hpp" +#include "./gtc/matrix_integer.hpp" +#include "./gtc/matrix_inverse.hpp" +#include "./gtc/matrix_transform.hpp" +#include "./gtc/noise.hpp" +#include "./gtc/packing.hpp" +#include "./gtc/quaternion.hpp" +#include "./gtc/random.hpp" +#include "./gtc/reciprocal.hpp" +#include "./gtc/round.hpp" +#include "./gtc/type_precision.hpp" +#include "./gtc/type_ptr.hpp" +#include "./gtc/ulp.hpp" +#include "./gtc/vec1.hpp" +#if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE +# include "./gtc/type_aligned.hpp" +#endif + +#ifdef GLM_ENABLE_EXPERIMENTAL +#include "./gtx/associated_min_max.hpp" +#include "./gtx/bit.hpp" +#include "./gtx/closest_point.hpp" +#include "./gtx/color_encoding.hpp" +#include "./gtx/color_space.hpp" +#include "./gtx/color_space_YCoCg.hpp" +#include "./gtx/common.hpp" +#include "./gtx/compatibility.hpp" +#include "./gtx/component_wise.hpp" +#include "./gtx/dual_quaternion.hpp" +#include "./gtx/easing.hpp" +#include "./gtx/euler_angles.hpp" +#include "./gtx/extend.hpp" +#include "./gtx/extended_min_max.hpp" +#include "./gtx/fast_exponential.hpp" +#include "./gtx/fast_square_root.hpp" +#include "./gtx/fast_trigonometry.hpp" +#include "./gtx/functions.hpp" +#include "./gtx/gradient_paint.hpp" +#include "./gtx/handed_coordinate_space.hpp" + +#if __cplusplus >= 201103L +#include "./gtx/hash.hpp" +#endif + +#include "./gtx/integer.hpp" +#include "./gtx/intersect.hpp" +#include "./gtx/io.hpp" +#include "./gtx/log_base.hpp" +#include "./gtx/matrix_cross_product.hpp" +#include "./gtx/matrix_decompose.hpp" +#include "./gtx/matrix_factorisation.hpp" +#include "./gtx/matrix_interpolation.hpp" +#include "./gtx/matrix_major_storage.hpp" +#include "./gtx/matrix_operation.hpp" +#include "./gtx/matrix_query.hpp" +#include "./gtx/mixed_product.hpp" +#include "./gtx/norm.hpp" +#include "./gtx/normal.hpp" +#include "./gtx/normalize_dot.hpp" +#include "./gtx/number_precision.hpp" +#include "./gtx/optimum_pow.hpp" +#include "./gtx/orthonormalize.hpp" +#include "./gtx/pca.hpp" +#include "./gtx/perpendicular.hpp" +#include "./gtx/polar_coordinates.hpp" +#include "./gtx/projection.hpp" +#include "./gtx/quaternion.hpp" +#include "./gtx/raw_data.hpp" +#include "./gtx/rotate_normalized_axis.hpp" +#include "./gtx/rotate_vector.hpp" +#include "./gtx/spline.hpp" +#include "./gtx/std_based_type.hpp" +#if !((GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP)) +# include "./gtx/string_cast.hpp" +#endif +#include "./gtx/transform.hpp" +#include "./gtx/transform2.hpp" +#include "./gtx/vec_swizzle.hpp" +#include "./gtx/vector_angle.hpp" +#include "./gtx/vector_query.hpp" +#include "./gtx/wrap.hpp" + +#if GLM_HAS_TEMPLATE_ALIASES +# include "./gtx/scalar_multiplication.hpp" +#endif + +#if GLM_HAS_RANGE_FOR +# include "./gtx/range.hpp" +#endif +#endif//GLM_ENABLE_EXPERIMENTAL diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/_matrix_vectorize.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/_matrix_vectorize.hpp new file mode 100644 index 0000000..0d08117 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/_matrix_vectorize.hpp @@ -0,0 +1,128 @@ +#pragma once + +namespace glm { + + namespace detail { + + template class mat, length_t C, length_t R, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<2, 2, T, Q> call(Ret (*Func)(T x), mat<2, 2, T, Q> const &x) { + return mat<2, 2, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), + Func(x[1][0]), Func(x[1][1]) + ); + } + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<2, 3, T, Q> call(Ret (*Func)(T x), mat<2, 3, T, Q> const &x) { + return mat<2, 3, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), Func(x[0][2]), + Func(x[1][0]), Func(x[1][1]), Func(x[1][2]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<2, 4, T, Q> call(Ret (*Func)(T x), mat<2, 4, T, Q> const &x) { + return mat<2, 4, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), Func(x[0][2]), Func(x[0][3]), + Func(x[1][0]), Func(x[1][1]), Func(x[1][2]), Func(x[1][3]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<3, 2, T, Q> call(Ret (*Func)(T x), mat<3, 2, T, Q> const &x) { + return mat<3, 2, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), + Func(x[1][0]), Func(x[1][1]), + Func(x[2][0]), Func(x[2][1]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<3, 3, T, Q> call(Ret (*Func)(T x), mat<3, 3, T, Q> const &x) { + return mat<3, 3, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), Func(x[0][2]), + Func(x[1][0]), Func(x[1][1]), Func(x[1][2]), + Func(x[2][0]), Func(x[2][1]), Func(x[2][2]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<3, 4, T, Q> call(Ret (*Func)(T x), mat<3, 4, T, Q> const &x) { + return mat<3, 4, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), Func(x[0][2]), Func(x[0][3]), + Func(x[1][0]), Func(x[1][1]), Func(x[1][2]), Func(x[1][3]), + Func(x[2][0]), Func(x[2][1]), Func(x[2][2]), Func(x[2][3]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<4, 2, T, Q> call(Ret (*Func)(T x), mat<4, 2, T, Q> const &x) { + return mat<4, 2, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), + Func(x[1][0]), Func(x[1][1]), + Func(x[2][0]), Func(x[2][1]), + Func(x[3][0]), Func(x[3][1]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<4, 3, T, Q> call(Ret (*Func)(T x), mat<4, 3, T, Q> const &x) { + return mat<4, 3, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), Func(x[0][2]), + Func(x[1][0]), Func(x[1][1]), Func(x[1][2]), + Func(x[2][0]), Func(x[2][1]), Func(x[2][2]), + Func(x[3][0]), Func(x[3][1]), Func(x[3][2]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<4, 4, T, Q> call(Ret (*Func)(T x), mat<4, 4, T, Q> const &x) { + return mat<4, 4, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), Func(x[0][2]), Func(x[0][3]), + Func(x[1][0]), Func(x[1][1]), Func(x[1][2]), Func(x[1][3]), + Func(x[2][0]), Func(x[2][1]), Func(x[2][2]), Func(x[2][3]), + Func(x[3][0]), Func(x[3][1]), Func(x[3][2]), Func(x[3][3]) + ); + } + + }; + + } + +}// namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_clip_space.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_clip_space.hpp new file mode 100644 index 0000000..43579b8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_clip_space.hpp @@ -0,0 +1,522 @@ +/// @ref ext_matrix_clip_space +/// @file glm/ext/matrix_clip_space.hpp +/// +/// @defgroup ext_matrix_clip_space GLM_EXT_matrix_clip_space +/// @ingroup ext +/// +/// Defines functions that generate clip space transformation matrices. +/// +/// The matrices generated by this extension use standard OpenGL fixed-function +/// conventions. For example, the lookAt function generates a transform from world +/// space into the specific eye space that the projective matrix functions +/// (perspective, ortho, etc) are designed to expect. The OpenGL compatibility +/// specifications defines the particular layout of this eye space. +/// +/// Include to use the features of this extension. +/// +/// @see ext_matrix_transform +/// @see ext_matrix_projection + +#pragma once + +// Dependencies +#include "../ext/scalar_constants.hpp" +#include "../geometric.hpp" +#include "../trigonometric.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_clip_space extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_clip_space + /// @{ + + /// Creates a matrix for projecting two-dimensional coordinates onto the screen. + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top, T const& zNear, T const& zFar) + /// @see gluOrtho2D man page + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> ortho( + T left, T right, T bottom, T top); + + /// Creates a matrix for an orthographic parallel viewing volume, using left-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoLH_ZO( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume using left-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoLH_NO( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using right-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoRH_ZO( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using right-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoRH_NO( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using left-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoZO( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoNO( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using left-handed coordinates. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoLH( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using right-handed coordinates. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoRH( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using the default handedness and default near and far clip planes definition. + /// To change default handedness use GLM_FORCE_LEFT_HANDED. To change default near and far clip planes definition use GLM_FORCE_DEPTH_ZERO_TO_ONE. + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + /// @see glOrtho man page + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> ortho( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a left-handed frustum matrix. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumLH_ZO( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a left-handed frustum matrix. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumLH_NO( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a right-handed frustum matrix. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumRH_ZO( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a right-handed frustum matrix. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumRH_NO( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a frustum matrix using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumZO( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a frustum matrix using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumNO( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a left-handed frustum matrix. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumLH( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a right-handed frustum matrix. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumRH( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a frustum matrix with default handedness, using the default handedness and default near and far clip planes definition. + /// To change default handedness use GLM_FORCE_LEFT_HANDED. To change default near and far clip planes definition use GLM_FORCE_DEPTH_ZERO_TO_ONE. + /// + /// @tparam T A floating-point scalar type + /// @see glFrustum man page + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustum( + T left, T right, T bottom, T top, T near, T far); + + + /// Creates a matrix for a right-handed, symmetric perspective-view frustum. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveRH_ZO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a right-handed, symmetric perspective-view frustum. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveRH_NO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a left-handed, symmetric perspective-view frustum. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveLH_ZO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a left-handed, symmetric perspective-view frustum. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveLH_NO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a symmetric perspective-view frustum using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveZO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a symmetric perspective-view frustum using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveNO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a right-handed, symmetric perspective-view frustum. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveRH( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a left-handed, symmetric perspective-view frustum. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveLH( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a symmetric perspective-view frustum based on the default handedness and default near and far clip planes definition. + /// To change default handedness use GLM_FORCE_LEFT_HANDED. To change default near and far clip planes definition use GLM_FORCE_DEPTH_ZERO_TO_ONE. + /// + /// @param fovy Specifies the field of view angle in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + /// @see gluPerspective man page + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspective( + T fovy, T aspect, T near, T far); + + /// Builds a perspective projection matrix based on a field of view using right-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovRH_ZO( + T fov, T width, T height, T near, T far); + + /// Builds a perspective projection matrix based on a field of view using right-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovRH_NO( + T fov, T width, T height, T near, T far); + + /// Builds a perspective projection matrix based on a field of view using left-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovLH_ZO( + T fov, T width, T height, T near, T far); + + /// Builds a perspective projection matrix based on a field of view using left-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovLH_NO( + T fov, T width, T height, T near, T far); + + /// Builds a perspective projection matrix based on a field of view using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovZO( + T fov, T width, T height, T near, T far); + + /// Builds a perspective projection matrix based on a field of view using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovNO( + T fov, T width, T height, T near, T far); + + /// Builds a right-handed perspective projection matrix based on a field of view. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovRH( + T fov, T width, T height, T near, T far); + + /// Builds a left-handed perspective projection matrix based on a field of view. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovLH( + T fov, T width, T height, T near, T far); + + /// Builds a perspective projection matrix based on a field of view and the default handedness and default near and far clip planes definition. + /// To change default handedness use GLM_FORCE_LEFT_HANDED. To change default near and far clip planes definition use GLM_FORCE_DEPTH_ZERO_TO_ONE. + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFov( + T fov, T width, T height, T near, T far); + + /// Creates a matrix for a left-handed, symmetric perspective-view frustum with far plane at infinite. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> infinitePerspectiveLH( + T fovy, T aspect, T near); + + /// Creates a matrix for a right-handed, symmetric perspective-view frustum with far plane at infinite. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> infinitePerspectiveRH( + T fovy, T aspect, T near); + + /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite with default handedness. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> infinitePerspective( + T fovy, T aspect, T near); + + /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite for graphics hardware that doesn't support depth clamping. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> tweakedInfinitePerspective( + T fovy, T aspect, T near); + + /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite for graphics hardware that doesn't support depth clamping. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param ep Epsilon + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> tweakedInfinitePerspective( + T fovy, T aspect, T near, T ep); + + /// @} +}//namespace glm + +#include "matrix_clip_space.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_clip_space.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_clip_space.inl new file mode 100644 index 0000000..27fb6a1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_clip_space.inl @@ -0,0 +1,595 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> ortho(T left, T right, T bottom, T top) + { + mat<4, 4, T, defaultp> Result(static_cast(1)); + Result[0][0] = static_cast(2) / (right - left); + Result[1][1] = static_cast(2) / (top - bottom); + Result[2][2] = - static_cast(1); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoLH_ZO(T left, T right, T bottom, T top, T zNear, T zFar) + { + mat<4, 4, T, defaultp> Result(1); + Result[0][0] = static_cast(2) / (right - left); + Result[1][1] = static_cast(2) / (top - bottom); + Result[2][2] = static_cast(1) / (zFar - zNear); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + Result[3][2] = - zNear / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoLH_NO(T left, T right, T bottom, T top, T zNear, T zFar) + { + mat<4, 4, T, defaultp> Result(1); + Result[0][0] = static_cast(2) / (right - left); + Result[1][1] = static_cast(2) / (top - bottom); + Result[2][2] = static_cast(2) / (zFar - zNear); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + Result[3][2] = - (zFar + zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoRH_ZO(T left, T right, T bottom, T top, T zNear, T zFar) + { + mat<4, 4, T, defaultp> Result(1); + Result[0][0] = static_cast(2) / (right - left); + Result[1][1] = static_cast(2) / (top - bottom); + Result[2][2] = - static_cast(1) / (zFar - zNear); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + Result[3][2] = - zNear / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoRH_NO(T left, T right, T bottom, T top, T zNear, T zFar) + { + mat<4, 4, T, defaultp> Result(1); + Result[0][0] = static_cast(2) / (right - left); + Result[1][1] = static_cast(2) / (top - bottom); + Result[2][2] = - static_cast(2) / (zFar - zNear); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + Result[3][2] = - (zFar + zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoZO(T left, T right, T bottom, T top, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return orthoLH_ZO(left, right, bottom, top, zNear, zFar); +# else + return orthoRH_ZO(left, right, bottom, top, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoNO(T left, T right, T bottom, T top, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return orthoLH_NO(left, right, bottom, top, zNear, zFar); +# else + return orthoRH_NO(left, right, bottom, top, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoLH(T left, T right, T bottom, T top, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return orthoLH_ZO(left, right, bottom, top, zNear, zFar); +# else + return orthoLH_NO(left, right, bottom, top, zNear, zFar); +# endif + + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoRH(T left, T right, T bottom, T top, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return orthoRH_ZO(left, right, bottom, top, zNear, zFar); +# else + return orthoRH_NO(left, right, bottom, top, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> ortho(T left, T right, T bottom, T top, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_ZO + return orthoLH_ZO(left, right, bottom, top, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_NO + return orthoLH_NO(left, right, bottom, top, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO + return orthoRH_ZO(left, right, bottom, top, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_NO + return orthoRH_NO(left, right, bottom, top, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumLH_ZO(T left, T right, T bottom, T top, T nearVal, T farVal) + { + mat<4, 4, T, defaultp> Result(0); + Result[0][0] = (static_cast(2) * nearVal) / (right - left); + Result[1][1] = (static_cast(2) * nearVal) / (top - bottom); + Result[2][0] = -(right + left) / (right - left); + Result[2][1] = -(top + bottom) / (top - bottom); + Result[2][2] = farVal / (farVal - nearVal); + Result[2][3] = static_cast(1); + Result[3][2] = -(farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumLH_NO(T left, T right, T bottom, T top, T nearVal, T farVal) + { + mat<4, 4, T, defaultp> Result(0); + Result[0][0] = (static_cast(2) * nearVal) / (right - left); + Result[1][1] = (static_cast(2) * nearVal) / (top - bottom); + Result[2][0] = -(right + left) / (right - left); + Result[2][1] = -(top + bottom) / (top - bottom); + Result[2][2] = (farVal + nearVal) / (farVal - nearVal); + Result[2][3] = static_cast(1); + Result[3][2] = - (static_cast(2) * farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumRH_ZO(T left, T right, T bottom, T top, T nearVal, T farVal) + { + mat<4, 4, T, defaultp> Result(0); + Result[0][0] = (static_cast(2) * nearVal) / (right - left); + Result[1][1] = (static_cast(2) * nearVal) / (top - bottom); + Result[2][0] = (right + left) / (right - left); + Result[2][1] = (top + bottom) / (top - bottom); + Result[2][2] = farVal / (nearVal - farVal); + Result[2][3] = static_cast(-1); + Result[3][2] = -(farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumRH_NO(T left, T right, T bottom, T top, T nearVal, T farVal) + { + mat<4, 4, T, defaultp> Result(0); + Result[0][0] = (static_cast(2) * nearVal) / (right - left); + Result[1][1] = (static_cast(2) * nearVal) / (top - bottom); + Result[2][0] = (right + left) / (right - left); + Result[2][1] = (top + bottom) / (top - bottom); + Result[2][2] = - (farVal + nearVal) / (farVal - nearVal); + Result[2][3] = static_cast(-1); + Result[3][2] = - (static_cast(2) * farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumZO(T left, T right, T bottom, T top, T nearVal, T farVal) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return frustumLH_ZO(left, right, bottom, top, nearVal, farVal); +# else + return frustumRH_ZO(left, right, bottom, top, nearVal, farVal); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumNO(T left, T right, T bottom, T top, T nearVal, T farVal) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return frustumLH_NO(left, right, bottom, top, nearVal, farVal); +# else + return frustumRH_NO(left, right, bottom, top, nearVal, farVal); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumLH(T left, T right, T bottom, T top, T nearVal, T farVal) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return frustumLH_ZO(left, right, bottom, top, nearVal, farVal); +# else + return frustumLH_NO(left, right, bottom, top, nearVal, farVal); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumRH(T left, T right, T bottom, T top, T nearVal, T farVal) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return frustumRH_ZO(left, right, bottom, top, nearVal, farVal); +# else + return frustumRH_NO(left, right, bottom, top, nearVal, farVal); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustum(T left, T right, T bottom, T top, T nearVal, T farVal) + { +# if GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_ZO + return frustumLH_ZO(left, right, bottom, top, nearVal, farVal); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_NO + return frustumLH_NO(left, right, bottom, top, nearVal, farVal); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO + return frustumRH_ZO(left, right, bottom, top, nearVal, farVal); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_NO + return frustumRH_NO(left, right, bottom, top, nearVal, farVal); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveRH_ZO(T fovy, T aspect, T zNear, T zFar) + { + assert(abs(aspect - std::numeric_limits::epsilon()) > static_cast(0)); + + T const tanHalfFovy = tan(fovy / static_cast(2)); + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = static_cast(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast(1) / (tanHalfFovy); + Result[2][2] = zFar / (zNear - zFar); + Result[2][3] = - static_cast(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveRH_NO(T fovy, T aspect, T zNear, T zFar) + { + assert(abs(aspect - std::numeric_limits::epsilon()) > static_cast(0)); + + T const tanHalfFovy = tan(fovy / static_cast(2)); + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = static_cast(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast(1) / (tanHalfFovy); + Result[2][2] = - (zFar + zNear) / (zFar - zNear); + Result[2][3] = - static_cast(1); + Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveLH_ZO(T fovy, T aspect, T zNear, T zFar) + { + assert(abs(aspect - std::numeric_limits::epsilon()) > static_cast(0)); + + T const tanHalfFovy = tan(fovy / static_cast(2)); + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = static_cast(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast(1) / (tanHalfFovy); + Result[2][2] = zFar / (zFar - zNear); + Result[2][3] = static_cast(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveLH_NO(T fovy, T aspect, T zNear, T zFar) + { + assert(abs(aspect - std::numeric_limits::epsilon()) > static_cast(0)); + + T const tanHalfFovy = tan(fovy / static_cast(2)); + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = static_cast(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast(1) / (tanHalfFovy); + Result[2][2] = (zFar + zNear) / (zFar - zNear); + Result[2][3] = static_cast(1); + Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveZO(T fovy, T aspect, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return perspectiveLH_ZO(fovy, aspect, zNear, zFar); +# else + return perspectiveRH_ZO(fovy, aspect, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveNO(T fovy, T aspect, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return perspectiveLH_NO(fovy, aspect, zNear, zFar); +# else + return perspectiveRH_NO(fovy, aspect, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveLH(T fovy, T aspect, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return perspectiveLH_ZO(fovy, aspect, zNear, zFar); +# else + return perspectiveLH_NO(fovy, aspect, zNear, zFar); +# endif + + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveRH(T fovy, T aspect, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return perspectiveRH_ZO(fovy, aspect, zNear, zFar); +# else + return perspectiveRH_NO(fovy, aspect, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspective(T fovy, T aspect, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_ZO + return perspectiveLH_ZO(fovy, aspect, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_NO + return perspectiveLH_NO(fovy, aspect, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO + return perspectiveRH_ZO(fovy, aspect, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_NO + return perspectiveRH_NO(fovy, aspect, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovRH_ZO(T fov, T width, T height, T zNear, T zFar) + { + assert(width > static_cast(0)); + assert(height > static_cast(0)); + assert(fov > static_cast(0)); + + T const rad = fov; + T const h = glm::cos(static_cast(0.5) * rad) / glm::sin(static_cast(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = zFar / (zNear - zFar); + Result[2][3] = - static_cast(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovRH_NO(T fov, T width, T height, T zNear, T zFar) + { + assert(width > static_cast(0)); + assert(height > static_cast(0)); + assert(fov > static_cast(0)); + + T const rad = fov; + T const h = glm::cos(static_cast(0.5) * rad) / glm::sin(static_cast(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = - (zFar + zNear) / (zFar - zNear); + Result[2][3] = - static_cast(1); + Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovLH_ZO(T fov, T width, T height, T zNear, T zFar) + { + assert(width > static_cast(0)); + assert(height > static_cast(0)); + assert(fov > static_cast(0)); + + T const rad = fov; + T const h = glm::cos(static_cast(0.5) * rad) / glm::sin(static_cast(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = zFar / (zFar - zNear); + Result[2][3] = static_cast(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovLH_NO(T fov, T width, T height, T zNear, T zFar) + { + assert(width > static_cast(0)); + assert(height > static_cast(0)); + assert(fov > static_cast(0)); + + T const rad = fov; + T const h = glm::cos(static_cast(0.5) * rad) / glm::sin(static_cast(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = (zFar + zNear) / (zFar - zNear); + Result[2][3] = static_cast(1); + Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovZO(T fov, T width, T height, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return perspectiveFovLH_ZO(fov, width, height, zNear, zFar); +# else + return perspectiveFovRH_ZO(fov, width, height, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovNO(T fov, T width, T height, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return perspectiveFovLH_NO(fov, width, height, zNear, zFar); +# else + return perspectiveFovRH_NO(fov, width, height, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovLH(T fov, T width, T height, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return perspectiveFovLH_ZO(fov, width, height, zNear, zFar); +# else + return perspectiveFovLH_NO(fov, width, height, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovRH(T fov, T width, T height, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return perspectiveFovRH_ZO(fov, width, height, zNear, zFar); +# else + return perspectiveFovRH_NO(fov, width, height, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFov(T fov, T width, T height, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_ZO + return perspectiveFovLH_ZO(fov, width, height, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_NO + return perspectiveFovLH_NO(fov, width, height, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO + return perspectiveFovRH_ZO(fov, width, height, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_NO + return perspectiveFovRH_NO(fov, width, height, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveRH_NO(T fovy, T aspect, T zNear) + { + T const range = tan(fovy / static_cast(2)) * zNear; + T const left = -range * aspect; + T const right = range * aspect; + T const bottom = -range; + T const top = range; + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = (static_cast(2) * zNear) / (right - left); + Result[1][1] = (static_cast(2) * zNear) / (top - bottom); + Result[2][2] = - static_cast(1); + Result[2][3] = - static_cast(1); + Result[3][2] = - static_cast(2) * zNear; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveRH_ZO(T fovy, T aspect, T zNear) + { + T const range = tan(fovy / static_cast(2)) * zNear; + T const left = -range * aspect; + T const right = range * aspect; + T const bottom = -range; + T const top = range; + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = (static_cast(2) * zNear) / (right - left); + Result[1][1] = (static_cast(2) * zNear) / (top - bottom); + Result[2][2] = - static_cast(1); + Result[2][3] = - static_cast(1); + Result[3][2] = - zNear; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveLH_NO(T fovy, T aspect, T zNear) + { + T const range = tan(fovy / static_cast(2)) * zNear; + T const left = -range * aspect; + T const right = range * aspect; + T const bottom = -range; + T const top = range; + + mat<4, 4, T, defaultp> Result(T(0)); + Result[0][0] = (static_cast(2) * zNear) / (right - left); + Result[1][1] = (static_cast(2) * zNear) / (top - bottom); + Result[2][2] = static_cast(1); + Result[2][3] = static_cast(1); + Result[3][2] = - static_cast(2) * zNear; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveLH_ZO(T fovy, T aspect, T zNear) + { + T const range = tan(fovy / static_cast(2)) * zNear; + T const left = -range * aspect; + T const right = range * aspect; + T const bottom = -range; + T const top = range; + + mat<4, 4, T, defaultp> Result(T(0)); + Result[0][0] = (static_cast(2) * zNear) / (right - left); + Result[1][1] = (static_cast(2) * zNear) / (top - bottom); + Result[2][2] = static_cast(1); + Result[2][3] = static_cast(1); + Result[3][2] = - zNear; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspective(T fovy, T aspect, T zNear) + { +# if GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_ZO + return infinitePerspectiveLH_ZO(fovy, aspect, zNear); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_NO + return infinitePerspectiveLH_NO(fovy, aspect, zNear); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO + return infinitePerspectiveRH_ZO(fovy, aspect, zNear); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_NO + return infinitePerspectiveRH_NO(fovy, aspect, zNear); +# endif + } + + // Infinite projection matrix: http://www.terathon.com/gdc07_lengyel.pdf + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> tweakedInfinitePerspective(T fovy, T aspect, T zNear, T ep) + { + T const range = tan(fovy / static_cast(2)) * zNear; + T const left = -range * aspect; + T const right = range * aspect; + T const bottom = -range; + T const top = range; + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = (static_cast(2) * zNear) / (right - left); + Result[1][1] = (static_cast(2) * zNear) / (top - bottom); + Result[2][2] = ep - static_cast(1); + Result[2][3] = static_cast(-1); + Result[3][2] = (ep - static_cast(2)) * zNear; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> tweakedInfinitePerspective(T fovy, T aspect, T zNear) + { + return tweakedInfinitePerspective(fovy, aspect, zNear, epsilon()); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_common.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_common.hpp new file mode 100644 index 0000000..6bb3d06 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_common.hpp @@ -0,0 +1,39 @@ +/// @ref ext_matrix_common +/// @file glm/ext/matrix_common.hpp +/// +/// @defgroup ext_matrix_common GLM_EXT_matrix_common +/// @ingroup ext +/// +/// Defines functions for common matrix operations. +/// +/// Include to use the features of this extension. +/// +/// @see ext_matrix_common + +#pragma once + +#include "../detail/qualifier.hpp" +#include "../detail/_fixes.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_common extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_common + /// @{ + + template + GLM_FUNC_DECL mat mix(mat const& x, mat const& y, mat const& a); + + template + GLM_FUNC_DECL mat mix(mat const& x, mat const& y, U a); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat abs(mat const& x); + + /// @} +}//namespace glm + +#include "matrix_common.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_common.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_common.inl new file mode 100644 index 0000000..1be4222 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_common.inl @@ -0,0 +1,34 @@ +#include "../matrix.hpp" + +#include "_matrix_vectorize.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat mix(mat const& x, mat const& y, U a) + { + return mat(x) * (static_cast(1) - a) + mat(y) * a; + } + + template + GLM_FUNC_QUALIFIER mat mix(mat const& x, mat const& y, mat const& a) + { + return matrixCompMult(mat(x), static_cast(1) - a) + matrixCompMult(mat(y), a); + } + + template + struct compute_abs_matrix + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat call(mat const& x) + { + return detail::matrix_functor_1::call(abs, x); + } + }; + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat abs(mat const& x) + { + return compute_abs_matrix::value>::call(x); + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x2.hpp new file mode 100644 index 0000000..94dca54 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x2.hpp @@ -0,0 +1,23 @@ +/// @ref core +/// @file glm/ext/matrix_double2x2.hpp + +#pragma once +#include "../detail/type_mat2x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 2 columns of 2 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 2, double, defaultp> dmat2x2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 2, double, defaultp> dmat2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x2_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x2_precision.hpp new file mode 100644 index 0000000..9e2c174 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x2_precision.hpp @@ -0,0 +1,49 @@ +/// @ref core +/// @file glm/ext/matrix_double2x2_precision.hpp + +#pragma once +#include "../detail/type_mat2x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 2 columns of 2 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, double, lowp> lowp_dmat2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, double, mediump> mediump_dmat2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, double, highp> highp_dmat2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, double, lowp> lowp_dmat2x2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, double, mediump> mediump_dmat2x2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, double, highp> highp_dmat2x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x3.hpp new file mode 100644 index 0000000..bfef87a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_double2x3.hpp + +#pragma once +#include "../detail/type_mat2x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 2 columns of 3 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 3, double, defaultp> dmat2x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x3_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x3_precision.hpp new file mode 100644 index 0000000..098fb60 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x3_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_double2x3_precision.hpp + +#pragma once +#include "../detail/type_mat2x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 2 columns of 3 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 3, double, lowp> lowp_dmat2x3; + + /// 2 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 3, double, mediump> mediump_dmat2x3; + + /// 2 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 3, double, highp> highp_dmat2x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x4.hpp new file mode 100644 index 0000000..499284b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_double2x4.hpp + +#pragma once +#include "../detail/type_mat2x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 2 columns of 4 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 4, double, defaultp> dmat2x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x4_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x4_precision.hpp new file mode 100644 index 0000000..9b61ebc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double2x4_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_double2x4_precision.hpp + +#pragma once +#include "../detail/type_mat2x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 2 columns of 4 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 4, double, lowp> lowp_dmat2x4; + + /// 2 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 4, double, mediump> mediump_dmat2x4; + + /// 2 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 4, double, highp> highp_dmat2x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x2.hpp new file mode 100644 index 0000000..dd23f36 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_double3x2.hpp + +#pragma once +#include "../detail/type_mat3x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 3 columns of 2 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 2, double, defaultp> dmat3x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x2_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x2_precision.hpp new file mode 100644 index 0000000..068d9e9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_double3x2_precision.hpp + +#pragma once +#include "../detail/type_mat3x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 3 columns of 2 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 2, double, lowp> lowp_dmat3x2; + + /// 3 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 2, double, mediump> mediump_dmat3x2; + + /// 3 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 2, double, highp> highp_dmat3x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x3.hpp new file mode 100644 index 0000000..53572b7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x3.hpp @@ -0,0 +1,23 @@ +/// @ref core +/// @file glm/ext/matrix_double3x3.hpp + +#pragma once +#include "../detail/type_mat3x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 3 columns of 3 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 3, double, defaultp> dmat3x3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 3, double, defaultp> dmat3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x3_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x3_precision.hpp new file mode 100644 index 0000000..8691e78 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x3_precision.hpp @@ -0,0 +1,49 @@ +/// @ref core +/// @file glm/ext/matrix_double3x3_precision.hpp + +#pragma once +#include "../detail/type_mat3x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 3 columns of 3 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, double, lowp> lowp_dmat3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, double, mediump> mediump_dmat3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, double, highp> highp_dmat3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, double, lowp> lowp_dmat3x3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, double, mediump> mediump_dmat3x3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, double, highp> highp_dmat3x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x4.hpp new file mode 100644 index 0000000..c572d63 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_double3x4.hpp + +#pragma once +#include "../detail/type_mat3x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 3 columns of 4 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 4, double, defaultp> dmat3x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x4_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x4_precision.hpp new file mode 100644 index 0000000..f040217 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double3x4_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_double3x4_precision.hpp + +#pragma once +#include "../detail/type_mat3x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 3 columns of 4 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 4, double, lowp> lowp_dmat3x4; + + /// 3 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 4, double, mediump> mediump_dmat3x4; + + /// 3 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 4, double, highp> highp_dmat3x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x2.hpp new file mode 100644 index 0000000..9b229f4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_double4x2.hpp + +#pragma once +#include "../detail/type_mat4x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 4 columns of 2 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 2, double, defaultp> dmat4x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x2_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x2_precision.hpp new file mode 100644 index 0000000..6ad18ba --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_double4x2_precision.hpp + +#pragma once +#include "../detail/type_mat4x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 4 columns of 2 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 2, double, lowp> lowp_dmat4x2; + + /// 4 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 2, double, mediump> mediump_dmat4x2; + + /// 4 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 2, double, highp> highp_dmat4x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x3.hpp new file mode 100644 index 0000000..dca4cf9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_double4x3.hpp + +#pragma once +#include "../detail/type_mat4x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 4 columns of 3 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 3, double, defaultp> dmat4x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x3_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x3_precision.hpp new file mode 100644 index 0000000..f7371de --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x3_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_double4x3_precision.hpp + +#pragma once +#include "../detail/type_mat4x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 4 columns of 3 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 3, double, lowp> lowp_dmat4x3; + + /// 4 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 3, double, mediump> mediump_dmat4x3; + + /// 4 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 3, double, highp> highp_dmat4x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x4.hpp new file mode 100644 index 0000000..81e1bf6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x4.hpp @@ -0,0 +1,23 @@ +/// @ref core +/// @file glm/ext/matrix_double4x4.hpp + +#pragma once +#include "../detail/type_mat4x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 4 columns of 4 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 4, double, defaultp> dmat4x4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 4, double, defaultp> dmat4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x4_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x4_precision.hpp new file mode 100644 index 0000000..4c36a84 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_double4x4_precision.hpp @@ -0,0 +1,49 @@ +/// @ref core +/// @file glm/ext/matrix_double4x4_precision.hpp + +#pragma once +#include "../detail/type_mat4x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 4 columns of 4 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, double, lowp> lowp_dmat4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, double, mediump> mediump_dmat4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, double, highp> highp_dmat4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, double, lowp> lowp_dmat4x4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, double, mediump> mediump_dmat4x4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, double, highp> highp_dmat4x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x2.hpp new file mode 100644 index 0000000..53df921 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x2.hpp @@ -0,0 +1,23 @@ +/// @ref core +/// @file glm/ext/matrix_float2x2.hpp + +#pragma once +#include "../detail/type_mat2x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 2 columns of 2 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 2, float, defaultp> mat2x2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 2, float, defaultp> mat2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x2_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x2_precision.hpp new file mode 100644 index 0000000..898b6db --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x2_precision.hpp @@ -0,0 +1,49 @@ +/// @ref core +/// @file glm/ext/matrix_float2x2_precision.hpp + +#pragma once +#include "../detail/type_mat2x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 2 columns of 2 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, float, lowp> lowp_mat2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, float, mediump> mediump_mat2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, float, highp> highp_mat2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, float, lowp> lowp_mat2x2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, float, mediump> mediump_mat2x2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, float, highp> highp_mat2x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x3.hpp new file mode 100644 index 0000000..6f68822 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_float2x3.hpp + +#pragma once +#include "../detail/type_mat2x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 2 columns of 3 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 3, float, defaultp> mat2x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x3_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x3_precision.hpp new file mode 100644 index 0000000..50c1032 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x3_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_float2x3_precision.hpp + +#pragma once +#include "../detail/type_mat2x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 2 columns of 3 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 3, float, lowp> lowp_mat2x3; + + /// 2 columns of 3 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 3, float, mediump> mediump_mat2x3; + + /// 2 columns of 3 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 3, float, highp> highp_mat2x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x4.hpp new file mode 100644 index 0000000..30f30de --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_float2x4.hpp + +#pragma once +#include "../detail/type_mat2x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 2 columns of 4 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 4, float, defaultp> mat2x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x4_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x4_precision.hpp new file mode 100644 index 0000000..079d638 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float2x4_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_float2x4_precision.hpp + +#pragma once +#include "../detail/type_mat2x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 2 columns of 4 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 4, float, lowp> lowp_mat2x4; + + /// 2 columns of 4 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 4, float, mediump> mediump_mat2x4; + + /// 2 columns of 4 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 4, float, highp> highp_mat2x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x2.hpp new file mode 100644 index 0000000..280d0a3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_float3x2.hpp + +#pragma once +#include "../detail/type_mat3x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 3 columns of 2 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 2, float, defaultp> mat3x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x2_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x2_precision.hpp new file mode 100644 index 0000000..8572c2a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_float3x2_precision.hpp + +#pragma once +#include "../detail/type_mat3x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 3 columns of 2 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 2, float, lowp> lowp_mat3x2; + + /// 3 columns of 2 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 2, float, mediump> mediump_mat3x2; + + /// 3 columns of 2 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 2, float, highp> highp_mat3x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x3.hpp new file mode 100644 index 0000000..177d809 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x3.hpp @@ -0,0 +1,23 @@ +/// @ref core +/// @file glm/ext/matrix_float3x3.hpp + +#pragma once +#include "../detail/type_mat3x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 3 columns of 3 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 3, float, defaultp> mat3x3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 3, float, defaultp> mat3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x3_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x3_precision.hpp new file mode 100644 index 0000000..8a900c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x3_precision.hpp @@ -0,0 +1,49 @@ +/// @ref core +/// @file glm/ext/matrix_float3x3_precision.hpp + +#pragma once +#include "../detail/type_mat3x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 3 columns of 3 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, float, lowp> lowp_mat3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, float, mediump> mediump_mat3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, float, highp> highp_mat3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, float, lowp> lowp_mat3x3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, float, mediump> mediump_mat3x3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, float, highp> highp_mat3x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x4.hpp new file mode 100644 index 0000000..64b8459 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_float3x4.hpp + +#pragma once +#include "../detail/type_mat3x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 3 columns of 4 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 4, float, defaultp> mat3x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x4_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x4_precision.hpp new file mode 100644 index 0000000..bc36bf13 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float3x4_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_float3x4_precision.hpp + +#pragma once +#include "../detail/type_mat3x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 3 columns of 4 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 4, float, lowp> lowp_mat3x4; + + /// 3 columns of 4 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 4, float, mediump> mediump_mat3x4; + + /// 3 columns of 4 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 4, float, highp> highp_mat3x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x2.hpp new file mode 100644 index 0000000..1ed5227 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_float4x2.hpp + +#pragma once +#include "../detail/type_mat4x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 4 columns of 2 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 2, float, defaultp> mat4x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x2_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x2_precision.hpp new file mode 100644 index 0000000..88fd069 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_float2x2_precision.hpp + +#pragma once +#include "../detail/type_mat2x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 4 columns of 2 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 2, float, lowp> lowp_mat4x2; + + /// 4 columns of 2 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 2, float, mediump> mediump_mat4x2; + + /// 4 columns of 2 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 2, float, highp> highp_mat4x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x3.hpp new file mode 100644 index 0000000..5dbe765 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_float4x3.hpp + +#pragma once +#include "../detail/type_mat4x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 4 columns of 3 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 3, float, defaultp> mat4x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x3_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x3_precision.hpp new file mode 100644 index 0000000..846ed4f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x3_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_float4x3_precision.hpp + +#pragma once +#include "../detail/type_mat4x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 4 columns of 3 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 3, float, lowp> lowp_mat4x3; + + /// 4 columns of 3 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 3, float, mediump> mediump_mat4x3; + + /// 4 columns of 3 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 3, float, highp> highp_mat4x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x4.hpp new file mode 100644 index 0000000..5ba111d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x4.hpp @@ -0,0 +1,23 @@ +/// @ref core +/// @file glm/ext/matrix_float4x4.hpp + +#pragma once +#include "../detail/type_mat4x4.hpp" + +namespace glm +{ + /// @ingroup core_matrix + /// @{ + + /// 4 columns of 4 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 4, float, defaultp> mat4x4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 4, float, defaultp> mat4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x4_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x4_precision.hpp new file mode 100644 index 0000000..597149b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_float4x4_precision.hpp @@ -0,0 +1,49 @@ +/// @ref core +/// @file glm/ext/matrix_float4x4_precision.hpp + +#pragma once +#include "../detail/type_mat4x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 4 columns of 4 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, float, lowp> lowp_mat4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, float, mediump> mediump_mat4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, float, highp> highp_mat4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, float, lowp> lowp_mat4x4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, float, mediump> mediump_mat4x4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, float, highp> highp_mat4x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x2.hpp new file mode 100644 index 0000000..c6aa068 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x2.hpp @@ -0,0 +1,38 @@ +/// @ref ext_matrix_int2x2 +/// @file glm/ext/matrix_int2x2.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x2 GLM_EXT_matrix_int2x2 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int2x2 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int2x2 + /// @{ + + /// Signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2 + typedef mat<2, 2, int, defaultp> imat2x2; + + /// Signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2 + typedef mat<2, 2, int, defaultp> imat2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x2_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x2_sized.hpp new file mode 100644 index 0000000..70c0c21 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x2_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_matrix_int2x2_sized +/// @file glm/ext/matrix_int2x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x2_sized GLM_EXT_matrix_int2x2_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x2.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int2x2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int2x2_sized + /// @{ + + /// 8 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int8, defaultp> i8mat2x2; + + /// 16 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int16, defaultp> i16mat2x2; + + /// 32 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int32, defaultp> i32mat2x2; + + /// 64 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int64, defaultp> i64mat2x2; + + + /// 8 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int8, defaultp> i8mat2; + + /// 16 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int16, defaultp> i16mat2; + + /// 32 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int32, defaultp> i32mat2; + + /// 64 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int64, defaultp> i64mat2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x3.hpp new file mode 100644 index 0000000..aee415c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x3.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_int2x3 +/// @file glm/ext/matrix_int2x3.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x3 GLM_EXT_matrix_int2x3 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x3.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int2x3 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int2x3 + /// @{ + + /// Signed integer 2x3 matrix. + /// + /// @see ext_matrix_int2x3 + typedef mat<2, 3, int, defaultp> imat2x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x3_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x3_sized.hpp new file mode 100644 index 0000000..b5526fe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x3_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_int2x3_sized +/// @file glm/ext/matrix_int2x3_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x3_sized GLM_EXT_matrix_int2x3_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x3.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int2x3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int2x3_sized + /// @{ + + /// 8 bit signed integer 2x3 matrix. + /// + /// @see ext_matrix_int2x3_sized + typedef mat<2, 3, int8, defaultp> i8mat2x3; + + /// 16 bit signed integer 2x3 matrix. + /// + /// @see ext_matrix_int2x3_sized + typedef mat<2, 3, int16, defaultp> i16mat2x3; + + /// 32 bit signed integer 2x3 matrix. + /// + /// @see ext_matrix_int2x3_sized + typedef mat<2, 3, int32, defaultp> i32mat2x3; + + /// 64 bit signed integer 2x3 matrix. + /// + /// @see ext_matrix_int2x3_sized + typedef mat<2, 3, int64, defaultp> i64mat2x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x4.hpp new file mode 100644 index 0000000..4f36331 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x4.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_int2x4 +/// @file glm/ext/matrix_int2x4.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x4 GLM_EXT_matrix_int2x4 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int2x4 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int2x4 + /// @{ + + /// Signed integer 2x4 matrix. + /// + /// @see ext_matrix_int2x4 + typedef mat<2, 4, int, defaultp> imat2x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x4_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x4_sized.hpp new file mode 100644 index 0000000..a66a5e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int2x4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_int2x4_sized +/// @file glm/ext/matrix_int2x4_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x4_sized GLM_EXT_matrix_int2x4_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x4.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int2x4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int2x4_sized + /// @{ + + /// 8 bit signed integer 2x4 matrix. + /// + /// @see ext_matrix_int2x4_sized + typedef mat<2, 4, int8, defaultp> i8mat2x4; + + /// 16 bit signed integer 2x4 matrix. + /// + /// @see ext_matrix_int2x4_sized + typedef mat<2, 4, int16, defaultp> i16mat2x4; + + /// 32 bit signed integer 2x4 matrix. + /// + /// @see ext_matrix_int2x4_sized + typedef mat<2, 4, int32, defaultp> i32mat2x4; + + /// 64 bit signed integer 2x4 matrix. + /// + /// @see ext_matrix_int2x4_sized + typedef mat<2, 4, int64, defaultp> i64mat2x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x2.hpp new file mode 100644 index 0000000..3bd563b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x2.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_int3x2 +/// @file glm/ext/matrix_int3x2.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x2 GLM_EXT_matrix_int3x2 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int3x2 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int3x2 + /// @{ + + /// Signed integer 3x2 matrix. + /// + /// @see ext_matrix_int3x2 + typedef mat<3, 2, int, defaultp> imat3x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x2_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x2_sized.hpp new file mode 100644 index 0000000..7e34c52 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x2_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_int3x2_sized +/// @file glm/ext/matrix_int3x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x2_sized GLM_EXT_matrix_int3x2_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x2.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int3x2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int3x2_sized + /// @{ + + /// 8 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_int3x2_sized + typedef mat<3, 2, int8, defaultp> i8mat3x2; + + /// 16 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_int3x2_sized + typedef mat<3, 2, int16, defaultp> i16mat3x2; + + /// 32 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_int3x2_sized + typedef mat<3, 2, int32, defaultp> i32mat3x2; + + /// 64 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_int3x2_sized + typedef mat<3, 2, int64, defaultp> i64mat3x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x3.hpp new file mode 100644 index 0000000..287488d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x3.hpp @@ -0,0 +1,38 @@ +/// @ref ext_matrix_int3x3 +/// @file glm/ext/matrix_int3x3.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x3 GLM_EXT_matrix_int3x3 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int3x3 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int3x3 + /// @{ + + /// Signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3 + typedef mat<3, 3, int, defaultp> imat3x3; + + /// Signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3 + typedef mat<3, 3, int, defaultp> imat3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x3_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x3_sized.hpp new file mode 100644 index 0000000..577e305 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x3_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_matrix_int3x3_sized +/// @file glm/ext/matrix_int3x3_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x3_sized GLM_EXT_matrix_int3x3_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int3x3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int3x3_sized + /// @{ + + /// 8 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int8, defaultp> i8mat3x3; + + /// 16 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int16, defaultp> i16mat3x3; + + /// 32 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int32, defaultp> i32mat3x3; + + /// 64 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int64, defaultp> i64mat3x3; + + + /// 8 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int8, defaultp> i8mat3; + + /// 16 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int16, defaultp> i16mat3; + + /// 32 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int32, defaultp> i32mat3; + + /// 64 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int64, defaultp> i64mat3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x4.hpp new file mode 100644 index 0000000..08e534d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x4.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_int3x4 +/// @file glm/ext/matrix_int3x4.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x4 GLM_EXT_matrix_int3x4 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int3x4 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int3x4 + /// @{ + + /// Signed integer 3x4 matrix. + /// + /// @see ext_matrix_int3x4 + typedef mat<3, 4, int, defaultp> imat3x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x4_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x4_sized.hpp new file mode 100644 index 0000000..692c48c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int3x4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_int3x4_sized +/// @file glm/ext/matrix_int3x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x4_sized GLM_EXT_matrix_int3x4_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x4.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int3x4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int3x4_sized + /// @{ + + /// 8 bit signed integer 3x4 matrix. + /// + /// @see ext_matrix_int3x4_sized + typedef mat<3, 4, int8, defaultp> i8mat3x4; + + /// 16 bit signed integer 3x4 matrix. + /// + /// @see ext_matrix_int3x4_sized + typedef mat<3, 4, int16, defaultp> i16mat3x4; + + /// 32 bit signed integer 3x4 matrix. + /// + /// @see ext_matrix_int3x4_sized + typedef mat<3, 4, int32, defaultp> i32mat3x4; + + /// 64 bit signed integer 3x4 matrix. + /// + /// @see ext_matrix_int3x4_sized + typedef mat<3, 4, int64, defaultp> i64mat3x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x2.hpp new file mode 100644 index 0000000..f756ef2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x2.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_int4x2 +/// @file glm/ext/matrix_int4x2.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int4x2 GLM_EXT_matrix_int4x2 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int4x2 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int4x2 + /// @{ + + /// Signed integer 4x2 matrix. + /// + /// @see ext_matrix_int4x2 + typedef mat<4, 2, int, defaultp> imat4x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x2_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x2_sized.hpp new file mode 100644 index 0000000..63a99d6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x2_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_int4x2_sized +/// @file glm/ext/matrix_int4x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int4x2_sized GLM_EXT_matrix_int4x2_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x2.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int4x2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int4x2_sized + /// @{ + + /// 8 bit signed integer 4x2 matrix. + /// + /// @see ext_matrix_int4x2_sized + typedef mat<4, 2, int8, defaultp> i8mat4x2; + + /// 16 bit signed integer 4x2 matrix. + /// + /// @see ext_matrix_int4x2_sized + typedef mat<4, 2, int16, defaultp> i16mat4x2; + + /// 32 bit signed integer 4x2 matrix. + /// + /// @see ext_matrix_int4x2_sized + typedef mat<4, 2, int32, defaultp> i32mat4x2; + + /// 64 bit signed integer 4x2 matrix. + /// + /// @see ext_matrix_int4x2_sized + typedef mat<4, 2, int64, defaultp> i64mat4x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x3.hpp new file mode 100644 index 0000000..d5d97a7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x3.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_int4x3 +/// @file glm/ext/matrix_int4x3.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int4x3 GLM_EXT_matrix_int4x3 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x3.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int4x3 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int4x3 + /// @{ + + /// Signed integer 4x3 matrix. + /// + /// @see ext_matrix_int4x3 + typedef mat<4, 3, int, defaultp> imat4x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x3_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x3_sized.hpp new file mode 100644 index 0000000..55078fa --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x3_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_int4x3_sized +/// @file glm/ext/matrix_int4x3_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int4x3_sized GLM_EXT_matrix_int4x3_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x3.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int4x3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int4x3_sized + /// @{ + + /// 8 bit signed integer 4x3 matrix. + /// + /// @see ext_matrix_int4x3_sized + typedef mat<4, 3, int8, defaultp> i8mat4x3; + + /// 16 bit signed integer 4x3 matrix. + /// + /// @see ext_matrix_int4x3_sized + typedef mat<4, 3, int16, defaultp> i16mat4x3; + + /// 32 bit signed integer 4x3 matrix. + /// + /// @see ext_matrix_int4x3_sized + typedef mat<4, 3, int32, defaultp> i32mat4x3; + + /// 64 bit signed integer 4x3 matrix. + /// + /// @see ext_matrix_int4x3_sized + typedef mat<4, 3, int64, defaultp> i64mat4x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x4.hpp new file mode 100644 index 0000000..e17cff1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x4.hpp @@ -0,0 +1,38 @@ +/// @ref ext_matrix_int4x4 +/// @file glm/ext/matrix_int4x4.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int4x4 GLM_EXT_matrix_int4x4 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int4x4 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int4x4 + /// @{ + + /// Signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4 + typedef mat<4, 4, int, defaultp> imat4x4; + + /// Signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4 + typedef mat<4, 4, int, defaultp> imat4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x4_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x4_sized.hpp new file mode 100644 index 0000000..4a11203 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_int4x4_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_matrix_int4x4_sized +/// @file glm/ext/matrix_int4x4_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int4x4_sized GLM_EXT_matrix_int4x4_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x4.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int4x4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int4x4_sized + /// @{ + + /// 8 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int8, defaultp> i8mat4x4; + + /// 16 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int16, defaultp> i16mat4x4; + + /// 32 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int32, defaultp> i32mat4x4; + + /// 64 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int64, defaultp> i64mat4x4; + + + /// 8 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int8, defaultp> i8mat4; + + /// 16 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int16, defaultp> i16mat4; + + /// 32 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int32, defaultp> i32mat4; + + /// 64 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int64, defaultp> i64mat4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_integer.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_integer.hpp new file mode 100644 index 0000000..7d7dfc5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_integer.hpp @@ -0,0 +1,91 @@ +/// @ref ext_matrix_integer +/// @file glm/ext/matrix_integer.hpp +/// +/// @defgroup ext_matrix_integer GLM_EXT_matrix_integer +/// @ingroup ext +/// +/// Defines functions that generate common transformation matrices. +/// +/// The matrices generated by this extension use standard OpenGL fixed-function +/// conventions. For example, the lookAt function generates a transform from world +/// space into the specific eye space that the projective matrix functions +/// (perspective, ortho, etc) are designed to expect. The OpenGL compatibility +/// specifications defines the particular layout of this eye space. +/// +/// Include to use the features of this extension. +/// +/// @see ext_matrix_projection +/// @see ext_matrix_clip_space + +#pragma once + +// Dependencies +#include "../gtc/constants.hpp" +#include "../geometric.hpp" +#include "../trigonometric.hpp" +#include "../matrix.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_integer + /// @{ + + /// Multiply matrix x by matrix y component-wise, i.e., + /// result[i][j] is the scalar product of x[i][j] and y[i][j]. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL matrixCompMult man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL mat matrixCompMult(mat const& x, mat const& y); + + /// Treats the first parameter c as a column vector + /// and the second parameter r as a row vector + /// and does a linear algebraic matrix multiply c * r. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL outerProduct man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL typename detail::outerProduct_trait::type outerProduct(vec const& c, vec const& r); + + /// Returns the transposed matrix of x + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL transpose man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL typename mat::transpose_type transpose(mat const& x); + + /// Return the determinant of a squared matrix. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL determinant man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL T determinant(mat const& m); + + /// @} +}//namespace glm + +#include "matrix_integer.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_integer.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_integer.inl new file mode 100644 index 0000000..8b377ce --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_integer.inl @@ -0,0 +1,38 @@ +namespace glm{ +namespace detail +{ + template + struct compute_matrixCompMult_type { + GLM_FUNC_QUALIFIER static mat call(mat const& x, mat const& y) + { + return detail::compute_matrixCompMult::value>::call(x, y); + } + }; + + template + struct compute_outerProduct_type { + GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait::type call(vec const& c, vec const& r) + { + return detail::compute_outerProduct::call(c, r); + } + }; + + template + struct compute_transpose_type + { + GLM_FUNC_QUALIFIER static mat call(mat const& m) + { + return detail::compute_transpose::value>::call(m); + } + }; + + template + struct compute_determinant_type{ + + GLM_FUNC_QUALIFIER static T call(mat const& m) + { + return detail::compute_determinant::value>::call(m); + } + }; +}//namespace detail +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_projection.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_projection.hpp new file mode 100644 index 0000000..51fd01b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_projection.hpp @@ -0,0 +1,149 @@ +/// @ref ext_matrix_projection +/// @file glm/ext/matrix_projection.hpp +/// +/// @defgroup ext_matrix_projection GLM_EXT_matrix_projection +/// @ingroup ext +/// +/// Functions that generate common projection transformation matrices. +/// +/// The matrices generated by this extension use standard OpenGL fixed-function +/// conventions. For example, the lookAt function generates a transform from world +/// space into the specific eye space that the projective matrix functions +/// (perspective, ortho, etc) are designed to expect. The OpenGL compatibility +/// specifications defines the particular layout of this eye space. +/// +/// Include to use the features of this extension. +/// +/// @see ext_matrix_transform +/// @see ext_matrix_clip_space + +#pragma once + +// Dependencies +#include "../gtc/constants.hpp" +#include "../geometric.hpp" +#include "../trigonometric.hpp" +#include "../matrix.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_projection extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_projection + /// @{ + + /// Map the specified object coordinates (obj.x, obj.y, obj.z) into window coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param obj Specify the object coordinates. + /// @param model Specifies the current modelview matrix + /// @param proj Specifies the current projection matrix + /// @param viewport Specifies the current viewport + /// @return Return the computed window coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluProject man page + template + GLM_FUNC_DECL vec<3, T, Q> projectZO( + vec<3, T, Q> const& obj, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport); + + /// Map the specified object coordinates (obj.x, obj.y, obj.z) into window coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param obj Specify the object coordinates. + /// @param model Specifies the current modelview matrix + /// @param proj Specifies the current projection matrix + /// @param viewport Specifies the current viewport + /// @return Return the computed window coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluProject man page + template + GLM_FUNC_DECL vec<3, T, Q> projectNO( + vec<3, T, Q> const& obj, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport); + + /// Map the specified object coordinates (obj.x, obj.y, obj.z) into window coordinates using default near and far clip planes definition. + /// To change default near and far clip planes definition use GLM_FORCE_DEPTH_ZERO_TO_ONE. + /// + /// @param obj Specify the object coordinates. + /// @param model Specifies the current modelview matrix + /// @param proj Specifies the current projection matrix + /// @param viewport Specifies the current viewport + /// @return Return the computed window coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluProject man page + template + GLM_FUNC_DECL vec<3, T, Q> project( + vec<3, T, Q> const& obj, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport); + + /// Map the specified window coordinates (win.x, win.y, win.z) into object coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param win Specify the window coordinates to be mapped. + /// @param model Specifies the modelview matrix + /// @param proj Specifies the projection matrix + /// @param viewport Specifies the viewport + /// @return Returns the computed object coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluUnProject man page + template + GLM_FUNC_DECL vec<3, T, Q> unProjectZO( + vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport); + + /// Map the specified window coordinates (win.x, win.y, win.z) into object coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param win Specify the window coordinates to be mapped. + /// @param model Specifies the modelview matrix + /// @param proj Specifies the projection matrix + /// @param viewport Specifies the viewport + /// @return Returns the computed object coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluUnProject man page + template + GLM_FUNC_DECL vec<3, T, Q> unProjectNO( + vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport); + + /// Map the specified window coordinates (win.x, win.y, win.z) into object coordinates using default near and far clip planes definition. + /// To change default near and far clip planes definition use GLM_FORCE_DEPTH_ZERO_TO_ONE. + /// + /// @param win Specify the window coordinates to be mapped. + /// @param model Specifies the modelview matrix + /// @param proj Specifies the projection matrix + /// @param viewport Specifies the viewport + /// @return Returns the computed object coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluUnProject man page + template + GLM_FUNC_DECL vec<3, T, Q> unProject( + vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport); + + /// Define a picking region + /// + /// @param center Specify the center of a picking region in window coordinates. + /// @param delta Specify the width and height, respectively, of the picking region in window coordinates. + /// @param viewport Rendering viewport + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluPickMatrix man page + template + GLM_FUNC_DECL mat<4, 4, T, Q> pickMatrix( + vec<2, T, Q> const& center, vec<2, T, Q> const& delta, vec<4, U, Q> const& viewport); + + /// @} +}//namespace glm + +#include "matrix_projection.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_projection.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_projection.inl new file mode 100644 index 0000000..2f2c196 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_projection.inl @@ -0,0 +1,106 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> projectZO(vec<3, T, Q> const& obj, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport) + { + vec<4, T, Q> tmp = vec<4, T, Q>(obj, static_cast(1)); + tmp = model * tmp; + tmp = proj * tmp; + + tmp /= tmp.w; + tmp.x = tmp.x * static_cast(0.5) + static_cast(0.5); + tmp.y = tmp.y * static_cast(0.5) + static_cast(0.5); + + tmp[0] = tmp[0] * T(viewport[2]) + T(viewport[0]); + tmp[1] = tmp[1] * T(viewport[3]) + T(viewport[1]); + + return vec<3, T, Q>(tmp); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> projectNO(vec<3, T, Q> const& obj, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport) + { + vec<4, T, Q> tmp = vec<4, T, Q>(obj, static_cast(1)); + tmp = model * tmp; + tmp = proj * tmp; + + tmp /= tmp.w; + tmp = tmp * static_cast(0.5) + static_cast(0.5); + tmp[0] = tmp[0] * T(viewport[2]) + T(viewport[0]); + tmp[1] = tmp[1] * T(viewport[3]) + T(viewport[1]); + + return vec<3, T, Q>(tmp); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> project(vec<3, T, Q> const& obj, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return projectZO(obj, model, proj, viewport); +# else + return projectNO(obj, model, proj, viewport); +# endif + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> unProjectZO(vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport) + { + mat<4, 4, T, Q> Inverse = inverse(proj * model); + + vec<4, T, Q> tmp = vec<4, T, Q>(win, T(1)); + tmp.x = (tmp.x - T(viewport[0])) / T(viewport[2]); + tmp.y = (tmp.y - T(viewport[1])) / T(viewport[3]); + tmp.x = tmp.x * static_cast(2) - static_cast(1); + tmp.y = tmp.y * static_cast(2) - static_cast(1); + + vec<4, T, Q> obj = Inverse * tmp; + obj /= obj.w; + + return vec<3, T, Q>(obj); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> unProjectNO(vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport) + { + mat<4, 4, T, Q> Inverse = inverse(proj * model); + + vec<4, T, Q> tmp = vec<4, T, Q>(win, T(1)); + tmp.x = (tmp.x - T(viewport[0])) / T(viewport[2]); + tmp.y = (tmp.y - T(viewport[1])) / T(viewport[3]); + tmp = tmp * static_cast(2) - static_cast(1); + + vec<4, T, Q> obj = Inverse * tmp; + obj /= obj.w; + + return vec<3, T, Q>(obj); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> unProject(vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return unProjectZO(win, model, proj, viewport); +# else + return unProjectNO(win, model, proj, viewport); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> pickMatrix(vec<2, T, Q> const& center, vec<2, T, Q> const& delta, vec<4, U, Q> const& viewport) + { + assert(delta.x > static_cast(0) && delta.y > static_cast(0)); + mat<4, 4, T, Q> Result(static_cast(1)); + + if(!(delta.x > static_cast(0) && delta.y > static_cast(0))) + return Result; // Error + + vec<3, T, Q> Temp( + (static_cast(viewport[2]) - static_cast(2) * (center.x - static_cast(viewport[0]))) / delta.x, + (static_cast(viewport[3]) - static_cast(2) * (center.y - static_cast(viewport[1]))) / delta.y, + static_cast(0)); + + // Translate and scale the picked region to the entire window + Result = translate(Result, Temp); + return scale(Result, vec<3, T, Q>(static_cast(viewport[2]) / delta.x, static_cast(viewport[3]) / delta.y, static_cast(1))); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_relational.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_relational.hpp new file mode 100644 index 0000000..20023ad --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_relational.hpp @@ -0,0 +1,132 @@ +/// @ref ext_matrix_relational +/// @file glm/ext/matrix_relational.hpp +/// +/// @defgroup ext_matrix_relational GLM_EXT_matrix_relational +/// @ingroup ext +/// +/// Exposes comparison functions for matrix types that take a user defined epsilon values. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_relational +/// @see ext_scalar_relational +/// @see ext_quaternion_relational + +#pragma once + +// Dependencies +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_relational extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_relational + /// @{ + + /// Perform a component-wise equal-to comparison of two matrices. + /// Return a boolean vector which components value is True if this expression is satisfied per column of the matrices. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(mat const& x, mat const& y); + + /// Perform a component-wise not-equal-to comparison of two matrices. + /// Return a boolean vector which components value is True if this expression is satisfied per column of the matrices. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(mat const& x, mat const& y, T epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(mat const& x, mat const& y, vec const& epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is not satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y, T epsilon); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// True if this expression is not satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y, vec const& epsilon); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(mat const& x, mat const& y, int ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(mat const& x, mat const& y, vec const& ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is not satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y, int ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is not satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y, vec const& ULPs); + + /// @} +}//namespace glm + +#include "matrix_relational.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_relational.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_relational.inl new file mode 100644 index 0000000..9cd42b7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_relational.inl @@ -0,0 +1,88 @@ +/// @ref ext_vector_relational +/// @file glm/ext/vector_relational.inl + +// Dependency: +#include "../ext/vector_relational.hpp" +#include "../common.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(mat const& a, mat const& b) + { + vec Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = all(equal(a[i], b[i])); + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(mat const& a, mat const& b, T Epsilon) + { + return equal(a, b, vec(Epsilon)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(mat const& a, mat const& b, vec const& Epsilon) + { + vec Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = all(equal(a[i], b[i], Epsilon[i])); + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(mat const& a, mat const& b) + { + vec Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = any(notEqual(a[i], b[i])); + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(mat const& a, mat const& b, T Epsilon) + { + return notEqual(a, b, vec(Epsilon)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(mat const& a, mat const& b, vec const& Epsilon) + { + vec Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = any(notEqual(a[i], b[i], Epsilon[i])); + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(mat const& a, mat const& b, int MaxULPs) + { + return equal(a, b, vec(MaxULPs)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(mat const& a, mat const& b, vec const& MaxULPs) + { + vec Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = all(equal(a[i], b[i], MaxULPs[i])); + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(mat const& a, mat const& b, int MaxULPs) + { + return notEqual(a, b, vec(MaxULPs)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(mat const& a, mat const& b, vec const& MaxULPs) + { + vec Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = any(notEqual(a[i], b[i], MaxULPs[i])); + return Result; + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_transform.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_transform.hpp new file mode 100644 index 0000000..52695b8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_transform.hpp @@ -0,0 +1,171 @@ +/// @ref ext_matrix_transform +/// @file glm/ext/matrix_transform.hpp +/// +/// @defgroup ext_matrix_transform GLM_EXT_matrix_transform +/// @ingroup ext +/// +/// Defines functions that generate common transformation matrices. +/// +/// The matrices generated by this extension use standard OpenGL fixed-function +/// conventions. For example, the lookAt function generates a transform from world +/// space into the specific eye space that the projective matrix functions +/// (perspective, ortho, etc) are designed to expect. The OpenGL compatibility +/// specifications defines the particular layout of this eye space. +/// +/// Include to use the features of this extension. +/// +/// @see ext_matrix_projection +/// @see ext_matrix_clip_space + +#pragma once + +// Dependencies +#include "../gtc/constants.hpp" +#include "../geometric.hpp" +#include "../trigonometric.hpp" +#include "../matrix.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_transform extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_transform + /// @{ + + /// Builds an identity matrix. + template + GLM_FUNC_DECL GLM_CONSTEXPR genType identity(); + + /// Builds a translation 4 * 4 matrix created from a vector of 3 components. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param v Coordinates of a translation vector. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @code + /// #include + /// #include + /// ... + /// glm::mat4 m = glm::translate(glm::mat4(1.0f), glm::vec3(1.0f)); + /// // m[0][0] == 1.0f, m[0][1] == 0.0f, m[0][2] == 0.0f, m[0][3] == 0.0f + /// // m[1][0] == 0.0f, m[1][1] == 1.0f, m[1][2] == 0.0f, m[1][3] == 0.0f + /// // m[2][0] == 0.0f, m[2][1] == 0.0f, m[2][2] == 1.0f, m[2][3] == 0.0f + /// // m[3][0] == 1.0f, m[3][1] == 1.0f, m[3][2] == 1.0f, m[3][3] == 1.0f + /// @endcode + /// + /// @see - translate(mat<4, 4, T, Q> const& m, T x, T y, T z) + /// @see - translate(vec<3, T, Q> const& v) + /// @see glTranslate man page + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> translate( + mat<4, 4, T, Q> const& m, vec<3, T, Q> const& v); + + /// Builds a rotation 4 * 4 matrix created from an axis vector and an angle. + /// + /// @param m Input matrix multiplied by this rotation matrix. + /// @param angle Rotation angle expressed in radians. + /// @param axis Rotation axis, recommended to be normalized. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @see - rotate(mat<4, 4, T, Q> const& m, T angle, T x, T y, T z) + /// @see - rotate(T angle, vec<3, T, Q> const& v) + /// @see glRotate man page + template + GLM_FUNC_DECL mat<4, 4, T, Q> rotate( + mat<4, 4, T, Q> const& m, T angle, vec<3, T, Q> const& axis); + + /// Builds a scale 4 * 4 matrix created from 3 scalars. + /// + /// @param m Input matrix multiplied by this scale matrix. + /// @param v Ratio of scaling for each axis. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @see - scale(mat<4, 4, T, Q> const& m, T x, T y, T z) + /// @see - scale(vec<3, T, Q> const& v) + /// @see glScale man page + template + GLM_FUNC_DECL mat<4, 4, T, Q> scale( + mat<4, 4, T, Q> const& m, vec<3, T, Q> const& v); + + /// Builds a scale 4 * 4 matrix created from point referent 3 shearers. + /// + /// @param m Input matrix multiplied by this shear matrix. + /// @param p Point of shearing as reference. + /// @param l_x Ratio of matrix.x projection in YZ plane relative to the y-axis/z-axis. + /// @param l_y Ratio of matrix.y projection in XZ plane relative to the x-axis/z-axis. + /// @param l_z Ratio of matrix.z projection in XY plane relative to the x-axis/y-axis. + /// + /// as example: + /// [1 , l_xy, l_xz, -(l_xy+l_xz) * p_x] [x] T + /// [x`, y`, z`, w`] = [x`, y`, z`, w`] * [l_yx, 1 , l_yz, -(l_yx+l_yz) * p_y] [y] + /// [l_zx, l_zy, 1 , -(l_zx+l_zy) * p_z] [z] + /// [0 , 0 , 0 , 1 ] [w] + /// + /// @tparam T A floating-point shear type + /// @tparam Q A value from qualifier enum + /// + /// @see - shear(mat<4, 4, T, Q> const& m, T x, T y, T z) + /// @see - shear(vec<3, T, Q> const& p) + /// @see - shear(vec<2, T, Q> const& l_x) + /// @see - shear(vec<2, T, Q> const& l_y) + /// @see - shear(vec<2, T, Q> const& l_z) + /// @see no resource... + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shear( + mat<4, 4, T, Q> const &m, vec<3, T, Q> const& p, vec<2, T, Q> const &l_x, vec<2, T, Q> const &l_y, vec<2, T, Q> const &l_z); + + /// Build a right handed look at view matrix. + /// + /// @param eye Position of the camera + /// @param center Position where the camera is looking at + /// @param up Normalized up vector, how the camera is oriented. Typically (0, 0, 1) + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @see - frustum(T const& left, T const& right, T const& bottom, T const& top, T const& nearVal, T const& farVal) frustum(T const& left, T const& right, T const& bottom, T const& top, T const& nearVal, T const& farVal) + template + GLM_FUNC_DECL mat<4, 4, T, Q> lookAtRH( + vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up); + + /// Build a left handed look at view matrix. + /// + /// @param eye Position of the camera + /// @param center Position where the camera is looking at + /// @param up Normalized up vector, how the camera is oriented. Typically (0, 0, 1) + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @see - frustum(T const& left, T const& right, T const& bottom, T const& top, T const& nearVal, T const& farVal) frustum(T const& left, T const& right, T const& bottom, T const& top, T const& nearVal, T const& farVal) + template + GLM_FUNC_DECL mat<4, 4, T, Q> lookAtLH( + vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up); + + /// Build a look at view matrix based on the default handedness. + /// + /// @param eye Position of the camera + /// @param center Position where the camera is looking at + /// @param up Normalized up vector, how the camera is oriented. Typically (0, 0, 1) + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @see - frustum(T const& left, T const& right, T const& bottom, T const& top, T const& nearVal, T const& farVal) frustum(T const& left, T const& right, T const& bottom, T const& top, T const& nearVal, T const& farVal) + /// @see gluLookAt man page + template + GLM_FUNC_DECL mat<4, 4, T, Q> lookAt( + vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up); + + /// @} +}//namespace glm + +#include "matrix_transform.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_transform.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_transform.inl new file mode 100644 index 0000000..029ef0f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_transform.inl @@ -0,0 +1,207 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType identity() + { + return detail::init_gentype::GENTYPE>::identity(); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> translate(mat<4, 4, T, Q> const& m, vec<3, T, Q> const& v) + { + mat<4, 4, T, Q> Result(m); + Result[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rotate(mat<4, 4, T, Q> const& m, T angle, vec<3, T, Q> const& v) + { + T const a = angle; + T const c = cos(a); + T const s = sin(a); + + vec<3, T, Q> axis(normalize(v)); + vec<3, T, Q> temp((T(1) - c) * axis); + + mat<4, 4, T, Q> Rotate; + Rotate[0][0] = c + temp[0] * axis[0]; + Rotate[0][1] = temp[0] * axis[1] + s * axis[2]; + Rotate[0][2] = temp[0] * axis[2] - s * axis[1]; + + Rotate[1][0] = temp[1] * axis[0] - s * axis[2]; + Rotate[1][1] = c + temp[1] * axis[1]; + Rotate[1][2] = temp[1] * axis[2] + s * axis[0]; + + Rotate[2][0] = temp[2] * axis[0] + s * axis[1]; + Rotate[2][1] = temp[2] * axis[1] - s * axis[0]; + Rotate[2][2] = c + temp[2] * axis[2]; + + mat<4, 4, T, Q> Result; + Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2]; + Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2]; + Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2]; + Result[3] = m[3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rotate_slow(mat<4, 4, T, Q> const& m, T angle, vec<3, T, Q> const& v) + { + T const a = angle; + T const c = cos(a); + T const s = sin(a); + mat<4, 4, T, Q> Result; + + vec<3, T, Q> axis = normalize(v); + + Result[0][0] = c + (static_cast(1) - c) * axis.x * axis.x; + Result[0][1] = (static_cast(1) - c) * axis.x * axis.y + s * axis.z; + Result[0][2] = (static_cast(1) - c) * axis.x * axis.z - s * axis.y; + Result[0][3] = static_cast(0); + + Result[1][0] = (static_cast(1) - c) * axis.y * axis.x - s * axis.z; + Result[1][1] = c + (static_cast(1) - c) * axis.y * axis.y; + Result[1][2] = (static_cast(1) - c) * axis.y * axis.z + s * axis.x; + Result[1][3] = static_cast(0); + + Result[2][0] = (static_cast(1) - c) * axis.z * axis.x + s * axis.y; + Result[2][1] = (static_cast(1) - c) * axis.z * axis.y - s * axis.x; + Result[2][2] = c + (static_cast(1) - c) * axis.z * axis.z; + Result[2][3] = static_cast(0); + + Result[3] = vec<4, T, Q>(0, 0, 0, 1); + return m * Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> scale(mat<4, 4, T, Q> const& m, vec<3, T, Q> const& v) + { + mat<4, 4, T, Q> Result; + Result[0] = m[0] * v[0]; + Result[1] = m[1] * v[1]; + Result[2] = m[2] * v[2]; + Result[3] = m[3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> scale_slow(mat<4, 4, T, Q> const& m, vec<3, T, Q> const& v) + { + mat<4, 4, T, Q> Result(T(1)); + Result[0][0] = v.x; + Result[1][1] = v.y; + Result[2][2] = v.z; + return m * Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shear(mat<4, 4, T, Q> const &m, vec<3, T, Q> const& p, vec<2, T, Q> const &l_x, vec<2, T, Q> const &l_y, vec<2, T, Q> const &l_z) + { + T const lambda_xy = l_x[0]; + T const lambda_xz = l_x[1]; + T const lambda_yx = l_y[0]; + T const lambda_yz = l_y[1]; + T const lambda_zx = l_z[0]; + T const lambda_zy = l_z[1]; + + vec<3, T, Q> point_lambda = vec<3, T, Q>( + (lambda_xy + lambda_xz), (lambda_yx + lambda_yz), (lambda_zx + lambda_zy) + ); + + mat<4, 4, T, Q> Shear = mat<4, 4, T, Q>( + 1 , lambda_yx , lambda_zx , 0, + lambda_xy , 1 , lambda_zy , 0, + lambda_xz , lambda_yz , 1 , 0, + -point_lambda[0] * p[0], -point_lambda[1] * p[1], -point_lambda[2] * p[2], 1 + ); + + mat<4, 4, T, Q> Result; + Result[0] = m[0] * Shear[0][0] + m[1] * Shear[0][1] + m[2] * Shear[0][2] + m[3] * Shear[0][3]; + Result[1] = m[0] * Shear[1][0] + m[1] * Shear[1][1] + m[2] * Shear[1][2] + m[3] * Shear[1][3]; + Result[2] = m[0] * Shear[2][0] + m[1] * Shear[2][1] + m[2] * Shear[2][2] + m[3] * Shear[2][3]; + Result[3] = m[0] * Shear[3][0] + m[1] * Shear[3][1] + m[2] * Shear[3][2] + m[3] * Shear[3][3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shear_slow(mat<4, 4, T, Q> const &m, vec<3, T, Q> const& p, vec<2, T, Q> const &l_x, vec<2, T, Q> const &l_y, vec<2, T, Q> const &l_z) + { + T const lambda_xy = static_cast(l_x[0]); + T const lambda_xz = static_cast(l_x[1]); + T const lambda_yx = static_cast(l_y[0]); + T const lambda_yz = static_cast(l_y[1]); + T const lambda_zx = static_cast(l_z[0]); + T const lambda_zy = static_cast(l_z[1]); + + vec<3, T, Q> point_lambda = vec<3, T, Q>( + static_cast(lambda_xy + lambda_xz), + static_cast(lambda_yx + lambda_yz), + static_cast(lambda_zx + lambda_zy) + ); + + mat<4, 4, T, Q> Shear = mat<4, 4, T, Q>( + 1 , lambda_yx , lambda_zx , 0, + lambda_xy , 1 , lambda_zy , 0, + lambda_xz , lambda_yz , 1 , 0, + -point_lambda[0] * p[0], -point_lambda[1] * p[1], -point_lambda[2] * p[2], 1 + ); + return m * Shear; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAtRH(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up) + { + vec<3, T, Q> const f(normalize(center - eye)); + vec<3, T, Q> const s(normalize(cross(f, up))); + vec<3, T, Q> const u(cross(s, f)); + + mat<4, 4, T, Q> Result(1); + Result[0][0] = s.x; + Result[1][0] = s.y; + Result[2][0] = s.z; + Result[0][1] = u.x; + Result[1][1] = u.y; + Result[2][1] = u.z; + Result[0][2] =-f.x; + Result[1][2] =-f.y; + Result[2][2] =-f.z; + Result[3][0] =-dot(s, eye); + Result[3][1] =-dot(u, eye); + Result[3][2] = dot(f, eye); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAtLH(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up) + { + vec<3, T, Q> const f(normalize(center - eye)); + vec<3, T, Q> const s(normalize(cross(up, f))); + vec<3, T, Q> const u(cross(f, s)); + + mat<4, 4, T, Q> Result(1); + Result[0][0] = s.x; + Result[1][0] = s.y; + Result[2][0] = s.z; + Result[0][1] = u.x; + Result[1][1] = u.y; + Result[2][1] = u.z; + Result[0][2] = f.x; + Result[1][2] = f.y; + Result[2][2] = f.z; + Result[3][0] = -dot(s, eye); + Result[3][1] = -dot(u, eye); + Result[3][2] = -dot(f, eye); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAt(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up) + { +# if (GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT) + return lookAtLH(eye, center, up); +# else + return lookAtRH(eye, center, up); +# endif + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x2.hpp new file mode 100644 index 0000000..034771a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x2.hpp @@ -0,0 +1,38 @@ +/// @ref ext_matrix_uint2x2 +/// @file glm/ext/matrix_uint2x2.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint2x2 GLM_EXT_matrix_uint2x2 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint2x2 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint2x2 + /// @{ + + /// Unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2 + typedef mat<2, 2, uint, defaultp> umat2x2; + + /// Unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2 + typedef mat<2, 2, uint, defaultp> umat2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x2_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x2_sized.hpp new file mode 100644 index 0000000..4555324 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x2_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_matrix_uint2x2_sized +/// @file glm/ext/matrix_uint2x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint2x2_sized GLM_EXT_matrix_uint2x2_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x2.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint2x2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint2x2_sized + /// @{ + + /// 8 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint8, defaultp> u8mat2x2; + + /// 16 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint16, defaultp> u16mat2x2; + + /// 32 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint32, defaultp> u32mat2x2; + + /// 64 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint64, defaultp> u64mat2x2; + + + /// 8 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint8, defaultp> u8mat2; + + /// 16 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint16, defaultp> u16mat2; + + /// 32 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint32, defaultp> u32mat2; + + /// 64 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint64, defaultp> u64mat2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x3.hpp new file mode 100644 index 0000000..f496c53 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x3.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_uint2x3 +/// @file glm/ext/matrix_uint2x3.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint2x3 GLM_EXT_matrix_uint2x3 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x3.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint2x3 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint2x3 + /// @{ + + /// Unsigned integer 2x3 matrix. + /// + /// @see ext_matrix_uint2x3 + typedef mat<2, 3, uint, defaultp> umat2x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x3_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x3_sized.hpp new file mode 100644 index 0000000..db7939c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x3_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint2x3_sized +/// @file glm/ext/matrix_uint2x3_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint2x3_sized GLM_EXT_matrix_uint2x3_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x3.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint2x3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint2x3_sized + /// @{ + + /// 8 bit unsigned integer 2x3 matrix. + /// + /// @see ext_matrix_uint2x3_sized + typedef mat<2, 3, uint8, defaultp> u8mat2x3; + + /// 16 bit unsigned integer 2x3 matrix. + /// + /// @see ext_matrix_uint2x3_sized + typedef mat<2, 3, uint16, defaultp> u16mat2x3; + + /// 32 bit unsigned integer 2x3 matrix. + /// + /// @see ext_matrix_uint2x3_sized + typedef mat<2, 3, uint32, defaultp> u32mat2x3; + + /// 64 bit unsigned integer 2x3 matrix. + /// + /// @see ext_matrix_uint2x3_sized + typedef mat<2, 3, uint64, defaultp> u64mat2x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x4.hpp new file mode 100644 index 0000000..0f99350 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x4.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_uint2x4 +/// @file glm/ext/matrix_uint2x4.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint2x4 GLM_EXT_matrix_int2x4 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint2x4 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint2x4 + /// @{ + + /// Unsigned integer 2x4 matrix. + /// + /// @see ext_matrix_uint2x4 + typedef mat<2, 4, uint, defaultp> umat2x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x4_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x4_sized.hpp new file mode 100644 index 0000000..5c55547 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint2x4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint2x4_sized +/// @file glm/ext/matrix_uint2x4_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint2x4_sized GLM_EXT_matrix_uint2x4_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x4.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint2x4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint2x4_sized + /// @{ + + /// 8 bit unsigned integer 2x4 matrix. + /// + /// @see ext_matrix_uint2x4_sized + typedef mat<2, 4, uint8, defaultp> u8mat2x4; + + /// 16 bit unsigned integer 2x4 matrix. + /// + /// @see ext_matrix_uint2x4_sized + typedef mat<2, 4, uint16, defaultp> u16mat2x4; + + /// 32 bit unsigned integer 2x4 matrix. + /// + /// @see ext_matrix_uint2x4_sized + typedef mat<2, 4, uint32, defaultp> u32mat2x4; + + /// 64 bit unsigned integer 2x4 matrix. + /// + /// @see ext_matrix_uint2x4_sized + typedef mat<2, 4, uint64, defaultp> u64mat2x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x2.hpp new file mode 100644 index 0000000..55a9bed --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x2.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_uint3x2 +/// @file glm/ext/matrix_uint3x2.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint3x2 GLM_EXT_matrix_uint3x2 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint3x2 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint3x2 + /// @{ + + /// Unsigned integer 3x2 matrix. + /// + /// @see ext_matrix_uint3x2 + typedef mat<3, 2, uint, defaultp> umat3x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x2_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x2_sized.hpp new file mode 100644 index 0000000..c81af8f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x2_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint3x2_sized +/// @file glm/ext/matrix_uint3x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint3x2_sized GLM_EXT_matrix_uint3x2_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x2.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint3x2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint3x2_sized + /// @{ + + /// 8 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_uint3x2_sized + typedef mat<3, 2, uint8, defaultp> u8mat3x2; + + /// 16 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_uint3x2_sized + typedef mat<3, 2, uint16, defaultp> u16mat3x2; + + /// 32 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_uint3x2_sized + typedef mat<3, 2, uint32, defaultp> u32mat3x2; + + /// 64 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_uint3x2_sized + typedef mat<3, 2, uint64, defaultp> u64mat3x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x3.hpp new file mode 100644 index 0000000..1004c0d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x3.hpp @@ -0,0 +1,38 @@ +/// @ref ext_matrix_uint3x3 +/// @file glm/ext/matrix_uint3x3.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint3x3 GLM_EXT_matrix_uint3x3 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint3x3 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint3x3 + /// @{ + + /// Unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3 + typedef mat<3, 3, uint, defaultp> umat3x3; + + /// Unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3 + typedef mat<3, 3, uint, defaultp> umat3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x3_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x3_sized.hpp new file mode 100644 index 0000000..41a8be7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x3_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_matrix_uint3x3_sized +/// @file glm/ext/matrix_uint3x3_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint3x3_sized GLM_EXT_matrix_uint3x3_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint3x3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint3x3_sized + /// @{ + + /// 8 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint8, defaultp> u8mat3x3; + + /// 16 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint16, defaultp> u16mat3x3; + + /// 32 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint32, defaultp> u32mat3x3; + + /// 64 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint64, defaultp> u64mat3x3; + + + /// 8 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint8, defaultp> u8mat3; + + /// 16 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint16, defaultp> u16mat3; + + /// 32 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint32, defaultp> u32mat3; + + /// 64 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint64, defaultp> u64mat3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x4.hpp new file mode 100644 index 0000000..c6dd78c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x4.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_uint3x4 +/// @file glm/ext/matrix_uint3x4.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint3x4 GLM_EXT_matrix_uint3x4 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint3x4 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint3x4 + /// @{ + + /// Signed integer 3x4 matrix. + /// + /// @see ext_matrix_uint3x4 + typedef mat<3, 4, uint, defaultp> umat3x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x4_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x4_sized.hpp new file mode 100644 index 0000000..2ce28ad --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint3x4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint3x4_sized +/// @file glm/ext/matrix_uint3x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint3x4_sized GLM_EXT_matrix_uint3x4_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x4.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint3x4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint3x4_sized + /// @{ + + /// 8 bit unsigned integer 3x4 matrix. + /// + /// @see ext_matrix_uint3x4_sized + typedef mat<3, 4, uint8, defaultp> u8mat3x4; + + /// 16 bit unsigned integer 3x4 matrix. + /// + /// @see ext_matrix_uint3x4_sized + typedef mat<3, 4, uint16, defaultp> u16mat3x4; + + /// 32 bit unsigned integer 3x4 matrix. + /// + /// @see ext_matrix_uint3x4_sized + typedef mat<3, 4, uint32, defaultp> u32mat3x4; + + /// 64 bit unsigned integer 3x4 matrix. + /// + /// @see ext_matrix_uint3x4_sized + typedef mat<3, 4, uint64, defaultp> u64mat3x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x2.hpp new file mode 100644 index 0000000..0446f57 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x2.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_uint4x2 +/// @file glm/ext/matrix_uint4x2.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint4x2 GLM_EXT_matrix_uint4x2 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint4x2 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint4x2 + /// @{ + + /// Unsigned integer 4x2 matrix. + /// + /// @see ext_matrix_uint4x2 + typedef mat<4, 2, uint, defaultp> umat4x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x2_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x2_sized.hpp new file mode 100644 index 0000000..57a66bf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x2_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint4x2_sized +/// @file glm/ext/matrix_uint4x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint4x2_sized GLM_EXT_matrix_uint4x2_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x2.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint4x2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint4x2_sized + /// @{ + + /// 8 bit unsigned integer 4x2 matrix. + /// + /// @see ext_matrix_uint4x2_sized + typedef mat<4, 2, uint8, defaultp> u8mat4x2; + + /// 16 bit unsigned integer 4x2 matrix. + /// + /// @see ext_matrix_uint4x2_sized + typedef mat<4, 2, uint16, defaultp> u16mat4x2; + + /// 32 bit unsigned integer 4x2 matrix. + /// + /// @see ext_matrix_uint4x2_sized + typedef mat<4, 2, uint32, defaultp> u32mat4x2; + + /// 64 bit unsigned integer 4x2 matrix. + /// + /// @see ext_matrix_uint4x2_sized + typedef mat<4, 2, uint64, defaultp> u64mat4x2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x3.hpp new file mode 100644 index 0000000..54c24e4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x3.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_uint4x3 +/// @file glm/ext/matrix_uint4x3.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint4x3 GLM_EXT_matrix_uint4x3 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x3.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint4x3 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint4x3 + /// @{ + + /// Unsigned integer 4x3 matrix. + /// + /// @see ext_matrix_uint4x3 + typedef mat<4, 3, uint, defaultp> umat4x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x3_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x3_sized.hpp new file mode 100644 index 0000000..2e61124 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x3_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint4x3_sized +/// @file glm/ext/matrix_uint4x3_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint4x3_sized GLM_EXT_matrix_uint4x3_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x3.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint4x3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint4x3_sized + /// @{ + + /// 8 bit unsigned integer 4x3 matrix. + /// + /// @see ext_matrix_uint4x3_sized + typedef mat<4, 3, uint8, defaultp> u8mat4x3; + + /// 16 bit unsigned integer 4x3 matrix. + /// + /// @see ext_matrix_uint4x3_sized + typedef mat<4, 3, uint16, defaultp> u16mat4x3; + + /// 32 bit unsigned integer 4x3 matrix. + /// + /// @see ext_matrix_uint4x3_sized + typedef mat<4, 3, uint32, defaultp> u32mat4x3; + + /// 64 bit unsigned integer 4x3 matrix. + /// + /// @see ext_matrix_uint4x3_sized + typedef mat<4, 3, uint64, defaultp> u64mat4x3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x4.hpp new file mode 100644 index 0000000..5cc8455 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x4.hpp @@ -0,0 +1,38 @@ +/// @ref ext_matrix_uint4x4 +/// @file glm/ext/matrix_uint4x4.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint4x4 GLM_EXT_matrix_uint4x4 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint4x4 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint4x4 + /// @{ + + /// Unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4 + typedef mat<4, 4, uint, defaultp> umat4x4; + + /// Unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4 + typedef mat<4, 4, uint, defaultp> umat4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x4_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x4_sized.hpp new file mode 100644 index 0000000..bb10bd2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_uint4x4_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_matrix_uint4x4_sized +/// @file glm/ext/matrix_uint4x4_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint4x4_sized GLM_EXT_matrix_uint4x4_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x4.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint4x4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint4x4_sized + /// @{ + + /// 8 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint8, defaultp> u8mat4x4; + + /// 16 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint16, defaultp> u16mat4x4; + + /// 32 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint32, defaultp> u32mat4x4; + + /// 64 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint64, defaultp> u64mat4x4; + + + /// 8 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint8, defaultp> u8mat4; + + /// 16 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint16, defaultp> u16mat4; + + /// 32 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint32, defaultp> u32mat4; + + /// 64 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint64, defaultp> u64mat4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_common.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_common.hpp new file mode 100644 index 0000000..f738692 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_common.hpp @@ -0,0 +1,135 @@ +/// @ref ext_quaternion_common +/// @file glm/ext/quaternion_common.hpp +/// +/// @defgroup ext_quaternion_common GLM_EXT_quaternion_common +/// @ingroup ext +/// +/// Provides common functions for quaternion types +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_common +/// @see ext_vector_common +/// @see ext_quaternion_float +/// @see ext_quaternion_double +/// @see ext_quaternion_exponential +/// @see ext_quaternion_geometric +/// @see ext_quaternion_relational +/// @see ext_quaternion_trigonometric +/// @see ext_quaternion_transform + +#pragma once + +// Dependency: +#include "../ext/scalar_constants.hpp" +#include "../ext/quaternion_geometric.hpp" +#include "../common.hpp" +#include "../trigonometric.hpp" +#include "../exponential.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_common extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_common + /// @{ + + /// Spherical linear interpolation of two quaternions. + /// The interpolation is oriented and the rotation is performed at constant speed. + /// For short path spherical linear interpolation, use the slerp function. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @see - slerp(qua const& x, qua const& y, T const& a) + template + GLM_FUNC_DECL qua mix(qua const& x, qua const& y, T a); + + /// Linear interpolation of two quaternions. + /// The interpolation is oriented. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined in the range [0, 1]. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR qua lerp(qua const& x, qua const& y, T a); + + /// Spherical linear interpolation of two quaternions. + /// The interpolation always take the short path and the rotation is performed at constant speed. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua slerp(qua const& x, qua const& y, T a); + + /// Spherical linear interpolation of two quaternions with multiple spins over rotation axis. + /// The interpolation always take the short path when the spin count is positive and long path + /// when count is negative. Rotation is performed at constant speed. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// @param k Additional spin count. If Value is negative interpolation will be on "long" path. + /// + /// @tparam T A floating-point scalar type + /// @tparam S An integer scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua slerp(qua const& x, qua const& y, T a, S k); + + /// Returns the q conjugate. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR qua conjugate(qua const& q); + + /// Returns the q inverse. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR qua inverse(qua const& q); + + /// Returns true if x holds a NaN (not a number) + /// representation in the underlying implementation's set of + /// floating point representations. Returns false otherwise, + /// including for implementations with no NaN + /// representations. + /// + /// /!\ When using compiler fast math, this function may fail. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL vec<4, bool, Q> isnan(qua const& x); + + /// Returns true if x holds a positive infinity or negative + /// infinity representation in the underlying implementation's + /// set of floating point representations. Returns false + /// otherwise, including for implementations with no infinity + /// representations. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL vec<4, bool, Q> isinf(qua const& x); + + /// @} +} //namespace glm + +#include "quaternion_common.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_common.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_common.inl new file mode 100644 index 0000000..ad171f9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_common.inl @@ -0,0 +1,144 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER qua mix(qua const& x, qua const& y, T a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'mix' only accept floating-point inputs"); + + T const cosTheta = dot(x, y); + + // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator + if(cosTheta > static_cast(1) - epsilon()) + { + // Linear interpolation + return qua::wxyz( + mix(x.w, y.w, a), + mix(x.x, y.x, a), + mix(x.y, y.y, a), + mix(x.z, y.z, a)); + } + else + { + // Essential Mathematics, page 467 + T angle = acos(cosTheta); + return (sin((static_cast(1) - a) * angle) * x + sin(a * angle) * y) / sin(angle); + } + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua lerp(qua const& x, qua const& y, T a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'lerp' only accept floating-point inputs"); + + // Lerp is only defined in [0, 1] + assert(a >= static_cast(0)); + assert(a <= static_cast(1)); + + return x * (static_cast(1) - a) + (y * a); + } + + template + GLM_FUNC_QUALIFIER qua slerp(qua const& x, qua const& y, T a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'slerp' only accept floating-point inputs"); + + qua z = y; + + T cosTheta = dot(x, y); + + // If cosTheta < 0, the interpolation will take the long way around the sphere. + // To fix this, one quat must be negated. + if(cosTheta < static_cast(0)) + { + z = -y; + cosTheta = -cosTheta; + } + + // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator + if(cosTheta > static_cast(1) - epsilon()) + { + // Linear interpolation + return qua::wxyz( + mix(x.w, z.w, a), + mix(x.x, z.x, a), + mix(x.y, z.y, a), + mix(x.z, z.z, a)); + } + else + { + // Essential Mathematics, page 467 + T angle = acos(cosTheta); + return (sin((static_cast(1) - a) * angle) * x + sin(a * angle) * z) / sin(angle); + } + } + + template + GLM_FUNC_QUALIFIER qua slerp(qua const& x, qua const& y, T a, S k) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'slerp' only accept floating-point inputs"); + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'slerp' only accept integer for spin count"); + + qua z = y; + + T cosTheta = dot(x, y); + + // If cosTheta < 0, the interpolation will take the long way around the sphere. + // To fix this, one quat must be negated. + if (cosTheta < static_cast(0)) + { + z = -y; + cosTheta = -cosTheta; + } + + // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator + if (cosTheta > static_cast(1) - epsilon()) + { + // Linear interpolation + return qua::wxyz( + mix(x.w, z.w, a), + mix(x.x, z.x, a), + mix(x.y, z.y, a), + mix(x.z, z.z, a)); + } + else + { + // Graphics Gems III, page 96 + T angle = acos(cosTheta); + T phi = angle + static_cast(k) * glm::pi(); + return (sin(angle - a * phi)* x + sin(a * phi) * z) / sin(angle); + } + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua conjugate(qua const& q) + { + return qua::wxyz(q.w, -q.x, -q.y, -q.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua inverse(qua const& q) + { + return conjugate(q) / dot(q, q); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> isnan(qua const& q) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isnan' only accept floating-point inputs"); + + return vec<4, bool, Q>(isnan(q.x), isnan(q.y), isnan(q.z), isnan(q.w)); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> isinf(qua const& q) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isinf' only accept floating-point inputs"); + + return vec<4, bool, Q>(isinf(q.x), isinf(q.y), isinf(q.z), isinf(q.w)); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "quaternion_common_simd.inl" +#endif + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_common_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_common_simd.inl new file mode 100644 index 0000000..ddfc8a4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_common_simd.inl @@ -0,0 +1,18 @@ +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ + template + struct compute_dot, float, true> + { + static GLM_FUNC_QUALIFIER float call(qua const& x, qua const& y) + { + return _mm_cvtss_f32(glm_vec1_dot(x.data, y.data)); + } + }; +}//namespace detail +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_double.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_double.hpp new file mode 100644 index 0000000..63b24de --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_double.hpp @@ -0,0 +1,39 @@ +/// @ref ext_quaternion_double +/// @file glm/ext/quaternion_double.hpp +/// +/// @defgroup ext_quaternion_double GLM_EXT_quaternion_double +/// @ingroup ext +/// +/// Exposes double-precision floating point quaternion type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_quaternion_float +/// @see ext_quaternion_double_precision +/// @see ext_quaternion_common +/// @see ext_quaternion_exponential +/// @see ext_quaternion_geometric +/// @see ext_quaternion_relational +/// @see ext_quaternion_transform +/// @see ext_quaternion_trigonometric + +#pragma once + +// Dependency: +#include "../detail/type_quat.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_double extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_double + /// @{ + + /// Quaternion of double-precision floating-point numbers. + typedef qua dquat; + + /// @} +} //namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_double_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_double_precision.hpp new file mode 100644 index 0000000..8aa24a1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_double_precision.hpp @@ -0,0 +1,42 @@ +/// @ref ext_quaternion_double_precision +/// @file glm/ext/quaternion_double_precision.hpp +/// +/// @defgroup ext_quaternion_double_precision GLM_EXT_quaternion_double_precision +/// @ingroup ext +/// +/// Exposes double-precision floating point quaternion type with various precision in term of ULPs. +/// +/// Include to use the features of this extension. + +#pragma once + +// Dependency: +#include "../detail/type_quat.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_double_precision extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_double_precision + /// @{ + + /// Quaternion of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see ext_quaternion_double_precision + typedef qua lowp_dquat; + + /// Quaternion of medium double-qualifier floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see ext_quaternion_double_precision + typedef qua mediump_dquat; + + /// Quaternion of high double-qualifier floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see ext_quaternion_double_precision + typedef qua highp_dquat; + + /// @} +} //namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_exponential.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_exponential.hpp new file mode 100644 index 0000000..affe297 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_exponential.hpp @@ -0,0 +1,63 @@ +/// @ref ext_quaternion_exponential +/// @file glm/ext/quaternion_exponential.hpp +/// +/// @defgroup ext_quaternion_exponential GLM_EXT_quaternion_exponential +/// @ingroup ext +/// +/// Provides exponential functions for quaternion types +/// +/// Include to use the features of this extension. +/// +/// @see core_exponential +/// @see ext_quaternion_float +/// @see ext_quaternion_double + +#pragma once + +// Dependency: +#include "../common.hpp" +#include "../trigonometric.hpp" +#include "../geometric.hpp" +#include "../ext/scalar_constants.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_exponential extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_transform + /// @{ + + /// Returns a exponential of a quaternion. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua exp(qua const& q); + + /// Returns a logarithm of a quaternion + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua log(qua const& q); + + /// Returns a quaternion raised to a power. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua pow(qua const& q, T y); + + /// Returns the square root of a quaternion + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua sqrt(qua const& q); + + /// @} +} //namespace glm + +#include "quaternion_exponential.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_exponential.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_exponential.inl new file mode 100644 index 0000000..8a9d774 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_exponential.inl @@ -0,0 +1,89 @@ +#include "scalar_constants.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER qua exp(qua const& q) + { + vec<3, T, Q> u(q.x, q.y, q.z); + T const Angle = glm::length(u); + if (Angle < epsilon()) + return qua(); + + vec<3, T, Q> const v(u / Angle); + return qua(cos(Angle), sin(Angle) * v); + } + + template + GLM_FUNC_QUALIFIER qua log(qua const& q) + { + vec<3, T, Q> u(q.x, q.y, q.z); + T Vec3Len = length(u); + + if (Vec3Len < epsilon()) + { + if(q.w > static_cast(0)) + return qua::wxyz(log(q.w), static_cast(0), static_cast(0), static_cast(0)); + else if(q.w < static_cast(0)) + return qua::wxyz(log(-q.w), pi(), static_cast(0), static_cast(0)); + else + return qua::wxyz(std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity()); + } + else + { + T t = atan(Vec3Len, T(q.w)) / Vec3Len; + T QuatLen2 = Vec3Len * Vec3Len + q.w * q.w; + return qua::wxyz(static_cast(0.5) * log(QuatLen2), t * q.x, t * q.y, t * q.z); + } + } + + template + GLM_FUNC_QUALIFIER qua pow(qua const& x, T y) + { + //Raising to the power of 0 should yield 1 + //Needed to prevent a division by 0 error later on + if(y > -epsilon() && y < epsilon()) + return qua::wxyz(1,0,0,0); + + //To deal with non-unit quaternions + T magnitude = sqrt(x.x * x.x + x.y * x.y + x.z * x.z + x.w *x.w); + + T Angle; + if(abs(x.w / magnitude) > cos_one_over_two()) + { + //Scalar component is close to 1; using it to recover angle would lose precision + //Instead, we use the non-scalar components since sin() is accurate around 0 + + //Prevent a division by 0 error later on + T VectorMagnitude = x.x * x.x + x.y * x.y + x.z * x.z; + //Despite the compiler might say, we actually want to compare + //VectorMagnitude to 0. here; we could use denorm_int() compiling a + //project with unsafe maths optimizations might make the comparison + //always false, even when VectorMagnitude is 0. + if (VectorMagnitude < std::numeric_limits::min()) { + //Equivalent to raising a real number to a power + return qua::wxyz(pow(x.w, y), 0, 0, 0); + } + + Angle = asin(sqrt(VectorMagnitude) / magnitude); + } + else + { + //Scalar component is small, shouldn't cause loss of precision + Angle = acos(x.w / magnitude); + } + + T NewAngle = Angle * y; + T Div = sin(NewAngle) / sin(Angle); + T Mag = pow(magnitude, y - static_cast(1)); + return qua::wxyz(cos(NewAngle) * magnitude * Mag, x.x * Div * Mag, x.y * Div * Mag, x.z * Div * Mag); + } + + template + GLM_FUNC_QUALIFIER qua sqrt(qua const& x) + { + return pow(x, static_cast(0.5)); + } +}//namespace glm + + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_float.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_float.hpp new file mode 100644 index 0000000..ca42a60 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_float.hpp @@ -0,0 +1,39 @@ +/// @ref ext_quaternion_float +/// @file glm/ext/quaternion_float.hpp +/// +/// @defgroup ext_quaternion_float GLM_EXT_quaternion_float +/// @ingroup ext +/// +/// Exposes single-precision floating point quaternion type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_quaternion_double +/// @see ext_quaternion_float_precision +/// @see ext_quaternion_common +/// @see ext_quaternion_exponential +/// @see ext_quaternion_geometric +/// @see ext_quaternion_relational +/// @see ext_quaternion_transform +/// @see ext_quaternion_trigonometric + +#pragma once + +// Dependency: +#include "../detail/type_quat.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_float extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_float + /// @{ + + /// Quaternion of single-precision floating-point numbers. + typedef qua quat; + + /// @} +} //namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_float_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_float_precision.hpp new file mode 100644 index 0000000..f9e4f5c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_float_precision.hpp @@ -0,0 +1,36 @@ +/// @ref ext_quaternion_float_precision +/// @file glm/ext/quaternion_float_precision.hpp +/// +/// @defgroup ext_quaternion_float_precision GLM_EXT_quaternion_float_precision +/// @ingroup ext +/// +/// Exposes single-precision floating point quaternion type with various precision in term of ULPs. +/// +/// Include to use the features of this extension. + +#pragma once + +// Dependency: +#include "../detail/type_quat.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_float_precision extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_float_precision + /// @{ + + /// Quaternion of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef qua lowp_quat; + + /// Quaternion of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef qua mediump_quat; + + /// Quaternion of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef qua highp_quat; + + /// @} +} //namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_geometric.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_geometric.hpp new file mode 100644 index 0000000..6a2403f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_geometric.hpp @@ -0,0 +1,70 @@ +/// @ref ext_quaternion_geometric +/// @file glm/ext/quaternion_geometric.hpp +/// +/// @defgroup ext_quaternion_geometric GLM_EXT_quaternion_geometric +/// @ingroup ext +/// +/// Provides geometric functions for quaternion types +/// +/// Include to use the features of this extension. +/// +/// @see core_func_geometric +/// @see ext_quaternion_float +/// @see ext_quaternion_double + +#pragma once + +// Dependency: +#include "../geometric.hpp" +#include "../exponential.hpp" +#include "../ext/vector_relational.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_geometric extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_geometric + /// @{ + + /// Returns the norm of a quaternions + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_geometric + template + GLM_FUNC_DECL T length(qua const& q); + + /// Returns the normalized quaternion. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_geometric + template + GLM_FUNC_DECL qua normalize(qua const& q); + + /// Returns dot product of q1 and q2, i.e., q1[0] * q2[0] + q1[1] * q2[1] + ... + /// + /// @tparam T Floating-point scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_geometric + template + GLM_FUNC_DECL GLM_CONSTEXPR T dot(qua const& x, qua const& y); + + /// Compute a cross product. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_geometric + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua cross(qua const& q1, qua const& q2); + + /// @} +} //namespace glm + +#include "quaternion_geometric.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_geometric.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_geometric.inl new file mode 100644 index 0000000..88dc4d6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_geometric.inl @@ -0,0 +1,36 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T dot(qua const& x, qua const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'dot' accepts only floating-point inputs"); + return detail::compute_dot, T, detail::is_aligned::value>::call(x, y); + } + + template + GLM_FUNC_QUALIFIER T length(qua const& q) + { + return glm::sqrt(dot(q, q)); + } + + template + GLM_FUNC_QUALIFIER qua normalize(qua const& q) + { + T len = length(q); + if(len <= static_cast(0)) // Problem + return qua::wxyz(static_cast(1), static_cast(0), static_cast(0), static_cast(0)); + T oneOverLen = static_cast(1) / len; + return qua::wxyz(q.w * oneOverLen, q.x * oneOverLen, q.y * oneOverLen, q.z * oneOverLen); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua cross(qua const& q1, qua const& q2) + { + return qua::wxyz( + q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z, + q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y, + q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z, + q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x); + } +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_relational.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_relational.hpp new file mode 100644 index 0000000..7aa121d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_relational.hpp @@ -0,0 +1,62 @@ +/// @ref ext_quaternion_relational +/// @file glm/ext/quaternion_relational.hpp +/// +/// @defgroup ext_quaternion_relational GLM_EXT_quaternion_relational +/// @ingroup ext +/// +/// Exposes comparison functions for quaternion types that take a user defined epsilon values. +/// +/// Include to use the features of this extension. +/// +/// @see core_vector_relational +/// @see ext_vector_relational +/// @see ext_matrix_relational +/// @see ext_quaternion_float +/// @see ext_quaternion_double + +#pragma once + +// Dependency: +#include "../vector_relational.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_relational extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_relational + /// @{ + + /// Returns the component-wise comparison of result x == y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL vec<4, bool, Q> equal(qua const& x, qua const& y); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL vec<4, bool, Q> equal(qua const& x, qua const& y, T epsilon); + + /// Returns the component-wise comparison of result x != y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL vec<4, bool, Q> notEqual(qua const& x, qua const& y); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL vec<4, bool, Q> notEqual(qua const& x, qua const& y, T epsilon); + + /// @} +} //namespace glm + +#include "quaternion_relational.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_relational.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_relational.inl new file mode 100644 index 0000000..b1713e9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_relational.inl @@ -0,0 +1,35 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> equal(qua const& x, qua const& y) + { + vec<4, bool, Q> Result; + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] == y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> equal(qua const& x, qua const& y, T epsilon) + { + vec<4, T, Q> v(x.x - y.x, x.y - y.y, x.z - y.z, x.w - y.w); + return lessThan(abs(v), vec<4, T, Q>(epsilon)); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> notEqual(qua const& x, qua const& y) + { + vec<4, bool, Q> Result; + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] != y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> notEqual(qua const& x, qua const& y, T epsilon) + { + vec<4, T, Q> v(x.x - y.x, x.y - y.y, x.z - y.z, x.w - y.w); + return greaterThanEqual(abs(v), vec<4, T, Q>(epsilon)); + } +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_transform.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_transform.hpp new file mode 100644 index 0000000..a9cc5c2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_transform.hpp @@ -0,0 +1,47 @@ +/// @ref ext_quaternion_transform +/// @file glm/ext/quaternion_transform.hpp +/// +/// @defgroup ext_quaternion_transform GLM_EXT_quaternion_transform +/// @ingroup ext +/// +/// Provides transformation functions for quaternion types +/// +/// Include to use the features of this extension. +/// +/// @see ext_quaternion_float +/// @see ext_quaternion_double +/// @see ext_quaternion_exponential +/// @see ext_quaternion_geometric +/// @see ext_quaternion_relational +/// @see ext_quaternion_trigonometric + +#pragma once + +// Dependency: +#include "../common.hpp" +#include "../trigonometric.hpp" +#include "../geometric.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_transform extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_transform + /// @{ + + /// Rotates a quaternion from a vector of 3 components axis and an angle. + /// + /// @param q Source orientation + /// @param angle Angle expressed in radians. + /// @param axis Axis of the rotation + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL qua rotate(qua const& q, T const& angle, vec<3, T, Q> const& axis); + /// @} +} //namespace glm + +#include "quaternion_transform.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_transform.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_transform.inl new file mode 100644 index 0000000..7e773fb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_transform.inl @@ -0,0 +1,24 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER qua rotate(qua const& q, T const& angle, vec<3, T, Q> const& v) + { + vec<3, T, Q> Tmp = v; + + // Axis of rotation must be normalised + T len = glm::length(Tmp); + if(abs(len - static_cast(1)) > static_cast(0.001)) + { + T oneOverLen = static_cast(1) / len; + Tmp.x *= oneOverLen; + Tmp.y *= oneOverLen; + Tmp.z *= oneOverLen; + } + + T const AngleRad(angle); + T const Sin = sin(AngleRad * static_cast(0.5)); + + return q * qua::wxyz(cos(AngleRad * static_cast(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); + } +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_trigonometric.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_trigonometric.hpp new file mode 100644 index 0000000..574a704 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_trigonometric.hpp @@ -0,0 +1,65 @@ +/// @ref ext_quaternion_trigonometric +/// @file glm/ext/quaternion_trigonometric.hpp +/// +/// @defgroup ext_quaternion_trigonometric GLM_EXT_quaternion_trigonometric +/// @ingroup ext +/// +/// Provides trigonometric functions for quaternion types +/// +/// Include to use the features of this extension. +/// +/// @see ext_quaternion_float +/// @see ext_quaternion_double +/// @see ext_quaternion_exponential +/// @see ext_quaternion_geometric +/// @see ext_quaternion_relational +/// @see ext_quaternion_transform + +#pragma once + +// Dependency: +#include "../trigonometric.hpp" +#include "../exponential.hpp" +#include "scalar_constants.hpp" +#include "vector_relational.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_trigonometric extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_trigonometric + /// @{ + + /// Returns the quaternion rotation angle. + /// + /// @param x A normalized quaternion. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL T angle(qua const& x); + + /// Returns the q rotation axis. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL vec<3, T, Q> axis(qua const& x); + + /// Build a quaternion from an angle and a normalized axis. + /// + /// @param angle Angle expressed in radians. + /// @param axis Axis of the quaternion, must be normalized. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua angleAxis(T const& angle, vec<3, T, Q> const& axis); + + /// @} +} //namespace glm + +#include "quaternion_trigonometric.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_trigonometric.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_trigonometric.inl new file mode 100644 index 0000000..896449a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_trigonometric.inl @@ -0,0 +1,37 @@ +#include "scalar_constants.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T angle(qua const& x) + { + if (abs(x.w) > cos_one_over_two()) + { + T const a = asin(sqrt(x.x * x.x + x.y * x.y + x.z * x.z)) * static_cast(2); + if(x.w < static_cast(0)) + return pi() * static_cast(2) - a; + return a; + } + + return acos(x.w) * static_cast(2); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> axis(qua const& x) + { + T const tmp1 = static_cast(1) - x.w * x.w; + if(tmp1 <= static_cast(0)) + return vec<3, T, Q>(0, 0, 1); + T const tmp2 = static_cast(1) / sqrt(tmp1); + return vec<3, T, Q>(x.x * tmp2, x.y * tmp2, x.z * tmp2); + } + + template + GLM_FUNC_QUALIFIER qua angleAxis(T const& angle, vec<3, T, Q> const& v) + { + T const a(angle); + T const s = glm::sin(a * static_cast(0.5)); + + return qua(glm::cos(a * static_cast(0.5)), v * s); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_common.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_common.hpp new file mode 100644 index 0000000..df04b6b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_common.hpp @@ -0,0 +1,181 @@ +/// @ref ext_scalar_common +/// @file glm/ext/scalar_common.hpp +/// +/// @defgroup ext_scalar_common GLM_EXT_scalar_common +/// @ingroup ext +/// +/// Exposes min and max functions for 3 to 4 scalar parameters. +/// +/// Include to use the features of this extension. +/// +/// @see core_func_common +/// @see ext_vector_common + +#pragma once + +// Dependency: +#include "../common.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_common extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_scalar_common + /// @{ + + /// Returns the minimum component-wise values of 3 inputs + /// + /// @tparam T A floating-point scalar type. + /// + /// @see ext_scalar_common + template + GLM_FUNC_DECL T min(T a, T b, T c); + + /// Returns the minimum component-wise values of 4 inputs + /// + /// @tparam T A floating-point scalar type. + /// + /// @see ext_scalar_common + template + GLM_FUNC_DECL T min(T a, T b, T c, T d); + + /// Returns the maximum component-wise values of 3 inputs + /// + /// @tparam T A floating-point scalar type. + /// + /// @see ext_scalar_common + template + GLM_FUNC_DECL T max(T a, T b, T c); + + /// Returns the maximum component-wise values of 4 inputs + /// + /// @tparam T A floating-point scalar type. + /// + /// @see ext_scalar_common + template + GLM_FUNC_DECL T max(T a, T b, T c, T d); + + /// Returns the minimum component-wise values of 2 inputs. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam T A floating-point scalar type. + /// + /// @see std::fmin documentation + /// @see ext_scalar_common + template + GLM_FUNC_DECL T fmin(T a, T b); + + /// Returns the minimum component-wise values of 3 inputs. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam T A floating-point scalar type. + /// + /// @see std::fmin documentation + /// @see ext_scalar_common + template + GLM_FUNC_DECL T fmin(T a, T b, T c); + + /// Returns the minimum component-wise values of 4 inputs. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam T A floating-point scalar type. + /// + /// @see std::fmin documentation + /// @see ext_scalar_common + template + GLM_FUNC_DECL T fmin(T a, T b, T c, T d); + + /// Returns the maximum component-wise values of 2 inputs. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam T A floating-point scalar type. + /// + /// @see std::fmax documentation + /// @see ext_scalar_common + template + GLM_FUNC_DECL T fmax(T a, T b); + + /// Returns the maximum component-wise values of 3 inputs. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam T A floating-point scalar type. + /// + /// @see std::fmax documentation + /// @see ext_scalar_common + template + GLM_FUNC_DECL T fmax(T a, T b, T C); + + /// Returns the maximum component-wise values of 4 inputs. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam T A floating-point scalar type. + /// + /// @see std::fmax documentation + /// @see ext_scalar_common + template + GLM_FUNC_DECL T fmax(T a, T b, T C, T D); + + /// Returns min(max(x, minVal), maxVal) for each component in x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam genType Floating-point scalar types. + /// + /// @see ext_scalar_common + template + GLM_FUNC_DECL genType fclamp(genType x, genType minVal, genType maxVal); + + /// Simulate GL_CLAMP OpenGL wrap mode + /// + /// @tparam genType Floating-point scalar types. + /// + /// @see ext_scalar_common extension. + template + GLM_FUNC_DECL genType clamp(genType const& Texcoord); + + /// Simulate GL_REPEAT OpenGL wrap mode + /// + /// @tparam genType Floating-point scalar types. + /// + /// @see ext_scalar_common extension. + template + GLM_FUNC_DECL genType repeat(genType const& Texcoord); + + /// Simulate GL_MIRRORED_REPEAT OpenGL wrap mode + /// + /// @tparam genType Floating-point scalar types. + /// + /// @see ext_scalar_common extension. + template + GLM_FUNC_DECL genType mirrorClamp(genType const& Texcoord); + + /// Simulate GL_MIRROR_REPEAT OpenGL wrap mode + /// + /// @tparam genType Floating-point scalar types. + /// + /// @see ext_scalar_common extension. + template + GLM_FUNC_DECL genType mirrorRepeat(genType const& Texcoord); + + /// Returns a value equal to the nearest integer to x. + /// The fraction 0.5 will round in a direction chosen by the + /// implementation, presumably the direction that is fastest. + /// + /// @param x The values of the argument must be greater or equal to zero. + /// @tparam genType floating point scalar types. + /// + /// @see GLSL round man page + /// @see ext_scalar_common extension. + template + GLM_FUNC_DECL int iround(genType const& x); + + /// Returns a value equal to the nearest integer to x. + /// The fraction 0.5 will round in a direction chosen by the + /// implementation, presumably the direction that is fastest. + /// + /// @param x The values of the argument must be greater or equal to zero. + /// @tparam genType floating point scalar types. + /// + /// @see GLSL round man page + /// @see ext_scalar_common extension. + template + GLM_FUNC_DECL uint uround(genType const& x); + + /// @} +}//namespace glm + +#include "scalar_common.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_common.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_common.inl new file mode 100644 index 0000000..3d09fef --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_common.inl @@ -0,0 +1,170 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER T min(T a, T b, T c) + { + return glm::min(glm::min(a, b), c); + } + + template + GLM_FUNC_QUALIFIER T min(T a, T b, T c, T d) + { + return glm::min(glm::min(a, b), glm::min(c, d)); + } + + template + GLM_FUNC_QUALIFIER T max(T a, T b, T c) + { + return glm::max(glm::max(a, b), c); + } + + template + GLM_FUNC_QUALIFIER T max(T a, T b, T c, T d) + { + return glm::max(glm::max(a, b), glm::max(c, d)); + } + +# if GLM_HAS_CXX11_STL + using std::fmin; +# else + template + GLM_FUNC_QUALIFIER T fmin(T a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'fmin' only accept floating-point input"); + + if (isnan(a)) + return b; + return min(a, b); + } +# endif + + template + GLM_FUNC_QUALIFIER T fmin(T a, T b, T c) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'fmin' only accept floating-point input"); + + if (isnan(a)) + return fmin(b, c); + if (isnan(b)) + return fmin(a, c); + if (isnan(c)) + return min(a, b); + return min(a, b, c); + } + + template + GLM_FUNC_QUALIFIER T fmin(T a, T b, T c, T d) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'fmin' only accept floating-point input"); + + if (isnan(a)) + return fmin(b, c, d); + if (isnan(b)) + return min(a, fmin(c, d)); + if (isnan(c)) + return fmin(min(a, b), d); + if (isnan(d)) + return min(a, b, c); + return min(a, b, c, d); + } + + +# if GLM_HAS_CXX11_STL + using std::fmax; +# else + template + GLM_FUNC_QUALIFIER T fmax(T a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'fmax' only accept floating-point input"); + + if (isnan(a)) + return b; + return max(a, b); + } +# endif + + template + GLM_FUNC_QUALIFIER T fmax(T a, T b, T c) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'fmax' only accept floating-point input"); + + if (isnan(a)) + return fmax(b, c); + if (isnan(b)) + return fmax(a, c); + if (isnan(c)) + return max(a, b); + return max(a, b, c); + } + + template + GLM_FUNC_QUALIFIER T fmax(T a, T b, T c, T d) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'fmax' only accept floating-point input"); + + if (isnan(a)) + return fmax(b, c, d); + if (isnan(b)) + return max(a, fmax(c, d)); + if (isnan(c)) + return fmax(max(a, b), d); + if (isnan(d)) + return max(a, b, c); + return max(a, b, c, d); + } + + // fclamp + template + GLM_FUNC_QUALIFIER genType fclamp(genType x, genType minVal, genType maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'fclamp' only accept floating-point or integer inputs"); + return fmin(fmax(x, minVal), maxVal); + } + + template + GLM_FUNC_QUALIFIER genType clamp(genType const& Texcoord) + { + return glm::clamp(Texcoord, static_cast(0), static_cast(1)); + } + + template + GLM_FUNC_QUALIFIER genType repeat(genType const& Texcoord) + { + return glm::fract(Texcoord); + } + + template + GLM_FUNC_QUALIFIER genType mirrorClamp(genType const& Texcoord) + { + return glm::fract(glm::abs(Texcoord)); + } + + template + GLM_FUNC_QUALIFIER genType mirrorRepeat(genType const& Texcoord) + { + genType const Abs = glm::abs(Texcoord); + genType const Clamp = glm::mod(glm::floor(Abs), static_cast(2)); + genType const Floor = glm::floor(Abs); + genType const Rest = Abs - Floor; + genType const Mirror = Clamp + Rest; + return mix(Rest, static_cast(1) - Rest, Mirror >= static_cast(1)); + } + + template + GLM_FUNC_QUALIFIER int iround(genType const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'iround' only accept floating-point inputs"); + assert(static_cast(0.0) <= x); + + return static_cast(x + static_cast(0.5)); + } + + template + GLM_FUNC_QUALIFIER uint uround(genType const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'uround' only accept floating-point inputs"); + assert(static_cast(0.0) <= x); + + return static_cast(x + static_cast(0.5)); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_constants.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_constants.hpp new file mode 100644 index 0000000..74e210d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_constants.hpp @@ -0,0 +1,40 @@ +/// @ref ext_scalar_constants +/// @file glm/ext/scalar_constants.hpp +/// +/// @defgroup ext_scalar_constants GLM_EXT_scalar_constants +/// @ingroup ext +/// +/// Provides a list of constants and precomputed useful values. +/// +/// Include to use the features of this extension. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_constants extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_scalar_constants + /// @{ + + /// Return the epsilon constant for floating point types. + template + GLM_FUNC_DECL GLM_CONSTEXPR genType epsilon(); + + /// Return the pi constant for floating point types. + template + GLM_FUNC_DECL GLM_CONSTEXPR genType pi(); + + /// Return the value of cos(1 / 2) for floating point types. + template + GLM_FUNC_DECL GLM_CONSTEXPR genType cos_one_over_two(); + + /// @} +} //namespace glm + +#include "scalar_constants.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_constants.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_constants.inl new file mode 100644 index 0000000..b928e51 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_constants.inl @@ -0,0 +1,24 @@ +#include + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType epsilon() + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'epsilon' only accepts floating-point inputs"); + return std::numeric_limits::epsilon(); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType pi() + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'pi' only accepts floating-point inputs"); + return static_cast(3.14159265358979323846264338327950288); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType cos_one_over_two() + { + return genType(0.877582561890372716130286068203503191); + } +} //namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_int_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_int_sized.hpp new file mode 100644 index 0000000..8e9c511 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_int_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_scalar_int_sized +/// @file glm/ext/scalar_int_sized.hpp +/// +/// @defgroup ext_scalar_int_sized GLM_EXT_scalar_int_sized +/// @ingroup ext +/// +/// Exposes sized signed integer scalar types. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_uint_sized + +#pragma once + +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_int_sized extension included") +#endif + +namespace glm{ +namespace detail +{ +# if GLM_HAS_EXTENDED_INTEGER_TYPE + typedef std::int8_t int8; + typedef std::int16_t int16; + typedef std::int32_t int32; +# else + typedef signed char int8; + typedef signed short int16; + typedef signed int int32; +#endif// + + template<> + struct is_int + { + enum test {value = ~0}; + }; + + template<> + struct is_int + { + enum test {value = ~0}; + }; + + template<> + struct is_int + { + enum test {value = ~0}; + }; +}//namespace detail + + + /// @addtogroup ext_scalar_int_sized + /// @{ + + /// 8 bit signed integer type. + typedef detail::int8 int8; + + /// 16 bit signed integer type. + typedef detail::int16 int16; + + /// 32 bit signed integer type. + typedef detail::int32 int32; + + /// 64 bit signed integer type. + typedef detail::int64 int64; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_integer.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_integer.hpp new file mode 100644 index 0000000..a2ca8a2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_integer.hpp @@ -0,0 +1,92 @@ +/// @ref ext_scalar_integer +/// @file glm/ext/scalar_integer.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_scalar_integer GLM_EXT_scalar_integer +/// @ingroup ext +/// +/// Include to use the features of this extension. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/_vectorize.hpp" +#include "../detail/type_float.hpp" +#include "../vector_relational.hpp" +#include "../common.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_scalar_integer + /// @{ + + /// Return true if the value is a power of two number. + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL bool isPowerOfTwo(genIUType v); + + /// Return the power of two number which value is just higher the input value, + /// round up to a power of two. + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL genIUType nextPowerOfTwo(genIUType v); + + /// Return the power of two number which value is just lower the input value, + /// round down to a power of two. + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL genIUType prevPowerOfTwo(genIUType v); + + /// Return true if the 'Value' is a multiple of 'Multiple'. + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL bool isMultiple(genIUType v, genIUType Multiple); + + /// Higher multiple number of Source. + /// + /// @tparam genIUType Integer scalar or vector types. + /// + /// @param v Source value to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL genIUType nextMultiple(genIUType v, genIUType Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam genIUType Integer scalar or vector types. + /// + /// @param v Source value to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL genIUType prevMultiple(genIUType v, genIUType Multiple); + + /// Returns the bit number of the Nth significant bit set to + /// 1 in the binary representation of value. + /// If value bitcount is less than the Nth significant bit, -1 will be returned. + /// + /// @tparam genIUType Signed or unsigned integer scalar types. + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL int findNSB(genIUType x, int significantBitCount); + + /// @} +} //namespace glm + +#include "scalar_integer.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_integer.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_integer.inl new file mode 100644 index 0000000..d416197 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_integer.inl @@ -0,0 +1,243 @@ +#include "../integer.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_ceilShift + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T) + { + return v; + } + }; + + template + struct compute_ceilShift + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T Shift) + { + return v | (v >> Shift); + } + }; + + template + struct compute_ceilPowerOfTwo + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + GLM_STATIC_ASSERT(!std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + vec const Sign(sign(x)); + + vec v(abs(x)); + + v = v - static_cast(1); + v = v | (v >> static_cast(1)); + v = v | (v >> static_cast(2)); + v = v | (v >> static_cast(4)); + v = compute_ceilShift= 2>::call(v, 8); + v = compute_ceilShift= 4>::call(v, 16); + v = compute_ceilShift= 8>::call(v, 32); + return (v + static_cast(1)) * Sign; + } + }; + + template + struct compute_ceilPowerOfTwo + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + GLM_STATIC_ASSERT(!std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + vec v(x); + + v = v - static_cast(1); + v = v | (v >> static_cast(1)); + v = v | (v >> static_cast(2)); + v = v | (v >> static_cast(4)); + v = compute_ceilShift= 2>::call(v, 8); + v = compute_ceilShift= 4>::call(v, 16); + v = compute_ceilShift= 8>::call(v, 32); + return v + static_cast(1); + } + }; + + template + struct compute_ceilMultiple{}; + + template<> + struct compute_ceilMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source > genType(0)) + return Source + (Multiple - std::fmod(Source, Multiple)); + else + return Source + std::fmod(-Source, Multiple); + } + }; + + template<> + struct compute_ceilMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + genType Tmp = Source - genType(1); + return Tmp + (Multiple - (Tmp % Multiple)); + } + }; + + template<> + struct compute_ceilMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + assert(Multiple > genType(0)); + if(Source > genType(0)) + { + genType Tmp = Source - genType(1); + return Tmp + (Multiple - (Tmp % Multiple)); + } + else + return Source + (-Source % Multiple); + } + }; + + template + struct compute_floorMultiple{}; + + template<> + struct compute_floorMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source >= genType(0)) + return Source - std::fmod(Source, Multiple); + else + return Source - std::fmod(Source, Multiple) - Multiple; + } + }; + + template<> + struct compute_floorMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source >= genType(0)) + return Source - Source % Multiple; + else + { + genType Tmp = Source + genType(1); + return Tmp - Tmp % Multiple - Multiple; + } + } + }; + + template<> + struct compute_floorMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source >= genType(0)) + return Source - Source % Multiple; + else + { + genType Tmp = Source + genType(1); + return Tmp - Tmp % Multiple - Multiple; + } + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER bool isPowerOfTwo(genIUType Value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'isPowerOfTwo' only accept integer inputs"); + + genIUType const Result = glm::abs(Value); + return !(Result & (Result - 1)); + } + + template + GLM_FUNC_QUALIFIER genIUType nextPowerOfTwo(genIUType value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'nextPowerOfTwo' only accept integer inputs"); + + return detail::compute_ceilPowerOfTwo<1, genIUType, defaultp, std::numeric_limits::is_signed>::call(vec<1, genIUType, defaultp>(value)).x; + } + + template + GLM_FUNC_QUALIFIER genIUType prevPowerOfTwo(genIUType value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'prevPowerOfTwo' only accept integer inputs"); + + return isPowerOfTwo(value) ? value : static_cast(static_cast(1) << static_cast(findMSB(value))); + } + + template + GLM_FUNC_QUALIFIER bool isMultiple(genIUType Value, genIUType Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'isMultiple' only accept integer inputs"); + + return isMultiple(vec<1, genIUType>(Value), vec<1, genIUType>(Multiple)).x; + } + + template + GLM_FUNC_QUALIFIER genIUType nextMultiple(genIUType Source, genIUType Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'nextMultiple' only accept integer inputs"); + + return detail::compute_ceilMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER genIUType prevMultiple(genIUType Source, genIUType Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'prevMultiple' only accept integer inputs"); + + return detail::compute_floorMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER int findNSB(genIUType x, int significantBitCount) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findNSB' only accept integer inputs"); + + if(bitCount(x) < significantBitCount) + return -1; + + genIUType const One = static_cast(1); + int bitPos = 0; + + genIUType key = x; + int nBitCount = significantBitCount; + int Step = sizeof(x) * 8 / 2; + while (key > One) + { + genIUType Mask = static_cast((One << Step) - One); + genIUType currentKey = key & Mask; + int currentBitCount = bitCount(currentKey); + if (nBitCount > currentBitCount) + { + nBitCount -= currentBitCount; + bitPos += Step; + key >>= static_cast(Step); + } + else + { + key = key & Mask; + } + + Step >>= 1; + } + + return static_cast(bitPos); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_packing.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_packing.hpp new file mode 100644 index 0000000..18b85b7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_packing.hpp @@ -0,0 +1,32 @@ +/// @ref ext_scalar_packing +/// @file glm/ext/scalar_packing.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_scalar_packing GLM_EXT_scalar_packing +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// This extension provides a set of function to convert scalar values to packed +/// formats. + +#pragma once + +// Dependency: +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_packing extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_scalar_packing + /// @{ + + + /// @} +}// namespace glm + +#include "scalar_packing.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_packing.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_packing.inl new file mode 100644 index 0000000..e69de29 diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_reciprocal.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_reciprocal.hpp new file mode 100644 index 0000000..1c7b81d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_reciprocal.hpp @@ -0,0 +1,135 @@ +/// @ref ext_scalar_reciprocal +/// @file glm/ext/scalar_reciprocal.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_scalar_reciprocal GLM_EXT_scalar_reciprocal +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Define secant, cosecant and cotangent functions. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_reciprocal extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_scalar_reciprocal + /// @{ + + /// Secant function. + /// hypotenuse / adjacent or 1 / cos(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType sec(genType angle); + + /// Cosecant function. + /// hypotenuse / opposite or 1 / sin(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType csc(genType angle); + + /// Cotangent function. + /// adjacent / opposite or 1 / tan(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType cot(genType angle); + + /// Inverse secant function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType asec(genType x); + + /// Inverse cosecant function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType acsc(genType x); + + /// Inverse cotangent function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType acot(genType x); + + /// Secant hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType sech(genType angle); + + /// Cosecant hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType csch(genType angle); + + /// Cotangent hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType coth(genType angle); + + /// Inverse secant hyperbolic function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType asech(genType x); + + /// Inverse cosecant hyperbolic function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType acsch(genType x); + + /// Inverse cotangent hyperbolic function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType acoth(genType x); + + /// @} +}//namespace glm + +#include "scalar_reciprocal.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_reciprocal.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_reciprocal.inl new file mode 100644 index 0000000..0cd5f87 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_reciprocal.inl @@ -0,0 +1,107 @@ +/// @ref ext_scalar_reciprocal + +#include "../trigonometric.hpp" +#include + +namespace glm +{ + // sec + template + GLM_FUNC_QUALIFIER genType sec(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'sec' only accept floating-point values"); + return genType(1) / glm::cos(angle); + } + + // csc + template + GLM_FUNC_QUALIFIER genType csc(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'csc' only accept floating-point values"); + return genType(1) / glm::sin(angle); + } + + // cot + template + GLM_FUNC_QUALIFIER genType cot(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'cot' only accept floating-point values"); + + genType const pi_over_2 = genType(3.1415926535897932384626433832795 / 2.0); + return glm::tan(pi_over_2 - angle); + } + + // asec + template + GLM_FUNC_QUALIFIER genType asec(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'asec' only accept floating-point values"); + return acos(genType(1) / x); + } + + // acsc + template + GLM_FUNC_QUALIFIER genType acsc(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acsc' only accept floating-point values"); + return asin(genType(1) / x); + } + + // acot + template + GLM_FUNC_QUALIFIER genType acot(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acot' only accept floating-point values"); + + genType const pi_over_2 = genType(3.1415926535897932384626433832795 / 2.0); + return pi_over_2 - atan(x); + } + + // sech + template + GLM_FUNC_QUALIFIER genType sech(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'sech' only accept floating-point values"); + return genType(1) / glm::cosh(angle); + } + + // csch + template + GLM_FUNC_QUALIFIER genType csch(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'csch' only accept floating-point values"); + return genType(1) / glm::sinh(angle); + } + + // coth + template + GLM_FUNC_QUALIFIER genType coth(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'coth' only accept floating-point values"); + return glm::cosh(angle) / glm::sinh(angle); + } + + // asech + template + GLM_FUNC_QUALIFIER genType asech(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'asech' only accept floating-point values"); + return acosh(genType(1) / x); + } + + // acsch + template + GLM_FUNC_QUALIFIER genType acsch(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acsch' only accept floating-point values"); + return asinh(genType(1) / x); + } + + // acoth + template + GLM_FUNC_QUALIFIER genType acoth(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acoth' only accept floating-point values"); + return atanh(genType(1) / x); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_relational.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_relational.hpp new file mode 100644 index 0000000..e84df17 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_relational.hpp @@ -0,0 +1,68 @@ +/// @ref ext_scalar_relational +/// @file glm/ext/scalar_relational.hpp +/// +/// @defgroup ext_scalar_relational GLM_EXT_scalar_relational +/// @ingroup ext +/// +/// Exposes comparison functions for scalar types that take a user defined epsilon values. +/// +/// Include to use the features of this extension. +/// +/// @see core_vector_relational +/// @see ext_vector_relational +/// @see ext_matrix_relational + +#pragma once + +// Dependencies +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_relational extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_scalar_relational + /// @{ + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @tparam genType Floating-point or integer scalar types + template + GLM_FUNC_DECL GLM_CONSTEXPR bool equal(genType const& x, genType const& y, genType const& epsilon); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// True if this expression is not satisfied. + /// + /// @tparam genType Floating-point or integer scalar types + template + GLM_FUNC_DECL GLM_CONSTEXPR bool notEqual(genType const& x, genType const& y, genType const& epsilon); + + /// Returns the component-wise comparison between two scalars in term of ULPs. + /// True if this expression is satisfied. + /// + /// @param x First operand. + /// @param y Second operand. + /// @param ULPs Maximum difference in ULPs between the two operators to consider them equal. + /// + /// @tparam genType Floating-point or integer scalar types + template + GLM_FUNC_DECL GLM_CONSTEXPR bool equal(genType const& x, genType const& y, int ULPs); + + /// Returns the component-wise comparison between two scalars in term of ULPs. + /// True if this expression is not satisfied. + /// + /// @param x First operand. + /// @param y Second operand. + /// @param ULPs Maximum difference in ULPs between the two operators to consider them not equal. + /// + /// @tparam genType Floating-point or integer scalar types + template + GLM_FUNC_DECL GLM_CONSTEXPR bool notEqual(genType const& x, genType const& y, int ULPs); + + /// @} +}//namespace glm + +#include "scalar_relational.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_relational.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_relational.inl new file mode 100644 index 0000000..c85583e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_relational.inl @@ -0,0 +1,40 @@ +#include "../common.hpp" +#include "../ext/scalar_int_sized.hpp" +#include "../ext/scalar_uint_sized.hpp" +#include "../detail/type_float.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool equal(genType const& x, genType const& y, genType const& epsilon) + { + return abs(x - y) <= epsilon; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool notEqual(genType const& x, genType const& y, genType const& epsilon) + { + return abs(x - y) > epsilon; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool equal(genType const& x, genType const& y, int MaxULPs) + { + detail::float_t const a(x); + detail::float_t const b(y); + + // Different signs means they do not match. + if(a.negative() != b.negative()) + return false; + + // Find the difference in ULPs. + typename detail::float_t::int_type const DiffULPs = abs(a.i - b.i); + return DiffULPs <= MaxULPs; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool notEqual(genType const& x, genType const& y, int ULPs) + { + return !equal(x, y, ULPs); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_uint_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_uint_sized.hpp new file mode 100644 index 0000000..fd5267f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_uint_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_scalar_uint_sized +/// @file glm/ext/scalar_uint_sized.hpp +/// +/// @defgroup ext_scalar_uint_sized GLM_EXT_scalar_uint_sized +/// @ingroup ext +/// +/// Exposes sized unsigned integer scalar types. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_int_sized + +#pragma once + +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_uint_sized extension included") +#endif + +namespace glm{ +namespace detail +{ +# if GLM_HAS_EXTENDED_INTEGER_TYPE + typedef std::uint8_t uint8; + typedef std::uint16_t uint16; + typedef std::uint32_t uint32; +# else + typedef unsigned char uint8; + typedef unsigned short uint16; + typedef unsigned int uint32; +#endif + + template<> + struct is_int + { + enum test {value = ~0}; + }; + + template<> + struct is_int + { + enum test {value = ~0}; + }; + + template<> + struct is_int + { + enum test {value = ~0}; + }; +}//namespace detail + + + /// @addtogroup ext_scalar_uint_sized + /// @{ + + /// 8 bit unsigned integer type. + typedef detail::uint8 uint8; + + /// 16 bit unsigned integer type. + typedef detail::uint16 uint16; + + /// 32 bit unsigned integer type. + typedef detail::uint32 uint32; + + /// 64 bit unsigned integer type. + typedef detail::uint64 uint64; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_ulp.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_ulp.hpp new file mode 100644 index 0000000..6344d95 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_ulp.hpp @@ -0,0 +1,77 @@ +/// @ref ext_scalar_ulp +/// @file glm/ext/scalar_ulp.hpp +/// +/// @defgroup ext_scalar_ulp GLM_EXT_scalar_ulp +/// @ingroup ext +/// +/// Allow the measurement of the accuracy of a function against a reference +/// implementation. This extension works on floating-point data and provide results +/// in ULP. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_ulp +/// @see ext_scalar_relational + +#pragma once + +// Dependencies +#include "../ext/scalar_int_sized.hpp" +#include "../common.hpp" +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_ulp extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_scalar_ulp + /// @{ + + /// Return the next ULP value(s) after the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL genType nextFloat(genType x); + + /// Return the previous ULP value(s) before the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL genType prevFloat(genType x); + + /// Return the value(s) ULP distance after the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL genType nextFloat(genType x, int ULPs); + + /// Return the value(s) ULP distance before the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL genType prevFloat(genType x, int ULPs); + + /// Return the distance in the number of ULP between 2 single-precision floating-point scalars. + /// + /// @see ext_scalar_ulp + GLM_FUNC_DECL int floatDistance(float x, float y); + + /// Return the distance in the number of ULP between 2 double-precision floating-point scalars. + /// + /// @see ext_scalar_ulp + GLM_FUNC_DECL int64 floatDistance(double x, double y); + + /// @} +}//namespace glm + +#include "scalar_ulp.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_ulp.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_ulp.inl new file mode 100644 index 0000000..716528d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_ulp.inl @@ -0,0 +1,291 @@ +/// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +/// +/// Developed at SunPro, a Sun Microsystems, Inc. business. +/// Permission to use, copy, modify, and distribute this +/// software is freely granted, provided that this notice +/// is preserved. + +#include "../detail/type_float.hpp" +#include "../ext/scalar_constants.hpp" +#include +#include + +#if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable : 4127) +# pragma warning(disable : 4365) // '=': signed/unsigned mismatch +#elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wsign-conversion" +# pragma clang diagnostic ignored "-Wpadded" +#endif + +typedef union +{ + float value; + /* FIXME: Assumes 32 bit int. */ + unsigned int word; +} ieee_float_shape_type; + +typedef union +{ + double value; + struct + { + int lsw; + int msw; + } parts; +} ieee_double_shape_type; + +#define GLM_EXTRACT_WORDS(ix0,ix1,d) \ + do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ + } while (0) + +#define GLM_GET_FLOAT_WORD(i,d) \ + do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = static_cast(gf_u.word); \ + } while (0) + +#define GLM_SET_FLOAT_WORD(d,i) \ + do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = static_cast(i); \ + (d) = sf_u.value; \ + } while (0) + +#define GLM_INSERT_WORDS(d,ix0,ix1) \ + do { \ + ieee_double_shape_type iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ + } while (0) + +namespace glm{ +namespace detail +{ + GLM_FUNC_QUALIFIER float nextafterf(float x, float y) + { + volatile float t; + int hx, hy, ix, iy; + + GLM_GET_FLOAT_WORD(hx, x); + GLM_GET_FLOAT_WORD(hy, y); + ix = hx & 0x7fffffff; // |x| + iy = hy & 0x7fffffff; // |y| + + if((ix > 0x7f800000) || // x is nan + (iy > 0x7f800000)) // y is nan + return x + y; + if(abs(y - x) <= epsilon()) + return y; // x=y, return y + if(ix == 0) + { // x == 0 + GLM_SET_FLOAT_WORD(x, (hy & 0x80000000) | 1);// return +-minsubnormal + t = x * x; + if(abs(t - x) <= epsilon()) + return t; + else + return x; // raise underflow flag + } + if(hx >= 0) + { // x > 0 + if(hx > hy) // x > y, x -= ulp + hx -= 1; + else // x < y, x += ulp + hx += 1; + } + else + { // x < 0 + if(hy >= 0 || hx > hy) // x < y, x -= ulp + hx -= 1; + else // x > y, x += ulp + hx += 1; + } + hy = hx & 0x7f800000; + if(hy >= 0x7f800000) + return x + x; // overflow + if(hy < 0x00800000) // underflow + { + t = x * x; + if(abs(t - x) > epsilon()) + { // raise underflow flag + GLM_SET_FLOAT_WORD(y, hx); + return y; + } + } + GLM_SET_FLOAT_WORD(x, hx); + return x; + } + + GLM_FUNC_QUALIFIER double nextafter(double x, double y) + { + volatile double t; + int hx, hy, ix, iy; + unsigned int lx, ly; + + GLM_EXTRACT_WORDS(hx, lx, x); + GLM_EXTRACT_WORDS(hy, ly, y); + ix = hx & 0x7fffffff; // |x| + iy = hy & 0x7fffffff; // |y| + + if(((ix >= 0x7ff00000) && ((ix - 0x7ff00000) | lx) != 0) || // x is nan + ((iy >= 0x7ff00000) && ((iy - 0x7ff00000) | ly) != 0)) // y is nan + return x + y; + if(abs(y - x) <= epsilon()) + return y; // x=y, return y + if((ix | lx) == 0) + { // x == 0 + GLM_INSERT_WORDS(x, hy & 0x80000000, 1); // return +-minsubnormal + t = x * x; + if(abs(t - x) <= epsilon()) + return t; + else + return x; // raise underflow flag + } + if(hx >= 0) { // x > 0 + if(hx > hy || ((hx == hy) && (lx > ly))) { // x > y, x -= ulp + if(lx == 0) hx -= 1; + lx -= 1; + } + else { // x < y, x += ulp + lx += 1; + if(lx == 0) hx += 1; + } + } + else { // x < 0 + if(hy >= 0 || hx > hy || ((hx == hy) && (lx > ly))){// x < y, x -= ulp + if(lx == 0) hx -= 1; + lx -= 1; + } + else { // x > y, x += ulp + lx += 1; + if(lx == 0) hx += 1; + } + } + hy = hx & 0x7ff00000; + if(hy >= 0x7ff00000) + return x + x; // overflow + if(hy < 0x00100000) + { // underflow + t = x * x; + if(abs(t - x) > epsilon()) + { // raise underflow flag + GLM_INSERT_WORDS(y, hx, lx); + return y; + } + } + GLM_INSERT_WORDS(x, hx, lx); + return x; + } +}//namespace detail +}//namespace glm + +#if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +#elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +#endif + +namespace glm +{ + template<> + GLM_FUNC_QUALIFIER float nextFloat(float x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::max()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafterf(x, FLT_MAX); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafterf(x, FLT_MAX); +# else + return nextafterf(x, FLT_MAX); +# endif + } + + template<> + GLM_FUNC_QUALIFIER double nextFloat(double x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::max()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafter(x, std::numeric_limits::max()); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafter(x, DBL_MAX); +# else + return nextafter(x, DBL_MAX); +# endif + } + + template + GLM_FUNC_QUALIFIER T nextFloat(T x, int ULPs) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'next_float' only accept floating-point input"); + assert(ULPs >= 0); + + T temp = x; + for(int i = 0; i < ULPs; ++i) + temp = nextFloat(temp); + return temp; + } + + GLM_FUNC_QUALIFIER float prevFloat(float x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::min()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafterf(x, FLT_MIN); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafterf(x, FLT_MIN); +# else + return nextafterf(x, FLT_MIN); +# endif + } + + GLM_FUNC_QUALIFIER double prevFloat(double x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::min()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return _nextafter(x, DBL_MIN); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafter(x, DBL_MIN); +# else + return nextafter(x, DBL_MIN); +# endif + } + + template + GLM_FUNC_QUALIFIER T prevFloat(T x, int ULPs) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'prev_float' only accept floating-point input"); + assert(ULPs >= 0); + + T temp = x; + for(int i = 0; i < ULPs; ++i) + temp = prevFloat(temp); + return temp; + } + + GLM_FUNC_QUALIFIER int floatDistance(float x, float y) + { + detail::float_t const a(x); + detail::float_t const b(y); + + return abs(a.i - b.i); + } + + GLM_FUNC_QUALIFIER int64 floatDistance(double x, double y) + { + detail::float_t const a(x); + detail::float_t const b(y); + + return abs(a.i - b.i); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool1.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool1.hpp new file mode 100644 index 0000000..002c320 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool1.hpp @@ -0,0 +1,30 @@ +/// @ref ext_vector_bool1 +/// @file glm/ext/vector_bool1.hpp +/// +/// @defgroup ext_vector_bool1 GLM_EXT_vector_bool1 +/// @ingroup ext +/// +/// Exposes bvec1 vector type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_bool1_precision extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_bool1 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_bool1 + /// @{ + + /// 1 components vector of boolean. + typedef vec<1, bool, defaultp> bvec1; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool1_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool1_precision.hpp new file mode 100644 index 0000000..e62d3cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool1_precision.hpp @@ -0,0 +1,34 @@ +/// @ref ext_vector_bool1_precision +/// @file glm/ext/vector_bool1_precision.hpp +/// +/// @defgroup ext_vector_bool1_precision GLM_EXT_vector_bool1_precision +/// @ingroup ext +/// +/// Exposes highp_bvec1, mediump_bvec1 and lowp_bvec1 types. +/// +/// Include to use the features of this extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_bool1_precision extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_bool1_precision + /// @{ + + /// 1 component vector of bool values. + typedef vec<1, bool, highp> highp_bvec1; + + /// 1 component vector of bool values. + typedef vec<1, bool, mediump> mediump_bvec1; + + /// 1 component vector of bool values. + typedef vec<1, bool, lowp> lowp_bvec1; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool2.hpp new file mode 100644 index 0000000..52288b7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_bool2.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 2 components vector of boolean. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<2, bool, defaultp> bvec2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool2_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool2_precision.hpp new file mode 100644 index 0000000..4370933 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_bool2_precision.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 2 components vector of high qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, bool, highp> highp_bvec2; + + /// 2 components vector of medium qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, bool, mediump> mediump_bvec2; + + /// 2 components vector of low qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, bool, lowp> lowp_bvec2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool3.hpp new file mode 100644 index 0000000..90a0b7e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_bool3.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 3 components vector of boolean. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<3, bool, defaultp> bvec3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool3_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool3_precision.hpp new file mode 100644 index 0000000..89cd2d3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool3_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_bool3_precision.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 3 components vector of high qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, bool, highp> highp_bvec3; + + /// 3 components vector of medium qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, bool, mediump> mediump_bvec3; + + /// 3 components vector of low qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, bool, lowp> lowp_bvec3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool4.hpp new file mode 100644 index 0000000..18aa71b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_bool4.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 4 components vector of boolean. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<4, bool, defaultp> bvec4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool4_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool4_precision.hpp new file mode 100644 index 0000000..79786e5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_bool4_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_bool4_precision.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 4 components vector of high qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, bool, highp> highp_bvec4; + + /// 4 components vector of medium qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, bool, mediump> mediump_bvec4; + + /// 4 components vector of low qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, bool, lowp> lowp_bvec4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_common.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_common.hpp new file mode 100644 index 0000000..c0a2858 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_common.hpp @@ -0,0 +1,228 @@ +/// @ref ext_vector_common +/// @file glm/ext/vector_common.hpp +/// +/// @defgroup ext_vector_common GLM_EXT_vector_common +/// @ingroup ext +/// +/// Exposes min and max functions for 3 to 4 vector parameters. +/// +/// Include to use the features of this extension. +/// +/// @see core_common +/// @see ext_scalar_common + +#pragma once + +// Dependency: +#include "../ext/scalar_common.hpp" +#include "../common.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_common extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_common + /// @{ + + /// Return the minimum component-wise values of 3 inputs + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec min(vec const& a, vec const& b, vec const& c); + + /// Return the minimum component-wise values of 4 inputs + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec min(vec const& a, vec const& b, vec const& c, vec const& d); + + /// Return the maximum component-wise values of 3 inputs + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec max(vec const& x, vec const& y, vec const& z); + + /// Return the maximum component-wise values of 4 inputs + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec max( vec const& x, vec const& y, vec const& z, vec const& w); + + /// Returns y if y < x; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmin documentation + template + GLM_FUNC_DECL vec fmin(vec const& x, T y); + + /// Returns y if y < x; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmin documentation + template + GLM_FUNC_DECL vec fmin(vec const& x, vec const& y); + + /// Returns y if y < x; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmin documentation + template + GLM_FUNC_DECL vec fmin(vec const& a, vec const& b, vec const& c); + + /// Returns y if y < x; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmin documentation + template + GLM_FUNC_DECL vec fmin(vec const& a, vec const& b, vec const& c, vec const& d); + + /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmax documentation + template + GLM_FUNC_DECL vec fmax(vec const& a, T b); + + /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmax documentation + template + GLM_FUNC_DECL vec fmax(vec const& a, vec const& b); + + /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmax documentation + template + GLM_FUNC_DECL vec fmax(vec const& a, vec const& b, vec const& c); + + /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmax documentation + template + GLM_FUNC_DECL vec fmax(vec const& a, vec const& b, vec const& c, vec const& d); + + /// Returns min(max(x, minVal), maxVal) for each component in x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common + template + GLM_FUNC_DECL vec fclamp(vec const& x, T minVal, T maxVal); + + /// Returns min(max(x, minVal), maxVal) for each component in x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common + template + GLM_FUNC_DECL vec fclamp(vec const& x, vec const& minVal, vec const& maxVal); + + /// Simulate GL_CLAMP OpenGL wrap mode + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common extension. + template + GLM_FUNC_DECL vec clamp(vec const& Texcoord); + + /// Simulate GL_REPEAT OpenGL wrap mode + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common extension. + template + GLM_FUNC_DECL vec repeat(vec const& Texcoord); + + /// Simulate GL_MIRRORED_REPEAT OpenGL wrap mode + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common extension. + template + GLM_FUNC_DECL vec mirrorClamp(vec const& Texcoord); + + /// Simulate GL_MIRROR_REPEAT OpenGL wrap mode + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common extension. + template + GLM_FUNC_DECL vec mirrorRepeat(vec const& Texcoord); + + /// Returns a value equal to the nearest integer to x. + /// The fraction 0.5 will round in a direction chosen by the + /// implementation, presumably the direction that is fastest. + /// + /// @param x The values of the argument must be greater or equal to zero. + /// @tparam T floating point scalar types. + /// + /// @see GLSL round man page + /// @see ext_vector_common extension. + template + GLM_FUNC_DECL vec iround(vec const& x); + + /// Returns a value equal to the nearest integer to x. + /// The fraction 0.5 will round in a direction chosen by the + /// implementation, presumably the direction that is fastest. + /// + /// @param x The values of the argument must be greater or equal to zero. + /// @tparam T floating point scalar types. + /// + /// @see GLSL round man page + /// @see ext_vector_common extension. + template + GLM_FUNC_DECL vec uround(vec const& x); + + /// @} +}//namespace glm + +#include "vector_common.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_common.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_common.inl new file mode 100644 index 0000000..67817fc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_common.inl @@ -0,0 +1,147 @@ +#include "../detail/_vectorize.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec min(vec const& x, vec const& y, vec const& z) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'min' only accept floating-point or integer inputs"); + return glm::min(glm::min(x, y), z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec min(vec const& x, vec const& y, vec const& z, vec const& w) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'min' only accept floating-point or integer inputs"); + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec max(vec const& x, vec const& y, vec const& z) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'max' only accept floating-point or integer inputs"); + return glm::max(glm::max(x, y), z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec max(vec const& x, vec const& y, vec const& z, vec const& w) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'max' only accept floating-point or integer inputs"); + return glm::max(glm::max(x, y), glm::max(z, w)); + } + + template + GLM_FUNC_QUALIFIER vec fmin(vec const& a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point inputs"); + return detail::functor2::call(fmin, a, vec(b)); + } + + template + GLM_FUNC_QUALIFIER vec fmin(vec const& a, vec const& b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point inputs"); + return detail::functor2::call(fmin, a, b); + } + + template + GLM_FUNC_QUALIFIER vec fmin(vec const& a, vec const& b, vec const& c) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point inputs"); + return fmin(fmin(a, b), c); + } + + template + GLM_FUNC_QUALIFIER vec fmin(vec const& a, vec const& b, vec const& c, vec const& d) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point inputs"); + return fmin(fmin(a, b), fmin(c, d)); + } + + template + GLM_FUNC_QUALIFIER vec fmax(vec const& a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point inputs"); + return detail::functor2::call(fmax, a, vec(b)); + } + + template + GLM_FUNC_QUALIFIER vec fmax(vec const& a, vec const& b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point inputs"); + return detail::functor2::call(fmax, a, b); + } + + template + GLM_FUNC_QUALIFIER vec fmax(vec const& a, vec const& b, vec const& c) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point inputs"); + return fmax(fmax(a, b), c); + } + + template + GLM_FUNC_QUALIFIER vec fmax(vec const& a, vec const& b, vec const& c, vec const& d) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point inputs"); + return fmax(fmax(a, b), fmax(c, d)); + } + + template + GLM_FUNC_QUALIFIER vec fclamp(vec const& x, T minVal, T maxVal) + { + return fmin(fmax(x, vec(minVal)), vec(maxVal)); + } + + template + GLM_FUNC_QUALIFIER vec fclamp(vec const& x, vec const& minVal, vec const& maxVal) + { + return fmin(fmax(x, minVal), maxVal); + } + + template + GLM_FUNC_QUALIFIER vec clamp(vec const& Texcoord) + { + return glm::clamp(Texcoord, vec(0), vec(1)); + } + + template + GLM_FUNC_QUALIFIER vec repeat(vec const& Texcoord) + { + return glm::fract(Texcoord); + } + + template + GLM_FUNC_QUALIFIER vec mirrorClamp(vec const& Texcoord) + { + return glm::fract(glm::abs(Texcoord)); + } + + template + GLM_FUNC_QUALIFIER vec mirrorRepeat(vec const& Texcoord) + { + vec const Abs = glm::abs(Texcoord); + vec const Clamp = glm::mod(glm::floor(Abs), vec(2)); + vec const Floor = glm::floor(Abs); + vec const Rest = Abs - Floor; + vec const Mirror = Clamp + Rest; + return mix(Rest, vec(1) - Rest, glm::greaterThanEqual(Mirror, vec(1))); + } + + template + GLM_FUNC_QUALIFIER vec iround(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'iround' only accept floating-point inputs"); + assert(all(lessThanEqual(vec(0), x))); + + return vec(x + static_cast(0.5)); + } + + template + GLM_FUNC_QUALIFIER vec uround(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'uround' only accept floating-point inputs"); + assert(all(lessThanEqual(vec(0), x))); + + return vec(x + static_cast(0.5)); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double1.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double1.hpp new file mode 100644 index 0000000..3882667 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double1.hpp @@ -0,0 +1,31 @@ +/// @ref ext_vector_double1 +/// @file glm/ext/vector_double1.hpp +/// +/// @defgroup ext_vector_double1 GLM_EXT_vector_double1 +/// @ingroup ext +/// +/// Exposes double-precision floating point vector type with one component. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_double1_precision extension. +/// @see ext_vector_float1 extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_double1 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_double1 + /// @{ + + /// 1 components vector of double-precision floating-point numbers. + typedef vec<1, double, defaultp> dvec1; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double1_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double1_precision.hpp new file mode 100644 index 0000000..1d47195 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double1_precision.hpp @@ -0,0 +1,36 @@ +/// @ref ext_vector_double1_precision +/// @file glm/ext/vector_double1_precision.hpp +/// +/// @defgroup ext_vector_double1_precision GLM_EXT_vector_double1_precision +/// @ingroup ext +/// +/// Exposes highp_dvec1, mediump_dvec1 and lowp_dvec1 types. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_double1 + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_double1_precision extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_double1_precision + /// @{ + + /// 1 component vector of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<1, double, highp> highp_dvec1; + + /// 1 component vector of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<1, double, mediump> mediump_dvec1; + + /// 1 component vector of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<1, double, lowp> lowp_dvec1; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double2.hpp new file mode 100644 index 0000000..60e3577 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_double2.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 2 components vector of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<2, double, defaultp> dvec2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double2_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double2_precision.hpp new file mode 100644 index 0000000..fa53940 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_double2_precision.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 2 components vector of high double-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, double, highp> highp_dvec2; + + /// 2 components vector of medium double-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, double, mediump> mediump_dvec2; + + /// 2 components vector of low double-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, double, lowp> lowp_dvec2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double3.hpp new file mode 100644 index 0000000..6dfe4c6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_double3.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 3 components vector of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<3, double, defaultp> dvec3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double3_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double3_precision.hpp new file mode 100644 index 0000000..a8cfa37 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double3_precision.hpp @@ -0,0 +1,34 @@ +/// @ref core +/// @file glm/ext/vector_double3_precision.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 3 components vector of high double-qualifier floating-point numbers. + /// There is no guarantee on the actual qualifier. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, double, highp> highp_dvec3; + + /// 3 components vector of medium double-qualifier floating-point numbers. + /// There is no guarantee on the actual qualifier. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, double, mediump> mediump_dvec3; + + /// 3 components vector of low double-qualifier floating-point numbers. + /// There is no guarantee on the actual qualifier. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, double, lowp> lowp_dvec3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double4.hpp new file mode 100644 index 0000000..87f225f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_double4.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 4 components vector of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<4, double, defaultp> dvec4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double4_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double4_precision.hpp new file mode 100644 index 0000000..09cafa1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_double4_precision.hpp @@ -0,0 +1,35 @@ +/// @ref core +/// @file glm/ext/vector_double4_precision.hpp + +#pragma once +#include "../detail/setup.hpp" +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 4 components vector of high double-qualifier floating-point numbers. + /// There is no guarantee on the actual qualifier. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, double, highp> highp_dvec4; + + /// 4 components vector of medium double-qualifier floating-point numbers. + /// There is no guarantee on the actual qualifier. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, double, mediump> mediump_dvec4; + + /// 4 components vector of low double-qualifier floating-point numbers. + /// There is no guarantee on the actual qualifier. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, double, lowp> lowp_dvec4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float1.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float1.hpp new file mode 100644 index 0000000..28acc2c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float1.hpp @@ -0,0 +1,31 @@ +/// @ref ext_vector_float1 +/// @file glm/ext/vector_float1.hpp +/// +/// @defgroup ext_vector_float1 GLM_EXT_vector_float1 +/// @ingroup ext +/// +/// Exposes single-precision floating point vector type with one component. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_float1_precision extension. +/// @see ext_vector_double1 extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_float1 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_float1 + /// @{ + + /// 1 components vector of single-precision floating-point numbers. + typedef vec<1, float, defaultp> vec1; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float1_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float1_precision.hpp new file mode 100644 index 0000000..6e8dad8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float1_precision.hpp @@ -0,0 +1,36 @@ +/// @ref ext_vector_float1_precision +/// @file glm/ext/vector_float1_precision.hpp +/// +/// @defgroup ext_vector_float1_precision GLM_EXT_vector_float1_precision +/// @ingroup ext +/// +/// Exposes highp_vec1, mediump_vec1 and lowp_vec1 types. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_float1 extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_float1_precision extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_float1_precision + /// @{ + + /// 1 component vector of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<1, float, highp> highp_vec1; + + /// 1 component vector of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<1, float, mediump> mediump_vec1; + + /// 1 component vector of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<1, float, lowp> lowp_vec1; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float2.hpp new file mode 100644 index 0000000..d31545d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_float2.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 2 components vector of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<2, float, defaultp> vec2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float2_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float2_precision.hpp new file mode 100644 index 0000000..23c0820 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_float2_precision.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 2 components vector of high single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, float, highp> highp_vec2; + + /// 2 components vector of medium single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, float, mediump> mediump_vec2; + + /// 2 components vector of low single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, float, lowp> lowp_vec2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float3.hpp new file mode 100644 index 0000000..cd79a62 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_float3.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 3 components vector of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<3, float, defaultp> vec3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float3_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float3_precision.hpp new file mode 100644 index 0000000..be640b5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float3_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_float3_precision.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 3 components vector of high single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, float, highp> highp_vec3; + + /// 3 components vector of medium single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, float, mediump> mediump_vec3; + + /// 3 components vector of low single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, float, lowp> lowp_vec3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float4.hpp new file mode 100644 index 0000000..d84adcc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_float4.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 4 components vector of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<4, float, defaultp> vec4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float4_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float4_precision.hpp new file mode 100644 index 0000000..aede838 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_float4_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_float4_precision.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 4 components vector of high single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, float, highp> highp_vec4; + + /// 4 components vector of medium single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, float, mediump> mediump_vec4; + + /// 4 components vector of low single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, float, lowp> lowp_vec4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int1.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int1.hpp new file mode 100644 index 0000000..dc86038 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int1.hpp @@ -0,0 +1,32 @@ +/// @ref ext_vector_int1 +/// @file glm/ext/vector_int1.hpp +/// +/// @defgroup ext_vector_int1 GLM_EXT_vector_int1 +/// @ingroup ext +/// +/// Exposes ivec1 vector type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_uint1 extension. +/// @see ext_vector_int1_precision extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_int1 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_int1 + /// @{ + + /// 1 component vector of signed integer numbers. + typedef vec<1, int, defaultp> ivec1; + + /// @} +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int1_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int1_sized.hpp new file mode 100644 index 0000000..de0d4cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int1_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_int1_sized +/// @file glm/ext/vector_int1_sized.hpp +/// +/// @defgroup ext_vector_int1_sized GLM_EXT_vector_int1_sized +/// @ingroup ext +/// +/// Exposes sized signed integer vector types. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_int_sized +/// @see ext_vector_uint1_sized + +#pragma once + +#include "../ext/vector_int1.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_int1_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_int1_sized + /// @{ + + /// 8 bit signed integer vector of 1 component type. + /// + /// @see ext_vector_int1_sized + typedef vec<1, int8, defaultp> i8vec1; + + /// 16 bit signed integer vector of 1 component type. + /// + /// @see ext_vector_int1_sized + typedef vec<1, int16, defaultp> i16vec1; + + /// 32 bit signed integer vector of 1 component type. + /// + /// @see ext_vector_int1_sized + typedef vec<1, int32, defaultp> i32vec1; + + /// 64 bit signed integer vector of 1 component type. + /// + /// @see ext_vector_int1_sized + typedef vec<1, int64, defaultp> i64vec1; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int2.hpp new file mode 100644 index 0000000..aef803e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_int2.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 2 components vector of signed integer numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<2, int, defaultp> ivec2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int2_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int2_sized.hpp new file mode 100644 index 0000000..1fd57ee --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int2_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_int2_sized +/// @file glm/ext/vector_int2_sized.hpp +/// +/// @defgroup ext_vector_int2_sized GLM_EXT_vector_int2_sized +/// @ingroup ext +/// +/// Exposes sized signed integer vector of 2 components type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_int_sized +/// @see ext_vector_uint2_sized + +#pragma once + +#include "../ext/vector_int2.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_int2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_int2_sized + /// @{ + + /// 8 bit signed integer vector of 2 components type. + /// + /// @see ext_vector_int2_sized + typedef vec<2, int8, defaultp> i8vec2; + + /// 16 bit signed integer vector of 2 components type. + /// + /// @see ext_vector_int2_sized + typedef vec<2, int16, defaultp> i16vec2; + + /// 32 bit signed integer vector of 2 components type. + /// + /// @see ext_vector_int2_sized + typedef vec<2, int32, defaultp> i32vec2; + + /// 64 bit signed integer vector of 2 components type. + /// + /// @see ext_vector_int2_sized + typedef vec<2, int64, defaultp> i64vec2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int3.hpp new file mode 100644 index 0000000..4767e61 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_int3.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 3 components vector of signed integer numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<3, int, defaultp> ivec3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int3_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int3_sized.hpp new file mode 100644 index 0000000..085a3fe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int3_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_int3_sized +/// @file glm/ext/vector_int3_sized.hpp +/// +/// @defgroup ext_vector_int3_sized GLM_EXT_vector_int3_sized +/// @ingroup ext +/// +/// Exposes sized signed integer vector of 3 components type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_int_sized +/// @see ext_vector_uint3_sized + +#pragma once + +#include "../ext/vector_int3.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_int3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_int3_sized + /// @{ + + /// 8 bit signed integer vector of 3 components type. + /// + /// @see ext_vector_int3_sized + typedef vec<3, int8, defaultp> i8vec3; + + /// 16 bit signed integer vector of 3 components type. + /// + /// @see ext_vector_int3_sized + typedef vec<3, int16, defaultp> i16vec3; + + /// 32 bit signed integer vector of 3 components type. + /// + /// @see ext_vector_int3_sized + typedef vec<3, int32, defaultp> i32vec3; + + /// 64 bit signed integer vector of 3 components type. + /// + /// @see ext_vector_int3_sized + typedef vec<3, int64, defaultp> i64vec3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int4.hpp new file mode 100644 index 0000000..bb23adf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_int4.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 4 components vector of signed integer numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<4, int, defaultp> ivec4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int4_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int4_sized.hpp new file mode 100644 index 0000000..c63d465 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_int4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_int4_sized +/// @file glm/ext/vector_int4_sized.hpp +/// +/// @defgroup ext_vector_int4_sized GLM_EXT_vector_int4_sized +/// @ingroup ext +/// +/// Exposes sized signed integer vector of 4 components type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_int_sized +/// @see ext_vector_uint4_sized + +#pragma once + +#include "../ext/vector_int4.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_int4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_int4_sized + /// @{ + + /// 8 bit signed integer vector of 4 components type. + /// + /// @see ext_vector_int4_sized + typedef vec<4, int8, defaultp> i8vec4; + + /// 16 bit signed integer vector of 4 components type. + /// + /// @see ext_vector_int4_sized + typedef vec<4, int16, defaultp> i16vec4; + + /// 32 bit signed integer vector of 4 components type. + /// + /// @see ext_vector_int4_sized + typedef vec<4, int32, defaultp> i32vec4; + + /// 64 bit signed integer vector of 4 components type. + /// + /// @see ext_vector_int4_sized + typedef vec<4, int64, defaultp> i64vec4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_integer.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_integer.hpp new file mode 100644 index 0000000..1304dd8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_integer.hpp @@ -0,0 +1,149 @@ +/// @ref ext_vector_integer +/// @file glm/ext/vector_integer.hpp +/// +/// @see core (dependence) +/// @see ext_vector_integer (dependence) +/// +/// @defgroup ext_vector_integer GLM_EXT_vector_integer +/// @ingroup ext +/// +/// Include to use the features of this extension. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/_vectorize.hpp" +#include "../vector_relational.hpp" +#include "../common.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_integer + /// @{ + + /// Return true if the value is a power of two number. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec isPowerOfTwo(vec const& v); + + /// Return the power of two number which value is just higher the input value, + /// round up to a power of two. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec nextPowerOfTwo(vec const& v); + + /// Return the power of two number which value is just lower the input value, + /// round down to a power of two. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec prevPowerOfTwo(vec const& v); + + /// Return true if the 'Value' is a multiple of 'Multiple'. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec isMultiple(vec const& v, T Multiple); + + /// Return true if the 'Value' is a multiple of 'Multiple'. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec isMultiple(vec const& v, vec const& Multiple); + + /// Higher multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec nextMultiple(vec const& v, T Multiple); + + /// Higher multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec nextMultiple(vec const& v, vec const& Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec prevMultiple(vec const& v, T Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec prevMultiple(vec const& v, vec const& Multiple); + + /// Returns the bit number of the Nth significant bit set to + /// 1 in the binary representation of value. + /// If value bitcount is less than the Nth significant bit, -1 will be returned. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar types. + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec findNSB(vec const& Source, vec SignificantBitCount); + + /// @} +} //namespace glm + +#include "vector_integer.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_integer.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_integer.inl new file mode 100644 index 0000000..cefb132 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_integer.inl @@ -0,0 +1,85 @@ +#include "scalar_integer.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec isPowerOfTwo(vec const& Value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'isPowerOfTwo' only accept integer inputs"); + + vec const Result(abs(Value)); + return equal(Result & (Result - vec(1)), vec(0)); + } + + template + GLM_FUNC_QUALIFIER vec nextPowerOfTwo(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'nextPowerOfTwo' only accept integer inputs"); + + return detail::compute_ceilPowerOfTwo::is_signed>::call(v); + } + + template + GLM_FUNC_QUALIFIER vec prevPowerOfTwo(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'prevPowerOfTwo' only accept integer inputs"); + + return detail::functor1::call(prevPowerOfTwo, v); + } + + template + GLM_FUNC_QUALIFIER vec isMultiple(vec const& Value, T Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'isMultiple' only accept integer inputs"); + + return equal(Value % Multiple, vec(0)); + } + + template + GLM_FUNC_QUALIFIER vec isMultiple(vec const& Value, vec const& Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'isMultiple' only accept integer inputs"); + + return equal(Value % Multiple, vec(0)); + } + + template + GLM_FUNC_QUALIFIER vec nextMultiple(vec const& Source, T Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'nextMultiple' only accept integer inputs"); + + return detail::functor2::call(nextMultiple, Source, vec(Multiple)); + } + + template + GLM_FUNC_QUALIFIER vec nextMultiple(vec const& Source, vec const& Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'nextMultiple' only accept integer inputs"); + + return detail::functor2::call(nextMultiple, Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec prevMultiple(vec const& Source, T Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'prevMultiple' only accept integer inputs"); + + return detail::functor2::call(prevMultiple, Source, vec(Multiple)); + } + + template + GLM_FUNC_QUALIFIER vec prevMultiple(vec const& Source, vec const& Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'prevMultiple' only accept integer inputs"); + + return detail::functor2::call(prevMultiple, Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec findNSB(vec const& Source, vec SignificantBitCount) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findNSB' only accept integer inputs"); + + return detail::functor2_vec_int::call(findNSB, Source, SignificantBitCount); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_packing.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_packing.hpp new file mode 100644 index 0000000..76e5d0c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_packing.hpp @@ -0,0 +1,32 @@ +/// @ref ext_vector_packing +/// @file glm/ext/vector_packing.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_vector_packing GLM_EXT_vector_packing +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// This extension provides a set of function to convert vectors to packed +/// formats. + +#pragma once + +// Dependency: +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_packing extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_packing + /// @{ + + + /// @} +}// namespace glm + +#include "vector_packing.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_packing.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_packing.inl new file mode 100644 index 0000000..e69de29 diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_reciprocal.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_reciprocal.hpp new file mode 100644 index 0000000..84d6766 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_reciprocal.hpp @@ -0,0 +1,135 @@ +/// @ref ext_vector_reciprocal +/// @file glm/ext/vector_reciprocal.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_vector_reciprocal GLM_EXT_vector_reciprocal +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Define secant, cosecant and cotangent functions. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_reciprocal extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_reciprocal + /// @{ + + /// Secant function. + /// hypotenuse / adjacent or 1 / cos(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType sec(genType angle); + + /// Cosecant function. + /// hypotenuse / opposite or 1 / sin(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType csc(genType angle); + + /// Cotangent function. + /// adjacent / opposite or 1 / tan(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType cot(genType angle); + + /// Inverse secant function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType asec(genType x); + + /// Inverse cosecant function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType acsc(genType x); + + /// Inverse cotangent function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType acot(genType x); + + /// Secant hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType sech(genType angle); + + /// Cosecant hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType csch(genType angle); + + /// Cotangent hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType coth(genType angle); + + /// Inverse secant hyperbolic function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType asech(genType x); + + /// Inverse cosecant hyperbolic function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType acsch(genType x); + + /// Inverse cotangent hyperbolic function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType acoth(genType x); + + /// @} +}//namespace glm + +#include "vector_reciprocal.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_reciprocal.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_reciprocal.inl new file mode 100644 index 0000000..b85102a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_reciprocal.inl @@ -0,0 +1,105 @@ +/// @ref ext_vector_reciprocal + +#include "../trigonometric.hpp" +#include + +namespace glm +{ + // sec + template + GLM_FUNC_QUALIFIER vec sec(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'sec' only accept floating-point inputs"); + return static_cast(1) / detail::functor1::call(cos, x); + } + + // csc + template + GLM_FUNC_QUALIFIER vec csc(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'csc' only accept floating-point inputs"); + return static_cast(1) / detail::functor1::call(sin, x); + } + + // cot + template + GLM_FUNC_QUALIFIER vec cot(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'cot' only accept floating-point inputs"); + T const pi_over_2 = static_cast(3.1415926535897932384626433832795 / 2.0); + return detail::functor1::call(tan, pi_over_2 - x); + } + + // asec + template + GLM_FUNC_QUALIFIER vec asec(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'asec' only accept floating-point inputs"); + return detail::functor1::call(acos, static_cast(1) / x); + } + + // acsc + template + GLM_FUNC_QUALIFIER vec acsc(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acsc' only accept floating-point inputs"); + return detail::functor1::call(asin, static_cast(1) / x); + } + + // acot + template + GLM_FUNC_QUALIFIER vec acot(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acot' only accept floating-point inputs"); + T const pi_over_2 = static_cast(3.1415926535897932384626433832795 / 2.0); + return pi_over_2 - detail::functor1::call(atan, x); + } + + // sech + template + GLM_FUNC_QUALIFIER vec sech(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'sech' only accept floating-point inputs"); + return static_cast(1) / detail::functor1::call(cosh, x); + } + + // csch + template + GLM_FUNC_QUALIFIER vec csch(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'csch' only accept floating-point inputs"); + return static_cast(1) / detail::functor1::call(sinh, x); + } + + // coth + template + GLM_FUNC_QUALIFIER vec coth(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'coth' only accept floating-point inputs"); + return glm::cosh(x) / glm::sinh(x); + } + + // asech + template + GLM_FUNC_QUALIFIER vec asech(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'asech' only accept floating-point inputs"); + return detail::functor1::call(acosh, static_cast(1) / x); + } + + // acsch + template + GLM_FUNC_QUALIFIER vec acsch(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acsch' only accept floating-point inputs"); + return detail::functor1::call(asinh, static_cast(1) / x); + } + + // acoth + template + GLM_FUNC_QUALIFIER vec acoth(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acoth' only accept floating-point inputs"); + return detail::functor1::call(atanh, static_cast(1) / x); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_relational.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_relational.hpp new file mode 100644 index 0000000..1c2367d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_relational.hpp @@ -0,0 +1,107 @@ +/// @ref ext_vector_relational +/// @file glm/ext/vector_relational.hpp +/// +/// @see core (dependence) +/// @see ext_scalar_integer (dependence) +/// +/// @defgroup ext_vector_relational GLM_EXT_vector_relational +/// @ingroup ext +/// +/// Exposes comparison functions for vector types that take a user defined epsilon values. +/// +/// Include to use the features of this extension. +/// +/// @see core_vector_relational +/// @see ext_scalar_relational +/// @see ext_matrix_relational + +#pragma once + +// Dependencies +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_relational extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_relational + /// @{ + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(vec const& x, vec const& y, T epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(vec const& x, vec const& y, vec const& epsilon); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// True if this expression is not satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, T epsilon); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// True if this expression is not satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, vec const& epsilon); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(vec const& x, vec const& y, int ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(vec const& x, vec const& y, vec const& ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is not satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, int ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is not satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, vec const& ULPs); + + /// @} +}//namespace glm + +#include "vector_relational.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_relational.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_relational.inl new file mode 100644 index 0000000..7a39ab5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_relational.inl @@ -0,0 +1,75 @@ +#include "../vector_relational.hpp" +#include "../common.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/type_float.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(vec const& x, vec const& y, T Epsilon) + { + return equal(x, y, vec(Epsilon)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(vec const& x, vec const& y, vec const& Epsilon) + { + return lessThanEqual(abs(x - y), Epsilon); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, T Epsilon) + { + return notEqual(x, y, vec(Epsilon)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, vec const& Epsilon) + { + return greaterThan(abs(x - y), Epsilon); + } + + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(vec const& x, vec const& y, int MaxULPs) + { + return equal(x, y, vec(MaxULPs)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(vec const& x, vec const& y, vec const& MaxULPs) + { + vec Result(false); + for(length_t i = 0; i < L; ++i) + { + detail::float_t const a(x[i]); + detail::float_t const b(y[i]); + + // Different signs means they do not match. + if(a.negative() != b.negative()) + { + // Check for equality to make sure +0==-0 + Result[i] = a.mantissa() == b.mantissa() && a.exponent() == b.exponent(); + } + else + { + // Find the difference in ULPs. + typename detail::float_t::int_type const DiffULPs = abs(a.i - b.i); + Result[i] = DiffULPs <= MaxULPs[i]; + } + } + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, int MaxULPs) + { + return notEqual(x, y, vec(MaxULPs)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, vec const& MaxULPs) + { + return not_(equal(x, y, MaxULPs)); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint1.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint1.hpp new file mode 100644 index 0000000..eb8a704 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint1.hpp @@ -0,0 +1,32 @@ +/// @ref ext_vector_uint1 +/// @file glm/ext/vector_uint1.hpp +/// +/// @defgroup ext_vector_uint1 GLM_EXT_vector_uint1 +/// @ingroup ext +/// +/// Exposes uvec1 vector type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_int1 extension. +/// @see ext_vector_uint1_precision extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_uint1 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_uint1 + /// @{ + + /// 1 component vector of unsigned integer numbers. + typedef vec<1, unsigned int, defaultp> uvec1; + + /// @} +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint1_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint1_sized.hpp new file mode 100644 index 0000000..2a938bb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint1_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_uint1_sized +/// @file glm/ext/vector_uint1_sized.hpp +/// +/// @defgroup ext_vector_uint1_sized GLM_EXT_vector_uint1_sized +/// @ingroup ext +/// +/// Exposes sized unsigned integer vector types. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_uint_sized +/// @see ext_vector_int1_sized + +#pragma once + +#include "../ext/vector_uint1.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_uint1_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_uint1_sized + /// @{ + + /// 8 bit unsigned integer vector of 1 component type. + /// + /// @see ext_vector_uint1_sized + typedef vec<1, uint8, defaultp> u8vec1; + + /// 16 bit unsigned integer vector of 1 component type. + /// + /// @see ext_vector_uint1_sized + typedef vec<1, uint16, defaultp> u16vec1; + + /// 32 bit unsigned integer vector of 1 component type. + /// + /// @see ext_vector_uint1_sized + typedef vec<1, uint32, defaultp> u32vec1; + + /// 64 bit unsigned integer vector of 1 component type. + /// + /// @see ext_vector_uint1_sized + typedef vec<1, uint64, defaultp> u64vec1; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint2.hpp new file mode 100644 index 0000000..03c00f5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_uint2.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 2 components vector of unsigned integer numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<2, unsigned int, defaultp> uvec2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint2_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint2_sized.hpp new file mode 100644 index 0000000..620fdc6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint2_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_uint2_sized +/// @file glm/ext/vector_uint2_sized.hpp +/// +/// @defgroup ext_vector_uint2_sized GLM_EXT_vector_uint2_sized +/// @ingroup ext +/// +/// Exposes sized unsigned integer vector of 2 components type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_uint_sized +/// @see ext_vector_int2_sized + +#pragma once + +#include "../ext/vector_uint2.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_uint2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_uint2_sized + /// @{ + + /// 8 bit unsigned integer vector of 2 components type. + /// + /// @see ext_vector_uint2_sized + typedef vec<2, uint8, defaultp> u8vec2; + + /// 16 bit unsigned integer vector of 2 components type. + /// + /// @see ext_vector_uint2_sized + typedef vec<2, uint16, defaultp> u16vec2; + + /// 32 bit unsigned integer vector of 2 components type. + /// + /// @see ext_vector_uint2_sized + typedef vec<2, uint32, defaultp> u32vec2; + + /// 64 bit unsigned integer vector of 2 components type. + /// + /// @see ext_vector_uint2_sized + typedef vec<2, uint64, defaultp> u64vec2; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint3.hpp new file mode 100644 index 0000000..f5b41c4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_uint3.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 3 components vector of unsigned integer numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<3, unsigned int, defaultp> uvec3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint3_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint3_sized.hpp new file mode 100644 index 0000000..6f96b98 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint3_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_uint3_sized +/// @file glm/ext/vector_uint3_sized.hpp +/// +/// @defgroup ext_vector_uint3_sized GLM_EXT_vector_uint3_sized +/// @ingroup ext +/// +/// Exposes sized unsigned integer vector of 3 components type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_uint_sized +/// @see ext_vector_int3_sized + +#pragma once + +#include "../ext/vector_uint3.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_uint3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_uint3_sized + /// @{ + + /// 8 bit unsigned integer vector of 3 components type. + /// + /// @see ext_vector_uint3_sized + typedef vec<3, uint8, defaultp> u8vec3; + + /// 16 bit unsigned integer vector of 3 components type. + /// + /// @see ext_vector_uint3_sized + typedef vec<3, uint16, defaultp> u16vec3; + + /// 32 bit unsigned integer vector of 3 components type. + /// + /// @see ext_vector_uint3_sized + typedef vec<3, uint32, defaultp> u32vec3; + + /// 64 bit unsigned integer vector of 3 components type. + /// + /// @see ext_vector_uint3_sized + typedef vec<3, uint64, defaultp> u64vec3; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint4.hpp new file mode 100644 index 0000000..32ced58 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_uint4.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 4 components vector of unsigned integer numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<4, unsigned int, defaultp> uvec4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint4_sized.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint4_sized.hpp new file mode 100644 index 0000000..da992ea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_uint4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_uint4_sized +/// @file glm/ext/vector_uint4_sized.hpp +/// +/// @defgroup ext_vector_uint4_sized GLM_EXT_vector_uint4_sized +/// @ingroup ext +/// +/// Exposes sized unsigned integer vector of 4 components type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_uint_sized +/// @see ext_vector_int4_sized + +#pragma once + +#include "../ext/vector_uint4.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_uint4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_uint4_sized + /// @{ + + /// 8 bit unsigned integer vector of 4 components type. + /// + /// @see ext_vector_uint4_sized + typedef vec<4, uint8, defaultp> u8vec4; + + /// 16 bit unsigned integer vector of 4 components type. + /// + /// @see ext_vector_uint4_sized + typedef vec<4, uint16, defaultp> u16vec4; + + /// 32 bit unsigned integer vector of 4 components type. + /// + /// @see ext_vector_uint4_sized + typedef vec<4, uint32, defaultp> u32vec4; + + /// 64 bit unsigned integer vector of 4 components type. + /// + /// @see ext_vector_uint4_sized + typedef vec<4, uint64, defaultp> u64vec4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_ulp.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_ulp.hpp new file mode 100644 index 0000000..7c539bb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_ulp.hpp @@ -0,0 +1,112 @@ +/// @ref ext_vector_ulp +/// @file glm/ext/vector_ulp.hpp +/// +/// @defgroup ext_vector_ulp GLM_EXT_vector_ulp +/// @ingroup ext +/// +/// Allow the measurement of the accuracy of a function against a reference +/// implementation. This extension works on floating-point data and provide results +/// in ULP. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_ulp +/// @see ext_scalar_relational +/// @see ext_vector_relational + +#pragma once + +// Dependencies +#include "../ext/scalar_ulp.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_ulp extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_ulp + /// @{ + + /// Return the next ULP value(s) after the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec nextFloat(vec const& x); + + /// Return the value(s) ULP distance after the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec nextFloat(vec const& x, int ULPs); + + /// Return the value(s) ULP distance after the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec nextFloat(vec const& x, vec const& ULPs); + + /// Return the previous ULP value(s) before the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec prevFloat(vec const& x); + + /// Return the value(s) ULP distance before the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec prevFloat(vec const& x, int ULPs); + + /// Return the value(s) ULP distance before the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec prevFloat(vec const& x, vec const& ULPs); + + /// Return the distance in the number of ULP between 2 single-precision floating-point scalars. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec floatDistance(vec const& x, vec const& y); + + /// Return the distance in the number of ULP between 2 double-precision floating-point scalars. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec floatDistance(vec const& x, vec const& y); + + /// @} +}//namespace glm + +#include "vector_ulp.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_ulp.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_ulp.inl new file mode 100644 index 0000000..d3c7648 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_ulp.inl @@ -0,0 +1,74 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec nextFloat(vec const& x) + { + vec Result(0); + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = nextFloat(x[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec nextFloat(vec const& x, int ULPs) + { + vec Result(0); + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = nextFloat(x[i], ULPs); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec nextFloat(vec const& x, vec const& ULPs) + { + vec Result(0); + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = nextFloat(x[i], ULPs[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec prevFloat(vec const& x) + { + vec Result(0); + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prevFloat(x[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec prevFloat(vec const& x, int ULPs) + { + vec Result(0); + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prevFloat(x[i], ULPs); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec prevFloat(vec const& x, vec const& ULPs) + { + vec Result(0); + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prevFloat(x[i], ULPs[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec floatDistance(vec const& x, vec const& y) + { + vec Result(0); + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = floatDistance(x[i], y[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec floatDistance(vec const& x, vec const& y) + { + vec Result(0); + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = floatDistance(x[i], y[i]); + return Result; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/fwd.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/fwd.hpp new file mode 100644 index 0000000..9c2e5ea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/fwd.hpp @@ -0,0 +1,1233 @@ +#pragma once + +#include "detail/qualifier.hpp" + +namespace glm +{ +#if GLM_HAS_EXTENDED_INTEGER_TYPE + typedef std::int8_t int8; + typedef std::int16_t int16; + typedef std::int32_t int32; + typedef std::int64_t int64; + + typedef std::uint8_t uint8; + typedef std::uint16_t uint16; + typedef std::uint32_t uint32; + typedef std::uint64_t uint64; +#else + typedef signed char int8; + typedef signed short int16; + typedef signed int int32; + typedef detail::int64 int64; + + typedef unsigned char uint8; + typedef unsigned short uint16; + typedef unsigned int uint32; + typedef detail::uint64 uint64; +#endif + + // Scalar int + + typedef int8 lowp_i8; + typedef int8 mediump_i8; + typedef int8 highp_i8; + typedef int8 i8; + + typedef int8 lowp_int8; + typedef int8 mediump_int8; + typedef int8 highp_int8; + + typedef int8 lowp_int8_t; + typedef int8 mediump_int8_t; + typedef int8 highp_int8_t; + typedef int8 int8_t; + + typedef int16 lowp_i16; + typedef int16 mediump_i16; + typedef int16 highp_i16; + typedef int16 i16; + + typedef int16 lowp_int16; + typedef int16 mediump_int16; + typedef int16 highp_int16; + + typedef int16 lowp_int16_t; + typedef int16 mediump_int16_t; + typedef int16 highp_int16_t; + typedef int16 int16_t; + + typedef int32 lowp_i32; + typedef int32 mediump_i32; + typedef int32 highp_i32; + typedef int32 i32; + + typedef int32 lowp_int32; + typedef int32 mediump_int32; + typedef int32 highp_int32; + + typedef int32 lowp_int32_t; + typedef int32 mediump_int32_t; + typedef int32 highp_int32_t; + typedef int32 int32_t; + + typedef int64 lowp_i64; + typedef int64 mediump_i64; + typedef int64 highp_i64; + typedef int64 i64; + + typedef int64 lowp_int64; + typedef int64 mediump_int64; + typedef int64 highp_int64; + + typedef int64 lowp_int64_t; + typedef int64 mediump_int64_t; + typedef int64 highp_int64_t; + typedef int64 int64_t; + + // Scalar uint + + typedef unsigned int uint; + + typedef uint8 lowp_u8; + typedef uint8 mediump_u8; + typedef uint8 highp_u8; + typedef uint8 u8; + + typedef uint8 lowp_uint8; + typedef uint8 mediump_uint8; + typedef uint8 highp_uint8; + + typedef uint8 lowp_uint8_t; + typedef uint8 mediump_uint8_t; + typedef uint8 highp_uint8_t; + typedef uint8 uint8_t; + + typedef uint16 lowp_u16; + typedef uint16 mediump_u16; + typedef uint16 highp_u16; + typedef uint16 u16; + + typedef uint16 lowp_uint16; + typedef uint16 mediump_uint16; + typedef uint16 highp_uint16; + + typedef uint16 lowp_uint16_t; + typedef uint16 mediump_uint16_t; + typedef uint16 highp_uint16_t; + typedef uint16 uint16_t; + + typedef uint32 lowp_u32; + typedef uint32 mediump_u32; + typedef uint32 highp_u32; + typedef uint32 u32; + + typedef uint32 lowp_uint32; + typedef uint32 mediump_uint32; + typedef uint32 highp_uint32; + + typedef uint32 lowp_uint32_t; + typedef uint32 mediump_uint32_t; + typedef uint32 highp_uint32_t; + typedef uint32 uint32_t; + + typedef uint64 lowp_u64; + typedef uint64 mediump_u64; + typedef uint64 highp_u64; + typedef uint64 u64; + + typedef uint64 lowp_uint64; + typedef uint64 mediump_uint64; + typedef uint64 highp_uint64; + + typedef uint64 lowp_uint64_t; + typedef uint64 mediump_uint64_t; + typedef uint64 highp_uint64_t; + typedef uint64 uint64_t; + + // Scalar float + + typedef float lowp_f32; + typedef float mediump_f32; + typedef float highp_f32; + typedef float f32; + + typedef float lowp_float32; + typedef float mediump_float32; + typedef float highp_float32; + typedef float float32; + + typedef float lowp_float32_t; + typedef float mediump_float32_t; + typedef float highp_float32_t; + typedef float float32_t; + + + typedef double lowp_f64; + typedef double mediump_f64; + typedef double highp_f64; + typedef double f64; + + typedef double lowp_float64; + typedef double mediump_float64; + typedef double highp_float64; + typedef double float64; + + typedef double lowp_float64_t; + typedef double mediump_float64_t; + typedef double highp_float64_t; + typedef double float64_t; + + // Vector bool + + typedef vec<1, bool, lowp> lowp_bvec1; + typedef vec<2, bool, lowp> lowp_bvec2; + typedef vec<3, bool, lowp> lowp_bvec3; + typedef vec<4, bool, lowp> lowp_bvec4; + + typedef vec<1, bool, mediump> mediump_bvec1; + typedef vec<2, bool, mediump> mediump_bvec2; + typedef vec<3, bool, mediump> mediump_bvec3; + typedef vec<4, bool, mediump> mediump_bvec4; + + typedef vec<1, bool, highp> highp_bvec1; + typedef vec<2, bool, highp> highp_bvec2; + typedef vec<3, bool, highp> highp_bvec3; + typedef vec<4, bool, highp> highp_bvec4; + + typedef vec<1, bool, defaultp> bvec1; + typedef vec<2, bool, defaultp> bvec2; + typedef vec<3, bool, defaultp> bvec3; + typedef vec<4, bool, defaultp> bvec4; + + // Vector int + + typedef vec<1, int, lowp> lowp_ivec1; + typedef vec<2, int, lowp> lowp_ivec2; + typedef vec<3, int, lowp> lowp_ivec3; + typedef vec<4, int, lowp> lowp_ivec4; + + typedef vec<1, int, mediump> mediump_ivec1; + typedef vec<2, int, mediump> mediump_ivec2; + typedef vec<3, int, mediump> mediump_ivec3; + typedef vec<4, int, mediump> mediump_ivec4; + + typedef vec<1, int, highp> highp_ivec1; + typedef vec<2, int, highp> highp_ivec2; + typedef vec<3, int, highp> highp_ivec3; + typedef vec<4, int, highp> highp_ivec4; + + typedef vec<1, int, defaultp> ivec1; + typedef vec<2, int, defaultp> ivec2; + typedef vec<3, int, defaultp> ivec3; + typedef vec<4, int, defaultp> ivec4; + + typedef vec<1, i8, lowp> lowp_i8vec1; + typedef vec<2, i8, lowp> lowp_i8vec2; + typedef vec<3, i8, lowp> lowp_i8vec3; + typedef vec<4, i8, lowp> lowp_i8vec4; + + typedef vec<1, i8, mediump> mediump_i8vec1; + typedef vec<2, i8, mediump> mediump_i8vec2; + typedef vec<3, i8, mediump> mediump_i8vec3; + typedef vec<4, i8, mediump> mediump_i8vec4; + + typedef vec<1, i8, highp> highp_i8vec1; + typedef vec<2, i8, highp> highp_i8vec2; + typedef vec<3, i8, highp> highp_i8vec3; + typedef vec<4, i8, highp> highp_i8vec4; + + typedef vec<1, i8, defaultp> i8vec1; + typedef vec<2, i8, defaultp> i8vec2; + typedef vec<3, i8, defaultp> i8vec3; + typedef vec<4, i8, defaultp> i8vec4; + + typedef vec<1, i16, lowp> lowp_i16vec1; + typedef vec<2, i16, lowp> lowp_i16vec2; + typedef vec<3, i16, lowp> lowp_i16vec3; + typedef vec<4, i16, lowp> lowp_i16vec4; + + typedef vec<1, i16, mediump> mediump_i16vec1; + typedef vec<2, i16, mediump> mediump_i16vec2; + typedef vec<3, i16, mediump> mediump_i16vec3; + typedef vec<4, i16, mediump> mediump_i16vec4; + + typedef vec<1, i16, highp> highp_i16vec1; + typedef vec<2, i16, highp> highp_i16vec2; + typedef vec<3, i16, highp> highp_i16vec3; + typedef vec<4, i16, highp> highp_i16vec4; + + typedef vec<1, i16, defaultp> i16vec1; + typedef vec<2, i16, defaultp> i16vec2; + typedef vec<3, i16, defaultp> i16vec3; + typedef vec<4, i16, defaultp> i16vec4; + + typedef vec<1, i32, lowp> lowp_i32vec1; + typedef vec<2, i32, lowp> lowp_i32vec2; + typedef vec<3, i32, lowp> lowp_i32vec3; + typedef vec<4, i32, lowp> lowp_i32vec4; + + typedef vec<1, i32, mediump> mediump_i32vec1; + typedef vec<2, i32, mediump> mediump_i32vec2; + typedef vec<3, i32, mediump> mediump_i32vec3; + typedef vec<4, i32, mediump> mediump_i32vec4; + + typedef vec<1, i32, highp> highp_i32vec1; + typedef vec<2, i32, highp> highp_i32vec2; + typedef vec<3, i32, highp> highp_i32vec3; + typedef vec<4, i32, highp> highp_i32vec4; + + typedef vec<1, i32, defaultp> i32vec1; + typedef vec<2, i32, defaultp> i32vec2; + typedef vec<3, i32, defaultp> i32vec3; + typedef vec<4, i32, defaultp> i32vec4; + + typedef vec<1, i64, lowp> lowp_i64vec1; + typedef vec<2, i64, lowp> lowp_i64vec2; + typedef vec<3, i64, lowp> lowp_i64vec3; + typedef vec<4, i64, lowp> lowp_i64vec4; + + typedef vec<1, i64, mediump> mediump_i64vec1; + typedef vec<2, i64, mediump> mediump_i64vec2; + typedef vec<3, i64, mediump> mediump_i64vec3; + typedef vec<4, i64, mediump> mediump_i64vec4; + + typedef vec<1, i64, highp> highp_i64vec1; + typedef vec<2, i64, highp> highp_i64vec2; + typedef vec<3, i64, highp> highp_i64vec3; + typedef vec<4, i64, highp> highp_i64vec4; + + typedef vec<1, i64, defaultp> i64vec1; + typedef vec<2, i64, defaultp> i64vec2; + typedef vec<3, i64, defaultp> i64vec3; + typedef vec<4, i64, defaultp> i64vec4; + + // Vector uint + + typedef vec<1, uint, lowp> lowp_uvec1; + typedef vec<2, uint, lowp> lowp_uvec2; + typedef vec<3, uint, lowp> lowp_uvec3; + typedef vec<4, uint, lowp> lowp_uvec4; + + typedef vec<1, uint, mediump> mediump_uvec1; + typedef vec<2, uint, mediump> mediump_uvec2; + typedef vec<3, uint, mediump> mediump_uvec3; + typedef vec<4, uint, mediump> mediump_uvec4; + + typedef vec<1, uint, highp> highp_uvec1; + typedef vec<2, uint, highp> highp_uvec2; + typedef vec<3, uint, highp> highp_uvec3; + typedef vec<4, uint, highp> highp_uvec4; + + typedef vec<1, uint, defaultp> uvec1; + typedef vec<2, uint, defaultp> uvec2; + typedef vec<3, uint, defaultp> uvec3; + typedef vec<4, uint, defaultp> uvec4; + + typedef vec<1, u8, lowp> lowp_u8vec1; + typedef vec<2, u8, lowp> lowp_u8vec2; + typedef vec<3, u8, lowp> lowp_u8vec3; + typedef vec<4, u8, lowp> lowp_u8vec4; + + typedef vec<1, u8, mediump> mediump_u8vec1; + typedef vec<2, u8, mediump> mediump_u8vec2; + typedef vec<3, u8, mediump> mediump_u8vec3; + typedef vec<4, u8, mediump> mediump_u8vec4; + + typedef vec<1, u8, highp> highp_u8vec1; + typedef vec<2, u8, highp> highp_u8vec2; + typedef vec<3, u8, highp> highp_u8vec3; + typedef vec<4, u8, highp> highp_u8vec4; + + typedef vec<1, u8, defaultp> u8vec1; + typedef vec<2, u8, defaultp> u8vec2; + typedef vec<3, u8, defaultp> u8vec3; + typedef vec<4, u8, defaultp> u8vec4; + + typedef vec<1, u16, lowp> lowp_u16vec1; + typedef vec<2, u16, lowp> lowp_u16vec2; + typedef vec<3, u16, lowp> lowp_u16vec3; + typedef vec<4, u16, lowp> lowp_u16vec4; + + typedef vec<1, u16, mediump> mediump_u16vec1; + typedef vec<2, u16, mediump> mediump_u16vec2; + typedef vec<3, u16, mediump> mediump_u16vec3; + typedef vec<4, u16, mediump> mediump_u16vec4; + + typedef vec<1, u16, highp> highp_u16vec1; + typedef vec<2, u16, highp> highp_u16vec2; + typedef vec<3, u16, highp> highp_u16vec3; + typedef vec<4, u16, highp> highp_u16vec4; + + typedef vec<1, u16, defaultp> u16vec1; + typedef vec<2, u16, defaultp> u16vec2; + typedef vec<3, u16, defaultp> u16vec3; + typedef vec<4, u16, defaultp> u16vec4; + + typedef vec<1, u32, lowp> lowp_u32vec1; + typedef vec<2, u32, lowp> lowp_u32vec2; + typedef vec<3, u32, lowp> lowp_u32vec3; + typedef vec<4, u32, lowp> lowp_u32vec4; + + typedef vec<1, u32, mediump> mediump_u32vec1; + typedef vec<2, u32, mediump> mediump_u32vec2; + typedef vec<3, u32, mediump> mediump_u32vec3; + typedef vec<4, u32, mediump> mediump_u32vec4; + + typedef vec<1, u32, highp> highp_u32vec1; + typedef vec<2, u32, highp> highp_u32vec2; + typedef vec<3, u32, highp> highp_u32vec3; + typedef vec<4, u32, highp> highp_u32vec4; + + typedef vec<1, u32, defaultp> u32vec1; + typedef vec<2, u32, defaultp> u32vec2; + typedef vec<3, u32, defaultp> u32vec3; + typedef vec<4, u32, defaultp> u32vec4; + + typedef vec<1, u64, lowp> lowp_u64vec1; + typedef vec<2, u64, lowp> lowp_u64vec2; + typedef vec<3, u64, lowp> lowp_u64vec3; + typedef vec<4, u64, lowp> lowp_u64vec4; + + typedef vec<1, u64, mediump> mediump_u64vec1; + typedef vec<2, u64, mediump> mediump_u64vec2; + typedef vec<3, u64, mediump> mediump_u64vec3; + typedef vec<4, u64, mediump> mediump_u64vec4; + + typedef vec<1, u64, highp> highp_u64vec1; + typedef vec<2, u64, highp> highp_u64vec2; + typedef vec<3, u64, highp> highp_u64vec3; + typedef vec<4, u64, highp> highp_u64vec4; + + typedef vec<1, u64, defaultp> u64vec1; + typedef vec<2, u64, defaultp> u64vec2; + typedef vec<3, u64, defaultp> u64vec3; + typedef vec<4, u64, defaultp> u64vec4; + + // Vector float + + typedef vec<1, float, lowp> lowp_vec1; + typedef vec<2, float, lowp> lowp_vec2; + typedef vec<3, float, lowp> lowp_vec3; + typedef vec<4, float, lowp> lowp_vec4; + + typedef vec<1, float, mediump> mediump_vec1; + typedef vec<2, float, mediump> mediump_vec2; + typedef vec<3, float, mediump> mediump_vec3; + typedef vec<4, float, mediump> mediump_vec4; + + typedef vec<1, float, highp> highp_vec1; + typedef vec<2, float, highp> highp_vec2; + typedef vec<3, float, highp> highp_vec3; + typedef vec<4, float, highp> highp_vec4; + + typedef vec<1, float, defaultp> vec1; + typedef vec<2, float, defaultp> vec2; + typedef vec<3, float, defaultp> vec3; + typedef vec<4, float, defaultp> vec4; + + typedef vec<1, float, lowp> lowp_fvec1; + typedef vec<2, float, lowp> lowp_fvec2; + typedef vec<3, float, lowp> lowp_fvec3; + typedef vec<4, float, lowp> lowp_fvec4; + + typedef vec<1, float, mediump> mediump_fvec1; + typedef vec<2, float, mediump> mediump_fvec2; + typedef vec<3, float, mediump> mediump_fvec3; + typedef vec<4, float, mediump> mediump_fvec4; + + typedef vec<1, float, highp> highp_fvec1; + typedef vec<2, float, highp> highp_fvec2; + typedef vec<3, float, highp> highp_fvec3; + typedef vec<4, float, highp> highp_fvec4; + + typedef vec<1, f32, defaultp> fvec1; + typedef vec<2, f32, defaultp> fvec2; + typedef vec<3, f32, defaultp> fvec3; + typedef vec<4, f32, defaultp> fvec4; + + typedef vec<1, f32, lowp> lowp_f32vec1; + typedef vec<2, f32, lowp> lowp_f32vec2; + typedef vec<3, f32, lowp> lowp_f32vec3; + typedef vec<4, f32, lowp> lowp_f32vec4; + + typedef vec<1, f32, mediump> mediump_f32vec1; + typedef vec<2, f32, mediump> mediump_f32vec2; + typedef vec<3, f32, mediump> mediump_f32vec3; + typedef vec<4, f32, mediump> mediump_f32vec4; + + typedef vec<1, f32, highp> highp_f32vec1; + typedef vec<2, f32, highp> highp_f32vec2; + typedef vec<3, f32, highp> highp_f32vec3; + typedef vec<4, f32, highp> highp_f32vec4; + + typedef vec<1, f32, defaultp> f32vec1; + typedef vec<2, f32, defaultp> f32vec2; + typedef vec<3, f32, defaultp> f32vec3; + typedef vec<4, f32, defaultp> f32vec4; + + typedef vec<1, f64, lowp> lowp_dvec1; + typedef vec<2, f64, lowp> lowp_dvec2; + typedef vec<3, f64, lowp> lowp_dvec3; + typedef vec<4, f64, lowp> lowp_dvec4; + + typedef vec<1, f64, mediump> mediump_dvec1; + typedef vec<2, f64, mediump> mediump_dvec2; + typedef vec<3, f64, mediump> mediump_dvec3; + typedef vec<4, f64, mediump> mediump_dvec4; + + typedef vec<1, f64, highp> highp_dvec1; + typedef vec<2, f64, highp> highp_dvec2; + typedef vec<3, f64, highp> highp_dvec3; + typedef vec<4, f64, highp> highp_dvec4; + + typedef vec<1, f64, defaultp> dvec1; + typedef vec<2, f64, defaultp> dvec2; + typedef vec<3, f64, defaultp> dvec3; + typedef vec<4, f64, defaultp> dvec4; + + typedef vec<1, f64, lowp> lowp_f64vec1; + typedef vec<2, f64, lowp> lowp_f64vec2; + typedef vec<3, f64, lowp> lowp_f64vec3; + typedef vec<4, f64, lowp> lowp_f64vec4; + + typedef vec<1, f64, mediump> mediump_f64vec1; + typedef vec<2, f64, mediump> mediump_f64vec2; + typedef vec<3, f64, mediump> mediump_f64vec3; + typedef vec<4, f64, mediump> mediump_f64vec4; + + typedef vec<1, f64, highp> highp_f64vec1; + typedef vec<2, f64, highp> highp_f64vec2; + typedef vec<3, f64, highp> highp_f64vec3; + typedef vec<4, f64, highp> highp_f64vec4; + + typedef vec<1, f64, defaultp> f64vec1; + typedef vec<2, f64, defaultp> f64vec2; + typedef vec<3, f64, defaultp> f64vec3; + typedef vec<4, f64, defaultp> f64vec4; + + // Matrix NxN + + typedef mat<2, 2, f32, lowp> lowp_mat2; + typedef mat<3, 3, f32, lowp> lowp_mat3; + typedef mat<4, 4, f32, lowp> lowp_mat4; + + typedef mat<2, 2, f32, mediump> mediump_mat2; + typedef mat<3, 3, f32, mediump> mediump_mat3; + typedef mat<4, 4, f32, mediump> mediump_mat4; + + typedef mat<2, 2, f32, highp> highp_mat2; + typedef mat<3, 3, f32, highp> highp_mat3; + typedef mat<4, 4, f32, highp> highp_mat4; + + typedef mat<2, 2, f32, defaultp> mat2; + typedef mat<3, 3, f32, defaultp> mat3; + typedef mat<4, 4, f32, defaultp> mat4; + + typedef mat<2, 2, f32, lowp> lowp_fmat2; + typedef mat<3, 3, f32, lowp> lowp_fmat3; + typedef mat<4, 4, f32, lowp> lowp_fmat4; + + typedef mat<2, 2, f32, mediump> mediump_fmat2; + typedef mat<3, 3, f32, mediump> mediump_fmat3; + typedef mat<4, 4, f32, mediump> mediump_fmat4; + + typedef mat<2, 2, f32, highp> highp_fmat2; + typedef mat<3, 3, f32, highp> highp_fmat3; + typedef mat<4, 4, f32, highp> highp_fmat4; + + typedef mat<2, 2, f32, defaultp> fmat2; + typedef mat<3, 3, f32, defaultp> fmat3; + typedef mat<4, 4, f32, defaultp> fmat4; + + typedef mat<2, 2, f32, lowp> lowp_f32mat2; + typedef mat<3, 3, f32, lowp> lowp_f32mat3; + typedef mat<4, 4, f32, lowp> lowp_f32mat4; + + typedef mat<2, 2, f32, mediump> mediump_f32mat2; + typedef mat<3, 3, f32, mediump> mediump_f32mat3; + typedef mat<4, 4, f32, mediump> mediump_f32mat4; + + typedef mat<2, 2, f32, highp> highp_f32mat2; + typedef mat<3, 3, f32, highp> highp_f32mat3; + typedef mat<4, 4, f32, highp> highp_f32mat4; + + typedef mat<2, 2, f32, defaultp> f32mat2; + typedef mat<3, 3, f32, defaultp> f32mat3; + typedef mat<4, 4, f32, defaultp> f32mat4; + + typedef mat<2, 2, f64, lowp> lowp_dmat2; + typedef mat<3, 3, f64, lowp> lowp_dmat3; + typedef mat<4, 4, f64, lowp> lowp_dmat4; + + typedef mat<2, 2, f64, mediump> mediump_dmat2; + typedef mat<3, 3, f64, mediump> mediump_dmat3; + typedef mat<4, 4, f64, mediump> mediump_dmat4; + + typedef mat<2, 2, f64, highp> highp_dmat2; + typedef mat<3, 3, f64, highp> highp_dmat3; + typedef mat<4, 4, f64, highp> highp_dmat4; + + typedef mat<2, 2, f64, defaultp> dmat2; + typedef mat<3, 3, f64, defaultp> dmat3; + typedef mat<4, 4, f64, defaultp> dmat4; + + typedef mat<2, 2, f64, lowp> lowp_f64mat2; + typedef mat<3, 3, f64, lowp> lowp_f64mat3; + typedef mat<4, 4, f64, lowp> lowp_f64mat4; + + typedef mat<2, 2, f64, mediump> mediump_f64mat2; + typedef mat<3, 3, f64, mediump> mediump_f64mat3; + typedef mat<4, 4, f64, mediump> mediump_f64mat4; + + typedef mat<2, 2, f64, highp> highp_f64mat2; + typedef mat<3, 3, f64, highp> highp_f64mat3; + typedef mat<4, 4, f64, highp> highp_f64mat4; + + typedef mat<2, 2, f64, defaultp> f64mat2; + typedef mat<3, 3, f64, defaultp> f64mat3; + typedef mat<4, 4, f64, defaultp> f64mat4; + + // Matrix MxN + + typedef mat<2, 2, f32, lowp> lowp_mat2x2; + typedef mat<2, 3, f32, lowp> lowp_mat2x3; + typedef mat<2, 4, f32, lowp> lowp_mat2x4; + typedef mat<3, 2, f32, lowp> lowp_mat3x2; + typedef mat<3, 3, f32, lowp> lowp_mat3x3; + typedef mat<3, 4, f32, lowp> lowp_mat3x4; + typedef mat<4, 2, f32, lowp> lowp_mat4x2; + typedef mat<4, 3, f32, lowp> lowp_mat4x3; + typedef mat<4, 4, f32, lowp> lowp_mat4x4; + + typedef mat<2, 2, f32, mediump> mediump_mat2x2; + typedef mat<2, 3, f32, mediump> mediump_mat2x3; + typedef mat<2, 4, f32, mediump> mediump_mat2x4; + typedef mat<3, 2, f32, mediump> mediump_mat3x2; + typedef mat<3, 3, f32, mediump> mediump_mat3x3; + typedef mat<3, 4, f32, mediump> mediump_mat3x4; + typedef mat<4, 2, f32, mediump> mediump_mat4x2; + typedef mat<4, 3, f32, mediump> mediump_mat4x3; + typedef mat<4, 4, f32, mediump> mediump_mat4x4; + + typedef mat<2, 2, f32, highp> highp_mat2x2; + typedef mat<2, 3, f32, highp> highp_mat2x3; + typedef mat<2, 4, f32, highp> highp_mat2x4; + typedef mat<3, 2, f32, highp> highp_mat3x2; + typedef mat<3, 3, f32, highp> highp_mat3x3; + typedef mat<3, 4, f32, highp> highp_mat3x4; + typedef mat<4, 2, f32, highp> highp_mat4x2; + typedef mat<4, 3, f32, highp> highp_mat4x3; + typedef mat<4, 4, f32, highp> highp_mat4x4; + + typedef mat<2, 2, f32, defaultp> mat2x2; + typedef mat<2, 3, f32, defaultp> mat2x3; + typedef mat<2, 4, f32, defaultp> mat2x4; + typedef mat<3, 2, f32, defaultp> mat3x2; + typedef mat<3, 3, f32, defaultp> mat3x3; + typedef mat<3, 4, f32, defaultp> mat3x4; + typedef mat<4, 2, f32, defaultp> mat4x2; + typedef mat<4, 3, f32, defaultp> mat4x3; + typedef mat<4, 4, f32, defaultp> mat4x4; + + typedef mat<2, 2, f32, lowp> lowp_fmat2x2; + typedef mat<2, 3, f32, lowp> lowp_fmat2x3; + typedef mat<2, 4, f32, lowp> lowp_fmat2x4; + typedef mat<3, 2, f32, lowp> lowp_fmat3x2; + typedef mat<3, 3, f32, lowp> lowp_fmat3x3; + typedef mat<3, 4, f32, lowp> lowp_fmat3x4; + typedef mat<4, 2, f32, lowp> lowp_fmat4x2; + typedef mat<4, 3, f32, lowp> lowp_fmat4x3; + typedef mat<4, 4, f32, lowp> lowp_fmat4x4; + + typedef mat<2, 2, f32, mediump> mediump_fmat2x2; + typedef mat<2, 3, f32, mediump> mediump_fmat2x3; + typedef mat<2, 4, f32, mediump> mediump_fmat2x4; + typedef mat<3, 2, f32, mediump> mediump_fmat3x2; + typedef mat<3, 3, f32, mediump> mediump_fmat3x3; + typedef mat<3, 4, f32, mediump> mediump_fmat3x4; + typedef mat<4, 2, f32, mediump> mediump_fmat4x2; + typedef mat<4, 3, f32, mediump> mediump_fmat4x3; + typedef mat<4, 4, f32, mediump> mediump_fmat4x4; + + typedef mat<2, 2, f32, highp> highp_fmat2x2; + typedef mat<2, 3, f32, highp> highp_fmat2x3; + typedef mat<2, 4, f32, highp> highp_fmat2x4; + typedef mat<3, 2, f32, highp> highp_fmat3x2; + typedef mat<3, 3, f32, highp> highp_fmat3x3; + typedef mat<3, 4, f32, highp> highp_fmat3x4; + typedef mat<4, 2, f32, highp> highp_fmat4x2; + typedef mat<4, 3, f32, highp> highp_fmat4x3; + typedef mat<4, 4, f32, highp> highp_fmat4x4; + + typedef mat<2, 2, f32, defaultp> fmat2x2; + typedef mat<2, 3, f32, defaultp> fmat2x3; + typedef mat<2, 4, f32, defaultp> fmat2x4; + typedef mat<3, 2, f32, defaultp> fmat3x2; + typedef mat<3, 3, f32, defaultp> fmat3x3; + typedef mat<3, 4, f32, defaultp> fmat3x4; + typedef mat<4, 2, f32, defaultp> fmat4x2; + typedef mat<4, 3, f32, defaultp> fmat4x3; + typedef mat<4, 4, f32, defaultp> fmat4x4; + + typedef mat<2, 2, f32, lowp> lowp_f32mat2x2; + typedef mat<2, 3, f32, lowp> lowp_f32mat2x3; + typedef mat<2, 4, f32, lowp> lowp_f32mat2x4; + typedef mat<3, 2, f32, lowp> lowp_f32mat3x2; + typedef mat<3, 3, f32, lowp> lowp_f32mat3x3; + typedef mat<3, 4, f32, lowp> lowp_f32mat3x4; + typedef mat<4, 2, f32, lowp> lowp_f32mat4x2; + typedef mat<4, 3, f32, lowp> lowp_f32mat4x3; + typedef mat<4, 4, f32, lowp> lowp_f32mat4x4; + + typedef mat<2, 2, f32, mediump> mediump_f32mat2x2; + typedef mat<2, 3, f32, mediump> mediump_f32mat2x3; + typedef mat<2, 4, f32, mediump> mediump_f32mat2x4; + typedef mat<3, 2, f32, mediump> mediump_f32mat3x2; + typedef mat<3, 3, f32, mediump> mediump_f32mat3x3; + typedef mat<3, 4, f32, mediump> mediump_f32mat3x4; + typedef mat<4, 2, f32, mediump> mediump_f32mat4x2; + typedef mat<4, 3, f32, mediump> mediump_f32mat4x3; + typedef mat<4, 4, f32, mediump> mediump_f32mat4x4; + + typedef mat<2, 2, f32, highp> highp_f32mat2x2; + typedef mat<2, 3, f32, highp> highp_f32mat2x3; + typedef mat<2, 4, f32, highp> highp_f32mat2x4; + typedef mat<3, 2, f32, highp> highp_f32mat3x2; + typedef mat<3, 3, f32, highp> highp_f32mat3x3; + typedef mat<3, 4, f32, highp> highp_f32mat3x4; + typedef mat<4, 2, f32, highp> highp_f32mat4x2; + typedef mat<4, 3, f32, highp> highp_f32mat4x3; + typedef mat<4, 4, f32, highp> highp_f32mat4x4; + + typedef mat<2, 2, f32, defaultp> f32mat2x2; + typedef mat<2, 3, f32, defaultp> f32mat2x3; + typedef mat<2, 4, f32, defaultp> f32mat2x4; + typedef mat<3, 2, f32, defaultp> f32mat3x2; + typedef mat<3, 3, f32, defaultp> f32mat3x3; + typedef mat<3, 4, f32, defaultp> f32mat3x4; + typedef mat<4, 2, f32, defaultp> f32mat4x2; + typedef mat<4, 3, f32, defaultp> f32mat4x3; + typedef mat<4, 4, f32, defaultp> f32mat4x4; + + typedef mat<2, 2, double, lowp> lowp_dmat2x2; + typedef mat<2, 3, double, lowp> lowp_dmat2x3; + typedef mat<2, 4, double, lowp> lowp_dmat2x4; + typedef mat<3, 2, double, lowp> lowp_dmat3x2; + typedef mat<3, 3, double, lowp> lowp_dmat3x3; + typedef mat<3, 4, double, lowp> lowp_dmat3x4; + typedef mat<4, 2, double, lowp> lowp_dmat4x2; + typedef mat<4, 3, double, lowp> lowp_dmat4x3; + typedef mat<4, 4, double, lowp> lowp_dmat4x4; + + typedef mat<2, 2, double, mediump> mediump_dmat2x2; + typedef mat<2, 3, double, mediump> mediump_dmat2x3; + typedef mat<2, 4, double, mediump> mediump_dmat2x4; + typedef mat<3, 2, double, mediump> mediump_dmat3x2; + typedef mat<3, 3, double, mediump> mediump_dmat3x3; + typedef mat<3, 4, double, mediump> mediump_dmat3x4; + typedef mat<4, 2, double, mediump> mediump_dmat4x2; + typedef mat<4, 3, double, mediump> mediump_dmat4x3; + typedef mat<4, 4, double, mediump> mediump_dmat4x4; + + typedef mat<2, 2, double, highp> highp_dmat2x2; + typedef mat<2, 3, double, highp> highp_dmat2x3; + typedef mat<2, 4, double, highp> highp_dmat2x4; + typedef mat<3, 2, double, highp> highp_dmat3x2; + typedef mat<3, 3, double, highp> highp_dmat3x3; + typedef mat<3, 4, double, highp> highp_dmat3x4; + typedef mat<4, 2, double, highp> highp_dmat4x2; + typedef mat<4, 3, double, highp> highp_dmat4x3; + typedef mat<4, 4, double, highp> highp_dmat4x4; + + typedef mat<2, 2, double, defaultp> dmat2x2; + typedef mat<2, 3, double, defaultp> dmat2x3; + typedef mat<2, 4, double, defaultp> dmat2x4; + typedef mat<3, 2, double, defaultp> dmat3x2; + typedef mat<3, 3, double, defaultp> dmat3x3; + typedef mat<3, 4, double, defaultp> dmat3x4; + typedef mat<4, 2, double, defaultp> dmat4x2; + typedef mat<4, 3, double, defaultp> dmat4x3; + typedef mat<4, 4, double, defaultp> dmat4x4; + + typedef mat<2, 2, f64, lowp> lowp_f64mat2x2; + typedef mat<2, 3, f64, lowp> lowp_f64mat2x3; + typedef mat<2, 4, f64, lowp> lowp_f64mat2x4; + typedef mat<3, 2, f64, lowp> lowp_f64mat3x2; + typedef mat<3, 3, f64, lowp> lowp_f64mat3x3; + typedef mat<3, 4, f64, lowp> lowp_f64mat3x4; + typedef mat<4, 2, f64, lowp> lowp_f64mat4x2; + typedef mat<4, 3, f64, lowp> lowp_f64mat4x3; + typedef mat<4, 4, f64, lowp> lowp_f64mat4x4; + + typedef mat<2, 2, f64, mediump> mediump_f64mat2x2; + typedef mat<2, 3, f64, mediump> mediump_f64mat2x3; + typedef mat<2, 4, f64, mediump> mediump_f64mat2x4; + typedef mat<3, 2, f64, mediump> mediump_f64mat3x2; + typedef mat<3, 3, f64, mediump> mediump_f64mat3x3; + typedef mat<3, 4, f64, mediump> mediump_f64mat3x4; + typedef mat<4, 2, f64, mediump> mediump_f64mat4x2; + typedef mat<4, 3, f64, mediump> mediump_f64mat4x3; + typedef mat<4, 4, f64, mediump> mediump_f64mat4x4; + + typedef mat<2, 2, f64, highp> highp_f64mat2x2; + typedef mat<2, 3, f64, highp> highp_f64mat2x3; + typedef mat<2, 4, f64, highp> highp_f64mat2x4; + typedef mat<3, 2, f64, highp> highp_f64mat3x2; + typedef mat<3, 3, f64, highp> highp_f64mat3x3; + typedef mat<3, 4, f64, highp> highp_f64mat3x4; + typedef mat<4, 2, f64, highp> highp_f64mat4x2; + typedef mat<4, 3, f64, highp> highp_f64mat4x3; + typedef mat<4, 4, f64, highp> highp_f64mat4x4; + + typedef mat<2, 2, f64, defaultp> f64mat2x2; + typedef mat<2, 3, f64, defaultp> f64mat2x3; + typedef mat<2, 4, f64, defaultp> f64mat2x4; + typedef mat<3, 2, f64, defaultp> f64mat3x2; + typedef mat<3, 3, f64, defaultp> f64mat3x3; + typedef mat<3, 4, f64, defaultp> f64mat3x4; + typedef mat<4, 2, f64, defaultp> f64mat4x2; + typedef mat<4, 3, f64, defaultp> f64mat4x3; + typedef mat<4, 4, f64, defaultp> f64mat4x4; + + // Signed integer matrix MxN + + typedef mat<2, 2, int, lowp> lowp_imat2x2; + typedef mat<2, 3, int, lowp> lowp_imat2x3; + typedef mat<2, 4, int, lowp> lowp_imat2x4; + typedef mat<3, 2, int, lowp> lowp_imat3x2; + typedef mat<3, 3, int, lowp> lowp_imat3x3; + typedef mat<3, 4, int, lowp> lowp_imat3x4; + typedef mat<4, 2, int, lowp> lowp_imat4x2; + typedef mat<4, 3, int, lowp> lowp_imat4x3; + typedef mat<4, 4, int, lowp> lowp_imat4x4; + + typedef mat<2, 2, int, mediump> mediump_imat2x2; + typedef mat<2, 3, int, mediump> mediump_imat2x3; + typedef mat<2, 4, int, mediump> mediump_imat2x4; + typedef mat<3, 2, int, mediump> mediump_imat3x2; + typedef mat<3, 3, int, mediump> mediump_imat3x3; + typedef mat<3, 4, int, mediump> mediump_imat3x4; + typedef mat<4, 2, int, mediump> mediump_imat4x2; + typedef mat<4, 3, int, mediump> mediump_imat4x3; + typedef mat<4, 4, int, mediump> mediump_imat4x4; + + typedef mat<2, 2, int, highp> highp_imat2x2; + typedef mat<2, 3, int, highp> highp_imat2x3; + typedef mat<2, 4, int, highp> highp_imat2x4; + typedef mat<3, 2, int, highp> highp_imat3x2; + typedef mat<3, 3, int, highp> highp_imat3x3; + typedef mat<3, 4, int, highp> highp_imat3x4; + typedef mat<4, 2, int, highp> highp_imat4x2; + typedef mat<4, 3, int, highp> highp_imat4x3; + typedef mat<4, 4, int, highp> highp_imat4x4; + + typedef mat<2, 2, int, defaultp> imat2x2; + typedef mat<2, 3, int, defaultp> imat2x3; + typedef mat<2, 4, int, defaultp> imat2x4; + typedef mat<3, 2, int, defaultp> imat3x2; + typedef mat<3, 3, int, defaultp> imat3x3; + typedef mat<3, 4, int, defaultp> imat3x4; + typedef mat<4, 2, int, defaultp> imat4x2; + typedef mat<4, 3, int, defaultp> imat4x3; + typedef mat<4, 4, int, defaultp> imat4x4; + + + typedef mat<2, 2, int8, lowp> lowp_i8mat2x2; + typedef mat<2, 3, int8, lowp> lowp_i8mat2x3; + typedef mat<2, 4, int8, lowp> lowp_i8mat2x4; + typedef mat<3, 2, int8, lowp> lowp_i8mat3x2; + typedef mat<3, 3, int8, lowp> lowp_i8mat3x3; + typedef mat<3, 4, int8, lowp> lowp_i8mat3x4; + typedef mat<4, 2, int8, lowp> lowp_i8mat4x2; + typedef mat<4, 3, int8, lowp> lowp_i8mat4x3; + typedef mat<4, 4, int8, lowp> lowp_i8mat4x4; + + typedef mat<2, 2, int8, mediump> mediump_i8mat2x2; + typedef mat<2, 3, int8, mediump> mediump_i8mat2x3; + typedef mat<2, 4, int8, mediump> mediump_i8mat2x4; + typedef mat<3, 2, int8, mediump> mediump_i8mat3x2; + typedef mat<3, 3, int8, mediump> mediump_i8mat3x3; + typedef mat<3, 4, int8, mediump> mediump_i8mat3x4; + typedef mat<4, 2, int8, mediump> mediump_i8mat4x2; + typedef mat<4, 3, int8, mediump> mediump_i8mat4x3; + typedef mat<4, 4, int8, mediump> mediump_i8mat4x4; + + typedef mat<2, 2, int8, highp> highp_i8mat2x2; + typedef mat<2, 3, int8, highp> highp_i8mat2x3; + typedef mat<2, 4, int8, highp> highp_i8mat2x4; + typedef mat<3, 2, int8, highp> highp_i8mat3x2; + typedef mat<3, 3, int8, highp> highp_i8mat3x3; + typedef mat<3, 4, int8, highp> highp_i8mat3x4; + typedef mat<4, 2, int8, highp> highp_i8mat4x2; + typedef mat<4, 3, int8, highp> highp_i8mat4x3; + typedef mat<4, 4, int8, highp> highp_i8mat4x4; + + typedef mat<2, 2, int8, defaultp> i8mat2x2; + typedef mat<2, 3, int8, defaultp> i8mat2x3; + typedef mat<2, 4, int8, defaultp> i8mat2x4; + typedef mat<3, 2, int8, defaultp> i8mat3x2; + typedef mat<3, 3, int8, defaultp> i8mat3x3; + typedef mat<3, 4, int8, defaultp> i8mat3x4; + typedef mat<4, 2, int8, defaultp> i8mat4x2; + typedef mat<4, 3, int8, defaultp> i8mat4x3; + typedef mat<4, 4, int8, defaultp> i8mat4x4; + + + typedef mat<2, 2, int16, lowp> lowp_i16mat2x2; + typedef mat<2, 3, int16, lowp> lowp_i16mat2x3; + typedef mat<2, 4, int16, lowp> lowp_i16mat2x4; + typedef mat<3, 2, int16, lowp> lowp_i16mat3x2; + typedef mat<3, 3, int16, lowp> lowp_i16mat3x3; + typedef mat<3, 4, int16, lowp> lowp_i16mat3x4; + typedef mat<4, 2, int16, lowp> lowp_i16mat4x2; + typedef mat<4, 3, int16, lowp> lowp_i16mat4x3; + typedef mat<4, 4, int16, lowp> lowp_i16mat4x4; + + typedef mat<2, 2, int16, mediump> mediump_i16mat2x2; + typedef mat<2, 3, int16, mediump> mediump_i16mat2x3; + typedef mat<2, 4, int16, mediump> mediump_i16mat2x4; + typedef mat<3, 2, int16, mediump> mediump_i16mat3x2; + typedef mat<3, 3, int16, mediump> mediump_i16mat3x3; + typedef mat<3, 4, int16, mediump> mediump_i16mat3x4; + typedef mat<4, 2, int16, mediump> mediump_i16mat4x2; + typedef mat<4, 3, int16, mediump> mediump_i16mat4x3; + typedef mat<4, 4, int16, mediump> mediump_i16mat4x4; + + typedef mat<2, 2, int16, highp> highp_i16mat2x2; + typedef mat<2, 3, int16, highp> highp_i16mat2x3; + typedef mat<2, 4, int16, highp> highp_i16mat2x4; + typedef mat<3, 2, int16, highp> highp_i16mat3x2; + typedef mat<3, 3, int16, highp> highp_i16mat3x3; + typedef mat<3, 4, int16, highp> highp_i16mat3x4; + typedef mat<4, 2, int16, highp> highp_i16mat4x2; + typedef mat<4, 3, int16, highp> highp_i16mat4x3; + typedef mat<4, 4, int16, highp> highp_i16mat4x4; + + typedef mat<2, 2, int16, defaultp> i16mat2x2; + typedef mat<2, 3, int16, defaultp> i16mat2x3; + typedef mat<2, 4, int16, defaultp> i16mat2x4; + typedef mat<3, 2, int16, defaultp> i16mat3x2; + typedef mat<3, 3, int16, defaultp> i16mat3x3; + typedef mat<3, 4, int16, defaultp> i16mat3x4; + typedef mat<4, 2, int16, defaultp> i16mat4x2; + typedef mat<4, 3, int16, defaultp> i16mat4x3; + typedef mat<4, 4, int16, defaultp> i16mat4x4; + + + typedef mat<2, 2, int32, lowp> lowp_i32mat2x2; + typedef mat<2, 3, int32, lowp> lowp_i32mat2x3; + typedef mat<2, 4, int32, lowp> lowp_i32mat2x4; + typedef mat<3, 2, int32, lowp> lowp_i32mat3x2; + typedef mat<3, 3, int32, lowp> lowp_i32mat3x3; + typedef mat<3, 4, int32, lowp> lowp_i32mat3x4; + typedef mat<4, 2, int32, lowp> lowp_i32mat4x2; + typedef mat<4, 3, int32, lowp> lowp_i32mat4x3; + typedef mat<4, 4, int32, lowp> lowp_i32mat4x4; + + typedef mat<2, 2, int32, mediump> mediump_i32mat2x2; + typedef mat<2, 3, int32, mediump> mediump_i32mat2x3; + typedef mat<2, 4, int32, mediump> mediump_i32mat2x4; + typedef mat<3, 2, int32, mediump> mediump_i32mat3x2; + typedef mat<3, 3, int32, mediump> mediump_i32mat3x3; + typedef mat<3, 4, int32, mediump> mediump_i32mat3x4; + typedef mat<4, 2, int32, mediump> mediump_i32mat4x2; + typedef mat<4, 3, int32, mediump> mediump_i32mat4x3; + typedef mat<4, 4, int32, mediump> mediump_i32mat4x4; + + typedef mat<2, 2, int32, highp> highp_i32mat2x2; + typedef mat<2, 3, int32, highp> highp_i32mat2x3; + typedef mat<2, 4, int32, highp> highp_i32mat2x4; + typedef mat<3, 2, int32, highp> highp_i32mat3x2; + typedef mat<3, 3, int32, highp> highp_i32mat3x3; + typedef mat<3, 4, int32, highp> highp_i32mat3x4; + typedef mat<4, 2, int32, highp> highp_i32mat4x2; + typedef mat<4, 3, int32, highp> highp_i32mat4x3; + typedef mat<4, 4, int32, highp> highp_i32mat4x4; + + typedef mat<2, 2, int32, defaultp> i32mat2x2; + typedef mat<2, 3, int32, defaultp> i32mat2x3; + typedef mat<2, 4, int32, defaultp> i32mat2x4; + typedef mat<3, 2, int32, defaultp> i32mat3x2; + typedef mat<3, 3, int32, defaultp> i32mat3x3; + typedef mat<3, 4, int32, defaultp> i32mat3x4; + typedef mat<4, 2, int32, defaultp> i32mat4x2; + typedef mat<4, 3, int32, defaultp> i32mat4x3; + typedef mat<4, 4, int32, defaultp> i32mat4x4; + + + typedef mat<2, 2, int64, lowp> lowp_i64mat2x2; + typedef mat<2, 3, int64, lowp> lowp_i64mat2x3; + typedef mat<2, 4, int64, lowp> lowp_i64mat2x4; + typedef mat<3, 2, int64, lowp> lowp_i64mat3x2; + typedef mat<3, 3, int64, lowp> lowp_i64mat3x3; + typedef mat<3, 4, int64, lowp> lowp_i64mat3x4; + typedef mat<4, 2, int64, lowp> lowp_i64mat4x2; + typedef mat<4, 3, int64, lowp> lowp_i64mat4x3; + typedef mat<4, 4, int64, lowp> lowp_i64mat4x4; + + typedef mat<2, 2, int64, mediump> mediump_i64mat2x2; + typedef mat<2, 3, int64, mediump> mediump_i64mat2x3; + typedef mat<2, 4, int64, mediump> mediump_i64mat2x4; + typedef mat<3, 2, int64, mediump> mediump_i64mat3x2; + typedef mat<3, 3, int64, mediump> mediump_i64mat3x3; + typedef mat<3, 4, int64, mediump> mediump_i64mat3x4; + typedef mat<4, 2, int64, mediump> mediump_i64mat4x2; + typedef mat<4, 3, int64, mediump> mediump_i64mat4x3; + typedef mat<4, 4, int64, mediump> mediump_i64mat4x4; + + typedef mat<2, 2, int64, highp> highp_i64mat2x2; + typedef mat<2, 3, int64, highp> highp_i64mat2x3; + typedef mat<2, 4, int64, highp> highp_i64mat2x4; + typedef mat<3, 2, int64, highp> highp_i64mat3x2; + typedef mat<3, 3, int64, highp> highp_i64mat3x3; + typedef mat<3, 4, int64, highp> highp_i64mat3x4; + typedef mat<4, 2, int64, highp> highp_i64mat4x2; + typedef mat<4, 3, int64, highp> highp_i64mat4x3; + typedef mat<4, 4, int64, highp> highp_i64mat4x4; + + typedef mat<2, 2, int64, defaultp> i64mat2x2; + typedef mat<2, 3, int64, defaultp> i64mat2x3; + typedef mat<2, 4, int64, defaultp> i64mat2x4; + typedef mat<3, 2, int64, defaultp> i64mat3x2; + typedef mat<3, 3, int64, defaultp> i64mat3x3; + typedef mat<3, 4, int64, defaultp> i64mat3x4; + typedef mat<4, 2, int64, defaultp> i64mat4x2; + typedef mat<4, 3, int64, defaultp> i64mat4x3; + typedef mat<4, 4, int64, defaultp> i64mat4x4; + + + // Unsigned integer matrix MxN + + typedef mat<2, 2, uint, lowp> lowp_umat2x2; + typedef mat<2, 3, uint, lowp> lowp_umat2x3; + typedef mat<2, 4, uint, lowp> lowp_umat2x4; + typedef mat<3, 2, uint, lowp> lowp_umat3x2; + typedef mat<3, 3, uint, lowp> lowp_umat3x3; + typedef mat<3, 4, uint, lowp> lowp_umat3x4; + typedef mat<4, 2, uint, lowp> lowp_umat4x2; + typedef mat<4, 3, uint, lowp> lowp_umat4x3; + typedef mat<4, 4, uint, lowp> lowp_umat4x4; + + typedef mat<2, 2, uint, mediump> mediump_umat2x2; + typedef mat<2, 3, uint, mediump> mediump_umat2x3; + typedef mat<2, 4, uint, mediump> mediump_umat2x4; + typedef mat<3, 2, uint, mediump> mediump_umat3x2; + typedef mat<3, 3, uint, mediump> mediump_umat3x3; + typedef mat<3, 4, uint, mediump> mediump_umat3x4; + typedef mat<4, 2, uint, mediump> mediump_umat4x2; + typedef mat<4, 3, uint, mediump> mediump_umat4x3; + typedef mat<4, 4, uint, mediump> mediump_umat4x4; + + typedef mat<2, 2, uint, highp> highp_umat2x2; + typedef mat<2, 3, uint, highp> highp_umat2x3; + typedef mat<2, 4, uint, highp> highp_umat2x4; + typedef mat<3, 2, uint, highp> highp_umat3x2; + typedef mat<3, 3, uint, highp> highp_umat3x3; + typedef mat<3, 4, uint, highp> highp_umat3x4; + typedef mat<4, 2, uint, highp> highp_umat4x2; + typedef mat<4, 3, uint, highp> highp_umat4x3; + typedef mat<4, 4, uint, highp> highp_umat4x4; + + typedef mat<2, 2, uint, defaultp> umat2x2; + typedef mat<2, 3, uint, defaultp> umat2x3; + typedef mat<2, 4, uint, defaultp> umat2x4; + typedef mat<3, 2, uint, defaultp> umat3x2; + typedef mat<3, 3, uint, defaultp> umat3x3; + typedef mat<3, 4, uint, defaultp> umat3x4; + typedef mat<4, 2, uint, defaultp> umat4x2; + typedef mat<4, 3, uint, defaultp> umat4x3; + typedef mat<4, 4, uint, defaultp> umat4x4; + + + typedef mat<2, 2, uint8, lowp> lowp_u8mat2x2; + typedef mat<2, 3, uint8, lowp> lowp_u8mat2x3; + typedef mat<2, 4, uint8, lowp> lowp_u8mat2x4; + typedef mat<3, 2, uint8, lowp> lowp_u8mat3x2; + typedef mat<3, 3, uint8, lowp> lowp_u8mat3x3; + typedef mat<3, 4, uint8, lowp> lowp_u8mat3x4; + typedef mat<4, 2, uint8, lowp> lowp_u8mat4x2; + typedef mat<4, 3, uint8, lowp> lowp_u8mat4x3; + typedef mat<4, 4, uint8, lowp> lowp_u8mat4x4; + + typedef mat<2, 2, uint8, mediump> mediump_u8mat2x2; + typedef mat<2, 3, uint8, mediump> mediump_u8mat2x3; + typedef mat<2, 4, uint8, mediump> mediump_u8mat2x4; + typedef mat<3, 2, uint8, mediump> mediump_u8mat3x2; + typedef mat<3, 3, uint8, mediump> mediump_u8mat3x3; + typedef mat<3, 4, uint8, mediump> mediump_u8mat3x4; + typedef mat<4, 2, uint8, mediump> mediump_u8mat4x2; + typedef mat<4, 3, uint8, mediump> mediump_u8mat4x3; + typedef mat<4, 4, uint8, mediump> mediump_u8mat4x4; + + typedef mat<2, 2, uint8, highp> highp_u8mat2x2; + typedef mat<2, 3, uint8, highp> highp_u8mat2x3; + typedef mat<2, 4, uint8, highp> highp_u8mat2x4; + typedef mat<3, 2, uint8, highp> highp_u8mat3x2; + typedef mat<3, 3, uint8, highp> highp_u8mat3x3; + typedef mat<3, 4, uint8, highp> highp_u8mat3x4; + typedef mat<4, 2, uint8, highp> highp_u8mat4x2; + typedef mat<4, 3, uint8, highp> highp_u8mat4x3; + typedef mat<4, 4, uint8, highp> highp_u8mat4x4; + + typedef mat<2, 2, uint8, defaultp> u8mat2x2; + typedef mat<2, 3, uint8, defaultp> u8mat2x3; + typedef mat<2, 4, uint8, defaultp> u8mat2x4; + typedef mat<3, 2, uint8, defaultp> u8mat3x2; + typedef mat<3, 3, uint8, defaultp> u8mat3x3; + typedef mat<3, 4, uint8, defaultp> u8mat3x4; + typedef mat<4, 2, uint8, defaultp> u8mat4x2; + typedef mat<4, 3, uint8, defaultp> u8mat4x3; + typedef mat<4, 4, uint8, defaultp> u8mat4x4; + + + typedef mat<2, 2, uint16, lowp> lowp_u16mat2x2; + typedef mat<2, 3, uint16, lowp> lowp_u16mat2x3; + typedef mat<2, 4, uint16, lowp> lowp_u16mat2x4; + typedef mat<3, 2, uint16, lowp> lowp_u16mat3x2; + typedef mat<3, 3, uint16, lowp> lowp_u16mat3x3; + typedef mat<3, 4, uint16, lowp> lowp_u16mat3x4; + typedef mat<4, 2, uint16, lowp> lowp_u16mat4x2; + typedef mat<4, 3, uint16, lowp> lowp_u16mat4x3; + typedef mat<4, 4, uint16, lowp> lowp_u16mat4x4; + + typedef mat<2, 2, uint16, mediump> mediump_u16mat2x2; + typedef mat<2, 3, uint16, mediump> mediump_u16mat2x3; + typedef mat<2, 4, uint16, mediump> mediump_u16mat2x4; + typedef mat<3, 2, uint16, mediump> mediump_u16mat3x2; + typedef mat<3, 3, uint16, mediump> mediump_u16mat3x3; + typedef mat<3, 4, uint16, mediump> mediump_u16mat3x4; + typedef mat<4, 2, uint16, mediump> mediump_u16mat4x2; + typedef mat<4, 3, uint16, mediump> mediump_u16mat4x3; + typedef mat<4, 4, uint16, mediump> mediump_u16mat4x4; + + typedef mat<2, 2, uint16, highp> highp_u16mat2x2; + typedef mat<2, 3, uint16, highp> highp_u16mat2x3; + typedef mat<2, 4, uint16, highp> highp_u16mat2x4; + typedef mat<3, 2, uint16, highp> highp_u16mat3x2; + typedef mat<3, 3, uint16, highp> highp_u16mat3x3; + typedef mat<3, 4, uint16, highp> highp_u16mat3x4; + typedef mat<4, 2, uint16, highp> highp_u16mat4x2; + typedef mat<4, 3, uint16, highp> highp_u16mat4x3; + typedef mat<4, 4, uint16, highp> highp_u16mat4x4; + + typedef mat<2, 2, uint16, defaultp> u16mat2x2; + typedef mat<2, 3, uint16, defaultp> u16mat2x3; + typedef mat<2, 4, uint16, defaultp> u16mat2x4; + typedef mat<3, 2, uint16, defaultp> u16mat3x2; + typedef mat<3, 3, uint16, defaultp> u16mat3x3; + typedef mat<3, 4, uint16, defaultp> u16mat3x4; + typedef mat<4, 2, uint16, defaultp> u16mat4x2; + typedef mat<4, 3, uint16, defaultp> u16mat4x3; + typedef mat<4, 4, uint16, defaultp> u16mat4x4; + + + typedef mat<2, 2, uint32, lowp> lowp_u32mat2x2; + typedef mat<2, 3, uint32, lowp> lowp_u32mat2x3; + typedef mat<2, 4, uint32, lowp> lowp_u32mat2x4; + typedef mat<3, 2, uint32, lowp> lowp_u32mat3x2; + typedef mat<3, 3, uint32, lowp> lowp_u32mat3x3; + typedef mat<3, 4, uint32, lowp> lowp_u32mat3x4; + typedef mat<4, 2, uint32, lowp> lowp_u32mat4x2; + typedef mat<4, 3, uint32, lowp> lowp_u32mat4x3; + typedef mat<4, 4, uint32, lowp> lowp_u32mat4x4; + + typedef mat<2, 2, uint32, mediump> mediump_u32mat2x2; + typedef mat<2, 3, uint32, mediump> mediump_u32mat2x3; + typedef mat<2, 4, uint32, mediump> mediump_u32mat2x4; + typedef mat<3, 2, uint32, mediump> mediump_u32mat3x2; + typedef mat<3, 3, uint32, mediump> mediump_u32mat3x3; + typedef mat<3, 4, uint32, mediump> mediump_u32mat3x4; + typedef mat<4, 2, uint32, mediump> mediump_u32mat4x2; + typedef mat<4, 3, uint32, mediump> mediump_u32mat4x3; + typedef mat<4, 4, uint32, mediump> mediump_u32mat4x4; + + typedef mat<2, 2, uint32, highp> highp_u32mat2x2; + typedef mat<2, 3, uint32, highp> highp_u32mat2x3; + typedef mat<2, 4, uint32, highp> highp_u32mat2x4; + typedef mat<3, 2, uint32, highp> highp_u32mat3x2; + typedef mat<3, 3, uint32, highp> highp_u32mat3x3; + typedef mat<3, 4, uint32, highp> highp_u32mat3x4; + typedef mat<4, 2, uint32, highp> highp_u32mat4x2; + typedef mat<4, 3, uint32, highp> highp_u32mat4x3; + typedef mat<4, 4, uint32, highp> highp_u32mat4x4; + + typedef mat<2, 2, uint32, defaultp> u32mat2x2; + typedef mat<2, 3, uint32, defaultp> u32mat2x3; + typedef mat<2, 4, uint32, defaultp> u32mat2x4; + typedef mat<3, 2, uint32, defaultp> u32mat3x2; + typedef mat<3, 3, uint32, defaultp> u32mat3x3; + typedef mat<3, 4, uint32, defaultp> u32mat3x4; + typedef mat<4, 2, uint32, defaultp> u32mat4x2; + typedef mat<4, 3, uint32, defaultp> u32mat4x3; + typedef mat<4, 4, uint32, defaultp> u32mat4x4; + + + typedef mat<2, 2, uint64, lowp> lowp_u64mat2x2; + typedef mat<2, 3, uint64, lowp> lowp_u64mat2x3; + typedef mat<2, 4, uint64, lowp> lowp_u64mat2x4; + typedef mat<3, 2, uint64, lowp> lowp_u64mat3x2; + typedef mat<3, 3, uint64, lowp> lowp_u64mat3x3; + typedef mat<3, 4, uint64, lowp> lowp_u64mat3x4; + typedef mat<4, 2, uint64, lowp> lowp_u64mat4x2; + typedef mat<4, 3, uint64, lowp> lowp_u64mat4x3; + typedef mat<4, 4, uint64, lowp> lowp_u64mat4x4; + + typedef mat<2, 2, uint64, mediump> mediump_u64mat2x2; + typedef mat<2, 3, uint64, mediump> mediump_u64mat2x3; + typedef mat<2, 4, uint64, mediump> mediump_u64mat2x4; + typedef mat<3, 2, uint64, mediump> mediump_u64mat3x2; + typedef mat<3, 3, uint64, mediump> mediump_u64mat3x3; + typedef mat<3, 4, uint64, mediump> mediump_u64mat3x4; + typedef mat<4, 2, uint64, mediump> mediump_u64mat4x2; + typedef mat<4, 3, uint64, mediump> mediump_u64mat4x3; + typedef mat<4, 4, uint64, mediump> mediump_u64mat4x4; + + typedef mat<2, 2, uint64, highp> highp_u64mat2x2; + typedef mat<2, 3, uint64, highp> highp_u64mat2x3; + typedef mat<2, 4, uint64, highp> highp_u64mat2x4; + typedef mat<3, 2, uint64, highp> highp_u64mat3x2; + typedef mat<3, 3, uint64, highp> highp_u64mat3x3; + typedef mat<3, 4, uint64, highp> highp_u64mat3x4; + typedef mat<4, 2, uint64, highp> highp_u64mat4x2; + typedef mat<4, 3, uint64, highp> highp_u64mat4x3; + typedef mat<4, 4, uint64, highp> highp_u64mat4x4; + + typedef mat<2, 2, uint64, defaultp> u64mat2x2; + typedef mat<2, 3, uint64, defaultp> u64mat2x3; + typedef mat<2, 4, uint64, defaultp> u64mat2x4; + typedef mat<3, 2, uint64, defaultp> u64mat3x2; + typedef mat<3, 3, uint64, defaultp> u64mat3x3; + typedef mat<3, 4, uint64, defaultp> u64mat3x4; + typedef mat<4, 2, uint64, defaultp> u64mat4x2; + typedef mat<4, 3, uint64, defaultp> u64mat4x3; + typedef mat<4, 4, uint64, defaultp> u64mat4x4; + + // Quaternion + + typedef qua lowp_quat; + typedef qua mediump_quat; + typedef qua highp_quat; + typedef qua quat; + + typedef qua lowp_fquat; + typedef qua mediump_fquat; + typedef qua highp_fquat; + typedef qua fquat; + + typedef qua lowp_f32quat; + typedef qua mediump_f32quat; + typedef qua highp_f32quat; + typedef qua f32quat; + + typedef qua lowp_dquat; + typedef qua mediump_dquat; + typedef qua highp_dquat; + typedef qua dquat; + + typedef qua lowp_f64quat; + typedef qua mediump_f64quat; + typedef qua highp_f64quat; + typedef qua f64quat; +}//namespace glm + + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/geometric.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/geometric.hpp new file mode 100644 index 0000000..ac857e6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/geometric.hpp @@ -0,0 +1,116 @@ +/// @ref core +/// @file glm/geometric.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions +/// +/// @defgroup core_func_geometric Geometric functions +/// @ingroup core +/// +/// These operate on vectors as vectors, not component-wise. +/// +/// Include to use these core features. + +#pragma once + +#include "detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_func_geometric + /// @{ + + /// Returns the length of x, i.e., sqrt(x * x). + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL length man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL T length(vec const& x); + + /// Returns the distance between p0 and p1, i.e., length(p0 - p1). + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL distance man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL T distance(vec const& p0, vec const& p1); + + /// Returns the dot product of x and y, i.e., result = x * y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL dot man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR T dot(vec const& x, vec const& y); + + /// Returns the cross product of x and y. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL cross man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> cross(vec<3, T, Q> const& x, vec<3, T, Q> const& y); + + /// Returns a vector in the same direction as x but with length of 1. + /// According to issue 10 GLSL 1.10 specification, if length(x) == 0 then result is undefined and generate an error. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL normalize man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL vec normalize(vec const& x); + + /// If dot(Nref, I) < 0.0, return N, otherwise, return -N. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL faceforward man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL vec faceforward( + vec const& N, + vec const& I, + vec const& Nref); + + /// For the incident vector I and surface orientation N, + /// returns the reflection direction : result = I - 2.0 * dot(N, I) * N. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL reflect man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL vec reflect( + vec const& I, + vec const& N); + + /// For the incident vector I and surface normal N, + /// and the ratio of indices of refraction eta, + /// return the refraction vector. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL refract man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL vec refract( + vec const& I, + vec const& N, + T eta); + + /// @} +}//namespace glm + +#include "detail/func_geometric.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/glm.cppm b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/glm.cppm new file mode 100644 index 0000000..85e946e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/glm.cppm @@ -0,0 +1,2675 @@ +module; + +// #define GLM_GTC_INLINE_NAMESPACE to inline glm::gtc into glm +// #define GLM_EXT_INLINE_NAMESPACE to inline glm::ext into glm +// #define GLM_GTX_INLINE_NAMESPACE to inline glm::gtx into glm + +#include +#include + +export module glm; + +export namespace glm { + // Base types + using glm::qualifier; + using glm::precision; + using glm::vec; + using glm::mat; + using glm::qua; +# if GLM_HAS_TEMPLATE_ALIASES + using glm::tvec1; + using glm::tvec2; + using glm::tvec3; + using glm::tvec4; + using glm::tmat2x2; + using glm::tmat2x3; + using glm::tmat2x4; + using glm::tmat3x2; + using glm::tmat3x3; + using glm::tmat3x4; + using glm::tmat4x2; + using glm::tmat4x3; + using glm::tmat4x4; + using glm::tquat; +# endif + + using glm::int8; + using glm::int16; + using glm::int32; + using glm::int64; + using glm::uint8; + using glm::uint16; + using glm::uint32; + using glm::uint64; + using glm::lowp_i8; + using glm::mediump_i8; + using glm::highp_i8; + using glm::i8; + using glm::lowp_int8; + using glm::mediump_int8; + using glm::highp_int8; + using glm::lowp_int8_t; + using glm::mediump_int8_t; + using glm::highp_int8_t; + using glm::int8_t; + using glm::lowp_i16; + using glm::mediump_i16; + using glm::highp_i16; + using glm::i16; + using glm::lowp_int16; + using glm::mediump_int16; + using glm::highp_int16; + using glm::lowp_int16_t; + using glm::mediump_int16_t; + using glm::highp_int16_t; + using glm::int16_t; + using glm::lowp_i32; + using glm::mediump_i32; + using glm::highp_i32; + using glm::i32; + using glm::lowp_int32; + using glm::mediump_int32; + using glm::highp_int32; + using glm::lowp_int32_t; + using glm::mediump_int32_t; + using glm::highp_int32_t; + using glm::int32_t; + using glm::lowp_i64; + using glm::mediump_i64; + using glm::highp_i64; + using glm::i64; + using glm::lowp_int64; + using glm::mediump_int64; + using glm::highp_int64; + using glm::lowp_int64_t; + using glm::mediump_int64_t; + using glm::highp_int64_t; + using glm::int64_t; + using glm::uint; + using glm::lowp_u8; + using glm::mediump_u8; + using glm::highp_u8; + using glm::u8; + using glm::lowp_uint8; + using glm::mediump_uint8; + using glm::highp_uint8; + using glm::lowp_uint8_t; + using glm::mediump_uint8_t; + using glm::highp_uint8_t; + using glm::uint8_t; + using glm::lowp_u16; + using glm::mediump_u16; + using glm::highp_u16; + using glm::u16; + using glm::lowp_uint16; + using glm::mediump_uint16; + using glm::highp_uint16; + using glm::lowp_uint16_t; + using glm::mediump_uint16_t; + using glm::highp_uint16_t; + using glm::uint16_t; + using glm::lowp_u32; + using glm::mediump_u32; + using glm::highp_u32; + using glm::u32; + using glm::lowp_uint32; + using glm::mediump_uint32; + using glm::highp_uint32; + using glm::lowp_uint32_t; + using glm::mediump_uint32_t; + using glm::highp_uint32_t; + using glm::uint32_t; + using glm::lowp_u64; + using glm::mediump_u64; + using glm::highp_u64; + using glm::u64; + using glm::lowp_uint64; + using glm::mediump_uint64; + using glm::highp_uint64; + using glm::lowp_uint64_t; + using glm::mediump_uint64_t; + using glm::highp_uint64_t; + using glm::uint64_t; + using glm::lowp_f32; + using glm::mediump_f32; + using glm::highp_f32; + using glm::f32; + using glm::lowp_float32; + using glm::mediump_float32; + using glm::highp_float32; + using glm::float32; + using glm::lowp_float32_t; + using glm::mediump_float32_t; + using glm::highp_float32_t; + using glm::float32_t; + using glm::lowp_f64; + using glm::mediump_f64; + using glm::highp_f64; + using glm::f64; + using glm::lowp_float64; + using glm::mediump_float64; + using glm::highp_float64; + using glm::float64; + using glm::lowp_float64_t; + using glm::mediump_float64_t; + using glm::highp_float64_t; + using glm::float64_t; + using glm::lowp_bvec1; + using glm::lowp_bvec2; + using glm::lowp_bvec3; + using glm::lowp_bvec4; + using glm::mediump_bvec1; + using glm::mediump_bvec2; + using glm::mediump_bvec3; + using glm::mediump_bvec4; + using glm::highp_bvec1; + using glm::highp_bvec2; + using glm::highp_bvec3; + using glm::highp_bvec4; + using glm::bvec1; + using glm::bvec2; + using glm::bvec3; + using glm::bvec4; + using glm::lowp_ivec1; + using glm::lowp_ivec2; + using glm::lowp_ivec3; + using glm::lowp_ivec4; + using glm::mediump_ivec1; + using glm::mediump_ivec2; + using glm::mediump_ivec3; + using glm::mediump_ivec4; + using glm::highp_ivec1; + using glm::highp_ivec2; + using glm::highp_ivec3; + using glm::highp_ivec4; + using glm::ivec1; + using glm::ivec2; + using glm::ivec3; + using glm::ivec4; + using glm::lowp_i8vec1; + using glm::lowp_i8vec2; + using glm::lowp_i8vec3; + using glm::lowp_i8vec4; + using glm::mediump_i8vec1; + using glm::mediump_i8vec2; + using glm::mediump_i8vec3; + using glm::mediump_i8vec4; + using glm::highp_i8vec1; + using glm::highp_i8vec2; + using glm::highp_i8vec3; + using glm::highp_i8vec4; + using glm::i8vec1; + using glm::i8vec2; + using glm::i8vec3; + using glm::i8vec4; + using glm::lowp_i16vec1; + using glm::lowp_i16vec2; + using glm::lowp_i16vec3; + using glm::lowp_i16vec4; + using glm::mediump_i16vec1; + using glm::mediump_i16vec2; + using glm::mediump_i16vec3; + using glm::mediump_i16vec4; + using glm::highp_i16vec1; + using glm::highp_i16vec2; + using glm::highp_i16vec3; + using glm::highp_i16vec4; + using glm::i16vec1; + using glm::i16vec2; + using glm::i16vec3; + using glm::i16vec4; + using glm::lowp_i32vec1; + using glm::lowp_i32vec2; + using glm::lowp_i32vec3; + using glm::lowp_i32vec4; + using glm::mediump_i32vec1; + using glm::mediump_i32vec2; + using glm::mediump_i32vec3; + using glm::mediump_i32vec4; + using glm::highp_i32vec1; + using glm::highp_i32vec2; + using glm::highp_i32vec3; + using glm::highp_i32vec4; + using glm::i32vec1; + using glm::i32vec2; + using glm::i32vec3; + using glm::i32vec4; + using glm::lowp_i64vec1; + using glm::lowp_i64vec2; + using glm::lowp_i64vec3; + using glm::lowp_i64vec4; + using glm::mediump_i64vec1; + using glm::mediump_i64vec2; + using glm::mediump_i64vec3; + using glm::mediump_i64vec4; + using glm::highp_i64vec1; + using glm::highp_i64vec2; + using glm::highp_i64vec3; + using glm::highp_i64vec4; + using glm::i64vec1; + using glm::i64vec2; + using glm::i64vec3; + using glm::i64vec4; + using glm::lowp_uvec1; + using glm::lowp_uvec2; + using glm::lowp_uvec3; + using glm::lowp_uvec4; + using glm::mediump_uvec1; + using glm::mediump_uvec2; + using glm::mediump_uvec3; + using glm::mediump_uvec4; + using glm::highp_uvec1; + using glm::highp_uvec2; + using glm::highp_uvec3; + using glm::highp_uvec4; + using glm::uvec1; + using glm::uvec2; + using glm::uvec3; + using glm::uvec4; + using glm::lowp_u8vec1; + using glm::lowp_u8vec2; + using glm::lowp_u8vec3; + using glm::lowp_u8vec4; + using glm::mediump_u8vec1; + using glm::mediump_u8vec2; + using glm::mediump_u8vec3; + using glm::mediump_u8vec4; + using glm::highp_u8vec1; + using glm::highp_u8vec2; + using glm::highp_u8vec3; + using glm::highp_u8vec4; + using glm::u8vec1; + using glm::u8vec2; + using glm::u8vec3; + using glm::u8vec4; + using glm::lowp_u16vec1; + using glm::lowp_u16vec2; + using glm::lowp_u16vec3; + using glm::lowp_u16vec4; + using glm::mediump_u16vec1; + using glm::mediump_u16vec2; + using glm::mediump_u16vec3; + using glm::mediump_u16vec4; + using glm::highp_u16vec1; + using glm::highp_u16vec2; + using glm::highp_u16vec3; + using glm::highp_u16vec4; + using glm::u16vec1; + using glm::u16vec2; + using glm::u16vec3; + using glm::u16vec4; + using glm::lowp_u32vec1; + using glm::lowp_u32vec2; + using glm::lowp_u32vec3; + using glm::lowp_u32vec4; + using glm::mediump_u32vec1; + using glm::mediump_u32vec2; + using glm::mediump_u32vec3; + using glm::mediump_u32vec4; + using glm::highp_u32vec1; + using glm::highp_u32vec2; + using glm::highp_u32vec3; + using glm::highp_u32vec4; + using glm::u32vec1; + using glm::u32vec2; + using glm::u32vec3; + using glm::u32vec4; + using glm::lowp_u64vec1; + using glm::lowp_u64vec2; + using glm::lowp_u64vec3; + using glm::lowp_u64vec4; + using glm::mediump_u64vec1; + using glm::mediump_u64vec2; + using glm::mediump_u64vec3; + using glm::mediump_u64vec4; + using glm::highp_u64vec1; + using glm::highp_u64vec2; + using glm::highp_u64vec3; + using glm::highp_u64vec4; + using glm::u64vec1; + using glm::u64vec2; + using glm::u64vec3; + using glm::u64vec4; + using glm::lowp_vec1; + using glm::lowp_vec2; + using glm::lowp_vec3; + using glm::lowp_vec4; + using glm::mediump_vec1; + using glm::mediump_vec2; + using glm::mediump_vec3; + using glm::mediump_vec4; + using glm::highp_vec1; + using glm::highp_vec2; + using glm::highp_vec3; + using glm::highp_vec4; + using glm::vec1; + using glm::vec2; + using glm::vec3; + using glm::vec4; + using glm::lowp_fvec1; + using glm::lowp_fvec2; + using glm::lowp_fvec3; + using glm::lowp_fvec4; + using glm::mediump_fvec1; + using glm::mediump_fvec2; + using glm::mediump_fvec3; + using glm::mediump_fvec4; + using glm::highp_fvec1; + using glm::highp_fvec2; + using glm::highp_fvec3; + using glm::highp_fvec4; + using glm::fvec1; + using glm::fvec2; + using glm::fvec3; + using glm::fvec4; + using glm::lowp_f32vec1; + using glm::lowp_f32vec2; + using glm::lowp_f32vec3; + using glm::lowp_f32vec4; + using glm::mediump_f32vec1; + using glm::mediump_f32vec2; + using glm::mediump_f32vec3; + using glm::mediump_f32vec4; + using glm::highp_f32vec1; + using glm::highp_f32vec2; + using glm::highp_f32vec3; + using glm::highp_f32vec4; + using glm::f32vec1; + using glm::f32vec2; + using glm::f32vec3; + using glm::f32vec4; + using glm::lowp_dvec1; + using glm::lowp_dvec2; + using glm::lowp_dvec3; + using glm::lowp_dvec4; + using glm::mediump_dvec1; + using glm::mediump_dvec2; + using glm::mediump_dvec3; + using glm::mediump_dvec4; + using glm::highp_dvec1; + using glm::highp_dvec2; + using glm::highp_dvec3; + using glm::highp_dvec4; + using glm::dvec1; + using glm::dvec2; + using glm::dvec3; + using glm::dvec4; + using glm::lowp_f64vec1; + using glm::lowp_f64vec2; + using glm::lowp_f64vec3; + using glm::lowp_f64vec4; + using glm::mediump_f64vec1; + using glm::mediump_f64vec2; + using glm::mediump_f64vec3; + using glm::mediump_f64vec4; + using glm::highp_f64vec1; + using glm::highp_f64vec2; + using glm::highp_f64vec3; + using glm::highp_f64vec4; + using glm::f64vec1; + using glm::f64vec2; + using glm::f64vec3; + using glm::f64vec4; + using glm::lowp_mat2; + using glm::lowp_mat3; + using glm::lowp_mat4; + using glm::mediump_mat2; + using glm::mediump_mat3; + using glm::mediump_mat4; + using glm::highp_mat2; + using glm::highp_mat3; + using glm::highp_mat4; + using glm::mat2; + using glm::mat3; + using glm::mat4; + using glm::lowp_fmat2; + using glm::lowp_fmat3; + using glm::lowp_fmat4; + using glm::mediump_fmat2; + using glm::mediump_fmat3; + using glm::mediump_fmat4; + using glm::highp_fmat2; + using glm::highp_fmat3; + using glm::highp_fmat4; + using glm::fmat2; + using glm::fmat3; + using glm::fmat4; + using glm::lowp_f32mat2; + using glm::lowp_f32mat3; + using glm::lowp_f32mat4; + using glm::mediump_f32mat2; + using glm::mediump_f32mat3; + using glm::mediump_f32mat4; + using glm::highp_f32mat2; + using glm::highp_f32mat3; + using glm::highp_f32mat4; + using glm::f32mat2; + using glm::f32mat3; + using glm::f32mat4; + using glm::lowp_dmat2; + using glm::lowp_dmat3; + using glm::lowp_dmat4; + using glm::mediump_dmat2; + using glm::mediump_dmat3; + using glm::mediump_dmat4; + using glm::highp_dmat2; + using glm::highp_dmat3; + using glm::highp_dmat4; + using glm::dmat2; + using glm::dmat3; + using glm::dmat4; + using glm::lowp_f64mat2; + using glm::lowp_f64mat3; + using glm::lowp_f64mat4; + using glm::mediump_f64mat2; + using glm::mediump_f64mat3; + using glm::mediump_f64mat4; + using glm::highp_f64mat2; + using glm::highp_f64mat3; + using glm::highp_f64mat4; + using glm::f64mat2; + using glm::f64mat3; + using glm::f64mat4; + using glm::lowp_mat2x2; + using glm::lowp_mat2x3; + using glm::lowp_mat2x4; + using glm::lowp_mat3x2; + using glm::lowp_mat3x3; + using glm::lowp_mat3x4; + using glm::lowp_mat4x2; + using glm::lowp_mat4x3; + using glm::lowp_mat4x4; + using glm::mediump_mat2x2; + using glm::mediump_mat2x3; + using glm::mediump_mat2x4; + using glm::mediump_mat3x2; + using glm::mediump_mat3x3; + using glm::mediump_mat3x4; + using glm::mediump_mat4x2; + using glm::mediump_mat4x3; + using glm::mediump_mat4x4; + using glm::highp_mat2x2; + using glm::highp_mat2x3; + using glm::highp_mat2x4; + using glm::highp_mat3x2; + using glm::highp_mat3x3; + using glm::highp_mat3x4; + using glm::highp_mat4x2; + using glm::highp_mat4x3; + using glm::highp_mat4x4; + using glm::mat2x2; + using glm::mat2x3; + using glm::mat2x4; + using glm::mat3x2; + using glm::mat3x3; + using glm::mat3x4; + using glm::mat4x2; + using glm::mat4x3; + using glm::mat4x4; + using glm::lowp_fmat2x2; + using glm::lowp_fmat2x3; + using glm::lowp_fmat2x4; + using glm::lowp_fmat3x2; + using glm::lowp_fmat3x3; + using glm::lowp_fmat3x4; + using glm::lowp_fmat4x2; + using glm::lowp_fmat4x3; + using glm::lowp_fmat4x4; + using glm::mediump_fmat2x2; + using glm::mediump_fmat2x3; + using glm::mediump_fmat2x4; + using glm::mediump_fmat3x2; + using glm::mediump_fmat3x3; + using glm::mediump_fmat3x4; + using glm::mediump_fmat4x2; + using glm::mediump_fmat4x3; + using glm::mediump_fmat4x4; + using glm::highp_fmat2x2; + using glm::highp_fmat2x3; + using glm::highp_fmat2x4; + using glm::highp_fmat3x2; + using glm::highp_fmat3x3; + using glm::highp_fmat3x4; + using glm::highp_fmat4x2; + using glm::highp_fmat4x3; + using glm::highp_fmat4x4; + using glm::fmat2x2; + using glm::fmat2x3; + using glm::fmat2x4; + using glm::fmat3x2; + using glm::fmat3x3; + using glm::fmat3x4; + using glm::fmat4x2; + using glm::fmat4x3; + using glm::fmat4x4; + using glm::lowp_f32mat2x2; + using glm::lowp_f32mat2x3; + using glm::lowp_f32mat2x4; + using glm::lowp_f32mat3x2; + using glm::lowp_f32mat3x3; + using glm::lowp_f32mat3x4; + using glm::lowp_f32mat4x2; + using glm::lowp_f32mat4x3; + using glm::lowp_f32mat4x4; + + using glm::mediump_f32mat2x2; + using glm::mediump_f32mat2x3; + using glm::mediump_f32mat2x4; + using glm::mediump_f32mat3x2; + using glm::mediump_f32mat3x3; + using glm::mediump_f32mat3x4; + using glm::mediump_f32mat4x2; + using glm::mediump_f32mat4x3; + using glm::mediump_f32mat4x4; + using glm::highp_f32mat2x2; + using glm::highp_f32mat2x3; + using glm::highp_f32mat2x4; + using glm::highp_f32mat3x2; + using glm::highp_f32mat3x3; + using glm::highp_f32mat3x4; + using glm::highp_f32mat4x2; + using glm::highp_f32mat4x3; + using glm::highp_f32mat4x4; + using glm::f32mat2x2; + using glm::f32mat2x3; + using glm::f32mat2x4; + using glm::f32mat3x2; + using glm::f32mat3x3; + using glm::f32mat3x4; + using glm::f32mat4x2; + using glm::f32mat4x3; + using glm::f32mat4x4; + using glm::lowp_dmat2x2; + using glm::lowp_dmat2x3; + using glm::lowp_dmat2x4; + using glm::lowp_dmat3x2; + using glm::lowp_dmat3x3; + using glm::lowp_dmat3x4; + using glm::lowp_dmat4x2; + using glm::lowp_dmat4x3; + using glm::lowp_dmat4x4; + using glm::mediump_dmat2x2; + using glm::mediump_dmat2x3; + using glm::mediump_dmat2x4; + using glm::mediump_dmat3x2; + using glm::mediump_dmat3x3; + using glm::mediump_dmat3x4; + using glm::mediump_dmat4x2; + using glm::mediump_dmat4x3; + using glm::mediump_dmat4x4; + using glm::highp_dmat2x2; + using glm::highp_dmat2x3; + using glm::highp_dmat2x4; + using glm::highp_dmat3x2; + using glm::highp_dmat3x3; + using glm::highp_dmat3x4; + using glm::highp_dmat4x2; + using glm::highp_dmat4x3; + using glm::highp_dmat4x4; + using glm::dmat2x2; + using glm::dmat2x3; + using glm::dmat2x4; + using glm::dmat3x2; + using glm::dmat3x3; + using glm::dmat3x4; + using glm::dmat4x2; + using glm::dmat4x3; + using glm::dmat4x4; + using glm::lowp_f64mat2x2; + using glm::lowp_f64mat2x3; + using glm::lowp_f64mat2x4; + using glm::lowp_f64mat3x2; + using glm::lowp_f64mat3x3; + using glm::lowp_f64mat3x4; + using glm::lowp_f64mat4x2; + using glm::lowp_f64mat4x3; + using glm::lowp_f64mat4x4; + using glm::mediump_f64mat2x2; + using glm::mediump_f64mat2x3; + using glm::mediump_f64mat2x4; + using glm::mediump_f64mat3x2; + using glm::mediump_f64mat3x3; + using glm::mediump_f64mat3x4; + using glm::mediump_f64mat4x2; + using glm::mediump_f64mat4x3; + using glm::mediump_f64mat4x4; + using glm::highp_f64mat2x2; + using glm::highp_f64mat2x3; + using glm::highp_f64mat2x4; + using glm::highp_f64mat3x2; + using glm::highp_f64mat3x3; + using glm::highp_f64mat3x4; + using glm::highp_f64mat4x2; + using glm::highp_f64mat4x3; + using glm::highp_f64mat4x4; + using glm::f64mat2x2; + using glm::f64mat2x3; + using glm::f64mat2x4; + using glm::f64mat3x2; + using glm::f64mat3x3; + using glm::f64mat3x4; + using glm::f64mat4x2; + using glm::f64mat4x3; + using glm::f64mat4x4; + using glm::lowp_imat2x2; + using glm::lowp_imat2x3; + using glm::lowp_imat2x4; + using glm::lowp_imat3x2; + using glm::lowp_imat3x3; + using glm::lowp_imat3x4; + using glm::lowp_imat4x2; + using glm::lowp_imat4x3; + using glm::lowp_imat4x4; + using glm::mediump_imat2x2; + using glm::mediump_imat2x3; + using glm::mediump_imat2x4; + using glm::mediump_imat3x2; + using glm::mediump_imat3x3; + using glm::mediump_imat3x4; + using glm::mediump_imat4x2; + using glm::mediump_imat4x3; + using glm::mediump_imat4x4; + using glm::highp_imat2x2; + using glm::highp_imat2x3; + using glm::highp_imat2x4; + using glm::highp_imat3x2; + using glm::highp_imat3x3; + using glm::highp_imat3x4; + using glm::highp_imat4x2; + using glm::highp_imat4x3; + using glm::highp_imat4x4; + using glm::imat2x2; + using glm::imat2x3; + using glm::imat2x4; + using glm::imat3x2; + using glm::imat3x3; + using glm::imat3x4; + using glm::imat4x2; + using glm::imat4x3; + using glm::imat4x4; + using glm::lowp_i8mat2x2; + using glm::lowp_i8mat2x3; + using glm::lowp_i8mat2x4; + using glm::lowp_i8mat3x2; + using glm::lowp_i8mat3x3; + using glm::lowp_i8mat3x4; + using glm::lowp_i8mat4x2; + using glm::lowp_i8mat4x3; + using glm::lowp_i8mat4x4; + using glm::mediump_i8mat2x2; + using glm::mediump_i8mat2x3; + using glm::mediump_i8mat2x4; + using glm::mediump_i8mat3x2; + using glm::mediump_i8mat3x3; + using glm::mediump_i8mat3x4; + using glm::mediump_i8mat4x2; + using glm::mediump_i8mat4x3; + using glm::mediump_i8mat4x4; + using glm::highp_i8mat2x2; + using glm::highp_i8mat2x3; + using glm::highp_i8mat2x4; + using glm::highp_i8mat3x2; + using glm::highp_i8mat3x3; + using glm::highp_i8mat3x4; + using glm::highp_i8mat4x2; + using glm::highp_i8mat4x3; + using glm::highp_i8mat4x4; + using glm::i8mat2x2; + using glm::i8mat2x3; + using glm::i8mat2x4; + using glm::i8mat3x2; + using glm::i8mat3x3; + using glm::i8mat3x4; + using glm::i8mat4x2; + using glm::i8mat4x3; + using glm::i8mat4x4; + using glm::lowp_i16mat2x2; + using glm::lowp_i16mat2x3; + using glm::lowp_i16mat2x4; + using glm::lowp_i16mat3x2; + using glm::lowp_i16mat3x3; + using glm::lowp_i16mat3x4; + using glm::lowp_i16mat4x2; + using glm::lowp_i16mat4x3; + using glm::lowp_i16mat4x4; + using glm::mediump_i16mat2x2; + using glm::mediump_i16mat2x3; + using glm::mediump_i16mat2x4; + using glm::mediump_i16mat3x2; + using glm::mediump_i16mat3x3; + using glm::mediump_i16mat3x4; + using glm::mediump_i16mat4x2; + using glm::mediump_i16mat4x3; + using glm::mediump_i16mat4x4; + using glm::highp_i16mat2x2; + using glm::highp_i16mat2x3; + using glm::highp_i16mat2x4; + using glm::highp_i16mat3x2; + using glm::highp_i16mat3x3; + using glm::highp_i16mat3x4; + using glm::highp_i16mat4x2; + using glm::highp_i16mat4x3; + using glm::highp_i16mat4x4; + using glm::i16mat2x2; + using glm::i16mat2x3; + using glm::i16mat2x4; + using glm::i16mat3x2; + using glm::i16mat3x3; + using glm::i16mat3x4; + using glm::i16mat4x2; + using glm::i16mat4x3; + using glm::i16mat4x4; + using glm::lowp_i32mat2x2; + using glm::lowp_i32mat2x3; + using glm::lowp_i32mat2x4; + using glm::lowp_i32mat3x2; + using glm::lowp_i32mat3x3; + using glm::lowp_i32mat3x4; + using glm::lowp_i32mat4x2; + using glm::lowp_i32mat4x3; + using glm::lowp_i32mat4x4; + using glm::mediump_i32mat2x2; + using glm::mediump_i32mat2x3; + using glm::mediump_i32mat2x4; + using glm::mediump_i32mat3x2; + using glm::mediump_i32mat3x3; + using glm::mediump_i32mat3x4; + using glm::mediump_i32mat4x2; + using glm::mediump_i32mat4x3; + using glm::mediump_i32mat4x4; + using glm::highp_i32mat2x2; + using glm::highp_i32mat2x3; + using glm::highp_i32mat2x4; + using glm::highp_i32mat3x2; + using glm::highp_i32mat3x3; + using glm::highp_i32mat3x4; + using glm::highp_i32mat4x2; + using glm::highp_i32mat4x3; + using glm::highp_i32mat4x4; + using glm::i32mat2x2; + using glm::i32mat2x3; + using glm::i32mat2x4; + using glm::i32mat3x2; + using glm::i32mat3x3; + using glm::i32mat3x4; + using glm::i32mat4x2; + using glm::i32mat4x3; + using glm::i32mat4x4; + using glm::lowp_i64mat2x2; + using glm::lowp_i64mat2x3; + using glm::lowp_i64mat2x4; + using glm::lowp_i64mat3x2; + using glm::lowp_i64mat3x3; + using glm::lowp_i64mat3x4; + using glm::lowp_i64mat4x2; + using glm::lowp_i64mat4x3; + using glm::lowp_i64mat4x4; + using glm::mediump_i64mat2x2; + using glm::mediump_i64mat2x3; + using glm::mediump_i64mat2x4; + using glm::mediump_i64mat3x2; + using glm::mediump_i64mat3x3; + using glm::mediump_i64mat3x4; + using glm::mediump_i64mat4x2; + using glm::mediump_i64mat4x3; + using glm::mediump_i64mat4x4; + using glm::highp_i64mat2x2; + using glm::highp_i64mat2x3; + using glm::highp_i64mat2x4; + using glm::highp_i64mat3x2; + using glm::highp_i64mat3x3; + using glm::highp_i64mat3x4; + using glm::highp_i64mat4x2; + using glm::highp_i64mat4x3; + using glm::highp_i64mat4x4; + using glm::i64mat2x2; + using glm::i64mat2x3; + using glm::i64mat2x4; + using glm::i64mat3x2; + using glm::i64mat3x3; + using glm::i64mat3x4; + using glm::i64mat4x2; + using glm::i64mat4x3; + using glm::i64mat4x4; + using glm::lowp_umat2x2; + using glm::lowp_umat2x3; + using glm::lowp_umat2x4; + using glm::lowp_umat3x2; + using glm::lowp_umat3x3; + using glm::lowp_umat3x4; + using glm::lowp_umat4x2; + using glm::lowp_umat4x3; + using glm::lowp_umat4x4; + using glm::mediump_umat2x2; + using glm::mediump_umat2x3; + using glm::mediump_umat2x4; + using glm::mediump_umat3x2; + using glm::mediump_umat3x3; + using glm::mediump_umat3x4; + using glm::mediump_umat4x2; + using glm::mediump_umat4x3; + using glm::mediump_umat4x4; + using glm::highp_umat2x2; + using glm::highp_umat2x3; + using glm::highp_umat2x4; + using glm::highp_umat3x2; + using glm::highp_umat3x3; + using glm::highp_umat3x4; + using glm::highp_umat4x2; + using glm::highp_umat4x3; + using glm::highp_umat4x4; + using glm::umat2x2; + using glm::umat2x3; + using glm::umat2x4; + using glm::umat3x2; + using glm::umat3x3; + using glm::umat3x4; + using glm::umat4x2; + using glm::umat4x3; + using glm::umat4x4; + using glm::lowp_u8mat2x2; + using glm::lowp_u8mat2x3; + using glm::lowp_u8mat2x4; + using glm::lowp_u8mat3x2; + using glm::lowp_u8mat3x3; + using glm::lowp_u8mat3x4; + using glm::lowp_u8mat4x2; + using glm::lowp_u8mat4x3; + using glm::lowp_u8mat4x4; + using glm::mediump_u8mat2x2; + using glm::mediump_u8mat2x3; + using glm::mediump_u8mat2x4; + using glm::mediump_u8mat3x2; + using glm::mediump_u8mat3x3; + using glm::mediump_u8mat3x4; + using glm::mediump_u8mat4x2; + using glm::mediump_u8mat4x3; + using glm::mediump_u8mat4x4; + using glm::highp_u8mat2x2; + using glm::highp_u8mat2x3; + using glm::highp_u8mat2x4; + using glm::highp_u8mat3x2; + using glm::highp_u8mat3x3; + using glm::highp_u8mat3x4; + using glm::highp_u8mat4x2; + using glm::highp_u8mat4x3; + using glm::highp_u8mat4x4; + using glm::u8mat2x2; + using glm::u8mat2x3; + using glm::u8mat2x4; + using glm::u8mat3x2; + using glm::u8mat3x3; + using glm::u8mat3x4; + using glm::u8mat4x2; + using glm::u8mat4x3; + using glm::u8mat4x4; + using glm::lowp_u16mat2x2; + using glm::lowp_u16mat2x3; + using glm::lowp_u16mat2x4; + using glm::lowp_u16mat3x2; + using glm::lowp_u16mat3x3; + using glm::lowp_u16mat3x4; + using glm::lowp_u16mat4x2; + using glm::lowp_u16mat4x3; + using glm::lowp_u16mat4x4; + using glm::mediump_u16mat2x2; + using glm::mediump_u16mat2x3; + using glm::mediump_u16mat2x4; + using glm::mediump_u16mat3x2; + using glm::mediump_u16mat3x3; + using glm::mediump_u16mat3x4; + using glm::mediump_u16mat4x2; + using glm::mediump_u16mat4x3; + using glm::mediump_u16mat4x4; + using glm::highp_u16mat2x2; + using glm::highp_u16mat2x3; + using glm::highp_u16mat2x4; + using glm::highp_u16mat3x2; + using glm::highp_u16mat3x3; + using glm::highp_u16mat3x4; + using glm::highp_u16mat4x2; + using glm::highp_u16mat4x3; + using glm::highp_u16mat4x4; + using glm::u16mat2x2; + using glm::u16mat2x3; + using glm::u16mat2x4; + using glm::u16mat3x2; + using glm::u16mat3x3; + using glm::u16mat3x4; + using glm::u16mat4x2; + using glm::u16mat4x3; + using glm::u16mat4x4; + using glm::lowp_u32mat2x2; + using glm::lowp_u32mat2x3; + using glm::lowp_u32mat2x4; + using glm::lowp_u32mat3x2; + using glm::lowp_u32mat3x3; + using glm::lowp_u32mat3x4; + using glm::lowp_u32mat4x2; + using glm::lowp_u32mat4x3; + using glm::lowp_u32mat4x4; + using glm::mediump_u32mat2x2; + using glm::mediump_u32mat2x3; + using glm::mediump_u32mat2x4; + using glm::mediump_u32mat3x2; + using glm::mediump_u32mat3x3; + using glm::mediump_u32mat3x4; + using glm::mediump_u32mat4x2; + using glm::mediump_u32mat4x3; + using glm::mediump_u32mat4x4; + using glm::highp_u32mat2x2; + using glm::highp_u32mat2x3; + using glm::highp_u32mat2x4; + using glm::highp_u32mat3x2; + using glm::highp_u32mat3x3; + using glm::highp_u32mat3x4; + using glm::highp_u32mat4x2; + using glm::highp_u32mat4x3; + using glm::highp_u32mat4x4; + using glm::u32mat2x2; + using glm::u32mat2x3; + using glm::u32mat2x4; + using glm::u32mat3x2; + using glm::u32mat3x3; + using glm::u32mat3x4; + using glm::u32mat4x2; + using glm::u32mat4x3; + using glm::u32mat4x4; + using glm::lowp_u64mat2x2; + using glm::lowp_u64mat2x3; + using glm::lowp_u64mat2x4; + using glm::lowp_u64mat3x2; + using glm::lowp_u64mat3x3; + using glm::lowp_u64mat3x4; + using glm::lowp_u64mat4x2; + using glm::lowp_u64mat4x3; + using glm::lowp_u64mat4x4; + using glm::mediump_u64mat2x2; + using glm::mediump_u64mat2x3; + using glm::mediump_u64mat2x4; + using glm::mediump_u64mat3x2; + using glm::mediump_u64mat3x3; + using glm::mediump_u64mat3x4; + using glm::mediump_u64mat4x2; + using glm::mediump_u64mat4x3; + using glm::mediump_u64mat4x4; + using glm::highp_u64mat2x2; + using glm::highp_u64mat2x3; + using glm::highp_u64mat2x4; + using glm::highp_u64mat3x2; + using glm::highp_u64mat3x3; + using glm::highp_u64mat3x4; + using glm::highp_u64mat4x2; + using glm::highp_u64mat4x3; + using glm::highp_u64mat4x4; + using glm::u64mat2x2; + using glm::u64mat2x3; + using glm::u64mat2x4; + using glm::u64mat3x2; + using glm::u64mat3x3; + using glm::u64mat3x4; + using glm::u64mat4x2; + using glm::u64mat4x3; + using glm::u64mat4x4; + using glm::lowp_quat; + using glm::mediump_quat; + using glm::highp_quat; + using glm::quat; + using glm::lowp_fquat; + using glm::mediump_fquat; + using glm::highp_fquat; + using glm::fquat; + using glm::lowp_f32quat; + using glm::mediump_f32quat; + using glm::highp_f32quat; + using glm::f32quat; + using glm::lowp_dquat; + using glm::mediump_dquat; + using glm::highp_dquat; + using glm::dquat; + using glm::lowp_f64quat; + using glm::mediump_f64quat; + using glm::highp_f64quat; + using glm::f64quat; + + // Operators + using glm::operator+; + using glm::operator-; + using glm::operator*; + using glm::operator/; + using glm::operator%; + using glm::operator^; + using glm::operator&; + using glm::operator|; + using glm::operator~; + using glm::operator<<; + using glm::operator>>; + using glm::operator==; + using glm::operator!=; + using glm::operator&&; + using glm::operator||; + + // Core functions + using glm::abs; + using glm::acos; + using glm::acosh; + using glm::all; + using glm::any; + using glm::asin; + using glm::asinh; + using glm::atan; + using glm::atanh; + using glm::bitCount; + using glm::bitfieldExtract; + using glm::bitfieldInsert; + using glm::bitfieldReverse; + using glm::ceil; + using glm::clamp; + using glm::cos; + using glm::cosh; + using glm::cross; + using glm::degrees; + using glm::determinant; + using glm::distance; + using glm::dot; + using glm::equal; + using glm::exp; + using glm::exp2; + using glm::faceforward; + using glm::findLSB; + using glm::findMSB; + using glm::floatBitsToInt; + using glm::floatBitsToUint; + using glm::floor; + using glm::fma; + using glm::fract; + using glm::frexp; + using glm::greaterThan; + using glm::greaterThanEqual; + using glm::imulExtended; + using glm::intBitsToFloat; + using glm::inverse; + using glm::inversesqrt; + using glm::isinf; + using glm::isnan; + using glm::ldexp; + using glm::length; + using glm::lessThan; + using glm::lessThanEqual; + using glm::log; + using glm::log2; + using glm::matrixCompMult; + using glm::max; + using glm::min; + using glm::mix; + using glm::mod; + using glm::modf; + using glm::normalize; + using glm::notEqual; + using glm::not_; + using glm::outerProduct; + using glm::packDouble2x32; + using glm::packHalf2x16; + using glm::packSnorm2x16; + using glm::packSnorm4x8; + using glm::packUnorm2x16; + using glm::packUnorm4x8; + using glm::pow; + using glm::radians; + using glm::reflect; + using glm::refract; + using glm::round; + using glm::roundEven; + using glm::sign; + using glm::sin; + using glm::sinh; + using glm::smoothstep; + using glm::sqrt; + using glm::step; + using glm::tan; + using glm::tanh; + using glm::transpose; + using glm::trunc; + using glm::uaddCarry; + using glm::uintBitsToFloat; + using glm::umulExtended; + using glm::unpackDouble2x32; + using glm::unpackHalf2x16; + using glm::unpackSnorm2x16; + using glm::unpackSnorm4x8; + using glm::unpackUnorm2x16; + using glm::unpackUnorm4x8; + using glm::usubBorrow; + +# ifdef GLM_GTC_INLINE_NAMESPACE + inline +# endif + namespace gtc { +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + using glm::aligned_highp_vec1; + using glm::aligned_mediump_vec1; + using glm::aligned_lowp_vec1; + using glm::aligned_highp_dvec1; + using glm::aligned_mediump_dvec1; + using glm::aligned_lowp_dvec1; + using glm::aligned_highp_ivec1; + using glm::aligned_mediump_ivec1; + using glm::aligned_lowp_ivec1; + using glm::aligned_highp_uvec1; + using glm::aligned_mediump_uvec1; + using glm::aligned_lowp_uvec1; + using glm::aligned_highp_bvec1; + using glm::aligned_mediump_bvec1; + using glm::aligned_lowp_bvec1; + using glm::packed_highp_vec1; + using glm::packed_mediump_vec1; + using glm::packed_lowp_vec1; + using glm::packed_highp_dvec1; + using glm::packed_mediump_dvec1; + using glm::packed_lowp_dvec1; + using glm::packed_highp_ivec1; + using glm::packed_mediump_ivec1; + using glm::packed_lowp_ivec1; + using glm::packed_highp_uvec1; + using glm::packed_mediump_uvec1; + using glm::packed_lowp_uvec1; + using glm::packed_highp_bvec1; + using glm::packed_mediump_bvec1; + using glm::packed_lowp_bvec1; + using glm::aligned_highp_vec2; + using glm::aligned_mediump_vec2; + using glm::aligned_lowp_vec2; + using glm::aligned_highp_dvec2; + using glm::aligned_mediump_dvec2; + using glm::aligned_lowp_dvec2; + using glm::aligned_highp_ivec2; + using glm::aligned_mediump_ivec2; + using glm::aligned_lowp_ivec2; + using glm::aligned_highp_uvec2; + using glm::aligned_mediump_uvec2; + using glm::aligned_lowp_uvec2; + using glm::aligned_highp_bvec2; + using glm::aligned_mediump_bvec2; + using glm::aligned_lowp_bvec2; + using glm::packed_highp_vec2; + using glm::packed_mediump_vec2; + using glm::packed_lowp_vec2; + using glm::packed_highp_dvec2; + using glm::packed_mediump_dvec2; + using glm::packed_lowp_dvec2; + using glm::packed_highp_ivec2; + using glm::packed_mediump_ivec2; + using glm::packed_lowp_ivec2; + using glm::packed_highp_uvec2; + using glm::packed_mediump_uvec2; + using glm::packed_lowp_uvec2; + using glm::packed_highp_bvec2; + using glm::packed_mediump_bvec2; + using glm::packed_lowp_bvec2; + using glm::aligned_highp_vec3; + using glm::aligned_mediump_vec3; + using glm::aligned_lowp_vec3; + using glm::aligned_highp_dvec3; + using glm::aligned_mediump_dvec3; + using glm::aligned_lowp_dvec3; + using glm::aligned_highp_ivec3; + using glm::aligned_mediump_ivec3; + using glm::aligned_lowp_ivec3; + using glm::aligned_highp_uvec3; + using glm::aligned_mediump_uvec3; + using glm::aligned_lowp_uvec3; + using glm::aligned_highp_bvec3; + using glm::aligned_mediump_bvec3; + using glm::aligned_lowp_bvec3; + using glm::packed_highp_vec3; + using glm::packed_mediump_vec3; + using glm::packed_lowp_vec3; + using glm::packed_highp_dvec3; + using glm::packed_mediump_dvec3; + using glm::packed_lowp_dvec3; + using glm::packed_highp_ivec3; + using glm::packed_mediump_ivec3; + using glm::packed_lowp_ivec3; + using glm::packed_highp_uvec3; + using glm::packed_mediump_uvec3; + using glm::packed_lowp_uvec3; + using glm::packed_highp_bvec3; + using glm::packed_mediump_bvec3; + using glm::packed_lowp_bvec3; + using glm::aligned_highp_vec4; + using glm::aligned_mediump_vec4; + using glm::aligned_lowp_vec4; + using glm::aligned_highp_dvec4; + using glm::aligned_mediump_dvec4; + using glm::aligned_lowp_dvec4; + using glm::aligned_highp_ivec4; + using glm::aligned_mediump_ivec4; + using glm::aligned_lowp_ivec4; + using glm::aligned_highp_uvec4; + using glm::aligned_mediump_uvec4; + using glm::aligned_lowp_uvec4; + using glm::aligned_highp_bvec4; + using glm::aligned_mediump_bvec4; + using glm::aligned_lowp_bvec4; + using glm::packed_highp_vec4; + using glm::packed_mediump_vec4; + using glm::packed_lowp_vec4; + using glm::packed_highp_dvec4; + using glm::packed_mediump_dvec4; + using glm::packed_lowp_dvec4; + using glm::packed_highp_ivec4; + using glm::packed_mediump_ivec4; + using glm::packed_lowp_ivec4; + using glm::packed_highp_uvec4; + using glm::packed_mediump_uvec4; + using glm::packed_lowp_uvec4; + using glm::packed_highp_bvec4; + using glm::packed_mediump_bvec4; + using glm::packed_lowp_bvec4; + using glm::aligned_highp_mat2; + using glm::aligned_mediump_mat2; + using glm::aligned_lowp_mat2; + using glm::aligned_highp_dmat2; + using glm::aligned_mediump_dmat2; + using glm::aligned_lowp_dmat2; + using glm::packed_highp_mat2; + using glm::packed_mediump_mat2; + using glm::packed_lowp_mat2; + using glm::packed_highp_dmat2; + using glm::packed_mediump_dmat2; + using glm::packed_lowp_dmat2; + using glm::aligned_highp_mat3; + using glm::aligned_mediump_mat3; + using glm::aligned_lowp_mat3; + using glm::aligned_highp_dmat3; + using glm::aligned_mediump_dmat3; + using glm::aligned_lowp_dmat3; + using glm::packed_highp_mat3; + using glm::packed_mediump_mat3; + using glm::packed_lowp_mat3; + using glm::packed_highp_dmat3; + using glm::packed_mediump_dmat3; + using glm::packed_lowp_dmat3; + using glm::aligned_highp_mat4; + using glm::aligned_mediump_mat4; + using glm::aligned_lowp_mat4; + using glm::aligned_highp_dmat4; + using glm::aligned_mediump_dmat4; + using glm::aligned_lowp_dmat4; + using glm::packed_highp_mat4; + using glm::packed_mediump_mat4; + using glm::packed_lowp_mat4; + using glm::packed_highp_dmat4; + using glm::packed_mediump_dmat4; + using glm::packed_lowp_dmat4; + using glm::aligned_highp_mat2x2; + using glm::aligned_mediump_mat2x2; + using glm::aligned_lowp_mat2x2; + using glm::aligned_highp_dmat2x2; + using glm::aligned_mediump_dmat2x2; + using glm::aligned_lowp_dmat2x2; + using glm::packed_highp_mat2x2; + using glm::packed_mediump_mat2x2; + using glm::packed_lowp_mat2x2; + using glm::packed_highp_dmat2x2; + using glm::packed_mediump_dmat2x2; + using glm::packed_lowp_dmat2x2; + using glm::aligned_highp_mat2x3; + using glm::aligned_mediump_mat2x3; + using glm::aligned_lowp_mat2x3; + using glm::aligned_highp_dmat2x3; + using glm::aligned_mediump_dmat2x3; + using glm::aligned_lowp_dmat2x3; + using glm::packed_highp_mat2x3; + using glm::packed_mediump_mat2x3; + using glm::packed_lowp_mat2x3; + using glm::packed_highp_dmat2x3; + using glm::packed_mediump_dmat2x3; + using glm::packed_lowp_dmat2x3; + using glm::aligned_highp_mat2x4; + using glm::aligned_mediump_mat2x4; + using glm::aligned_lowp_mat2x4; + using glm::aligned_highp_dmat2x4; + using glm::aligned_mediump_dmat2x4; + using glm::aligned_lowp_dmat2x4; + using glm::packed_highp_mat2x4; + using glm::packed_mediump_mat2x4; + using glm::packed_lowp_mat2x4; + using glm::packed_highp_dmat2x4; + using glm::packed_mediump_dmat2x4; + using glm::packed_lowp_dmat2x4; + using glm::aligned_highp_mat3x2; + using glm::aligned_mediump_mat3x2; + using glm::aligned_lowp_mat3x2; + using glm::aligned_highp_dmat3x2; + using glm::aligned_mediump_dmat3x2; + using glm::aligned_lowp_dmat3x2; + using glm::packed_highp_mat3x2; + using glm::packed_mediump_mat3x2; + using glm::packed_lowp_mat3x2; + using glm::packed_highp_dmat3x2; + using glm::packed_mediump_dmat3x2; + using glm::packed_lowp_dmat3x2; + using glm::aligned_highp_mat3x3; + using glm::aligned_mediump_mat3x3; + using glm::aligned_lowp_mat3x3; + using glm::aligned_highp_dmat3x3; + using glm::aligned_mediump_dmat3x3; + using glm::aligned_lowp_dmat3x3; + using glm::packed_highp_mat3x3; + using glm::packed_mediump_mat3x3; + using glm::packed_lowp_mat3x3; + using glm::packed_highp_dmat3x3; + using glm::packed_mediump_dmat3x3; + using glm::packed_lowp_dmat3x3; + using glm::aligned_highp_mat3x4; + using glm::aligned_mediump_mat3x4; + using glm::aligned_lowp_mat3x4; + using glm::aligned_highp_dmat3x4; + using glm::aligned_mediump_dmat3x4; + using glm::aligned_lowp_dmat3x4; + using glm::packed_highp_mat3x4; + using glm::packed_mediump_mat3x4; + using glm::packed_lowp_mat3x4; + using glm::packed_highp_dmat3x4; + using glm::packed_mediump_dmat3x4; + using glm::packed_lowp_dmat3x4; + using glm::aligned_highp_mat4x2; + using glm::aligned_mediump_mat4x2; + using glm::aligned_lowp_mat4x2; + using glm::aligned_highp_dmat4x2; + using glm::aligned_mediump_dmat4x2; + using glm::aligned_lowp_dmat4x2; + using glm::packed_highp_mat4x2; + using glm::packed_mediump_mat4x2; + using glm::packed_lowp_mat4x2; + using glm::packed_highp_dmat4x2; + using glm::packed_mediump_dmat4x2; + using glm::packed_lowp_dmat4x2; + using glm::aligned_highp_mat4x3; + using glm::aligned_mediump_mat4x3; + using glm::aligned_lowp_mat4x3; + using glm::aligned_highp_dmat4x3; + using glm::aligned_mediump_dmat4x3; + using glm::aligned_lowp_dmat4x3; + using glm::packed_highp_mat4x3; + using glm::packed_mediump_mat4x3; + using glm::packed_lowp_mat4x3; + using glm::packed_highp_dmat4x3; + using glm::packed_mediump_dmat4x3; + using glm::packed_lowp_dmat4x3; + using glm::aligned_highp_mat4x4; + using glm::aligned_mediump_mat4x4; + using glm::aligned_lowp_mat4x4; + using glm::aligned_highp_dmat4x4; + using glm::aligned_mediump_dmat4x4; + using glm::aligned_lowp_dmat4x4; + using glm::packed_highp_mat4x4; + using glm::packed_mediump_mat4x4; + using glm::packed_lowp_mat4x4; + using glm::packed_highp_dmat4x4; + using glm::packed_mediump_dmat4x4; + using glm::packed_lowp_dmat4x4; +# if(defined(GLM_PRECISION_LOWP_FLOAT)) + using glm::aligned_vec1; + using glm::aligned_vec2; + using glm::aligned_vec3; + using glm::aligned_vec4; + using glm::packed_vec1; + using glm::packed_vec2; + using glm::packed_vec3; + using glm::packed_vec4; + using glm::aligned_mat2; + using glm::aligned_mat3; + using glm::aligned_mat4; + using glm::packed_mat2; + using glm::packed_mat3; + using glm::packed_mat4; + using glm::aligned_mat2x2; + using glm::aligned_mat2x3; + using glm::aligned_mat2x4; + using glm::aligned_mat3x2; + using glm::aligned_mat3x3; + using glm::aligned_mat3x4; + using glm::aligned_mat4x2; + using glm::aligned_mat4x3; + using glm::aligned_mat4x4; + using glm::packed_mat2x2; + using glm::packed_mat2x3; + using glm::packed_mat2x4; + using glm::packed_mat3x2; + using glm::packed_mat3x3; + using glm::packed_mat3x4; + using glm::packed_mat4x2; + using glm::packed_mat4x3; + using glm::packed_mat4x4; +# elif(defined(GLM_PRECISION_MEDIUMP_FLOAT)) + using glm::aligned_vec1; + using glm::aligned_vec2; + using glm::aligned_vec3; + using glm::aligned_vec4; + using glm::packed_vec1; + using glm::packed_vec2; + using glm::packed_vec3; + using glm::packed_vec4; + using glm::aligned_mat2; + using glm::aligned_mat3; + using glm::aligned_mat4; + using glm::packed_mat2; + using glm::packed_mat3; + using glm::packed_mat4; + using glm::aligned_mat2x2; + using glm::aligned_mat2x3; + using glm::aligned_mat2x4; + using glm::aligned_mat3x2; + using glm::aligned_mat3x3; + using glm::aligned_mat3x4; + using glm::aligned_mat4x2; + using glm::aligned_mat4x3; + using glm::aligned_mat4x4; + using glm::packed_mat2x2; + using glm::packed_mat2x3; + using glm::packed_mat2x4; + using glm::packed_mat3x2; + using glm::packed_mat3x3; + using glm::packed_mat3x4; + using glm::packed_mat4x2; + using glm::packed_mat4x3; + using glm::packed_mat4x4; +# else //defined(GLM_PRECISION_HIGHP_FLOAT) + using glm::aligned_vec1; + using glm::aligned_vec2; + using glm::aligned_vec3; + using glm::aligned_vec4; + using glm::packed_vec1; + using glm::packed_vec2; + using glm::packed_vec3; + using glm::packed_vec4; + using glm::aligned_mat2; + using glm::aligned_mat3; + using glm::aligned_mat4; + using glm::packed_mat2; + using glm::packed_mat3; + using glm::packed_mat4; + using glm::aligned_mat2x2; + using glm::aligned_mat2x3; + using glm::aligned_mat2x4; + using glm::aligned_mat3x2; + using glm::aligned_mat3x3; + using glm::aligned_mat3x4; + using glm::aligned_mat4x2; + using glm::aligned_mat4x3; + using glm::aligned_mat4x4; + using glm::packed_mat2x2; + using glm::packed_mat2x3; + using glm::packed_mat2x4; + using glm::packed_mat3x2; + using glm::packed_mat3x3; + using glm::packed_mat3x4; + using glm::packed_mat4x2; + using glm::packed_mat4x3; + using glm::packed_mat4x4; +# endif//GLM_PRECISION +# if(defined(GLM_PRECISION_LOWP_DOUBLE)) + using glm::aligned_dvec1; + using glm::aligned_dvec2; + using glm::aligned_dvec3; + using glm::aligned_dvec4; + using glm::packed_dvec1; + using glm::packed_dvec2; + using glm::packed_dvec3; + using glm::packed_dvec4; + using glm::aligned_dmat2; + using glm::aligned_dmat3; + using glm::aligned_dmat4; + using glm::packed_dmat2; + using glm::packed_dmat3; + using glm::packed_dmat4; + using glm::aligned_dmat2x2; + using glm::aligned_dmat2x3; + using glm::aligned_dmat2x4; + using glm::aligned_dmat3x2; + using glm::aligned_dmat3x3; + using glm::aligned_dmat3x4; + using glm::aligned_dmat4x2; + using glm::aligned_dmat4x3; + using glm::aligned_dmat4x4; + using glm::packed_dmat2x2; + using glm::packed_dmat2x3; + using glm::packed_dmat2x4; + using glm::packed_dmat3x2; + using glm::packed_dmat3x3; + using glm::packed_dmat3x4; + using glm::packed_dmat4x2; + using glm::packed_dmat4x3; + using glm::packed_dmat4x4; +# elif(defined(GLM_PRECISION_MEDIUMP_DOUBLE)) + using glm::aligned_dvec1; + using glm::aligned_dvec2; + using glm::aligned_dvec3; + using glm::aligned_dvec4; + using glm::packed_dvec1; + using glm::packed_dvec2; + using glm::packed_dvec3; + using glm::packed_dvec4; + using glm::aligned_dmat2; + using glm::aligned_dmat3; + using glm::aligned_dmat4; + using glm::packed_dmat2; + using glm::packed_dmat3; + using glm::packed_dmat4; + using glm::aligned_dmat2x2; + using glm::aligned_dmat2x3; + using glm::aligned_dmat2x4; + using glm::aligned_dmat3x2; + using glm::aligned_dmat3x3; + using glm::aligned_dmat3x4; + using glm::aligned_dmat4x2; + using glm::aligned_dmat4x3; + using glm::aligned_dmat4x4; + using glm::packed_dmat2x2; + using glm::packed_dmat2x3; + using glm::packed_dmat2x4; + using glm::packed_dmat3x2; + using glm::packed_dmat3x3; + using glm::packed_dmat3x4; + using glm::packed_dmat4x2; + using glm::packed_dmat4x3; + using glm::packed_dmat4x4; +# else //defined(GLM_PRECISION_HIGHP_DOUBLE) + using glm::aligned_dvec1; + using glm::aligned_dvec2; + using glm::aligned_dvec3; + using glm::aligned_dvec4; + using glm::packed_dvec1; + using glm::packed_dvec2; + using glm::packed_dvec3; + using glm::packed_dvec4; + using glm::aligned_dmat2; + using glm::aligned_dmat3; + using glm::aligned_dmat4; + using glm::packed_dmat2; + using glm::packed_dmat3; + using glm::packed_dmat4; + using glm::aligned_dmat2x2; + using glm::aligned_dmat2x3; + using glm::aligned_dmat2x4; + using glm::aligned_dmat3x2; + using glm::aligned_dmat3x3; + using glm::aligned_dmat3x4; + using glm::aligned_dmat4x2; + using glm::aligned_dmat4x3; + using glm::aligned_dmat4x4; + using glm::packed_dmat2x2; + using glm::packed_dmat2x3; + using glm::packed_dmat2x4; + using glm::packed_dmat3x2; + using glm::packed_dmat3x3; + using glm::packed_dmat3x4; + using glm::packed_dmat4x2; + using glm::packed_dmat4x3; + using glm::packed_dmat4x4; +# endif//GLM_PRECISION +# if(defined(GLM_PRECISION_LOWP_INT)) + using glm::aligned_ivec1; + using glm::aligned_ivec2; + using glm::aligned_ivec3; + using glm::aligned_ivec4; +# elif(defined(GLM_PRECISION_MEDIUMP_INT)) + using glm::aligned_ivec1; + using glm::aligned_ivec2; + using glm::aligned_ivec3; + using glm::aligned_ivec4; +# else //defined(GLM_PRECISION_HIGHP_INT) + using glm::aligned_ivec1; + using glm::aligned_ivec2; + using glm::aligned_ivec3; + using glm::aligned_ivec4; + using glm::packed_ivec1; + using glm::packed_ivec2; + using glm::packed_ivec3; + using glm::packed_ivec4; +# endif//GLM_PRECISION +# if(defined(GLM_PRECISION_LOWP_UINT)) + using glm::aligned_uvec1; + using glm::aligned_uvec2; + using glm::aligned_uvec3; + using glm::aligned_uvec4; +# elif(defined(GLM_PRECISION_MEDIUMP_UINT)) + using glm::aligned_uvec1; + using glm::aligned_uvec2; + using glm::aligned_uvec3; + using glm::aligned_uvec4; +# else //defined(GLM_PRECISION_HIGHP_UINT) + using glm::aligned_uvec1; + using glm::aligned_uvec2; + using glm::aligned_uvec3; + using glm::aligned_uvec4; + using glm::packed_uvec1; + using glm::packed_uvec2; + using glm::packed_uvec3; + using glm::packed_uvec4; +# endif//GLM_PRECISION +# if(defined(GLM_PRECISION_LOWP_BOOL)) + using glm::aligned_bvec1; + using glm::aligned_bvec2; + using glm::aligned_bvec3; + using glm::aligned_bvec4; +# elif(defined(GLM_PRECISION_MEDIUMP_BOOL)) + using glm::aligned_bvec1; + using glm::aligned_bvec2; + using glm::aligned_bvec3; + using glm::aligned_bvec4; +# else //defined(GLM_PRECISION_HIGHP_BOOL) + using glm::aligned_bvec1; + using glm::aligned_bvec2; + using glm::aligned_bvec3; + using glm::aligned_bvec4; + using glm::packed_bvec1; + using glm::packed_bvec2; + using glm::packed_bvec3; + using glm::packed_bvec4; +# endif//GLM_PRECISION +# endif + + + using glm::abs; + using glm::acos; + using glm::acosh; + using glm::acot; + using glm::acoth; + using glm::acsc; + using glm::acsch; + using glm::affineInverse; + using glm::all; + using glm::angle; + using glm::angleAxis; + using glm::any; + using glm::asec; + using glm::asech; + using glm::asin; + using glm::asinh; + using glm::atan; + using glm::atanh; + using glm::axis; + using glm::ballRand; + using glm::bitCount; + using glm::bitfieldDeinterleave; + using glm::bitfieldExtract; + using glm::bitfieldFillOne; + using glm::bitfieldFillZero; + using glm::bitfieldInsert; + using glm::bitfieldInterleave; + using glm::bitfieldReverse; + using glm::bitfieldRotateLeft; + using glm::bitfieldRotateRight; + using glm::ceil; + using glm::ceilMultiple; + using glm::ceilPowerOfTwo; + using glm::circularRand; + using glm::clamp; + using glm::column; + using glm::conjugate; + using glm::convertLinearToSRGB; + using glm::convertSRGBToLinear; + using glm::cos; + using glm::cos_one_over_two; + using glm::cosh; + using glm::cot; + using glm::coth; + using glm::cross; + using glm::csc; + using glm::csch; + using glm::degrees; + using glm::determinant; + using glm::diskRand; + using glm::distance; + using glm::dot; + using glm::e; + using glm::epsilon; + using glm::epsilonEqual; + using glm::epsilonNotEqual; + using glm::equal; + using glm::euler; + using glm::eulerAngles; + using glm::exp; + using glm::exp2; + using glm::faceforward; + using glm::fclamp; + using glm::findLSB; + using glm::findMSB; + using glm::floatBitsToInt; + using glm::floatBitsToUint; + using glm::float_distance; + using glm::floor; + using glm::floorMultiple; + using glm::floorPowerOfTwo; + using glm::fma; + using glm::fmax; + using glm::fmin; + using glm::four_over_pi; + using glm::fract; + using glm::frexp; + using glm::frustum; + using glm::frustumLH; + using glm::frustumLH_NO; + using glm::frustumLH_ZO; + using glm::frustumNO; + using glm::frustumRH; + using glm::frustumRH_NO; + using glm::frustumRH_ZO; + using glm::frustumZO; + using glm::gaussRand; + using glm::golden_ratio; + using glm::greaterThan; + using glm::greaterThanEqual; + using glm::half_pi; + using glm::identity; + using glm::imulExtended; + using glm::infinitePerspective; + using glm::infinitePerspectiveLH; + using glm::infinitePerspectiveRH; + using glm::intBitsToFloat; + using glm::inverse; + using glm::inverseTranspose; + using glm::inversesqrt; + using glm::iround; + using glm::isinf; + using glm::isnan; + using glm::ldexp; + using glm::length; + using glm::lerp; + using glm::lessThan; + using glm::lessThanEqual; + using glm::linearRand; + using glm::ln_ln_two; + using glm::ln_ten; + using glm::ln_two; + using glm::log; + using glm::log2; + using glm::lookAt; + using glm::lookAtLH; + using glm::lookAtRH; + using glm::make_mat2; + using glm::make_mat2x2; + using glm::make_mat2x3; + using glm::make_mat2x4; + using glm::make_mat3; + using glm::make_mat3x2; + using glm::make_mat3x3; + using glm::make_mat3x4; + using glm::make_mat4; + using glm::make_mat4x2; + using glm::make_mat4x3; + using glm::make_mat4x4; + using glm::make_quat; + using glm::make_vec1; + using glm::make_vec2; + using glm::make_vec3; + using glm::make_vec4; + using glm::mask; + using glm::mat3_cast; + using glm::mat4_cast; + using glm::matrixCompMult; + using glm::max; + using glm::min; + using glm::mirrorClamp; + using glm::mirrorRepeat; + using glm::mix; + using glm::mod; + using glm::modf; + using glm::next_float; + using glm::normalize; + using glm::notEqual; + using glm::not_; + using glm::one; + using glm::one_over_pi; + using glm::one_over_root_two; + using glm::one_over_two_pi; + using glm::ortho; + using glm::orthoLH; + using glm::orthoLH_NO; + using glm::orthoLH_ZO; + using glm::orthoNO; + using glm::orthoRH; + using glm::orthoRH_NO; + using glm::orthoRH_ZO; + using glm::orthoZO; + using glm::outerProduct; + using glm::packF2x11_1x10; + using glm::packF3x9_E1x5; + using glm::packHalf; + using glm::packHalf1x16; + using glm::packHalf4x16; + using glm::packI3x10_1x2; + using glm::packInt2x16; + using glm::packInt2x32; + using glm::packInt2x8; + using glm::packInt4x16; + using glm::packInt4x8; + using glm::packRGBM; + using glm::packSnorm; + using glm::packSnorm1x16; + using glm::packSnorm1x8; + using glm::packSnorm2x8; + using glm::packSnorm3x10_1x2; + using glm::packSnorm4x16; + using glm::packU3x10_1x2; + using glm::packUint2x16; + using glm::packUint2x32; + using glm::packUint2x8; + using glm::packUint4x16; + using glm::packUint4x8; + using glm::packUnorm; + using glm::packUnorm1x16; + using glm::packUnorm1x5_1x6_1x5; + using glm::packUnorm1x8; + using glm::packUnorm2x3_1x2; + using glm::packUnorm2x4; + using glm::packUnorm2x8; + using glm::packUnorm3x10_1x2; + using glm::packUnorm3x5_1x1; + using glm::packUnorm4x16; + using glm::packUnorm4x4; + using glm::perlin; + using glm::perspective; + using glm::perspectiveFov; + using glm::perspectiveFovLH; + using glm::perspectiveFovLH_NO; + using glm::perspectiveFovLH_ZO; + using glm::perspectiveFovNO; + using glm::perspectiveFovRH; + using glm::perspectiveFovRH_NO; + using glm::perspectiveFovRH_ZO; + using glm::perspectiveFovZO; + using glm::perspectiveLH; + using glm::perspectiveLH_NO; + using glm::perspectiveLH_ZO; + using glm::perspectiveNO; + using glm::perspectiveRH; + using glm::perspectiveRH_NO; + using glm::perspectiveRH_ZO; + using glm::perspectiveZO; + using glm::pi; + using glm::pickMatrix; + using glm::pitch; + using glm::pow; + using glm::prev_float; + using glm::project; + using glm::projectNO; + using glm::projectZO; + using glm::quarter_pi; + using glm::quatLookAt; + using glm::quatLookAtLH; + using glm::quatLookAtRH; + using glm::quat_cast; + using glm::radians; + using glm::reflect; + using glm::refract; + using glm::repeat; + using glm::roll; + using glm::root_five; + using glm::root_half_pi; + using glm::root_ln_four; + using glm::root_pi; + using glm::root_three; + using glm::root_two; + using glm::root_two_pi; + using glm::rotate; + using glm::round; + using glm::roundEven; + using glm::roundMultiple; + using glm::roundPowerOfTwo; + using glm::row; + using glm::scale; + using glm::sec; + using glm::sech; + using glm::sign; + using glm::simplex; + using glm::sin; + using glm::sinh; + using glm::slerp; + using glm::smoothstep; + using glm::sphericalRand; + using glm::sqrt; + using glm::step; + using glm::tan; + using glm::tanh; + using glm::third; + using glm::three_over_two_pi; + using glm::translate; + using glm::transpose; + using glm::trunc; + using glm::tweakedInfinitePerspective; + using glm::two_over_pi; + using glm::two_over_root_pi; + using glm::two_pi; + using glm::two_thirds; + using glm::uaddCarry; + using glm::uintBitsToFloat; + using glm::umulExtended; + using glm::unProject; + using glm::unProjectNO; + using glm::unProjectZO; + using glm::unpackF2x11_1x10; + using glm::unpackF3x9_E1x5; + using glm::unpackHalf; + using glm::unpackHalf1x16; + using glm::unpackHalf4x16; + using glm::unpackI3x10_1x2; + using glm::unpackInt2x16; + using glm::unpackInt2x32; + using glm::unpackInt2x8; + using glm::unpackInt4x16; + using glm::unpackInt4x8; + using glm::unpackRGBM; + using glm::unpackSnorm; + using glm::unpackSnorm1x16; + using glm::unpackSnorm1x8; + using glm::unpackSnorm2x8; + using glm::unpackSnorm3x10_1x2; + using glm::unpackSnorm4x16; + using glm::unpackU3x10_1x2; + using glm::unpackUint2x16; + using glm::unpackUint2x32; + using glm::unpackUint2x8; + using glm::unpackUint4x16; + using glm::unpackUint4x8; + using glm::unpackUnorm; + using glm::unpackUnorm1x16; + using glm::unpackUnorm1x5_1x6_1x5; + using glm::unpackUnorm1x8; + using glm::unpackUnorm2x3_1x2; + using glm::unpackUnorm2x4; + using glm::unpackUnorm2x8; + using glm::unpackUnorm3x10_1x2; + using glm::unpackUnorm3x5_1x1; + using glm::unpackUnorm4x16; + using glm::unpackUnorm4x4; + using glm::uround; + using glm::usubBorrow; + using glm::value_ptr; + using glm::yaw; + using glm::zero; + } + +# ifdef GLM_EXT_INLINE_NAMESPACE + inline +# endif + namespace ext { + using glm::abs; + using glm::acos; + using glm::acosh; + using glm::acot; + using glm::acoth; + using glm::acsc; + using glm::acsch; + using glm::all; + using glm::angle; + using glm::angleAxis; + using glm::any; + using glm::asec; + using glm::asech; + using glm::asin; + using glm::asinh; + using glm::atan; + using glm::atanh; + using glm::axis; + using glm::ceil; + using glm::clamp; + using glm::conjugate; + using glm::cos; + using glm::cos_one_over_two; + using glm::cosh; + using glm::cot; + using glm::coth; + using glm::cross; + using glm::csc; + using glm::csch; + using glm::degrees; + using glm::determinant; + using glm::distance; + using glm::dot; + using glm::e; + using glm::epsilon; + using glm::equal; + using glm::euler; + using glm::exp; + using glm::exp2; + using glm::faceforward; + using glm::fclamp; + using glm::findNSB; + using glm::floatBitsToInt; + using glm::floatBitsToUint; + using glm::floatDistance; + using glm::floor; + using glm::fma; + using glm::fmax; + using glm::fmin; + using glm::four_over_pi; + using glm::fract; + using glm::frexp; + using glm::frustum; + using glm::frustumLH; + using glm::frustumLH_NO; + using glm::frustumLH_ZO; + using glm::frustumNO; + using glm::frustumRH; + using glm::frustumRH_NO; + using glm::frustumRH_ZO; + using glm::frustumZO; + using glm::golden_ratio; + using glm::greaterThan; + using glm::greaterThanEqual; + using glm::half_pi; + using glm::identity; + using glm::infinitePerspective; + using glm::infinitePerspectiveLH; + using glm::infinitePerspectiveRH; + using glm::intBitsToFloat; + using glm::inverse; + using glm::inversesqrt; + using glm::iround; + using glm::isMultiple; + using glm::isPowerOfTwo; + using glm::isinf; + using glm::isnan; + using glm::ldexp; + using glm::length; + using glm::lerp; + using glm::lessThan; + using glm::lessThanEqual; + using glm::ln_ln_two; + using glm::ln_ten; + using glm::ln_two; + using glm::log; + using glm::log2; + using glm::lookAt; + using glm::lookAtLH; + using glm::lookAtRH; + using glm::matrixCompMult; + using glm::max; + using glm::min; + using glm::mirrorClamp; + using glm::mirrorRepeat; + using glm::mix; + using glm::mod; + using glm::modf; + using glm::nextFloat; + using glm::nextMultiple; + using glm::nextPowerOfTwo; + using glm::normalize; + using glm::notEqual; + using glm::not_; + using glm::one; + using glm::one_over_pi; + using glm::one_over_root_two; + using glm::one_over_two_pi; + using glm::ortho; + using glm::orthoLH; + using glm::orthoLH_NO; + using glm::orthoLH_ZO; + using glm::orthoNO; + using glm::orthoRH; + using glm::orthoRH_NO; + using glm::orthoRH_ZO; + using glm::orthoZO; + using glm::outerProduct; + using glm::perspective; + using glm::perspectiveFov; + using glm::perspectiveFovLH; + using glm::perspectiveFovLH_NO; + using glm::perspectiveFovLH_ZO; + using glm::perspectiveFovNO; + using glm::perspectiveFovRH; + using glm::perspectiveFovRH_NO; + using glm::perspectiveFovRH_ZO; + using glm::perspectiveFovZO; + using glm::perspectiveLH; + using glm::perspectiveLH_NO; + using glm::perspectiveLH_ZO; + using glm::perspectiveNO; + using glm::perspectiveRH; + using glm::perspectiveRH_NO; + using glm::perspectiveRH_ZO; + using glm::perspectiveZO; + using glm::pi; + using glm::pickMatrix; + using glm::pow; + using glm::prevFloat; + using glm::prevMultiple; + using glm::prevPowerOfTwo; + using glm::project; + using glm::projectNO; + using glm::projectZO; + using glm::quarter_pi; + using glm::radians; + using glm::reflect; + using glm::refract; + using glm::repeat; + using glm::root_five; + using glm::root_half_pi; + using glm::root_ln_four; + using glm::root_pi; + using glm::root_three; + using glm::root_two; + using glm::root_two_pi; + using glm::rotate; + using glm::round; + using glm::roundEven; + using glm::scale; + using glm::sec; + using glm::sech; + using glm::sign; + using glm::sin; + using glm::sinh; + using glm::slerp; + using glm::smoothstep; + using glm::sqrt; + using glm::step; + using glm::tan; + using glm::tanh; + using glm::third; + using glm::three_over_two_pi; + using glm::translate; + using glm::transpose; + using glm::trunc; + using glm::tweakedInfinitePerspective; + using glm::two_over_pi; + using glm::two_over_root_pi; + using glm::two_pi; + using glm::two_thirds; + using glm::uintBitsToFloat; + using glm::unProject; + using glm::unProjectNO; + using glm::unProjectZO; + using glm::uround; + using glm::zero; + } + +# ifdef GLM_ENABLE_EXPERIMENTAL +# ifdef GLM_GTX_INLINE_NAMESPACE + inline +# endif + namespace gtx { + using glm::io::order_type; + using glm::io::format_punct; + using glm::io::basic_state_saver; + using glm::io::basic_format_saver; + using glm::io::precision; + using glm::io::width; + using glm::io::delimeter; + using glm::io::order; + using glm::io::get_facet; + using glm::io::formatted; + using glm::io::unformatted; + using glm::io::operator<<; + using glm::operator<<; + using glm::tdualquat; + +# if !((GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP)) + using glm::to_string; +# endif +# if GLM_HAS_TEMPLATE_ALIASES + using glm::operator*; + using glm::operator/; +# endif +# if GLM_HAS_RANGE_FOR + using glm::components; + using glm::begin; + using glm::end; +# endif + + using glm::abs; + using glm::acos; + using glm::acosh; + using glm::adjugate; + using glm::all; + using glm::angle; + using glm::angleAxis; + using glm::any; + using glm::areCollinear; + using glm::areOrthogonal; + using glm::areOrthonormal; + using glm::asin; + using glm::asinh; + using glm::associatedMax; + using glm::associatedMin; + using glm::atan; + using glm::atanh; + using glm::axis; + using glm::axisAngle; + using glm::axisAngleMatrix; + using glm::backEaseIn; + using glm::backEaseInOut; + using glm::backEaseOut; + using glm::bitCount; + using glm::bitfieldDeinterleave; + using glm::bitfieldExtract; + using glm::bitfieldFillOne; + using glm::bitfieldFillZero; + using glm::bitfieldInsert; + using glm::bitfieldInterleave; + using glm::bitfieldReverse; + using glm::bitfieldRotateLeft; + using glm::bitfieldRotateRight; + using glm::bounceEaseIn; + using glm::bounceEaseInOut; + using glm::bounceEaseOut; + using glm::catmullRom; + using glm::ceil; + using glm::circularEaseIn; + using glm::circularEaseInOut; + using glm::circularEaseOut; + using glm::clamp; + using glm::closeBounded; + using glm::closestPointOnLine; + using glm::colMajor2; + using glm::colMajor3; + using glm::colMajor4; + using glm::compAdd; + using glm::compMax; + using glm::compMin; + using glm::compMul; + using glm::compNormalize; + using glm::compScale; + using glm::computeCovarianceMatrix; + using glm::conjugate; + using glm::convertD65XYZToD50XYZ; + using glm::convertD65XYZToLinearSRGB; + using glm::convertLinearSRGBToD50XYZ; + using glm::convertLinearSRGBToD65XYZ; + using glm::cos; + using glm::cos_one_over_two; + using glm::cosh; + using glm::cross; + using glm::cubic; + using glm::cubicEaseIn; + using glm::cubicEaseInOut; + using glm::cubicEaseOut; + using glm::decompose; + using glm::degrees; + using glm::derivedEulerAngleX; + using glm::derivedEulerAngleY; + using glm::derivedEulerAngleZ; + using glm::determinant; + using glm::diagonal2x2; + using glm::diagonal2x3; + using glm::diagonal2x4; + using glm::diagonal3x2; + using glm::diagonal3x3; + using glm::diagonal3x4; + using glm::diagonal4x2; + using glm::diagonal4x3; + using glm::diagonal4x4; + using glm::distance; + using glm::distance2; + using glm::dot; + using glm::dual_quat_identity; + using glm::dualquat_cast; + using glm::e; + using glm::elasticEaseIn; + using glm::elasticEaseInOut; + using glm::elasticEaseOut; + using glm::epsilon; + using glm::epsilonEqual; + using glm::epsilonNotEqual; + using glm::equal; + using glm::euclidean; + using glm::euler; + using glm::eulerAngleX; + using glm::eulerAngleXY; + using glm::eulerAngleXYX; + using glm::eulerAngleXYZ; + using glm::eulerAngleXZ; + using glm::eulerAngleXZX; + using glm::eulerAngleXZY; + using glm::eulerAngleY; + using glm::eulerAngleYX; + using glm::eulerAngleYXY; + using glm::eulerAngleYXZ; + using glm::eulerAngleYZ; + using glm::eulerAngleYZX; + using glm::eulerAngleYZY; + using glm::eulerAngleZ; + using glm::eulerAngleZX; + using glm::eulerAngleZXY; + using glm::eulerAngleZXZ; + using glm::eulerAngleZY; + using glm::eulerAngleZYX; + using glm::eulerAngleZYZ; + using glm::eulerAngles; + using glm::exp; + using glm::exp2; + using glm::exponentialEaseIn; + using glm::exponentialEaseInOut; + using glm::exponentialEaseOut; + using glm::extend; + using glm::extractEulerAngleXYX; + using glm::extractEulerAngleXYZ; + using glm::extractEulerAngleXZX; + using glm::extractEulerAngleXZY; + using glm::extractEulerAngleYXY; + using glm::extractEulerAngleYXZ; + using glm::extractEulerAngleYZX; + using glm::extractEulerAngleYZY; + using glm::extractEulerAngleZXY; + using glm::extractEulerAngleZXZ; + using glm::extractEulerAngleZYX; + using glm::extractEulerAngleZYZ; + using glm::extractMatrixRotation; + using glm::extractRealComponent; + using glm::faceforward; + using glm::factorial; + using glm::fastAcos; + using glm::fastAsin; + using glm::fastAtan; + using glm::fastCos; + using glm::fastDistance; + using glm::fastExp; + using glm::fastExp2; + using glm::fastInverseSqrt; + using glm::fastLength; + using glm::fastLog; + using glm::fastLog2; + using glm::fastMix; + using glm::fastNormalize; + using glm::fastNormalizeDot; + using glm::fastPow; + using glm::fastSin; + using glm::fastSqrt; + using glm::fastTan; + using glm::fclamp; + using glm::findLSB; + using glm::findMSB; + using glm::fliplr; + using glm::flipud; + using glm::floatBitsToInt; + using glm::floatBitsToUint; + using glm::floor; + using glm::floor_log2; + using glm::fma; + using glm::fmax; + using glm::fmin; + using glm::fmod; + using glm::four_over_pi; + using glm::fract; + using glm::frexp; + using glm::frustum; + using glm::frustumLH; + using glm::frustumLH_NO; + using glm::frustumLH_ZO; + using glm::frustumNO; + using glm::frustumRH; + using glm::frustumRH_NO; + using glm::frustumRH_ZO; + using glm::frustumZO; + using glm::gauss; + using glm::golden_ratio; + using glm::greaterThan; + using glm::greaterThanEqual; + using glm::half_pi; + using glm::hermite; + using glm::highestBitValue; + using glm::hsvColor; + using glm::identity; + using glm::imulExtended; + using glm::infinitePerspective; + using glm::infinitePerspectiveLH; + using glm::infinitePerspectiveRH; + using glm::intBitsToFloat; + using glm::intermediate; + using glm::interpolate; + using glm::intersectLineSphere; + using glm::intersectLineTriangle; + using glm::intersectRayPlane; + using glm::intersectRaySphere; + using glm::intersectRayTriangle; + using glm::inverse; + using glm::inversesqrt; + using glm::iround; + using glm::isCompNull; + using glm::isIdentity; + using glm::isNormalized; + using glm::isNull; + using glm::isOrthogonal; + using glm::isdenormal; + using glm::isfinite; + using glm::isinf; + using glm::isnan; + using glm::l1Norm; + using glm::l2Norm; + using glm::lMaxNorm; + using glm::ldexp; + using glm::leftHanded; + using glm::length; + using glm::length2; + using glm::lerp; + using glm::lessThan; + using glm::lessThanEqual; + using glm::linearGradient; + using glm::linearInterpolation; + using glm::ln_ln_two; + using glm::ln_ten; + using glm::ln_two; + using glm::log; + using glm::log2; + using glm::lookAt; + using glm::lookAtLH; + using glm::lookAtRH; + using glm::lowestBitValue; + using glm::luminosity; + using glm::lxNorm; + using glm::make_mat2; + using glm::make_mat2x2; + using glm::make_mat2x3; + using glm::make_mat2x4; + using glm::make_mat3; + using glm::make_mat3x2; + using glm::make_mat3x3; + using glm::make_mat3x4; + using glm::make_mat4; + using glm::make_mat4x2; + using glm::make_mat4x3; + using glm::make_mat4x4; + using glm::make_quat; + using glm::make_vec1; + using glm::make_vec2; + using glm::make_vec3; + using glm::make_vec4; + using glm::mask; + using glm::mat2x4_cast; + using glm::mat3_cast; + using glm::mat3x4_cast; + using glm::mat4_cast; + using glm::matrixCompMult; + using glm::matrixCross3; + using glm::matrixCross4; + using glm::max; + using glm::min; + using glm::mirrorClamp; + using glm::mirrorRepeat; + using glm::mix; + using glm::mixedProduct; + using glm::mod; + using glm::modf; + using glm::nlz; + using glm::normalize; + using glm::normalizeDot; + using glm::notEqual; + using glm::not_; + using glm::YCoCg2rgb; + using glm::YCoCgR2rgb; + using glm::one; + using glm::one_over_pi; + using glm::one_over_root_two; + using glm::one_over_two_pi; + using glm::openBounded; + using glm::orientate2; + using glm::orientate3; + using glm::orientate4; + using glm::orientation; + using glm::orientedAngle; + using glm::ortho; + using glm::orthoLH; + using glm::orthoLH_NO; + using glm::orthoLH_ZO; + using glm::orthoNO; + using glm::orthoRH; + using glm::orthoRH_NO; + using glm::orthoRH_ZO; + using glm::orthoZO; + using glm::orthonormalize; + using glm::outerProduct; + using glm::packDouble2x32; + using glm::packHalf2x16; + using glm::packSnorm2x16; + using glm::packSnorm4x8; + using glm::packUnorm2x16; + using glm::packUnorm4x8; + using glm::perp; + using glm::perspective; + using glm::perspectiveFov; + using glm::perspectiveFovLH; + using glm::perspectiveFovLH_NO; + using glm::perspectiveFovLH_ZO; + using glm::perspectiveFovNO; + using glm::perspectiveFovRH; + using glm::perspectiveFovRH_NO; + using glm::perspectiveFovRH_ZO; + using glm::perspectiveFovZO; + using glm::perspectiveLH; + using glm::perspectiveLH_NO; + using glm::perspectiveLH_ZO; + using glm::perspectiveNO; + using glm::perspectiveRH; + using glm::perspectiveRH_NO; + using glm::perspectiveRH_ZO; + using glm::perspectiveZO; + using glm::pi; + using glm::pickMatrix; + using glm::pitch; + using glm::polar; + using glm::pow; + using glm::pow2; + using glm::pow3; + using glm::pow4; + using glm::powerOfTwoAbove; + using glm::powerOfTwoBelow; + using glm::powerOfTwoNearest; + using glm::proj; + using glm::proj2D; + using glm::proj3D; + using glm::project; + using glm::projectNO; + using glm::projectZO; + using glm::qr_decompose; + using glm::quadraticEaseIn; + using glm::quadraticEaseInOut; + using glm::quadraticEaseOut; + using glm::quarter_pi; + using glm::quarticEaseIn; + using glm::quarticEaseInOut; + using glm::quarticEaseOut; + using glm::quatLookAt; + using glm::quatLookAtLH; + using glm::quatLookAtRH; + using glm::quat_cast; + using glm::quat_identity; + using glm::quinticEaseIn; + using glm::quinticEaseInOut; + using glm::quinticEaseOut; + using glm::radialGradient; + using glm::radians; + using glm::recompose; + using glm::reflect; + using glm::refract; + using glm::repeat; + using glm::rgb2YCoCg; + using glm::rgb2YCoCgR; + using glm::rgbColor; + using glm::rightHanded; + using glm::roll; + using glm::root_five; + using glm::root_half_pi; + using glm::root_ln_four; + using glm::root_pi; + using glm::root_three; + using glm::root_two; + using glm::root_two_pi; + using glm::rotate; + using glm::rotateNormalizedAxis; + using glm::rotateX; + using glm::rotateY; + using glm::rotateZ; + using glm::rotation; + using glm::round; + using glm::roundEven; + using glm::rowMajor2; + using glm::rowMajor3; + using glm::rowMajor4; + using glm::rq_decompose; + using glm::saturation; + using glm::scale; + using glm::scaleBias; + using glm::shearX2D; + using glm::shearX3D; + using glm::shearY2D; + using glm::shearY3D; + using glm::shearZ3D; + using glm::shortMix; + using glm::sign; + using glm::sin; + using glm::sineEaseIn; + using glm::sineEaseInOut; + using glm::sineEaseOut; + using glm::sinh; + using glm::slerp; + using glm::smoothstep; + using glm::sortEigenvalues; + using glm::sqrt; + using glm::squad; + using glm::step; + using glm::tan; + using glm::tanh; + using glm::third; + using glm::three_over_two_pi; + using glm::translate; + using glm::transpose; + using glm::triangleNormal; + using glm::trunc; + using glm::tweakedInfinitePerspective; + using glm::two_over_pi; + using glm::two_over_root_pi; + using glm::two_pi; + using glm::two_thirds; + using glm::uaddCarry; + using glm::uintBitsToFloat; + using glm::umulExtended; + using glm::unProject; + using glm::unProjectNO; + using glm::unProjectZO; + using glm::unpackDouble2x32; + using glm::unpackHalf2x16; + using glm::unpackSnorm2x16; + using glm::unpackSnorm4x8; + using glm::unpackUnorm2x16; + using glm::unpackUnorm4x8; + using glm::uround; + using glm::usubBorrow; + using glm::value_ptr; + using glm::wrapAngle; + using glm::wxyz; + using glm::yaw; + using glm::yawPitchRoll; + using glm::zero; + } +# endif +} + +#if defined(_MSC_VER) // Workaround +// Partial template specialization doesn't need to be exported explicitly, but this may not work otherwise on MSVC. +export namespace std { + using std::hash; // See GLM_GTX_hash +} +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/glm.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/glm.hpp new file mode 100644 index 0000000..8b37545 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/glm.hpp @@ -0,0 +1,137 @@ +/// @ref core +/// @file glm/glm.hpp +/// +/// @mainpage OpenGL Mathematics (GLM) +/// - Website: glm.g-truc.net +/// - GLM API documentation +/// - GLM Manual +/// +/// @defgroup core Core features +/// +/// @brief Features that implement in C++ the GLSL specification as closely as possible. +/// +/// The GLM core consists of C++ types that mirror GLSL types and +/// C++ functions that mirror the GLSL functions. +/// +/// The best documentation for GLM Core is the current GLSL specification, +/// version 4.2 +/// (pdf file). +/// +/// GLM core functionalities require to be included to be used. +/// +/// +/// @defgroup core_vector Vector types +/// +/// Vector types of two to four components with an exhaustive set of operators. +/// +/// @ingroup core +/// +/// +/// @defgroup core_vector_precision Vector types with precision qualifiers +/// +/// @brief Vector types with precision qualifiers which may result in various precision in term of ULPs +/// +/// GLSL allows defining qualifiers for particular variables. +/// With OpenGL's GLSL, these qualifiers have no effect; they are there for compatibility, +/// with OpenGL ES's GLSL, these qualifiers do have an effect. +/// +/// C++ has no language equivalent to qualifier qualifiers. So GLM provides the next-best thing: +/// a number of typedefs that use a particular qualifier. +/// +/// None of these types make any guarantees about the actual qualifier used. +/// +/// @ingroup core +/// +/// +/// @defgroup core_matrix Matrix types +/// +/// Matrix types of with C columns and R rows where C and R are values between 2 to 4 included. +/// These types have exhaustive sets of operators. +/// +/// @ingroup core +/// +/// +/// @defgroup core_matrix_precision Matrix types with precision qualifiers +/// +/// @brief Matrix types with precision qualifiers which may result in various precision in term of ULPs +/// +/// GLSL allows defining qualifiers for particular variables. +/// With OpenGL's GLSL, these qualifiers have no effect; they are there for compatibility, +/// with OpenGL ES's GLSL, these qualifiers do have an effect. +/// +/// C++ has no language equivalent to qualifier qualifiers. So GLM provides the next-best thing: +/// a number of typedefs that use a particular qualifier. +/// +/// None of these types make any guarantees about the actual qualifier used. +/// +/// @ingroup core +/// +/// +/// @defgroup ext Stable extensions +/// +/// @brief Additional features not specified by GLSL specification. +/// +/// EXT extensions are fully tested and documented. +/// +/// Even if it's highly unrecommended, it's possible to include all the extensions at once by +/// including . Otherwise, each extension needs to be included a specific file. +/// +/// +/// @defgroup gtc Recommended extensions +/// +/// @brief Additional features not specified by GLSL specification. +/// +/// GTC extensions aim to be stable with tests and documentation. +/// +/// Even if it's highly unrecommended, it's possible to include all the extensions at once by +/// including . Otherwise, each extension needs to be included a specific file. +/// +/// +/// @defgroup gtx Experimental extensions +/// +/// @brief Experimental features not specified by GLSL specification. +/// +/// Experimental extensions are useful functions and types, but the development of +/// their API and functionality is not necessarily stable. They can change +/// substantially between versions. Backwards compatibility is not much of an issue +/// for them. +/// +/// Even if it's highly unrecommended, it's possible to include all the extensions +/// at once by including . Otherwise, each extension needs to be +/// included a specific file. +/// + +#include "detail/_fixes.hpp" + +#include "detail/setup.hpp" + +#pragma once + +#include +#include +#include +#include +#include +#include "fwd.hpp" + +#include "vec2.hpp" +#include "vec3.hpp" +#include "vec4.hpp" +#include "mat2x2.hpp" +#include "mat2x3.hpp" +#include "mat2x4.hpp" +#include "mat3x2.hpp" +#include "mat3x3.hpp" +#include "mat3x4.hpp" +#include "mat4x2.hpp" +#include "mat4x3.hpp" +#include "mat4x4.hpp" + +#include "trigonometric.hpp" +#include "exponential.hpp" +#include "common.hpp" +#include "packing.hpp" +#include "geometric.hpp" +#include "matrix.hpp" +#include "vector_relational.hpp" +#include "integer.hpp" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/bitfield.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/bitfield.hpp new file mode 100644 index 0000000..084fbe7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/bitfield.hpp @@ -0,0 +1,266 @@ +/// @ref gtc_bitfield +/// @file glm/gtc/bitfield.hpp +/// +/// @see core (dependence) +/// @see gtc_bitfield (dependence) +/// +/// @defgroup gtc_bitfield GLM_GTC_bitfield +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Allow to perform bit operations on integer values + +#include "../detail/setup.hpp" + +#pragma once + +// Dependencies +#include "../ext/scalar_int_sized.hpp" +#include "../ext/scalar_uint_sized.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/_vectorize.hpp" +#include "type_precision.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_bitfield extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_bitfield + /// @{ + + /// Build a mask of 'count' bits + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL genIUType mask(genIUType Bits); + + /// Build a mask of 'count' bits + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed and unsigned integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL vec mask(vec const& v); + + /// Rotate all bits to the right. All the bits dropped in the right side are inserted back on the left side. + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL genIUType bitfieldRotateRight(genIUType In, int Shift); + + /// Rotate all bits to the right. All the bits dropped in the right side are inserted back on the left side. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed and unsigned integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL vec bitfieldRotateRight(vec const& In, int Shift); + + /// Rotate all bits to the left. All the bits dropped in the left side are inserted back on the right side. + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL genIUType bitfieldRotateLeft(genIUType In, int Shift); + + /// Rotate all bits to the left. All the bits dropped in the left side are inserted back on the right side. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed and unsigned integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL vec bitfieldRotateLeft(vec const& In, int Shift); + + /// Set to 1 a range of bits. + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL genIUType bitfieldFillOne(genIUType Value, int FirstBit, int BitCount); + + /// Set to 1 a range of bits. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed and unsigned integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL vec bitfieldFillOne(vec const& Value, int FirstBit, int BitCount); + + /// Set to 0 a range of bits. + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL genIUType bitfieldFillZero(genIUType Value, int FirstBit, int BitCount); + + /// Set to 0 a range of bits. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed and unsigned integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL vec bitfieldFillZero(vec const& Value, int FirstBit, int BitCount); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int16 bitfieldInterleave(int8 x, int8 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint16 bitfieldInterleave(uint8 x, uint8 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of v.x followed by the first bit of v.y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint16 bitfieldInterleave(u8vec2 const& v); + + /// Deinterleaves the bits of x. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL glm::u8vec2 bitfieldDeinterleave(glm::uint16 x); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int32 bitfieldInterleave(int16 x, int16 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint32 bitfieldInterleave(uint16 x, uint16 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of v.x followed by the first bit of v.y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint32 bitfieldInterleave(u16vec2 const& v); + + /// Deinterleaves the bits of x. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL glm::u16vec2 bitfieldDeinterleave(glm::uint32 x); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int64 bitfieldInterleave(int32 x, int32 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(uint32 x, uint32 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of v.x followed by the first bit of v.y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(u32vec2 const& v); + + /// Deinterleaves the bits of x. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL glm::u32vec2 bitfieldDeinterleave(glm::uint64 x); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int32 bitfieldInterleave(int8 x, int8 y, int8 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int64 bitfieldInterleave(int16 x, int16 y, int16 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int64 bitfieldInterleave(int32 x, int32 y, int32 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(uint32 x, uint32 y, uint32 z); + + /// Interleaves the bits of x, y, z and w. + /// The first bit is the first bit of x followed by the first bit of y, the first bit of z and finally the first bit of w. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int32 bitfieldInterleave(int8 x, int8 y, int8 z, int8 w); + + /// Interleaves the bits of x, y, z and w. + /// The first bit is the first bit of x followed by the first bit of y, the first bit of z and finally the first bit of w. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z, uint8 w); + + /// Interleaves the bits of x, y, z and w. + /// The first bit is the first bit of x followed by the first bit of y, the first bit of z and finally the first bit of w. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int64 bitfieldInterleave(int16 x, int16 y, int16 z, int16 w); + + /// Interleaves the bits of x, y, z and w. + /// The first bit is the first bit of x followed by the first bit of y, the first bit of z and finally the first bit of w. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z, uint16 w); + + /// @} +} //namespace glm + +#include "bitfield.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/bitfield.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/bitfield.inl new file mode 100644 index 0000000..e7a0b4f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/bitfield.inl @@ -0,0 +1,635 @@ +/// @ref gtc_bitfield + +#include "../simd/integer.h" + +namespace glm{ +namespace detail +{ + template + GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y); + + template + GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y, PARAM z); + + template + GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y, PARAM z, PARAM w); + + template<> + GLM_FUNC_QUALIFIER glm::uint16 bitfieldInterleave(glm::uint8 x, glm::uint8 y) + { + glm::uint16 REG1(x); + glm::uint16 REG2(y); + + REG1 = ((REG1 << 4) | REG1) & static_cast(0x0F0F); + REG2 = ((REG2 << 4) | REG2) & static_cast(0x0F0F); + + REG1 = ((REG1 << 2) | REG1) & static_cast(0x3333); + REG2 = ((REG2 << 2) | REG2) & static_cast(0x3333); + + REG1 = ((REG1 << 1) | REG1) & static_cast(0x5555); + REG2 = ((REG2 << 1) | REG2) & static_cast(0x5555); + + return REG1 | static_cast(REG2 << 1); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(glm::uint16 x, glm::uint16 y) + { + glm::uint32 REG1(x); + glm::uint32 REG2(y); + + REG1 = ((REG1 << 8) | REG1) & static_cast(0x00FF00FF); + REG2 = ((REG2 << 8) | REG2) & static_cast(0x00FF00FF); + + REG1 = ((REG1 << 4) | REG1) & static_cast(0x0F0F0F0F); + REG2 = ((REG2 << 4) | REG2) & static_cast(0x0F0F0F0F); + + REG1 = ((REG1 << 2) | REG1) & static_cast(0x33333333); + REG2 = ((REG2 << 2) | REG2) & static_cast(0x33333333); + + REG1 = ((REG1 << 1) | REG1) & static_cast(0x55555555); + REG2 = ((REG2 << 1) | REG2) & static_cast(0x55555555); + + return REG1 | (REG2 << 1); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint32 x, glm::uint32 y) + { + glm::uint64 REG1(x); + glm::uint64 REG2(y); + + REG1 = ((REG1 << 16) | REG1) & static_cast(0x0000FFFF0000FFFFull); + REG2 = ((REG2 << 16) | REG2) & static_cast(0x0000FFFF0000FFFFull); + + REG1 = ((REG1 << 8) | REG1) & static_cast(0x00FF00FF00FF00FFull); + REG2 = ((REG2 << 8) | REG2) & static_cast(0x00FF00FF00FF00FFull); + + REG1 = ((REG1 << 4) | REG1) & static_cast(0x0F0F0F0F0F0F0F0Full); + REG2 = ((REG2 << 4) | REG2) & static_cast(0x0F0F0F0F0F0F0F0Full); + + REG1 = ((REG1 << 2) | REG1) & static_cast(0x3333333333333333ull); + REG2 = ((REG2 << 2) | REG2) & static_cast(0x3333333333333333ull); + + REG1 = ((REG1 << 1) | REG1) & static_cast(0x5555555555555555ull); + REG2 = ((REG2 << 1) | REG2) & static_cast(0x5555555555555555ull); + + return REG1 | (REG2 << 1); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(glm::uint8 x, glm::uint8 y, glm::uint8 z) + { + glm::uint32 REG1(x); + glm::uint32 REG2(y); + glm::uint32 REG3(z); + + REG1 = ((REG1 << 16) | REG1) & static_cast(0xFF0000FFu); + REG2 = ((REG2 << 16) | REG2) & static_cast(0xFF0000FFu); + REG3 = ((REG3 << 16) | REG3) & static_cast(0xFF0000FFu); + + REG1 = ((REG1 << 8) | REG1) & static_cast(0x0F00F00Fu); + REG2 = ((REG2 << 8) | REG2) & static_cast(0x0F00F00Fu); + REG3 = ((REG3 << 8) | REG3) & static_cast(0x0F00F00Fu); + + REG1 = ((REG1 << 4) | REG1) & static_cast(0xC30C30C3u); + REG2 = ((REG2 << 4) | REG2) & static_cast(0xC30C30C3u); + REG3 = ((REG3 << 4) | REG3) & static_cast(0xC30C30C3u); + + REG1 = ((REG1 << 2) | REG1) & static_cast(0x49249249u); + REG2 = ((REG2 << 2) | REG2) & static_cast(0x49249249u); + REG3 = ((REG3 << 2) | REG3) & static_cast(0x49249249u); + + return REG1 | (REG2 << 1) | (REG3 << 2); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint16 x, glm::uint16 y, glm::uint16 z) + { + glm::uint64 REG1(x); + glm::uint64 REG2(y); + glm::uint64 REG3(z); + + REG1 = ((REG1 << 32) | REG1) & static_cast(0xFFFF00000000FFFFull); + REG2 = ((REG2 << 32) | REG2) & static_cast(0xFFFF00000000FFFFull); + REG3 = ((REG3 << 32) | REG3) & static_cast(0xFFFF00000000FFFFull); + + REG1 = ((REG1 << 16) | REG1) & static_cast(0x00FF0000FF0000FFull); + REG2 = ((REG2 << 16) | REG2) & static_cast(0x00FF0000FF0000FFull); + REG3 = ((REG3 << 16) | REG3) & static_cast(0x00FF0000FF0000FFull); + + REG1 = ((REG1 << 8) | REG1) & static_cast(0xF00F00F00F00F00Full); + REG2 = ((REG2 << 8) | REG2) & static_cast(0xF00F00F00F00F00Full); + REG3 = ((REG3 << 8) | REG3) & static_cast(0xF00F00F00F00F00Full); + + REG1 = ((REG1 << 4) | REG1) & static_cast(0x30C30C30C30C30C3ull); + REG2 = ((REG2 << 4) | REG2) & static_cast(0x30C30C30C30C30C3ull); + REG3 = ((REG3 << 4) | REG3) & static_cast(0x30C30C30C30C30C3ull); + + REG1 = ((REG1 << 2) | REG1) & static_cast(0x9249249249249249ull); + REG2 = ((REG2 << 2) | REG2) & static_cast(0x9249249249249249ull); + REG3 = ((REG3 << 2) | REG3) & static_cast(0x9249249249249249ull); + + return REG1 | (REG2 << 1) | (REG3 << 2); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint32 x, glm::uint32 y, glm::uint32 z) + { + glm::uint64 REG1(x); + glm::uint64 REG2(y); + glm::uint64 REG3(z); + + REG1 = ((REG1 << 32) | REG1) & static_cast(0xFFFF00000000FFFFull); + REG2 = ((REG2 << 32) | REG2) & static_cast(0xFFFF00000000FFFFull); + REG3 = ((REG3 << 32) | REG3) & static_cast(0xFFFF00000000FFFFull); + + REG1 = ((REG1 << 16) | REG1) & static_cast(0x00FF0000FF0000FFull); + REG2 = ((REG2 << 16) | REG2) & static_cast(0x00FF0000FF0000FFull); + REG3 = ((REG3 << 16) | REG3) & static_cast(0x00FF0000FF0000FFull); + + REG1 = ((REG1 << 8) | REG1) & static_cast(0xF00F00F00F00F00Full); + REG2 = ((REG2 << 8) | REG2) & static_cast(0xF00F00F00F00F00Full); + REG3 = ((REG3 << 8) | REG3) & static_cast(0xF00F00F00F00F00Full); + + REG1 = ((REG1 << 4) | REG1) & static_cast(0x30C30C30C30C30C3ull); + REG2 = ((REG2 << 4) | REG2) & static_cast(0x30C30C30C30C30C3ull); + REG3 = ((REG3 << 4) | REG3) & static_cast(0x30C30C30C30C30C3ull); + + REG1 = ((REG1 << 2) | REG1) & static_cast(0x9249249249249249ull); + REG2 = ((REG2 << 2) | REG2) & static_cast(0x9249249249249249ull); + REG3 = ((REG3 << 2) | REG3) & static_cast(0x9249249249249249ull); + + return REG1 | (REG2 << 1) | (REG3 << 2); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(glm::uint8 x, glm::uint8 y, glm::uint8 z, glm::uint8 w) + { + glm::uint32 REG1(x); + glm::uint32 REG2(y); + glm::uint32 REG3(z); + glm::uint32 REG4(w); + + REG1 = ((REG1 << 12) | REG1) & static_cast(0x000F000Fu); + REG2 = ((REG2 << 12) | REG2) & static_cast(0x000F000Fu); + REG3 = ((REG3 << 12) | REG3) & static_cast(0x000F000Fu); + REG4 = ((REG4 << 12) | REG4) & static_cast(0x000F000Fu); + + REG1 = ((REG1 << 6) | REG1) & static_cast(0x03030303u); + REG2 = ((REG2 << 6) | REG2) & static_cast(0x03030303u); + REG3 = ((REG3 << 6) | REG3) & static_cast(0x03030303u); + REG4 = ((REG4 << 6) | REG4) & static_cast(0x03030303u); + + REG1 = ((REG1 << 3) | REG1) & static_cast(0x11111111u); + REG2 = ((REG2 << 3) | REG2) & static_cast(0x11111111u); + REG3 = ((REG3 << 3) | REG3) & static_cast(0x11111111u); + REG4 = ((REG4 << 3) | REG4) & static_cast(0x11111111u); + + return REG1 | (REG2 << 1) | (REG3 << 2) | (REG4 << 3); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint16 x, glm::uint16 y, glm::uint16 z, glm::uint16 w) + { + glm::uint64 REG1(x); + glm::uint64 REG2(y); + glm::uint64 REG3(z); + glm::uint64 REG4(w); + + REG1 = ((REG1 << 24) | REG1) & static_cast(0x000000FF000000FFull); + REG2 = ((REG2 << 24) | REG2) & static_cast(0x000000FF000000FFull); + REG3 = ((REG3 << 24) | REG3) & static_cast(0x000000FF000000FFull); + REG4 = ((REG4 << 24) | REG4) & static_cast(0x000000FF000000FFull); + + REG1 = ((REG1 << 12) | REG1) & static_cast(0x000F000F000F000Full); + REG2 = ((REG2 << 12) | REG2) & static_cast(0x000F000F000F000Full); + REG3 = ((REG3 << 12) | REG3) & static_cast(0x000F000F000F000Full); + REG4 = ((REG4 << 12) | REG4) & static_cast(0x000F000F000F000Full); + + REG1 = ((REG1 << 6) | REG1) & static_cast(0x0303030303030303ull); + REG2 = ((REG2 << 6) | REG2) & static_cast(0x0303030303030303ull); + REG3 = ((REG3 << 6) | REG3) & static_cast(0x0303030303030303ull); + REG4 = ((REG4 << 6) | REG4) & static_cast(0x0303030303030303ull); + + REG1 = ((REG1 << 3) | REG1) & static_cast(0x1111111111111111ull); + REG2 = ((REG2 << 3) | REG2) & static_cast(0x1111111111111111ull); + REG3 = ((REG3 << 3) | REG3) & static_cast(0x1111111111111111ull); + REG4 = ((REG4 << 3) | REG4) & static_cast(0x1111111111111111ull); + + return REG1 | (REG2 << 1) | (REG3 << 2) | (REG4 << 3); + } +}//namespace detail + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wsign-compare" +#endif + + template + GLM_FUNC_QUALIFIER genIUType mask(genIUType Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'mask' accepts only integer values"); + + return Bits >= sizeof(genIUType) * 8 ? ~static_cast(0) : (static_cast(1) << Bits) - static_cast(1); + } + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +#endif + + template + GLM_FUNC_QUALIFIER vec mask(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'mask' accepts only integer values"); + + return detail::functor1::call(mask, v); + } + + template + GLM_FUNC_QUALIFIER genIType bitfieldRotateRight(genIType In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldRotateRight' accepts only integer values"); + + int const BitSize = static_cast(sizeof(genIType) * 8); + return (In << static_cast(Shift)) | (In >> static_cast(BitSize - Shift)); + } + + template + GLM_FUNC_QUALIFIER vec bitfieldRotateRight(vec const& In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldRotateRight' accepts only integer values"); + + int const BitSize = static_cast(sizeof(T) * 8); + return (In << static_cast(Shift)) | (In >> static_cast(BitSize - Shift)); + } + + template + GLM_FUNC_QUALIFIER genIType bitfieldRotateLeft(genIType In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldRotateLeft' accepts only integer values"); + + int const BitSize = static_cast(sizeof(genIType) * 8); + return (In >> static_cast(Shift)) | (In << static_cast(BitSize - Shift)); + } + + template + GLM_FUNC_QUALIFIER vec bitfieldRotateLeft(vec const& In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldRotateLeft' accepts only integer values"); + + int const BitSize = static_cast(sizeof(T) * 8); + return (In >> static_cast(Shift)) | (In << static_cast(BitSize - Shift)); + } + + template + GLM_FUNC_QUALIFIER genIUType bitfieldFillOne(genIUType Value, int FirstBit, int BitCount) + { + return Value | static_cast(mask(BitCount) << FirstBit); + } + + template + GLM_FUNC_QUALIFIER vec bitfieldFillOne(vec const& Value, int FirstBit, int BitCount) + { + return Value | static_cast(mask(BitCount) << FirstBit); + } + + template + GLM_FUNC_QUALIFIER genIUType bitfieldFillZero(genIUType Value, int FirstBit, int BitCount) + { + return Value & static_cast(~(mask(BitCount) << FirstBit)); + } + + template + GLM_FUNC_QUALIFIER vec bitfieldFillZero(vec const& Value, int FirstBit, int BitCount) + { + return Value & static_cast(~(mask(BitCount) << FirstBit)); + } + + GLM_FUNC_QUALIFIER int16 bitfieldInterleave(int8 x, int8 y) + { + union sign8 + { + int8 i; + uint8 u; + } sign_x, sign_y; + + union sign16 + { + int16 i; + uint16 u; + } result; + + sign_x.i = x; + sign_y.i = y; + result.u = bitfieldInterleave(sign_x.u, sign_y.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint16 bitfieldInterleave(uint8 x, uint8 y) + { + return detail::bitfieldInterleave(x, y); + } + + GLM_FUNC_QUALIFIER uint16 bitfieldInterleave(u8vec2 const& v) + { + return detail::bitfieldInterleave(v.x, v.y); + } + + GLM_FUNC_QUALIFIER u8vec2 bitfieldDeinterleave(glm::uint16 x) + { + uint16 REG1(x); + uint16 REG2(x >>= 1); + + REG1 = REG1 & static_cast(0x5555); + REG2 = REG2 & static_cast(0x5555); + + REG1 = ((REG1 >> 1) | REG1) & static_cast(0x3333); + REG2 = ((REG2 >> 1) | REG2) & static_cast(0x3333); + + REG1 = ((REG1 >> 2) | REG1) & static_cast(0x0F0F); + REG2 = ((REG2 >> 2) | REG2) & static_cast(0x0F0F); + + REG1 = ((REG1 >> 4) | REG1) & static_cast(0x00FF); + REG2 = ((REG2 >> 4) | REG2) & static_cast(0x00FF); + + REG1 = ((REG1 >> 8) | REG1) & static_cast(0xFFFF); + REG2 = ((REG2 >> 8) | REG2) & static_cast(0xFFFF); + + return glm::u8vec2(REG1, REG2); + } + + GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int16 x, int16 y) + { + union sign16 + { + int16 i; + uint16 u; + } sign_x, sign_y; + + union sign32 + { + int32 i; + uint32 u; + } result; + + sign_x.i = x; + sign_y.i = y; + result.u = bitfieldInterleave(sign_x.u, sign_y.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(uint16 x, uint16 y) + { + return detail::bitfieldInterleave(x, y); + } + + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(u16vec2 const& v) + { + return detail::bitfieldInterleave(v.x, v.y); + } + + GLM_FUNC_QUALIFIER glm::u16vec2 bitfieldDeinterleave(glm::uint32 x) + { + glm::uint32 REG1(x); + glm::uint32 REG2(x >>= 1); + + REG1 = REG1 & static_cast(0x55555555); + REG2 = REG2 & static_cast(0x55555555); + + REG1 = ((REG1 >> 1) | REG1) & static_cast(0x33333333); + REG2 = ((REG2 >> 1) | REG2) & static_cast(0x33333333); + + REG1 = ((REG1 >> 2) | REG1) & static_cast(0x0F0F0F0F); + REG2 = ((REG2 >> 2) | REG2) & static_cast(0x0F0F0F0F); + + REG1 = ((REG1 >> 4) | REG1) & static_cast(0x00FF00FF); + REG2 = ((REG2 >> 4) | REG2) & static_cast(0x00FF00FF); + + REG1 = ((REG1 >> 8) | REG1) & static_cast(0x0000FFFF); + REG2 = ((REG2 >> 8) | REG2) & static_cast(0x0000FFFF); + + return glm::u16vec2(REG1, REG2); + } + + GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int32 x, int32 y) + { + union sign32 + { + int32 i; + uint32 u; + } sign_x, sign_y; + + union sign64 + { + int64 i; + uint64 u; + } result; + + sign_x.i = x; + sign_y.i = y; + result.u = bitfieldInterleave(sign_x.u, sign_y.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint32 x, uint32 y) + { + return detail::bitfieldInterleave(x, y); + } + + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(u32vec2 const& v) + { + return detail::bitfieldInterleave(v.x, v.y); + } + + GLM_FUNC_QUALIFIER glm::u32vec2 bitfieldDeinterleave(glm::uint64 x) + { + glm::uint64 REG1(x); + glm::uint64 REG2(x >>= 1); + + REG1 = REG1 & static_cast(0x5555555555555555ull); + REG2 = REG2 & static_cast(0x5555555555555555ull); + + REG1 = ((REG1 >> 1) | REG1) & static_cast(0x3333333333333333ull); + REG2 = ((REG2 >> 1) | REG2) & static_cast(0x3333333333333333ull); + + REG1 = ((REG1 >> 2) | REG1) & static_cast(0x0F0F0F0F0F0F0F0Full); + REG2 = ((REG2 >> 2) | REG2) & static_cast(0x0F0F0F0F0F0F0F0Full); + + REG1 = ((REG1 >> 4) | REG1) & static_cast(0x00FF00FF00FF00FFull); + REG2 = ((REG2 >> 4) | REG2) & static_cast(0x00FF00FF00FF00FFull); + + REG1 = ((REG1 >> 8) | REG1) & static_cast(0x0000FFFF0000FFFFull); + REG2 = ((REG2 >> 8) | REG2) & static_cast(0x0000FFFF0000FFFFull); + + REG1 = ((REG1 >> 16) | REG1) & static_cast(0x00000000FFFFFFFFull); + REG2 = ((REG2 >> 16) | REG2) & static_cast(0x00000000FFFFFFFFull); + + return glm::u32vec2(REG1, REG2); + } + + GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int8 x, int8 y, int8 z) + { + union sign8 + { + int8 i; + uint8 u; + } sign_x, sign_y, sign_z; + + union sign32 + { + int32 i; + uint32 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z) + { + return detail::bitfieldInterleave(x, y, z); + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(u8vec3 const& v) + { + return detail::bitfieldInterleave(v.x, v.y, v.z); + } + + GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int16 x, int16 y, int16 z) + { + union sign16 + { + int16 i; + uint16 u; + } sign_x, sign_y, sign_z; + + union sign64 + { + int64 i; + uint64 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z) + { + return detail::bitfieldInterleave(x, y, z); + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(u16vec3 const& v) + { + return detail::bitfieldInterleave(v.x, v.y, v.z); + } + + GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int32 x, int32 y, int32 z) + { + union sign16 + { + int32 i; + uint32 u; + } sign_x, sign_y, sign_z; + + union sign64 + { + int64 i; + uint64 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint32 x, uint32 y, uint32 z) + { + return detail::bitfieldInterleave(x, y, z); + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(u32vec3 const& v) + { + return detail::bitfieldInterleave(v.x, v.y, v.z); + } + + GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int8 x, int8 y, int8 z, int8 w) + { + union sign8 + { + int8 i; + uint8 u; + } sign_x, sign_y, sign_z, sign_w; + + union sign32 + { + int32 i; + uint32 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + sign_w.i = w; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u, sign_w.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z, uint8 w) + { + return detail::bitfieldInterleave(x, y, z, w); + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(u8vec4 const& v) + { + return detail::bitfieldInterleave(v.x, v.y, v.z, v.w); + } + + GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int16 x, int16 y, int16 z, int16 w) + { + union sign16 + { + int16 i; + uint16 u; + } sign_x, sign_y, sign_z, sign_w; + + union sign64 + { + int64 i; + uint64 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + sign_w.i = w; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u, sign_w.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z, uint16 w) + { + return detail::bitfieldInterleave(x, y, z, w); + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(u16vec4 const& v) + { + return detail::bitfieldInterleave(v.x, v.y, v.z, v.w); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/color_space.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/color_space.hpp new file mode 100644 index 0000000..cffd9f0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/color_space.hpp @@ -0,0 +1,56 @@ +/// @ref gtc_color_space +/// @file glm/gtc/color_space.hpp +/// +/// @see core (dependence) +/// @see gtc_color_space (dependence) +/// +/// @defgroup gtc_color_space GLM_GTC_color_space +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Allow to perform bit operations on integer values + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../exponential.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_color_space extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_color_space + /// @{ + + /// Convert a linear color to sRGB color using a standard gamma correction. + /// IEC 61966-2-1:1999 / Rec. 709 specification https://www.w3.org/Graphics/Color/srgb + template + GLM_FUNC_DECL vec convertLinearToSRGB(vec const& ColorLinear); + + /// Convert a linear color to sRGB color using a custom gamma correction. + /// IEC 61966-2-1:1999 / Rec. 709 specification https://www.w3.org/Graphics/Color/srgb + template + GLM_FUNC_DECL vec convertLinearToSRGB(vec const& ColorLinear, T Gamma); + + /// Convert a sRGB color to linear color using a standard gamma correction. + /// IEC 61966-2-1:1999 / Rec. 709 specification https://www.w3.org/Graphics/Color/srgb + template + GLM_FUNC_DECL vec convertSRGBToLinear(vec const& ColorSRGB); + + /// Convert a sRGB color to linear color using a custom gamma correction. + // IEC 61966-2-1:1999 / Rec. 709 specification https://www.w3.org/Graphics/Color/srgb + template + GLM_FUNC_DECL vec convertSRGBToLinear(vec const& ColorSRGB, T Gamma); + + /// @} +} //namespace glm + +#include "color_space.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/color_space.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/color_space.inl new file mode 100644 index 0000000..2a90004 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/color_space.inl @@ -0,0 +1,84 @@ +/// @ref gtc_color_space + +namespace glm{ +namespace detail +{ + template + struct compute_rgbToSrgb + { + GLM_FUNC_QUALIFIER static vec call(vec const& ColorRGB, T GammaCorrection) + { + vec const ClampedColor(clamp(ColorRGB, static_cast(0), static_cast(1))); + + return mix( + pow(ClampedColor, vec(GammaCorrection)) * static_cast(1.055) - static_cast(0.055), + ClampedColor * static_cast(12.92), + lessThan(ClampedColor, vec(static_cast(0.0031308)))); + } + }; + + template + struct compute_rgbToSrgb<4, T, Q> + { + GLM_FUNC_QUALIFIER static vec<4, T, Q> call(vec<4, T, Q> const& ColorRGB, T GammaCorrection) + { + return vec<4, T, Q>(compute_rgbToSrgb<3, T, Q>::call(vec<3, T, Q>(ColorRGB), GammaCorrection), ColorRGB.w); + } + }; + + template + struct compute_srgbToRgb + { + GLM_FUNC_QUALIFIER static vec call(vec const& ColorSRGB, T Gamma) + { + return mix( + pow((ColorSRGB + static_cast(0.055)) * static_cast(0.94786729857819905213270142180095), vec(Gamma)), + ColorSRGB * static_cast(0.07739938080495356037151702786378), + lessThanEqual(ColorSRGB, vec(static_cast(0.04045)))); + } + }; + + template + struct compute_srgbToRgb<4, T, Q> + { + GLM_FUNC_QUALIFIER static vec<4, T, Q> call(vec<4, T, Q> const& ColorSRGB, T Gamma) + { + return vec<4, T, Q>(compute_srgbToRgb<3, T, Q>::call(vec<3, T, Q>(ColorSRGB), Gamma), ColorSRGB.w); + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER vec convertLinearToSRGB(vec const& ColorLinear) + { + return detail::compute_rgbToSrgb::call(ColorLinear, static_cast(0.41666)); + } + + // Based on Ian Taylor http://chilliant.blogspot.fr/2012/08/srgb-approximations-for-hlsl.html + template<> + GLM_FUNC_QUALIFIER vec<3, float, lowp> convertLinearToSRGB(vec<3, float, lowp> const& ColorLinear) + { + vec<3, float, lowp> S1 = sqrt(ColorLinear); + vec<3, float, lowp> S2 = sqrt(S1); + vec<3, float, lowp> S3 = sqrt(S2); + return 0.662002687f * S1 + 0.684122060f * S2 - 0.323583601f * S3 - 0.0225411470f * ColorLinear; + } + + template + GLM_FUNC_QUALIFIER vec convertLinearToSRGB(vec const& ColorLinear, T Gamma) + { + return detail::compute_rgbToSrgb::call(ColorLinear, static_cast(1) / Gamma); + } + + template + GLM_FUNC_QUALIFIER vec convertSRGBToLinear(vec const& ColorSRGB) + { + return detail::compute_srgbToRgb::call(ColorSRGB, static_cast(2.4)); + } + + template + GLM_FUNC_QUALIFIER vec convertSRGBToLinear(vec const& ColorSRGB, T Gamma) + { + return detail::compute_srgbToRgb::call(ColorSRGB, Gamma); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/constants.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/constants.hpp new file mode 100644 index 0000000..6a1f37d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/constants.hpp @@ -0,0 +1,170 @@ +/// @ref gtc_constants +/// @file glm/gtc/constants.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_constants GLM_GTC_constants +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Provide a list of constants and precomputed useful values. + +#pragma once + +// Dependencies +#include "../ext/scalar_constants.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_constants extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_constants + /// @{ + + /// Return 0. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType zero(); + + /// Return 1. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType one(); + + /// Return pi * 2. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType two_pi(); + + /// Return unit-circle circumference, or pi * 2. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType tau(); + + /// Return square root of pi. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_pi(); + + /// Return pi / 2. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType half_pi(); + + /// Return pi / 2 * 3. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType three_over_two_pi(); + + /// Return pi / 4. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType quarter_pi(); + + /// Return 1 / pi. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType one_over_pi(); + + /// Return 1 / (pi * 2). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType one_over_two_pi(); + + /// Return 2 / pi. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType two_over_pi(); + + /// Return 4 / pi. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType four_over_pi(); + + /// Return 2 / sqrt(pi). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType two_over_root_pi(); + + /// Return 1 / sqrt(2). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType one_over_root_two(); + + /// Return sqrt(pi / 2). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_half_pi(); + + /// Return sqrt(2 * pi). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_two_pi(); + + /// Return sqrt(ln(4)). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_ln_four(); + + /// Return e constant. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType e(); + + /// Return Euler's constant. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType euler(); + + /// Return sqrt(2). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_two(); + + /// Return sqrt(3). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_three(); + + /// Return sqrt(5). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_five(); + + /// Return ln(2). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType ln_two(); + + /// Return ln(10). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType ln_ten(); + + /// Return ln(ln(2)). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType ln_ln_two(); + + /// Return 1 / 3. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType third(); + + /// Return 2 / 3. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType two_thirds(); + + /// Return the golden ratio constant. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType golden_ratio(); + + /// @} +} //namespace glm + +#include "constants.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/constants.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/constants.inl new file mode 100644 index 0000000..e9d3776 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/constants.inl @@ -0,0 +1,173 @@ +/// @ref gtc_constants + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType zero() + { + return genType(0); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType one() + { + return genType(1); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType two_pi() + { + return genType(6.28318530717958647692528676655900576); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType tau() + { + return two_pi(); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_pi() + { + return genType(1.772453850905516027); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType half_pi() + { + return genType(1.57079632679489661923132169163975144); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType three_over_two_pi() + { + return genType(4.71238898038468985769396507491925432); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType quarter_pi() + { + return genType(0.785398163397448309615660845819875721); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType one_over_pi() + { + return genType(0.318309886183790671537767526745028724); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType one_over_two_pi() + { + return genType(0.159154943091895335768883763372514362); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType two_over_pi() + { + return genType(0.636619772367581343075535053490057448); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType four_over_pi() + { + return genType(1.273239544735162686151070106980114898); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType two_over_root_pi() + { + return genType(1.12837916709551257389615890312154517); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType one_over_root_two() + { + return genType(0.707106781186547524400844362104849039); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_half_pi() + { + return genType(1.253314137315500251); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_two_pi() + { + return genType(2.506628274631000502); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_ln_four() + { + return genType(1.17741002251547469); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType e() + { + return genType(2.71828182845904523536); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType euler() + { + return genType(0.577215664901532860606); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_two() + { + return genType(1.41421356237309504880168872420969808); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_three() + { + return genType(1.73205080756887729352744634150587236); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_five() + { + return genType(2.23606797749978969640917366873127623); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType ln_two() + { + return genType(0.693147180559945309417232121458176568); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType ln_ten() + { + return genType(2.30258509299404568401799145468436421); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType ln_ln_two() + { + return genType(-0.3665129205816643); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType third() + { + return genType(0.3333333333333333333333333333333333333333); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType two_thirds() + { + return genType(0.666666666666666666666666666666666666667); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType golden_ratio() + { + return genType(1.61803398874989484820458683436563811); + } + +} //namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/epsilon.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/epsilon.hpp new file mode 100644 index 0000000..640439b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/epsilon.hpp @@ -0,0 +1,60 @@ +/// @ref gtc_epsilon +/// @file glm/gtc/epsilon.hpp +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtc_epsilon GLM_GTC_epsilon +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Comparison functions for a user defined epsilon values. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_epsilon extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_epsilon + /// @{ + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @see gtc_epsilon + template + GLM_FUNC_DECL vec epsilonEqual(vec const& x, vec const& y, T const& epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @see gtc_epsilon + template + GLM_FUNC_DECL bool epsilonEqual(genType const& x, genType const& y, genType const& epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is not satisfied. + /// + /// @see gtc_epsilon + template + GLM_FUNC_DECL vec epsilonNotEqual(vec const& x, vec const& y, T const& epsilon); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// True if this expression is not satisfied. + /// + /// @see gtc_epsilon + template + GLM_FUNC_DECL bool epsilonNotEqual(genType const& x, genType const& y, genType const& epsilon); + + /// @} +}//namespace glm + +#include "epsilon.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/epsilon.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/epsilon.inl new file mode 100644 index 0000000..508b9f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/epsilon.inl @@ -0,0 +1,80 @@ +/// @ref gtc_epsilon + +// Dependency: +#include "../vector_relational.hpp" +#include "../common.hpp" + +namespace glm +{ + template<> + GLM_FUNC_QUALIFIER bool epsilonEqual + ( + float const& x, + float const& y, + float const& epsilon + ) + { + return abs(x - y) < epsilon; + } + + template<> + GLM_FUNC_QUALIFIER bool epsilonEqual + ( + double const& x, + double const& y, + double const& epsilon + ) + { + return abs(x - y) < epsilon; + } + + template + GLM_FUNC_QUALIFIER vec epsilonEqual(vec const& x, vec const& y, T const& epsilon) + { + return lessThan(abs(x - y), vec(epsilon)); + } + + template + GLM_FUNC_QUALIFIER vec epsilonEqual(vec const& x, vec const& y, vec const& epsilon) + { + return lessThan(abs(x - y), vec(epsilon)); + } + + template<> + GLM_FUNC_QUALIFIER bool epsilonNotEqual(float const& x, float const& y, float const& epsilon) + { + return abs(x - y) >= epsilon; + } + + template<> + GLM_FUNC_QUALIFIER bool epsilonNotEqual(double const& x, double const& y, double const& epsilon) + { + return abs(x - y) >= epsilon; + } + + template + GLM_FUNC_QUALIFIER vec epsilonNotEqual(vec const& x, vec const& y, T const& epsilon) + { + return greaterThanEqual(abs(x - y), vec(epsilon)); + } + + template + GLM_FUNC_QUALIFIER vec epsilonNotEqual(vec const& x, vec const& y, vec const& epsilon) + { + return greaterThanEqual(abs(x - y), vec(epsilon)); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> epsilonEqual(qua const& x, qua const& y, T const& epsilon) + { + vec<4, T, Q> v(x.x - y.x, x.y - y.y, x.z - y.z, x.w - y.w); + return lessThan(abs(v), vec<4, T, Q>(epsilon)); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> epsilonNotEqual(qua const& x, qua const& y, T const& epsilon) + { + vec<4, T, Q> v(x.x - y.x, x.y - y.y, x.z - y.z, x.w - y.w); + return greaterThanEqual(abs(v), vec<4, T, Q>(epsilon)); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/integer.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/integer.hpp new file mode 100644 index 0000000..cff08dc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/integer.hpp @@ -0,0 +1,43 @@ +/// @ref gtc_integer +/// @file glm/gtc/integer.hpp +/// +/// @see core (dependence) +/// @see gtc_integer (dependence) +/// +/// @defgroup gtc_integer GLM_GTC_integer +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// @brief Allow to perform bit operations on integer values + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../common.hpp" +#include "../integer.hpp" +#include "../exponential.hpp" +#include "../ext/scalar_common.hpp" +#include "../ext/vector_common.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_integer + /// @{ + + /// Returns the log2 of x for integer values. Useful to compute mipmap count from the texture size. + /// @see gtc_integer + template + GLM_FUNC_DECL vec log2(vec const& v); + + /// @} +} //namespace glm + +#include "integer.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/integer.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/integer.inl new file mode 100644 index 0000000..5f66dfe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/integer.inl @@ -0,0 +1,33 @@ +/// @ref gtc_integer + +namespace glm{ +namespace detail +{ + template + struct compute_log2 + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + //Equivalent to return findMSB(vec); but save one function call in ASM with VC + //return findMSB(vec); + return vec(detail::compute_findMSB_vec::call(v)); + } + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template + struct compute_log2<4, int, Q, false, Aligned> + { + GLM_FUNC_QUALIFIER static vec<4, int, Q> call(vec<4, int, Q> const& v) + { + vec<4, int, Q> Result; + _BitScanReverse(reinterpret_cast(&Result.x), v.x); + _BitScanReverse(reinterpret_cast(&Result.y), v.y); + _BitScanReverse(reinterpret_cast(&Result.z), v.z); + _BitScanReverse(reinterpret_cast(&Result.w), v.w); + return Result; + } + }; +# endif//GLM_HAS_BITSCAN_WINDOWS +}//namespace detail +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_access.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_access.hpp new file mode 100644 index 0000000..4935ba7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_access.hpp @@ -0,0 +1,60 @@ +/// @ref gtc_matrix_access +/// @file glm/gtc/matrix_access.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_matrix_access GLM_GTC_matrix_access +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines functions to access rows or columns of a matrix easily. + +#pragma once + +// Dependency: +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_matrix_access extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_matrix_access + /// @{ + + /// Get a specific row of a matrix. + /// @see gtc_matrix_access + template + GLM_FUNC_DECL typename genType::row_type row( + genType const& m, + length_t index); + + /// Set a specific row to a matrix. + /// @see gtc_matrix_access + template + GLM_FUNC_DECL genType row( + genType const& m, + length_t index, + typename genType::row_type const& x); + + /// Get a specific column of a matrix. + /// @see gtc_matrix_access + template + GLM_FUNC_DECL typename genType::col_type column( + genType const& m, + length_t index); + + /// Set a specific column to a matrix. + /// @see gtc_matrix_access + template + GLM_FUNC_DECL genType column( + genType const& m, + length_t index, + typename genType::col_type const& x); + + /// @} +}//namespace glm + +#include "matrix_access.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_access.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_access.inl new file mode 100644 index 0000000..09fcc10 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_access.inl @@ -0,0 +1,62 @@ +/// @ref gtc_matrix_access + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType row + ( + genType const& m, + length_t index, + typename genType::row_type const& x + ) + { + assert(index >= 0 && index < m[0].length()); + + genType Result = m; + for(length_t i = 0; i < m.length(); ++i) + Result[i][index] = x[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER typename genType::row_type row + ( + genType const& m, + length_t index + ) + { + assert(index >= 0 && index < m[0].length()); + + typename genType::row_type Result(0); + for(length_t i = 0; i < m.length(); ++i) + Result[i] = m[i][index]; + return Result; + } + + template + GLM_FUNC_QUALIFIER genType column + ( + genType const& m, + length_t index, + typename genType::col_type const& x + ) + { + assert(index >= 0 && index < m.length()); + + genType Result = m; + Result[index] = x; + return Result; + } + + template + GLM_FUNC_QUALIFIER typename genType::col_type column + ( + genType const& m, + length_t index + ) + { + assert(index >= 0 && index < m.length()); + + return m[index]; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_integer.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_integer.hpp new file mode 100644 index 0000000..d7ebdc7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_integer.hpp @@ -0,0 +1,433 @@ +/// @ref gtc_matrix_integer +/// @file glm/gtc/matrix_integer.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_matrix_integer GLM_GTC_matrix_integer +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x2.hpp" +#include "../mat2x3.hpp" +#include "../mat2x4.hpp" +#include "../mat3x2.hpp" +#include "../mat3x3.hpp" +#include "../mat3x4.hpp" +#include "../mat4x2.hpp" +#include "../mat4x3.hpp" +#include "../mat4x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_matrix_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_matrix_integer + /// @{ + + /// High-qualifier signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, highp> highp_imat2; + + /// High-qualifier signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, highp> highp_imat3; + + /// High-qualifier signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, highp> highp_imat4; + + /// High-qualifier signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, highp> highp_imat2x2; + + /// High-qualifier signed integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, int, highp> highp_imat2x3; + + /// High-qualifier signed integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, int, highp> highp_imat2x4; + + /// High-qualifier signed integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, int, highp> highp_imat3x2; + + /// High-qualifier signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, highp> highp_imat3x3; + + /// High-qualifier signed integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, int, highp> highp_imat3x4; + + /// High-qualifier signed integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, int, highp> highp_imat4x2; + + /// High-qualifier signed integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, int, highp> highp_imat4x3; + + /// High-qualifier signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, highp> highp_imat4x4; + + + /// Medium-qualifier signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, mediump> mediump_imat2; + + /// Medium-qualifier signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, mediump> mediump_imat3; + + /// Medium-qualifier signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, mediump> mediump_imat4; + + + /// Medium-qualifier signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, mediump> mediump_imat2x2; + + /// Medium-qualifier signed integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, int, mediump> mediump_imat2x3; + + /// Medium-qualifier signed integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, int, mediump> mediump_imat2x4; + + /// Medium-qualifier signed integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, int, mediump> mediump_imat3x2; + + /// Medium-qualifier signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, mediump> mediump_imat3x3; + + /// Medium-qualifier signed integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, int, mediump> mediump_imat3x4; + + /// Medium-qualifier signed integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, int, mediump> mediump_imat4x2; + + /// Medium-qualifier signed integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, int, mediump> mediump_imat4x3; + + /// Medium-qualifier signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, mediump> mediump_imat4x4; + + + /// Low-qualifier signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, lowp> lowp_imat2; + + /// Low-qualifier signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, lowp> lowp_imat3; + + /// Low-qualifier signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, lowp> lowp_imat4; + + + /// Low-qualifier signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, lowp> lowp_imat2x2; + + /// Low-qualifier signed integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, int, lowp> lowp_imat2x3; + + /// Low-qualifier signed integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, int, lowp> lowp_imat2x4; + + /// Low-qualifier signed integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, int, lowp> lowp_imat3x2; + + /// Low-qualifier signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, lowp> lowp_imat3x3; + + /// Low-qualifier signed integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, int, lowp> lowp_imat3x4; + + /// Low-qualifier signed integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, int, lowp> lowp_imat4x2; + + /// Low-qualifier signed integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, int, lowp> lowp_imat4x3; + + /// Low-qualifier signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, lowp> lowp_imat4x4; + + + /// High-qualifier unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, highp> highp_umat2; + + /// High-qualifier unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, highp> highp_umat3; + + /// High-qualifier unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, highp> highp_umat4; + + /// High-qualifier unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, highp> highp_umat2x2; + + /// High-qualifier unsigned integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, uint, highp> highp_umat2x3; + + /// High-qualifier unsigned integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, uint, highp> highp_umat2x4; + + /// High-qualifier unsigned integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, uint, highp> highp_umat3x2; + + /// High-qualifier unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, highp> highp_umat3x3; + + /// High-qualifier unsigned integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, uint, highp> highp_umat3x4; + + /// High-qualifier unsigned integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, uint, highp> highp_umat4x2; + + /// High-qualifier unsigned integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, uint, highp> highp_umat4x3; + + /// High-qualifier unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, highp> highp_umat4x4; + + + /// Medium-qualifier unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, mediump> mediump_umat2; + + /// Medium-qualifier unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, mediump> mediump_umat3; + + /// Medium-qualifier unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, mediump> mediump_umat4; + + + /// Medium-qualifier unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, mediump> mediump_umat2x2; + + /// Medium-qualifier unsigned integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, uint, mediump> mediump_umat2x3; + + /// Medium-qualifier unsigned integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, uint, mediump> mediump_umat2x4; + + /// Medium-qualifier unsigned integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, uint, mediump> mediump_umat3x2; + + /// Medium-qualifier unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, mediump> mediump_umat3x3; + + /// Medium-qualifier unsigned integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, uint, mediump> mediump_umat3x4; + + /// Medium-qualifier unsigned integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, uint, mediump> mediump_umat4x2; + + /// Medium-qualifier unsigned integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, uint, mediump> mediump_umat4x3; + + /// Medium-qualifier unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, mediump> mediump_umat4x4; + + + /// Low-qualifier unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, lowp> lowp_umat2; + + /// Low-qualifier unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, lowp> lowp_umat3; + + /// Low-qualifier unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, lowp> lowp_umat4; + + + /// Low-qualifier unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, lowp> lowp_umat2x2; + + /// Low-qualifier unsigned integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, uint, lowp> lowp_umat2x3; + + /// Low-qualifier unsigned integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, uint, lowp> lowp_umat2x4; + + /// Low-qualifier unsigned integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, uint, lowp> lowp_umat3x2; + + /// Low-qualifier unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, lowp> lowp_umat3x3; + + /// Low-qualifier unsigned integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, uint, lowp> lowp_umat3x4; + + /// Low-qualifier unsigned integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, uint, lowp> lowp_umat4x2; + + /// Low-qualifier unsigned integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, uint, lowp> lowp_umat4x3; + + /// Low-qualifier unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, lowp> lowp_umat4x4; + + + + /// Signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, defaultp> imat2; + + /// Signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, defaultp> imat3; + + /// Signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, defaultp> imat4; + + /// Signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, defaultp> imat2x2; + + /// Signed integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, int, defaultp> imat2x3; + + /// Signed integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, int, defaultp> imat2x4; + + /// Signed integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, int, defaultp> imat3x2; + + /// Signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, defaultp> imat3x3; + + /// Signed integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, int, defaultp> imat3x4; + + /// Signed integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, int, defaultp> imat4x2; + + /// Signed integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, int, defaultp> imat4x3; + + /// Signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, defaultp> imat4x4; + + + + /// Unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, defaultp> umat2; + + /// Unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, defaultp> umat3; + + /// Unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, defaultp> umat4; + + /// Unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, defaultp> umat2x2; + + /// Unsigned integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, uint, defaultp> umat2x3; + + /// Unsigned integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, uint, defaultp> umat2x4; + + /// Unsigned integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, uint, defaultp> umat3x2; + + /// Unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, defaultp> umat3x3; + + /// Unsigned integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, uint, defaultp> umat3x4; + + /// Unsigned integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, uint, defaultp> umat4x2; + + /// Unsigned integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, uint, defaultp> umat4x3; + + /// Unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, defaultp> umat4x4; + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_inverse.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_inverse.hpp new file mode 100644 index 0000000..75d53f2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_inverse.hpp @@ -0,0 +1,50 @@ +/// @ref gtc_matrix_inverse +/// @file glm/gtc/matrix_inverse.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_matrix_inverse GLM_GTC_matrix_inverse +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines additional matrix inverting functions. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../matrix.hpp" +#include "../mat2x2.hpp" +#include "../mat3x3.hpp" +#include "../mat4x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_matrix_inverse extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_matrix_inverse + /// @{ + + /// Fast matrix inverse for affine matrix. + /// + /// @param m Input matrix to invert. + /// @tparam genType Squared floating-point matrix: half, float or double. Inverse of matrix based of half-qualifier floating point value is highly inaccurate. + /// @see gtc_matrix_inverse + template + GLM_FUNC_DECL genType affineInverse(genType const& m); + + /// Compute the inverse transpose of a matrix. + /// + /// @param m Input matrix to invert transpose. + /// @tparam genType Squared floating-point matrix: half, float or double. Inverse of matrix based of half-qualifier floating point value is highly inaccurate. + /// @see gtc_matrix_inverse + template + GLM_FUNC_DECL genType inverseTranspose(genType const& m); + + /// @} +}//namespace glm + +#include "matrix_inverse.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_inverse.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_inverse.inl new file mode 100644 index 0000000..c004b9e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_inverse.inl @@ -0,0 +1,118 @@ +/// @ref gtc_matrix_inverse + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> affineInverse(mat<3, 3, T, Q> const& m) + { + mat<2, 2, T, Q> const Inv(inverse(mat<2, 2, T, Q>(m))); + + return mat<3, 3, T, Q>( + vec<3, T, Q>(Inv[0], static_cast(0)), + vec<3, T, Q>(Inv[1], static_cast(0)), + vec<3, T, Q>(-Inv * vec<2, T, Q>(m[2]), static_cast(1))); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> affineInverse(mat<4, 4, T, Q> const& m) + { + mat<3, 3, T, Q> const Inv(inverse(mat<3, 3, T, Q>(m))); + + return mat<4, 4, T, Q>( + vec<4, T, Q>(Inv[0], static_cast(0)), + vec<4, T, Q>(Inv[1], static_cast(0)), + vec<4, T, Q>(Inv[2], static_cast(0)), + vec<4, T, Q>(-Inv * vec<3, T, Q>(m[3]), static_cast(1))); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> inverseTranspose(mat<2, 2, T, Q> const& m) + { + T Determinant = m[0][0] * m[1][1] - m[1][0] * m[0][1]; + + mat<2, 2, T, Q> Inverse( + + m[1][1] / Determinant, + - m[0][1] / Determinant, + - m[1][0] / Determinant, + + m[0][0] / Determinant); + + return Inverse; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> inverseTranspose(mat<3, 3, T, Q> const& m) + { + T Determinant = + + m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) + - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) + + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); + + mat<3, 3, T, Q> Inverse; + Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]); + Inverse[0][1] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]); + Inverse[0][2] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]); + Inverse[1][0] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]); + Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]); + Inverse[1][2] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]); + Inverse[2][0] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]); + Inverse[2][1] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]); + Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]); + Inverse /= Determinant; + + return Inverse; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> inverseTranspose(mat<4, 4, T, Q> const& m) + { + T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + T SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + T SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + T SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + T SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + T SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + T SubFactor11 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + T SubFactor12 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + T SubFactor13 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + T SubFactor14 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + T SubFactor15 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + T SubFactor16 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + T SubFactor17 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + mat<4, 4, T, Q> Inverse; + Inverse[0][0] = + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02); + Inverse[0][1] = - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04); + Inverse[0][2] = + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05); + Inverse[0][3] = - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05); + + Inverse[1][0] = - (m[0][1] * SubFactor00 - m[0][2] * SubFactor01 + m[0][3] * SubFactor02); + Inverse[1][1] = + (m[0][0] * SubFactor00 - m[0][2] * SubFactor03 + m[0][3] * SubFactor04); + Inverse[1][2] = - (m[0][0] * SubFactor01 - m[0][1] * SubFactor03 + m[0][3] * SubFactor05); + Inverse[1][3] = + (m[0][0] * SubFactor02 - m[0][1] * SubFactor04 + m[0][2] * SubFactor05); + + Inverse[2][0] = + (m[0][1] * SubFactor06 - m[0][2] * SubFactor07 + m[0][3] * SubFactor08); + Inverse[2][1] = - (m[0][0] * SubFactor06 - m[0][2] * SubFactor09 + m[0][3] * SubFactor10); + Inverse[2][2] = + (m[0][0] * SubFactor07 - m[0][1] * SubFactor09 + m[0][3] * SubFactor11); + Inverse[2][3] = - (m[0][0] * SubFactor08 - m[0][1] * SubFactor10 + m[0][2] * SubFactor11); + + Inverse[3][0] = - (m[0][1] * SubFactor12 - m[0][2] * SubFactor13 + m[0][3] * SubFactor14); + Inverse[3][1] = + (m[0][0] * SubFactor12 - m[0][2] * SubFactor15 + m[0][3] * SubFactor16); + Inverse[3][2] = - (m[0][0] * SubFactor13 - m[0][1] * SubFactor15 + m[0][3] * SubFactor17); + Inverse[3][3] = + (m[0][0] * SubFactor14 - m[0][1] * SubFactor16 + m[0][2] * SubFactor17); + + T Determinant = + + m[0][0] * Inverse[0][0] + + m[0][1] * Inverse[0][1] + + m[0][2] * Inverse[0][2] + + m[0][3] * Inverse[0][3]; + + Inverse /= Determinant; + + return Inverse; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_transform.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_transform.hpp new file mode 100644 index 0000000..612418f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_transform.hpp @@ -0,0 +1,36 @@ +/// @ref gtc_matrix_transform +/// @file glm/gtc/matrix_transform.hpp +/// +/// @see core (dependence) +/// @see gtx_transform +/// @see gtx_transform2 +/// +/// @defgroup gtc_matrix_transform GLM_GTC_matrix_transform +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines functions that generate common transformation matrices. +/// +/// The matrices generated by this extension use standard OpenGL fixed-function +/// conventions. For example, the lookAt function generates a transform from world +/// space into the specific eye space that the projective matrix functions +/// (perspective, ortho, etc) are designed to expect. The OpenGL compatibility +/// specifications defines the particular layout of this eye space. + +#pragma once + +// Dependencies +#include "../mat4x4.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../ext/matrix_projection.hpp" +#include "../ext/matrix_clip_space.hpp" +#include "../ext/matrix_transform.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_matrix_transform extension included") +#endif + +#include "matrix_transform.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_transform.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_transform.inl new file mode 100644 index 0000000..15b46bc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_transform.inl @@ -0,0 +1,3 @@ +#include "../geometric.hpp" +#include "../trigonometric.hpp" +#include "../matrix.hpp" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/noise.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/noise.hpp new file mode 100644 index 0000000..ab1772e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/noise.hpp @@ -0,0 +1,61 @@ +/// @ref gtc_noise +/// @file glm/gtc/noise.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_noise GLM_GTC_noise +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines 2D, 3D and 4D procedural noise functions +/// Based on the work of Stefan Gustavson and Ashima Arts on "webgl-noise": +/// https://github.com/ashima/webgl-noise +/// Following Stefan Gustavson's paper "Simplex noise demystified": +/// http://www.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/_noise.hpp" +#include "../geometric.hpp" +#include "../common.hpp" +#include "../vector_relational.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_noise extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_noise + /// @{ + + /// Classic perlin noise. + /// @see gtc_noise + template + GLM_FUNC_DECL T perlin( + vec const& p); + + /// Periodic perlin noise. + /// @see gtc_noise + template + GLM_FUNC_DECL T perlin( + vec const& p, + vec const& rep); + + /// Simplex noise. + /// @see gtc_noise + template + GLM_FUNC_DECL T simplex( + vec const& p); + + /// @} +}//namespace glm + +#include "noise.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/noise.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/noise.inl new file mode 100644 index 0000000..a1cf399 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/noise.inl @@ -0,0 +1,807 @@ +/// @ref gtc_noise +/// +// Based on the work of Stefan Gustavson and Ashima Arts on "webgl-noise": +// https://github.com/ashima/webgl-noise +// Following Stefan Gustavson's paper "Simplex noise demystified": +// http://www.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf + +namespace glm{ +namespace detail +{ + template + GLM_FUNC_QUALIFIER vec<4, T, Q> grad4(T const& j, vec<4, T, Q> const& ip) + { + vec<3, T, Q> pXYZ = floor(fract(vec<3, T, Q>(j) * vec<3, T, Q>(ip)) * T(7)) * ip[2] - T(1); + T pW = static_cast(1.5) - dot(abs(pXYZ), vec<3, T, Q>(1)); + vec<4, T, Q> s = vec<4, T, Q>(lessThan(vec<4, T, Q>(pXYZ, pW), vec<4, T, Q>(0.0))); + pXYZ = pXYZ + (vec<3, T, Q>(s) * T(2) - T(1)) * s.w; + return vec<4, T, Q>(pXYZ, pW); + } +}//namespace detail + + // Classic Perlin noise + template + GLM_FUNC_QUALIFIER T perlin(vec<2, T, Q> const& Position) + { + vec<4, T, Q> Pi = glm::floor(vec<4, T, Q>(Position.x, Position.y, Position.x, Position.y)) + vec<4, T, Q>(0.0, 0.0, 1.0, 1.0); + vec<4, T, Q> Pf = glm::fract(vec<4, T, Q>(Position.x, Position.y, Position.x, Position.y)) - vec<4, T, Q>(0.0, 0.0, 1.0, 1.0); + Pi = mod(Pi, vec<4, T, Q>(289)); // To avoid truncation effects in permutation + vec<4, T, Q> ix(Pi.x, Pi.z, Pi.x, Pi.z); + vec<4, T, Q> iy(Pi.y, Pi.y, Pi.w, Pi.w); + vec<4, T, Q> fx(Pf.x, Pf.z, Pf.x, Pf.z); + vec<4, T, Q> fy(Pf.y, Pf.y, Pf.w, Pf.w); + + vec<4, T, Q> i = detail::permute(detail::permute(ix) + iy); + + vec<4, T, Q> gx = static_cast(2) * glm::fract(i / T(41)) - T(1); + vec<4, T, Q> gy = glm::abs(gx) - T(0.5); + vec<4, T, Q> tx = glm::floor(gx + T(0.5)); + gx = gx - tx; + + vec<2, T, Q> g00(gx.x, gy.x); + vec<2, T, Q> g10(gx.y, gy.y); + vec<2, T, Q> g01(gx.z, gy.z); + vec<2, T, Q> g11(gx.w, gy.w); + + vec<4, T, Q> norm = detail::taylorInvSqrt(vec<4, T, Q>(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11))); + g00 *= norm.x; + g01 *= norm.y; + g10 *= norm.z; + g11 *= norm.w; + + T n00 = dot(g00, vec<2, T, Q>(fx.x, fy.x)); + T n10 = dot(g10, vec<2, T, Q>(fx.y, fy.y)); + T n01 = dot(g01, vec<2, T, Q>(fx.z, fy.z)); + T n11 = dot(g11, vec<2, T, Q>(fx.w, fy.w)); + + vec<2, T, Q> fade_xy = detail::fade(vec<2, T, Q>(Pf.x, Pf.y)); + vec<2, T, Q> n_x = mix(vec<2, T, Q>(n00, n01), vec<2, T, Q>(n10, n11), fade_xy.x); + T n_xy = mix(n_x.x, n_x.y, fade_xy.y); + return T(2.3) * n_xy; + } + + // Classic Perlin noise + template + GLM_FUNC_QUALIFIER T perlin(vec<3, T, Q> const& Position) + { + vec<3, T, Q> Pi0 = floor(Position); // Integer part for indexing + vec<3, T, Q> Pi1 = Pi0 + T(1); // Integer part + 1 + Pi0 = detail::mod289(Pi0); + Pi1 = detail::mod289(Pi1); + vec<3, T, Q> Pf0 = fract(Position); // Fractional part for interpolation + vec<3, T, Q> Pf1 = Pf0 - T(1); // Fractional part - 1.0 + vec<4, T, Q> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec<4, T, Q> iy = vec<4, T, Q>(vec<2, T, Q>(Pi0.y), vec<2, T, Q>(Pi1.y)); + vec<4, T, Q> iz0(Pi0.z); + vec<4, T, Q> iz1(Pi1.z); + + vec<4, T, Q> ixy = detail::permute(detail::permute(ix) + iy); + vec<4, T, Q> ixy0 = detail::permute(ixy + iz0); + vec<4, T, Q> ixy1 = detail::permute(ixy + iz1); + + vec<4, T, Q> gx0 = ixy0 * T(1.0 / 7.0); + vec<4, T, Q> gy0 = fract(floor(gx0) * T(1.0 / 7.0)) - T(0.5); + gx0 = fract(gx0); + vec<4, T, Q> gz0 = vec<4, T, Q>(0.5) - abs(gx0) - abs(gy0); + vec<4, T, Q> sz0 = step(gz0, vec<4, T, Q>(0.0)); + gx0 -= sz0 * (step(T(0), gx0) - T(0.5)); + gy0 -= sz0 * (step(T(0), gy0) - T(0.5)); + + vec<4, T, Q> gx1 = ixy1 * T(1.0 / 7.0); + vec<4, T, Q> gy1 = fract(floor(gx1) * T(1.0 / 7.0)) - T(0.5); + gx1 = fract(gx1); + vec<4, T, Q> gz1 = vec<4, T, Q>(0.5) - abs(gx1) - abs(gy1); + vec<4, T, Q> sz1 = step(gz1, vec<4, T, Q>(0.0)); + gx1 -= sz1 * (step(T(0), gx1) - T(0.5)); + gy1 -= sz1 * (step(T(0), gy1) - T(0.5)); + + vec<3, T, Q> g000(gx0.x, gy0.x, gz0.x); + vec<3, T, Q> g100(gx0.y, gy0.y, gz0.y); + vec<3, T, Q> g010(gx0.z, gy0.z, gz0.z); + vec<3, T, Q> g110(gx0.w, gy0.w, gz0.w); + vec<3, T, Q> g001(gx1.x, gy1.x, gz1.x); + vec<3, T, Q> g101(gx1.y, gy1.y, gz1.y); + vec<3, T, Q> g011(gx1.z, gy1.z, gz1.z); + vec<3, T, Q> g111(gx1.w, gy1.w, gz1.w); + + vec<4, T, Q> norm0 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec<4, T, Q> norm1 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + T n000 = dot(g000, Pf0); + T n100 = dot(g100, vec<3, T, Q>(Pf1.x, Pf0.y, Pf0.z)); + T n010 = dot(g010, vec<3, T, Q>(Pf0.x, Pf1.y, Pf0.z)); + T n110 = dot(g110, vec<3, T, Q>(Pf1.x, Pf1.y, Pf0.z)); + T n001 = dot(g001, vec<3, T, Q>(Pf0.x, Pf0.y, Pf1.z)); + T n101 = dot(g101, vec<3, T, Q>(Pf1.x, Pf0.y, Pf1.z)); + T n011 = dot(g011, vec<3, T, Q>(Pf0.x, Pf1.y, Pf1.z)); + T n111 = dot(g111, Pf1); + + vec<3, T, Q> fade_xyz = detail::fade(Pf0); + vec<4, T, Q> n_z = mix(vec<4, T, Q>(n000, n100, n010, n110), vec<4, T, Q>(n001, n101, n011, n111), fade_xyz.z); + vec<2, T, Q> n_yz = mix(vec<2, T, Q>(n_z.x, n_z.y), vec<2, T, Q>(n_z.z, n_z.w), fade_xyz.y); + T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return T(2.2) * n_xyz; + } + /* + // Classic Perlin noise + template + GLM_FUNC_QUALIFIER T perlin(vec<3, T, Q> const& P) + { + vec<3, T, Q> Pi0 = floor(P); // Integer part for indexing + vec<3, T, Q> Pi1 = Pi0 + T(1); // Integer part + 1 + Pi0 = mod(Pi0, T(289)); + Pi1 = mod(Pi1, T(289)); + vec<3, T, Q> Pf0 = fract(P); // Fractional part for interpolation + vec<3, T, Q> Pf1 = Pf0 - T(1); // Fractional part - 1.0 + vec<4, T, Q> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec<4, T, Q> iy(Pi0.y, Pi0.y, Pi1.y, Pi1.y); + vec<4, T, Q> iz0(Pi0.z); + vec<4, T, Q> iz1(Pi1.z); + + vec<4, T, Q> ixy = permute(permute(ix) + iy); + vec<4, T, Q> ixy0 = permute(ixy + iz0); + vec<4, T, Q> ixy1 = permute(ixy + iz1); + + vec<4, T, Q> gx0 = ixy0 / T(7); + vec<4, T, Q> gy0 = fract(floor(gx0) / T(7)) - T(0.5); + gx0 = fract(gx0); + vec<4, T, Q> gz0 = vec<4, T, Q>(0.5) - abs(gx0) - abs(gy0); + vec<4, T, Q> sz0 = step(gz0, vec<4, T, Q>(0.0)); + gx0 -= sz0 * (step(0.0, gx0) - T(0.5)); + gy0 -= sz0 * (step(0.0, gy0) - T(0.5)); + + vec<4, T, Q> gx1 = ixy1 / T(7); + vec<4, T, Q> gy1 = fract(floor(gx1) / T(7)) - T(0.5); + gx1 = fract(gx1); + vec<4, T, Q> gz1 = vec<4, T, Q>(0.5) - abs(gx1) - abs(gy1); + vec<4, T, Q> sz1 = step(gz1, vec<4, T, Q>(0.0)); + gx1 -= sz1 * (step(T(0), gx1) - T(0.5)); + gy1 -= sz1 * (step(T(0), gy1) - T(0.5)); + + vec<3, T, Q> g000(gx0.x, gy0.x, gz0.x); + vec<3, T, Q> g100(gx0.y, gy0.y, gz0.y); + vec<3, T, Q> g010(gx0.z, gy0.z, gz0.z); + vec<3, T, Q> g110(gx0.w, gy0.w, gz0.w); + vec<3, T, Q> g001(gx1.x, gy1.x, gz1.x); + vec<3, T, Q> g101(gx1.y, gy1.y, gz1.y); + vec<3, T, Q> g011(gx1.z, gy1.z, gz1.z); + vec<3, T, Q> g111(gx1.w, gy1.w, gz1.w); + + vec<4, T, Q> norm0 = taylorInvSqrt(vec<4, T, Q>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec<4, T, Q> norm1 = taylorInvSqrt(vec<4, T, Q>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + T n000 = dot(g000, Pf0); + T n100 = dot(g100, vec<3, T, Q>(Pf1.x, Pf0.y, Pf0.z)); + T n010 = dot(g010, vec<3, T, Q>(Pf0.x, Pf1.y, Pf0.z)); + T n110 = dot(g110, vec<3, T, Q>(Pf1.x, Pf1.y, Pf0.z)); + T n001 = dot(g001, vec<3, T, Q>(Pf0.x, Pf0.y, Pf1.z)); + T n101 = dot(g101, vec<3, T, Q>(Pf1.x, Pf0.y, Pf1.z)); + T n011 = dot(g011, vec<3, T, Q>(Pf0.x, Pf1.y, Pf1.z)); + T n111 = dot(g111, Pf1); + + vec<3, T, Q> fade_xyz = fade(Pf0); + vec<4, T, Q> n_z = mix(vec<4, T, Q>(n000, n100, n010, n110), vec<4, T, Q>(n001, n101, n011, n111), fade_xyz.z); + vec<2, T, Q> n_yz = mix( + vec<2, T, Q>(n_z.x, n_z.y), + vec<2, T, Q>(n_z.z, n_z.w), fade_xyz.y); + T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return T(2.2) * n_xyz; + } + */ + // Classic Perlin noise + template + GLM_FUNC_QUALIFIER T perlin(vec<4, T, Q> const& Position) + { + vec<4, T, Q> Pi0 = floor(Position); // Integer part for indexing + vec<4, T, Q> Pi1 = Pi0 + T(1); // Integer part + 1 + Pi0 = mod(Pi0, vec<4, T, Q>(289)); + Pi1 = mod(Pi1, vec<4, T, Q>(289)); + vec<4, T, Q> Pf0 = fract(Position); // Fractional part for interpolation + vec<4, T, Q> Pf1 = Pf0 - T(1); // Fractional part - 1.0 + vec<4, T, Q> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec<4, T, Q> iy(Pi0.y, Pi0.y, Pi1.y, Pi1.y); + vec<4, T, Q> iz0(Pi0.z); + vec<4, T, Q> iz1(Pi1.z); + vec<4, T, Q> iw0(Pi0.w); + vec<4, T, Q> iw1(Pi1.w); + + vec<4, T, Q> ixy = detail::permute(detail::permute(ix) + iy); + vec<4, T, Q> ixy0 = detail::permute(ixy + iz0); + vec<4, T, Q> ixy1 = detail::permute(ixy + iz1); + vec<4, T, Q> ixy00 = detail::permute(ixy0 + iw0); + vec<4, T, Q> ixy01 = detail::permute(ixy0 + iw1); + vec<4, T, Q> ixy10 = detail::permute(ixy1 + iw0); + vec<4, T, Q> ixy11 = detail::permute(ixy1 + iw1); + + vec<4, T, Q> gx00 = ixy00 / T(7); + vec<4, T, Q> gy00 = floor(gx00) / T(7); + vec<4, T, Q> gz00 = floor(gy00) / T(6); + gx00 = fract(gx00) - T(0.5); + gy00 = fract(gy00) - T(0.5); + gz00 = fract(gz00) - T(0.5); + vec<4, T, Q> gw00 = vec<4, T, Q>(0.75) - abs(gx00) - abs(gy00) - abs(gz00); + vec<4, T, Q> sw00 = step(gw00, vec<4, T, Q>(0.0)); + gx00 -= sw00 * (step(T(0), gx00) - T(0.5)); + gy00 -= sw00 * (step(T(0), gy00) - T(0.5)); + + vec<4, T, Q> gx01 = ixy01 / T(7); + vec<4, T, Q> gy01 = floor(gx01) / T(7); + vec<4, T, Q> gz01 = floor(gy01) / T(6); + gx01 = fract(gx01) - T(0.5); + gy01 = fract(gy01) - T(0.5); + gz01 = fract(gz01) - T(0.5); + vec<4, T, Q> gw01 = vec<4, T, Q>(0.75) - abs(gx01) - abs(gy01) - abs(gz01); + vec<4, T, Q> sw01 = step(gw01, vec<4, T, Q>(0.0)); + gx01 -= sw01 * (step(T(0), gx01) - T(0.5)); + gy01 -= sw01 * (step(T(0), gy01) - T(0.5)); + + vec<4, T, Q> gx10 = ixy10 / T(7); + vec<4, T, Q> gy10 = floor(gx10) / T(7); + vec<4, T, Q> gz10 = floor(gy10) / T(6); + gx10 = fract(gx10) - T(0.5); + gy10 = fract(gy10) - T(0.5); + gz10 = fract(gz10) - T(0.5); + vec<4, T, Q> gw10 = vec<4, T, Q>(0.75) - abs(gx10) - abs(gy10) - abs(gz10); + vec<4, T, Q> sw10 = step(gw10, vec<4, T, Q>(0)); + gx10 -= sw10 * (step(T(0), gx10) - T(0.5)); + gy10 -= sw10 * (step(T(0), gy10) - T(0.5)); + + vec<4, T, Q> gx11 = ixy11 / T(7); + vec<4, T, Q> gy11 = floor(gx11) / T(7); + vec<4, T, Q> gz11 = floor(gy11) / T(6); + gx11 = fract(gx11) - T(0.5); + gy11 = fract(gy11) - T(0.5); + gz11 = fract(gz11) - T(0.5); + vec<4, T, Q> gw11 = vec<4, T, Q>(0.75) - abs(gx11) - abs(gy11) - abs(gz11); + vec<4, T, Q> sw11 = step(gw11, vec<4, T, Q>(0.0)); + gx11 -= sw11 * (step(T(0), gx11) - T(0.5)); + gy11 -= sw11 * (step(T(0), gy11) - T(0.5)); + + vec<4, T, Q> g0000(gx00.x, gy00.x, gz00.x, gw00.x); + vec<4, T, Q> g1000(gx00.y, gy00.y, gz00.y, gw00.y); + vec<4, T, Q> g0100(gx00.z, gy00.z, gz00.z, gw00.z); + vec<4, T, Q> g1100(gx00.w, gy00.w, gz00.w, gw00.w); + vec<4, T, Q> g0010(gx10.x, gy10.x, gz10.x, gw10.x); + vec<4, T, Q> g1010(gx10.y, gy10.y, gz10.y, gw10.y); + vec<4, T, Q> g0110(gx10.z, gy10.z, gz10.z, gw10.z); + vec<4, T, Q> g1110(gx10.w, gy10.w, gz10.w, gw10.w); + vec<4, T, Q> g0001(gx01.x, gy01.x, gz01.x, gw01.x); + vec<4, T, Q> g1001(gx01.y, gy01.y, gz01.y, gw01.y); + vec<4, T, Q> g0101(gx01.z, gy01.z, gz01.z, gw01.z); + vec<4, T, Q> g1101(gx01.w, gy01.w, gz01.w, gw01.w); + vec<4, T, Q> g0011(gx11.x, gy11.x, gz11.x, gw11.x); + vec<4, T, Q> g1011(gx11.y, gy11.y, gz11.y, gw11.y); + vec<4, T, Q> g0111(gx11.z, gy11.z, gz11.z, gw11.z); + vec<4, T, Q> g1111(gx11.w, gy11.w, gz11.w, gw11.w); + + vec<4, T, Q> norm00 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100))); + g0000 *= norm00.x; + g0100 *= norm00.y; + g1000 *= norm00.z; + g1100 *= norm00.w; + + vec<4, T, Q> norm01 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101))); + g0001 *= norm01.x; + g0101 *= norm01.y; + g1001 *= norm01.z; + g1101 *= norm01.w; + + vec<4, T, Q> norm10 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110))); + g0010 *= norm10.x; + g0110 *= norm10.y; + g1010 *= norm10.z; + g1110 *= norm10.w; + + vec<4, T, Q> norm11 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111))); + g0011 *= norm11.x; + g0111 *= norm11.y; + g1011 *= norm11.z; + g1111 *= norm11.w; + + T n0000 = dot(g0000, Pf0); + T n1000 = dot(g1000, vec<4, T, Q>(Pf1.x, Pf0.y, Pf0.z, Pf0.w)); + T n0100 = dot(g0100, vec<4, T, Q>(Pf0.x, Pf1.y, Pf0.z, Pf0.w)); + T n1100 = dot(g1100, vec<4, T, Q>(Pf1.x, Pf1.y, Pf0.z, Pf0.w)); + T n0010 = dot(g0010, vec<4, T, Q>(Pf0.x, Pf0.y, Pf1.z, Pf0.w)); + T n1010 = dot(g1010, vec<4, T, Q>(Pf1.x, Pf0.y, Pf1.z, Pf0.w)); + T n0110 = dot(g0110, vec<4, T, Q>(Pf0.x, Pf1.y, Pf1.z, Pf0.w)); + T n1110 = dot(g1110, vec<4, T, Q>(Pf1.x, Pf1.y, Pf1.z, Pf0.w)); + T n0001 = dot(g0001, vec<4, T, Q>(Pf0.x, Pf0.y, Pf0.z, Pf1.w)); + T n1001 = dot(g1001, vec<4, T, Q>(Pf1.x, Pf0.y, Pf0.z, Pf1.w)); + T n0101 = dot(g0101, vec<4, T, Q>(Pf0.x, Pf1.y, Pf0.z, Pf1.w)); + T n1101 = dot(g1101, vec<4, T, Q>(Pf1.x, Pf1.y, Pf0.z, Pf1.w)); + T n0011 = dot(g0011, vec<4, T, Q>(Pf0.x, Pf0.y, Pf1.z, Pf1.w)); + T n1011 = dot(g1011, vec<4, T, Q>(Pf1.x, Pf0.y, Pf1.z, Pf1.w)); + T n0111 = dot(g0111, vec<4, T, Q>(Pf0.x, Pf1.y, Pf1.z, Pf1.w)); + T n1111 = dot(g1111, Pf1); + + vec<4, T, Q> fade_xyzw = detail::fade(Pf0); + vec<4, T, Q> n_0w = mix(vec<4, T, Q>(n0000, n1000, n0100, n1100), vec<4, T, Q>(n0001, n1001, n0101, n1101), fade_xyzw.w); + vec<4, T, Q> n_1w = mix(vec<4, T, Q>(n0010, n1010, n0110, n1110), vec<4, T, Q>(n0011, n1011, n0111, n1111), fade_xyzw.w); + vec<4, T, Q> n_zw = mix(n_0w, n_1w, fade_xyzw.z); + vec<2, T, Q> n_yzw = mix(vec<2, T, Q>(n_zw.x, n_zw.y), vec<2, T, Q>(n_zw.z, n_zw.w), fade_xyzw.y); + T n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x); + return T(2.2) * n_xyzw; + } + + // Classic Perlin noise, periodic variant + template + GLM_FUNC_QUALIFIER T perlin(vec<2, T, Q> const& Position, vec<2, T, Q> const& rep) + { + vec<4, T, Q> Pi = floor(vec<4, T, Q>(Position.x, Position.y, Position.x, Position.y)) + vec<4, T, Q>(0.0, 0.0, 1.0, 1.0); + vec<4, T, Q> Pf = fract(vec<4, T, Q>(Position.x, Position.y, Position.x, Position.y)) - vec<4, T, Q>(0.0, 0.0, 1.0, 1.0); + Pi = mod(Pi, vec<4, T, Q>(rep.x, rep.y, rep.x, rep.y)); // To create noise with explicit period + Pi = mod(Pi, vec<4, T, Q>(289)); // To avoid truncation effects in permutation + vec<4, T, Q> ix(Pi.x, Pi.z, Pi.x, Pi.z); + vec<4, T, Q> iy(Pi.y, Pi.y, Pi.w, Pi.w); + vec<4, T, Q> fx(Pf.x, Pf.z, Pf.x, Pf.z); + vec<4, T, Q> fy(Pf.y, Pf.y, Pf.w, Pf.w); + + vec<4, T, Q> i = detail::permute(detail::permute(ix) + iy); + + vec<4, T, Q> gx = static_cast(2) * fract(i / T(41)) - T(1); + vec<4, T, Q> gy = abs(gx) - T(0.5); + vec<4, T, Q> tx = floor(gx + T(0.5)); + gx = gx - tx; + + vec<2, T, Q> g00(gx.x, gy.x); + vec<2, T, Q> g10(gx.y, gy.y); + vec<2, T, Q> g01(gx.z, gy.z); + vec<2, T, Q> g11(gx.w, gy.w); + + vec<4, T, Q> norm = detail::taylorInvSqrt(vec<4, T, Q>(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11))); + g00 *= norm.x; + g01 *= norm.y; + g10 *= norm.z; + g11 *= norm.w; + + T n00 = dot(g00, vec<2, T, Q>(fx.x, fy.x)); + T n10 = dot(g10, vec<2, T, Q>(fx.y, fy.y)); + T n01 = dot(g01, vec<2, T, Q>(fx.z, fy.z)); + T n11 = dot(g11, vec<2, T, Q>(fx.w, fy.w)); + + vec<2, T, Q> fade_xy = detail::fade(vec<2, T, Q>(Pf.x, Pf.y)); + vec<2, T, Q> n_x = mix(vec<2, T, Q>(n00, n01), vec<2, T, Q>(n10, n11), fade_xy.x); + T n_xy = mix(n_x.x, n_x.y, fade_xy.y); + return T(2.3) * n_xy; + } + + // Classic Perlin noise, periodic variant + template + GLM_FUNC_QUALIFIER T perlin(vec<3, T, Q> const& Position, vec<3, T, Q> const& rep) + { + vec<3, T, Q> Pi0 = mod(floor(Position), rep); // Integer part, modulo period + vec<3, T, Q> Pi1 = mod(Pi0 + vec<3, T, Q>(T(1)), rep); // Integer part + 1, mod period + Pi0 = mod(Pi0, vec<3, T, Q>(289)); + Pi1 = mod(Pi1, vec<3, T, Q>(289)); + vec<3, T, Q> Pf0 = fract(Position); // Fractional part for interpolation + vec<3, T, Q> Pf1 = Pf0 - vec<3, T, Q>(T(1)); // Fractional part - 1.0 + vec<4, T, Q> ix = vec<4, T, Q>(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec<4, T, Q> iy = vec<4, T, Q>(Pi0.y, Pi0.y, Pi1.y, Pi1.y); + vec<4, T, Q> iz0(Pi0.z); + vec<4, T, Q> iz1(Pi1.z); + + vec<4, T, Q> ixy = detail::permute(detail::permute(ix) + iy); + vec<4, T, Q> ixy0 = detail::permute(ixy + iz0); + vec<4, T, Q> ixy1 = detail::permute(ixy + iz1); + + vec<4, T, Q> gx0 = ixy0 / T(7); + vec<4, T, Q> gy0 = fract(floor(gx0) / T(7)) - T(0.5); + gx0 = fract(gx0); + vec<4, T, Q> gz0 = vec<4, T, Q>(0.5) - abs(gx0) - abs(gy0); + vec<4, T, Q> sz0 = step(gz0, vec<4, T, Q>(0)); + gx0 -= sz0 * (step(T(0), gx0) - T(0.5)); + gy0 -= sz0 * (step(T(0), gy0) - T(0.5)); + + vec<4, T, Q> gx1 = ixy1 / T(7); + vec<4, T, Q> gy1 = fract(floor(gx1) / T(7)) - T(0.5); + gx1 = fract(gx1); + vec<4, T, Q> gz1 = vec<4, T, Q>(0.5) - abs(gx1) - abs(gy1); + vec<4, T, Q> sz1 = step(gz1, vec<4, T, Q>(T(0))); + gx1 -= sz1 * (step(T(0), gx1) - T(0.5)); + gy1 -= sz1 * (step(T(0), gy1) - T(0.5)); + + vec<3, T, Q> g000 = vec<3, T, Q>(gx0.x, gy0.x, gz0.x); + vec<3, T, Q> g100 = vec<3, T, Q>(gx0.y, gy0.y, gz0.y); + vec<3, T, Q> g010 = vec<3, T, Q>(gx0.z, gy0.z, gz0.z); + vec<3, T, Q> g110 = vec<3, T, Q>(gx0.w, gy0.w, gz0.w); + vec<3, T, Q> g001 = vec<3, T, Q>(gx1.x, gy1.x, gz1.x); + vec<3, T, Q> g101 = vec<3, T, Q>(gx1.y, gy1.y, gz1.y); + vec<3, T, Q> g011 = vec<3, T, Q>(gx1.z, gy1.z, gz1.z); + vec<3, T, Q> g111 = vec<3, T, Q>(gx1.w, gy1.w, gz1.w); + + vec<4, T, Q> norm0 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec<4, T, Q> norm1 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + T n000 = dot(g000, Pf0); + T n100 = dot(g100, vec<3, T, Q>(Pf1.x, Pf0.y, Pf0.z)); + T n010 = dot(g010, vec<3, T, Q>(Pf0.x, Pf1.y, Pf0.z)); + T n110 = dot(g110, vec<3, T, Q>(Pf1.x, Pf1.y, Pf0.z)); + T n001 = dot(g001, vec<3, T, Q>(Pf0.x, Pf0.y, Pf1.z)); + T n101 = dot(g101, vec<3, T, Q>(Pf1.x, Pf0.y, Pf1.z)); + T n011 = dot(g011, vec<3, T, Q>(Pf0.x, Pf1.y, Pf1.z)); + T n111 = dot(g111, Pf1); + + vec<3, T, Q> fade_xyz = detail::fade(Pf0); + vec<4, T, Q> n_z = mix(vec<4, T, Q>(n000, n100, n010, n110), vec<4, T, Q>(n001, n101, n011, n111), fade_xyz.z); + vec<2, T, Q> n_yz = mix(vec<2, T, Q>(n_z.x, n_z.y), vec<2, T, Q>(n_z.z, n_z.w), fade_xyz.y); + T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return T(2.2) * n_xyz; + } + + // Classic Perlin noise, periodic version + template + GLM_FUNC_QUALIFIER T perlin(vec<4, T, Q> const& Position, vec<4, T, Q> const& rep) + { + vec<4, T, Q> Pi0 = mod(floor(Position), rep); // Integer part modulo rep + vec<4, T, Q> Pi1 = mod(Pi0 + T(1), rep); // Integer part + 1 mod rep + vec<4, T, Q> Pf0 = fract(Position); // Fractional part for interpolation + vec<4, T, Q> Pf1 = Pf0 - T(1); // Fractional part - 1.0 + vec<4, T, Q> ix = vec<4, T, Q>(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec<4, T, Q> iy = vec<4, T, Q>(Pi0.y, Pi0.y, Pi1.y, Pi1.y); + vec<4, T, Q> iz0(Pi0.z); + vec<4, T, Q> iz1(Pi1.z); + vec<4, T, Q> iw0(Pi0.w); + vec<4, T, Q> iw1(Pi1.w); + + vec<4, T, Q> ixy = detail::permute(detail::permute(ix) + iy); + vec<4, T, Q> ixy0 = detail::permute(ixy + iz0); + vec<4, T, Q> ixy1 = detail::permute(ixy + iz1); + vec<4, T, Q> ixy00 = detail::permute(ixy0 + iw0); + vec<4, T, Q> ixy01 = detail::permute(ixy0 + iw1); + vec<4, T, Q> ixy10 = detail::permute(ixy1 + iw0); + vec<4, T, Q> ixy11 = detail::permute(ixy1 + iw1); + + vec<4, T, Q> gx00 = ixy00 / T(7); + vec<4, T, Q> gy00 = floor(gx00) / T(7); + vec<4, T, Q> gz00 = floor(gy00) / T(6); + gx00 = fract(gx00) - T(0.5); + gy00 = fract(gy00) - T(0.5); + gz00 = fract(gz00) - T(0.5); + vec<4, T, Q> gw00 = vec<4, T, Q>(0.75) - abs(gx00) - abs(gy00) - abs(gz00); + vec<4, T, Q> sw00 = step(gw00, vec<4, T, Q>(0)); + gx00 -= sw00 * (step(T(0), gx00) - T(0.5)); + gy00 -= sw00 * (step(T(0), gy00) - T(0.5)); + + vec<4, T, Q> gx01 = ixy01 / T(7); + vec<4, T, Q> gy01 = floor(gx01) / T(7); + vec<4, T, Q> gz01 = floor(gy01) / T(6); + gx01 = fract(gx01) - T(0.5); + gy01 = fract(gy01) - T(0.5); + gz01 = fract(gz01) - T(0.5); + vec<4, T, Q> gw01 = vec<4, T, Q>(0.75) - abs(gx01) - abs(gy01) - abs(gz01); + vec<4, T, Q> sw01 = step(gw01, vec<4, T, Q>(0.0)); + gx01 -= sw01 * (step(T(0), gx01) - T(0.5)); + gy01 -= sw01 * (step(T(0), gy01) - T(0.5)); + + vec<4, T, Q> gx10 = ixy10 / T(7); + vec<4, T, Q> gy10 = floor(gx10) / T(7); + vec<4, T, Q> gz10 = floor(gy10) / T(6); + gx10 = fract(gx10) - T(0.5); + gy10 = fract(gy10) - T(0.5); + gz10 = fract(gz10) - T(0.5); + vec<4, T, Q> gw10 = vec<4, T, Q>(0.75) - abs(gx10) - abs(gy10) - abs(gz10); + vec<4, T, Q> sw10 = step(gw10, vec<4, T, Q>(0.0)); + gx10 -= sw10 * (step(T(0), gx10) - T(0.5)); + gy10 -= sw10 * (step(T(0), gy10) - T(0.5)); + + vec<4, T, Q> gx11 = ixy11 / T(7); + vec<4, T, Q> gy11 = floor(gx11) / T(7); + vec<4, T, Q> gz11 = floor(gy11) / T(6); + gx11 = fract(gx11) - T(0.5); + gy11 = fract(gy11) - T(0.5); + gz11 = fract(gz11) - T(0.5); + vec<4, T, Q> gw11 = vec<4, T, Q>(0.75) - abs(gx11) - abs(gy11) - abs(gz11); + vec<4, T, Q> sw11 = step(gw11, vec<4, T, Q>(T(0))); + gx11 -= sw11 * (step(T(0), gx11) - T(0.5)); + gy11 -= sw11 * (step(T(0), gy11) - T(0.5)); + + vec<4, T, Q> g0000(gx00.x, gy00.x, gz00.x, gw00.x); + vec<4, T, Q> g1000(gx00.y, gy00.y, gz00.y, gw00.y); + vec<4, T, Q> g0100(gx00.z, gy00.z, gz00.z, gw00.z); + vec<4, T, Q> g1100(gx00.w, gy00.w, gz00.w, gw00.w); + vec<4, T, Q> g0010(gx10.x, gy10.x, gz10.x, gw10.x); + vec<4, T, Q> g1010(gx10.y, gy10.y, gz10.y, gw10.y); + vec<4, T, Q> g0110(gx10.z, gy10.z, gz10.z, gw10.z); + vec<4, T, Q> g1110(gx10.w, gy10.w, gz10.w, gw10.w); + vec<4, T, Q> g0001(gx01.x, gy01.x, gz01.x, gw01.x); + vec<4, T, Q> g1001(gx01.y, gy01.y, gz01.y, gw01.y); + vec<4, T, Q> g0101(gx01.z, gy01.z, gz01.z, gw01.z); + vec<4, T, Q> g1101(gx01.w, gy01.w, gz01.w, gw01.w); + vec<4, T, Q> g0011(gx11.x, gy11.x, gz11.x, gw11.x); + vec<4, T, Q> g1011(gx11.y, gy11.y, gz11.y, gw11.y); + vec<4, T, Q> g0111(gx11.z, gy11.z, gz11.z, gw11.z); + vec<4, T, Q> g1111(gx11.w, gy11.w, gz11.w, gw11.w); + + vec<4, T, Q> norm00 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100))); + g0000 *= norm00.x; + g0100 *= norm00.y; + g1000 *= norm00.z; + g1100 *= norm00.w; + + vec<4, T, Q> norm01 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101))); + g0001 *= norm01.x; + g0101 *= norm01.y; + g1001 *= norm01.z; + g1101 *= norm01.w; + + vec<4, T, Q> norm10 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110))); + g0010 *= norm10.x; + g0110 *= norm10.y; + g1010 *= norm10.z; + g1110 *= norm10.w; + + vec<4, T, Q> norm11 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111))); + g0011 *= norm11.x; + g0111 *= norm11.y; + g1011 *= norm11.z; + g1111 *= norm11.w; + + T n0000 = dot(g0000, Pf0); + T n1000 = dot(g1000, vec<4, T, Q>(Pf1.x, Pf0.y, Pf0.z, Pf0.w)); + T n0100 = dot(g0100, vec<4, T, Q>(Pf0.x, Pf1.y, Pf0.z, Pf0.w)); + T n1100 = dot(g1100, vec<4, T, Q>(Pf1.x, Pf1.y, Pf0.z, Pf0.w)); + T n0010 = dot(g0010, vec<4, T, Q>(Pf0.x, Pf0.y, Pf1.z, Pf0.w)); + T n1010 = dot(g1010, vec<4, T, Q>(Pf1.x, Pf0.y, Pf1.z, Pf0.w)); + T n0110 = dot(g0110, vec<4, T, Q>(Pf0.x, Pf1.y, Pf1.z, Pf0.w)); + T n1110 = dot(g1110, vec<4, T, Q>(Pf1.x, Pf1.y, Pf1.z, Pf0.w)); + T n0001 = dot(g0001, vec<4, T, Q>(Pf0.x, Pf0.y, Pf0.z, Pf1.w)); + T n1001 = dot(g1001, vec<4, T, Q>(Pf1.x, Pf0.y, Pf0.z, Pf1.w)); + T n0101 = dot(g0101, vec<4, T, Q>(Pf0.x, Pf1.y, Pf0.z, Pf1.w)); + T n1101 = dot(g1101, vec<4, T, Q>(Pf1.x, Pf1.y, Pf0.z, Pf1.w)); + T n0011 = dot(g0011, vec<4, T, Q>(Pf0.x, Pf0.y, Pf1.z, Pf1.w)); + T n1011 = dot(g1011, vec<4, T, Q>(Pf1.x, Pf0.y, Pf1.z, Pf1.w)); + T n0111 = dot(g0111, vec<4, T, Q>(Pf0.x, Pf1.y, Pf1.z, Pf1.w)); + T n1111 = dot(g1111, Pf1); + + vec<4, T, Q> fade_xyzw = detail::fade(Pf0); + vec<4, T, Q> n_0w = mix(vec<4, T, Q>(n0000, n1000, n0100, n1100), vec<4, T, Q>(n0001, n1001, n0101, n1101), fade_xyzw.w); + vec<4, T, Q> n_1w = mix(vec<4, T, Q>(n0010, n1010, n0110, n1110), vec<4, T, Q>(n0011, n1011, n0111, n1111), fade_xyzw.w); + vec<4, T, Q> n_zw = mix(n_0w, n_1w, fade_xyzw.z); + vec<2, T, Q> n_yzw = mix(vec<2, T, Q>(n_zw.x, n_zw.y), vec<2, T, Q>(n_zw.z, n_zw.w), fade_xyzw.y); + T n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x); + return T(2.2) * n_xyzw; + } + + template + GLM_FUNC_QUALIFIER T simplex(glm::vec<2, T, Q> const& v) + { + vec<4, T, Q> const C = vec<4, T, Q>( + T( 0.211324865405187), // (3.0 - sqrt(3.0)) / 6.0 + T( 0.366025403784439), // 0.5 * (sqrt(3.0) - 1.0) + T(-0.577350269189626), // -1.0 + 2.0 * C.x + T( 0.024390243902439)); // 1.0 / 41.0 + + // First corner + vec<2, T, Q> i = floor(v + dot(v, vec<2, T, Q>(C[1]))); + vec<2, T, Q> x0 = v - i + dot(i, vec<2, T, Q>(C[0])); + + // Other corners + //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 + //i1.y = 1.0 - i1.x; + vec<2, T, Q> i1 = (x0.x > x0.y) ? vec<2, T, Q>(1, 0) : vec<2, T, Q>(0, 1); + // x0 = x0 - 0.0 + 0.0 * C.xx ; + // x1 = x0 - i1 + 1.0 * C.xx ; + // x2 = x0 - 1.0 + 2.0 * C.xx ; + vec<4, T, Q> x12 = vec<4, T, Q>(x0.x, x0.y, x0.x, x0.y) + vec<4, T, Q>(C.x, C.x, C.z, C.z); + x12 = vec<4, T, Q>(vec<2, T, Q>(x12) - i1, x12.z, x12.w); + + // Permutations + i = mod(i, vec<2, T, Q>(289)); // Avoid truncation effects in permutation + vec<3, T, Q> p = detail::permute( + detail::permute(i.y + vec<3, T, Q>(T(0), i1.y, T(1))) + + i.x + vec<3, T, Q>(T(0), i1.x, T(1))); + + vec<3, T, Q> m = max(vec<3, T, Q>(0.5) - vec<3, T, Q>( + dot(x0, x0), + dot(vec<2, T, Q>(x12.x, x12.y), vec<2, T, Q>(x12.x, x12.y)), + dot(vec<2, T, Q>(x12.z, x12.w), vec<2, T, Q>(x12.z, x12.w))), vec<3, T, Q>(0)); + m = m * m ; + m = m * m ; + + // Gradients: 41 points uniformly over a line, mapped onto a diamond. + // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) + + vec<3, T, Q> x = static_cast(2) * fract(p * C.w) - T(1); + vec<3, T, Q> h = abs(x) - T(0.5); + vec<3, T, Q> ox = floor(x + T(0.5)); + vec<3, T, Q> a0 = x - ox; + + // Normalise gradients implicitly by scaling m + // Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h ); + m *= static_cast(1.79284291400159) - T(0.85373472095314) * (a0 * a0 + h * h); + + // Compute final noise value at P + vec<3, T, Q> g; + g.x = a0.x * x0.x + h.x * x0.y; + //g.yz = a0.yz * x12.xz + h.yz * x12.yw; + g.y = a0.y * x12.x + h.y * x12.y; + g.z = a0.z * x12.z + h.z * x12.w; + return T(130) * dot(m, g); + } + + template + GLM_FUNC_QUALIFIER T simplex(vec<3, T, Q> const& v) + { + vec<2, T, Q> const C(1.0 / 6.0, 1.0 / 3.0); + vec<4, T, Q> const D(0.0, 0.5, 1.0, 2.0); + + // First corner + vec<3, T, Q> i(floor(v + dot(v, vec<3, T, Q>(C.y)))); + vec<3, T, Q> x0(v - i + dot(i, vec<3, T, Q>(C.x))); + + // Other corners + vec<3, T, Q> g(step(vec<3, T, Q>(x0.y, x0.z, x0.x), x0)); + vec<3, T, Q> l(T(1) - g); + vec<3, T, Q> i1(min(g, vec<3, T, Q>(l.z, l.x, l.y))); + vec<3, T, Q> i2(max(g, vec<3, T, Q>(l.z, l.x, l.y))); + + // x0 = x0 - 0.0 + 0.0 * C.xxx; + // x1 = x0 - i1 + 1.0 * C.xxx; + // x2 = x0 - i2 + 2.0 * C.xxx; + // x3 = x0 - 1.0 + 3.0 * C.xxx; + vec<3, T, Q> x1(x0 - i1 + C.x); + vec<3, T, Q> x2(x0 - i2 + C.y); // 2.0*C.x = 1/3 = C.y + vec<3, T, Q> x3(x0 - D.y); // -1.0+3.0*C.x = -0.5 = -D.y + + // Permutations + i = detail::mod289(i); + vec<4, T, Q> p(detail::permute(detail::permute(detail::permute( + i.z + vec<4, T, Q>(T(0), i1.z, i2.z, T(1))) + + i.y + vec<4, T, Q>(T(0), i1.y, i2.y, T(1))) + + i.x + vec<4, T, Q>(T(0), i1.x, i2.x, T(1)))); + + // Gradients: 7x7 points over a square, mapped onto an octahedron. + // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) + T n_ = static_cast(0.142857142857); // 1.0/7.0 + vec<3, T, Q> ns(n_ * vec<3, T, Q>(D.w, D.y, D.z) - vec<3, T, Q>(D.x, D.z, D.x)); + + vec<4, T, Q> j(p - T(49) * floor(p * ns.z * ns.z)); // mod(p,7*7) + + vec<4, T, Q> x_(floor(j * ns.z)); + vec<4, T, Q> y_(floor(j - T(7) * x_)); // mod(j,N) + + vec<4, T, Q> x(x_ * ns.x + ns.y); + vec<4, T, Q> y(y_ * ns.x + ns.y); + vec<4, T, Q> h(T(1) - abs(x) - abs(y)); + + vec<4, T, Q> b0(x.x, x.y, y.x, y.y); + vec<4, T, Q> b1(x.z, x.w, y.z, y.w); + + // vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; + // vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; + vec<4, T, Q> s0(floor(b0) * T(2) + T(1)); + vec<4, T, Q> s1(floor(b1) * T(2) + T(1)); + vec<4, T, Q> sh(-step(h, vec<4, T, Q>(0.0))); + + vec<4, T, Q> a0 = vec<4, T, Q>(b0.x, b0.z, b0.y, b0.w) + vec<4, T, Q>(s0.x, s0.z, s0.y, s0.w) * vec<4, T, Q>(sh.x, sh.x, sh.y, sh.y); + vec<4, T, Q> a1 = vec<4, T, Q>(b1.x, b1.z, b1.y, b1.w) + vec<4, T, Q>(s1.x, s1.z, s1.y, s1.w) * vec<4, T, Q>(sh.z, sh.z, sh.w, sh.w); + + vec<3, T, Q> p0(a0.x, a0.y, h.x); + vec<3, T, Q> p1(a0.z, a0.w, h.y); + vec<3, T, Q> p2(a1.x, a1.y, h.z); + vec<3, T, Q> p3(a1.z, a1.w, h.w); + + // Normalise gradients + vec<4, T, Q> norm = detail::taylorInvSqrt(vec<4, T, Q>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + + // Mix final noise value + vec<4, T, Q> m = max(T(0.6) - vec<4, T, Q>(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), vec<4, T, Q>(0)); + m = m * m; + return T(42) * dot(m * m, vec<4, T, Q>(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3))); + } + + template + GLM_FUNC_QUALIFIER T simplex(vec<4, T, Q> const& v) + { + vec<4, T, Q> const C( + 0.138196601125011, // (5 - sqrt(5))/20 G4 + 0.276393202250021, // 2 * G4 + 0.414589803375032, // 3 * G4 + -0.447213595499958); // -1 + 4 * G4 + + // (sqrt(5) - 1)/4 = F4, used once below + T const F4 = static_cast(0.309016994374947451); + + // First corner + vec<4, T, Q> i = floor(v + dot(v, vec<4, T, Q>(F4))); + vec<4, T, Q> x0 = v - i + dot(i, vec<4, T, Q>(C.x)); + + // Other corners + + // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) + vec<4, T, Q> i0; + vec<3, T, Q> isX = step(vec<3, T, Q>(x0.y, x0.z, x0.w), vec<3, T, Q>(x0.x)); + vec<3, T, Q> isYZ = step(vec<3, T, Q>(x0.z, x0.w, x0.w), vec<3, T, Q>(x0.y, x0.y, x0.z)); + // i0.x = dot(isX, vec3(1.0)); + //i0.x = isX.x + isX.y + isX.z; + //i0.yzw = static_cast(1) - isX; + i0 = vec<4, T, Q>(isX.x + isX.y + isX.z, T(1) - isX); + // i0.y += dot(isYZ.xy, vec2(1.0)); + i0.y += isYZ.x + isYZ.y; + //i0.zw += 1.0 - vec<2, T, Q>(isYZ.x, isYZ.y); + i0.z += static_cast(1) - isYZ.x; + i0.w += static_cast(1) - isYZ.y; + i0.z += isYZ.z; + i0.w += static_cast(1) - isYZ.z; + + // i0 now contains the unique values 0,1,2,3 in each channel + vec<4, T, Q> i3 = clamp(i0, T(0), T(1)); + vec<4, T, Q> i2 = clamp(i0 - T(1), T(0), T(1)); + vec<4, T, Q> i1 = clamp(i0 - T(2), T(0), T(1)); + + // x0 = x0 - 0.0 + 0.0 * C.xxxx + // x1 = x0 - i1 + 0.0 * C.xxxx + // x2 = x0 - i2 + 0.0 * C.xxxx + // x3 = x0 - i3 + 0.0 * C.xxxx + // x4 = x0 - 1.0 + 4.0 * C.xxxx + vec<4, T, Q> x1 = x0 - i1 + C.x; + vec<4, T, Q> x2 = x0 - i2 + C.y; + vec<4, T, Q> x3 = x0 - i3 + C.z; + vec<4, T, Q> x4 = x0 + C.w; + + // Permutations + i = mod(i, vec<4, T, Q>(289)); + T j0 = detail::permute(detail::permute(detail::permute(detail::permute(i.w) + i.z) + i.y) + i.x); + vec<4, T, Q> j1 = detail::permute(detail::permute(detail::permute(detail::permute( + i.w + vec<4, T, Q>(i1.w, i2.w, i3.w, T(1))) + + i.z + vec<4, T, Q>(i1.z, i2.z, i3.z, T(1))) + + i.y + vec<4, T, Q>(i1.y, i2.y, i3.y, T(1))) + + i.x + vec<4, T, Q>(i1.x, i2.x, i3.x, T(1))); + + // Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope + // 7*7*6 = 294, which is close to the ring size 17*17 = 289. + vec<4, T, Q> ip = vec<4, T, Q>(T(1) / T(294), T(1) / T(49), T(1) / T(7), T(0)); + + vec<4, T, Q> p0 = detail::grad4(j0, ip); + vec<4, T, Q> p1 = detail::grad4(j1.x, ip); + vec<4, T, Q> p2 = detail::grad4(j1.y, ip); + vec<4, T, Q> p3 = detail::grad4(j1.z, ip); + vec<4, T, Q> p4 = detail::grad4(j1.w, ip); + + // Normalise gradients + vec<4, T, Q> norm = detail::taylorInvSqrt(vec<4, T, Q>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + p4 *= detail::taylorInvSqrt(dot(p4, p4)); + + // Mix contributions from the five corners + vec<3, T, Q> m0 = max(T(0.6) - vec<3, T, Q>(dot(x0, x0), dot(x1, x1), dot(x2, x2)), vec<3, T, Q>(0)); + vec<2, T, Q> m1 = max(T(0.6) - vec<2, T, Q>(dot(x3, x3), dot(x4, x4) ), vec<2, T, Q>(0)); + m0 = m0 * m0; + m1 = m1 * m1; + return T(49) * + (dot(m0 * m0, vec<3, T, Q>(dot(p0, x0), dot(p1, x1), dot(p2, x2))) + + dot(m1 * m1, vec<2, T, Q>(dot(p3, x3), dot(p4, x4)))); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/packing.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/packing.hpp new file mode 100644 index 0000000..8e416b3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/packing.hpp @@ -0,0 +1,728 @@ +/// @ref gtc_packing +/// @file glm/gtc/packing.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_packing GLM_GTC_packing +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// This extension provides a set of function to convert vertors to packed +/// formats. + +#pragma once + +// Dependency: +#include "type_precision.hpp" +#include "../ext/vector_packing.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_packing extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_packing + /// @{ + + /// First, converts the normalized floating-point value v into a 8-bit integer value. + /// Then, the results are packed into the returned 8-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm1x8: round(clamp(c, 0, +1) * 255.0) + /// + /// @see gtc_packing + /// @see uint16 packUnorm2x8(vec2 const& v) + /// @see uint32 packUnorm4x8(vec4 const& v) + /// @see GLSL packUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint8 packUnorm1x8(float v); + + /// Convert a single 8-bit integer to a normalized floating-point value. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm4x8: f / 255.0 + /// + /// @see gtc_packing + /// @see vec2 unpackUnorm2x8(uint16 p) + /// @see vec4 unpackUnorm4x8(uint32 p) + /// @see GLSL unpackUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL float unpackUnorm1x8(uint8 p); + + /// First, converts each component of the normalized floating-point value v into 8-bit integer values. + /// Then, the results are packed into the returned 16-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm2x8: round(clamp(c, 0, +1) * 255.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see gtc_packing + /// @see uint8 packUnorm1x8(float const& v) + /// @see uint32 packUnorm4x8(vec4 const& v) + /// @see GLSL packUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint16 packUnorm2x8(vec2 const& v); + + /// First, unpacks a single 16-bit unsigned integer p into a pair of 8-bit unsigned integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm4x8: f / 255.0 + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see float unpackUnorm1x8(uint8 v) + /// @see vec4 unpackUnorm4x8(uint32 p) + /// @see GLSL unpackUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec2 unpackUnorm2x8(uint16 p); + + /// First, converts the normalized floating-point value v into 8-bit integer value. + /// Then, the results are packed into the returned 8-bit unsigned integer. + /// + /// The conversion to fixed point is done as follows: + /// packSnorm1x8: round(clamp(s, -1, +1) * 127.0) + /// + /// @see gtc_packing + /// @see uint16 packSnorm2x8(vec2 const& v) + /// @see uint32 packSnorm4x8(vec4 const& v) + /// @see GLSL packSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint8 packSnorm1x8(float s); + + /// First, unpacks a single 8-bit unsigned integer p into a single 8-bit signed integers. + /// Then, the value is converted to a normalized floating-point value to generate the returned scalar. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm1x8: clamp(f / 127.0, -1, +1) + /// + /// @see gtc_packing + /// @see vec2 unpackSnorm2x8(uint16 p) + /// @see vec4 unpackSnorm4x8(uint32 p) + /// @see GLSL unpackSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL float unpackSnorm1x8(uint8 p); + + /// First, converts each component of the normalized floating-point value v into 8-bit integer values. + /// Then, the results are packed into the returned 16-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm2x8: round(clamp(c, -1, +1) * 127.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see gtc_packing + /// @see uint8 packSnorm1x8(float const& v) + /// @see uint32 packSnorm4x8(vec4 const& v) + /// @see GLSL packSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint16 packSnorm2x8(vec2 const& v); + + /// First, unpacks a single 16-bit unsigned integer p into a pair of 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm2x8: clamp(f / 127.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see float unpackSnorm1x8(uint8 p) + /// @see vec4 unpackSnorm4x8(uint32 p) + /// @see GLSL unpackSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec2 unpackSnorm2x8(uint16 p); + + /// First, converts the normalized floating-point value v into a 16-bit integer value. + /// Then, the results are packed into the returned 16-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm1x16: round(clamp(c, 0, +1) * 65535.0) + /// + /// @see gtc_packing + /// @see uint16 packSnorm1x16(float const& v) + /// @see uint64 packSnorm4x16(vec4 const& v) + /// @see GLSL packUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint16 packUnorm1x16(float v); + + /// First, unpacks a single 16-bit unsigned integer p into a of 16-bit unsigned integers. + /// Then, the value is converted to a normalized floating-point value to generate the returned scalar. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm1x16: f / 65535.0 + /// + /// @see gtc_packing + /// @see vec2 unpackUnorm2x16(uint32 p) + /// @see vec4 unpackUnorm4x16(uint64 p) + /// @see GLSL unpackUnorm2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL float unpackUnorm1x16(uint16 p); + + /// First, converts each component of the normalized floating-point value v into 16-bit integer values. + /// Then, the results are packed into the returned 64-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm4x16: round(clamp(c, 0, +1) * 65535.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see gtc_packing + /// @see uint16 packUnorm1x16(float const& v) + /// @see uint32 packUnorm2x16(vec2 const& v) + /// @see GLSL packUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint64 packUnorm4x16(vec4 const& v); + + /// First, unpacks a single 64-bit unsigned integer p into four 16-bit unsigned integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnormx4x16: f / 65535.0 + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see float unpackUnorm1x16(uint16 p) + /// @see vec2 unpackUnorm2x16(uint32 p) + /// @see GLSL unpackUnorm2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec4 unpackUnorm4x16(uint64 p); + + /// First, converts the normalized floating-point value v into 16-bit integer value. + /// Then, the results are packed into the returned 16-bit unsigned integer. + /// + /// The conversion to fixed point is done as follows: + /// packSnorm1x8: round(clamp(s, -1, +1) * 32767.0) + /// + /// @see gtc_packing + /// @see uint32 packSnorm2x16(vec2 const& v) + /// @see uint64 packSnorm4x16(vec4 const& v) + /// @see GLSL packSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint16 packSnorm1x16(float v); + + /// First, unpacks a single 16-bit unsigned integer p into a single 16-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned scalar. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm1x16: clamp(f / 32767.0, -1, +1) + /// + /// @see gtc_packing + /// @see vec2 unpackSnorm2x16(uint32 p) + /// @see vec4 unpackSnorm4x16(uint64 p) + /// @see GLSL unpackSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL float unpackSnorm1x16(uint16 p); + + /// First, converts each component of the normalized floating-point value v into 16-bit integer values. + /// Then, the results are packed into the returned 64-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm2x8: round(clamp(c, -1, +1) * 32767.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see gtc_packing + /// @see uint16 packSnorm1x16(float const& v) + /// @see uint32 packSnorm2x16(vec2 const& v) + /// @see GLSL packSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint64 packSnorm4x16(vec4 const& v); + + /// First, unpacks a single 64-bit unsigned integer p into four 16-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm4x16: clamp(f / 32767.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see float unpackSnorm1x16(uint16 p) + /// @see vec2 unpackSnorm2x16(uint32 p) + /// @see GLSL unpackSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec4 unpackSnorm4x16(uint64 p); + + /// Returns an unsigned integer obtained by converting the components of a floating-point scalar + /// to the 16-bit floating-point representation found in the OpenGL Specification, + /// and then packing this 16-bit value into a 16-bit unsigned integer. + /// + /// @see gtc_packing + /// @see uint32 packHalf2x16(vec2 const& v) + /// @see uint64 packHalf4x16(vec4 const& v) + /// @see GLSL packHalf2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint16 packHalf1x16(float v); + + /// Returns a floating-point scalar with components obtained by unpacking a 16-bit unsigned integer into a 16-bit value, + /// interpreted as a 16-bit floating-point number according to the OpenGL Specification, + /// and converting it to 32-bit floating-point values. + /// + /// @see gtc_packing + /// @see vec2 unpackHalf2x16(uint32 const& v) + /// @see vec4 unpackHalf4x16(uint64 const& v) + /// @see GLSL unpackHalf2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL float unpackHalf1x16(uint16 v); + + /// Returns an unsigned integer obtained by converting the components of a four-component floating-point vector + /// to the 16-bit floating-point representation found in the OpenGL Specification, + /// and then packing these four 16-bit values into a 64-bit unsigned integer. + /// The first vector component specifies the 16 least-significant bits of the result; + /// the forth component specifies the 16 most-significant bits. + /// + /// @see gtc_packing + /// @see uint16 packHalf1x16(float const& v) + /// @see uint32 packHalf2x16(vec2 const& v) + /// @see GLSL packHalf2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint64 packHalf4x16(vec4 const& v); + + /// Returns a four-component floating-point vector with components obtained by unpacking a 64-bit unsigned integer into four 16-bit values, + /// interpreting those values as 16-bit floating-point numbers according to the OpenGL Specification, + /// and converting them to 32-bit floating-point values. + /// The first component of the vector is obtained from the 16 least-significant bits of v; + /// the forth component is obtained from the 16 most-significant bits of v. + /// + /// @see gtc_packing + /// @see float unpackHalf1x16(uint16 const& v) + /// @see vec2 unpackHalf2x16(uint32 const& v) + /// @see GLSL unpackHalf2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec4 unpackHalf4x16(uint64 p); + + /// Returns an unsigned integer obtained by converting the components of a four-component signed integer vector + /// to the 10-10-10-2-bit signed integer representation found in the OpenGL Specification, + /// and then packing these four values into a 32-bit unsigned integer. + /// The first vector component specifies the 10 least-significant bits of the result; + /// the forth component specifies the 2 most-significant bits. + /// + /// @see gtc_packing + /// @see uint32 packI3x10_1x2(uvec4 const& v) + /// @see uint32 packSnorm3x10_1x2(vec4 const& v) + /// @see uint32 packUnorm3x10_1x2(vec4 const& v) + /// @see ivec4 unpackI3x10_1x2(uint32 const& p) + GLM_FUNC_DECL uint32 packI3x10_1x2(ivec4 const& v); + + /// Unpacks a single 32-bit unsigned integer p into three 10-bit and one 2-bit signed integers. + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packU3x10_1x2(uvec4 const& v) + /// @see vec4 unpackSnorm3x10_1x2(uint32 const& p); + /// @see uvec4 unpackI3x10_1x2(uint32 const& p); + GLM_FUNC_DECL ivec4 unpackI3x10_1x2(uint32 p); + + /// Returns an unsigned integer obtained by converting the components of a four-component unsigned integer vector + /// to the 10-10-10-2-bit unsigned integer representation found in the OpenGL Specification, + /// and then packing these four values into a 32-bit unsigned integer. + /// The first vector component specifies the 10 least-significant bits of the result; + /// the forth component specifies the 2 most-significant bits. + /// + /// @see gtc_packing + /// @see uint32 packI3x10_1x2(ivec4 const& v) + /// @see uint32 packSnorm3x10_1x2(vec4 const& v) + /// @see uint32 packUnorm3x10_1x2(vec4 const& v) + /// @see ivec4 unpackU3x10_1x2(uint32 const& p) + GLM_FUNC_DECL uint32 packU3x10_1x2(uvec4 const& v); + + /// Unpacks a single 32-bit unsigned integer p into three 10-bit and one 2-bit unsigned integers. + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packU3x10_1x2(uvec4 const& v) + /// @see vec4 unpackSnorm3x10_1x2(uint32 const& p); + /// @see uvec4 unpackI3x10_1x2(uint32 const& p); + GLM_FUNC_DECL uvec4 unpackU3x10_1x2(uint32 p); + + /// First, converts the first three components of the normalized floating-point value v into 10-bit signed integer values. + /// Then, converts the forth component of the normalized floating-point value v into 2-bit signed integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm3x10_1x2(xyz): round(clamp(c, -1, +1) * 511.0) + /// packSnorm3x10_1x2(w): round(clamp(c, -1, +1) * 1.0) + /// + /// The first vector component specifies the 10 least-significant bits of the result; + /// the forth component specifies the 2 most-significant bits. + /// + /// @see gtc_packing + /// @see vec4 unpackSnorm3x10_1x2(uint32 const& p) + /// @see uint32 packUnorm3x10_1x2(vec4 const& v) + /// @see uint32 packU3x10_1x2(uvec4 const& v) + /// @see uint32 packI3x10_1x2(ivec4 const& v) + GLM_FUNC_DECL uint32 packSnorm3x10_1x2(vec4 const& v); + + /// First, unpacks a single 32-bit unsigned integer p into four 16-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm3x10_1x2(xyz): clamp(f / 511.0, -1, +1) + /// unpackSnorm3x10_1x2(w): clamp(f / 511.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packSnorm3x10_1x2(vec4 const& v) + /// @see vec4 unpackUnorm3x10_1x2(uint32 const& p)) + /// @see uvec4 unpackI3x10_1x2(uint32 const& p) + /// @see uvec4 unpackU3x10_1x2(uint32 const& p) + GLM_FUNC_DECL vec4 unpackSnorm3x10_1x2(uint32 p); + + /// First, converts the first three components of the normalized floating-point value v into 10-bit unsigned integer values. + /// Then, converts the forth component of the normalized floating-point value v into 2-bit signed uninteger values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm3x10_1x2(xyz): round(clamp(c, 0, +1) * 1023.0) + /// packUnorm3x10_1x2(w): round(clamp(c, 0, +1) * 3.0) + /// + /// The first vector component specifies the 10 least-significant bits of the result; + /// the forth component specifies the 2 most-significant bits. + /// + /// @see gtc_packing + /// @see vec4 unpackUnorm3x10_1x2(uint32 const& p) + /// @see uint32 packUnorm3x10_1x2(vec4 const& v) + /// @see uint32 packU3x10_1x2(uvec4 const& v) + /// @see uint32 packI3x10_1x2(ivec4 const& v) + GLM_FUNC_DECL uint32 packUnorm3x10_1x2(vec4 const& v); + + /// First, unpacks a single 32-bit unsigned integer p into four 16-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm3x10_1x2(xyz): clamp(f / 1023.0, 0, +1) + /// unpackSnorm3x10_1x2(w): clamp(f / 3.0, 0, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packSnorm3x10_1x2(vec4 const& v) + /// @see vec4 unpackInorm3x10_1x2(uint32 const& p)) + /// @see uvec4 unpackI3x10_1x2(uint32 const& p) + /// @see uvec4 unpackU3x10_1x2(uint32 const& p) + GLM_FUNC_DECL vec4 unpackUnorm3x10_1x2(uint32 p); + + /// First, converts the first two components of the normalized floating-point value v into 11-bit signless floating-point values. + /// Then, converts the third component of the normalized floating-point value v into a 10-bit signless floating-point value. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The first vector component specifies the 11 least-significant bits of the result; + /// the last component specifies the 10 most-significant bits. + /// + /// @see gtc_packing + /// @see vec3 unpackF2x11_1x10(uint32 const& p) + GLM_FUNC_DECL uint32 packF2x11_1x10(vec3 const& v); + + /// First, unpacks a single 32-bit unsigned integer p into two 11-bit signless floating-point values and one 10-bit signless floating-point value . + /// Then, each component is converted to a normalized floating-point value to generate the returned three-component vector. + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packF2x11_1x10(vec3 const& v) + GLM_FUNC_DECL vec3 unpackF2x11_1x10(uint32 p); + + + /// First, converts the first two components of the normalized floating-point value v into 11-bit signless floating-point values. + /// Then, converts the third component of the normalized floating-point value v into a 10-bit signless floating-point value. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The first vector component specifies the 11 least-significant bits of the result; + /// the last component specifies the 10 most-significant bits. + /// + /// packF3x9_E1x5 allows encoding into RGBE / RGB9E5 format + /// + /// @see gtc_packing + /// @see vec3 unpackF3x9_E1x5(uint32 const& p) + GLM_FUNC_DECL uint32 packF3x9_E1x5(vec3 const& v); + + /// First, unpacks a single 32-bit unsigned integer p into two 11-bit signless floating-point values and one 10-bit signless floating-point value . + /// Then, each component is converted to a normalized floating-point value to generate the returned three-component vector. + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// unpackF3x9_E1x5 allows decoding RGBE / RGB9E5 data + /// + /// @see gtc_packing + /// @see uint32 packF3x9_E1x5(vec3 const& v) + GLM_FUNC_DECL vec3 unpackF3x9_E1x5(uint32 p); + + /// Returns an unsigned integer vector obtained by converting the components of a floating-point vector + /// to the 16-bit floating-point representation found in the OpenGL Specification. + /// The first vector component specifies the 16 least-significant bits of the result; + /// the forth component specifies the 16 most-significant bits. + /// + /// @see gtc_packing + /// @see vec<3, T, Q> unpackRGBM(vec<4, T, Q> const& p) + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + template + GLM_FUNC_DECL vec<4, T, Q> packRGBM(vec<3, T, Q> const& rgb); + + /// Returns a floating-point vector with components obtained by reinterpreting an integer vector as 16-bit floating-point numbers and converting them to 32-bit floating-point values. + /// The first component of the vector is obtained from the 16 least-significant bits of v; + /// the forth component is obtained from the 16 most-significant bits of v. + /// + /// @see gtc_packing + /// @see vec<4, T, Q> packRGBM(vec<3, float, Q> const& v) + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + template + GLM_FUNC_DECL vec<3, T, Q> unpackRGBM(vec<4, T, Q> const& rgbm); + + /// Returns an unsigned integer vector obtained by converting the components of a floating-point vector + /// to the 16-bit floating-point representation found in the OpenGL Specification. + /// The first vector component specifies the 16 least-significant bits of the result; + /// the forth component specifies the 16 most-significant bits. + /// + /// @see gtc_packing + /// @see vec unpackHalf(vec const& p) + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + template + GLM_FUNC_DECL vec packHalf(vec const& v); + + /// Returns a floating-point vector with components obtained by reinterpreting an integer vector as 16-bit floating-point numbers and converting them to 32-bit floating-point values. + /// The first component of the vector is obtained from the 16 least-significant bits of v; + /// the forth component is obtained from the 16 most-significant bits of v. + /// + /// @see gtc_packing + /// @see vec packHalf(vec const& v) + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + template + GLM_FUNC_DECL vec unpackHalf(vec const& p); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec unpackUnorm(vec const& p); + template + GLM_FUNC_DECL vec packUnorm(vec const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see vec packUnorm(vec const& v) + template + GLM_FUNC_DECL vec unpackUnorm(vec const& v); + + /// Convert each component of the normalized floating-point vector into signed integer values. + /// + /// @see gtc_packing + /// @see vec unpackSnorm(vec const& p); + template + GLM_FUNC_DECL vec packSnorm(vec const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see vec packSnorm(vec const& v) + template + GLM_FUNC_DECL vec unpackSnorm(vec const& v); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec2 unpackUnorm2x4(uint8 p) + GLM_FUNC_DECL uint8 packUnorm2x4(vec2 const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see uint8 packUnorm2x4(vec2 const& v) + GLM_FUNC_DECL vec2 unpackUnorm2x4(uint8 p); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec4 unpackUnorm4x4(uint16 p) + GLM_FUNC_DECL uint16 packUnorm4x4(vec4 const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see uint16 packUnorm4x4(vec4 const& v) + GLM_FUNC_DECL vec4 unpackUnorm4x4(uint16 p); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec3 unpackUnorm1x5_1x6_1x5(uint16 p) + GLM_FUNC_DECL uint16 packUnorm1x5_1x6_1x5(vec3 const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see uint16 packUnorm1x5_1x6_1x5(vec3 const& v) + GLM_FUNC_DECL vec3 unpackUnorm1x5_1x6_1x5(uint16 p); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec4 unpackUnorm3x5_1x1(uint16 p) + GLM_FUNC_DECL uint16 packUnorm3x5_1x1(vec4 const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see uint16 packUnorm3x5_1x1(vec4 const& v) + GLM_FUNC_DECL vec4 unpackUnorm3x5_1x1(uint16 p); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec3 unpackUnorm2x3_1x2(uint8 p) + GLM_FUNC_DECL uint8 packUnorm2x3_1x2(vec3 const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see uint8 packUnorm2x3_1x2(vec3 const& v) + GLM_FUNC_DECL vec3 unpackUnorm2x3_1x2(uint8 p); + + + + /// Convert each component from an integer vector into a packed integer. + /// + /// @see gtc_packing + /// @see i8vec2 unpackInt2x8(int16 p) + GLM_FUNC_DECL int16 packInt2x8(i8vec2 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see int16 packInt2x8(i8vec2 const& v) + GLM_FUNC_DECL i8vec2 unpackInt2x8(int16 p); + + /// Convert each component from an integer vector into a packed unsigned integer. + /// + /// @see gtc_packing + /// @see u8vec2 unpackInt2x8(uint16 p) + GLM_FUNC_DECL uint16 packUint2x8(u8vec2 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see uint16 packInt2x8(u8vec2 const& v) + GLM_FUNC_DECL u8vec2 unpackUint2x8(uint16 p); + + /// Convert each component from an integer vector into a packed integer. + /// + /// @see gtc_packing + /// @see i8vec4 unpackInt4x8(int32 p) + GLM_FUNC_DECL int32 packInt4x8(i8vec4 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see int32 packInt2x8(i8vec4 const& v) + GLM_FUNC_DECL i8vec4 unpackInt4x8(int32 p); + + /// Convert each component from an integer vector into a packed unsigned integer. + /// + /// @see gtc_packing + /// @see u8vec4 unpackUint4x8(uint32 p) + GLM_FUNC_DECL uint32 packUint4x8(u8vec4 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see uint32 packUint4x8(u8vec2 const& v) + GLM_FUNC_DECL u8vec4 unpackUint4x8(uint32 p); + + /// Convert each component from an integer vector into a packed integer. + /// + /// @see gtc_packing + /// @see i16vec2 unpackInt2x16(int p) + GLM_FUNC_DECL int packInt2x16(i16vec2 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see int packInt2x16(i16vec2 const& v) + GLM_FUNC_DECL i16vec2 unpackInt2x16(int p); + + /// Convert each component from an integer vector into a packed integer. + /// + /// @see gtc_packing + /// @see i16vec4 unpackInt4x16(int64 p) + GLM_FUNC_DECL int64 packInt4x16(i16vec4 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see int64 packInt4x16(i16vec4 const& v) + GLM_FUNC_DECL i16vec4 unpackInt4x16(int64 p); + + /// Convert each component from an integer vector into a packed unsigned integer. + /// + /// @see gtc_packing + /// @see u16vec2 unpackUint2x16(uint p) + GLM_FUNC_DECL uint packUint2x16(u16vec2 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see uint packUint2x16(u16vec2 const& v) + GLM_FUNC_DECL u16vec2 unpackUint2x16(uint p); + + /// Convert each component from an integer vector into a packed unsigned integer. + /// + /// @see gtc_packing + /// @see u16vec4 unpackUint4x16(uint64 p) + GLM_FUNC_DECL uint64 packUint4x16(u16vec4 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see uint64 packUint4x16(u16vec4 const& v) + GLM_FUNC_DECL u16vec4 unpackUint4x16(uint64 p); + + /// Convert each component from an integer vector into a packed integer. + /// + /// @see gtc_packing + /// @see i32vec2 unpackInt2x32(int p) + GLM_FUNC_DECL int64 packInt2x32(i32vec2 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see int packInt2x16(i32vec2 const& v) + GLM_FUNC_DECL i32vec2 unpackInt2x32(int64 p); + + /// Convert each component from an integer vector into a packed unsigned integer. + /// + /// @see gtc_packing + /// @see u32vec2 unpackUint2x32(int p) + GLM_FUNC_DECL uint64 packUint2x32(u32vec2 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see int packUint2x16(u32vec2 const& v) + GLM_FUNC_DECL u32vec2 unpackUint2x32(uint64 p); + + /// @} +}// namespace glm + +#include "packing.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/packing.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/packing.inl new file mode 100644 index 0000000..1792760 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/packing.inl @@ -0,0 +1,951 @@ +/// @ref gtc_packing + +#include "../ext/scalar_relational.hpp" +#include "../ext/vector_relational.hpp" +#include "../common.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../detail/type_half.hpp" +#include +#include + +namespace glm{ +namespace detail +{ + GLM_FUNC_QUALIFIER glm::uint16 float2half(glm::uint32 f) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x00007c00 => 00000000 00000000 01111100 00000000 + // 0x000003ff => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((f >> 16) & 0x8000) | // sign + ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) | // exponential + ((f >> 13) & 0x03ff); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint32 float2packed11(glm::uint32 f) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x000007c0 => 00000000 00000000 00000111 11000000 + // 0x00007c00 => 00000000 00000000 01111100 00000000 + // 0x000003ff => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((((f & 0x7f800000) - 0x38000000) >> 17) & 0x07c0) | // exponential + ((f >> 17) & 0x003f); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint32 packed11ToFloat(glm::uint32 p) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x000007c0 => 00000000 00000000 00000111 11000000 + // 0x00007c00 => 00000000 00000000 01111100 00000000 + // 0x000003ff => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((((p & 0x07c0) << 17) + 0x38000000) & 0x7f800000) | // exponential + ((p & 0x003f) << 17); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint32 float2packed10(glm::uint32 f) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x0000001F => 00000000 00000000 00000000 00011111 + // 0x0000003F => 00000000 00000000 00000000 00111111 + // 0x000003E0 => 00000000 00000000 00000011 11100000 + // 0x000007C0 => 00000000 00000000 00000111 11000000 + // 0x00007C00 => 00000000 00000000 01111100 00000000 + // 0x000003FF => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((((f & 0x7f800000) - 0x38000000) >> 18) & 0x03E0) | // exponential + ((f >> 18) & 0x001f); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint32 packed10ToFloat(glm::uint32 p) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x0000001F => 00000000 00000000 00000000 00011111 + // 0x0000003F => 00000000 00000000 00000000 00111111 + // 0x000003E0 => 00000000 00000000 00000011 11100000 + // 0x000007C0 => 00000000 00000000 00000111 11000000 + // 0x00007C00 => 00000000 00000000 01111100 00000000 + // 0x000003FF => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((((p & 0x03E0) << 18) + 0x38000000) & 0x7f800000) | // exponential + ((p & 0x001f) << 18); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint half2float(glm::uint h) + { + return ((h & 0x8000) << 16) | ((( h & 0x7c00) + 0x1C000) << 13) | ((h & 0x03FF) << 13); + } + + GLM_FUNC_QUALIFIER glm::uint floatTo11bit(float x) + { + if(x == 0.0f) + return 0u; + else if(glm::isnan(x)) + return ~0u; + else if(glm::isinf(x)) + return 0x1Fu << 6u; + + uint Pack = 0u; + memcpy(&Pack, &x, sizeof(Pack)); + return float2packed11(Pack); + } + + GLM_FUNC_QUALIFIER float packed11bitToFloat(glm::uint x) + { + if(x == 0) + return 0.0f; + else if(x == ((1 << 11) - 1)) + return ~0;//NaN + else if(x == (0x1f << 6)) + return ~0;//Inf + + uint Result = packed11ToFloat(x); + + float Temp = 0; + memcpy(&Temp, &Result, sizeof(Temp)); + return Temp; + } + + GLM_FUNC_QUALIFIER glm::uint floatTo10bit(float x) + { + if(x == 0.0f) + return 0u; + else if(glm::isnan(x)) + return ~0u; + else if(glm::isinf(x)) + return 0x1Fu << 5u; + + uint Pack = 0; + memcpy(&Pack, &x, sizeof(Pack)); + return float2packed10(Pack); + } + + GLM_FUNC_QUALIFIER float packed10bitToFloat(glm::uint x) + { + if(x == 0) + return 0.0f; + else if(x == ((1 << 10) - 1)) + return ~0;//NaN + else if(x == (0x1f << 5)) + return ~0;//Inf + + uint Result = packed10ToFloat(x); + + float Temp = 0; + memcpy(&Temp, &Result, sizeof(Temp)); + return Temp; + } + +// GLM_FUNC_QUALIFIER glm::uint f11_f11_f10(float x, float y, float z) +// { +// return ((floatTo11bit(x) & ((1 << 11) - 1)) << 0) | ((floatTo11bit(y) & ((1 << 11) - 1)) << 11) | ((floatTo10bit(z) & ((1 << 10) - 1)) << 22); +// } + +#if GLM_SILENT_WARNINGS == GLM_ENABLE +# if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# endif +#endif + + union u3u3u2 + { + struct Data + { + uint x : 3; + uint y : 3; + uint z : 2; + } data; + uint8 pack; + }; + + union u4u4 + { + struct Data + { + uint x : 4; + uint y : 4; + } data; + uint8 pack; + }; + + union u4u4u4u4 + { + struct Data + { + uint x : 4; + uint y : 4; + uint z : 4; + uint w : 4; + } data; + uint16 pack; + }; + + union u5u6u5 + { + struct Data + { + uint x : 5; + uint y : 6; + uint z : 5; + } data; + uint16 pack; + }; + + union u5u5u5u1 + { + struct Data + { + uint x : 5; + uint y : 5; + uint z : 5; + uint w : 1; + } data; + uint16 pack; + }; + +#if GLM_SILENT_WARNINGS == GLM_ENABLE +# if defined(__clang__) +# pragma clang diagnostic pop +# endif +#endif + + union u10u10u10u2 + { + struct Data + { + uint x : 10; + uint y : 10; + uint z : 10; + uint w : 2; + } data; + uint32 pack; + }; + + union i10i10i10i2 + { + struct Data + { + int x : 10; + int y : 10; + int z : 10; + int w : 2; + } data; + uint32 pack; + }; + + union u9u9u9e5 + { + struct Data + { + uint x : 9; + uint y : 9; + uint z : 9; + uint w : 5; + } data; + uint32 pack; + }; + + template + struct compute_half + {}; + + template + struct compute_half<1, Q> + { + GLM_FUNC_QUALIFIER static vec<1, uint16, Q> pack(vec<1, float, Q> const& v) + { + int16 const Unpack(detail::toFloat16(v.x)); + u16vec1 Packed; + memcpy(&Packed, &Unpack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER static vec<1, float, Q> unpack(vec<1, uint16, Q> const& v) + { + i16vec1 Unpack; + memcpy(&Unpack, &v, sizeof(Unpack)); + return vec<1, float, Q>(detail::toFloat32(v.x)); + } + }; + + template + struct compute_half<2, Q> + { + GLM_FUNC_QUALIFIER static vec<2, uint16, Q> pack(vec<2, float, Q> const& v) + { + vec<2, int16, Q> const Unpack(detail::toFloat16(v.x), detail::toFloat16(v.y)); + u16vec2 Packed; + memcpy(&Packed, &Unpack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER static vec<2, float, Q> unpack(vec<2, uint16, Q> const& v) + { + i16vec2 Unpack; + memcpy(&Unpack, &v, sizeof(Unpack)); + return vec<2, float, Q>(detail::toFloat32(v.x), detail::toFloat32(v.y)); + } + }; + + template + struct compute_half<3, Q> + { + GLM_FUNC_QUALIFIER static vec<3, uint16, Q> pack(vec<3, float, Q> const& v) + { + vec<3, int16, Q> const Unpack(detail::toFloat16(v.x), detail::toFloat16(v.y), detail::toFloat16(v.z)); + u16vec3 Packed; + memcpy(&Packed, &Unpack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER static vec<3, float, Q> unpack(vec<3, uint16, Q> const& v) + { + i16vec3 Unpack; + memcpy(&Unpack, &v, sizeof(Unpack)); + return vec<3, float, Q>(detail::toFloat32(v.x), detail::toFloat32(v.y), detail::toFloat32(v.z)); + } + }; + + template + struct compute_half<4, Q> + { + GLM_FUNC_QUALIFIER static vec<4, uint16, Q> pack(vec<4, float, Q> const& v) + { + vec<4, int16, Q> const Unpack(detail::toFloat16(v.x), detail::toFloat16(v.y), detail::toFloat16(v.z), detail::toFloat16(v.w)); + u16vec4 Packed; + memcpy(&Packed, &Unpack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER static vec<4, float, Q> unpack(vec<4, uint16, Q> const& v) + { + i16vec4 Unpack; + memcpy(&Unpack, &v, sizeof(Unpack)); + return vec<4, float, Q>(detail::toFloat32(Unpack.x), detail::toFloat32(Unpack.y), detail::toFloat32(Unpack.z), detail::toFloat32(Unpack.w)); + } + }; +}//namespace detail + + GLM_FUNC_QUALIFIER uint8 packUnorm1x8(float v) + { + return static_cast(round(clamp(v, 0.0f, 1.0f) * 255.0f)); + } + + GLM_FUNC_QUALIFIER float unpackUnorm1x8(uint8 p) + { + float const Unpack(p); + return Unpack * static_cast(0.0039215686274509803921568627451); // 1 / 255 + } + + GLM_FUNC_QUALIFIER uint16 packUnorm2x8(vec2 const& v) + { + u8vec2 const Topack(round(clamp(v, 0.0f, 1.0f) * 255.0f)); + + uint16 Unpack = 0; + memcpy(&Unpack, &Topack, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER vec2 unpackUnorm2x8(uint16 p) + { + u8vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return vec2(Unpack) * float(0.0039215686274509803921568627451); // 1 / 255 + } + + GLM_FUNC_QUALIFIER uint8 packSnorm1x8(float v) + { + int8 const Topack(static_cast(round(clamp(v ,-1.0f, 1.0f) * 127.0f))); + uint8 Packed = 0; + memcpy(&Packed, &Topack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER float unpackSnorm1x8(uint8 p) + { + int8 Unpack = 0; + memcpy(&Unpack, &p, sizeof(Unpack)); + return clamp( + static_cast(Unpack) * 0.00787401574803149606299212598425f, // 1.0f / 127.0f + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint16 packSnorm2x8(vec2 const& v) + { + i8vec2 const Topack(round(clamp(v, -1.0f, 1.0f) * 127.0f)); + uint16 Packed = 0; + memcpy(&Packed, &Topack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER vec2 unpackSnorm2x8(uint16 p) + { + i8vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return clamp( + vec2(Unpack) * 0.00787401574803149606299212598425f, // 1.0f / 127.0f + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint16 packUnorm1x16(float s) + { + return static_cast(round(clamp(s, 0.0f, 1.0f) * 65535.0f)); + } + + GLM_FUNC_QUALIFIER float unpackUnorm1x16(uint16 p) + { + float const Unpack(p); + return Unpack * 1.5259021896696421759365224689097e-5f; // 1.0 / 65535.0 + } + + GLM_FUNC_QUALIFIER uint64 packUnorm4x16(vec4 const& v) + { + u16vec4 const Topack(round(clamp(v , 0.0f, 1.0f) * 65535.0f)); + uint64 Packed = 0; + memcpy(&Packed, &Topack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm4x16(uint64 p) + { + u16vec4 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return vec4(Unpack) * 1.5259021896696421759365224689097e-5f; // 1.0 / 65535.0 + } + + GLM_FUNC_QUALIFIER uint16 packSnorm1x16(float v) + { + int16 const Topack = static_cast(round(clamp(v ,-1.0f, 1.0f) * 32767.0f)); + uint16 Packed = 0; + memcpy(&Packed, &Topack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER float unpackSnorm1x16(uint16 p) + { + int16 Unpack = 0; + memcpy(&Unpack, &p, sizeof(Unpack)); + return clamp( + static_cast(Unpack) * 3.0518509475997192297128208258309e-5f, //1.0f / 32767.0f, + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint64 packSnorm4x16(vec4 const& v) + { + i16vec4 const Topack(round(clamp(v ,-1.0f, 1.0f) * 32767.0f)); + uint64 Packed = 0; + memcpy(&Packed, &Topack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER vec4 unpackSnorm4x16(uint64 p) + { + i16vec4 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return clamp( + vec4(Unpack) * 3.0518509475997192297128208258309e-5f, //1.0f / 32767.0f, + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint16 packHalf1x16(float v) + { + int16 const Topack(detail::toFloat16(v)); + uint16 Packed = 0; + memcpy(&Packed, &Topack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER float unpackHalf1x16(uint16 v) + { + int16 Unpack = 0; + memcpy(&Unpack, &v, sizeof(Unpack)); + return detail::toFloat32(Unpack); + } + + GLM_FUNC_QUALIFIER uint64 packHalf4x16(glm::vec4 const& v) + { + i16vec4 const Unpack( + detail::toFloat16(v.x), + detail::toFloat16(v.y), + detail::toFloat16(v.z), + detail::toFloat16(v.w)); + uint64 Packed = 0; + memcpy(&Packed, &Unpack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER glm::vec4 unpackHalf4x16(uint64 v) + { + i16vec4 Unpack; + memcpy(&Unpack, &v, sizeof(Unpack)); + return vec4( + detail::toFloat32(Unpack.x), + detail::toFloat32(Unpack.y), + detail::toFloat32(Unpack.z), + detail::toFloat32(Unpack.w)); + } + + GLM_FUNC_QUALIFIER uint32 packI3x10_1x2(ivec4 const& v) + { + detail::i10i10i10i2 Result; + Result.data.x = v.x; + Result.data.y = v.y; + Result.data.z = v.z; + Result.data.w = v.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER ivec4 unpackI3x10_1x2(uint32 v) + { + detail::i10i10i10i2 Unpack; + Unpack.pack = v; + return ivec4( + Unpack.data.x, + Unpack.data.y, + Unpack.data.z, + Unpack.data.w); + } + + GLM_FUNC_QUALIFIER uint32 packU3x10_1x2(uvec4 const& v) + { + detail::u10u10u10u2 Result; + Result.data.x = v.x; + Result.data.y = v.y; + Result.data.z = v.z; + Result.data.w = v.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER uvec4 unpackU3x10_1x2(uint32 v) + { + detail::u10u10u10u2 Unpack; + Unpack.pack = v; + return uvec4( + Unpack.data.x, + Unpack.data.y, + Unpack.data.z, + Unpack.data.w); + } + + GLM_FUNC_QUALIFIER uint32 packSnorm3x10_1x2(vec4 const& v) + { + ivec4 const Pack(round(clamp(v,-1.0f, 1.0f) * vec4(511.f, 511.f, 511.f, 1.f))); + + detail::i10i10i10i2 Result; + Result.data.x = Pack.x; + Result.data.y = Pack.y; + Result.data.z = Pack.z; + Result.data.w = Pack.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec4 unpackSnorm3x10_1x2(uint32 v) + { + detail::i10i10i10i2 Unpack; + Unpack.pack = v; + + vec4 const Result(Unpack.data.x, Unpack.data.y, Unpack.data.z, Unpack.data.w); + + return clamp(Result * vec4(1.f / 511.f, 1.f / 511.f, 1.f / 511.f, 1.f), -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint32 packUnorm3x10_1x2(vec4 const& v) + { + uvec4 const Unpack(round(clamp(v, 0.0f, 1.0f) * vec4(1023.f, 1023.f, 1023.f, 3.f))); + + detail::u10u10u10u2 Result; + Result.data.x = Unpack.x; + Result.data.y = Unpack.y; + Result.data.z = Unpack.z; + Result.data.w = Unpack.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm3x10_1x2(uint32 v) + { + vec4 const ScaleFactors(1.0f / 1023.f, 1.0f / 1023.f, 1.0f / 1023.f, 1.0f / 3.f); + + detail::u10u10u10u2 Unpack; + Unpack.pack = v; + return vec4(Unpack.data.x, Unpack.data.y, Unpack.data.z, Unpack.data.w) * ScaleFactors; + } + + GLM_FUNC_QUALIFIER uint32 packF2x11_1x10(vec3 const& v) + { + return + ((detail::floatTo11bit(v.x) & ((1 << 11) - 1)) << 0) | + ((detail::floatTo11bit(v.y) & ((1 << 11) - 1)) << 11) | + ((detail::floatTo10bit(v.z) & ((1 << 10) - 1)) << 22); + } + + GLM_FUNC_QUALIFIER vec3 unpackF2x11_1x10(uint32 v) + { + return vec3( + detail::packed11bitToFloat(v >> 0), + detail::packed11bitToFloat(v >> 11), + detail::packed10bitToFloat(v >> 22)); + } + + GLM_FUNC_QUALIFIER uint32 packF3x9_E1x5(vec3 const& v) + { + float const SharedExpMax = (pow(2.0f, 9.0f - 1.0f) / pow(2.0f, 9.0f)) * pow(2.0f, 31.f - 15.f); + vec3 const Color = clamp(v, 0.0f, SharedExpMax); + float const MaxColor = max(Color.x, max(Color.y, Color.z)); + + float const ExpSharedP = max(-15.f - 1.f, floor(log2(MaxColor))) + 1.0f + 15.f; + float const MaxShared = floor(MaxColor / pow(2.0f, (ExpSharedP - 15.f - 9.f)) + 0.5f); + float const ExpShared = equal(MaxShared, pow(2.0f, 9.0f), epsilon()) ? ExpSharedP + 1.0f : ExpSharedP; + + uvec3 const ColorComp(floor(Color / pow(2.f, (ExpShared - 15.f - 9.f)) + 0.5f)); + + detail::u9u9u9e5 Unpack; + Unpack.data.x = ColorComp.x; + Unpack.data.y = ColorComp.y; + Unpack.data.z = ColorComp.z; + Unpack.data.w = uint(ExpShared); + return Unpack.pack; + } + + GLM_FUNC_QUALIFIER vec3 unpackF3x9_E1x5(uint32 v) + { + detail::u9u9u9e5 Unpack; + Unpack.pack = v; + + return vec3(Unpack.data.x, Unpack.data.y, Unpack.data.z) * pow(2.0f, static_cast(Unpack.data.w) - 15.f - 9.f); + } + + // Based on Brian Karis http://graphicrants.blogspot.fr/2009/04/rgbm-color-encoding.html + template + GLM_FUNC_QUALIFIER vec<4, T, Q> packRGBM(vec<3, T, Q> const& rgb) + { + vec<3, T, Q> const Color(rgb * static_cast(1.0 / 6.0)); + T Alpha = clamp(max(max(Color.x, Color.y), max(Color.z, static_cast(1e-6))), static_cast(0), static_cast(1)); + Alpha = ceil(Alpha * static_cast(255.0)) / static_cast(255.0); + return vec<4, T, Q>(Color / Alpha, Alpha); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> unpackRGBM(vec<4, T, Q> const& rgbm) + { + return vec<3, T, Q>(rgbm.x, rgbm.y, rgbm.z) * rgbm.w * static_cast(6); + } + + template + GLM_FUNC_QUALIFIER vec packHalf(vec const& v) + { + return detail::compute_half::pack(v); + } + + template + GLM_FUNC_QUALIFIER vec unpackHalf(vec const& v) + { + return detail::compute_half::unpack(v); + } + + template + GLM_FUNC_QUALIFIER vec packUnorm(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "uintType must be an integer type"); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "floatType must be a floating point type"); + + return vec(round(clamp(v, static_cast(0), static_cast(1)) * static_cast(std::numeric_limits::max()))); + } + + template + GLM_FUNC_QUALIFIER vec unpackUnorm(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "uintType must be an integer type"); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "floatType must be a floating point type"); + + return vec(v) * (static_cast(1) / static_cast(std::numeric_limits::max())); + } + + template + GLM_FUNC_QUALIFIER vec packSnorm(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "uintType must be an integer type"); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "floatType must be a floating point type"); + + return vec(round(clamp(v , static_cast(-1), static_cast(1)) * static_cast(std::numeric_limits::max()))); + } + + template + GLM_FUNC_QUALIFIER vec unpackSnorm(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "uintType must be an integer type"); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "floatType must be a floating point type"); + + return clamp(vec(v) * (static_cast(1) / static_cast(std::numeric_limits::max())), static_cast(-1), static_cast(1)); + } + + GLM_FUNC_QUALIFIER uint8 packUnorm2x4(vec2 const& v) + { + u32vec2 const Unpack(round(clamp(v, 0.0f, 1.0f) * 15.0f)); + detail::u4u4 Result; + Result.data.x = Unpack.x; + Result.data.y = Unpack.y; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec2 unpackUnorm2x4(uint8 v) + { + float const ScaleFactor(1.f / 15.f); + detail::u4u4 Unpack; + Unpack.pack = v; + return vec2(Unpack.data.x, Unpack.data.y) * ScaleFactor; + } + + GLM_FUNC_QUALIFIER uint16 packUnorm4x4(vec4 const& v) + { + u32vec4 const Unpack(round(clamp(v, 0.0f, 1.0f) * 15.0f)); + detail::u4u4u4u4 Result; + Result.data.x = Unpack.x; + Result.data.y = Unpack.y; + Result.data.z = Unpack.z; + Result.data.w = Unpack.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm4x4(uint16 v) + { + float const ScaleFactor(1.f / 15.f); + detail::u4u4u4u4 Unpack; + Unpack.pack = v; + return vec4(Unpack.data.x, Unpack.data.y, Unpack.data.z, Unpack.data.w) * ScaleFactor; + } + + GLM_FUNC_QUALIFIER uint16 packUnorm1x5_1x6_1x5(vec3 const& v) + { + u32vec3 const Unpack(round(clamp(v, 0.0f, 1.0f) * vec3(31.f, 63.f, 31.f))); + detail::u5u6u5 Result; + Result.data.x = Unpack.x; + Result.data.y = Unpack.y; + Result.data.z = Unpack.z; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec3 unpackUnorm1x5_1x6_1x5(uint16 v) + { + vec3 const ScaleFactor(1.f / 31.f, 1.f / 63.f, 1.f / 31.f); + detail::u5u6u5 Unpack; + Unpack.pack = v; + return vec3(Unpack.data.x, Unpack.data.y, Unpack.data.z) * ScaleFactor; + } + + GLM_FUNC_QUALIFIER uint16 packUnorm3x5_1x1(vec4 const& v) + { + u32vec4 const Unpack(round(clamp(v, 0.0f, 1.0f) * vec4(31.f, 31.f, 31.f, 1.f))); + detail::u5u5u5u1 Result; + Result.data.x = Unpack.x; + Result.data.y = Unpack.y; + Result.data.z = Unpack.z; + Result.data.w = Unpack.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm3x5_1x1(uint16 v) + { + vec4 const ScaleFactor(1.f / 31.f, 1.f / 31.f, 1.f / 31.f, 1.f); + detail::u5u5u5u1 Unpack; + Unpack.pack = v; + return vec4(Unpack.data.x, Unpack.data.y, Unpack.data.z, Unpack.data.w) * ScaleFactor; + } + + GLM_FUNC_QUALIFIER uint8 packUnorm2x3_1x2(vec3 const& v) + { + u32vec3 const Unpack(round(clamp(v, 0.0f, 1.0f) * vec3(7.f, 7.f, 3.f))); + detail::u3u3u2 Result; + Result.data.x = Unpack.x; + Result.data.y = Unpack.y; + Result.data.z = Unpack.z; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec3 unpackUnorm2x3_1x2(uint8 v) + { + vec3 const ScaleFactor(1.f / 7.f, 1.f / 7.f, 1.f / 3.f); + detail::u3u3u2 Unpack; + Unpack.pack = v; + return vec3(Unpack.data.x, Unpack.data.y, Unpack.data.z) * ScaleFactor; + } + + GLM_FUNC_QUALIFIER int16 packInt2x8(i8vec2 const& v) + { + int16 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER i8vec2 unpackInt2x8(int16 p) + { + i8vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER uint16 packUint2x8(u8vec2 const& v) + { + uint16 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER u8vec2 unpackUint2x8(uint16 p) + { + u8vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER int32 packInt4x8(i8vec4 const& v) + { + int32 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER i8vec4 unpackInt4x8(int32 p) + { + i8vec4 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER uint32 packUint4x8(u8vec4 const& v) + { + uint32 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER u8vec4 unpackUint4x8(uint32 p) + { + u8vec4 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER int packInt2x16(i16vec2 const& v) + { + int Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER i16vec2 unpackInt2x16(int p) + { + i16vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER int64 packInt4x16(i16vec4 const& v) + { + int64 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER i16vec4 unpackInt4x16(int64 p) + { + i16vec4 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER uint packUint2x16(u16vec2 const& v) + { + uint Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER u16vec2 unpackUint2x16(uint p) + { + u16vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER uint64 packUint4x16(u16vec4 const& v) + { + uint64 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER u16vec4 unpackUint4x16(uint64 p) + { + u16vec4 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER int64 packInt2x32(i32vec2 const& v) + { + int64 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER i32vec2 unpackInt2x32(int64 p) + { + i32vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER uint64 packUint2x32(u32vec2 const& v) + { + uint64 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER u32vec2 unpackUint2x32(uint64 p) + { + u32vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/quaternion.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/quaternion.hpp new file mode 100644 index 0000000..314449e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/quaternion.hpp @@ -0,0 +1,173 @@ +/// @ref gtc_quaternion +/// @file glm/gtc/quaternion.hpp +/// +/// @see core (dependence) +/// @see gtc_constants (dependence) +/// +/// @defgroup gtc_quaternion GLM_GTC_quaternion +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines a templated quaternion type and several quaternion operations. + +#pragma once + +// Dependency: +#include "../gtc/constants.hpp" +#include "../gtc/matrix_transform.hpp" +#include "../ext/vector_relational.hpp" +#include "../ext/quaternion_common.hpp" +#include "../ext/quaternion_float.hpp" +#include "../ext/quaternion_float_precision.hpp" +#include "../ext/quaternion_double.hpp" +#include "../ext/quaternion_double_precision.hpp" +#include "../ext/quaternion_relational.hpp" +#include "../ext/quaternion_geometric.hpp" +#include "../ext/quaternion_trigonometric.hpp" +#include "../ext/quaternion_transform.hpp" +#include "../detail/type_mat3x3.hpp" +#include "../detail/type_mat4x4.hpp" +#include "../detail/type_vec3.hpp" +#include "../detail/type_vec4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_quaternion extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_quaternion + /// @{ + + /// Returns euler angles, pitch as x, yaw as y, roll as z. + /// The result is expressed in radians. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL vec<3, T, Q> eulerAngles(qua const& x); + + /// Returns roll value of euler angles expressed in radians. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL T roll(qua const& x); + + /// Returns pitch value of euler angles expressed in radians. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL T pitch(qua const& x); + + /// Returns yaw value of euler angles expressed in radians. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL T yaw(qua const& x); + + /// Converts a quaternion to a 3 * 3 matrix. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL mat<3, 3, T, Q> mat3_cast(qua const& x); + + /// Converts a quaternion to a 4 * 4 matrix. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL mat<4, 4, T, Q> mat4_cast(qua const& x); + + /// Converts a pure rotation 3 * 3 matrix to a quaternion. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL qua quat_cast(mat<3, 3, T, Q> const& x); + + /// Converts a pure rotation 4 * 4 matrix to a quaternion. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL qua quat_cast(mat<4, 4, T, Q> const& x); + + /// Returns the component-wise comparison result of x < y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_relational + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, bool, Q> lessThan(qua const& x, qua const& y); + + /// Returns the component-wise comparison of result x <= y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_relational + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, bool, Q> lessThanEqual(qua const& x, qua const& y); + + /// Returns the component-wise comparison of result x > y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_relational + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, bool, Q> greaterThan(qua const& x, qua const& y); + + /// Returns the component-wise comparison of result x >= y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_relational + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, bool, Q> greaterThanEqual(qua const& x, qua const& y); + + /// Build a look at quaternion based on the default handedness. + /// + /// @param direction Desired forward direction. Needs to be normalized. + /// @param up Up vector, how the camera is oriented. Typically (0, 1, 0). + template + GLM_FUNC_DECL qua quatLookAt( + vec<3, T, Q> const& direction, + vec<3, T, Q> const& up); + + /// Build a right-handed look at quaternion. + /// + /// @param direction Desired forward direction onto which the -z-axis gets mapped. Needs to be normalized. + /// @param up Up vector, how the camera is oriented. Typically (0, 1, 0). + template + GLM_FUNC_DECL qua quatLookAtRH( + vec<3, T, Q> const& direction, + vec<3, T, Q> const& up); + + /// Build a left-handed look at quaternion. + /// + /// @param direction Desired forward direction onto which the +z-axis gets mapped. Needs to be normalized. + /// @param up Up vector, how the camera is oriented. Typically (0, 1, 0). + template + GLM_FUNC_DECL qua quatLookAtLH( + vec<3, T, Q> const& direction, + vec<3, T, Q> const& up); + /// @} +} //namespace glm + +#include "quaternion.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/quaternion.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/quaternion.inl new file mode 100644 index 0000000..ea159f2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/quaternion.inl @@ -0,0 +1,208 @@ +#include "../trigonometric.hpp" +#include "../geometric.hpp" +#include "../exponential.hpp" +#include "epsilon.hpp" +#include + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> eulerAngles(qua const& x) + { + return vec<3, T, Q>(pitch(x), yaw(x), roll(x)); + } + + template + GLM_FUNC_QUALIFIER T roll(qua const& q) + { + T const y = static_cast(2) * (q.x * q.y + q.w * q.z); + T const x = q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z; + + if(all(equal(vec<2, T, Q>(x, y), vec<2, T, Q>(0), epsilon()))) //avoid atan2(0,0) - handle singularity - Matiis + return static_cast(0); + + return static_cast(atan(y, x)); + } + + template + GLM_FUNC_QUALIFIER T pitch(qua const& q) + { + //return T(atan(T(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z)); + T const y = static_cast(2) * (q.y * q.z + q.w * q.x); + T const x = q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z; + + if(all(equal(vec<2, T, Q>(x, y), vec<2, T, Q>(0), epsilon()))) //avoid atan2(0,0) - handle singularity - Matiis + return static_cast(static_cast(2) * atan(q.x, q.w)); + + return static_cast(atan(y, x)); + } + + template + GLM_FUNC_QUALIFIER T yaw(qua const& q) + { + return asin(clamp(static_cast(-2) * (q.x * q.z - q.w * q.y), static_cast(-1), static_cast(1))); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> mat3_cast(qua const& q) + { + mat<3, 3, T, Q> Result(T(1)); + T qxx(q.x * q.x); + T qyy(q.y * q.y); + T qzz(q.z * q.z); + T qxz(q.x * q.z); + T qxy(q.x * q.y); + T qyz(q.y * q.z); + T qwx(q.w * q.x); + T qwy(q.w * q.y); + T qwz(q.w * q.z); + + Result[0][0] = T(1) - T(2) * (qyy + qzz); + Result[0][1] = T(2) * (qxy + qwz); + Result[0][2] = T(2) * (qxz - qwy); + + Result[1][0] = T(2) * (qxy - qwz); + Result[1][1] = T(1) - T(2) * (qxx + qzz); + Result[1][2] = T(2) * (qyz + qwx); + + Result[2][0] = T(2) * (qxz + qwy); + Result[2][1] = T(2) * (qyz - qwx); + Result[2][2] = T(1) - T(2) * (qxx + qyy); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> mat4_cast(qua const& q) + { + return mat<4, 4, T, Q>(mat3_cast(q)); + } + + template + GLM_FUNC_QUALIFIER qua quat_cast(mat<3, 3, T, Q> const& m) + { + T fourXSquaredMinus1 = m[0][0] - m[1][1] - m[2][2]; + T fourYSquaredMinus1 = m[1][1] - m[0][0] - m[2][2]; + T fourZSquaredMinus1 = m[2][2] - m[0][0] - m[1][1]; + T fourWSquaredMinus1 = m[0][0] + m[1][1] + m[2][2]; + + int biggestIndex = 0; + T fourBiggestSquaredMinus1 = fourWSquaredMinus1; + if(fourXSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourXSquaredMinus1; + biggestIndex = 1; + } + if(fourYSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourYSquaredMinus1; + biggestIndex = 2; + } + if(fourZSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourZSquaredMinus1; + biggestIndex = 3; + } + + T biggestVal = sqrt(fourBiggestSquaredMinus1 + static_cast(1)) * static_cast(0.5); + T mult = static_cast(0.25) / biggestVal; + + switch(biggestIndex) + { + case 0: + return qua::wxyz(biggestVal, (m[1][2] - m[2][1]) * mult, (m[2][0] - m[0][2]) * mult, (m[0][1] - m[1][0]) * mult); + case 1: + return qua::wxyz((m[1][2] - m[2][1]) * mult, biggestVal, (m[0][1] + m[1][0]) * mult, (m[2][0] + m[0][2]) * mult); + case 2: + return qua::wxyz((m[2][0] - m[0][2]) * mult, (m[0][1] + m[1][0]) * mult, biggestVal, (m[1][2] + m[2][1]) * mult); + case 3: + return qua::wxyz((m[0][1] - m[1][0]) * mult, (m[2][0] + m[0][2]) * mult, (m[1][2] + m[2][1]) * mult, biggestVal); + default: // Silence a -Wswitch-default warning in GCC. Should never actually get here. Assert is just for sanity. + assert(false); + return qua::wxyz(1, 0, 0, 0); + } + } + + template + GLM_FUNC_QUALIFIER qua quat_cast(mat<4, 4, T, Q> const& m4) + { + return quat_cast(mat<3, 3, T, Q>(m4)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> lessThan(qua const& x, qua const& y) + { + vec<4, bool, Q> Result(false, false, false, false); + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] < y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> lessThanEqual(qua const& x, qua const& y) + { + vec<4, bool, Q> Result(false, false, false, false); + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] <= y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> greaterThan(qua const& x, qua const& y) + { + vec<4, bool, Q> Result(false, false, false, false); + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] > y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> greaterThanEqual(qua const& x, qua const& y) + { + vec<4, bool, Q> Result(false, false, false, false); + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] >= y[i]; + return Result; + } + + + template + GLM_FUNC_QUALIFIER qua quatLookAt(vec<3, T, Q> const& direction, vec<3, T, Q> const& up) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return quatLookAtLH(direction, up); +# else + return quatLookAtRH(direction, up); +# endif + } + + template + GLM_FUNC_QUALIFIER qua quatLookAtRH(vec<3, T, Q> const& direction, vec<3, T, Q> const& up) + { + mat<3, 3, T, Q> Result; + + Result[2] = -direction; + vec<3, T, Q> const& Right = cross(up, Result[2]); + Result[0] = Right * inversesqrt(max(static_cast(0.00001), dot(Right, Right))); + Result[1] = cross(Result[2], Result[0]); + + return quat_cast(Result); + } + + template + GLM_FUNC_QUALIFIER qua quatLookAtLH(vec<3, T, Q> const& direction, vec<3, T, Q> const& up) + { + mat<3, 3, T, Q> Result; + + Result[2] = direction; + vec<3, T, Q> const& Right = cross(up, Result[2]); + Result[0] = Right * inversesqrt(max(static_cast(0.00001), dot(Right, Right))); + Result[1] = cross(Result[2], Result[0]); + + return quat_cast(Result); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "quaternion_simd.inl" +#endif + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/quaternion_simd.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/quaternion_simd.inl new file mode 100644 index 0000000..e69de29 diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/random.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/random.hpp new file mode 100644 index 0000000..c6485bf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/random.hpp @@ -0,0 +1,82 @@ +/// @ref gtc_random +/// @file glm/gtc/random.hpp +/// +/// @see core (dependence) +/// @see gtx_random (extended) +/// +/// @defgroup gtc_random GLM_GTC_random +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Generate random number from various distribution methods. + +#pragma once + +// Dependency: +#include "../ext/scalar_int_sized.hpp" +#include "../ext/scalar_uint_sized.hpp" +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_random extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_random + /// @{ + + /// Generate random numbers in the interval [Min, Max], according a linear distribution + /// + /// @param Min Minimum value included in the sampling + /// @param Max Maximum value included in the sampling + /// @tparam genType Value type. Currently supported: float or double scalars. + /// @see gtc_random + template + GLM_FUNC_DECL genType linearRand(genType Min, genType Max); + + /// Generate random numbers in the interval [Min, Max], according a linear distribution + /// + /// @param Min Minimum value included in the sampling + /// @param Max Maximum value included in the sampling + /// @tparam T Value type. Currently supported: float or double. + /// + /// @see gtc_random + template + GLM_FUNC_DECL vec linearRand(vec const& Min, vec const& Max); + + /// Generate random numbers in the interval [Min, Max], according a gaussian distribution + /// + /// @see gtc_random + template + GLM_FUNC_DECL genType gaussRand(genType Mean, genType Deviation); + + /// Generate a random 2D vector which coordinates are regularly distributed on a circle of a given radius + /// + /// @see gtc_random + template + GLM_FUNC_DECL vec<2, T, defaultp> circularRand(T Radius); + + /// Generate a random 3D vector which coordinates are regularly distributed on a sphere of a given radius + /// + /// @see gtc_random + template + GLM_FUNC_DECL vec<3, T, defaultp> sphericalRand(T Radius); + + /// Generate a random 2D vector which coordinates are regularly distributed within the area of a disk of a given radius + /// + /// @see gtc_random + template + GLM_FUNC_DECL vec<2, T, defaultp> diskRand(T Radius); + + /// Generate a random 3D vector which coordinates are regularly distributed within the volume of a ball of a given radius + /// + /// @see gtc_random + template + GLM_FUNC_DECL vec<3, T, defaultp> ballRand(T Radius); + + /// @} +}//namespace glm + +#include "random.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/random.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/random.inl new file mode 100644 index 0000000..249ec9f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/random.inl @@ -0,0 +1,303 @@ +#include "../geometric.hpp" +#include "../exponential.hpp" +#include "../trigonometric.hpp" +#include "../detail/type_vec1.hpp" +#include +#include +#include +#include + +namespace glm{ +namespace detail +{ + template + struct compute_rand + { + GLM_FUNC_QUALIFIER static vec call(); + }; + + template + struct compute_rand<1, uint8, P> + { + GLM_FUNC_QUALIFIER static vec<1, uint8, P> call() + { + return vec<1, uint8, P>( + static_cast(std::rand() % std::numeric_limits::max())); + } + }; + + template + struct compute_rand<2, uint8, P> + { + GLM_FUNC_QUALIFIER static vec<2, uint8, P> call() + { + return vec<2, uint8, P>( + std::rand() % std::numeric_limits::max(), + std::rand() % std::numeric_limits::max()); + } + }; + + template + struct compute_rand<3, uint8, P> + { + GLM_FUNC_QUALIFIER static vec<3, uint8, P> call() + { + return vec<3, uint8, P>( + std::rand() % std::numeric_limits::max(), + std::rand() % std::numeric_limits::max(), + std::rand() % std::numeric_limits::max()); + } + }; + + template + struct compute_rand<4, uint8, P> + { + GLM_FUNC_QUALIFIER static vec<4, uint8, P> call() + { + return vec<4, uint8, P>( + std::rand() % std::numeric_limits::max(), + std::rand() % std::numeric_limits::max(), + std::rand() % std::numeric_limits::max(), + std::rand() % std::numeric_limits::max()); + } + }; + + template + struct compute_rand + { + GLM_FUNC_QUALIFIER static vec call() + { + return + (vec(compute_rand::call()) << static_cast(8)) | + (vec(compute_rand::call()) << static_cast(0)); + } + }; + + template + struct compute_rand + { + GLM_FUNC_QUALIFIER static vec call() + { + return + (vec(compute_rand::call()) << static_cast(16)) | + (vec(compute_rand::call()) << static_cast(0)); + } + }; + + template + struct compute_rand + { + GLM_FUNC_QUALIFIER static vec call() + { + return + (vec(compute_rand::call()) << static_cast(32)) | + (vec(compute_rand::call()) << static_cast(0)); + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max); + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (vec(compute_rand::call() % vec(Max + static_cast(1) - Min))) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (compute_rand::call() % (Max + static_cast(1) - Min)) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (vec(compute_rand::call() % vec(Max + static_cast(1) - Min))) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (compute_rand::call() % (Max + static_cast(1) - Min)) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (vec(compute_rand::call() % vec(Max + static_cast(1) - Min))) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (compute_rand::call() % (Max + static_cast(1) - Min)) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (vec(compute_rand::call() % vec(Max + static_cast(1) - Min))) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (compute_rand::call() % (Max + static_cast(1) - Min)) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return vec(compute_rand::call()) / static_cast(std::numeric_limits::max()) * (Max - Min) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return vec(compute_rand::call()) / static_cast(std::numeric_limits::max()) * (Max - Min) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return vec(compute_rand::call()) / static_cast(std::numeric_limits::max()) * (Max - Min) + Min; + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER genType linearRand(genType Min, genType Max) + { + return detail::compute_linearRand<1, genType, highp>::call( + vec<1, genType, highp>(Min), + vec<1, genType, highp>(Max)).x; + } + + template + GLM_FUNC_QUALIFIER vec linearRand(vec const& Min, vec const& Max) + { + return detail::compute_linearRand::call(Min, Max); + } + + template + GLM_FUNC_QUALIFIER genType gaussRand(genType Mean, genType Deviation) + { + genType w, x1, x2; + + do + { + x1 = linearRand(genType(-1), genType(1)); + x2 = linearRand(genType(-1), genType(1)); + + w = x1 * x1 + x2 * x2; + } while(w > genType(1)); + + return static_cast(x2 * Deviation * Deviation * sqrt((genType(-2) * log(w)) / w) + Mean); + } + + template + GLM_FUNC_QUALIFIER vec gaussRand(vec const& Mean, vec const& Deviation) + { + return detail::functor2::call(gaussRand, Mean, Deviation); + } + + template + GLM_FUNC_QUALIFIER vec<2, T, defaultp> diskRand(T Radius) + { + assert(Radius > static_cast(0)); + + vec<2, T, defaultp> Result(T(0)); + T LenRadius(T(0)); + + do + { + Result = linearRand( + vec<2, T, defaultp>(-Radius), + vec<2, T, defaultp>(Radius)); + LenRadius = length(Result); + } + while(LenRadius > Radius); + + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, defaultp> ballRand(T Radius) + { + assert(Radius > static_cast(0)); + + vec<3, T, defaultp> Result(T(0)); + T LenRadius(T(0)); + + do + { + Result = linearRand( + vec<3, T, defaultp>(-Radius), + vec<3, T, defaultp>(Radius)); + LenRadius = length(Result); + } + while(LenRadius > Radius); + + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, defaultp> circularRand(T Radius) + { + assert(Radius > static_cast(0)); + + T a = linearRand(T(0), static_cast(6.283185307179586476925286766559)); + return vec<2, T, defaultp>(glm::cos(a), glm::sin(a)) * Radius; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, defaultp> sphericalRand(T Radius) + { + assert(Radius > static_cast(0)); + + T theta = linearRand(T(0), T(6.283185307179586476925286766559f)); + T phi = std::acos(linearRand(T(-1.0f), T(1.0f))); + + T x = std::sin(phi) * std::cos(theta); + T y = std::sin(phi) * std::sin(theta); + T z = std::cos(phi); + + return vec<3, T, defaultp>(x, y, z) * Radius; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/reciprocal.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/reciprocal.hpp new file mode 100644 index 0000000..4d0fc91 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/reciprocal.hpp @@ -0,0 +1,24 @@ +/// @ref gtc_reciprocal +/// @file glm/gtc/reciprocal.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_reciprocal GLM_GTC_reciprocal +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Define secant, cosecant and cotangent functions. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_reciprocal extension included") +#endif + +#include "../ext/scalar_reciprocal.hpp" +#include "../ext/vector_reciprocal.hpp" + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/round.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/round.hpp new file mode 100644 index 0000000..56edbbc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/round.hpp @@ -0,0 +1,160 @@ +/// @ref gtc_round +/// @file glm/gtc/round.hpp +/// +/// @see core (dependence) +/// @see gtc_round (dependence) +/// +/// @defgroup gtc_round GLM_GTC_round +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Rounding value to specific boundings + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/_vectorize.hpp" +#include "../vector_relational.hpp" +#include "../common.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_round extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_round + /// @{ + + /// Return the power of two number which value is just higher the input value, + /// round up to a power of two. + /// + /// @see gtc_round + template + GLM_FUNC_DECL genIUType ceilPowerOfTwo(genIUType v); + + /// Return the power of two number which value is just higher the input value, + /// round up to a power of two. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_round + template + GLM_FUNC_DECL vec ceilPowerOfTwo(vec const& v); + + /// Return the power of two number which value is just lower the input value, + /// round down to a power of two. + /// + /// @see gtc_round + template + GLM_FUNC_DECL genIUType floorPowerOfTwo(genIUType v); + + /// Return the power of two number which value is just lower the input value, + /// round down to a power of two. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_round + template + GLM_FUNC_DECL vec floorPowerOfTwo(vec const& v); + + /// Return the power of two number which value is the closet to the input value. + /// + /// @see gtc_round + template + GLM_FUNC_DECL genIUType roundPowerOfTwo(genIUType v); + + /// Return the power of two number which value is the closet to the input value. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_round + template + GLM_FUNC_DECL vec roundPowerOfTwo(vec const& v); + + /// Higher multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// + /// @param v Source value to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template + GLM_FUNC_DECL genType ceilMultiple(genType v, genType Multiple); + + /// Higher multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template + GLM_FUNC_DECL vec ceilMultiple(vec const& v, vec const& Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// + /// @param v Source value to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template + GLM_FUNC_DECL genType floorMultiple(genType v, genType Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template + GLM_FUNC_DECL vec floorMultiple(vec const& v, vec const& Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// + /// @param v Source value to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template + GLM_FUNC_DECL genType roundMultiple(genType v, genType Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template + GLM_FUNC_DECL vec roundMultiple(vec const& v, vec const& Multiple); + + /// @} +} //namespace glm + +#include "round.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/round.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/round.inl new file mode 100644 index 0000000..48411e4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/round.inl @@ -0,0 +1,155 @@ +/// @ref gtc_round + +#include "../integer.hpp" +#include "../ext/vector_integer.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_roundMultiple {}; + + template<> + struct compute_roundMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if (Source >= genType(0)) + return Source - std::fmod(Source, Multiple); + else + { + genType Tmp = Source + genType(1); + return Tmp - std::fmod(Tmp, Multiple) - Multiple; + } + } + }; + + template<> + struct compute_roundMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if (Source >= genType(0)) + return Source - Source % Multiple; + else + { + genType Tmp = Source + genType(1); + return Tmp - Tmp % Multiple - Multiple; + } + } + }; + + template<> + struct compute_roundMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if (Source >= genType(0)) + return Source - Source % Multiple; + else + { + genType Tmp = Source + genType(1); + return Tmp - Tmp % Multiple - Multiple; + } + } + }; +}//namespace detail + + ////////////////// + // ceilPowerOfTwo + + template + GLM_FUNC_QUALIFIER genType ceilPowerOfTwo(genType value) + { + return detail::compute_ceilPowerOfTwo<1, genType, defaultp, std::numeric_limits::is_signed>::call(vec<1, genType, defaultp>(value)).x; + } + + template + GLM_FUNC_QUALIFIER vec ceilPowerOfTwo(vec const& v) + { + return detail::compute_ceilPowerOfTwo::is_signed>::call(v); + } + + /////////////////// + // floorPowerOfTwo + + template + GLM_FUNC_QUALIFIER genType floorPowerOfTwo(genType value) + { + return isPowerOfTwo(value) ? value : static_cast(1) << findMSB(value); + } + + template + GLM_FUNC_QUALIFIER vec floorPowerOfTwo(vec const& v) + { + return detail::functor1::call(floorPowerOfTwo, v); + } + + /////////////////// + // roundPowerOfTwo + + template + GLM_FUNC_QUALIFIER genIUType roundPowerOfTwo(genIUType value) + { + if(isPowerOfTwo(value)) + return value; + + genIUType const prev = static_cast(1) << findMSB(value); + genIUType const next = prev << static_cast(1); + return (next - value) < (value - prev) ? next : prev; + } + + template + GLM_FUNC_QUALIFIER vec roundPowerOfTwo(vec const& v) + { + return detail::functor1::call(roundPowerOfTwo, v); + } + + ////////////////////// + // ceilMultiple + + template + GLM_FUNC_QUALIFIER genType ceilMultiple(genType Source, genType Multiple) + { + return detail::compute_ceilMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec ceilMultiple(vec const& Source, vec const& Multiple) + { + return detail::functor2::call(ceilMultiple, Source, Multiple); + } + + ////////////////////// + // floorMultiple + + template + GLM_FUNC_QUALIFIER genType floorMultiple(genType Source, genType Multiple) + { + return detail::compute_floorMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec floorMultiple(vec const& Source, vec const& Multiple) + { + return detail::functor2::call(floorMultiple, Source, Multiple); + } + + ////////////////////// + // roundMultiple + + template + GLM_FUNC_QUALIFIER genType roundMultiple(genType Source, genType Multiple) + { + return detail::compute_roundMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec roundMultiple(vec const& Source, vec const& Multiple) + { + return detail::functor2::call(roundMultiple, Source, Multiple); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_aligned.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_aligned.hpp new file mode 100644 index 0000000..5403abf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_aligned.hpp @@ -0,0 +1,1315 @@ +/// @ref gtc_type_aligned +/// @file glm/gtc/type_aligned.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_type_aligned GLM_GTC_type_aligned +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Aligned types allowing SIMD optimizations of vectors and matrices types + +#pragma once + +#if (GLM_CONFIG_ALIGNED_GENTYPES == GLM_DISABLE) +# error "GLM: Aligned gentypes require to enable C++ language extensions. Define GLM_FORCE_ALIGNED_GENTYPES before including GLM headers to use aligned types." +#endif + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_type_aligned extension included") +#endif + +#include "../mat4x4.hpp" +#include "../mat4x3.hpp" +#include "../mat4x2.hpp" +#include "../mat3x4.hpp" +#include "../mat3x3.hpp" +#include "../mat3x2.hpp" +#include "../mat2x4.hpp" +#include "../mat2x3.hpp" +#include "../mat2x2.hpp" +#include "../gtc/vec1.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" + +namespace glm +{ + /// @addtogroup gtc_type_aligned + /// @{ + + // -- *vec1 -- + + /// 1 component vector aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<1, float, aligned_highp> aligned_highp_vec1; + + /// 1 component vector aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<1, float, aligned_mediump> aligned_mediump_vec1; + + /// 1 component vector aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<1, float, aligned_lowp> aligned_lowp_vec1; + + /// 1 component vector aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<1, double, aligned_highp> aligned_highp_dvec1; + + /// 1 component vector aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<1, double, aligned_mediump> aligned_mediump_dvec1; + + /// 1 component vector aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<1, double, aligned_lowp> aligned_lowp_dvec1; + + /// 1 component vector aligned in memory of signed integer numbers. + typedef vec<1, int, aligned_highp> aligned_highp_ivec1; + + /// 1 component vector aligned in memory of signed integer numbers. + typedef vec<1, int, aligned_mediump> aligned_mediump_ivec1; + + /// 1 component vector aligned in memory of signed integer numbers. + typedef vec<1, int, aligned_lowp> aligned_lowp_ivec1; + + /// 1 component vector aligned in memory of unsigned integer numbers. + typedef vec<1, uint, aligned_highp> aligned_highp_uvec1; + + /// 1 component vector aligned in memory of unsigned integer numbers. + typedef vec<1, uint, aligned_mediump> aligned_mediump_uvec1; + + /// 1 component vector aligned in memory of unsigned integer numbers. + typedef vec<1, uint, aligned_lowp> aligned_lowp_uvec1; + + /// 1 component vector aligned in memory of bool values. + typedef vec<1, bool, aligned_highp> aligned_highp_bvec1; + + /// 1 component vector aligned in memory of bool values. + typedef vec<1, bool, aligned_mediump> aligned_mediump_bvec1; + + /// 1 component vector aligned in memory of bool values. + typedef vec<1, bool, aligned_lowp> aligned_lowp_bvec1; + + /// 1 component vector tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<1, float, packed_highp> packed_highp_vec1; + + /// 1 component vector tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<1, float, packed_mediump> packed_mediump_vec1; + + /// 1 component vector tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<1, float, packed_lowp> packed_lowp_vec1; + + /// 1 component vector tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<1, double, packed_highp> packed_highp_dvec1; + + /// 1 component vector tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<1, double, packed_mediump> packed_mediump_dvec1; + + /// 1 component vector tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<1, double, packed_lowp> packed_lowp_dvec1; + + /// 1 component vector tightly packed in memory of signed integer numbers. + typedef vec<1, int, packed_highp> packed_highp_ivec1; + + /// 1 component vector tightly packed in memory of signed integer numbers. + typedef vec<1, int, packed_mediump> packed_mediump_ivec1; + + /// 1 component vector tightly packed in memory of signed integer numbers. + typedef vec<1, int, packed_lowp> packed_lowp_ivec1; + + /// 1 component vector tightly packed in memory of unsigned integer numbers. + typedef vec<1, uint, packed_highp> packed_highp_uvec1; + + /// 1 component vector tightly packed in memory of unsigned integer numbers. + typedef vec<1, uint, packed_mediump> packed_mediump_uvec1; + + /// 1 component vector tightly packed in memory of unsigned integer numbers. + typedef vec<1, uint, packed_lowp> packed_lowp_uvec1; + + /// 1 component vector tightly packed in memory of bool values. + typedef vec<1, bool, packed_highp> packed_highp_bvec1; + + /// 1 component vector tightly packed in memory of bool values. + typedef vec<1, bool, packed_mediump> packed_mediump_bvec1; + + /// 1 component vector tightly packed in memory of bool values. + typedef vec<1, bool, packed_lowp> packed_lowp_bvec1; + + // -- *vec2 -- + + /// 2 components vector aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<2, float, aligned_highp> aligned_highp_vec2; + + /// 2 components vector aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<2, float, aligned_mediump> aligned_mediump_vec2; + + /// 2 components vector aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<2, float, aligned_lowp> aligned_lowp_vec2; + + /// 2 components vector aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<2, double, aligned_highp> aligned_highp_dvec2; + + /// 2 components vector aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<2, double, aligned_mediump> aligned_mediump_dvec2; + + /// 2 components vector aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<2, double, aligned_lowp> aligned_lowp_dvec2; + + /// 2 components vector aligned in memory of signed integer numbers. + typedef vec<2, int, aligned_highp> aligned_highp_ivec2; + + /// 2 components vector aligned in memory of signed integer numbers. + typedef vec<2, int, aligned_mediump> aligned_mediump_ivec2; + + /// 2 components vector aligned in memory of signed integer numbers. + typedef vec<2, int, aligned_lowp> aligned_lowp_ivec2; + + /// 2 components vector aligned in memory of unsigned integer numbers. + typedef vec<2, uint, aligned_highp> aligned_highp_uvec2; + + /// 2 components vector aligned in memory of unsigned integer numbers. + typedef vec<2, uint, aligned_mediump> aligned_mediump_uvec2; + + /// 2 components vector aligned in memory of unsigned integer numbers. + typedef vec<2, uint, aligned_lowp> aligned_lowp_uvec2; + + /// 2 components vector aligned in memory of bool values. + typedef vec<2, bool, aligned_highp> aligned_highp_bvec2; + + /// 2 components vector aligned in memory of bool values. + typedef vec<2, bool, aligned_mediump> aligned_mediump_bvec2; + + /// 2 components vector aligned in memory of bool values. + typedef vec<2, bool, aligned_lowp> aligned_lowp_bvec2; + + /// 2 components vector tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<2, float, packed_highp> packed_highp_vec2; + + /// 2 components vector tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<2, float, packed_mediump> packed_mediump_vec2; + + /// 2 components vector tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<2, float, packed_lowp> packed_lowp_vec2; + + /// 2 components vector tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<2, double, packed_highp> packed_highp_dvec2; + + /// 2 components vector tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<2, double, packed_mediump> packed_mediump_dvec2; + + /// 2 components vector tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<2, double, packed_lowp> packed_lowp_dvec2; + + /// 2 components vector tightly packed in memory of signed integer numbers. + typedef vec<2, int, packed_highp> packed_highp_ivec2; + + /// 2 components vector tightly packed in memory of signed integer numbers. + typedef vec<2, int, packed_mediump> packed_mediump_ivec2; + + /// 2 components vector tightly packed in memory of signed integer numbers. + typedef vec<2, int, packed_lowp> packed_lowp_ivec2; + + /// 2 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<2, uint, packed_highp> packed_highp_uvec2; + + /// 2 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<2, uint, packed_mediump> packed_mediump_uvec2; + + /// 2 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<2, uint, packed_lowp> packed_lowp_uvec2; + + /// 2 components vector tightly packed in memory of bool values. + typedef vec<2, bool, packed_highp> packed_highp_bvec2; + + /// 2 components vector tightly packed in memory of bool values. + typedef vec<2, bool, packed_mediump> packed_mediump_bvec2; + + /// 2 components vector tightly packed in memory of bool values. + typedef vec<2, bool, packed_lowp> packed_lowp_bvec2; + + // -- *vec3 -- + + /// 3 components vector aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<3, float, aligned_highp> aligned_highp_vec3; + + /// 3 components vector aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<3, float, aligned_mediump> aligned_mediump_vec3; + + /// 3 components vector aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<3, float, aligned_lowp> aligned_lowp_vec3; + + /// 3 components vector aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<3, double, aligned_highp> aligned_highp_dvec3; + + /// 3 components vector aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<3, double, aligned_mediump> aligned_mediump_dvec3; + + /// 3 components vector aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<3, double, aligned_lowp> aligned_lowp_dvec3; + + /// 3 components vector aligned in memory of signed integer numbers. + typedef vec<3, int, aligned_highp> aligned_highp_ivec3; + + /// 3 components vector aligned in memory of signed integer numbers. + typedef vec<3, int, aligned_mediump> aligned_mediump_ivec3; + + /// 3 components vector aligned in memory of signed integer numbers. + typedef vec<3, int, aligned_lowp> aligned_lowp_ivec3; + + /// 3 components vector aligned in memory of unsigned integer numbers. + typedef vec<3, uint, aligned_highp> aligned_highp_uvec3; + + /// 3 components vector aligned in memory of unsigned integer numbers. + typedef vec<3, uint, aligned_mediump> aligned_mediump_uvec3; + + /// 3 components vector aligned in memory of unsigned integer numbers. + typedef vec<3, uint, aligned_lowp> aligned_lowp_uvec3; + + /// 3 components vector aligned in memory of bool values. + typedef vec<3, bool, aligned_highp> aligned_highp_bvec3; + + /// 3 components vector aligned in memory of bool values. + typedef vec<3, bool, aligned_mediump> aligned_mediump_bvec3; + + /// 3 components vector aligned in memory of bool values. + typedef vec<3, bool, aligned_lowp> aligned_lowp_bvec3; + + /// 3 components vector tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<3, float, packed_highp> packed_highp_vec3; + + /// 3 components vector tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<3, float, packed_mediump> packed_mediump_vec3; + + /// 3 components vector tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<3, float, packed_lowp> packed_lowp_vec3; + + /// 3 components vector tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<3, double, packed_highp> packed_highp_dvec3; + + /// 3 components vector tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<3, double, packed_mediump> packed_mediump_dvec3; + + /// 3 components vector tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<3, double, packed_lowp> packed_lowp_dvec3; + + /// 3 components vector tightly packed in memory of signed integer numbers. + typedef vec<3, int, packed_highp> packed_highp_ivec3; + + /// 3 components vector tightly packed in memory of signed integer numbers. + typedef vec<3, int, packed_mediump> packed_mediump_ivec3; + + /// 3 components vector tightly packed in memory of signed integer numbers. + typedef vec<3, int, packed_lowp> packed_lowp_ivec3; + + /// 3 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<3, uint, packed_highp> packed_highp_uvec3; + + /// 3 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<3, uint, packed_mediump> packed_mediump_uvec3; + + /// 3 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<3, uint, packed_lowp> packed_lowp_uvec3; + + /// 3 components vector tightly packed in memory of bool values. + typedef vec<3, bool, packed_highp> packed_highp_bvec3; + + /// 3 components vector tightly packed in memory of bool values. + typedef vec<3, bool, packed_mediump> packed_mediump_bvec3; + + /// 3 components vector tightly packed in memory of bool values. + typedef vec<3, bool, packed_lowp> packed_lowp_bvec3; + + // -- *vec4 -- + + /// 4 components vector aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<4, float, aligned_highp> aligned_highp_vec4; + + /// 4 components vector aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<4, float, aligned_mediump> aligned_mediump_vec4; + + /// 4 components vector aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<4, float, aligned_lowp> aligned_lowp_vec4; + + /// 4 components vector aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<4, double, aligned_highp> aligned_highp_dvec4; + + /// 4 components vector aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<4, double, aligned_mediump> aligned_mediump_dvec4; + + /// 4 components vector aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<4, double, aligned_lowp> aligned_lowp_dvec4; + + /// 4 components vector aligned in memory of signed integer numbers. + typedef vec<4, int, aligned_highp> aligned_highp_ivec4; + + /// 4 components vector aligned in memory of signed integer numbers. + typedef vec<4, int, aligned_mediump> aligned_mediump_ivec4; + + /// 4 components vector aligned in memory of signed integer numbers. + typedef vec<4, int, aligned_lowp> aligned_lowp_ivec4; + + /// 4 components vector aligned in memory of unsigned integer numbers. + typedef vec<4, uint, aligned_highp> aligned_highp_uvec4; + + /// 4 components vector aligned in memory of unsigned integer numbers. + typedef vec<4, uint, aligned_mediump> aligned_mediump_uvec4; + + /// 4 components vector aligned in memory of unsigned integer numbers. + typedef vec<4, uint, aligned_lowp> aligned_lowp_uvec4; + + /// 4 components vector aligned in memory of bool values. + typedef vec<4, bool, aligned_highp> aligned_highp_bvec4; + + /// 4 components vector aligned in memory of bool values. + typedef vec<4, bool, aligned_mediump> aligned_mediump_bvec4; + + /// 4 components vector aligned in memory of bool values. + typedef vec<4, bool, aligned_lowp> aligned_lowp_bvec4; + + /// 4 components vector tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<4, float, packed_highp> packed_highp_vec4; + + /// 4 components vector tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<4, float, packed_mediump> packed_mediump_vec4; + + /// 4 components vector tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<4, float, packed_lowp> packed_lowp_vec4; + + /// 4 components vector tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<4, double, packed_highp> packed_highp_dvec4; + + /// 4 components vector tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<4, double, packed_mediump> packed_mediump_dvec4; + + /// 4 components vector tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<4, double, packed_lowp> packed_lowp_dvec4; + + /// 4 components vector tightly packed in memory of signed integer numbers. + typedef vec<4, int, packed_highp> packed_highp_ivec4; + + /// 4 components vector tightly packed in memory of signed integer numbers. + typedef vec<4, int, packed_mediump> packed_mediump_ivec4; + + /// 4 components vector tightly packed in memory of signed integer numbers. + typedef vec<4, int, packed_lowp> packed_lowp_ivec4; + + /// 4 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<4, uint, packed_highp> packed_highp_uvec4; + + /// 4 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<4, uint, packed_mediump> packed_mediump_uvec4; + + /// 4 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<4, uint, packed_lowp> packed_lowp_uvec4; + + /// 4 components vector tightly packed in memory of bool values. + typedef vec<4, bool, packed_highp> packed_highp_bvec4; + + /// 4 components vector tightly packed in memory of bool values. + typedef vec<4, bool, packed_mediump> packed_mediump_bvec4; + + /// 4 components vector tightly packed in memory of bool values. + typedef vec<4, bool, packed_lowp> packed_lowp_bvec4; + + // -- *mat2 -- + + /// 2 by 2 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, float, aligned_highp> aligned_highp_mat2; + + /// 2 by 2 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, float, aligned_mediump> aligned_mediump_mat2; + + /// 2 by 2 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, float, aligned_lowp> aligned_lowp_mat2; + + /// 2 by 2 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, double, aligned_highp> aligned_highp_dmat2; + + /// 2 by 2 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, double, aligned_mediump> aligned_mediump_dmat2; + + /// 2 by 2 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, double, aligned_lowp> aligned_lowp_dmat2; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, float, packed_highp> packed_highp_mat2; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, float, packed_mediump> packed_mediump_mat2; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, float, packed_lowp> packed_lowp_mat2; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, double, packed_highp> packed_highp_dmat2; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, double, packed_mediump> packed_mediump_dmat2; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, double, packed_lowp> packed_lowp_dmat2; + + // -- *mat3 -- + + /// 3 by 3 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, float, aligned_highp> aligned_highp_mat3; + + /// 3 by 3 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, float, aligned_mediump> aligned_mediump_mat3; + + /// 3 by 3 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, float, aligned_lowp> aligned_lowp_mat3; + + /// 3 by 3 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, double, aligned_highp> aligned_highp_dmat3; + + /// 3 by 3 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, double, aligned_mediump> aligned_mediump_dmat3; + + /// 3 by 3 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, double, aligned_lowp> aligned_lowp_dmat3; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, float, packed_highp> packed_highp_mat3; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, float, packed_mediump> packed_mediump_mat3; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, float, packed_lowp> packed_lowp_mat3; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, double, packed_highp> packed_highp_dmat3; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, double, packed_mediump> packed_mediump_dmat3; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, double, packed_lowp> packed_lowp_dmat3; + + // -- *mat4 -- + + /// 4 by 4 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, float, aligned_highp> aligned_highp_mat4; + + /// 4 by 4 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, float, aligned_mediump> aligned_mediump_mat4; + + /// 4 by 4 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, float, aligned_lowp> aligned_lowp_mat4; + + /// 4 by 4 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, double, aligned_highp> aligned_highp_dmat4; + + /// 4 by 4 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, double, aligned_mediump> aligned_mediump_dmat4; + + /// 4 by 4 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, double, aligned_lowp> aligned_lowp_dmat4; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, float, packed_highp> packed_highp_mat4; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, float, packed_mediump> packed_mediump_mat4; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, float, packed_lowp> packed_lowp_mat4; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, double, packed_highp> packed_highp_dmat4; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, double, packed_mediump> packed_mediump_dmat4; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, double, packed_lowp> packed_lowp_dmat4; + + // -- *mat2x2 -- + + /// 2 by 2 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, float, aligned_highp> aligned_highp_mat2x2; + + /// 2 by 2 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, float, aligned_mediump> aligned_mediump_mat2x2; + + /// 2 by 2 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, float, aligned_lowp> aligned_lowp_mat2x2; + + /// 2 by 2 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, double, aligned_highp> aligned_highp_dmat2x2; + + /// 2 by 2 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, double, aligned_mediump> aligned_mediump_dmat2x2; + + /// 2 by 2 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, double, aligned_lowp> aligned_lowp_dmat2x2; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, float, packed_highp> packed_highp_mat2x2; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, float, packed_mediump> packed_mediump_mat2x2; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, float, packed_lowp> packed_lowp_mat2x2; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, double, packed_highp> packed_highp_dmat2x2; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, double, packed_mediump> packed_mediump_dmat2x2; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, double, packed_lowp> packed_lowp_dmat2x2; + + // -- *mat2x3 -- + + /// 2 by 3 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 3, float, aligned_highp> aligned_highp_mat2x3; + + /// 2 by 3 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 3, float, aligned_mediump> aligned_mediump_mat2x3; + + /// 2 by 3 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 3, float, aligned_lowp> aligned_lowp_mat2x3; + + /// 2 by 3 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 3, double, aligned_highp> aligned_highp_dmat2x3; + + /// 2 by 3 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 3, double, aligned_mediump> aligned_mediump_dmat2x3; + + /// 2 by 3 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 3, double, aligned_lowp> aligned_lowp_dmat2x3; + + /// 2 by 3 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 3, float, packed_highp> packed_highp_mat2x3; + + /// 2 by 3 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 3, float, packed_mediump> packed_mediump_mat2x3; + + /// 2 by 3 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 3, float, packed_lowp> packed_lowp_mat2x3; + + /// 2 by 3 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 3, double, packed_highp> packed_highp_dmat2x3; + + /// 2 by 3 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 3, double, packed_mediump> packed_mediump_dmat2x3; + + /// 2 by 3 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 3, double, packed_lowp> packed_lowp_dmat2x3; + + // -- *mat2x4 -- + + /// 2 by 4 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 4, float, aligned_highp> aligned_highp_mat2x4; + + /// 2 by 4 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 4, float, aligned_mediump> aligned_mediump_mat2x4; + + /// 2 by 4 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 4, float, aligned_lowp> aligned_lowp_mat2x4; + + /// 2 by 4 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 4, double, aligned_highp> aligned_highp_dmat2x4; + + /// 2 by 4 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 4, double, aligned_mediump> aligned_mediump_dmat2x4; + + /// 2 by 4 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 4, double, aligned_lowp> aligned_lowp_dmat2x4; + + /// 2 by 4 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 4, float, packed_highp> packed_highp_mat2x4; + + /// 2 by 4 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 4, float, packed_mediump> packed_mediump_mat2x4; + + /// 2 by 4 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 4, float, packed_lowp> packed_lowp_mat2x4; + + /// 2 by 4 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 4, double, packed_highp> packed_highp_dmat2x4; + + /// 2 by 4 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 4, double, packed_mediump> packed_mediump_dmat2x4; + + /// 2 by 4 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 4, double, packed_lowp> packed_lowp_dmat2x4; + + // -- *mat3x2 -- + + /// 3 by 2 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 2, float, aligned_highp> aligned_highp_mat3x2; + + /// 3 by 2 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 2, float, aligned_mediump> aligned_mediump_mat3x2; + + /// 3 by 2 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 2, float, aligned_lowp> aligned_lowp_mat3x2; + + /// 3 by 2 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 2, double, aligned_highp> aligned_highp_dmat3x2; + + /// 3 by 2 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 2, double, aligned_mediump> aligned_mediump_dmat3x2; + + /// 3 by 2 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 2, double, aligned_lowp> aligned_lowp_dmat3x2; + + /// 3 by 2 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 2, float, packed_highp> packed_highp_mat3x2; + + /// 3 by 2 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 2, float, packed_mediump> packed_mediump_mat3x2; + + /// 3 by 2 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 2, float, packed_lowp> packed_lowp_mat3x2; + + /// 3 by 2 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 2, double, packed_highp> packed_highp_dmat3x2; + + /// 3 by 2 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 2, double, packed_mediump> packed_mediump_dmat3x2; + + /// 3 by 2 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 2, double, packed_lowp> packed_lowp_dmat3x2; + + // -- *mat3x3 -- + + /// 3 by 3 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, float, aligned_highp> aligned_highp_mat3x3; + + /// 3 by 3 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, float, aligned_mediump> aligned_mediump_mat3x3; + + /// 3 by 3 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, float, aligned_lowp> aligned_lowp_mat3x3; + + /// 3 by 3 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, double, aligned_highp> aligned_highp_dmat3x3; + + /// 3 by 3 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, double, aligned_mediump> aligned_mediump_dmat3x3; + + /// 3 by 3 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, double, aligned_lowp> aligned_lowp_dmat3x3; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, float, packed_highp> packed_highp_mat3x3; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, float, packed_mediump> packed_mediump_mat3x3; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, float, packed_lowp> packed_lowp_mat3x3; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, double, packed_highp> packed_highp_dmat3x3; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, double, packed_mediump> packed_mediump_dmat3x3; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, double, packed_lowp> packed_lowp_dmat3x3; + + // -- *mat3x4 -- + + /// 3 by 4 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 4, float, aligned_highp> aligned_highp_mat3x4; + + /// 3 by 4 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 4, float, aligned_mediump> aligned_mediump_mat3x4; + + /// 3 by 4 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 4, float, aligned_lowp> aligned_lowp_mat3x4; + + /// 3 by 4 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 4, double, aligned_highp> aligned_highp_dmat3x4; + + /// 3 by 4 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 4, double, aligned_mediump> aligned_mediump_dmat3x4; + + /// 3 by 4 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 4, double, aligned_lowp> aligned_lowp_dmat3x4; + + /// 3 by 4 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 4, float, packed_highp> packed_highp_mat3x4; + + /// 3 by 4 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 4, float, packed_mediump> packed_mediump_mat3x4; + + /// 3 by 4 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 4, float, packed_lowp> packed_lowp_mat3x4; + + /// 3 by 4 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 4, double, packed_highp> packed_highp_dmat3x4; + + /// 3 by 4 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 4, double, packed_mediump> packed_mediump_dmat3x4; + + /// 3 by 4 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 4, double, packed_lowp> packed_lowp_dmat3x4; + + // -- *mat4x2 -- + + /// 4 by 2 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 2, float, aligned_highp> aligned_highp_mat4x2; + + /// 4 by 2 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 2, float, aligned_mediump> aligned_mediump_mat4x2; + + /// 4 by 2 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 2, float, aligned_lowp> aligned_lowp_mat4x2; + + /// 4 by 2 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 2, double, aligned_highp> aligned_highp_dmat4x2; + + /// 4 by 2 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 2, double, aligned_mediump> aligned_mediump_dmat4x2; + + /// 4 by 2 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 2, double, aligned_lowp> aligned_lowp_dmat4x2; + + /// 4 by 2 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 2, float, packed_highp> packed_highp_mat4x2; + + /// 4 by 2 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 2, float, packed_mediump> packed_mediump_mat4x2; + + /// 4 by 2 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 2, float, packed_lowp> packed_lowp_mat4x2; + + /// 4 by 2 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 2, double, packed_highp> packed_highp_dmat4x2; + + /// 4 by 2 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 2, double, packed_mediump> packed_mediump_dmat4x2; + + /// 4 by 2 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 2, double, packed_lowp> packed_lowp_dmat4x2; + + // -- *mat4x3 -- + + /// 4 by 3 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 3, float, aligned_highp> aligned_highp_mat4x3; + + /// 4 by 3 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 3, float, aligned_mediump> aligned_mediump_mat4x3; + + /// 4 by 3 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 3, float, aligned_lowp> aligned_lowp_mat4x3; + + /// 4 by 3 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 3, double, aligned_highp> aligned_highp_dmat4x3; + + /// 4 by 3 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 3, double, aligned_mediump> aligned_mediump_dmat4x3; + + /// 4 by 3 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 3, double, aligned_lowp> aligned_lowp_dmat4x3; + + /// 4 by 3 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 3, float, packed_highp> packed_highp_mat4x3; + + /// 4 by 3 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 3, float, packed_mediump> packed_mediump_mat4x3; + + /// 4 by 3 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 3, float, packed_lowp> packed_lowp_mat4x3; + + /// 4 by 3 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 3, double, packed_highp> packed_highp_dmat4x3; + + /// 4 by 3 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 3, double, packed_mediump> packed_mediump_dmat4x3; + + /// 4 by 3 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 3, double, packed_lowp> packed_lowp_dmat4x3; + + // -- *mat4x4 -- + + /// 4 by 4 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, float, aligned_highp> aligned_highp_mat4x4; + + /// 4 by 4 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, float, aligned_mediump> aligned_mediump_mat4x4; + + /// 4 by 4 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, float, aligned_lowp> aligned_lowp_mat4x4; + + /// 4 by 4 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, double, aligned_highp> aligned_highp_dmat4x4; + + /// 4 by 4 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, double, aligned_mediump> aligned_mediump_dmat4x4; + + /// 4 by 4 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, double, aligned_lowp> aligned_lowp_dmat4x4; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, float, packed_highp> packed_highp_mat4x4; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, float, packed_mediump> packed_mediump_mat4x4; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, float, packed_lowp> packed_lowp_mat4x4; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, double, packed_highp> packed_highp_dmat4x4; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, double, packed_mediump> packed_mediump_dmat4x4; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, double, packed_lowp> packed_lowp_dmat4x4; + + // -- default -- + +#if(defined(GLM_PRECISION_LOWP_FLOAT)) + typedef aligned_lowp_vec1 aligned_vec1; + typedef aligned_lowp_vec2 aligned_vec2; + typedef aligned_lowp_vec3 aligned_vec3; + typedef aligned_lowp_vec4 aligned_vec4; + typedef packed_lowp_vec1 packed_vec1; + typedef packed_lowp_vec2 packed_vec2; + typedef packed_lowp_vec3 packed_vec3; + typedef packed_lowp_vec4 packed_vec4; + + typedef aligned_lowp_mat2 aligned_mat2; + typedef aligned_lowp_mat3 aligned_mat3; + typedef aligned_lowp_mat4 aligned_mat4; + typedef packed_lowp_mat2 packed_mat2; + typedef packed_lowp_mat3 packed_mat3; + typedef packed_lowp_mat4 packed_mat4; + + typedef aligned_lowp_mat2x2 aligned_mat2x2; + typedef aligned_lowp_mat2x3 aligned_mat2x3; + typedef aligned_lowp_mat2x4 aligned_mat2x4; + typedef aligned_lowp_mat3x2 aligned_mat3x2; + typedef aligned_lowp_mat3x3 aligned_mat3x3; + typedef aligned_lowp_mat3x4 aligned_mat3x4; + typedef aligned_lowp_mat4x2 aligned_mat4x2; + typedef aligned_lowp_mat4x3 aligned_mat4x3; + typedef aligned_lowp_mat4x4 aligned_mat4x4; + typedef packed_lowp_mat2x2 packed_mat2x2; + typedef packed_lowp_mat2x3 packed_mat2x3; + typedef packed_lowp_mat2x4 packed_mat2x4; + typedef packed_lowp_mat3x2 packed_mat3x2; + typedef packed_lowp_mat3x3 packed_mat3x3; + typedef packed_lowp_mat3x4 packed_mat3x4; + typedef packed_lowp_mat4x2 packed_mat4x2; + typedef packed_lowp_mat4x3 packed_mat4x3; + typedef packed_lowp_mat4x4 packed_mat4x4; +#elif(defined(GLM_PRECISION_MEDIUMP_FLOAT)) + typedef aligned_mediump_vec1 aligned_vec1; + typedef aligned_mediump_vec2 aligned_vec2; + typedef aligned_mediump_vec3 aligned_vec3; + typedef aligned_mediump_vec4 aligned_vec4; + typedef packed_mediump_vec1 packed_vec1; + typedef packed_mediump_vec2 packed_vec2; + typedef packed_mediump_vec3 packed_vec3; + typedef packed_mediump_vec4 packed_vec4; + + typedef aligned_mediump_mat2 aligned_mat2; + typedef aligned_mediump_mat3 aligned_mat3; + typedef aligned_mediump_mat4 aligned_mat4; + typedef packed_mediump_mat2 packed_mat2; + typedef packed_mediump_mat3 packed_mat3; + typedef packed_mediump_mat4 packed_mat4; + + typedef aligned_mediump_mat2x2 aligned_mat2x2; + typedef aligned_mediump_mat2x3 aligned_mat2x3; + typedef aligned_mediump_mat2x4 aligned_mat2x4; + typedef aligned_mediump_mat3x2 aligned_mat3x2; + typedef aligned_mediump_mat3x3 aligned_mat3x3; + typedef aligned_mediump_mat3x4 aligned_mat3x4; + typedef aligned_mediump_mat4x2 aligned_mat4x2; + typedef aligned_mediump_mat4x3 aligned_mat4x3; + typedef aligned_mediump_mat4x4 aligned_mat4x4; + typedef packed_mediump_mat2x2 packed_mat2x2; + typedef packed_mediump_mat2x3 packed_mat2x3; + typedef packed_mediump_mat2x4 packed_mat2x4; + typedef packed_mediump_mat3x2 packed_mat3x2; + typedef packed_mediump_mat3x3 packed_mat3x3; + typedef packed_mediump_mat3x4 packed_mat3x4; + typedef packed_mediump_mat4x2 packed_mat4x2; + typedef packed_mediump_mat4x3 packed_mat4x3; + typedef packed_mediump_mat4x4 packed_mat4x4; +#else //defined(GLM_PRECISION_HIGHP_FLOAT) + /// 1 component vector aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_vec1 aligned_vec1; + + /// 2 components vector aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_vec2 aligned_vec2; + + /// 3 components vector aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_vec3 aligned_vec3; + + /// 4 components vector aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_vec4 aligned_vec4; + + /// 1 component vector tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_vec1 packed_vec1; + + /// 2 components vector tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_vec2 packed_vec2; + + /// 3 components vector tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_vec3 packed_vec3; + + /// 4 components vector tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_vec4 packed_vec4; + + /// 2 by 2 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat2 aligned_mat2; + + /// 3 by 3 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat3 aligned_mat3; + + /// 4 by 4 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat4 aligned_mat4; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat2 packed_mat2; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat3 packed_mat3; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat4 packed_mat4; + + /// 2 by 2 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat2x2 aligned_mat2x2; + + /// 2 by 3 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat2x3 aligned_mat2x3; + + /// 2 by 4 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat2x4 aligned_mat2x4; + + /// 3 by 2 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat3x2 aligned_mat3x2; + + /// 3 by 3 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat3x3 aligned_mat3x3; + + /// 3 by 4 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat3x4 aligned_mat3x4; + + /// 4 by 2 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat4x2 aligned_mat4x2; + + /// 4 by 3 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat4x3 aligned_mat4x3; + + /// 4 by 4 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat4x4 aligned_mat4x4; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat2x2 packed_mat2x2; + + /// 2 by 3 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat2x3 packed_mat2x3; + + /// 2 by 4 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat2x4 packed_mat2x4; + + /// 3 by 2 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat3x2 packed_mat3x2; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat3x3 packed_mat3x3; + + /// 3 by 4 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat3x4 packed_mat3x4; + + /// 4 by 2 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat4x2 packed_mat4x2; + + /// 4 by 3 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat4x3 packed_mat4x3; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat4x4 packed_mat4x4; +#endif//GLM_PRECISION + +#if(defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef aligned_lowp_dvec1 aligned_dvec1; + typedef aligned_lowp_dvec2 aligned_dvec2; + typedef aligned_lowp_dvec3 aligned_dvec3; + typedef aligned_lowp_dvec4 aligned_dvec4; + typedef packed_lowp_dvec1 packed_dvec1; + typedef packed_lowp_dvec2 packed_dvec2; + typedef packed_lowp_dvec3 packed_dvec3; + typedef packed_lowp_dvec4 packed_dvec4; + + typedef aligned_lowp_dmat2 aligned_dmat2; + typedef aligned_lowp_dmat3 aligned_dmat3; + typedef aligned_lowp_dmat4 aligned_dmat4; + typedef packed_lowp_dmat2 packed_dmat2; + typedef packed_lowp_dmat3 packed_dmat3; + typedef packed_lowp_dmat4 packed_dmat4; + + typedef aligned_lowp_dmat2x2 aligned_dmat2x2; + typedef aligned_lowp_dmat2x3 aligned_dmat2x3; + typedef aligned_lowp_dmat2x4 aligned_dmat2x4; + typedef aligned_lowp_dmat3x2 aligned_dmat3x2; + typedef aligned_lowp_dmat3x3 aligned_dmat3x3; + typedef aligned_lowp_dmat3x4 aligned_dmat3x4; + typedef aligned_lowp_dmat4x2 aligned_dmat4x2; + typedef aligned_lowp_dmat4x3 aligned_dmat4x3; + typedef aligned_lowp_dmat4x4 aligned_dmat4x4; + typedef packed_lowp_dmat2x2 packed_dmat2x2; + typedef packed_lowp_dmat2x3 packed_dmat2x3; + typedef packed_lowp_dmat2x4 packed_dmat2x4; + typedef packed_lowp_dmat3x2 packed_dmat3x2; + typedef packed_lowp_dmat3x3 packed_dmat3x3; + typedef packed_lowp_dmat3x4 packed_dmat3x4; + typedef packed_lowp_dmat4x2 packed_dmat4x2; + typedef packed_lowp_dmat4x3 packed_dmat4x3; + typedef packed_lowp_dmat4x4 packed_dmat4x4; +#elif(defined(GLM_PRECISION_MEDIUMP_DOUBLE)) + typedef aligned_mediump_dvec1 aligned_dvec1; + typedef aligned_mediump_dvec2 aligned_dvec2; + typedef aligned_mediump_dvec3 aligned_dvec3; + typedef aligned_mediump_dvec4 aligned_dvec4; + typedef packed_mediump_dvec1 packed_dvec1; + typedef packed_mediump_dvec2 packed_dvec2; + typedef packed_mediump_dvec3 packed_dvec3; + typedef packed_mediump_dvec4 packed_dvec4; + + typedef aligned_mediump_dmat2 aligned_dmat2; + typedef aligned_mediump_dmat3 aligned_dmat3; + typedef aligned_mediump_dmat4 aligned_dmat4; + typedef packed_mediump_dmat2 packed_dmat2; + typedef packed_mediump_dmat3 packed_dmat3; + typedef packed_mediump_dmat4 packed_dmat4; + + typedef aligned_mediump_dmat2x2 aligned_dmat2x2; + typedef aligned_mediump_dmat2x3 aligned_dmat2x3; + typedef aligned_mediump_dmat2x4 aligned_dmat2x4; + typedef aligned_mediump_dmat3x2 aligned_dmat3x2; + typedef aligned_mediump_dmat3x3 aligned_dmat3x3; + typedef aligned_mediump_dmat3x4 aligned_dmat3x4; + typedef aligned_mediump_dmat4x2 aligned_dmat4x2; + typedef aligned_mediump_dmat4x3 aligned_dmat4x3; + typedef aligned_mediump_dmat4x4 aligned_dmat4x4; + typedef packed_mediump_dmat2x2 packed_dmat2x2; + typedef packed_mediump_dmat2x3 packed_dmat2x3; + typedef packed_mediump_dmat2x4 packed_dmat2x4; + typedef packed_mediump_dmat3x2 packed_dmat3x2; + typedef packed_mediump_dmat3x3 packed_dmat3x3; + typedef packed_mediump_dmat3x4 packed_dmat3x4; + typedef packed_mediump_dmat4x2 packed_dmat4x2; + typedef packed_mediump_dmat4x3 packed_dmat4x3; + typedef packed_mediump_dmat4x4 packed_dmat4x4; +#else //defined(GLM_PRECISION_HIGHP_DOUBLE) + /// 1 component vector aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dvec1 aligned_dvec1; + + /// 2 components vector aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dvec2 aligned_dvec2; + + /// 3 components vector aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dvec3 aligned_dvec3; + + /// 4 components vector aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dvec4 aligned_dvec4; + + /// 1 component vector tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dvec1 packed_dvec1; + + /// 2 components vector tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dvec2 packed_dvec2; + + /// 3 components vector tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dvec3 packed_dvec3; + + /// 4 components vector tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dvec4 packed_dvec4; + + /// 2 by 2 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat2 aligned_dmat2; + + /// 3 by 3 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat3 aligned_dmat3; + + /// 4 by 4 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat4 aligned_dmat4; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat2 packed_dmat2; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat3 packed_dmat3; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat4 packed_dmat4; + + /// 2 by 2 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat2x2 aligned_dmat2x2; + + /// 2 by 3 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat2x3 aligned_dmat2x3; + + /// 2 by 4 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat2x4 aligned_dmat2x4; + + /// 3 by 2 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat3x2 aligned_dmat3x2; + + /// 3 by 3 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat3x3 aligned_dmat3x3; + + /// 3 by 4 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat3x4 aligned_dmat3x4; + + /// 4 by 2 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat4x2 aligned_dmat4x2; + + /// 4 by 3 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat4x3 aligned_dmat4x3; + + /// 4 by 4 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat4x4 aligned_dmat4x4; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat2x2 packed_dmat2x2; + + /// 2 by 3 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat2x3 packed_dmat2x3; + + /// 2 by 4 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat2x4 packed_dmat2x4; + + /// 3 by 2 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat3x2 packed_dmat3x2; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat3x3 packed_dmat3x3; + + /// 3 by 4 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat3x4 packed_dmat3x4; + + /// 4 by 2 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat4x2 packed_dmat4x2; + + /// 4 by 3 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat4x3 packed_dmat4x3; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat4x4 packed_dmat4x4; +#endif//GLM_PRECISION + +#if(defined(GLM_PRECISION_LOWP_INT)) + typedef aligned_lowp_ivec1 aligned_ivec1; + typedef aligned_lowp_ivec2 aligned_ivec2; + typedef aligned_lowp_ivec3 aligned_ivec3; + typedef aligned_lowp_ivec4 aligned_ivec4; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef aligned_mediump_ivec1 aligned_ivec1; + typedef aligned_mediump_ivec2 aligned_ivec2; + typedef aligned_mediump_ivec3 aligned_ivec3; + typedef aligned_mediump_ivec4 aligned_ivec4; +#else //defined(GLM_PRECISION_HIGHP_INT) + /// 1 component vector aligned in memory of signed integer numbers. + typedef aligned_highp_ivec1 aligned_ivec1; + + /// 2 components vector aligned in memory of signed integer numbers. + typedef aligned_highp_ivec2 aligned_ivec2; + + /// 3 components vector aligned in memory of signed integer numbers. + typedef aligned_highp_ivec3 aligned_ivec3; + + /// 4 components vector aligned in memory of signed integer numbers. + typedef aligned_highp_ivec4 aligned_ivec4; + + /// 1 component vector tightly packed in memory of signed integer numbers. + typedef packed_highp_ivec1 packed_ivec1; + + /// 2 components vector tightly packed in memory of signed integer numbers. + typedef packed_highp_ivec2 packed_ivec2; + + /// 3 components vector tightly packed in memory of signed integer numbers. + typedef packed_highp_ivec3 packed_ivec3; + + /// 4 components vector tightly packed in memory of signed integer numbers. + typedef packed_highp_ivec4 packed_ivec4; +#endif//GLM_PRECISION + + // -- Unsigned integer definition -- + +#if(defined(GLM_PRECISION_LOWP_UINT)) + typedef aligned_lowp_uvec1 aligned_uvec1; + typedef aligned_lowp_uvec2 aligned_uvec2; + typedef aligned_lowp_uvec3 aligned_uvec3; + typedef aligned_lowp_uvec4 aligned_uvec4; +#elif(defined(GLM_PRECISION_MEDIUMP_UINT)) + typedef aligned_mediump_uvec1 aligned_uvec1; + typedef aligned_mediump_uvec2 aligned_uvec2; + typedef aligned_mediump_uvec3 aligned_uvec3; + typedef aligned_mediump_uvec4 aligned_uvec4; +#else //defined(GLM_PRECISION_HIGHP_UINT) + /// 1 component vector aligned in memory of unsigned integer numbers. + typedef aligned_highp_uvec1 aligned_uvec1; + + /// 2 components vector aligned in memory of unsigned integer numbers. + typedef aligned_highp_uvec2 aligned_uvec2; + + /// 3 components vector aligned in memory of unsigned integer numbers. + typedef aligned_highp_uvec3 aligned_uvec3; + + /// 4 components vector aligned in memory of unsigned integer numbers. + typedef aligned_highp_uvec4 aligned_uvec4; + + /// 1 component vector tightly packed in memory of unsigned integer numbers. + typedef packed_highp_uvec1 packed_uvec1; + + /// 2 components vector tightly packed in memory of unsigned integer numbers. + typedef packed_highp_uvec2 packed_uvec2; + + /// 3 components vector tightly packed in memory of unsigned integer numbers. + typedef packed_highp_uvec3 packed_uvec3; + + /// 4 components vector tightly packed in memory of unsigned integer numbers. + typedef packed_highp_uvec4 packed_uvec4; +#endif//GLM_PRECISION + +#if(defined(GLM_PRECISION_LOWP_BOOL)) + typedef aligned_lowp_bvec1 aligned_bvec1; + typedef aligned_lowp_bvec2 aligned_bvec2; + typedef aligned_lowp_bvec3 aligned_bvec3; + typedef aligned_lowp_bvec4 aligned_bvec4; +#elif(defined(GLM_PRECISION_MEDIUMP_BOOL)) + typedef aligned_mediump_bvec1 aligned_bvec1; + typedef aligned_mediump_bvec2 aligned_bvec2; + typedef aligned_mediump_bvec3 aligned_bvec3; + typedef aligned_mediump_bvec4 aligned_bvec4; +#else //defined(GLM_PRECISION_HIGHP_BOOL) + /// 1 component vector aligned in memory of bool values. + typedef aligned_highp_bvec1 aligned_bvec1; + + /// 2 components vector aligned in memory of bool values. + typedef aligned_highp_bvec2 aligned_bvec2; + + /// 3 components vector aligned in memory of bool values. + typedef aligned_highp_bvec3 aligned_bvec3; + + /// 4 components vector aligned in memory of bool values. + typedef aligned_highp_bvec4 aligned_bvec4; + + /// 1 components vector tightly packed in memory of bool values. + typedef packed_highp_bvec1 packed_bvec1; + + /// 2 components vector tightly packed in memory of bool values. + typedef packed_highp_bvec2 packed_bvec2; + + /// 3 components vector tightly packed in memory of bool values. + typedef packed_highp_bvec3 packed_bvec3; + + /// 4 components vector tightly packed in memory of bool values. + typedef packed_highp_bvec4 packed_bvec4; +#endif//GLM_PRECISION + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_precision.hpp new file mode 100644 index 0000000..775e2f4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_precision.hpp @@ -0,0 +1,2094 @@ +/// @ref gtc_type_precision +/// @file glm/gtc/type_precision.hpp +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtc_type_precision GLM_GTC_type_precision +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines specific C++-based qualifier types. + +#pragma once + +// Dependency: +#include "../gtc/quaternion.hpp" +#include "../gtc/vec1.hpp" +#include "../ext/vector_int1_sized.hpp" +#include "../ext/vector_int2_sized.hpp" +#include "../ext/vector_int3_sized.hpp" +#include "../ext/vector_int4_sized.hpp" +#include "../ext/scalar_int_sized.hpp" +#include "../ext/vector_uint1_sized.hpp" +#include "../ext/vector_uint2_sized.hpp" +#include "../ext/vector_uint3_sized.hpp" +#include "../ext/vector_uint4_sized.hpp" +#include "../ext/scalar_uint_sized.hpp" +#include "../detail/type_vec2.hpp" +#include "../detail/type_vec3.hpp" +#include "../detail/type_vec4.hpp" +#include "../detail/type_mat2x2.hpp" +#include "../detail/type_mat2x3.hpp" +#include "../detail/type_mat2x4.hpp" +#include "../detail/type_mat3x2.hpp" +#include "../detail/type_mat3x3.hpp" +#include "../detail/type_mat3x4.hpp" +#include "../detail/type_mat4x2.hpp" +#include "../detail/type_mat4x3.hpp" +#include "../detail/type_mat4x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_type_precision extension included") +#endif + +namespace glm +{ + /////////////////////////// + // Signed int vector types + + /// @addtogroup gtc_type_precision + /// @{ + + /// Low qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 lowp_int8; + + /// Low qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 lowp_int16; + + /// Low qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 lowp_int32; + + /// Low qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 lowp_int64; + + /// Low qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 lowp_int8_t; + + /// Low qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 lowp_int16_t; + + /// Low qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 lowp_int32_t; + + /// Low qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 lowp_int64_t; + + /// Low qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 lowp_i8; + + /// Low qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 lowp_i16; + + /// Low qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 lowp_i32; + + /// Low qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 lowp_i64; + + /// Medium qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 mediump_int8; + + /// Medium qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 mediump_int16; + + /// Medium qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 mediump_int32; + + /// Medium qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 mediump_int64; + + /// Medium qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 mediump_int8_t; + + /// Medium qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 mediump_int16_t; + + /// Medium qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 mediump_int32_t; + + /// Medium qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 mediump_int64_t; + + /// Medium qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 mediump_i8; + + /// Medium qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 mediump_i16; + + /// Medium qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 mediump_i32; + + /// Medium qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 mediump_i64; + + /// High qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 highp_int8; + + /// High qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 highp_int16; + + /// High qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 highp_int32; + + /// High qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 highp_int64; + + /// High qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 highp_int8_t; + + /// High qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 highp_int16_t; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 highp_int32_t; + + /// High qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 highp_int64_t; + + /// High qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 highp_i8; + + /// High qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 highp_i16; + + /// High qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 highp_i32; + + /// High qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 highp_i64; + + +#if GLM_HAS_EXTENDED_INTEGER_TYPE + using std::int8_t; + using std::int16_t; + using std::int32_t; + using std::int64_t; +#else + /// 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 int8_t; + + /// 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 int16_t; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 int32_t; + + /// 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 int64_t; +#endif + + /// 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 i8; + + /// 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 i16; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 i32; + + /// 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 i64; + + ///////////////////////////// + // Unsigned int vector types + + /// Low qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 lowp_uint8; + + /// Low qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 lowp_uint16; + + /// Low qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 lowp_uint32; + + /// Low qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 lowp_uint64; + + /// Low qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 lowp_uint8_t; + + /// Low qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 lowp_uint16_t; + + /// Low qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 lowp_uint32_t; + + /// Low qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 lowp_uint64_t; + + /// Low qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 lowp_u8; + + /// Low qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 lowp_u16; + + /// Low qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 lowp_u32; + + /// Low qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 lowp_u64; + + /// Medium qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 mediump_uint8; + + /// Medium qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 mediump_uint16; + + /// Medium qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 mediump_uint32; + + /// Medium qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 mediump_uint64; + + /// Medium qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 mediump_uint8_t; + + /// Medium qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 mediump_uint16_t; + + /// Medium qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 mediump_uint32_t; + + /// Medium qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 mediump_uint64_t; + + /// Medium qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 mediump_u8; + + /// Medium qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 mediump_u16; + + /// Medium qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 mediump_u32; + + /// Medium qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 mediump_u64; + + /// High qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 highp_uint8; + + /// High qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 highp_uint16; + + /// High qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 highp_uint32; + + /// High qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 highp_uint64; + + /// High qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 highp_uint8_t; + + /// High qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 highp_uint16_t; + + /// High qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 highp_uint32_t; + + /// High qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 highp_uint64_t; + + /// High qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 highp_u8; + + /// High qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 highp_u16; + + /// High qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 highp_u32; + + /// High qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 highp_u64; + +#if GLM_HAS_EXTENDED_INTEGER_TYPE + using std::uint8_t; + using std::uint16_t; + using std::uint32_t; + using std::uint64_t; +#else + /// Default qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 uint8_t; + + /// Default qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 uint16_t; + + /// Default qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 uint32_t; + + /// Default qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 uint64_t; +#endif + + /// Default qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 u8; + + /// Default qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 u16; + + /// Default qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 u32; + + /// Default qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 u64; + + + + + + ////////////////////// + // Float vector types + + /// Single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float float32; + + /// Double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef double float64; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_float32; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_float64; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_float32_t; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_float64_t; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_f32; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_f64; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_float32; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_float64; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_float32_t; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_float64_t; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_f32; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_f64; + + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_float32; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_float64; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_float32_t; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_float64_t; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_f32; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_f64; + + + /// Medium 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 mediump_float32; + + /// Medium 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 mediump_float64; + + /// Medium 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 mediump_float32_t; + + /// Medium 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 mediump_float64_t; + + /// Medium 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 mediump_f32; + + /// Medium 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 mediump_f64; + + + /// High 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 highp_float32; + + /// High 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 highp_float64; + + /// High 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 highp_float32_t; + + /// High 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 highp_float64_t; + + /// High 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 highp_f32; + + /// High 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 highp_f64; + + +#if(defined(GLM_PRECISION_LOWP_FLOAT)) + /// Default 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef lowp_float32_t float32_t; + + /// Default 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef lowp_float64_t float64_t; + + /// Default 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef lowp_f32 f32; + + /// Default 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef lowp_f64 f64; + +#elif(defined(GLM_PRECISION_MEDIUMP_FLOAT)) + /// Default 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float32 float32_t; + + /// Default 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float64 float64_t; + + /// Default 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float32 f32; + + /// Default 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float64 f64; + +#else//(defined(GLM_PRECISION_HIGHP_FLOAT)) + + /// Default 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef highp_float32_t float32_t; + + /// Default 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef highp_float64_t float64_t; + + /// Default 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef highp_float32_t f32; + + /// Default 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef highp_float64_t f64; +#endif + + + /// Low single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, float, lowp> lowp_fvec1; + + /// Low single-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, float, lowp> lowp_fvec2; + + /// Low single-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, float, lowp> lowp_fvec3; + + /// Low single-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, float, lowp> lowp_fvec4; + + + /// Medium single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, float, mediump> mediump_fvec1; + + /// Medium Single-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, float, mediump> mediump_fvec2; + + /// Medium Single-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, float, mediump> mediump_fvec3; + + /// Medium Single-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, float, mediump> mediump_fvec4; + + + /// High single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, float, highp> highp_fvec1; + + /// High Single-qualifier floating-point vector of 2 components. + /// @see core_precision + typedef vec<2, float, highp> highp_fvec2; + + /// High Single-qualifier floating-point vector of 3 components. + /// @see core_precision + typedef vec<3, float, highp> highp_fvec3; + + /// High Single-qualifier floating-point vector of 4 components. + /// @see core_precision + typedef vec<4, float, highp> highp_fvec4; + + + /// Low single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f32, lowp> lowp_f32vec1; + + /// Low single-qualifier floating-point vector of 2 components. + /// @see core_precision + typedef vec<2, f32, lowp> lowp_f32vec2; + + /// Low single-qualifier floating-point vector of 3 components. + /// @see core_precision + typedef vec<3, f32, lowp> lowp_f32vec3; + + /// Low single-qualifier floating-point vector of 4 components. + /// @see core_precision + typedef vec<4, f32, lowp> lowp_f32vec4; + + /// Medium single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f32, mediump> mediump_f32vec1; + + /// Medium single-qualifier floating-point vector of 2 components. + /// @see core_precision + typedef vec<2, f32, mediump> mediump_f32vec2; + + /// Medium single-qualifier floating-point vector of 3 components. + /// @see core_precision + typedef vec<3, f32, mediump> mediump_f32vec3; + + /// Medium single-qualifier floating-point vector of 4 components. + /// @see core_precision + typedef vec<4, f32, mediump> mediump_f32vec4; + + /// High single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f32, highp> highp_f32vec1; + + /// High single-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, f32, highp> highp_f32vec2; + + /// High single-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, f32, highp> highp_f32vec3; + + /// High single-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, f32, highp> highp_f32vec4; + + + /// Low double-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f64, lowp> lowp_f64vec1; + + /// Low double-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, f64, lowp> lowp_f64vec2; + + /// Low double-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, f64, lowp> lowp_f64vec3; + + /// Low double-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, f64, lowp> lowp_f64vec4; + + /// Medium double-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f64, mediump> mediump_f64vec1; + + /// Medium double-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, f64, mediump> mediump_f64vec2; + + /// Medium double-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, f64, mediump> mediump_f64vec3; + + /// Medium double-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, f64, mediump> mediump_f64vec4; + + /// High double-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f64, highp> highp_f64vec1; + + /// High double-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, f64, highp> highp_f64vec2; + + /// High double-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, f64, highp> highp_f64vec3; + + /// High double-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, f64, highp> highp_f64vec4; + + + + ////////////////////// + // Float matrix types + + /// Low single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef lowp_f32 lowp_fmat1x1; + + /// Low single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, lowp> lowp_fmat2x2; + + /// Low single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, lowp> lowp_fmat2x3; + + /// Low single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, lowp> lowp_fmat2x4; + + /// Low single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, lowp> lowp_fmat3x2; + + /// Low single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, lowp> lowp_fmat3x3; + + /// Low single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, lowp> lowp_fmat3x4; + + /// Low single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, lowp> lowp_fmat4x2; + + /// Low single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, lowp> lowp_fmat4x3; + + /// Low single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, lowp> lowp_fmat4x4; + + /// Low single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef lowp_fmat1x1 lowp_fmat1; + + /// Low single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef lowp_fmat2x2 lowp_fmat2; + + /// Low single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef lowp_fmat3x3 lowp_fmat3; + + /// Low single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef lowp_fmat4x4 lowp_fmat4; + + + /// Medium single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef mediump_f32 mediump_fmat1x1; + + /// Medium single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, mediump> mediump_fmat2x2; + + /// Medium single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, mediump> mediump_fmat2x3; + + /// Medium single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, mediump> mediump_fmat2x4; + + /// Medium single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, mediump> mediump_fmat3x2; + + /// Medium single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, mediump> mediump_fmat3x3; + + /// Medium single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, mediump> mediump_fmat3x4; + + /// Medium single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, mediump> mediump_fmat4x2; + + /// Medium single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, mediump> mediump_fmat4x3; + + /// Medium single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, mediump> mediump_fmat4x4; + + /// Medium single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef mediump_fmat1x1 mediump_fmat1; + + /// Medium single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mediump_fmat2x2 mediump_fmat2; + + /// Medium single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mediump_fmat3x3 mediump_fmat3; + + /// Medium single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mediump_fmat4x4 mediump_fmat4; + + + /// High single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef highp_f32 highp_fmat1x1; + + /// High single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, highp> highp_fmat2x2; + + /// High single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, highp> highp_fmat2x3; + + /// High single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, highp> highp_fmat2x4; + + /// High single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, highp> highp_fmat3x2; + + /// High single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, highp> highp_fmat3x3; + + /// High single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, highp> highp_fmat3x4; + + /// High single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, highp> highp_fmat4x2; + + /// High single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, highp> highp_fmat4x3; + + /// High single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, highp> highp_fmat4x4; + + /// High single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef highp_fmat1x1 highp_fmat1; + + /// High single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef highp_fmat2x2 highp_fmat2; + + /// High single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef highp_fmat3x3 highp_fmat3; + + /// High single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef highp_fmat4x4 highp_fmat4; + + + /// Low single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 lowp_f32mat1x1; + + /// Low single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, lowp> lowp_f32mat2x2; + + /// Low single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, lowp> lowp_f32mat2x3; + + /// Low single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, lowp> lowp_f32mat2x4; + + /// Low single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, lowp> lowp_f32mat3x2; + + /// Low single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, lowp> lowp_f32mat3x3; + + /// Low single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, lowp> lowp_f32mat3x4; + + /// Low single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, lowp> lowp_f32mat4x2; + + /// Low single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, lowp> lowp_f32mat4x3; + + /// Low single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, lowp> lowp_f32mat4x4; + + /// Low single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1 lowp_f32mat1; + + /// Low single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef lowp_f32mat2x2 lowp_f32mat2; + + /// Low single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef lowp_f32mat3x3 lowp_f32mat3; + + /// Low single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef lowp_f32mat4x4 lowp_f32mat4; + + + /// High single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 mediump_f32mat1x1; + + /// Low single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, mediump> mediump_f32mat2x2; + + /// Medium single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, mediump> mediump_f32mat2x3; + + /// Medium single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, mediump> mediump_f32mat2x4; + + /// Medium single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, mediump> mediump_f32mat3x2; + + /// Medium single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, mediump> mediump_f32mat3x3; + + /// Medium single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, mediump> mediump_f32mat3x4; + + /// Medium single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, mediump> mediump_f32mat4x2; + + /// Medium single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, mediump> mediump_f32mat4x3; + + /// Medium single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, mediump> mediump_f32mat4x4; + + /// Medium single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1 f32mat1; + + /// Medium single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mediump_f32mat2x2 mediump_f32mat2; + + /// Medium single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mediump_f32mat3x3 mediump_f32mat3; + + /// Medium single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mediump_f32mat4x4 mediump_f32mat4; + + + /// High single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 highp_f32mat1x1; + + /// High single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, highp> highp_f32mat2x2; + + /// High single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, highp> highp_f32mat2x3; + + /// High single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, highp> highp_f32mat2x4; + + /// High single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, highp> highp_f32mat3x2; + + /// High single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, highp> highp_f32mat3x3; + + /// High single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, highp> highp_f32mat3x4; + + /// High single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, highp> highp_f32mat4x2; + + /// High single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, highp> highp_f32mat4x3; + + /// High single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, highp> highp_f32mat4x4; + + /// High single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1 f32mat1; + + /// High single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef highp_f32mat2x2 highp_f32mat2; + + /// High single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef highp_f32mat3x3 highp_f32mat3; + + /// High single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef highp_f32mat4x4 highp_f32mat4; + + + /// Low double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f64 lowp_f64mat1x1; + + /// Low double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f64, lowp> lowp_f64mat2x2; + + /// Low double-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f64, lowp> lowp_f64mat2x3; + + /// Low double-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f64, lowp> lowp_f64mat2x4; + + /// Low double-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f64, lowp> lowp_f64mat3x2; + + /// Low double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f64, lowp> lowp_f64mat3x3; + + /// Low double-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f64, lowp> lowp_f64mat3x4; + + /// Low double-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f64, lowp> lowp_f64mat4x2; + + /// Low double-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f64, lowp> lowp_f64mat4x3; + + /// Low double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f64, lowp> lowp_f64mat4x4; + + /// Low double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef lowp_f64mat1x1 lowp_f64mat1; + + /// Low double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef lowp_f64mat2x2 lowp_f64mat2; + + /// Low double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef lowp_f64mat3x3 lowp_f64mat3; + + /// Low double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef lowp_f64mat4x4 lowp_f64mat4; + + + /// Medium double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f64 Highp_f64mat1x1; + + /// Medium double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f64, mediump> mediump_f64mat2x2; + + /// Medium double-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f64, mediump> mediump_f64mat2x3; + + /// Medium double-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f64, mediump> mediump_f64mat2x4; + + /// Medium double-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f64, mediump> mediump_f64mat3x2; + + /// Medium double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f64, mediump> mediump_f64mat3x3; + + /// Medium double-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f64, mediump> mediump_f64mat3x4; + + /// Medium double-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f64, mediump> mediump_f64mat4x2; + + /// Medium double-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f64, mediump> mediump_f64mat4x3; + + /// Medium double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f64, mediump> mediump_f64mat4x4; + + /// Medium double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef mediump_f64mat1x1 mediump_f64mat1; + + /// Medium double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mediump_f64mat2x2 mediump_f64mat2; + + /// Medium double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mediump_f64mat3x3 mediump_f64mat3; + + /// Medium double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mediump_f64mat4x4 mediump_f64mat4; + + /// High double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f64 highp_f64mat1x1; + + /// High double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f64, highp> highp_f64mat2x2; + + /// High double-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f64, highp> highp_f64mat2x3; + + /// High double-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f64, highp> highp_f64mat2x4; + + /// High double-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f64, highp> highp_f64mat3x2; + + /// High double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f64, highp> highp_f64mat3x3; + + /// High double-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f64, highp> highp_f64mat3x4; + + /// High double-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f64, highp> highp_f64mat4x2; + + /// High double-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f64, highp> highp_f64mat4x3; + + /// High double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f64, highp> highp_f64mat4x4; + + /// High double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef highp_f64mat1x1 highp_f64mat1; + + /// High double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef highp_f64mat2x2 highp_f64mat2; + + /// High double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef highp_f64mat3x3 highp_f64mat3; + + /// High double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef highp_f64mat4x4 highp_f64mat4; + + + ///////////////////////////// + // Signed int vector types + + /// Low qualifier signed integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, int, lowp> lowp_ivec1; + + /// Low qualifier signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, int, lowp> lowp_ivec2; + + /// Low qualifier signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, int, lowp> lowp_ivec3; + + /// Low qualifier signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, int, lowp> lowp_ivec4; + + + /// Medium qualifier signed integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, int, mediump> mediump_ivec1; + + /// Medium qualifier signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, int, mediump> mediump_ivec2; + + /// Medium qualifier signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, int, mediump> mediump_ivec3; + + /// Medium qualifier signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, int, mediump> mediump_ivec4; + + + /// High qualifier signed integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, int, highp> highp_ivec1; + + /// High qualifier signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, int, highp> highp_ivec2; + + /// High qualifier signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, int, highp> highp_ivec3; + + /// High qualifier signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, int, highp> highp_ivec4; + + + /// Low qualifier 8 bit signed integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, i8, lowp> lowp_i8vec1; + + /// Low qualifier 8 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i8, lowp> lowp_i8vec2; + + /// Low qualifier 8 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i8, lowp> lowp_i8vec3; + + /// Low qualifier 8 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i8, lowp> lowp_i8vec4; + + + /// Medium qualifier 8 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i8, mediump> mediump_i8vec1; + + /// Medium qualifier 8 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i8, mediump> mediump_i8vec2; + + /// Medium qualifier 8 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i8, mediump> mediump_i8vec3; + + /// Medium qualifier 8 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i8, mediump> mediump_i8vec4; + + + /// High qualifier 8 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i8, highp> highp_i8vec1; + + /// High qualifier 8 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i8, highp> highp_i8vec2; + + /// High qualifier 8 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i8, highp> highp_i8vec3; + + /// High qualifier 8 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i8, highp> highp_i8vec4; + + + /// Low qualifier 16 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i16, lowp> lowp_i16vec1; + + /// Low qualifier 16 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i16, lowp> lowp_i16vec2; + + /// Low qualifier 16 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i16, lowp> lowp_i16vec3; + + /// Low qualifier 16 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i16, lowp> lowp_i16vec4; + + + /// Medium qualifier 16 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i16, mediump> mediump_i16vec1; + + /// Medium qualifier 16 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i16, mediump> mediump_i16vec2; + + /// Medium qualifier 16 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i16, mediump> mediump_i16vec3; + + /// Medium qualifier 16 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i16, mediump> mediump_i16vec4; + + + /// High qualifier 16 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i16, highp> highp_i16vec1; + + /// High qualifier 16 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i16, highp> highp_i16vec2; + + /// High qualifier 16 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i16, highp> highp_i16vec3; + + /// High qualifier 16 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i16, highp> highp_i16vec4; + + + /// Low qualifier 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i32, lowp> lowp_i32vec1; + + /// Low qualifier 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i32, lowp> lowp_i32vec2; + + /// Low qualifier 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i32, lowp> lowp_i32vec3; + + /// Low qualifier 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i32, lowp> lowp_i32vec4; + + + /// Medium qualifier 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i32, mediump> mediump_i32vec1; + + /// Medium qualifier 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i32, mediump> mediump_i32vec2; + + /// Medium qualifier 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i32, mediump> mediump_i32vec3; + + /// Medium qualifier 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i32, mediump> mediump_i32vec4; + + + /// High qualifier 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i32, highp> highp_i32vec1; + + /// High qualifier 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i32, highp> highp_i32vec2; + + /// High qualifier 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i32, highp> highp_i32vec3; + + /// High qualifier 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i32, highp> highp_i32vec4; + + + /// Low qualifier 64 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i64, lowp> lowp_i64vec1; + + /// Low qualifier 64 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i64, lowp> lowp_i64vec2; + + /// Low qualifier 64 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i64, lowp> lowp_i64vec3; + + /// Low qualifier 64 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i64, lowp> lowp_i64vec4; + + + /// Medium qualifier 64 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i64, mediump> mediump_i64vec1; + + /// Medium qualifier 64 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i64, mediump> mediump_i64vec2; + + /// Medium qualifier 64 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i64, mediump> mediump_i64vec3; + + /// Medium qualifier 64 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i64, mediump> mediump_i64vec4; + + + /// High qualifier 64 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i64, highp> highp_i64vec1; + + /// High qualifier 64 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i64, highp> highp_i64vec2; + + /// High qualifier 64 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i64, highp> highp_i64vec3; + + /// High qualifier 64 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i64, highp> highp_i64vec4; + + + ///////////////////////////// + // Unsigned int vector types + + /// Low qualifier unsigned integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, uint, lowp> lowp_uvec1; + + /// Low qualifier unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, uint, lowp> lowp_uvec2; + + /// Low qualifier unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, uint, lowp> lowp_uvec3; + + /// Low qualifier unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, uint, lowp> lowp_uvec4; + + + /// Medium qualifier unsigned integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, uint, mediump> mediump_uvec1; + + /// Medium qualifier unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, uint, mediump> mediump_uvec2; + + /// Medium qualifier unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, uint, mediump> mediump_uvec3; + + /// Medium qualifier unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, uint, mediump> mediump_uvec4; + + + /// High qualifier unsigned integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, uint, highp> highp_uvec1; + + /// High qualifier unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, uint, highp> highp_uvec2; + + /// High qualifier unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, uint, highp> highp_uvec3; + + /// High qualifier unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, uint, highp> highp_uvec4; + + + /// Low qualifier 8 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u8, lowp> lowp_u8vec1; + + /// Low qualifier 8 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u8, lowp> lowp_u8vec2; + + /// Low qualifier 8 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u8, lowp> lowp_u8vec3; + + /// Low qualifier 8 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u8, lowp> lowp_u8vec4; + + + /// Medium qualifier 8 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u8, mediump> mediump_u8vec1; + + /// Medium qualifier 8 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u8, mediump> mediump_u8vec2; + + /// Medium qualifier 8 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u8, mediump> mediump_u8vec3; + + /// Medium qualifier 8 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u8, mediump> mediump_u8vec4; + + + /// High qualifier 8 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u8, highp> highp_u8vec1; + + /// High qualifier 8 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u8, highp> highp_u8vec2; + + /// High qualifier 8 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u8, highp> highp_u8vec3; + + /// High qualifier 8 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u8, highp> highp_u8vec4; + + + /// Low qualifier 16 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u16, lowp> lowp_u16vec1; + + /// Low qualifier 16 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u16, lowp> lowp_u16vec2; + + /// Low qualifier 16 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u16, lowp> lowp_u16vec3; + + /// Low qualifier 16 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u16, lowp> lowp_u16vec4; + + + /// Medium qualifier 16 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u16, mediump> mediump_u16vec1; + + /// Medium qualifier 16 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u16, mediump> mediump_u16vec2; + + /// Medium qualifier 16 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u16, mediump> mediump_u16vec3; + + /// Medium qualifier 16 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u16, mediump> mediump_u16vec4; + + + /// High qualifier 16 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u16, highp> highp_u16vec1; + + /// High qualifier 16 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u16, highp> highp_u16vec2; + + /// High qualifier 16 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u16, highp> highp_u16vec3; + + /// High qualifier 16 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u16, highp> highp_u16vec4; + + + /// Low qualifier 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u32, lowp> lowp_u32vec1; + + /// Low qualifier 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u32, lowp> lowp_u32vec2; + + /// Low qualifier 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u32, lowp> lowp_u32vec3; + + /// Low qualifier 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u32, lowp> lowp_u32vec4; + + + /// Medium qualifier 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u32, mediump> mediump_u32vec1; + + /// Medium qualifier 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u32, mediump> mediump_u32vec2; + + /// Medium qualifier 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u32, mediump> mediump_u32vec3; + + /// Medium qualifier 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u32, mediump> mediump_u32vec4; + + + /// High qualifier 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u32, highp> highp_u32vec1; + + /// High qualifier 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u32, highp> highp_u32vec2; + + /// High qualifier 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u32, highp> highp_u32vec3; + + /// High qualifier 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u32, highp> highp_u32vec4; + + + /// Low qualifier 64 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u64, lowp> lowp_u64vec1; + + /// Low qualifier 64 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u64, lowp> lowp_u64vec2; + + /// Low qualifier 64 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u64, lowp> lowp_u64vec3; + + /// Low qualifier 64 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u64, lowp> lowp_u64vec4; + + + /// Medium qualifier 64 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u64, mediump> mediump_u64vec1; + + /// Medium qualifier 64 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u64, mediump> mediump_u64vec2; + + /// Medium qualifier 64 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u64, mediump> mediump_u64vec3; + + /// Medium qualifier 64 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u64, mediump> mediump_u64vec4; + + + /// High qualifier 64 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u64, highp> highp_u64vec1; + + /// High qualifier 64 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u64, highp> highp_u64vec2; + + /// High qualifier 64 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u64, highp> highp_u64vec3; + + /// High qualifier 64 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u64, highp> highp_u64vec4; + + + ////////////////////// + // Float vector types + + /// 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 float32_t; + + /// 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 f32; + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 float64_t; + + /// 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 f64; +# endif//GLM_FORCE_SINGLE_ONLY + + /// Single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, float, defaultp> fvec1; + + /// Single-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, float, defaultp> fvec2; + + /// Single-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, float, defaultp> fvec3; + + /// Single-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, float, defaultp> fvec4; + + + /// Single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f32, defaultp> f32vec1; + + /// Single-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, f32, defaultp> f32vec2; + + /// Single-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, f32, defaultp> f32vec3; + + /// Single-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, f32, defaultp> f32vec4; + +# ifndef GLM_FORCE_SINGLE_ONLY + /// Double-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f64, defaultp> f64vec1; + + /// Double-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, f64, defaultp> f64vec2; + + /// Double-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, f64, defaultp> f64vec3; + + /// Double-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, f64, defaultp> f64vec4; +# endif//GLM_FORCE_SINGLE_ONLY + + + ////////////////////// + // Float matrix types + + /// Single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1 fmat1; + + /// Single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, defaultp> fmat2; + + /// Single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, defaultp> fmat3; + + /// Single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, defaultp> fmat4; + + + /// Single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 fmat1x1; + + /// Single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, defaultp> fmat2x2; + + /// Single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, defaultp> fmat2x3; + + /// Single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, defaultp> fmat2x4; + + /// Single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, defaultp> fmat3x2; + + /// Single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, defaultp> fmat3x3; + + /// Single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, defaultp> fmat3x4; + + /// Single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, defaultp> fmat4x2; + + /// Single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, defaultp> fmat4x3; + + /// Single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, defaultp> fmat4x4; + + + /// Single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1 f32mat1; + + /// Single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, defaultp> f32mat2; + + /// Single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, defaultp> f32mat3; + + /// Single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, defaultp> f32mat4; + + + /// Single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 f32mat1x1; + + /// Single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, defaultp> f32mat2x2; + + /// Single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, defaultp> f32mat2x3; + + /// Single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, defaultp> f32mat2x4; + + /// Single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, defaultp> f32mat3x2; + + /// Single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, defaultp> f32mat3x3; + + /// Single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, defaultp> f32mat3x4; + + /// Single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, defaultp> f32mat4x2; + + /// Single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, defaultp> f32mat4x3; + + /// Single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, defaultp> f32mat4x4; + + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// Double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1 f64mat1; + + /// Double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f64, defaultp> f64mat2; + + /// Double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f64, defaultp> f64mat3; + + /// Double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f64, defaultp> f64mat4; + + + /// Double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f64 f64mat1x1; + + /// Double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f64, defaultp> f64mat2x2; + + /// Double-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f64, defaultp> f64mat2x3; + + /// Double-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f64, defaultp> f64mat2x4; + + /// Double-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f64, defaultp> f64mat3x2; + + /// Double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f64, defaultp> f64mat3x3; + + /// Double-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f64, defaultp> f64mat3x4; + + /// Double-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f64, defaultp> f64mat4x2; + + /// Double-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f64, defaultp> f64mat4x3; + + /// Double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f64, defaultp> f64mat4x4; + +# endif//GLM_FORCE_SINGLE_ONLY + + ////////////////////////// + // Quaternion types + + /// Single-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua f32quat; + + /// Low single-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua lowp_f32quat; + + /// Low double-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua lowp_f64quat; + + /// Medium single-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua mediump_f32quat; + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// Medium double-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua mediump_f64quat; + + /// High single-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua highp_f32quat; + + /// High double-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua highp_f64quat; + + /// Double-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua f64quat; + +# endif//GLM_FORCE_SINGLE_ONLY + + /// @} +}//namespace glm + +#include "type_precision.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_precision.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_precision.inl new file mode 100644 index 0000000..ae80912 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_precision.inl @@ -0,0 +1,6 @@ +/// @ref gtc_precision + +namespace glm +{ + +} diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_ptr.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_ptr.hpp new file mode 100644 index 0000000..d7e625a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_ptr.hpp @@ -0,0 +1,230 @@ +/// @ref gtc_type_ptr +/// @file glm/gtc/type_ptr.hpp +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtc_type_ptr GLM_GTC_type_ptr +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Handles the interaction between pointers and vector, matrix types. +/// +/// This extension defines an overloaded function, glm::value_ptr. It returns +/// a pointer to the memory layout of the object. Matrix types store their values +/// in column-major order. +/// +/// This is useful for uploading data to matrices or copying data to buffer objects. +/// +/// Example: +/// @code +/// #include +/// #include +/// +/// glm::vec3 aVector(3); +/// glm::mat4 someMatrix(1.0); +/// +/// glUniform3fv(uniformLoc, 1, glm::value_ptr(aVector)); +/// glUniformMatrix4fv(uniformMatrixLoc, 1, GL_FALSE, glm::value_ptr(someMatrix)); +/// @endcode +/// +/// need to be included to use the features of this extension. + +#pragma once + +// Dependency: +#include "../gtc/quaternion.hpp" +#include "../gtc/vec1.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../mat2x2.hpp" +#include "../mat2x3.hpp" +#include "../mat2x4.hpp" +#include "../mat3x2.hpp" +#include "../mat3x3.hpp" +#include "../mat3x4.hpp" +#include "../mat4x2.hpp" +#include "../mat4x3.hpp" +#include "../mat4x4.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_type_ptr extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_type_ptr + /// @{ + + /// Return the constant address to the data of the input parameter. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL typename genType::value_type const * value_ptr(genType const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<1, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<2, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<3, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<4, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<1, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<2, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<3, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<4, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<1, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<2, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<3, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<4, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<4, T, Q> make_vec4(vec<1, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<4, T, Q> make_vec4(vec<2, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<4, T, Q> make_vec4(vec<3, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<4, T, Q> make_vec4(vec<4, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<2, T, defaultp> make_vec2(T const * const ptr); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<3, T, defaultp> make_vec3(T const * const ptr); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<4, T, defaultp> make_vec4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<2, 2, T, defaultp> make_mat2x2(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<2, 3, T, defaultp> make_mat2x3(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<2, 4, T, defaultp> make_mat2x4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<3, 2, T, defaultp> make_mat3x2(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<3, 3, T, defaultp> make_mat3x3(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<3, 4, T, defaultp> make_mat3x4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<4, 2, T, defaultp> make_mat4x2(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<4, 3, T, defaultp> make_mat4x3(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> make_mat4x4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<2, 2, T, defaultp> make_mat2(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<3, 3, T, defaultp> make_mat3(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> make_mat4(T const * const ptr); + + /// Build a quaternion from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL qua make_quat(T const * const ptr); + + /// @} +}//namespace glm + +#include "type_ptr.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_ptr.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_ptr.inl new file mode 100644 index 0000000..26b20b5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_ptr.inl @@ -0,0 +1,386 @@ +/// @ref gtc_type_ptr + +#include + +namespace glm +{ + /// @addtogroup gtc_type_ptr + /// @{ + + template + GLM_FUNC_QUALIFIER T const* value_ptr(vec<2, T, Q> const& v) + { + return &(v.x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(vec<2, T, Q>& v) + { + return &(v.x); + } + + template + GLM_FUNC_QUALIFIER T const * value_ptr(vec<3, T, Q> const& v) + { + return &(v.x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(vec<3, T, Q>& v) + { + return &(v.x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(vec<4, T, Q> const& v) + { + return &(v.x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(vec<4, T, Q>& v) + { + return &(v.x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<2, 2, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<2, 2, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<3, 3, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<3, 3, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<4, 4, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<4, 4, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<2, 3, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<2, 3, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<3, 2, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<3, 2, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<2, 4, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<2, 4, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<4, 2, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<4, 2, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<3, 4, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<3, 4, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<4, 3, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T * value_ptr(mat<4, 3, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const * value_ptr(qua const& q) + { + return &(q[0]); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(qua& q) + { + return &(q[0]); + } + + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<1, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<2, T, Q> const& v) + { + return vec<1, T, Q>(v); + } + + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<3, T, Q> const& v) + { + return vec<1, T, Q>(v); + } + + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<4, T, Q> const& v) + { + return vec<1, T, Q>(v); + } + + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<1, T, Q> const& v) + { + return vec<2, T, Q>(v.x, static_cast(0)); + } + + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<2, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<3, T, Q> const& v) + { + return vec<2, T, Q>(v); + } + + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<4, T, Q> const& v) + { + return vec<2, T, Q>(v); + } + + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<1, T, Q> const& v) + { + return vec<3, T, Q>(v.x, static_cast(0), static_cast(0)); + } + + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<2, T, Q> const& v) + { + return vec<3, T, Q>(v.x, v.y, static_cast(0)); + } + + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<3, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<4, T, Q> const& v) + { + return vec<3, T, Q>(v); + } + + template + GLM_FUNC_DECL vec<4, T, Q> make_vec4(vec<1, T, Q> const& v) + { + return vec<4, T, Q>(v.x, static_cast(0), static_cast(0), static_cast(1)); + } + + template + GLM_FUNC_DECL vec<4, T, Q> make_vec4(vec<2, T, Q> const& v) + { + return vec<4, T, Q>(v.x, v.y, static_cast(0), static_cast(1)); + } + + template + GLM_FUNC_DECL vec<4, T, Q> make_vec4(vec<3, T, Q> const& v) + { + return vec<4, T, Q>(v.x, v.y, v.z, static_cast(1)); + } + + template + GLM_FUNC_DECL vec<4, T, Q> make_vec4(vec<4, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, defaultp> make_vec2(T const *const ptr) + { + vec<2, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(vec<2, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, defaultp> make_vec3(T const *const ptr) + { + vec<3, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(vec<3, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, defaultp> make_vec4(T const *const ptr) + { + vec<4, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(vec<4, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, defaultp> make_mat2x2(T const *const ptr) + { + mat<2, 2, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<2, 2, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, defaultp> make_mat2x3(T const *const ptr) + { + mat<2, 3, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<2, 3, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, defaultp> make_mat2x4(T const *const ptr) + { + mat<2, 4, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<2, 4, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, defaultp> make_mat3x2(T const *const ptr) + { + mat<3, 2, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<3, 2, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, defaultp> make_mat3x3(T const *const ptr) + { + mat<3, 3, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<3, 3, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, defaultp> make_mat3x4(T const *const ptr) + { + mat<3, 4, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<3, 4, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, defaultp> make_mat4x2(T const *const ptr) + { + mat<4, 2, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<4, 2, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, defaultp> make_mat4x3(T const *const ptr) + { + mat<4, 3, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<4, 3, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> make_mat4x4(T const *const ptr) + { + mat<4, 4, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<4, 4, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, defaultp> make_mat2(T const *const ptr) + { + return make_mat2x2(ptr); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, defaultp> make_mat3(T const *const ptr) + { + return make_mat3x3(ptr); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> make_mat4(T const *const ptr) + { + return make_mat4x4(ptr); + } + + template + GLM_FUNC_QUALIFIER qua make_quat(T const *const ptr) + { + qua Result; + memcpy(value_ptr(Result), ptr, sizeof(qua)); + return Result; + } + + /// @} +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/ulp.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/ulp.hpp new file mode 100644 index 0000000..7b918f0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/ulp.hpp @@ -0,0 +1,155 @@ +/// @ref gtc_ulp +/// @file glm/gtc/ulp.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_ulp GLM_GTC_ulp +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Allow the measurement of the accuracy of a function against a reference +/// implementation. This extension works on floating-point data and provide results +/// in ULP. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/_vectorize.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_ulp extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_ulp + /// @{ + + /// Return the next ULP value(s) after the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL genType next_float(genType x); + + /// Return the previous ULP value(s) before the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL genType prev_float(genType x); + + /// Return the value(s) ULP distance after the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL genType next_float(genType x, int ULPs); + + /// Return the value(s) ULP distance before the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL genType prev_float(genType x, int ULPs); + + /// Return the distance in the number of ULP between 2 single-precision floating-point scalars. + /// + /// @see gtc_ulp + GLM_FUNC_DECL int float_distance(float x, float y); + + /// Return the distance in the number of ULP between 2 double-precision floating-point scalars. + /// + /// @see gtc_ulp + GLM_FUNC_DECL int64 float_distance(double x, double y); + + /// Return the next ULP value(s) after the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec next_float(vec const& x); + + /// Return the value(s) ULP distance after the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec next_float(vec const& x, int ULPs); + + /// Return the value(s) ULP distance after the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec next_float(vec const& x, vec const& ULPs); + + /// Return the previous ULP value(s) before the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec prev_float(vec const& x); + + /// Return the value(s) ULP distance before the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec prev_float(vec const& x, int ULPs); + + /// Return the value(s) ULP distance before the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec prev_float(vec const& x, vec const& ULPs); + + /// Return the distance in the number of ULP between 2 single-precision floating-point scalars. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec float_distance(vec const& x, vec const& y); + + /// Return the distance in the number of ULP between 2 double-precision floating-point scalars. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec float_distance(vec const& x, vec const& y); + + /// @} +}//namespace glm + +#include "ulp.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/ulp.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/ulp.inl new file mode 100644 index 0000000..836c84b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/ulp.inl @@ -0,0 +1,173 @@ +/// @ref gtc_ulp + +#include "../ext/scalar_ulp.hpp" + +namespace glm +{ + template<> + GLM_FUNC_QUALIFIER float next_float(float x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::max()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafterf(x, FLT_MAX); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafterf(x, FLT_MAX); +# else + return nextafterf(x, FLT_MAX); +# endif + } + + template<> + GLM_FUNC_QUALIFIER double next_float(double x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::max()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafter(x, std::numeric_limits::max()); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafter(x, DBL_MAX); +# else + return nextafter(x, DBL_MAX); +# endif + } + + template + GLM_FUNC_QUALIFIER T next_float(T x, int ULPs) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'next_float' only accept floating-point input"); + assert(ULPs >= 0); + + T temp = x; + for (int i = 0; i < ULPs; ++i) + temp = next_float(temp); + return temp; + } + + GLM_FUNC_QUALIFIER float prev_float(float x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::min()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafterf(x, FLT_MIN); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafterf(x, FLT_MIN); +# else + return nextafterf(x, FLT_MIN); +# endif + } + + GLM_FUNC_QUALIFIER double prev_float(double x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::min()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return _nextafter(x, DBL_MIN); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafter(x, DBL_MIN); +# else + return nextafter(x, DBL_MIN); +# endif + } + + template + GLM_FUNC_QUALIFIER T prev_float(T x, int ULPs) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'prev_float' only accept floating-point input"); + assert(ULPs >= 0); + + T temp = x; + for (int i = 0; i < ULPs; ++i) + temp = prev_float(temp); + return temp; + } + + GLM_FUNC_QUALIFIER int float_distance(float x, float y) + { + detail::float_t const a(x); + detail::float_t const b(y); + + return abs(a.i - b.i); + } + + GLM_FUNC_QUALIFIER int64 float_distance(double x, double y) + { + detail::float_t const a(x); + detail::float_t const b(y); + + return abs(a.i - b.i); + } + + template + GLM_FUNC_QUALIFIER vec next_float(vec const& x) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = next_float(x[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec next_float(vec const& x, int ULPs) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = next_float(x[i], ULPs); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec next_float(vec const& x, vec const& ULPs) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = next_float(x[i], ULPs[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec prev_float(vec const& x) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prev_float(x[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec prev_float(vec const& x, int ULPs) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prev_float(x[i], ULPs); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec prev_float(vec const& x, vec const& ULPs) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prev_float(x[i], ULPs[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec float_distance(vec const& x, vec const& y) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = float_distance(x[i], y[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec float_distance(vec const& x, vec const& y) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = float_distance(x[i], y[i]); + return Result; + } +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/vec1.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/vec1.hpp new file mode 100644 index 0000000..63697a2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/vec1.hpp @@ -0,0 +1,30 @@ +/// @ref gtc_vec1 +/// @file glm/gtc/vec1.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_vec1 GLM_GTC_vec1 +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Add vec1, ivec1, uvec1 and bvec1 types. + +#pragma once + +// Dependency: +#include "../ext/vector_bool1.hpp" +#include "../ext/vector_bool1_precision.hpp" +#include "../ext/vector_float1.hpp" +#include "../ext/vector_float1_precision.hpp" +#include "../ext/vector_double1.hpp" +#include "../ext/vector_double1_precision.hpp" +#include "../ext/vector_int1.hpp" +#include "../ext/vector_int1_sized.hpp" +#include "../ext/vector_uint1.hpp" +#include "../ext/vector_uint1_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_vec1 extension included") +#endif + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/associated_min_max.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/associated_min_max.hpp new file mode 100644 index 0000000..435230d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/associated_min_max.hpp @@ -0,0 +1,205 @@ +/// @ref gtx_associated_min_max +/// @file glm/gtx/associated_min_max.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_associated_min_max GLM_GTX_associated_min_max +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// @brief Min and max functions that return associated values not the compared ones. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_associated_min_max is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_associated_min_max extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_associated_min_max + /// @{ + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL U associatedMin(T x, U a, T y, U b); + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + vec const& x, vec const& a, + vec const& y, vec const& b); + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + T x, const vec& a, + T y, const vec& b); + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + vec const& x, U a, + vec const& y, U b); + + /// Minimum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL U associatedMin( + T x, U a, + T y, U b, + T z, U c); + + /// Minimum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL U associatedMin( + T x, U a, + T y, U b, + T z, U c, + T w, U d); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c, + vec const& w, vec const& d); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + T x, vec const& a, + T y, vec const& b, + T z, vec const& c, + T w, vec const& d); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + vec const& x, U a, + vec const& y, U b, + vec const& z, U c, + vec const& w, U d); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL U associatedMax(T x, U a, T y, U b); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + vec const& x, vec const& a, + vec const& y, vec const& b); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + T x, vec const& a, + T y, vec const& b); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + vec const& x, U a, + vec const& y, U b); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL U associatedMax( + T x, U a, + T y, U b, + T z, U c); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + T x, vec const& a, + T y, vec const& b, + T z, vec const& c); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + vec const& x, U a, + vec const& y, U b, + vec const& z, U c); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL U associatedMax( + T x, U a, + T y, U b, + T z, U c, + T w, U d); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c, + vec const& w, vec const& d); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + T x, vec const& a, + T y, vec const& b, + T z, vec const& c, + T w, vec const& d); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + vec const& x, U a, + vec const& y, U b, + vec const& z, U c, + vec const& w, U d); + + /// @} +} //namespace glm + +#include "associated_min_max.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/associated_min_max.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/associated_min_max.inl new file mode 100644 index 0000000..f09f5bb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/associated_min_max.inl @@ -0,0 +1,354 @@ +/// @ref gtx_associated_min_max + +namespace glm{ + +// Min comparison between 2 variables +template +GLM_FUNC_QUALIFIER U associatedMin(T x, U a, T y, U b) +{ + return x < y ? a : b; +} + +template +GLM_FUNC_QUALIFIER vec associatedMin +( + vec const& x, vec const& a, + vec const& y, vec const& b +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] < y[i] ? a[i] : b[i]; + return Result; +} + +template +GLM_FUNC_QUALIFIER vec associatedMin +( + T x, const vec& a, + T y, const vec& b +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x < y ? a[i] : b[i]; + return Result; +} + +template +GLM_FUNC_QUALIFIER vec associatedMin +( + vec const& x, U a, + vec const& y, U b +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] < y[i] ? a : b; + return Result; +} + +// Min comparison between 3 variables +template +GLM_FUNC_QUALIFIER U associatedMin +( + T x, U a, + T y, U b, + T z, U c +) +{ + U Result = x < y ? (x < z ? a : c) : (y < z ? b : c); + return Result; +} + +template +GLM_FUNC_QUALIFIER vec associatedMin +( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] < y[i] ? (x[i] < z[i] ? a[i] : c[i]) : (y[i] < z[i] ? b[i] : c[i]); + return Result; +} + +// Min comparison between 4 variables +template +GLM_FUNC_QUALIFIER U associatedMin +( + T x, U a, + T y, U b, + T z, U c, + T w, U d +) +{ + T Test1 = min(x, y); + T Test2 = min(z, w); + U Result1 = x < y ? a : b; + U Result2 = z < w ? c : d; + U Result = Test1 < Test2 ? Result1 : Result2; + return Result; +} + +// Min comparison between 4 variables +template +GLM_FUNC_QUALIFIER vec associatedMin +( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c, + vec const& w, vec const& d +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + { + T Test1 = min(x[i], y[i]); + T Test2 = min(z[i], w[i]); + U Result1 = x[i] < y[i] ? a[i] : b[i]; + U Result2 = z[i] < w[i] ? c[i] : d[i]; + Result[i] = Test1 < Test2 ? Result1 : Result2; + } + return Result; +} + +// Min comparison between 4 variables +template +GLM_FUNC_QUALIFIER vec associatedMin +( + T x, vec const& a, + T y, vec const& b, + T z, vec const& c, + T w, vec const& d +) +{ + T Test1 = min(x, y); + T Test2 = min(z, w); + + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + { + U Result1 = x < y ? a[i] : b[i]; + U Result2 = z < w ? c[i] : d[i]; + Result[i] = Test1 < Test2 ? Result1 : Result2; + } + return Result; +} + +// Min comparison between 4 variables +template +GLM_FUNC_QUALIFIER vec associatedMin +( + vec const& x, U a, + vec const& y, U b, + vec const& z, U c, + vec const& w, U d +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + { + T Test1 = min(x[i], y[i]); + T Test2 = min(z[i], w[i]); + U Result1 = x[i] < y[i] ? a : b; + U Result2 = z[i] < w[i] ? c : d; + Result[i] = Test1 < Test2 ? Result1 : Result2; + } + return Result; +} + +// Max comparison between 2 variables +template +GLM_FUNC_QUALIFIER U associatedMax(T x, U a, T y, U b) +{ + return x > y ? a : b; +} + +// Max comparison between 2 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + vec const& x, vec const& a, + vec const& y, vec const& b +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] > y[i] ? a[i] : b[i]; + return Result; +} + +// Max comparison between 2 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + T x, vec const& a, + T y, vec const& b +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x > y ? a[i] : b[i]; + return Result; +} + +// Max comparison between 2 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + vec const& x, U a, + vec const& y, U b +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] > y[i] ? a : b; + return Result; +} + +// Max comparison between 3 variables +template +GLM_FUNC_QUALIFIER U associatedMax +( + T x, U a, + T y, U b, + T z, U c +) +{ + U Result = x > y ? (x > z ? a : c) : (y > z ? b : c); + return Result; +} + +// Max comparison between 3 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] > y[i] ? (x[i] > z[i] ? a[i] : c[i]) : (y[i] > z[i] ? b[i] : c[i]); + return Result; +} + +// Max comparison between 3 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + T x, vec const& a, + T y, vec const& b, + T z, vec const& c +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x > y ? (x > z ? a[i] : c[i]) : (y > z ? b[i] : c[i]); + return Result; +} + +// Max comparison between 3 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + vec const& x, U a, + vec const& y, U b, + vec const& z, U c +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] > y[i] ? (x[i] > z[i] ? a : c) : (y[i] > z[i] ? b : c); + return Result; +} + +// Max comparison between 4 variables +template +GLM_FUNC_QUALIFIER U associatedMax +( + T x, U a, + T y, U b, + T z, U c, + T w, U d +) +{ + T Test1 = max(x, y); + T Test2 = max(z, w); + U Result1 = x > y ? a : b; + U Result2 = z > w ? c : d; + U Result = Test1 > Test2 ? Result1 : Result2; + return Result; +} + +// Max comparison between 4 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c, + vec const& w, vec const& d +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + { + T Test1 = max(x[i], y[i]); + T Test2 = max(z[i], w[i]); + U Result1 = x[i] > y[i] ? a[i] : b[i]; + U Result2 = z[i] > w[i] ? c[i] : d[i]; + Result[i] = Test1 > Test2 ? Result1 : Result2; + } + return Result; +} + +// Max comparison between 4 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + T x, vec const& a, + T y, vec const& b, + T z, vec const& c, + T w, vec const& d +) +{ + T Test1 = max(x, y); + T Test2 = max(z, w); + + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + { + U Result1 = x > y ? a[i] : b[i]; + U Result2 = z > w ? c[i] : d[i]; + Result[i] = Test1 > Test2 ? Result1 : Result2; + } + return Result; +} + +// Max comparison between 4 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + vec const& x, U a, + vec const& y, U b, + vec const& z, U c, + vec const& w, U d +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + { + T Test1 = max(x[i], y[i]); + T Test2 = max(z[i], w[i]); + U Result1 = x[i] > y[i] ? a : b; + U Result2 = z[i] > w[i] ? c : d; + Result[i] = Test1 > Test2 ? Result1 : Result2; + } + return Result; +} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/bit.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/bit.hpp new file mode 100644 index 0000000..2f6b3f6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/bit.hpp @@ -0,0 +1,96 @@ +/// @ref gtx_bit +/// @file glm/gtx/bit.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_bit GLM_GTX_bit +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Allow to perform bit operations on integer values + +#pragma once + +// Dependencies +#include "../gtc/bitfield.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_bit is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_bit extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_bit + /// @{ + + /// @see gtx_bit + template + GLM_FUNC_DECL genIUType highestBitValue(genIUType Value); + + /// @see gtx_bit + template + GLM_FUNC_DECL genIUType lowestBitValue(genIUType Value); + + /// Find the highest bit set to 1 in a integer variable and return its value. + /// + /// @see gtx_bit + template + GLM_FUNC_DECL vec highestBitValue(vec const& value); + + /// Return the power of two number which value is just higher the input value. + /// Deprecated, use ceilPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template + GLM_DEPRECATED GLM_FUNC_DECL genIUType powerOfTwoAbove(genIUType Value); + + /// Return the power of two number which value is just higher the input value. + /// Deprecated, use ceilPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template + GLM_DEPRECATED GLM_FUNC_DECL vec powerOfTwoAbove(vec const& value); + + /// Return the power of two number which value is just lower the input value. + /// Deprecated, use floorPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template + GLM_DEPRECATED GLM_FUNC_DECL genIUType powerOfTwoBelow(genIUType Value); + + /// Return the power of two number which value is just lower the input value. + /// Deprecated, use floorPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template + GLM_DEPRECATED GLM_FUNC_DECL vec powerOfTwoBelow(vec const& value); + + /// Return the power of two number which value is the closet to the input value. + /// Deprecated, use roundPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template + GLM_DEPRECATED GLM_FUNC_DECL genIUType powerOfTwoNearest(genIUType Value); + + /// Return the power of two number which value is the closet to the input value. + /// Deprecated, use roundPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template + GLM_DEPRECATED GLM_FUNC_DECL vec powerOfTwoNearest(vec const& value); + + /// @} +} //namespace glm + + +#include "bit.inl" + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/bit.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/bit.inl new file mode 100644 index 0000000..621b626 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/bit.inl @@ -0,0 +1,92 @@ +/// @ref gtx_bit + +namespace glm +{ + /////////////////// + // highestBitValue + + template + GLM_FUNC_QUALIFIER genIUType highestBitValue(genIUType Value) + { + genIUType tmp = Value; + genIUType result = genIUType(0); + while(tmp) + { + result = (tmp & (~tmp + 1)); // grab lowest bit + tmp &= ~result; // clear lowest bit + } + return result; + } + + template + GLM_FUNC_QUALIFIER vec highestBitValue(vec const& v) + { + return detail::functor1::call(highestBitValue, v); + } + + /////////////////// + // lowestBitValue + + template + GLM_FUNC_QUALIFIER genIUType lowestBitValue(genIUType Value) + { + return (Value & (~Value + 1)); + } + + template + GLM_FUNC_QUALIFIER vec lowestBitValue(vec const& v) + { + return detail::functor1::call(lowestBitValue, v); + } + + /////////////////// + // powerOfTwoAbove + + template + GLM_FUNC_QUALIFIER genType powerOfTwoAbove(genType value) + { + return isPowerOfTwo(value) ? value : highestBitValue(value) << 1; + } + + template + GLM_FUNC_QUALIFIER vec powerOfTwoAbove(vec const& v) + { + return detail::functor1::call(powerOfTwoAbove, v); + } + + /////////////////// + // powerOfTwoBelow + + template + GLM_FUNC_QUALIFIER genType powerOfTwoBelow(genType value) + { + return isPowerOfTwo(value) ? value : highestBitValue(value); + } + + template + GLM_FUNC_QUALIFIER vec powerOfTwoBelow(vec const& v) + { + return detail::functor1::call(powerOfTwoBelow, v); + } + + ///////////////////// + // powerOfTwoNearest + + template + GLM_FUNC_QUALIFIER genType powerOfTwoNearest(genType value) + { + if(isPowerOfTwo(value)) + return value; + + genType const prev = highestBitValue(value); + genType const next = prev << 1; + return (next - value) < (value - prev) ? next : prev; + } + + template + GLM_FUNC_QUALIFIER vec powerOfTwoNearest(vec const& v) + { + return detail::functor1::call(powerOfTwoNearest, v); + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/closest_point.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/closest_point.hpp new file mode 100644 index 0000000..a248e4b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/closest_point.hpp @@ -0,0 +1,47 @@ +/// @ref gtx_closest_point +/// @file glm/gtx/closest_point.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_closest_point GLM_GTX_closest_point +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Find the point on a straight line which is the closet of a point. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_closest_point is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_closest_point extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_closest_point + /// @{ + + /// Find the point on a straight line which is the closet of a point. + /// @see gtx_closest_point + template + GLM_FUNC_DECL vec<3, T, Q> closestPointOnLine( + vec<3, T, Q> const& point, + vec<3, T, Q> const& a, + vec<3, T, Q> const& b); + + /// 2d lines work as well + template + GLM_FUNC_DECL vec<2, T, Q> closestPointOnLine( + vec<2, T, Q> const& point, + vec<2, T, Q> const& a, + vec<2, T, Q> const& b); + + /// @} +}// namespace glm + +#include "closest_point.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/closest_point.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/closest_point.inl new file mode 100644 index 0000000..0a39b04 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/closest_point.inl @@ -0,0 +1,45 @@ +/// @ref gtx_closest_point + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> closestPointOnLine + ( + vec<3, T, Q> const& point, + vec<3, T, Q> const& a, + vec<3, T, Q> const& b + ) + { + T LineLength = distance(a, b); + vec<3, T, Q> Vector = point - a; + vec<3, T, Q> LineDirection = (b - a) / LineLength; + + // Project Vector to LineDirection to get the distance of point from a + T Distance = dot(Vector, LineDirection); + + if(Distance <= T(0)) return a; + if(Distance >= LineLength) return b; + return a + LineDirection * Distance; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> closestPointOnLine + ( + vec<2, T, Q> const& point, + vec<2, T, Q> const& a, + vec<2, T, Q> const& b + ) + { + T LineLength = distance(a, b); + vec<2, T, Q> Vector = point - a; + vec<2, T, Q> LineDirection = (b - a) / LineLength; + + // Project Vector to LineDirection to get the distance of point from a + T Distance = dot(Vector, LineDirection); + + if(Distance <= T(0)) return a; + if(Distance >= LineLength) return b; + return a + LineDirection * Distance; + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_encoding.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_encoding.hpp new file mode 100644 index 0000000..4769e0a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_encoding.hpp @@ -0,0 +1,52 @@ +/// @ref gtx_color_encoding +/// @file glm/gtx/color_encoding.hpp +/// +/// @see core (dependence) +/// @see gtx_color_encoding (dependence) +/// +/// @defgroup gtx_color_encoding GLM_GTX_color_encoding +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// @brief Allow to perform bit operations on integer values + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../vec3.hpp" +#include + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTC_color_encoding is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_color_encoding extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_color_encoding + /// @{ + + /// Convert a linear sRGB color to D65 YUV. + template + GLM_FUNC_DECL vec<3, T, Q> convertLinearSRGBToD65XYZ(vec<3, T, Q> const& ColorLinearSRGB); + + /// Convert a linear sRGB color to D50 YUV. + template + GLM_FUNC_DECL vec<3, T, Q> convertLinearSRGBToD50XYZ(vec<3, T, Q> const& ColorLinearSRGB); + + /// Convert a D65 YUV color to linear sRGB. + template + GLM_FUNC_DECL vec<3, T, Q> convertD65XYZToLinearSRGB(vec<3, T, Q> const& ColorD65XYZ); + + /// Convert a D65 YUV color to D50 YUV. + template + GLM_FUNC_DECL vec<3, T, Q> convertD65XYZToD50XYZ(vec<3, T, Q> const& ColorD65XYZ); + + /// @} +} //namespace glm + +#include "color_encoding.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_encoding.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_encoding.inl new file mode 100644 index 0000000..e50fa3e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_encoding.inl @@ -0,0 +1,45 @@ +/// @ref gtx_color_encoding + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> convertLinearSRGBToD65XYZ(vec<3, T, Q> const& ColorLinearSRGB) + { + vec<3, T, Q> const M(0.490f, 0.17697f, 0.2f); + vec<3, T, Q> const N(0.31f, 0.8124f, 0.01063f); + vec<3, T, Q> const O(0.490f, 0.01f, 0.99f); + + return (M * ColorLinearSRGB + N * ColorLinearSRGB + O * ColorLinearSRGB) * static_cast(5.650675255693055f); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> convertLinearSRGBToD50XYZ(vec<3, T, Q> const& ColorLinearSRGB) + { + vec<3, T, Q> const M(0.436030342570117f, 0.222438466210245f, 0.013897440074263f); + vec<3, T, Q> const N(0.385101860087134f, 0.716942745571917f, 0.097076381494207f); + vec<3, T, Q> const O(0.143067806654203f, 0.060618777416563f, 0.713926257896652f); + + return M * ColorLinearSRGB + N * ColorLinearSRGB + O * ColorLinearSRGB; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> convertD65XYZToLinearSRGB(vec<3, T, Q> const& ColorD65XYZ) + { + vec<3, T, Q> const M(0.41847f, -0.091169f, 0.0009209f); + vec<3, T, Q> const N(-0.15866f, 0.25243f, 0.015708f); + vec<3, T, Q> const O(0.0009209f, -0.0025498f, 0.1786f); + + return M * ColorD65XYZ + N * ColorD65XYZ + O * ColorD65XYZ; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> convertD65XYZToD50XYZ(vec<3, T, Q> const& ColorD65XYZ) + { + vec<3, T, Q> const M(+1.047844353856414f, +0.029549007606644f, -0.009250984365223f); + vec<3, T, Q> const N(+0.022898981050086f, +0.990508028941971f, +0.015072338237051f); + vec<3, T, Q> const O(-0.050206647741605f, -0.017074711360960f, +0.751717835079977f); + + return M * ColorD65XYZ + N * ColorD65XYZ + O * ColorD65XYZ; + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space.hpp new file mode 100644 index 0000000..c39a1f4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space.hpp @@ -0,0 +1,70 @@ +/// @ref gtx_color_space +/// @file glm/gtx/color_space.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_color_space GLM_GTX_color_space +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Related to RGB to HSV conversions and operations. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_color_space is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_color_space extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_color_space + /// @{ + + /// Converts a color from HSV color space to its color in RGB color space. + /// @see gtx_color_space + template + GLM_FUNC_DECL vec<3, T, Q> rgbColor( + vec<3, T, Q> const& hsvValue); + + /// Converts a color from RGB color space to its color in HSV color space. + /// @see gtx_color_space + template + GLM_FUNC_DECL vec<3, T, Q> hsvColor( + vec<3, T, Q> const& rgbValue); + + /// Build a saturation matrix. + /// @see gtx_color_space + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> saturation( + T const s); + + /// Modify the saturation of a color. + /// @see gtx_color_space + template + GLM_FUNC_DECL vec<3, T, Q> saturation( + T const s, + vec<3, T, Q> const& color); + + /// Modify the saturation of a color. + /// @see gtx_color_space + template + GLM_FUNC_DECL vec<4, T, Q> saturation( + T const s, + vec<4, T, Q> const& color); + + /// Compute color luminosity associating ratios (0.33, 0.59, 0.11) to RGB canals. + /// @see gtx_color_space + template + GLM_FUNC_DECL T luminosity( + vec<3, T, Q> const& color); + + /// @} +}//namespace glm + +#include "color_space.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space.inl new file mode 100644 index 0000000..b3183b9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space.inl @@ -0,0 +1,144 @@ +/// @ref gtx_color_space + +#include +#include + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rgbColor(const vec<3, T, Q>& hsvColor) + { + vec<3, T, Q> hsv = hsvColor; + vec<3, T, Q> rgbColor; + + if(equal(hsv.y, static_cast(0), epsilon())) + // achromatic (grey) + rgbColor = vec<3, T, Q>(hsv.z); + else + { + T sector = floor(hsv.x * (T(1) / T(60))); + T frac = (hsv.x * (T(1) / T(60))) - sector; + // factorial part of h + T o = hsv.z * (T(1) - hsv.y); + T p = hsv.z * (T(1) - hsv.y * frac); + T q = hsv.z * (T(1) - hsv.y * (T(1) - frac)); + + switch(int(sector)) + { + default: + case 0: + rgbColor.r = hsv.z; + rgbColor.g = q; + rgbColor.b = o; + break; + case 1: + rgbColor.r = p; + rgbColor.g = hsv.z; + rgbColor.b = o; + break; + case 2: + rgbColor.r = o; + rgbColor.g = hsv.z; + rgbColor.b = q; + break; + case 3: + rgbColor.r = o; + rgbColor.g = p; + rgbColor.b = hsv.z; + break; + case 4: + rgbColor.r = q; + rgbColor.g = o; + rgbColor.b = hsv.z; + break; + case 5: + rgbColor.r = hsv.z; + rgbColor.g = o; + rgbColor.b = p; + break; + } + } + + return rgbColor; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> hsvColor(const vec<3, T, Q>& rgbColor) + { + vec<3, T, Q> hsv = rgbColor; + T Min = min(min(rgbColor.r, rgbColor.g), rgbColor.b); + T Max = max(max(rgbColor.r, rgbColor.g), rgbColor.b); + T Delta = Max - Min; + + hsv.z = Max; + + if(!equal(Max, static_cast(0), epsilon())) + { + hsv.y = Delta / hsv.z; + T h = static_cast(0); + + if(equal(rgbColor.r, Max, epsilon())) + // between yellow & magenta + h = static_cast(0) + T(60) * (rgbColor.g - rgbColor.b) / Delta; + else if(equal(rgbColor.g, Max, epsilon())) + // between cyan & yellow + h = static_cast(120) + T(60) * (rgbColor.b - rgbColor.r) / Delta; + else + // between magenta & cyan + h = static_cast(240) + T(60) * (rgbColor.r - rgbColor.g) / Delta; + + if(h < T(0)) + hsv.x = h + T(360); + else + hsv.x = h; + } + else + { + // If r = g = b = 0 then s = 0, h is undefined + hsv.y = static_cast(0); + hsv.x = static_cast(0); + } + + return hsv; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> saturation(T const s) + { + vec<3, T, defaultp> rgbw = vec<3, T, defaultp>(T(0.2126), T(0.7152), T(0.0722)); + + vec<3, T, defaultp> const col((T(1) - s) * rgbw); + + mat<4, 4, T, defaultp> result(T(1)); + result[0][0] = col.x + s; + result[0][1] = col.x; + result[0][2] = col.x; + result[1][0] = col.y; + result[1][1] = col.y + s; + result[1][2] = col.y; + result[2][0] = col.z; + result[2][1] = col.z; + result[2][2] = col.z + s; + + return result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> saturation(const T s, const vec<3, T, Q>& color) + { + return vec<3, T, Q>(saturation(s) * vec<4, T, Q>(color, T(0))); + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> saturation(const T s, const vec<4, T, Q>& color) + { + return saturation(s) * color; + } + + template + GLM_FUNC_QUALIFIER T luminosity(const vec<3, T, Q>& color) + { + const vec<3, T, Q> tmp = vec<3, T, Q>(0.33, 0.59, 0.11); + return dot(color, tmp); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space_YCoCg.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space_YCoCg.hpp new file mode 100644 index 0000000..a418037 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space_YCoCg.hpp @@ -0,0 +1,58 @@ +/// @ref gtx_color_space_YCoCg +/// @file glm/gtx/color_space_YCoCg.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_color_space_YCoCg GLM_GTX_color_space_YCoCg +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// RGB to YCoCg conversions and operations + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_color_space_YCoCg is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_color_space_YCoCg extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_color_space_YCoCg + /// @{ + + /// Convert a color from RGB color space to YCoCg color space. + /// @see gtx_color_space_YCoCg + template + GLM_FUNC_DECL vec<3, T, Q> rgb2YCoCg( + vec<3, T, Q> const& rgbColor); + + /// Convert a color from YCoCg color space to RGB color space. + /// @see gtx_color_space_YCoCg + template + GLM_FUNC_DECL vec<3, T, Q> YCoCg2rgb( + vec<3, T, Q> const& YCoCgColor); + + /// Convert a color from RGB color space to YCoCgR color space. + /// @see "YCoCg-R: A Color Space with RGB Reversibility and Low Dynamic Range" + /// @see gtx_color_space_YCoCg + template + GLM_FUNC_DECL vec<3, T, Q> rgb2YCoCgR( + vec<3, T, Q> const& rgbColor); + + /// Convert a color from YCoCgR color space to RGB color space. + /// @see "YCoCg-R: A Color Space with RGB Reversibility and Low Dynamic Range" + /// @see gtx_color_space_YCoCg + template + GLM_FUNC_DECL vec<3, T, Q> YCoCgR2rgb( + vec<3, T, Q> const& YCoCgColor); + + /// @} +}//namespace glm + +#include "color_space_YCoCg.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space_YCoCg.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space_YCoCg.inl new file mode 100644 index 0000000..83ba857 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space_YCoCg.inl @@ -0,0 +1,107 @@ +/// @ref gtx_color_space_YCoCg + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rgb2YCoCg + ( + vec<3, T, Q> const& rgbColor + ) + { + vec<3, T, Q> result; + result.x/*Y */ = rgbColor.r / T(4) + rgbColor.g / T(2) + rgbColor.b / T(4); + result.y/*Co*/ = rgbColor.r / T(2) + rgbColor.g * T(0) - rgbColor.b / T(2); + result.z/*Cg*/ = - rgbColor.r / T(4) + rgbColor.g / T(2) - rgbColor.b / T(4); + return result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> YCoCg2rgb + ( + vec<3, T, Q> const& YCoCgColor + ) + { + vec<3, T, Q> result; + result.r = YCoCgColor.x + YCoCgColor.y - YCoCgColor.z; + result.g = YCoCgColor.x + YCoCgColor.z; + result.b = YCoCgColor.x - YCoCgColor.y - YCoCgColor.z; + return result; + } + + template + class compute_YCoCgR { + public: + static GLM_FUNC_QUALIFIER vec<3, T, Q> rgb2YCoCgR + ( + vec<3, T, Q> const& rgbColor + ) + { + vec<3, T, Q> result; + result.x/*Y */ = rgbColor.g * static_cast(0.5) + (rgbColor.r + rgbColor.b) * static_cast(0.25); + result.y/*Co*/ = rgbColor.r - rgbColor.b; + result.z/*Cg*/ = rgbColor.g - (rgbColor.r + rgbColor.b) * static_cast(0.5); + return result; + } + + static GLM_FUNC_QUALIFIER vec<3, T, Q> YCoCgR2rgb + ( + vec<3, T, Q> const& YCoCgRColor + ) + { + vec<3, T, Q> result; + T tmp = YCoCgRColor.x - (YCoCgRColor.z * static_cast(0.5)); + result.g = YCoCgRColor.z + tmp; + result.b = tmp - (YCoCgRColor.y * static_cast(0.5)); + result.r = result.b + YCoCgRColor.y; + return result; + } + }; + + template + class compute_YCoCgR { + public: + static GLM_FUNC_QUALIFIER vec<3, T, Q> rgb2YCoCgR + ( + vec<3, T, Q> const& rgbColor + ) + { + vec<3, T, Q> result; + result.y/*Co*/ = rgbColor.r - rgbColor.b; + T tmp = rgbColor.b + (result.y >> 1); + result.z/*Cg*/ = rgbColor.g - tmp; + result.x/*Y */ = tmp + (result.z >> 1); + return result; + } + + static GLM_FUNC_QUALIFIER vec<3, T, Q> YCoCgR2rgb + ( + vec<3, T, Q> const& YCoCgRColor + ) + { + vec<3, T, Q> result; + T tmp = YCoCgRColor.x - (YCoCgRColor.z >> 1); + result.g = YCoCgRColor.z + tmp; + result.b = tmp - (YCoCgRColor.y >> 1); + result.r = result.b + YCoCgRColor.y; + return result; + } + }; + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rgb2YCoCgR + ( + vec<3, T, Q> const& rgbColor + ) + { + return compute_YCoCgR::is_integer>::rgb2YCoCgR(rgbColor); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> YCoCgR2rgb + ( + vec<3, T, Q> const& YCoCgRColor + ) + { + return compute_YCoCgR::is_integer>::YCoCgR2rgb(YCoCgRColor); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/common.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/common.hpp new file mode 100644 index 0000000..283f947 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/common.hpp @@ -0,0 +1,74 @@ +/// @ref gtx_common +/// @file glm/gtx/common.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_common GLM_GTX_common +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// @brief Provide functions to increase the compatibility with Cg and HLSL languages + +#pragma once + +// Dependencies: +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../gtc/vec1.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_common is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_common extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_common + /// @{ + + /// Returns true if x is a denormalized number + /// Numbers whose absolute value is too small to be represented in the normal format are represented in an alternate, denormalized format. + /// This format is less precise but can represent values closer to zero. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL isnan man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL typename genType::bool_type isdenormal(genType const& x); + + /// Similar to 'mod' but with a different rounding and integer support. + /// Returns 'x - y * trunc(x/y)' instead of 'x - y * floor(x/y)' + /// + /// @see GLSL mod vs HLSL fmod + /// @see GLSL mod man page + template + GLM_FUNC_DECL vec fmod(vec const& v); + + /// Returns whether vector components values are within an interval. A open interval excludes its endpoints, and is denoted with square brackets. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_relational + template + GLM_FUNC_DECL vec openBounded(vec const& Value, vec const& Min, vec const& Max); + + /// Returns whether vector components values are within an interval. A closed interval includes its endpoints, and is denoted with square brackets. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_relational + template + GLM_FUNC_DECL vec closeBounded(vec const& Value, vec const& Min, vec const& Max); + + /// @} +}//namespace glm + +#include "common.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/common.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/common.inl new file mode 100644 index 0000000..4575b20 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/common.inl @@ -0,0 +1,125 @@ +/// @ref gtx_common + +#include +#include "../gtc/epsilon.hpp" +#include "../gtc/constants.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_fmod + { + GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) + { + return detail::functor2::call(std::fmod, a, b); + } + }; + + template + struct compute_fmod + { + GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) + { + return a % b; + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER bool isdenormal(T const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isdenormal' only accept floating-point inputs"); + +# if GLM_HAS_CXX11_STL + return std::fpclassify(x) == FP_SUBNORMAL; +# else + return epsilonNotEqual(x, static_cast(0), epsilon()) && std::fabs(x) < std::numeric_limits::min(); +# endif + } + + template + GLM_FUNC_QUALIFIER typename vec<1, T, Q>::bool_type isdenormal + ( + vec<1, T, Q> const& x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isdenormal' only accept floating-point inputs"); + + return typename vec<1, T, Q>::bool_type( + isdenormal(x.x)); + } + + template + GLM_FUNC_QUALIFIER typename vec<2, T, Q>::bool_type isdenormal + ( + vec<2, T, Q> const& x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isdenormal' only accept floating-point inputs"); + + return typename vec<2, T, Q>::bool_type( + isdenormal(x.x), + isdenormal(x.y)); + } + + template + GLM_FUNC_QUALIFIER typename vec<3, T, Q>::bool_type isdenormal + ( + vec<3, T, Q> const& x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isdenormal' only accept floating-point inputs"); + + return typename vec<3, T, Q>::bool_type( + isdenormal(x.x), + isdenormal(x.y), + isdenormal(x.z)); + } + + template + GLM_FUNC_QUALIFIER typename vec<4, T, Q>::bool_type isdenormal + ( + vec<4, T, Q> const& x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isdenormal' only accept floating-point inputs"); + + return typename vec<4, T, Q>::bool_type( + isdenormal(x.x), + isdenormal(x.y), + isdenormal(x.z), + isdenormal(x.w)); + } + + // fmod + template + GLM_FUNC_QUALIFIER genType fmod(genType x, genType y) + { + return fmod(vec<1, genType>(x), y).x; + } + + template + GLM_FUNC_QUALIFIER vec fmod(vec const& x, T y) + { + return detail::compute_fmod::is_iec559>::call(x, vec(y)); + } + + template + GLM_FUNC_QUALIFIER vec fmod(vec const& x, vec const& y) + { + return detail::compute_fmod::is_iec559>::call(x, y); + } + + template + GLM_FUNC_QUALIFIER vec openBounded(vec const& Value, vec const& Min, vec const& Max) + { + return greaterThan(Value, Min) && lessThan(Value, Max); + } + + template + GLM_FUNC_QUALIFIER vec closeBounded(vec const& Value, vec const& Min, vec const& Max) + { + return greaterThanEqual(Value, Min) && lessThanEqual(Value, Max); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/compatibility.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/compatibility.hpp new file mode 100644 index 0000000..463f86f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/compatibility.hpp @@ -0,0 +1,131 @@ +/// @ref gtx_compatibility +/// @file glm/gtx/compatibility.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_compatibility GLM_GTX_compatibility +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Provide functions to increase the compatibility with Cg and HLSL languages + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/quaternion.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_compatibility is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_compatibility extension included") +#endif + +#if GLM_COMPILER & GLM_COMPILER_VC +# include +#elif GLM_COMPILER & GLM_COMPILER_GCC +# include +# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID) +# undef isfinite +# endif +#endif//GLM_COMPILER + +namespace glm +{ + /// @addtogroup gtx_compatibility + /// @{ + + template GLM_FUNC_QUALIFIER T lerp(T x, T y, T a){return mix(x, y, a);} //!< \brief Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<2, T, Q> lerp(const vec<2, T, Q>& x, const vec<2, T, Q>& y, T a){return mix(x, y, a);} //!< \brief Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + + template GLM_FUNC_QUALIFIER vec<3, T, Q> lerp(const vec<3, T, Q>& x, const vec<3, T, Q>& y, T a){return mix(x, y, a);} //!< \brief Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<4, T, Q> lerp(const vec<4, T, Q>& x, const vec<4, T, Q>& y, T a){return mix(x, y, a);} //!< \brief Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<2, T, Q> lerp(const vec<2, T, Q>& x, const vec<2, T, Q>& y, const vec<2, T, Q>& a){return mix(x, y, a);} //!< \brief Returns the component-wise result of x * (1.0 - a) + y * a, i.e., the linear blend of x and y using vector a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<3, T, Q> lerp(const vec<3, T, Q>& x, const vec<3, T, Q>& y, const vec<3, T, Q>& a){return mix(x, y, a);} //!< \brief Returns the component-wise result of x * (1.0 - a) + y * a, i.e., the linear blend of x and y using vector a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<4, T, Q> lerp(const vec<4, T, Q>& x, const vec<4, T, Q>& y, const vec<4, T, Q>& a){return mix(x, y, a);} //!< \brief Returns the component-wise result of x * (1.0 - a) + y * a, i.e., the linear blend of x and y using vector a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + + template GLM_FUNC_QUALIFIER T saturate(T x){return clamp(x, T(0), T(1));} //!< \brief Returns clamp(x, 0, 1) for each component in x. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<2, T, Q> saturate(const vec<2, T, Q>& x){return clamp(x, T(0), T(1));} //!< \brief Returns clamp(x, 0, 1) for each component in x. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<3, T, Q> saturate(const vec<3, T, Q>& x){return clamp(x, T(0), T(1));} //!< \brief Returns clamp(x, 0, 1) for each component in x. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<4, T, Q> saturate(const vec<4, T, Q>& x){return clamp(x, T(0), T(1));} //!< \brief Returns clamp(x, 0, 1) for each component in x. (From GLM_GTX_compatibility) + + template GLM_FUNC_QUALIFIER T atan2(T y, T x){return atan(y, x);} //!< \brief Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what quadrant the angle is in. The range of values returned by this function is [-PI, PI]. Results are undefined if x and y are both 0. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<2, T, Q> atan2(const vec<2, T, Q>& y, const vec<2, T, Q>& x){return atan(y, x);} //!< \brief Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what quadrant the angle is in. The range of values returned by this function is [-PI, PI]. Results are undefined if x and y are both 0. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<3, T, Q> atan2(const vec<3, T, Q>& y, const vec<3, T, Q>& x){return atan(y, x);} //!< \brief Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what quadrant the angle is in. The range of values returned by this function is [-PI, PI]. Results are undefined if x and y are both 0. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<4, T, Q> atan2(const vec<4, T, Q>& y, const vec<4, T, Q>& x){return atan(y, x);} //!< \brief Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what quadrant the angle is in. The range of values returned by this function is [-PI, PI]. Results are undefined if x and y are both 0. (From GLM_GTX_compatibility) + + template GLM_FUNC_DECL bool isfinite(genType const& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + template GLM_FUNC_DECL vec<1, bool, Q> isfinite(const vec<1, T, Q>& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + template GLM_FUNC_DECL vec<2, bool, Q> isfinite(const vec<2, T, Q>& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + template GLM_FUNC_DECL vec<3, bool, Q> isfinite(const vec<3, T, Q>& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + template GLM_FUNC_DECL vec<4, bool, Q> isfinite(const vec<4, T, Q>& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + + typedef bool bool1; //!< \brief boolean type with 1 component. (From GLM_GTX_compatibility extension) + typedef vec<2, bool, highp> bool2; //!< \brief boolean type with 2 components. (From GLM_GTX_compatibility extension) + typedef vec<3, bool, highp> bool3; //!< \brief boolean type with 3 components. (From GLM_GTX_compatibility extension) + typedef vec<4, bool, highp> bool4; //!< \brief boolean type with 4 components. (From GLM_GTX_compatibility extension) + + typedef bool bool1x1; //!< \brief boolean matrix with 1 x 1 component. (From GLM_GTX_compatibility extension) + typedef mat<2, 2, bool, highp> bool2x2; //!< \brief boolean matrix with 2 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 3, bool, highp> bool2x3; //!< \brief boolean matrix with 2 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 4, bool, highp> bool2x4; //!< \brief boolean matrix with 2 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 2, bool, highp> bool3x2; //!< \brief boolean matrix with 3 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 3, bool, highp> bool3x3; //!< \brief boolean matrix with 3 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 4, bool, highp> bool3x4; //!< \brief boolean matrix with 3 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 2, bool, highp> bool4x2; //!< \brief boolean matrix with 4 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 3, bool, highp> bool4x3; //!< \brief boolean matrix with 4 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 4, bool, highp> bool4x4; //!< \brief boolean matrix with 4 x 4 components. (From GLM_GTX_compatibility extension) + + typedef int int1; //!< \brief integer vector with 1 component. (From GLM_GTX_compatibility extension) + typedef vec<2, int, highp> int2; //!< \brief integer vector with 2 components. (From GLM_GTX_compatibility extension) + typedef vec<3, int, highp> int3; //!< \brief integer vector with 3 components. (From GLM_GTX_compatibility extension) + typedef vec<4, int, highp> int4; //!< \brief integer vector with 4 components. (From GLM_GTX_compatibility extension) + + typedef int int1x1; //!< \brief integer matrix with 1 component. (From GLM_GTX_compatibility extension) + typedef mat<2, 2, int, highp> int2x2; //!< \brief integer matrix with 2 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 3, int, highp> int2x3; //!< \brief integer matrix with 2 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 4, int, highp> int2x4; //!< \brief integer matrix with 2 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 2, int, highp> int3x2; //!< \brief integer matrix with 3 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 3, int, highp> int3x3; //!< \brief integer matrix with 3 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 4, int, highp> int3x4; //!< \brief integer matrix with 3 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 2, int, highp> int4x2; //!< \brief integer matrix with 4 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 3, int, highp> int4x3; //!< \brief integer matrix with 4 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 4, int, highp> int4x4; //!< \brief integer matrix with 4 x 4 components. (From GLM_GTX_compatibility extension) + + typedef float float1; //!< \brief single-qualifier floating-point vector with 1 component. (From GLM_GTX_compatibility extension) + typedef vec<2, float, highp> float2; //!< \brief single-qualifier floating-point vector with 2 components. (From GLM_GTX_compatibility extension) + typedef vec<3, float, highp> float3; //!< \brief single-qualifier floating-point vector with 3 components. (From GLM_GTX_compatibility extension) + typedef vec<4, float, highp> float4; //!< \brief single-qualifier floating-point vector with 4 components. (From GLM_GTX_compatibility extension) + + typedef float float1x1; //!< \brief single-qualifier floating-point matrix with 1 component. (From GLM_GTX_compatibility extension) + typedef mat<2, 2, float, highp> float2x2; //!< \brief single-qualifier floating-point matrix with 2 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 3, float, highp> float2x3; //!< \brief single-qualifier floating-point matrix with 2 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 4, float, highp> float2x4; //!< \brief single-qualifier floating-point matrix with 2 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 2, float, highp> float3x2; //!< \brief single-qualifier floating-point matrix with 3 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 3, float, highp> float3x3; //!< \brief single-qualifier floating-point matrix with 3 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 4, float, highp> float3x4; //!< \brief single-qualifier floating-point matrix with 3 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 2, float, highp> float4x2; //!< \brief single-qualifier floating-point matrix with 4 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 3, float, highp> float4x3; //!< \brief single-qualifier floating-point matrix with 4 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 4, float, highp> float4x4; //!< \brief single-qualifier floating-point matrix with 4 x 4 components. (From GLM_GTX_compatibility extension) + + typedef double double1; //!< \brief double-qualifier floating-point vector with 1 component. (From GLM_GTX_compatibility extension) + typedef vec<2, double, highp> double2; //!< \brief double-qualifier floating-point vector with 2 components. (From GLM_GTX_compatibility extension) + typedef vec<3, double, highp> double3; //!< \brief double-qualifier floating-point vector with 3 components. (From GLM_GTX_compatibility extension) + typedef vec<4, double, highp> double4; //!< \brief double-qualifier floating-point vector with 4 components. (From GLM_GTX_compatibility extension) + + typedef double double1x1; //!< \brief double-qualifier floating-point matrix with 1 component. (From GLM_GTX_compatibility extension) + typedef mat<2, 2, double, highp> double2x2; //!< \brief double-qualifier floating-point matrix with 2 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 3, double, highp> double2x3; //!< \brief double-qualifier floating-point matrix with 2 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 4, double, highp> double2x4; //!< \brief double-qualifier floating-point matrix with 2 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 2, double, highp> double3x2; //!< \brief double-qualifier floating-point matrix with 3 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 3, double, highp> double3x3; //!< \brief double-qualifier floating-point matrix with 3 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 4, double, highp> double3x4; //!< \brief double-qualifier floating-point matrix with 3 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 2, double, highp> double4x2; //!< \brief double-qualifier floating-point matrix with 4 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 3, double, highp> double4x3; //!< \brief double-qualifier floating-point matrix with 4 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 4, double, highp> double4x4; //!< \brief double-qualifier floating-point matrix with 4 x 4 components. (From GLM_GTX_compatibility extension) + + /// @} +}//namespace glm + +#include "compatibility.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/compatibility.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/compatibility.inl new file mode 100644 index 0000000..1d49496 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/compatibility.inl @@ -0,0 +1,62 @@ +#include + +namespace glm +{ + // isfinite + template + GLM_FUNC_QUALIFIER bool isfinite( + genType const& x) + { +# if GLM_HAS_CXX11_STL + return std::isfinite(x) != 0; +# elif GLM_COMPILER & GLM_COMPILER_VC + return _finite(x) != 0; +# elif GLM_COMPILER & GLM_COMPILER_GCC && GLM_PLATFORM & GLM_PLATFORM_ANDROID + return _isfinite(x) != 0; +# else + if (std::numeric_limits::is_integer || std::denorm_absent == std::numeric_limits::has_denorm) + return std::numeric_limits::min() <= x && std::numeric_limits::max() >= x; + else + return -std::numeric_limits::max() <= x && std::numeric_limits::max() >= x; +# endif + } + + template + GLM_FUNC_QUALIFIER vec<1, bool, Q> isfinite( + vec<1, T, Q> const& x) + { + return vec<1, bool, Q>( + isfinite(x.x)); + } + + template + GLM_FUNC_QUALIFIER vec<2, bool, Q> isfinite( + vec<2, T, Q> const& x) + { + return vec<2, bool, Q>( + isfinite(x.x), + isfinite(x.y)); + } + + template + GLM_FUNC_QUALIFIER vec<3, bool, Q> isfinite( + vec<3, T, Q> const& x) + { + return vec<3, bool, Q>( + isfinite(x.x), + isfinite(x.y), + isfinite(x.z)); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> isfinite( + vec<4, T, Q> const& x) + { + return vec<4, bool, Q>( + isfinite(x.x), + isfinite(x.y), + isfinite(x.z), + isfinite(x.w)); + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/component_wise.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/component_wise.hpp new file mode 100644 index 0000000..b1caaa2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/component_wise.hpp @@ -0,0 +1,77 @@ +/// @ref gtx_component_wise +/// @file glm/gtx/component_wise.hpp +/// @date 2007-05-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_component_wise GLM_GTX_component_wise +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Operations between components of a type + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_component_wise is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_component_wise extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_component_wise + /// @{ + + /// Convert an integer vector to a normalized float vector. + /// If the parameter value type is already a floating qualifier type, the value is passed through. + /// @see gtx_component_wise + template + GLM_FUNC_DECL vec compNormalize(vec const& v); + + /// Convert a normalized float vector to an integer vector. + /// If the parameter value type is already a floating qualifier type, the value is passed through. + /// @see gtx_component_wise + template + GLM_FUNC_DECL vec compScale(vec const& v); + + /// Add all vector components together. + /// @see gtx_component_wise + template + GLM_FUNC_DECL typename genType::value_type compAdd(genType const& v); + + /// Multiply all vector components together. + /// @see gtx_component_wise + template + GLM_FUNC_DECL typename genType::value_type compMul(genType const& v); + + /// Find the minimum value between single vector components. + /// @see gtx_component_wise + template + GLM_FUNC_DECL typename genType::value_type compMin(genType const& v); + + /// Find the maximum value between single vector components. + /// @see gtx_component_wise + template + GLM_FUNC_DECL typename genType::value_type compMax(genType const& v); + + /// Find the minimum float between single vector components. + /// @see gtx_component_wise + template + GLM_FUNC_DECL typename genType::value_type fcompMin(genType const& v); + + /// Find the maximum float between single vector components. + /// @see gtx_component_wise + template + GLM_FUNC_DECL typename genType::value_type fcompMax(genType const& v); + + /// @} +}//namespace glm + +#include "component_wise.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/component_wise.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/component_wise.inl new file mode 100644 index 0000000..f8217b2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/component_wise.inl @@ -0,0 +1,147 @@ +/// @ref gtx_component_wise + +#include "../ext/scalar_common.hpp" +#include +#include + +namespace glm{ +namespace detail +{ + template + struct compute_compNormalize + {}; + + template + struct compute_compNormalize + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + floatType const Min = static_cast(std::numeric_limits::min()); + floatType const Max = static_cast(std::numeric_limits::max()); + return (vec(v) - Min) / (Max - Min) * static_cast(2) - static_cast(1); + } + }; + + template + struct compute_compNormalize + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + return vec(v) / static_cast(std::numeric_limits::max()); + } + }; + + template + struct compute_compNormalize + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + return v; + } + }; + + template + struct compute_compScale + {}; + + template + struct compute_compScale + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + floatType const Max = static_cast(std::numeric_limits::max()) + static_cast(0.5); + vec const Scaled(v * Max); + vec const Result(Scaled - static_cast(0.5)); + return Result; + } + }; + + template + struct compute_compScale + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + return vec(vec(v) * static_cast(std::numeric_limits::max())); + } + }; + + template + struct compute_compScale + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + return v; + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER vec compNormalize(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'compNormalize' accepts only floating-point types for 'floatType' template parameter"); + + return detail::compute_compNormalize::is_integer, std::numeric_limits::is_signed>::call(v); + } + + template + GLM_FUNC_QUALIFIER vec compScale(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'compScale' accepts only floating-point types for 'floatType' template parameter"); + + return detail::compute_compScale::is_integer, std::numeric_limits::is_signed>::call(v); + } + + template + GLM_FUNC_QUALIFIER T compAdd(vec const& v) + { + T Result(0); + for(length_t i = 0, n = v.length(); i < n; ++i) + Result += v[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER T compMul(vec const& v) + { + T Result(1); + for(length_t i = 0, n = v.length(); i < n; ++i) + Result *= v[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER T compMin(vec const& v) + { + T Result(v[0]); + for(length_t i = 1, n = v.length(); i < n; ++i) + Result = min(Result, v[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER T compMax(vec const& v) + { + T Result(v[0]); + for(length_t i = 1, n = v.length(); i < n; ++i) + Result = max(Result, v[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER T fcompMin(vec const& v) + { + T Result(v[0]); + for(length_t i = 1, n = v.length(); i < n; ++i) + Result = fmin(Result, v[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER T fcompMax(vec const& v) + { + T Result(v[0]); + for(length_t i = 1, n = v.length(); i < n; ++i) + Result = fmax(Result, v[i]); + return Result; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/dual_quaternion.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/dual_quaternion.hpp new file mode 100644 index 0000000..04a6070 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/dual_quaternion.hpp @@ -0,0 +1,272 @@ +/// @ref gtx_dual_quaternion +/// @file glm/gtx/dual_quaternion.hpp +/// @author Maksim Vorobiev (msomeone@gmail.com) +/// +/// @see core (dependence) +/// @see gtc_constants (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_dual_quaternion GLM_GTX_dual_quaternion +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defines a templated dual-quaternion type and several dual-quaternion operations. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/constants.hpp" +#include "../gtc/quaternion.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_dual_quaternion is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_dual_quaternion extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_dual_quaternion + /// @{ + + template + struct tdualquat + { + // -- Implementation detail -- + + typedef T value_type; + typedef qua part_type; + + // -- Data -- + + qua real, dual; + + // -- Component accesses -- + + typedef length_t length_type; + /// Return the count of components of a dual quaternion + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 2;} + + GLM_FUNC_DECL part_type & operator[](length_type i); + GLM_FUNC_DECL part_type const& operator[](length_type i) const; + + // -- Implicit basic constructors -- + + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR tdualquat() GLM_DEFAULT; + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR tdualquat(tdualquat const& d) GLM_DEFAULT; + template + GLM_CTOR_DECL tdualquat(tdualquat const& d); + + // -- Explicit basic constructors -- + + GLM_CTOR_DECL tdualquat(qua const& real); + GLM_CTOR_DECL tdualquat(qua const& orientation, vec<3, T, Q> const& translation); + GLM_CTOR_DECL tdualquat(qua const& real, qua const& dual); + + // -- Conversion constructors -- + + template + GLM_CTOR_DECL GLM_EXPLICIT tdualquat(tdualquat const& q); + + GLM_CTOR_DECL GLM_EXPLICIT tdualquat(mat<2, 4, T, Q> const& holder_mat); + GLM_CTOR_DECL GLM_EXPLICIT tdualquat(mat<3, 4, T, Q> const& aug_mat); + + // -- Unary arithmetic operators -- + + GLM_DEFAULTED_FUNC_DECL tdualquat & operator=(tdualquat const& m) GLM_DEFAULT; + + template + GLM_FUNC_DISCARD_DECL tdualquat & operator=(tdualquat const& m); + template + GLM_FUNC_DISCARD_DECL tdualquat & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL tdualquat & operator/=(U s); + }; + + // -- Unary bit operators -- + + template + GLM_FUNC_DECL tdualquat operator+(tdualquat const& q); + + template + GLM_FUNC_DECL tdualquat operator-(tdualquat const& q); + + // -- Binary operators -- + + template + GLM_FUNC_DECL tdualquat operator+(tdualquat const& q, tdualquat const& p); + + template + GLM_FUNC_DECL tdualquat operator*(tdualquat const& q, tdualquat const& p); + + template + GLM_FUNC_DECL vec<3, T, Q> operator*(tdualquat const& q, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL vec<3, T, Q> operator*(vec<3, T, Q> const& v, tdualquat const& q); + + template + GLM_FUNC_DECL vec<4, T, Q> operator*(tdualquat const& q, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL vec<4, T, Q> operator*(vec<4, T, Q> const& v, tdualquat const& q); + + template + GLM_FUNC_DECL tdualquat operator*(tdualquat const& q, T const& s); + + template + GLM_FUNC_DECL tdualquat operator*(T const& s, tdualquat const& q); + + template + GLM_FUNC_DECL tdualquat operator/(tdualquat const& q, T const& s); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL bool operator==(tdualquat const& q1, tdualquat const& q2); + + template + GLM_FUNC_DECL bool operator!=(tdualquat const& q1, tdualquat const& q2); + + /// Creates an identity dual quaternion. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL tdualquat dual_quat_identity(); + + /// Returns the normalized quaternion. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL tdualquat normalize(tdualquat const& q); + + /// Returns the linear interpolation of two dual quaternion. + /// + /// @see gtc_dual_quaternion + template + GLM_FUNC_DECL tdualquat lerp(tdualquat const& x, tdualquat const& y, T const& a); + + /// Returns the q inverse. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL tdualquat inverse(tdualquat const& q); + + /// Converts a quaternion to a 2 * 4 matrix. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL mat<2, 4, T, Q> mat2x4_cast(tdualquat const& x); + + /// Converts a quaternion to a 3 * 4 matrix. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL mat<3, 4, T, Q> mat3x4_cast(tdualquat const& x); + + /// Converts a 2 * 4 matrix (matrix which holds real and dual parts) to a quaternion. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL tdualquat dualquat_cast(mat<2, 4, T, Q> const& x); + + /// Converts a 3 * 4 matrix (augmented matrix rotation + translation) to a quaternion. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL tdualquat dualquat_cast(mat<3, 4, T, Q> const& x); + + + /// Dual-quaternion of low single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat lowp_dualquat; + + /// Dual-quaternion of medium single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat mediump_dualquat; + + /// Dual-quaternion of high single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat highp_dualquat; + + + /// Dual-quaternion of low single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat lowp_fdualquat; + + /// Dual-quaternion of medium single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat mediump_fdualquat; + + /// Dual-quaternion of high single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat highp_fdualquat; + + + /// Dual-quaternion of low double-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat lowp_ddualquat; + + /// Dual-quaternion of medium double-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat mediump_ddualquat; + + /// Dual-quaternion of high double-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat highp_ddualquat; + + +#if(!defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + /// Dual-quaternion of floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef highp_fdualquat dualquat; + + /// Dual-quaternion of single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef highp_fdualquat fdualquat; +#elif(defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + typedef highp_fdualquat dualquat; + typedef highp_fdualquat fdualquat; +#elif(!defined(GLM_PRECISION_HIGHP_FLOAT) && defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + typedef mediump_fdualquat dualquat; + typedef mediump_fdualquat fdualquat; +#elif(!defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && defined(GLM_PRECISION_LOWP_FLOAT)) + typedef lowp_fdualquat dualquat; + typedef lowp_fdualquat fdualquat; +#else +# error "GLM error: multiple default precision requested for single-precision floating-point types" +#endif + + +#if(!defined(GLM_PRECISION_HIGHP_DOUBLE) && !defined(GLM_PRECISION_MEDIUMP_DOUBLE) && !defined(GLM_PRECISION_LOWP_DOUBLE)) + /// Dual-quaternion of default double-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef highp_ddualquat ddualquat; +#elif(defined(GLM_PRECISION_HIGHP_DOUBLE) && !defined(GLM_PRECISION_MEDIUMP_DOUBLE) && !defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef highp_ddualquat ddualquat; +#elif(!defined(GLM_PRECISION_HIGHP_DOUBLE) && defined(GLM_PRECISION_MEDIUMP_DOUBLE) && !defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef mediump_ddualquat ddualquat; +#elif(!defined(GLM_PRECISION_HIGHP_DOUBLE) && !defined(GLM_PRECISION_MEDIUMP_DOUBLE) && defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef lowp_ddualquat ddualquat; +#else +# error "GLM error: Multiple default precision requested for double-precision floating-point types" +#endif + + /// @} +} //namespace glm + +#include "dual_quaternion.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/dual_quaternion.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/dual_quaternion.inl new file mode 100644 index 0000000..3a04160 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/dual_quaternion.inl @@ -0,0 +1,352 @@ +/// @ref gtx_dual_quaternion + +#include "../geometric.hpp" +#include + +namespace glm +{ + // -- Component accesses -- + + template + GLM_FUNC_QUALIFIER typename tdualquat::part_type & tdualquat::operator[](typename tdualquat::length_type i) + { + assert(i >= 0 && i < this->length()); + return (&real)[i]; + } + + template + GLM_FUNC_QUALIFIER typename tdualquat::part_type const& tdualquat::operator[](typename tdualquat::length_type i) const + { + assert(i >= 0 && i < this->length()); + return (&real)[i]; + } + + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat() +# if GLM_CONFIG_DEFAULTED_FUNCTIONS != GLM_DISABLE + : real(qua()) + , dual(qua::wxyz(0, 0, 0, 0)) +# endif + {} + + template + GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(tdualquat const& d) + : real(d.real) + , dual(d.dual) + {} +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(tdualquat const& d) + : real(d.real) + , dual(d.dual) + {} + + // -- Explicit basic constructors -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(qua const& r) + : real(r), dual(qua::wxyz(0, 0, 0, 0)) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(qua const& q, vec<3, T, Q> const& p) + : real(q), dual(qua::wxyz( + T(-0.5) * ( p.x*q.x + p.y*q.y + p.z*q.z), + T(+0.5) * ( p.x*q.w + p.y*q.z - p.z*q.y), + T(+0.5) * (-p.x*q.z + p.y*q.w + p.z*q.x), + T(+0.5) * ( p.x*q.y - p.y*q.x + p.z*q.w))) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(qua const& r, qua const& d) + : real(r), dual(d) + {} + + // -- Conversion constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(tdualquat const& q) + : real(q.real) + , dual(q.dual) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(mat<2, 4, T, Q> const& m) + { + *this = dualquat_cast(m); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(mat<3, 4, T, Q> const& m) + { + *this = dualquat_cast(m); + } + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_FUNC_QUALIFIER tdualquat & tdualquat::operator=(tdualquat const& q) + { + this->real = q.real; + this->dual = q.dual; + return *this; + } +# endif + + template + template + GLM_FUNC_QUALIFIER tdualquat & tdualquat::operator=(tdualquat const& q) + { + this->real = q.real; + this->dual = q.dual; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER tdualquat & tdualquat::operator*=(U s) + { + this->real *= static_cast(s); + this->dual *= static_cast(s); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER tdualquat & tdualquat::operator/=(U s) + { + this->real /= static_cast(s); + this->dual /= static_cast(s); + return *this; + } + + // -- Unary bit operators -- + + template + GLM_FUNC_QUALIFIER tdualquat operator+(tdualquat const& q) + { + return q; + } + + template + GLM_FUNC_QUALIFIER tdualquat operator-(tdualquat const& q) + { + return tdualquat(-q.real, -q.dual); + } + + // -- Binary operators -- + + template + GLM_FUNC_QUALIFIER tdualquat operator+(tdualquat const& q, tdualquat const& p) + { + return tdualquat(q.real + p.real,q.dual + p.dual); + } + + template + GLM_FUNC_QUALIFIER tdualquat operator*(tdualquat const& p, tdualquat const& o) + { + return tdualquat(p.real * o.real,p.real * o.dual + p.dual * o.real); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> operator*(tdualquat const& q, vec<3, T, Q> const& v) + { + vec<3, T, Q> const real_v3(q.real.x,q.real.y,q.real.z); + vec<3, T, Q> const dual_v3(q.dual.x,q.dual.y,q.dual.z); + return (cross(real_v3, cross(real_v3,v) + v * q.real.w + dual_v3) + dual_v3 * q.real.w - real_v3 * q.dual.w) * T(2) + v; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> operator*(vec<3, T, Q> const& v, tdualquat const& q) + { + return glm::inverse(q) * v; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> operator*(tdualquat const& q, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(q * vec<3, T, Q>(v), v.w); + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> operator*(vec<4, T, Q> const& v, tdualquat const& q) + { + return glm::inverse(q) * v; + } + + template + GLM_FUNC_QUALIFIER tdualquat operator*(tdualquat const& q, T const& s) + { + return tdualquat(q.real * s, q.dual * s); + } + + template + GLM_FUNC_QUALIFIER tdualquat operator*(T const& s, tdualquat const& q) + { + return q * s; + } + + template + GLM_FUNC_QUALIFIER tdualquat operator/(tdualquat const& q, T const& s) + { + return tdualquat(q.real / s, q.dual / s); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER bool operator==(tdualquat const& q1, tdualquat const& q2) + { + return (q1.real == q2.real) && (q1.dual == q2.dual); + } + + template + GLM_FUNC_QUALIFIER bool operator!=(tdualquat const& q1, tdualquat const& q2) + { + return (q1.real != q2.real) || (q1.dual != q2.dual); + } + + // -- Operations -- + + template + GLM_FUNC_QUALIFIER tdualquat dual_quat_identity() + { + return tdualquat( + qua::wxyz(static_cast(1), static_cast(0), static_cast(0), static_cast(0)), + qua::wxyz(static_cast(0), static_cast(0), static_cast(0), static_cast(0))); + } + + template + GLM_FUNC_QUALIFIER tdualquat normalize(tdualquat const& q) + { + return q / length(q.real); + } + + template + GLM_FUNC_QUALIFIER tdualquat lerp(tdualquat const& x, tdualquat const& y, T const& a) + { + // Dual Quaternion Linear blend aka DLB: + // Lerp is only defined in [0, 1] + assert(a >= static_cast(0)); + assert(a <= static_cast(1)); + T const k = dot(x.real,y.real) < static_cast(0) ? -a : a; + T const one(1); + return tdualquat(x * (one - a) + y * k); + } + + template + GLM_FUNC_QUALIFIER tdualquat inverse(tdualquat const& q) + { + const glm::qua real = conjugate(q.real); + const glm::qua dual = conjugate(q.dual); + return tdualquat(real, dual + (real * (-2.0f * dot(real,dual)))); + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> mat2x4_cast(tdualquat const& x) + { + return mat<2, 4, T, Q>( x[0].x, x[0].y, x[0].z, x[0].w, x[1].x, x[1].y, x[1].z, x[1].w ); + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> mat3x4_cast(tdualquat const& x) + { + qua r = x.real / length2(x.real); + + qua const rr(r.w * x.real.w, r.x * x.real.x, r.y * x.real.y, r.z * x.real.z); + r *= static_cast(2); + + T const xy = r.x * x.real.y; + T const xz = r.x * x.real.z; + T const yz = r.y * x.real.z; + T const wx = r.w * x.real.x; + T const wy = r.w * x.real.y; + T const wz = r.w * x.real.z; + + vec<4, T, Q> const a( + rr.w + rr.x - rr.y - rr.z, + xy - wz, + xz + wy, + -(x.dual.w * r.x - x.dual.x * r.w + x.dual.y * r.z - x.dual.z * r.y)); + + vec<4, T, Q> const b( + xy + wz, + rr.w + rr.y - rr.x - rr.z, + yz - wx, + -(x.dual.w * r.y - x.dual.x * r.z - x.dual.y * r.w + x.dual.z * r.x)); + + vec<4, T, Q> const c( + xz - wy, + yz + wx, + rr.w + rr.z - rr.x - rr.y, + -(x.dual.w * r.z + x.dual.x * r.y - x.dual.y * r.x - x.dual.z * r.w)); + + return mat<3, 4, T, Q>(a, b, c); + } + + template + GLM_FUNC_QUALIFIER tdualquat dualquat_cast(mat<2, 4, T, Q> const& x) + { + return tdualquat( + qua::wxyz( x[0].w, x[0].x, x[0].y, x[0].z ), + qua::wxyz( x[1].w, x[1].x, x[1].y, x[1].z )); + } + + template + GLM_FUNC_QUALIFIER tdualquat dualquat_cast(mat<3, 4, T, Q> const& x) + { + qua real; + + T const trace = x[0].x + x[1].y + x[2].z; + if(trace > static_cast(0)) + { + T const r = sqrt(T(1) + trace); + T const invr = static_cast(0.5) / r; + real.w = static_cast(0.5) * r; + real.x = (x[2].y - x[1].z) * invr; + real.y = (x[0].z - x[2].x) * invr; + real.z = (x[1].x - x[0].y) * invr; + } + else if(x[0].x > x[1].y && x[0].x > x[2].z) + { + T const r = sqrt(T(1) + x[0].x - x[1].y - x[2].z); + T const invr = static_cast(0.5) / r; + real.x = static_cast(0.5)*r; + real.y = (x[1].x + x[0].y) * invr; + real.z = (x[0].z + x[2].x) * invr; + real.w = (x[2].y - x[1].z) * invr; + } + else if(x[1].y > x[2].z) + { + T const r = sqrt(T(1) + x[1].y - x[0].x - x[2].z); + T const invr = static_cast(0.5) / r; + real.x = (x[1].x + x[0].y) * invr; + real.y = static_cast(0.5) * r; + real.z = (x[2].y + x[1].z) * invr; + real.w = (x[0].z - x[2].x) * invr; + } + else + { + T const r = sqrt(T(1) + x[2].z - x[0].x - x[1].y); + T const invr = static_cast(0.5) / r; + real.x = (x[0].z + x[2].x) * invr; + real.y = (x[2].y + x[1].z) * invr; + real.z = static_cast(0.5) * r; + real.w = (x[1].x - x[0].y) * invr; + } + + qua dual; + dual.x = static_cast(0.5) * ( x[0].w * real.w + x[1].w * real.z - x[2].w * real.y); + dual.y = static_cast(0.5) * (-x[0].w * real.z + x[1].w * real.w + x[2].w * real.x); + dual.z = static_cast(0.5) * ( x[0].w * real.y - x[1].w * real.x + x[2].w * real.w); + dual.w = -static_cast(0.5) * ( x[0].w * real.x + x[1].w * real.y + x[2].w * real.z); + return tdualquat(real, dual); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/easing.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/easing.hpp new file mode 100644 index 0000000..50ed903 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/easing.hpp @@ -0,0 +1,217 @@ +/// @ref gtx_easing +/// @file glm/gtx/easing.hpp +/// @author Robert Chisholm +/// +/// @see core (dependence) +/// +/// @defgroup gtx_easing GLM_GTX_easing +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Easing functions for animations and transitions +/// All functions take a parameter x in the range [0.0,1.0] +/// +/// Based on the AHEasing project of Warren Moore (https://github.com/warrenm/AHEasing) + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/constants.hpp" +#include "../detail/qualifier.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_easing is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_easing extension included") +#endif + +namespace glm{ + /// @addtogroup gtx_easing + /// @{ + + /// Modelled after the line y = x + /// @see gtx_easing + template + GLM_FUNC_DECL genType linearInterpolation(genType const & a); + + /// Modelled after the parabola y = x^2 + /// @see gtx_easing + template + GLM_FUNC_DECL genType quadraticEaseIn(genType const & a); + + /// Modelled after the parabola y = -x^2 + 2x + /// @see gtx_easing + template + GLM_FUNC_DECL genType quadraticEaseOut(genType const & a); + + /// Modelled after the piecewise quadratic + /// y = (1/2)((2x)^2) ; [0, 0.5) + /// y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType quadraticEaseInOut(genType const & a); + + /// Modelled after the cubic y = x^3 + template + GLM_FUNC_DECL genType cubicEaseIn(genType const & a); + + /// Modelled after the cubic y = (x - 1)^3 + 1 + /// @see gtx_easing + template + GLM_FUNC_DECL genType cubicEaseOut(genType const & a); + + /// Modelled after the piecewise cubic + /// y = (1/2)((2x)^3) ; [0, 0.5) + /// y = (1/2)((2x-2)^3 + 2) ; [0.5, 1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType cubicEaseInOut(genType const & a); + + /// Modelled after the quartic x^4 + /// @see gtx_easing + template + GLM_FUNC_DECL genType quarticEaseIn(genType const & a); + + /// Modelled after the quartic y = 1 - (x - 1)^4 + /// @see gtx_easing + template + GLM_FUNC_DECL genType quarticEaseOut(genType const & a); + + /// Modelled after the piecewise quartic + /// y = (1/2)((2x)^4) ; [0, 0.5) + /// y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType quarticEaseInOut(genType const & a); + + /// Modelled after the quintic y = x^5 + /// @see gtx_easing + template + GLM_FUNC_DECL genType quinticEaseIn(genType const & a); + + /// Modelled after the quintic y = (x - 1)^5 + 1 + /// @see gtx_easing + template + GLM_FUNC_DECL genType quinticEaseOut(genType const & a); + + /// Modelled after the piecewise quintic + /// y = (1/2)((2x)^5) ; [0, 0.5) + /// y = (1/2)((2x-2)^5 + 2) ; [0.5, 1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType quinticEaseInOut(genType const & a); + + /// Modelled after quarter-cycle of sine wave + /// @see gtx_easing + template + GLM_FUNC_DECL genType sineEaseIn(genType const & a); + + /// Modelled after quarter-cycle of sine wave (different phase) + /// @see gtx_easing + template + GLM_FUNC_DECL genType sineEaseOut(genType const & a); + + /// Modelled after half sine wave + /// @see gtx_easing + template + GLM_FUNC_DECL genType sineEaseInOut(genType const & a); + + /// Modelled after shifted quadrant IV of unit circle + /// @see gtx_easing + template + GLM_FUNC_DECL genType circularEaseIn(genType const & a); + + /// Modelled after shifted quadrant II of unit circle + /// @see gtx_easing + template + GLM_FUNC_DECL genType circularEaseOut(genType const & a); + + /// Modelled after the piecewise circular function + /// y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5) + /// y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType circularEaseInOut(genType const & a); + + /// Modelled after the exponential function y = 2^(10(x - 1)) + /// @see gtx_easing + template + GLM_FUNC_DECL genType exponentialEaseIn(genType const & a); + + /// Modelled after the exponential function y = -2^(-10x) + 1 + /// @see gtx_easing + template + GLM_FUNC_DECL genType exponentialEaseOut(genType const & a); + + /// Modelled after the piecewise exponential + /// y = (1/2)2^(10(2x - 1)) ; [0,0.5) + /// y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType exponentialEaseInOut(genType const & a); + + /// Modelled after the damped sine wave y = sin(13pi/2*x)*pow(2, 10 * (x - 1)) + /// @see gtx_easing + template + GLM_FUNC_DECL genType elasticEaseIn(genType const & a); + + /// Modelled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2, -10x) + 1 + /// @see gtx_easing + template + GLM_FUNC_DECL genType elasticEaseOut(genType const & a); + + /// Modelled after the piecewise exponentially-damped sine wave: + /// y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5) + /// y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType elasticEaseInOut(genType const & a); + + /// @see gtx_easing + template + GLM_FUNC_DECL genType backEaseIn(genType const& a); + + /// @see gtx_easing + template + GLM_FUNC_DECL genType backEaseOut(genType const& a); + + /// @see gtx_easing + template + GLM_FUNC_DECL genType backEaseInOut(genType const& a); + + /// @param a parameter + /// @param o Optional overshoot modifier + /// @see gtx_easing + template + GLM_FUNC_DECL genType backEaseIn(genType const& a, genType const& o); + + /// @param a parameter + /// @param o Optional overshoot modifier + /// @see gtx_easing + template + GLM_FUNC_DECL genType backEaseOut(genType const& a, genType const& o); + + /// @param a parameter + /// @param o Optional overshoot modifier + /// @see gtx_easing + template + GLM_FUNC_DECL genType backEaseInOut(genType const& a, genType const& o); + + /// @see gtx_easing + template + GLM_FUNC_DECL genType bounceEaseIn(genType const& a); + + /// @see gtx_easing + template + GLM_FUNC_DECL genType bounceEaseOut(genType const& a); + + /// @see gtx_easing + template + GLM_FUNC_DECL genType bounceEaseInOut(genType const& a); + + /// @} +}//namespace glm + +#include "easing.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/easing.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/easing.inl new file mode 100644 index 0000000..b599c30 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/easing.inl @@ -0,0 +1,436 @@ +/// @ref gtx_easing + +#include + +namespace glm{ + + template + GLM_FUNC_QUALIFIER genType linearInterpolation(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return a; + } + + template + GLM_FUNC_QUALIFIER genType quadraticEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return a * a; + } + + template + GLM_FUNC_QUALIFIER genType quadraticEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return -(a * (a - static_cast(2))); + } + + template + GLM_FUNC_QUALIFIER genType quadraticEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + { + return static_cast(2) * a * a; + } + else + { + return (-static_cast(2) * a * a) + (4 * a) - one(); + } + } + + template + GLM_FUNC_QUALIFIER genType cubicEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return a * a * a; + } + + template + GLM_FUNC_QUALIFIER genType cubicEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + genType const f = a - one(); + return f * f * f + one(); + } + + template + GLM_FUNC_QUALIFIER genType cubicEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if (a < static_cast(0.5)) + { + return static_cast(4) * a * a * a; + } + else + { + genType const f = ((static_cast(2) * a) - static_cast(2)); + return static_cast(0.5) * f * f * f + one(); + } + } + + template + GLM_FUNC_QUALIFIER genType quarticEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return a * a * a * a; + } + + template + GLM_FUNC_QUALIFIER genType quarticEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + genType const f = (a - one()); + return f * f * f * (one() - a) + one(); + } + + template + GLM_FUNC_QUALIFIER genType quarticEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + { + return static_cast(8) * a * a * a * a; + } + else + { + genType const f = (a - one()); + return -static_cast(8) * f * f * f * f + one(); + } + } + + template + GLM_FUNC_QUALIFIER genType quinticEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return a * a * a * a * a; + } + + template + GLM_FUNC_QUALIFIER genType quinticEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + genType const f = (a - one()); + return f * f * f * f * f + one(); + } + + template + GLM_FUNC_QUALIFIER genType quinticEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + { + return static_cast(16) * a * a * a * a * a; + } + else + { + genType const f = ((static_cast(2) * a) - static_cast(2)); + return static_cast(0.5) * f * f * f * f * f + one(); + } + } + + template + GLM_FUNC_QUALIFIER genType sineEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return sin((a - one()) * half_pi()) + one(); + } + + template + GLM_FUNC_QUALIFIER genType sineEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return sin(a * half_pi()); + } + + template + GLM_FUNC_QUALIFIER genType sineEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return static_cast(0.5) * (one() - cos(a * pi())); + } + + template + GLM_FUNC_QUALIFIER genType circularEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return one() - sqrt(one() - (a * a)); + } + + template + GLM_FUNC_QUALIFIER genType circularEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return sqrt((static_cast(2) - a) * a); + } + + template + GLM_FUNC_QUALIFIER genType circularEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + { + return static_cast(0.5) * (one() - std::sqrt(one() - static_cast(4) * (a * a))); + } + else + { + return static_cast(0.5) * (std::sqrt(-((static_cast(2) * a) - static_cast(3)) * ((static_cast(2) * a) - one())) + one()); + } + } + + template + GLM_FUNC_QUALIFIER genType exponentialEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a <= zero()) + return a; + else + { + genType const Complementary = a - one(); + genType const Two = static_cast(2); + + return glm::pow(Two, Complementary * static_cast(10)); + } + } + + template + GLM_FUNC_QUALIFIER genType exponentialEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a >= one()) + return a; + else + { + return one() - glm::pow(static_cast(2), -static_cast(10) * a); + } + } + + template + GLM_FUNC_QUALIFIER genType exponentialEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + return static_cast(0.5) * glm::pow(static_cast(2), (static_cast(20) * a) - static_cast(10)); + else + return -static_cast(0.5) * glm::pow(static_cast(2), (-static_cast(20) * a) + static_cast(10)) + one(); + } + + template + GLM_FUNC_QUALIFIER genType elasticEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return std::sin(static_cast(13) * half_pi() * a) * glm::pow(static_cast(2), static_cast(10) * (a - one())); + } + + template + GLM_FUNC_QUALIFIER genType elasticEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return std::sin(-static_cast(13) * half_pi() * (a + one())) * glm::pow(static_cast(2), -static_cast(10) * a) + one(); + } + + template + GLM_FUNC_QUALIFIER genType elasticEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + return static_cast(0.5) * std::sin(static_cast(13) * half_pi() * (static_cast(2) * a)) * glm::pow(static_cast(2), static_cast(10) * ((static_cast(2) * a) - one())); + else + return static_cast(0.5) * (std::sin(-static_cast(13) * half_pi() * ((static_cast(2) * a - one()) + one())) * glm::pow(static_cast(2), -static_cast(10) * (static_cast(2) * a - one())) + static_cast(2)); + } + + template + GLM_FUNC_QUALIFIER genType backEaseIn(genType const& a, genType const& o) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + genType z = ((o + one()) * a) - o; + return (a * a * z); + } + + template + GLM_FUNC_QUALIFIER genType backEaseOut(genType const& a, genType const& o) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + genType n = a - one(); + genType z = ((o + one()) * n) + o; + return (n * n * z) + one(); + } + + template + GLM_FUNC_QUALIFIER genType backEaseInOut(genType const& a, genType const& o) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + genType s = o * static_cast(1.525); + genType x = static_cast(0.5); + genType n = a / static_cast(0.5); + + if (n < static_cast(1)) + { + genType z = ((s + static_cast(1)) * n) - s; + genType m = n * n * z; + return x * m; + } + else + { + n -= static_cast(2); + genType z = ((s + static_cast(1)) * n) + s; + genType m = (n*n*z) + static_cast(2); + return x * m; + } + } + + template + GLM_FUNC_QUALIFIER genType backEaseIn(genType const& a) + { + return backEaseIn(a, static_cast(1.70158)); + } + + template + GLM_FUNC_QUALIFIER genType backEaseOut(genType const& a) + { + return backEaseOut(a, static_cast(1.70158)); + } + + template + GLM_FUNC_QUALIFIER genType backEaseInOut(genType const& a) + { + return backEaseInOut(a, static_cast(1.70158)); + } + + template + GLM_FUNC_QUALIFIER genType bounceEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(4.0 / 11.0)) + { + return (static_cast(121) * a * a) / static_cast(16); + } + else if(a < static_cast(8.0 / 11.0)) + { + return (static_cast(363.0 / 40.0) * a * a) - (static_cast(99.0 / 10.0) * a) + static_cast(17.0 / 5.0); + } + else if(a < static_cast(9.0 / 10.0)) + { + return (static_cast(4356.0 / 361.0) * a * a) - (static_cast(35442.0 / 1805.0) * a) + static_cast(16061.0 / 1805.0); + } + else + { + return (static_cast(54.0 / 5.0) * a * a) - (static_cast(513.0 / 25.0) * a) + static_cast(268.0 / 25.0); + } + } + + template + GLM_FUNC_QUALIFIER genType bounceEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return one() - bounceEaseOut(one() - a); + } + + template + GLM_FUNC_QUALIFIER genType bounceEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + { + return static_cast(0.5) * (one() - bounceEaseOut(one() - a * static_cast(2))); + } + else + { + return static_cast(0.5) * bounceEaseOut(a * static_cast(2) - one()) + static_cast(0.5); + } + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/euler_angles.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/euler_angles.hpp new file mode 100644 index 0000000..5d67d8e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/euler_angles.hpp @@ -0,0 +1,333 @@ +/// @ref gtx_euler_angles +/// @file glm/gtx/euler_angles.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_euler_angles GLM_GTX_euler_angles +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Build matrices from Euler angles. +/// +/// Extraction of Euler angles from rotation matrix. +/// Based on the original paper 2014 Mike Day - Extracting Euler Angles from a Rotation Matrix. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_euler_angles is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_euler_angles extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_euler_angles + /// @{ + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from an euler angle X. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleX( + T const& angleX); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from an euler angle Y. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleY( + T const& angleY); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from an euler angle Z. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZ( + T const& angleZ); + + /// Creates a 3D 4 * 4 homogeneous derived matrix from the rotation matrix about X-axis. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> derivedEulerAngleX( + T const & angleX, T const & angularVelocityX); + + /// Creates a 3D 4 * 4 homogeneous derived matrix from the rotation matrix about Y-axis. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> derivedEulerAngleY( + T const & angleY, T const & angularVelocityY); + + /// Creates a 3D 4 * 4 homogeneous derived matrix from the rotation matrix about Z-axis. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> derivedEulerAngleZ( + T const & angleZ, T const & angularVelocityZ); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Y). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleXY( + T const& angleX, + T const& angleY); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleYX( + T const& angleY, + T const& angleX); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleXZ( + T const& angleX, + T const& angleZ); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * X). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZX( + T const& angle, + T const& angleX); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleYZ( + T const& angleY, + T const& angleZ); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * Y). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZY( + T const& angleZ, + T const& angleY); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Y * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleXYZ( + T const& t1, + T const& t2, + T const& t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleYXZ( + T const& yaw, + T const& pitch, + T const& roll); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Z * X). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleXZX( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Y * X). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleXYX( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X * Y). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleYXY( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * Z * Y). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleYZY( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * Y * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZYZ( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * X * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZXZ( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Z * Y). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleXZY( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * Z * X). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleYZX( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * Y * X). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZYX( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * X * Y). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZXY( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> yawPitchRoll( + T const& yaw, + T const& pitch, + T const& roll); + + /// Creates a 2D 2 * 2 rotation matrix from an euler angle. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<2, 2, T, defaultp> orientate2(T const& angle); + + /// Creates a 2D 4 * 4 homogeneous rotation matrix from an euler angle. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<3, 3, T, defaultp> orientate3(T const& angle); + + /// Creates a 3D 3 * 3 rotation matrix from euler angles (Y * X * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<3, 3, T, Q> orientate3(vec<3, T, Q> const& angles); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, Q> orientate4(vec<3, T, Q> const& angles); + + /// Extracts the (X * Y * Z) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DISCARD_DECL void extractEulerAngleXYZ(mat<4, 4, T, defaultp> const& M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Y * X * Z) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DISCARD_DECL void extractEulerAngleYXZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (X * Z * X) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DISCARD_DECL void extractEulerAngleXZX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (X * Y * X) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DISCARD_DECL void extractEulerAngleXYX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Y * X * Y) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DISCARD_DECL void extractEulerAngleYXY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Y * Z * Y) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DISCARD_DECL void extractEulerAngleYZY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Z * Y * Z) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DISCARD_DECL void extractEulerAngleZYZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Z * X * Z) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DISCARD_DECL void extractEulerAngleZXZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (X * Z * Y) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DISCARD_DECL void extractEulerAngleXZY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Y * Z * X) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DISCARD_DECL void extractEulerAngleYZX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Z * Y * X) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DISCARD_DECL void extractEulerAngleZYX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Z * X * Y) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DISCARD_DECL void extractEulerAngleZXY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// @} +}//namespace glm + +#include "euler_angles.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/euler_angles.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/euler_angles.inl new file mode 100644 index 0000000..85f22b9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/euler_angles.inl @@ -0,0 +1,899 @@ +/// @ref gtx_euler_angles + +#include "compatibility.hpp" // glm::atan2 + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleX + ( + T const& angleX + ) + { + T cosX = glm::cos(angleX); + T sinX = glm::sin(angleX); + + return mat<4, 4, T, defaultp>( + T(1), T(0), T(0), T(0), + T(0), cosX, sinX, T(0), + T(0),-sinX, cosX, T(0), + T(0), T(0), T(0), T(1)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleY + ( + T const& angleY + ) + { + T cosY = glm::cos(angleY); + T sinY = glm::sin(angleY); + + return mat<4, 4, T, defaultp>( + cosY, T(0), -sinY, T(0), + T(0), T(1), T(0), T(0), + sinY, T(0), cosY, T(0), + T(0), T(0), T(0), T(1)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZ + ( + T const& angleZ + ) + { + T cosZ = glm::cos(angleZ); + T sinZ = glm::sin(angleZ); + + return mat<4, 4, T, defaultp>( + cosZ, sinZ, T(0), T(0), + -sinZ, cosZ, T(0), T(0), + T(0), T(0), T(1), T(0), + T(0), T(0), T(0), T(1)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> derivedEulerAngleX + ( + T const & angleX, + T const & angularVelocityX + ) + { + T cosX = glm::cos(angleX) * angularVelocityX; + T sinX = glm::sin(angleX) * angularVelocityX; + + return mat<4, 4, T, defaultp>( + T(0), T(0), T(0), T(0), + T(0),-sinX, cosX, T(0), + T(0),-cosX,-sinX, T(0), + T(0), T(0), T(0), T(0)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> derivedEulerAngleY + ( + T const & angleY, + T const & angularVelocityY + ) + { + T cosY = glm::cos(angleY) * angularVelocityY; + T sinY = glm::sin(angleY) * angularVelocityY; + + return mat<4, 4, T, defaultp>( + -sinY, T(0), -cosY, T(0), + T(0), T(0), T(0), T(0), + cosY, T(0), -sinY, T(0), + T(0), T(0), T(0), T(0)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> derivedEulerAngleZ + ( + T const & angleZ, + T const & angularVelocityZ + ) + { + T cosZ = glm::cos(angleZ) * angularVelocityZ; + T sinZ = glm::sin(angleZ) * angularVelocityZ; + + return mat<4, 4, T, defaultp>( + -sinZ, cosZ, T(0), T(0), + -cosZ, -sinZ, T(0), T(0), + T(0), T(0), T(0), T(0), + T(0), T(0), T(0), T(0)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXY + ( + T const& angleX, + T const& angleY + ) + { + T cosX = glm::cos(angleX); + T sinX = glm::sin(angleX); + T cosY = glm::cos(angleY); + T sinY = glm::sin(angleY); + + return mat<4, 4, T, defaultp>( + cosY, -sinX * -sinY, cosX * -sinY, T(0), + T(0), cosX, sinX, T(0), + sinY, -sinX * cosY, cosX * cosY, T(0), + T(0), T(0), T(0), T(1)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYX + ( + T const& angleY, + T const& angleX + ) + { + T cosX = glm::cos(angleX); + T sinX = glm::sin(angleX); + T cosY = glm::cos(angleY); + T sinY = glm::sin(angleY); + + return mat<4, 4, T, defaultp>( + cosY, 0, -sinY, T(0), + sinY * sinX, cosX, cosY * sinX, T(0), + sinY * cosX, -sinX, cosY * cosX, T(0), + T(0), T(0), T(0), T(1)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXZ + ( + T const& angleX, + T const& angleZ + ) + { + return eulerAngleX(angleX) * eulerAngleZ(angleZ); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZX + ( + T const& angleZ, + T const& angleX + ) + { + return eulerAngleZ(angleZ) * eulerAngleX(angleX); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYZ + ( + T const& angleY, + T const& angleZ + ) + { + return eulerAngleY(angleY) * eulerAngleZ(angleZ); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZY + ( + T const& angleZ, + T const& angleY + ) + { + return eulerAngleZ(angleZ) * eulerAngleY(angleY); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXYZ + ( + T const& t1, + T const& t2, + T const& t3 + ) + { + T c1 = glm::cos(-t1); + T c2 = glm::cos(-t2); + T c3 = glm::cos(-t3); + T s1 = glm::sin(-t1); + T s2 = glm::sin(-t2); + T s3 = glm::sin(-t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c2 * c3; + Result[0][1] =-c1 * s3 + s1 * s2 * c3; + Result[0][2] = s1 * s3 + c1 * s2 * c3; + Result[0][3] = static_cast(0); + Result[1][0] = c2 * s3; + Result[1][1] = c1 * c3 + s1 * s2 * s3; + Result[1][2] =-s1 * c3 + c1 * s2 * s3; + Result[1][3] = static_cast(0); + Result[2][0] =-s2; + Result[2][1] = s1 * c2; + Result[2][2] = c1 * c2; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYXZ + ( + T const& yaw, + T const& pitch, + T const& roll + ) + { + T tmp_ch = glm::cos(yaw); + T tmp_sh = glm::sin(yaw); + T tmp_cp = glm::cos(pitch); + T tmp_sp = glm::sin(pitch); + T tmp_cb = glm::cos(roll); + T tmp_sb = glm::sin(roll); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb; + Result[0][1] = tmp_sb * tmp_cp; + Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb; + Result[0][3] = static_cast(0); + Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb; + Result[1][1] = tmp_cb * tmp_cp; + Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb; + Result[1][3] = static_cast(0); + Result[2][0] = tmp_sh * tmp_cp; + Result[2][1] = -tmp_sp; + Result[2][2] = tmp_ch * tmp_cp; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXZX + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c2; + Result[0][1] = c1 * s2; + Result[0][2] = s1 * s2; + Result[0][3] = static_cast(0); + Result[1][0] =-c3 * s2; + Result[1][1] = c1 * c2 * c3 - s1 * s3; + Result[1][2] = c1 * s3 + c2 * c3 * s1; + Result[1][3] = static_cast(0); + Result[2][0] = s2 * s3; + Result[2][1] =-c3 * s1 - c1 * c2 * s3; + Result[2][2] = c1 * c3 - c2 * s1 * s3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXYX + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c2; + Result[0][1] = s1 * s2; + Result[0][2] =-c1 * s2; + Result[0][3] = static_cast(0); + Result[1][0] = s2 * s3; + Result[1][1] = c1 * c3 - c2 * s1 * s3; + Result[1][2] = c3 * s1 + c1 * c2 * s3; + Result[1][3] = static_cast(0); + Result[2][0] = c3 * s2; + Result[2][1] =-c1 * s3 - c2 * c3 * s1; + Result[2][2] = c1 * c2 * c3 - s1 * s3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYXY + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c3 - c2 * s1 * s3; + Result[0][1] = s2* s3; + Result[0][2] =-c3 * s1 - c1 * c2 * s3; + Result[0][3] = static_cast(0); + Result[1][0] = s1 * s2; + Result[1][1] = c2; + Result[1][2] = c1 * s2; + Result[1][3] = static_cast(0); + Result[2][0] = c1 * s3 + c2 * c3 * s1; + Result[2][1] =-c3 * s2; + Result[2][2] = c1 * c2 * c3 - s1 * s3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYZY + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c2 * c3 - s1 * s3; + Result[0][1] = c3 * s2; + Result[0][2] =-c1 * s3 - c2 * c3 * s1; + Result[0][3] = static_cast(0); + Result[1][0] =-c1 * s2; + Result[1][1] = c2; + Result[1][2] = s1 * s2; + Result[1][3] = static_cast(0); + Result[2][0] = c3 * s1 + c1 * c2 * s3; + Result[2][1] = s2 * s3; + Result[2][2] = c1 * c3 - c2 * s1 * s3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZYZ + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c2 * c3 - s1 * s3; + Result[0][1] = c1 * s3 + c2 * c3 * s1; + Result[0][2] =-c3 * s2; + Result[0][3] = static_cast(0); + Result[1][0] =-c3 * s1 - c1 * c2 * s3; + Result[1][1] = c1 * c3 - c2 * s1 * s3; + Result[1][2] = s2 * s3; + Result[1][3] = static_cast(0); + Result[2][0] = c1 * s2; + Result[2][1] = s1 * s2; + Result[2][2] = c2; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZXZ + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c3 - c2 * s1 * s3; + Result[0][1] = c3 * s1 + c1 * c2 * s3; + Result[0][2] = s2 *s3; + Result[0][3] = static_cast(0); + Result[1][0] =-c1 * s3 - c2 * c3 * s1; + Result[1][1] = c1 * c2 * c3 - s1 * s3; + Result[1][2] = c3 * s2; + Result[1][3] = static_cast(0); + Result[2][0] = s1 * s2; + Result[2][1] =-c1 * s2; + Result[2][2] = c2; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXZY + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c2 * c3; + Result[0][1] = s1 * s3 + c1 * c3 * s2; + Result[0][2] = c3 * s1 * s2 - c1 * s3; + Result[0][3] = static_cast(0); + Result[1][0] =-s2; + Result[1][1] = c1 * c2; + Result[1][2] = c2 * s1; + Result[1][3] = static_cast(0); + Result[2][0] = c2 * s3; + Result[2][1] = c1 * s2 * s3 - c3 * s1; + Result[2][2] = c1 * c3 + s1 * s2 *s3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYZX + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c2; + Result[0][1] = s2; + Result[0][2] =-c2 * s1; + Result[0][3] = static_cast(0); + Result[1][0] = s1 * s3 - c1 * c3 * s2; + Result[1][1] = c2 * c3; + Result[1][2] = c1 * s3 + c3 * s1 * s2; + Result[1][3] = static_cast(0); + Result[2][0] = c3 * s1 + c1 * s2 * s3; + Result[2][1] =-c2 * s3; + Result[2][2] = c1 * c3 - s1 * s2 * s3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZYX + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c2; + Result[0][1] = c2 * s1; + Result[0][2] =-s2; + Result[0][3] = static_cast(0); + Result[1][0] = c1 * s2 * s3 - c3 * s1; + Result[1][1] = c1 * c3 + s1 * s2 * s3; + Result[1][2] = c2 * s3; + Result[1][3] = static_cast(0); + Result[2][0] = s1 * s3 + c1 * c3 * s2; + Result[2][1] = c3 * s1 * s2 - c1 * s3; + Result[2][2] = c2 * c3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZXY + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c3 - s1 * s2 * s3; + Result[0][1] = c3 * s1 + c1 * s2 * s3; + Result[0][2] =-c2 * s3; + Result[0][3] = static_cast(0); + Result[1][0] =-c2 * s1; + Result[1][1] = c1 * c2; + Result[1][2] = s2; + Result[1][3] = static_cast(0); + Result[2][0] = c1 * s3 + c3 * s1 * s2; + Result[2][1] = s1 * s3 - c1 * c3 * s2; + Result[2][2] = c2 * c3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> yawPitchRoll + ( + T const& yaw, + T const& pitch, + T const& roll + ) + { + T tmp_ch = glm::cos(yaw); + T tmp_sh = glm::sin(yaw); + T tmp_cp = glm::cos(pitch); + T tmp_sp = glm::sin(pitch); + T tmp_cb = glm::cos(roll); + T tmp_sb = glm::sin(roll); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb; + Result[0][1] = tmp_sb * tmp_cp; + Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb; + Result[0][3] = static_cast(0); + Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb; + Result[1][1] = tmp_cb * tmp_cp; + Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb; + Result[1][3] = static_cast(0); + Result[2][0] = tmp_sh * tmp_cp; + Result[2][1] = -tmp_sp; + Result[2][2] = tmp_ch * tmp_cp; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, defaultp> orientate2 + ( + T const& angle + ) + { + T c = glm::cos(angle); + T s = glm::sin(angle); + + mat<2, 2, T, defaultp> Result; + Result[0][0] = c; + Result[0][1] = s; + Result[1][0] = -s; + Result[1][1] = c; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, defaultp> orientate3 + ( + T const& angle + ) + { + T c = glm::cos(angle); + T s = glm::sin(angle); + + mat<3, 3, T, defaultp> Result; + Result[0][0] = c; + Result[0][1] = s; + Result[0][2] = T(0.0); + Result[1][0] = -s; + Result[1][1] = c; + Result[1][2] = T(0.0); + Result[2][0] = T(0.0); + Result[2][1] = T(0.0); + Result[2][2] = T(1.0); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> orientate3 + ( + vec<3, T, Q> const& angles + ) + { + return mat<3, 3, T, Q>(yawPitchRoll(angles.z, angles.x, angles.y)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> orientate4 + ( + vec<3, T, Q> const& angles + ) + { + return yawPitchRoll(angles.z, angles.x, angles.y); + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleXYZ(mat<4, 4, T, defaultp> const& M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[2][1], M[2][2]); + T C2 = glm::sqrt(M[0][0]*M[0][0] + M[1][0]*M[1][0]); + T T2 = glm::atan2(-M[2][0], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(S1*M[0][2] - C1*M[0][1], C1*M[1][1] - S1*M[1][2 ]); + t1 = -T1; + t2 = -T2; + t3 = -T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleYXZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[2][0], M[2][2]); + T C2 = glm::sqrt(M[0][1]*M[0][1] + M[1][1]*M[1][1]); + T T2 = glm::atan2(-M[2][1], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(S1*M[1][2] - C1*M[1][0], C1*M[0][0] - S1*M[0][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleXZX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[0][2], M[0][1]); + T S2 = glm::sqrt(M[1][0]*M[1][0] + M[2][0]*M[2][0]); + T T2 = glm::atan2(S2, M[0][0]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(C1*M[1][2] - S1*M[1][1], C1*M[2][2] - S1*M[2][1]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleXYX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[0][1], -M[0][2]); + T S2 = glm::sqrt(M[1][0]*M[1][0] + M[2][0]*M[2][0]); + T T2 = glm::atan2(S2, M[0][0]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(-C1*M[2][1] - S1*M[2][2], C1*M[1][1] + S1*M[1][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleYXY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[1][0], M[1][2]); + T S2 = glm::sqrt(M[0][1]*M[0][1] + M[2][1]*M[2][1]); + T T2 = glm::atan2(S2, M[1][1]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(C1*M[2][0] - S1*M[2][2], C1*M[0][0] - S1*M[0][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleYZY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[1][2], -M[1][0]); + T S2 = glm::sqrt(M[0][1]*M[0][1] + M[2][1]*M[2][1]); + T T2 = glm::atan2(S2, M[1][1]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(-S1*M[0][0] - C1*M[0][2], S1*M[2][0] + C1*M[2][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleZYZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[2][1], M[2][0]); + T S2 = glm::sqrt(M[0][2]*M[0][2] + M[1][2]*M[1][2]); + T T2 = glm::atan2(S2, M[2][2]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(C1*M[0][1] - S1*M[0][0], C1*M[1][1] - S1*M[1][0]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleZXZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[2][0], -M[2][1]); + T S2 = glm::sqrt(M[0][2]*M[0][2] + M[1][2]*M[1][2]); + T T2 = glm::atan2(S2, M[2][2]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(-C1*M[1][0] - S1*M[1][1], C1*M[0][0] + S1*M[0][1]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleXZY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[1][2], M[1][1]); + T C2 = glm::sqrt(M[0][0]*M[0][0] + M[2][0]*M[2][0]); + T T2 = glm::atan2(-M[1][0], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(S1*M[0][1] - C1*M[0][2], C1*M[2][2] - S1*M[2][1]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleYZX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(-M[0][2], M[0][0]); + T C2 = glm::sqrt(M[1][1]*M[1][1] + M[2][1]*M[2][1]); + T T2 = glm::atan2(M[0][1], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(S1*M[1][0] + C1*M[1][2], S1*M[2][0] + C1*M[2][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleZYX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[0][1], M[0][0]); + T C2 = glm::sqrt(M[1][2]*M[1][2] + M[2][2]*M[2][2]); + T T2 = glm::atan2(-M[0][2], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(S1*M[2][0] - C1*M[2][1], C1*M[1][1] - S1*M[1][0]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleZXY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(-M[1][0], M[1][1]); + T C2 = glm::sqrt(M[0][2]*M[0][2] + M[2][2]*M[2][2]); + T T2 = glm::atan2(M[1][2], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(C1*M[2][0] + S1*M[2][1], C1*M[0][0] + S1*M[0][1]); + t1 = T1; + t2 = T2; + t3 = T3; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extend.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extend.hpp new file mode 100644 index 0000000..46bf5e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extend.hpp @@ -0,0 +1,40 @@ +/// @ref gtx_extend +/// @file glm/gtx/extend.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_extend GLM_GTX_extend +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Extend a position from a source to a position at a defined length. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_extend is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_extend extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_extend + /// @{ + + /// Extends of Length the Origin position using the (Source - Origin) direction. + /// @see gtx_extend + template + GLM_FUNC_DECL genType extend( + genType const& Origin, + genType const& Source, + typename genType::value_type const Length); + + /// @} +}//namespace glm + +#include "extend.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extend.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extend.inl new file mode 100644 index 0000000..32128eb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extend.inl @@ -0,0 +1,48 @@ +/// @ref gtx_extend + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType extend + ( + genType const& Origin, + genType const& Source, + genType const& Distance + ) + { + return Origin + (Source - Origin) * Distance; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> extend + ( + vec<2, T, Q> const& Origin, + vec<2, T, Q> const& Source, + T const& Distance + ) + { + return Origin + (Source - Origin) * Distance; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> extend + ( + vec<3, T, Q> const& Origin, + vec<3, T, Q> const& Source, + T const& Distance + ) + { + return Origin + (Source - Origin) * Distance; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> extend + ( + vec<4, T, Q> const& Origin, + vec<4, T, Q> const& Source, + T const& Distance + ) + { + return Origin + (Source - Origin) * Distance; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extended_min_max.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extended_min_max.hpp new file mode 100644 index 0000000..e1b722f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extended_min_max.hpp @@ -0,0 +1,135 @@ +/// @ref gtx_extended_min_max +/// @file glm/gtx/extended_min_max.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_extended_min_max GLM_GTX_extended_min_max +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Min and max functions for 3 to 4 parameters. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../ext/vector_common.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_extended_min_max is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_extended_min_max extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_extended_min_max + /// @{ + + /// Return the minimum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template + GLM_FUNC_DECL T min( + T const& x, + T const& y, + T const& z); + + /// Return the minimum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C min( + C const& x, + typename C::T const& y, + typename C::T const& z); + + /// Return the minimum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C min( + C const& x, + C const& y, + C const& z); + + /// Return the minimum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template + GLM_FUNC_DECL T min( + T const& x, + T const& y, + T const& z, + T const& w); + + /// Return the minimum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C min( + C const& x, + typename C::T const& y, + typename C::T const& z, + typename C::T const& w); + + /// Return the minimum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C min( + C const& x, + C const& y, + C const& z, + C const& w); + + /// Return the maximum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template + GLM_FUNC_DECL T max( + T const& x, + T const& y, + T const& z); + + /// Return the maximum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C max( + C const& x, + typename C::T const& y, + typename C::T const& z); + + /// Return the maximum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C max( + C const& x, + C const& y, + C const& z); + + /// Return the maximum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template + GLM_FUNC_DECL T max( + T const& x, + T const& y, + T const& z, + T const& w); + + /// Return the maximum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C max( + C const& x, + typename C::T const& y, + typename C::T const& z, + typename C::T const& w); + + /// Return the maximum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C max( + C const& x, + C const& y, + C const& z, + C const& w); + + /// @} +}//namespace glm + +#include "extended_min_max.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extended_min_max.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extended_min_max.inl new file mode 100644 index 0000000..de5998f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extended_min_max.inl @@ -0,0 +1,138 @@ +/// @ref gtx_extended_min_max + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T min( + T const& x, + T const& y, + T const& z) + { + return glm::min(glm::min(x, y), z); + } + + template class C> + GLM_FUNC_QUALIFIER C min + ( + C const& x, + typename C::T const& y, + typename C::T const& z + ) + { + return glm::min(glm::min(x, y), z); + } + + template class C> + GLM_FUNC_QUALIFIER C min + ( + C const& x, + C const& y, + C const& z + ) + { + return glm::min(glm::min(x, y), z); + } + + template + GLM_FUNC_QUALIFIER T min + ( + T const& x, + T const& y, + T const& z, + T const& w + ) + { + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template class C> + GLM_FUNC_QUALIFIER C min + ( + C const& x, + typename C::T const& y, + typename C::T const& z, + typename C::T const& w + ) + { + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template class C> + GLM_FUNC_QUALIFIER C min + ( + C const& x, + C const& y, + C const& z, + C const& w + ) + { + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template + GLM_FUNC_QUALIFIER T max( + T const& x, + T const& y, + T const& z) + { + return glm::max(glm::max(x, y), z); + } + + template class C> + GLM_FUNC_QUALIFIER C max + ( + C const& x, + typename C::T const& y, + typename C::T const& z + ) + { + return glm::max(glm::max(x, y), z); + } + + template class C> + GLM_FUNC_QUALIFIER C max + ( + C const& x, + C const& y, + C const& z + ) + { + return glm::max(glm::max(x, y), z); + } + + template + GLM_FUNC_QUALIFIER T max + ( + T const& x, + T const& y, + T const& z, + T const& w + ) + { + return glm::max(glm::max(x, y), glm::max(z, w)); + } + + template class C> + GLM_FUNC_QUALIFIER C max + ( + C const& x, + typename C::T const& y, + typename C::T const& z, + typename C::T const& w + ) + { + return glm::max(glm::max(x, y), glm::max(z, w)); + } + + template class C> + GLM_FUNC_QUALIFIER C max + ( + C const& x, + C const& y, + C const& z, + C const& w + ) + { + return glm::max(glm::max(x, y), glm::max(z, w)); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/exterior_product.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/exterior_product.hpp new file mode 100644 index 0000000..1979acc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/exterior_product.hpp @@ -0,0 +1,43 @@ +/// @ref gtx_exterior_product +/// @file glm/gtx/exterior_product.hpp +/// +/// @see core (dependence) +/// @see gtx_exterior_product (dependence) +/// +/// @defgroup gtx_exterior_product GLM_GTX_exterior_product +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// @brief Allow to perform bit operations on integer values + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_exterior_product is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_exterior_product extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_exterior_product + /// @{ + + /// Returns the cross product of x and y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see Exterior product + template + GLM_FUNC_DECL GLM_CONSTEXPR T cross(vec<2, T, Q> const& v, vec<2, T, Q> const& u); + + /// @} +} //namespace glm + +#include "exterior_product.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/exterior_product.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/exterior_product.inl new file mode 100644 index 0000000..690085d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/exterior_product.inl @@ -0,0 +1,26 @@ +/// @ref gtx_exterior_product + +#include + +namespace glm { +namespace detail +{ + template + struct compute_cross_vec2 + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(vec<2, T, Q> const& v, vec<2, T, Q> const& u) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'cross' accepts only floating-point inputs"); + + return v.x * u.y - u.x * v.y; + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T cross(vec<2, T, Q> const& x, vec<2, T, Q> const& y) + { + return detail::compute_cross_vec2::value>::call(x, y); + } +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_exponential.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_exponential.hpp new file mode 100644 index 0000000..9fae325 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_exponential.hpp @@ -0,0 +1,93 @@ +/// @ref gtx_fast_exponential +/// @file glm/gtx/fast_exponential.hpp +/// +/// @see core (dependence) +/// @see gtx_half_float (dependence) +/// +/// @defgroup gtx_fast_exponential GLM_GTX_fast_exponential +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Fast but less accurate implementations of exponential based functions. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_fast_exponential is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_fast_exponential extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_fast_exponential + /// @{ + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL genType fastPow(genType x, genType y); + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL vec fastPow(vec const& x, vec const& y); + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL genTypeT fastPow(genTypeT x, genTypeU y); + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL vec fastPow(vec const& x); + + /// Faster than the common exp function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL T fastExp(T x); + + /// Faster than the common exp function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL vec fastExp(vec const& x); + + /// Faster than the common log function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL T fastLog(T x); + + /// Faster than the common exp2 function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL vec fastLog(vec const& x); + + /// Faster than the common exp2 function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL T fastExp2(T x); + + /// Faster than the common exp2 function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL vec fastExp2(vec const& x); + + /// Faster than the common log2 function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL T fastLog2(T x); + + /// Faster than the common log2 function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL vec fastLog2(vec const& x); + + /// @} +}//namespace glm + +#include "fast_exponential.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_exponential.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_exponential.inl new file mode 100644 index 0000000..5b11742 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_exponential.inl @@ -0,0 +1,136 @@ +/// @ref gtx_fast_exponential + +namespace glm +{ + // fastPow: + template + GLM_FUNC_QUALIFIER genType fastPow(genType x, genType y) + { + return exp(y * log(x)); + } + + template + GLM_FUNC_QUALIFIER vec fastPow(vec const& x, vec const& y) + { + return exp(y * log(x)); + } + + template + GLM_FUNC_QUALIFIER T fastPow(T x, int y) + { + T f = static_cast(1); + for(int i = 0; i < y; ++i) + f *= x; + return f; + } + + template + GLM_FUNC_QUALIFIER vec fastPow(vec const& x, vec const& y) + { + vec Result; + for(length_t i = 0, n = x.length(); i < n; ++i) + Result[i] = fastPow(x[i], y[i]); + return Result; + } + + // fastExp + // Note: This function provides accurate results only for value between -1 and 1, else avoid it. + template + GLM_FUNC_QUALIFIER T fastExp(T x) + { + // This has a better looking and same performance in release mode than the following code. However, in debug mode it's slower. + // return 1.0f + x * (1.0f + x * 0.5f * (1.0f + x * 0.3333333333f * (1.0f + x * 0.25 * (1.0f + x * 0.2f)))); + T x2 = x * x; + T x3 = x2 * x; + T x4 = x3 * x; + T x5 = x4 * x; + return T(1) + x + (x2 * T(0.5)) + (x3 * T(0.1666666667)) + (x4 * T(0.041666667)) + (x5 * T(0.008333333333)); + } + /* // Try to handle all values of float... but often shower than std::exp, glm::floor and the loop kill the performance + GLM_FUNC_QUALIFIER float fastExp(float x) + { + const float e = 2.718281828f; + const float IntegerPart = floor(x); + const float FloatPart = x - IntegerPart; + float z = 1.f; + + for(int i = 0; i < int(IntegerPart); ++i) + z *= e; + + const float x2 = FloatPart * FloatPart; + const float x3 = x2 * FloatPart; + const float x4 = x3 * FloatPart; + const float x5 = x4 * FloatPart; + return z * (1.0f + FloatPart + (x2 * 0.5f) + (x3 * 0.1666666667f) + (x4 * 0.041666667f) + (x5 * 0.008333333333f)); + } + + // Increase accuracy on number bigger that 1 and smaller than -1 but it's not enough for high and negative numbers + GLM_FUNC_QUALIFIER float fastExp(float x) + { + // This has a better looking and same performance in release mode than the following code. However, in debug mode it's slower. + // return 1.0f + x * (1.0f + x * 0.5f * (1.0f + x * 0.3333333333f * (1.0f + x * 0.25 * (1.0f + x * 0.2f)))); + float x2 = x * x; + float x3 = x2 * x; + float x4 = x3 * x; + float x5 = x4 * x; + float x6 = x5 * x; + float x7 = x6 * x; + float x8 = x7 * x; + return 1.0f + x + (x2 * 0.5f) + (x3 * 0.1666666667f) + (x4 * 0.041666667f) + (x5 * 0.008333333333f)+ (x6 * 0.00138888888888f) + (x7 * 0.000198412698f) + (x8 * 0.0000248015873f);; + } + */ + + template + GLM_FUNC_QUALIFIER vec fastExp(vec const& x) + { + return detail::functor1::call(fastExp, x); + } + + // fastLog + template + GLM_FUNC_QUALIFIER genType fastLog(genType x) + { + return std::log(x); + } + + /* Slower than the VC7.1 function... + GLM_FUNC_QUALIFIER float fastLog(float x) + { + float y1 = (x - 1.0f) / (x + 1.0f); + float y2 = y1 * y1; + return 2.0f * y1 * (1.0f + y2 * (0.3333333333f + y2 * (0.2f + y2 * 0.1428571429f))); + } + */ + + template + GLM_FUNC_QUALIFIER vec fastLog(vec const& x) + { + return detail::functor1::call(fastLog, x); + } + + //fastExp2, ln2 = 0.69314718055994530941723212145818f + template + GLM_FUNC_QUALIFIER genType fastExp2(genType x) + { + return fastExp(static_cast(0.69314718055994530941723212145818) * x); + } + + template + GLM_FUNC_QUALIFIER vec fastExp2(vec const& x) + { + return detail::functor1::call(fastExp2, x); + } + + // fastLog2, ln2 = 0.69314718055994530941723212145818f + template + GLM_FUNC_QUALIFIER genType fastLog2(genType x) + { + return fastLog(x) / static_cast(0.69314718055994530941723212145818); + } + + template + GLM_FUNC_QUALIFIER vec fastLog2(vec const& x) + { + return detail::functor1::call(fastLog2, x); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_square_root.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_square_root.hpp new file mode 100644 index 0000000..80729db --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_square_root.hpp @@ -0,0 +1,96 @@ +/// @ref gtx_fast_square_root +/// @file glm/gtx/fast_square_root.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_fast_square_root GLM_GTX_fast_square_root +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Fast but less accurate implementations of square root based functions. +/// - Sqrt optimisation based on Newton's method, +/// www.gamedev.net/community/forums/topic.asp?topic id=139956 + +#pragma once + +// Dependency: +#include "../common.hpp" +#include "../exponential.hpp" +#include "../geometric.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_fast_square_root is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_fast_square_root extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_fast_square_root + /// @{ + + /// Faster than the common sqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL genType fastSqrt(genType x); + + /// Faster than the common sqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL vec fastSqrt(vec const& x); + + /// Faster than the common inversesqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL genType fastInverseSqrt(genType x); + + /// Faster than the common inversesqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL vec fastInverseSqrt(vec const& x); + + /// Faster than the common length function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL genType fastLength(genType x); + + /// Faster than the common length function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL T fastLength(vec const& x); + + /// Faster than the common distance function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL genType fastDistance(genType x, genType y); + + /// Faster than the common distance function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL T fastDistance(vec const& x, vec const& y); + + /// Faster than the common normalize function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL genType fastNormalize(genType x); + + /// Faster than the common normalize function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL vec fastNormalize(vec const& x); + + /// @} +}// namespace glm + +#include "fast_square_root.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_square_root.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_square_root.inl new file mode 100644 index 0000000..60fdb7a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_square_root.inl @@ -0,0 +1,75 @@ +/// @ref gtx_fast_square_root + +namespace glm +{ + // fastSqrt + template + GLM_FUNC_QUALIFIER genType fastSqrt(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'fastSqrt' only accept floating-point input"); + + return genType(1) / fastInverseSqrt(x); + } + + template + GLM_FUNC_QUALIFIER vec fastSqrt(vec const& x) + { + return detail::functor1::call(fastSqrt, x); + } + + // fastInversesqrt + template + GLM_FUNC_QUALIFIER genType fastInverseSqrt(genType x) + { + return detail::compute_inversesqrt<1, genType, lowp, detail::is_aligned::value>::call(vec<1, genType, lowp>(x)).x; + } + + template + GLM_FUNC_QUALIFIER vec fastInverseSqrt(vec const& x) + { + return detail::compute_inversesqrt::value>::call(x); + } + + // fastLength + template + GLM_FUNC_QUALIFIER genType fastLength(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'fastLength' only accept floating-point inputs"); + + return abs(x); + } + + template + GLM_FUNC_QUALIFIER T fastLength(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'fastLength' only accept floating-point inputs"); + + return fastSqrt(dot(x, x)); + } + + // fastDistance + template + GLM_FUNC_QUALIFIER genType fastDistance(genType x, genType y) + { + return fastLength(y - x); + } + + template + GLM_FUNC_QUALIFIER T fastDistance(vec const& x, vec const& y) + { + return fastLength(y - x); + } + + // fastNormalize + template + GLM_FUNC_QUALIFIER genType fastNormalize(genType x) + { + return x > genType(0) ? genType(1) : -genType(1); + } + + template + GLM_FUNC_QUALIFIER vec fastNormalize(vec const& x) + { + return x * fastInverseSqrt(dot(x, x)); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_trigonometry.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_trigonometry.hpp new file mode 100644 index 0000000..93acab5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_trigonometry.hpp @@ -0,0 +1,77 @@ +/// @ref gtx_fast_trigonometry +/// @file glm/gtx/fast_trigonometry.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_fast_trigonometry GLM_GTX_fast_trigonometry +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Fast but less accurate implementations of trigonometric functions. + +#pragma once + +// Dependency: +#include "../gtc/constants.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_fast_trigonometry is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_fast_trigonometry extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_fast_trigonometry + /// @{ + + /// Wrap an angle to [0 2pi[ + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T wrapAngle(T angle); + + /// Faster than the common sin function but less accurate. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastSin(T angle); + + /// Faster than the common cos function but less accurate. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastCos(T angle); + + /// Faster than the common tan function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastTan(T angle); + + /// Faster than the common asin function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastAsin(T angle); + + /// Faster than the common acos function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastAcos(T angle); + + /// Faster than the common atan function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastAtan(T y, T x); + + /// Faster than the common atan function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastAtan(T angle); + + /// @} +}//namespace glm + +#include "fast_trigonometry.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_trigonometry.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_trigonometry.inl new file mode 100644 index 0000000..1a710cb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_trigonometry.inl @@ -0,0 +1,142 @@ +/// @ref gtx_fast_trigonometry + +namespace glm{ +namespace detail +{ + template + GLM_FUNC_QUALIFIER vec taylorCos(vec const& x) + { + return static_cast(1) + - (x * x) * (1.f / 2.f) + + ((x * x) * (x * x)) * (1.f / 24.f) + - (((x * x) * (x * x)) * (x * x)) * (1.f / 720.f) + + (((x * x) * (x * x)) * ((x * x) * (x * x))) * (1.f / 40320.f); + } + + template + GLM_FUNC_QUALIFIER T cos_52s(T x) + { + T const xx(x * x); + return (T(0.9999932946) + xx * (T(-0.4999124376) + xx * (T(0.0414877472) + xx * T(-0.0012712095)))); + } + + template + GLM_FUNC_QUALIFIER vec cos_52s(vec const& x) + { + return detail::functor1::call(cos_52s, x); + } +}//namespace detail + + // wrapAngle + template + GLM_FUNC_QUALIFIER T wrapAngle(T angle) + { + return abs(mod(angle, two_pi())); + } + + template + GLM_FUNC_QUALIFIER vec wrapAngle(vec const& x) + { + return detail::functor1::call(wrapAngle, x); + } + + // cos + template + GLM_FUNC_QUALIFIER T fastCos(T x) + { + T const angle(wrapAngle(x)); + + if(angle < half_pi()) + return detail::cos_52s(angle); + if(angle < pi()) + return -detail::cos_52s(pi() - angle); + if(angle < (T(3) * half_pi())) + return -detail::cos_52s(angle - pi()); + + return detail::cos_52s(two_pi() - angle); + } + + template + GLM_FUNC_QUALIFIER vec fastCos(vec const& x) + { + return detail::functor1::call(fastCos, x); + } + + // sin + template + GLM_FUNC_QUALIFIER T fastSin(T x) + { + return fastCos(half_pi() - x); + } + + template + GLM_FUNC_QUALIFIER vec fastSin(vec const& x) + { + return detail::functor1::call(fastSin, x); + } + + // tan + template + GLM_FUNC_QUALIFIER T fastTan(T x) + { + return x + (x * x * x * T(0.3333333333)) + (x * x * x * x * x * T(0.1333333333333)) + (x * x * x * x * x * x * x * T(0.0539682539)); + } + + template + GLM_FUNC_QUALIFIER vec fastTan(vec const& x) + { + return detail::functor1::call(fastTan, x); + } + + // asin + template + GLM_FUNC_QUALIFIER T fastAsin(T x) + { + return x + (x * x * x * T(0.166666667)) + (x * x * x * x * x * T(0.075)) + (x * x * x * x * x * x * x * T(0.0446428571)) + (x * x * x * x * x * x * x * x * x * T(0.0303819444));// + (x * x * x * x * x * x * x * x * x * x * x * T(0.022372159)); + } + + template + GLM_FUNC_QUALIFIER vec fastAsin(vec const& x) + { + return detail::functor1::call(fastAsin, x); + } + + // acos + template + GLM_FUNC_QUALIFIER T fastAcos(T x) + { + return T(1.5707963267948966192313216916398) - fastAsin(x); //(PI / 2) + } + + template + GLM_FUNC_QUALIFIER vec fastAcos(vec const& x) + { + return detail::functor1::call(fastAcos, x); + } + + // atan + template + GLM_FUNC_QUALIFIER T fastAtan(T y, T x) + { + T sgn = sign(y) * sign(x); + return abs(fastAtan(y / x)) * sgn; + } + + template + GLM_FUNC_QUALIFIER vec fastAtan(vec const& y, vec const& x) + { + return detail::functor2::call(fastAtan, y, x); + } + + template + GLM_FUNC_QUALIFIER T fastAtan(T x) + { + return x - (x * x * x * T(0.333333333333)) + (x * x * x * x * x * T(0.2)) - (x * x * x * x * x * x * x * T(0.1428571429)) + (x * x * x * x * x * x * x * x * x * T(0.111111111111)) - (x * x * x * x * x * x * x * x * x * x * x * T(0.0909090909)); + } + + template + GLM_FUNC_QUALIFIER vec fastAtan(vec const& x) + { + return detail::functor1::call(fastAtan, x); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/float_notmalize.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/float_notmalize.inl new file mode 100644 index 0000000..8cdbc5a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/float_notmalize.inl @@ -0,0 +1,13 @@ +/// @ref gtx_float_normalize + +#include + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec floatNormalize(vec const& v) + { + return vec(v) / static_cast(std::numeric_limits::max()); + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/functions.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/functions.hpp new file mode 100644 index 0000000..df68a0d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/functions.hpp @@ -0,0 +1,54 @@ +/// @ref gtx_functions +/// @file glm/gtx/functions.hpp +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_functions GLM_GTX_functions +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// List of useful common functions. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/type_vec2.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_functions is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_functions extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_functions + /// @{ + + /// 1D gauss function + /// + /// @see gtc_epsilon + template + GLM_FUNC_DECL T gauss( + T x, + T ExpectedValue, + T StandardDeviation); + + /// 2D gauss function + /// + /// @see gtc_epsilon + template + GLM_FUNC_DECL T gauss( + vec<2, T, Q> const& Coord, + vec<2, T, Q> const& ExpectedValue, + vec<2, T, Q> const& StandardDeviation); + + /// @} +}//namespace glm + +#include "functions.inl" + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/functions.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/functions.inl new file mode 100644 index 0000000..29cbb20 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/functions.inl @@ -0,0 +1,30 @@ +/// @ref gtx_functions + +#include "../exponential.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T gauss + ( + T x, + T ExpectedValue, + T StandardDeviation + ) + { + return exp(-((x - ExpectedValue) * (x - ExpectedValue)) / (static_cast(2) * StandardDeviation * StandardDeviation)) / (StandardDeviation * sqrt(static_cast(6.28318530717958647692528676655900576))); + } + + template + GLM_FUNC_QUALIFIER T gauss + ( + vec<2, T, Q> const& Coord, + vec<2, T, Q> const& ExpectedValue, + vec<2, T, Q> const& StandardDeviation + ) + { + vec<2, T, Q> const Squared = ((Coord - ExpectedValue) * (Coord - ExpectedValue)) / (static_cast(2) * StandardDeviation * StandardDeviation); + return exp(-(Squared.x + Squared.y)); + } +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/gradient_paint.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/gradient_paint.hpp new file mode 100644 index 0000000..5656445 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/gradient_paint.hpp @@ -0,0 +1,51 @@ +/// @ref gtx_gradient_paint +/// @file glm/gtx/gradient_paint.hpp +/// +/// @see core (dependence) +/// @see gtx_optimum_pow (dependence) +/// +/// @defgroup gtx_gradient_paint GLM_GTX_gradient_paint +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Functions that return the color of procedural gradient for specific coordinates. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/optimum_pow.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_gradient_paint is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_gradient_paint extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_gradient_paint + /// @{ + + /// Return a color from a radial gradient. + /// @see - gtx_gradient_paint + template + GLM_FUNC_DECL T radialGradient( + vec<2, T, Q> const& Center, + T const& Radius, + vec<2, T, Q> const& Focal, + vec<2, T, Q> const& Position); + + /// Return a color from a linear gradient. + /// @see - gtx_gradient_paint + template + GLM_FUNC_DECL T linearGradient( + vec<2, T, Q> const& Point0, + vec<2, T, Q> const& Point1, + vec<2, T, Q> const& Position); + + /// @} +}// namespace glm + +#include "gradient_paint.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/gradient_paint.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/gradient_paint.inl new file mode 100644 index 0000000..4c495e6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/gradient_paint.inl @@ -0,0 +1,36 @@ +/// @ref gtx_gradient_paint + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T radialGradient + ( + vec<2, T, Q> const& Center, + T const& Radius, + vec<2, T, Q> const& Focal, + vec<2, T, Q> const& Position + ) + { + vec<2, T, Q> F = Focal - Center; + vec<2, T, Q> D = Position - Focal; + T Radius2 = pow2(Radius); + T Fx2 = pow2(F.x); + T Fy2 = pow2(F.y); + + T Numerator = (D.x * F.x + D.y * F.y) + sqrt(Radius2 * (pow2(D.x) + pow2(D.y)) - pow2(D.x * F.y - D.y * F.x)); + T Denominator = Radius2 - (Fx2 + Fy2); + return Numerator / Denominator; + } + + template + GLM_FUNC_QUALIFIER T linearGradient + ( + vec<2, T, Q> const& Point0, + vec<2, T, Q> const& Point1, + vec<2, T, Q> const& Position + ) + { + vec<2, T, Q> Dist = Point1 - Point0; + return (Dist.x * (Position.x - Point0.x) + Dist.y * (Position.y - Point0.y)) / glm::dot(Dist, Dist); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/handed_coordinate_space.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/handed_coordinate_space.hpp new file mode 100644 index 0000000..7c2aada --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/handed_coordinate_space.hpp @@ -0,0 +1,48 @@ +/// @ref gtx_handed_coordinate_space +/// @file glm/gtx/handed_coordinate_space.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_handed_coordinate_space GLM_GTX_handed_coordinate_space +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// To know if a set of three basis vectors defines a right or left-handed coordinate system. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_handed_coordinate_space is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_handed_coordinate_space extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_handed_coordinate_space + /// @{ + + //! Return if a trihedron right handed or not. + //! From GLM_GTX_handed_coordinate_space extension. + template + GLM_FUNC_DECL bool rightHanded( + vec<3, T, Q> const& tangent, + vec<3, T, Q> const& binormal, + vec<3, T, Q> const& normal); + + //! Return if a trihedron left handed or not. + //! From GLM_GTX_handed_coordinate_space extension. + template + GLM_FUNC_DECL bool leftHanded( + vec<3, T, Q> const& tangent, + vec<3, T, Q> const& binormal, + vec<3, T, Q> const& normal); + + /// @} +}// namespace glm + +#include "handed_coordinate_space.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/handed_coordinate_space.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/handed_coordinate_space.inl new file mode 100644 index 0000000..e43c17b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/handed_coordinate_space.inl @@ -0,0 +1,26 @@ +/// @ref gtx_handed_coordinate_space + +namespace glm +{ + template + GLM_FUNC_QUALIFIER bool rightHanded + ( + vec<3, T, Q> const& tangent, + vec<3, T, Q> const& binormal, + vec<3, T, Q> const& normal + ) + { + return dot(cross(normal, tangent), binormal) > T(0); + } + + template + GLM_FUNC_QUALIFIER bool leftHanded + ( + vec<3, T, Q> const& tangent, + vec<3, T, Q> const& binormal, + vec<3, T, Q> const& normal + ) + { + return dot(cross(normal, tangent), binormal) < T(0); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/hash.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/hash.hpp new file mode 100644 index 0000000..ef89290 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/hash.hpp @@ -0,0 +1,146 @@ +/// @ref gtx_hash +/// @file glm/gtx/hash.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_hash GLM_GTX_hash +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Add std::hash support for glm types + +#pragma once + +#if defined(GLM_FORCE_MESSAGES) && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_hash is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_hash extension included") +# endif +#endif + +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../gtc/vec1.hpp" + +#include "../gtc/quaternion.hpp" +#include "../gtx/dual_quaternion.hpp" + +#include "../mat2x2.hpp" +#include "../mat2x3.hpp" +#include "../mat2x4.hpp" + +#include "../mat3x2.hpp" +#include "../mat3x3.hpp" +#include "../mat3x4.hpp" + +#include "../mat4x2.hpp" +#include "../mat4x3.hpp" +#include "../mat4x4.hpp" + +#if __cplusplus < 201103L +#pragma message("GLM_GTX_hash requires C++11 standard library support") +#endif + +#if GLM_LANG & GLM_LANG_CXX11 +#define GLM_GTX_hash 1 +#include + +namespace std +{ + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::vec<1, T, Q> const& v) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::vec<2, T, Q> const& v) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::vec<3, T, Q> const& v) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::vec<4, T, Q> const& v) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::qua const& q) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::tdualquat const& q) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<2, 2, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<2, 3, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<2, 4, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<3, 2, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<3, 3, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<3, 4, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<4, 2, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<4, 3, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<4, 4, T,Q> const& m) const GLM_NOEXCEPT; + }; +} // namespace std + +#include "hash.inl" + +#endif //GLM_LANG & GLM_LANG_CXX11 diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/hash.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/hash.inl new file mode 100644 index 0000000..bcadfe5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/hash.inl @@ -0,0 +1,175 @@ +/// @ref gtx_hash + +namespace glm { +namespace detail +{ + GLM_INLINE void hash_combine(size_t &seed, size_t hash) + { + hash += 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= hash; + } +}} + +namespace std +{ + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::vec<1, T, Q> const& v) const GLM_NOEXCEPT + { + hash hasher; + return hasher(v.x); + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::vec<2, T, Q> const& v) const GLM_NOEXCEPT + { + size_t seed = 0; + hash hasher; + glm::detail::hash_combine(seed, hasher(v.x)); + glm::detail::hash_combine(seed, hasher(v.y)); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::vec<3, T, Q> const& v) const GLM_NOEXCEPT + { + size_t seed = 0; + hash hasher; + glm::detail::hash_combine(seed, hasher(v.x)); + glm::detail::hash_combine(seed, hasher(v.y)); + glm::detail::hash_combine(seed, hasher(v.z)); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::vec<4, T, Q> const& v) const GLM_NOEXCEPT + { + size_t seed = 0; + hash hasher; + glm::detail::hash_combine(seed, hasher(v.x)); + glm::detail::hash_combine(seed, hasher(v.y)); + glm::detail::hash_combine(seed, hasher(v.z)); + glm::detail::hash_combine(seed, hasher(v.w)); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::qua const& q) const GLM_NOEXCEPT + { + size_t seed = 0; + hash hasher; + glm::detail::hash_combine(seed, hasher(q.x)); + glm::detail::hash_combine(seed, hasher(q.y)); + glm::detail::hash_combine(seed, hasher(q.z)); + glm::detail::hash_combine(seed, hasher(q.w)); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::tdualquat const& q) const GLM_NOEXCEPT + { + size_t seed = 0; + hash > hasher; + glm::detail::hash_combine(seed, hasher(q.real)); + glm::detail::hash_combine(seed, hasher(q.dual)); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::mat<2, 2, T, Q> const& m) const GLM_NOEXCEPT + { + size_t seed = 0; + hash > hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::mat<2, 3, T, Q> const& m) const GLM_NOEXCEPT + { + size_t seed = 0; + hash > hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::mat<2, 4, T, Q> const& m) const GLM_NOEXCEPT + { + size_t seed = 0; + hash > hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::mat<3, 2, T, Q> const& m) const GLM_NOEXCEPT + { + size_t seed = 0; + hash > hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + glm::detail::hash_combine(seed, hasher(m[2])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::mat<3, 3, T, Q> const& m) const GLM_NOEXCEPT + { + size_t seed = 0; + hash > hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + glm::detail::hash_combine(seed, hasher(m[2])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::mat<3, 4, T, Q> const& m) const GLM_NOEXCEPT + { + size_t seed = 0; + hash > hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + glm::detail::hash_combine(seed, hasher(m[2])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::mat<4, 2, T,Q> const& m) const GLM_NOEXCEPT + { + size_t seed = 0; + hash > hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + glm::detail::hash_combine(seed, hasher(m[2])); + glm::detail::hash_combine(seed, hasher(m[3])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::mat<4, 3, T,Q> const& m) const GLM_NOEXCEPT + { + size_t seed = 0; + hash > hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + glm::detail::hash_combine(seed, hasher(m[2])); + glm::detail::hash_combine(seed, hasher(m[3])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::mat<4, 4, T, Q> const& m) const GLM_NOEXCEPT + { + size_t seed = 0; + hash > hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + glm::detail::hash_combine(seed, hasher(m[2])); + glm::detail::hash_combine(seed, hasher(m[3])); + return seed; + } +} diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/integer.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/integer.hpp new file mode 100644 index 0000000..2b16830 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/integer.hpp @@ -0,0 +1,74 @@ +/// @ref gtx_integer +/// @file glm/gtx/integer.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_integer GLM_GTX_integer +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Add support for integer for core functions + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/integer.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_integer is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_integer + /// @{ + + //! Returns x raised to the y power. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL int pow(int x, uint y); + + //! Returns the positive square root of x. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL int sqrt(int x); + + //! Returns the floor log2 of x. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL unsigned int floor_log2(unsigned int x); + + //! Modulus. Returns x - y * floor(x / y) for each component in x using the floating point value y. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL int mod(int x, int y); + + //! Return the factorial value of a number (!12 max, integer only) + //! From GLM_GTX_integer extension. + template + GLM_FUNC_DECL genType factorial(genType const& x); + + //! 32bit signed integer. + //! From GLM_GTX_integer extension. + typedef signed int sint; + + //! Returns x raised to the y power. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL uint pow(uint x, uint y); + + //! Returns the positive square root of x. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL uint sqrt(uint x); + + //! Modulus. Returns x - y * floor(x / y) for each component in x using the floating point value y. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL uint mod(uint x, uint y); + + //! Returns the number of leading zeros. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL uint nlz(uint x); + + /// @} +}//namespace glm + +#include "integer.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/integer.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/integer.inl new file mode 100644 index 0000000..eb5df30 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/integer.inl @@ -0,0 +1,185 @@ +/// @ref gtx_integer + +namespace glm +{ + // pow + GLM_FUNC_QUALIFIER int pow(int x, uint y) + { + if(y == 0) + return x >= 0 ? 1 : -1; + + int result = x; + for(uint i = 1; i < y; ++i) + result *= x; + return result; + } + + // sqrt: From Christopher J. Musial, An integer square root, Graphics Gems, 1990, page 387 + GLM_FUNC_QUALIFIER int sqrt(int x) + { + if(x <= 1) return x; + + int NextTrial = x >> 1; + int CurrentAnswer; + + do + { + CurrentAnswer = NextTrial; + NextTrial = (NextTrial + x / NextTrial) >> 1; + } while(NextTrial < CurrentAnswer); + + return CurrentAnswer; + } + +// Henry Gordon Dietz: http://aggregate.org/MAGIC/ +namespace detail +{ + GLM_FUNC_QUALIFIER unsigned int ones32(unsigned int x) + { + /* 32-bit recursive reduction using SWAR... + but first step is mapping 2-bit values + into sum of 2 1-bit values in sneaky way + */ + x -= ((x >> 1) & 0x55555555); + x = (((x >> 2) & 0x33333333) + (x & 0x33333333)); + x = (((x >> 4) + x) & 0x0f0f0f0f); + x += (x >> 8); + x += (x >> 16); + return(x & 0x0000003f); + } +}//namespace detail + + // Henry Gordon Dietz: http://aggregate.org/MAGIC/ +/* + GLM_FUNC_QUALIFIER unsigned int floor_log2(unsigned int x) + { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + + return _detail::ones32(x) >> 1; + } +*/ + // mod + GLM_FUNC_QUALIFIER int mod(int x, int y) + { + return ((x % y) + y) % y; + } + + // factorial (!12 max, integer only) + template + GLM_FUNC_QUALIFIER genType factorial(genType const& x) + { + genType Temp = x; + genType Result; + for(Result = 1; Temp > 1; --Temp) + Result *= Temp; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> factorial( + vec<2, T, Q> const& x) + { + return vec<2, T, Q>( + factorial(x.x), + factorial(x.y)); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> factorial( + vec<3, T, Q> const& x) + { + return vec<3, T, Q>( + factorial(x.x), + factorial(x.y), + factorial(x.z)); + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> factorial( + vec<4, T, Q> const& x) + { + return vec<4, T, Q>( + factorial(x.x), + factorial(x.y), + factorial(x.z), + factorial(x.w)); + } + + GLM_FUNC_QUALIFIER uint pow(uint x, uint y) + { + if (y == 0) + return 1u; + + uint result = x; + for(uint i = 1; i < y; ++i) + result *= x; + return result; + } + + GLM_FUNC_QUALIFIER uint sqrt(uint x) + { + if(x <= 1) return x; + + uint NextTrial = x >> 1; + uint CurrentAnswer; + + do + { + CurrentAnswer = NextTrial; + NextTrial = (NextTrial + x / NextTrial) >> 1; + } while(NextTrial < CurrentAnswer); + + return CurrentAnswer; + } + + GLM_FUNC_QUALIFIER uint mod(uint x, uint y) + { + return x - y * (x / y); + } + +//#if(GLM_COMPILER & (GLM_COMPILER_VC | GLM_COMPILER_GCC)) + + GLM_FUNC_QUALIFIER unsigned int nlz(unsigned int x) + { + return 31u - static_cast(findMSB(x)); + } +/* +#else + + // Hackers Delight: http://www.hackersdelight.org/HDcode/nlz.c.txt + GLM_FUNC_QUALIFIER unsigned int nlz(unsigned int x) + { + int y, m, n; + + y = -int(x >> 16); // If left half of x is 0, + m = (y >> 16) & 16; // set n = 16. If left half + n = 16 - m; // is nonzero, set n = 0 and + x = x >> m; // shift x right 16. + // Now x is of the form 0000xxxx. + y = x - 0x100; // If positions 8-15 are 0, + m = (y >> 16) & 8; // add 8 to n and shift x left 8. + n = n + m; + x = x << m; + + y = x - 0x1000; // If positions 12-15 are 0, + m = (y >> 16) & 4; // add 4 to n and shift x left 4. + n = n + m; + x = x << m; + + y = x - 0x4000; // If positions 14-15 are 0, + m = (y >> 16) & 2; // add 2 to n and shift x left 2. + n = n + m; + x = x << m; + + y = x >> 14; // Set y = 0, 1, 2, or 3. + m = y & ~(y >> 1); // Set m = 0, 1, 2, or 2 resp. + return unsigned(n + 2 - m); + } + +#endif//(GLM_COMPILER) +*/ +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/intersect.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/intersect.hpp new file mode 100644 index 0000000..c7aec6f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/intersect.hpp @@ -0,0 +1,90 @@ +/// @ref gtx_intersect +/// @file glm/gtx/intersect.hpp +/// +/// @see core (dependence) +/// @see gtx_closest_point (dependence) +/// +/// @defgroup gtx_intersect GLM_GTX_intersect +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Add intersection functions + +#pragma once + +// Dependency: +#include +#include +#include "../glm.hpp" +#include "../geometric.hpp" +#include "../gtx/closest_point.hpp" +#include "../gtx/vector_query.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_closest_point is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_closest_point extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_intersect + /// @{ + + //! Compute the intersection of a ray and a plane. + //! Ray direction and plane normal must be unit length. + //! From GLM_GTX_intersect extension. + template + GLM_FUNC_DECL bool intersectRayPlane( + genType const& orig, genType const& dir, + genType const& planeOrig, genType const& planeNormal, + typename genType::value_type & intersectionDistance); + + //! Compute the intersection of a ray and a triangle. + /// Based om Tomas Möller implementation http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/raytri/ + //! From GLM_GTX_intersect extension. + template + GLM_FUNC_DECL bool intersectRayTriangle( + vec<3, T, Q> const& orig, vec<3, T, Q> const& dir, + vec<3, T, Q> const& v0, vec<3, T, Q> const& v1, vec<3, T, Q> const& v2, + vec<2, T, Q>& baryPosition, T& distance); + + //! Compute the intersection of a line and a triangle. + //! From GLM_GTX_intersect extension. + template + GLM_FUNC_DECL bool intersectLineTriangle( + genType const& orig, genType const& dir, + genType const& vert0, genType const& vert1, genType const& vert2, + genType & position); + + //! Compute the intersection distance of a ray and a sphere. + //! The ray direction vector is unit length. + //! From GLM_GTX_intersect extension. + template + GLM_FUNC_DECL bool intersectRaySphere( + genType const& rayStarting, genType const& rayNormalizedDirection, + genType const& sphereCenter, typename genType::value_type const sphereRadiusSquared, + typename genType::value_type & intersectionDistance); + + //! Compute the intersection of a ray and a sphere. + //! From GLM_GTX_intersect extension. + template + GLM_FUNC_DECL bool intersectRaySphere( + genType const& rayStarting, genType const& rayNormalizedDirection, + genType const& sphereCenter, const typename genType::value_type sphereRadius, + genType & intersectionPosition, genType & intersectionNormal); + + //! Compute the intersection of a line and a sphere. + //! From GLM_GTX_intersect extension + template + GLM_FUNC_DECL bool intersectLineSphere( + genType const& point0, genType const& point1, + genType const& sphereCenter, typename genType::value_type sphereRadius, + genType & intersectionPosition1, genType & intersectionNormal1, + genType & intersectionPosition2 = genType(), genType & intersectionNormal2 = genType()); + + /// @} +}//namespace glm + +#include "intersect.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/intersect.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/intersect.inl new file mode 100644 index 0000000..925a903 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/intersect.inl @@ -0,0 +1,200 @@ +/// @ref gtx_intersect + +namespace glm +{ + template + GLM_FUNC_QUALIFIER bool intersectRayPlane + ( + genType const& orig, genType const& dir, + genType const& planeOrig, genType const& planeNormal, + typename genType::value_type & intersectionDistance + ) + { + typename genType::value_type d = glm::dot(dir, planeNormal); + typename genType::value_type Epsilon = std::numeric_limits::epsilon(); + + if(glm::abs(d) > Epsilon) // if dir and planeNormal are not perpendicular + { + typename genType::value_type const tmp_intersectionDistance = glm::dot(planeOrig - orig, planeNormal) / d; + if (tmp_intersectionDistance > static_cast(0)) { // allow only intersections + intersectionDistance = tmp_intersectionDistance; + return true; + } + } + + return false; + } + + template + GLM_FUNC_QUALIFIER bool intersectRayTriangle + ( + vec<3, T, Q> const& orig, vec<3, T, Q> const& dir, + vec<3, T, Q> const& vert0, vec<3, T, Q> const& vert1, vec<3, T, Q> const& vert2, + vec<2, T, Q>& baryPosition, T& distance + ) + { + // find vectors for two edges sharing vert0 + vec<3, T, Q> const edge1 = vert1 - vert0; + vec<3, T, Q> const edge2 = vert2 - vert0; + + // begin calculating determinant - also used to calculate U parameter + vec<3, T, Q> const p = glm::cross(dir, edge2); + + // if determinant is near zero, ray lies in plane of triangle + T const det = glm::dot(edge1, p); + + vec<3, T, Q> Perpendicular(0); + + if (det > static_cast(0)) + { + // calculate distance from vert0 to ray origin + vec<3, T, Q> const dist = orig - vert0; + + // calculate U parameter and test bounds + baryPosition.x = glm::dot(dist, p); + if(baryPosition.x < static_cast(0) || baryPosition.x > det) + return false; + + // prepare to test V parameter + Perpendicular = glm::cross(dist, edge1); + + // calculate V parameter and test bounds + baryPosition.y = glm::dot(dir, Perpendicular); + if((baryPosition.y < static_cast(0)) || ((baryPosition.x + baryPosition.y) > det)) + return false; + } + else if(det < static_cast(0)) + { + // calculate distance from vert0 to ray origin + vec<3, T, Q> const dist = orig - vert0; + + // calculate U parameter and test bounds + baryPosition.x = glm::dot(dist, p); + if((baryPosition.x > static_cast(0)) || (baryPosition.x < det)) + return false; + + // prepare to test V parameter + Perpendicular = glm::cross(dist, edge1); + + // calculate V parameter and test bounds + baryPosition.y = glm::dot(dir, Perpendicular); + if((baryPosition.y > static_cast(0)) || (baryPosition.x + baryPosition.y < det)) + return false; + } + else + return false; // ray is parallel to the plane of the triangle + + T inv_det = static_cast(1) / det; + + // calculate distance, ray intersects triangle + distance = glm::dot(edge2, Perpendicular) * inv_det; + baryPosition *= inv_det; + + return true; + } + + template + GLM_FUNC_QUALIFIER bool intersectLineTriangle + ( + genType const& orig, genType const& dir, + genType const& vert0, genType const& vert1, genType const& vert2, + genType & position + ) + { + typename genType::value_type Epsilon = std::numeric_limits::epsilon(); + + genType edge1 = vert1 - vert0; + genType edge2 = vert2 - vert0; + + genType Perpendicular = cross(dir, edge2); + + typename genType::value_type det = dot(edge1, Perpendicular); + + if (det > -Epsilon && det < Epsilon) + return false; + typename genType::value_type inv_det = typename genType::value_type(1) / det; + + genType Tangent = orig - vert0; + + position.y = dot(Tangent, Perpendicular) * inv_det; + if (position.y < typename genType::value_type(0) || position.y > typename genType::value_type(1)) + return false; + + genType Cotangent = cross(Tangent, edge1); + + position.z = dot(dir, Cotangent) * inv_det; + if (position.z < typename genType::value_type(0) || position.y + position.z > typename genType::value_type(1)) + return false; + + position.x = dot(edge2, Cotangent) * inv_det; + + return true; + } + + template + GLM_FUNC_QUALIFIER bool intersectRaySphere + ( + genType const& rayStarting, genType const& rayNormalizedDirection, + genType const& sphereCenter, const typename genType::value_type sphereRadiusSquared, + typename genType::value_type & intersectionDistance + ) + { + typename genType::value_type Epsilon = std::numeric_limits::epsilon(); + genType diff = sphereCenter - rayStarting; + typename genType::value_type t0 = dot(diff, rayNormalizedDirection); + typename genType::value_type dSquared = dot(diff, diff) - t0 * t0; + if( dSquared > sphereRadiusSquared ) + { + return false; + } + typename genType::value_type t1 = sqrt( sphereRadiusSquared - dSquared ); + intersectionDistance = t0 > t1 + Epsilon ? t0 - t1 : t0 + t1; + return intersectionDistance > Epsilon; + } + + template + GLM_FUNC_QUALIFIER bool intersectRaySphere + ( + genType const& rayStarting, genType const& rayNormalizedDirection, + genType const& sphereCenter, const typename genType::value_type sphereRadius, + genType & intersectionPosition, genType & intersectionNormal + ) + { + typename genType::value_type distance; + if( intersectRaySphere( rayStarting, rayNormalizedDirection, sphereCenter, sphereRadius * sphereRadius, distance ) ) + { + intersectionPosition = rayStarting + rayNormalizedDirection * distance; + intersectionNormal = (intersectionPosition - sphereCenter) / sphereRadius; + return true; + } + return false; + } + + template + GLM_FUNC_QUALIFIER bool intersectLineSphere + ( + genType const& point0, genType const& point1, + genType const& sphereCenter, typename genType::value_type sphereRadius, + genType & intersectionPoint1, genType & intersectionNormal1, + genType & intersectionPoint2, genType & intersectionNormal2 + ) + { + typename genType::value_type Epsilon = std::numeric_limits::epsilon(); + genType dir = normalize(point1 - point0); + genType diff = sphereCenter - point0; + typename genType::value_type t0 = dot(diff, dir); + typename genType::value_type dSquared = dot(diff, diff) - t0 * t0; + if( dSquared > sphereRadius * sphereRadius ) + { + return false; + } + typename genType::value_type t1 = sqrt( sphereRadius * sphereRadius - dSquared ); + if( t0 < t1 + Epsilon ) + t1 = -t1; + intersectionPoint1 = point0 + dir * (t0 - t1); + intersectionNormal1 = (intersectionPoint1 - sphereCenter) / sphereRadius; + intersectionPoint2 = point0 + dir * (t0 + t1); + intersectionNormal2 = (intersectionPoint2 - sphereCenter) / sphereRadius; + return true; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/io.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/io.hpp new file mode 100644 index 0000000..5afc8cc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/io.hpp @@ -0,0 +1,210 @@ +/// @ref gtx_io +/// @file glm/gtx/io.hpp +/// @author Jan P Springer (regnirpsj@gmail.com) +/// +/// @see core (dependence) +/// @see gtc_matrix_access (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_io GLM_GTX_io +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// std::[w]ostream support for glm types +/// +/// std::[w]ostream support for glm types + qualifier/width/etc. manipulators +/// based on howard hinnant's std::chrono io proposal +/// [http://home.roadrunner.com/~hinnant/bloomington/chrono_io.html] + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/quaternion.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_io is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_io extension included") +#endif + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wshorten-64-to-32" +# pragma clang diagnostic ignored "-Wglobal-constructors" +#endif + +#include // std::basic_ostream<> (fwd) +#include // std::locale, std::locale::facet, std::locale::id +#include // std::pair<> + +namespace glm +{ + /// @addtogroup gtx_io + /// @{ + + namespace io + { + enum order_type { column_major, row_major}; + + template + class format_punct : public std::locale::facet + { + typedef CTy char_type; + + public: + + static std::locale::id id; + + bool formatted; + unsigned precision; + unsigned width; + char_type separator; + char_type delim_left; + char_type delim_right; + char_type space; + char_type newline; + order_type order; + + GLM_FUNC_DISCARD_DECL explicit format_punct(size_t a = 0); + GLM_FUNC_DISCARD_DECL explicit format_punct(format_punct const&); + }; + + template > + class basic_state_saver { + + public: + + GLM_FUNC_DISCARD_DECL explicit basic_state_saver(std::basic_ios&); + GLM_FUNC_DISCARD_DECL ~basic_state_saver(); + + private: + + typedef ::std::basic_ios state_type; + typedef typename state_type::char_type char_type; + typedef ::std::ios_base::fmtflags flags_type; + typedef ::std::streamsize streamsize_type; + typedef ::std::locale const locale_type; + + state_type& state_; + flags_type flags_; + streamsize_type precision_; + streamsize_type width_; + char_type fill_; + locale_type locale_; + + GLM_FUNC_DECL basic_state_saver& operator=(basic_state_saver const&); + }; + + typedef basic_state_saver state_saver; + typedef basic_state_saver wstate_saver; + + template > + class basic_format_saver + { + public: + + GLM_FUNC_DISCARD_DECL explicit basic_format_saver(std::basic_ios&); + GLM_FUNC_DISCARD_DECL ~basic_format_saver(); + + private: + + basic_state_saver const bss_; + + GLM_FUNC_DECL basic_format_saver& operator=(basic_format_saver const&); + }; + + typedef basic_format_saver format_saver; + typedef basic_format_saver wformat_saver; + + struct precision + { + unsigned value; + + GLM_FUNC_DISCARD_DECL explicit precision(unsigned); + }; + + struct width + { + unsigned value; + + GLM_FUNC_DISCARD_DECL explicit width(unsigned); + }; + + template + struct delimeter + { + CTy value[3]; + + GLM_FUNC_DISCARD_DECL explicit delimeter(CTy /* left */, CTy /* right */, CTy /* separator */ = ','); + }; + + struct order + { + order_type value; + + GLM_FUNC_DISCARD_DECL explicit order(order_type); + }; + + // functions, inlined (inline) + + template + FTy const& get_facet(std::basic_ios&); + template + std::basic_ios& formatted(std::basic_ios&); + template + std::basic_ios& unformatted(std::basic_ios&); + + template + std::basic_ostream& operator<<(std::basic_ostream&, precision const&); + template + std::basic_ostream& operator<<(std::basic_ostream&, width const&); + template + std::basic_ostream& operator<<(std::basic_ostream&, delimeter const&); + template + std::basic_ostream& operator<<(std::basic_ostream&, order const&); + }//namespace io + + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, qua const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, vec<1, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, vec<2, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, vec<3, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, vec<4, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<2, 2, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<2, 3, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<2, 4, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<3, 2, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<3, 3, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<3, 4, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<4, 2, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<4, 3, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<4, 4, T, Q> const&); + + template + GLM_FUNC_DISCARD_DECL std::basic_ostream & operator<<(std::basic_ostream &, + std::pair const, mat<4, 4, T, Q> const> const&); + + /// @} +}//namespace glm + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +#endif + +#include "io.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/io.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/io.inl new file mode 100644 index 0000000..d4ef825 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/io.inl @@ -0,0 +1,452 @@ +/// @ref gtx_io +/// @author Jan P Springer (regnirpsj@gmail.com) + +#include // std::fixed, std::setfill<>, std::setprecision, std::right, std::setw +#include // std::basic_ostream<> +#include "../gtc/matrix_access.hpp" // glm::col, glm::row +#include "../gtx/type_trait.hpp" // glm::type<> + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wshorten-64-to-32" +# pragma clang diagnostic ignored "-Wglobal-constructors" +#endif + +namespace glm{ +namespace io +{ + template + GLM_FUNC_QUALIFIER format_punct::format_punct(size_t a) + : std::locale::facet(a) + , formatted(true) + , precision(3) + , width(1 + 4 + 1 + precision) + , separator(',') + , delim_left('[') + , delim_right(']') + , space(' ') + , newline('\n') + , order(column_major) + {} + + template + GLM_FUNC_QUALIFIER format_punct::format_punct(format_punct const& a) + : std::locale::facet(0) + , formatted(a.formatted) + , precision(a.precision) + , width(a.width) + , separator(a.separator) + , delim_left(a.delim_left) + , delim_right(a.delim_right) + , space(a.space) + , newline(a.newline) + , order(a.order) + {} + + template std::locale::id format_punct::id; + + template + GLM_FUNC_QUALIFIER basic_state_saver::basic_state_saver(std::basic_ios& a) + : state_(a) + , flags_(a.flags()) + , precision_(a.precision()) + , width_(a.width()) + , fill_(a.fill()) + , locale_(a.getloc()) + {} + + template + GLM_FUNC_QUALIFIER basic_state_saver::~basic_state_saver() + { + state_.imbue(locale_); + state_.fill(fill_); + state_.width(width_); + state_.precision(precision_); + state_.flags(flags_); + } + + template + GLM_FUNC_QUALIFIER basic_format_saver::basic_format_saver(std::basic_ios& a) + : bss_(a) + { + a.imbue(std::locale(a.getloc(), new format_punct(get_facet >(a)))); + } + + template + GLM_FUNC_QUALIFIER + basic_format_saver::~basic_format_saver() + {} + + GLM_FUNC_QUALIFIER precision::precision(unsigned a) + : value(a) + {} + + GLM_FUNC_QUALIFIER width::width(unsigned a) + : value(a) + {} + + template + GLM_FUNC_QUALIFIER delimeter::delimeter(CTy a, CTy b, CTy c) + : value() + { + value[0] = a; + value[1] = b; + value[2] = c; + } + + GLM_FUNC_QUALIFIER order::order(order_type a) + : value(a) + {} + + template + GLM_FUNC_QUALIFIER FTy const& get_facet(std::basic_ios& ios) + { + if(!std::has_facet(ios.getloc())) + ios.imbue(std::locale(ios.getloc(), new FTy)); + + return std::use_facet(ios.getloc()); + } + + template + GLM_FUNC_QUALIFIER std::basic_ios& formatted(std::basic_ios& ios) + { + const_cast&>(get_facet >(ios)).formatted = true; + return ios; + } + + template + GLM_FUNC_QUALIFIER std::basic_ios& unformatted(std::basic_ios& ios) + { + const_cast&>(get_facet >(ios)).formatted = false; + return ios; + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, precision const& a) + { + const_cast&>(get_facet >(os)).precision = a.value; + return os; + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, width const& a) + { + const_cast&>(get_facet >(os)).width = a.value; + return os; + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, delimeter const& a) + { + format_punct & fmt(const_cast&>(get_facet >(os))); + + fmt.delim_left = a.value[0]; + fmt.delim_right = a.value[1]; + fmt.separator = a.value[2]; + + return os; + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, order const& a) + { + const_cast&>(get_facet >(os)).order = a.value; + return os; + } +} // namespace io + +namespace detail +{ + template + GLM_FUNC_QUALIFIER std::basic_ostream& + print_vector_on(std::basic_ostream& os, V const& a) + { + typename std::basic_ostream::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct const& fmt(io::get_facet >(os)); + + length_t const& components(type::components); + + if(fmt.formatted) + { + io::basic_state_saver const bss(os); + + os << std::fixed << std::right << std::setprecision(static_cast(fmt.precision)) << std::setfill(fmt.space) << fmt.delim_left; + + for(length_t i(0); i < components; ++i) + { + os << std::setw(static_cast(fmt.width)) << a[i]; + if(components-1 != i) + os << fmt.separator; + } + + os << fmt.delim_right; + } + else + { + for(length_t i(0); i < components; ++i) + { + os << a[i]; + + if(components-1 != i) + os << fmt.space; + } + } + } + + return os; + } +}//namespace detail + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, qua const& a) + { + return detail::print_vector_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, vec<1, T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, vec<2, T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, vec<3, T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, vec<4, T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + +namespace detail +{ + template class M, length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream& print_matrix_on(std::basic_ostream& os, M const& a) + { + typename std::basic_ostream::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct const& fmt(io::get_facet >(os)); + + length_t const& cols(type >::cols); + length_t const& rows(type >::rows); + + if(fmt.formatted) + { + os << fmt.newline << fmt.delim_left; + + switch(fmt.order) + { + case io::column_major: + { + for(length_t i(0); i < rows; ++i) + { + if (0 != i) + os << fmt.space; + + os << row(a, i); + + if(rows-1 != i) + os << fmt.newline; + } + } + break; + + case io::row_major: + { + for(length_t i(0); i < cols; ++i) + { + if(0 != i) + os << fmt.space; + + os << column(a, i); + + if(cols-1 != i) + os << fmt.newline; + } + } + break; + } + + os << fmt.delim_right; + } + else + { + switch (fmt.order) + { + case io::column_major: + { + for(length_t i(0); i < cols; ++i) + { + os << column(a, i); + + if(cols - 1 != i) + os << fmt.space; + } + } + break; + + case io::row_major: + { + for (length_t i(0); i < rows; ++i) + { + os << row(a, i); + + if (rows-1 != i) + os << fmt.space; + } + } + break; + } + } + } + + return os; + } +}//namespace detail + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, mat<2, 2, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, mat<2, 3, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, mat<2, 4, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, mat<3, 2, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, mat<3, 3, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream & operator<<(std::basic_ostream& os, mat<3, 4, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream & operator<<(std::basic_ostream& os, mat<4, 2, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream & operator<<(std::basic_ostream& os, mat<4, 3, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream & operator<<(std::basic_ostream& os, mat<4, 4, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + +namespace detail +{ + template class M, length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream& print_matrix_pair_on(std::basic_ostream& os, std::pair const, M const> const& a) + { + typename std::basic_ostream::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct const& fmt(io::get_facet >(os)); + M const& ml(a.first); + M const& mr(a.second); + length_t const& cols(type >::cols); + length_t const& rows(type >::rows); + + if(fmt.formatted) + { + os << fmt.newline << fmt.delim_left; + + switch(fmt.order) + { + case io::column_major: + { + for(length_t i(0); i < rows; ++i) + { + if(0 != i) + os << fmt.space; + + os << row(ml, i) << ((rows-1 != i) ? fmt.space : fmt.delim_right) << fmt.space << ((0 != i) ? fmt.space : fmt.delim_left) << row(mr, i); + + if(rows-1 != i) + os << fmt.newline; + } + } + break; + case io::row_major: + { + for(length_t i(0); i < cols; ++i) + { + if(0 != i) + os << fmt.space; + + os << column(ml, i) << ((cols-1 != i) ? fmt.space : fmt.delim_right) << fmt.space << ((0 != i) ? fmt.space : fmt.delim_left) << column(mr, i); + + if(cols-1 != i) + os << fmt.newline; + } + } + break; + } + + os << fmt.delim_right; + } + else + { + os << ml << fmt.space << mr; + } + } + + return os; + } +}//namespace detail + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<( + std::basic_ostream & os, + std::pair const, + mat<4, 4, T, Q> const> const& a) + { + return detail::print_matrix_pair_on(os, a); + } +}//namespace glm + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +#endif + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/log_base.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/log_base.hpp new file mode 100644 index 0000000..915c7a4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/log_base.hpp @@ -0,0 +1,46 @@ +/// @ref gtx_log_base +/// @file glm/gtx/log_base.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_log_base GLM_GTX_log_base +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Logarithm for any base. base can be a vector or a scalar. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_log_base is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_log_base extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_log_base + /// @{ + + /// Logarithm for any base. + /// From GLM_GTX_log_base. + template + GLM_FUNC_DECL genType log( + genType const& x, + genType const& base); + + /// Logarithm for any base. + /// From GLM_GTX_log_base. + template + GLM_FUNC_DECL vec sign( + vec const& x, + vec const& base); + + /// @} +}//namespace glm + +#include "log_base.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/log_base.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/log_base.inl new file mode 100644 index 0000000..4bbb8e8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/log_base.inl @@ -0,0 +1,16 @@ +/// @ref gtx_log_base + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType log(genType const& x, genType const& base) + { + return glm::log(x) / glm::log(base); + } + + template + GLM_FUNC_QUALIFIER vec log(vec const& x, vec const& base) + { + return glm::log(x) / glm::log(base); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_cross_product.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_cross_product.hpp new file mode 100644 index 0000000..882a1d7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_cross_product.hpp @@ -0,0 +1,45 @@ +/// @ref gtx_matrix_cross_product +/// @file glm/gtx/matrix_cross_product.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_matrix_cross_product GLM_GTX_matrix_cross_product +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Build cross product matrices + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_matrix_cross_product is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_cross_product extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_cross_product + /// @{ + + //! Build a cross product matrix. + //! From GLM_GTX_matrix_cross_product extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> matrixCross3( + vec<3, T, Q> const& x); + + //! Build a cross product matrix. + //! From GLM_GTX_matrix_cross_product extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> matrixCross4( + vec<3, T, Q> const& x); + + /// @} +}//namespace glm + +#include "matrix_cross_product.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_cross_product.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_cross_product.inl new file mode 100644 index 0000000..3a15397 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_cross_product.inl @@ -0,0 +1,37 @@ +/// @ref gtx_matrix_cross_product + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> matrixCross3 + ( + vec<3, T, Q> const& x + ) + { + mat<3, 3, T, Q> Result(T(0)); + Result[0][1] = x.z; + Result[1][0] = -x.z; + Result[0][2] = -x.y; + Result[2][0] = x.y; + Result[1][2] = x.x; + Result[2][1] = -x.x; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> matrixCross4 + ( + vec<3, T, Q> const& x + ) + { + mat<4, 4, T, Q> Result(T(0)); + Result[0][1] = x.z; + Result[1][0] = -x.z; + Result[0][2] = -x.y; + Result[2][0] = x.y; + Result[1][2] = x.x; + Result[2][1] = -x.x; + return Result; + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_decompose.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_decompose.hpp new file mode 100644 index 0000000..19ac8a8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_decompose.hpp @@ -0,0 +1,50 @@ +/// @ref gtx_matrix_decompose +/// @file glm/gtx/matrix_decompose.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_decompose GLM_GTX_matrix_decompose +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Decomposes a model matrix to translations, rotation and scale components + +#pragma once + +// Dependencies +#include "../mat4x4.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../geometric.hpp" +#include "../gtc/quaternion.hpp" +#include "../gtc/matrix_transform.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_matrix_decompose is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_decompose extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_decompose + /// @{ + + /// Decomposes a model matrix to translations, rotation and scale components + /// @see gtx_matrix_decompose + template + GLM_FUNC_DISCARD_DECL bool decompose( + mat<4, 4, T, Q> const& modelMatrix, + vec<3, T, Q> & scale, qua & orientation, vec<3, T, Q> & translation, vec<3, T, Q> & skew, vec<4, T, Q> & perspective); + + // Recomposes a model matrix from a previously-decomposed matrix + template + GLM_FUNC_DISCARD_DECL mat<4, 4, T, Q> recompose( + vec<3, T, Q> const& scale, qua const& orientation, vec<3, T, Q> const& translation, + vec<3, T, Q> const& skew, vec<4, T, Q> const& perspective); + + /// @} +}//namespace glm + +#include "matrix_decompose.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_decompose.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_decompose.inl new file mode 100644 index 0000000..1b587e2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_decompose.inl @@ -0,0 +1,234 @@ +/// @ref gtx_matrix_decompose + +#include "../gtc/constants.hpp" +#include "../gtc/epsilon.hpp" +#include "../gtx/transform.hpp" + +namespace glm{ +namespace detail +{ + /// Make a linear combination of two vectors and return the result. + // result = (a * ascl) + (b * bscl) + template + GLM_FUNC_QUALIFIER vec<3, T, Q> combine( + vec<3, T, Q> const& a, + vec<3, T, Q> const& b, + T ascl, T bscl) + { + return (a * ascl) + (b * bscl); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> scale(vec<3, T, Q> const& v, T desiredLength) + { + return v * desiredLength / length(v); + } +}//namespace detail + + // Matrix decompose + // http://www.opensource.apple.com/source/WebCore/WebCore-514/platform/graphics/transforms/TransformationMatrix.cpp + // Decomposes the mode matrix to translations,rotation scale components + + template + GLM_FUNC_QUALIFIER bool decompose(mat<4, 4, T, Q> const& ModelMatrix, vec<3, T, Q> & Scale, qua & Orientation, vec<3, T, Q> & Translation, vec<3, T, Q> & Skew, vec<4, T, Q> & Perspective) + { + mat<4, 4, T, Q> LocalMatrix(ModelMatrix); + + // Normalize the matrix. + if(epsilonEqual(LocalMatrix[3][3], static_cast(0), epsilon())) + return false; + + for(length_t i = 0; i < 4; ++i) + for(length_t j = 0; j < 4; ++j) + LocalMatrix[i][j] /= LocalMatrix[3][3]; + + // perspectiveMatrix is used to solve for perspective, but it also provides + // an easy way to test for singularity of the upper 3x3 component. + mat<4, 4, T, Q> PerspectiveMatrix(LocalMatrix); + + for(length_t i = 0; i < 3; i++) + PerspectiveMatrix[i][3] = static_cast(0); + PerspectiveMatrix[3][3] = static_cast(1); + + /// TODO: Fixme! + if(epsilonEqual(determinant(PerspectiveMatrix), static_cast(0), epsilon())) + return false; + + // First, isolate perspective. This is the messiest. + if( + epsilonNotEqual(LocalMatrix[0][3], static_cast(0), epsilon()) || + epsilonNotEqual(LocalMatrix[1][3], static_cast(0), epsilon()) || + epsilonNotEqual(LocalMatrix[2][3], static_cast(0), epsilon())) + { + // rightHandSide is the right hand side of the equation. + vec<4, T, Q> RightHandSide; + RightHandSide[0] = LocalMatrix[0][3]; + RightHandSide[1] = LocalMatrix[1][3]; + RightHandSide[2] = LocalMatrix[2][3]; + RightHandSide[3] = LocalMatrix[3][3]; + + // Solve the equation by inverting PerspectiveMatrix and multiplying + // rightHandSide by the inverse. (This is the easiest way, not + // necessarily the best.) + mat<4, 4, T, Q> InversePerspectiveMatrix = glm::inverse(PerspectiveMatrix);// inverse(PerspectiveMatrix, inversePerspectiveMatrix); + mat<4, 4, T, Q> TransposedInversePerspectiveMatrix = glm::transpose(InversePerspectiveMatrix);// transposeMatrix4(inversePerspectiveMatrix, transposedInversePerspectiveMatrix); + + Perspective = TransposedInversePerspectiveMatrix * RightHandSide; + // v4MulPointByMatrix(rightHandSide, transposedInversePerspectiveMatrix, perspectivePoint); + + // Clear the perspective partition + LocalMatrix[0][3] = LocalMatrix[1][3] = LocalMatrix[2][3] = static_cast(0); + LocalMatrix[3][3] = static_cast(1); + } + else + { + // No perspective. + Perspective = vec<4, T, Q>(0, 0, 0, 1); + } + + // Next take care of translation (easy). + Translation = vec<3, T, Q>(LocalMatrix[3]); + LocalMatrix[3] = vec<4, T, Q>(0, 0, 0, LocalMatrix[3].w); + + vec<3, T, Q> Row[3], Pdum3; + + // Now get scale and shear. + for(length_t i = 0; i < 3; ++i) + for(length_t j = 0; j < 3; ++j) + Row[i][j] = LocalMatrix[i][j]; + + // Compute X scale factor and normalize first row. + Scale.x = length(Row[0]);// v3Length(Row[0]); + + Row[0] = detail::scale(Row[0], static_cast(1)); + + // Compute XY shear factor and make 2nd row orthogonal to 1st. + Skew.z = dot(Row[0], Row[1]); + Row[1] = detail::combine(Row[1], Row[0], static_cast(1), -Skew.z); + + // Now, compute Y scale and normalize 2nd row. + Scale.y = length(Row[1]); + Row[1] = detail::scale(Row[1], static_cast(1)); + Skew.z /= Scale.y; + + // Compute XZ and YZ shears, orthogonalize 3rd row. + Skew.y = glm::dot(Row[0], Row[2]); + Row[2] = detail::combine(Row[2], Row[0], static_cast(1), -Skew.y); + Skew.x = glm::dot(Row[1], Row[2]); + Row[2] = detail::combine(Row[2], Row[1], static_cast(1), -Skew.x); + + // Next, get Z scale and normalize 3rd row. + Scale.z = length(Row[2]); + Row[2] = detail::scale(Row[2], static_cast(1)); + Skew.y /= Scale.z; + Skew.x /= Scale.z; + + // At this point, the matrix (in rows[]) is orthonormal. + // Check for a coordinate system flip. If the determinant + // is -1, then negate the matrix and the scaling factors. + Pdum3 = cross(Row[1], Row[2]); // v3Cross(row[1], row[2], Pdum3); + if(dot(Row[0], Pdum3) < 0) + { + for(length_t i = 0; i < 3; i++) + { + Scale[i] *= static_cast(-1); + Row[i] *= static_cast(-1); + } + } + + // Now, get the rotations out, as described in the gem. + + // FIXME - Add the ability to return either quaternions (which are + // easier to recompose with) or Euler angles (rx, ry, rz), which + // are easier for authors to deal with. The latter will only be useful + // when we fix https://bugs.webkit.org/show_bug.cgi?id=23799, so I + // will leave the Euler angle code here for now. + + // ret.rotateY = asin(-Row[0][2]); + // if (cos(ret.rotateY) != 0) { + // ret.rotateX = atan2(Row[1][2], Row[2][2]); + // ret.rotateZ = atan2(Row[0][1], Row[0][0]); + // } else { + // ret.rotateX = atan2(-Row[2][0], Row[1][1]); + // ret.rotateZ = 0; + // } + + int i, j, k = 0; + T root, trace = Row[0].x + Row[1].y + Row[2].z; + if(trace > static_cast(0)) + { + root = sqrt(trace + static_cast(1.0)); + Orientation.w = static_cast(0.5) * root; + root = static_cast(0.5) / root; + Orientation.x = root * (Row[1].z - Row[2].y); + Orientation.y = root * (Row[2].x - Row[0].z); + Orientation.z = root * (Row[0].y - Row[1].x); + } // End if > 0 + else + { + static int Next[3] = {1, 2, 0}; + i = 0; + if(Row[1].y > Row[0].x) i = 1; + if(Row[2].z > Row[i][i]) i = 2; + j = Next[i]; + k = Next[j]; + +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + int off = 1; +# else + int off = 0; +# endif + + root = sqrt(Row[i][i] - Row[j][j] - Row[k][k] + static_cast(1.0)); + + Orientation[i + off] = static_cast(0.5) * root; + root = static_cast(0.5) / root; + Orientation[j + off] = root * (Row[i][j] + Row[j][i]); + Orientation[k + off] = root * (Row[i][k] + Row[k][i]); + Orientation.w = root * (Row[j][k] - Row[k][j]); + } // End if <= 0 + + return true; + } + + // Recomposes a model matrix from a previously-decomposed matrix + // http://www.opensource.apple.com/source/WebCore/WebCore-514/platform/graphics/transforms/TransformationMatrix.cpp + // https://stackoverflow.com/a/75573092/1047040 + template + GLM_FUNC_DECL mat<4, 4, T, Q> recompose( + vec<3, T, Q> const& scale, qua const& orientation, vec<3, T, Q> const& translation, + vec<3, T, Q> const& skew, vec<4, T, Q> const& perspective) + { + glm::mat4 m = glm::mat4(1.f); + + m[0][3] = perspective.x; + m[1][3] = perspective.y; + m[2][3] = perspective.z; + m[3][3] = perspective.w; + + m *= glm::translate(translation); + m *= glm::mat4_cast(orientation); + + if (abs(skew.x) > static_cast(0)) { + glm::mat4 tmp(1.f); + tmp[2][1] = skew.x; + m *= tmp; + } + + if (abs(skew.y) > static_cast(0)) { + glm::mat4 tmp(1.f); + tmp[2][0] = skew.y; + m *= tmp; + } + + if (abs(skew.z) > static_cast(0)) { + glm::mat4 tmp(1.f); + tmp[1][0] = skew.z; + m *= tmp; + } + + m *= glm::scale(scale); + + return m; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_factorisation.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_factorisation.hpp new file mode 100644 index 0000000..dc32847 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_factorisation.hpp @@ -0,0 +1,67 @@ +/// @ref gtx_matrix_factorisation +/// @file glm/gtx/matrix_factorisation.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_factorisation GLM_GTX_matrix_factorisation +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Functions to factor matrices in various forms + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_matrix_factorisation is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_factorisation extension included") +#endif + +/* +Suggestions: + - Move helper functions flipud and fliplr to another file: They may be helpful in more general circumstances. + - Implement other types of matrix factorisation, such as: QL and LQ, L(D)U, eigendecompositions, etc... +*/ + +namespace glm +{ + /// @addtogroup gtx_matrix_factorisation + /// @{ + + /// Flips the matrix rows up and down. + /// + /// From GLM_GTX_matrix_factorisation extension. + template + GLM_FUNC_DECL mat flipud(mat const& in); + + /// Flips the matrix columns right and left. + /// + /// From GLM_GTX_matrix_factorisation extension. + template + GLM_FUNC_DECL mat fliplr(mat const& in); + + /// Performs QR factorisation of a matrix. + /// Returns 2 matrices, q and r, such that the columns of q are orthonormal and span the same subspace than those of the input matrix, r is an upper triangular matrix, and q*r=in. + /// Given an n-by-m input matrix, q has dimensions min(n,m)-by-m, and r has dimensions n-by-min(n,m). + /// + /// From GLM_GTX_matrix_factorisation extension. + template + GLM_FUNC_DISCARD_DECL void qr_decompose(mat const& in, mat<(C < R ? C : R), R, T, Q>& q, mat& r); + + /// Performs RQ factorisation of a matrix. + /// Returns 2 matrices, r and q, such that r is an upper triangular matrix, the rows of q are orthonormal and span the same subspace than those of the input matrix, and r*q=in. + /// Note that in the context of RQ factorisation, the diagonal is seen as starting in the lower-right corner of the matrix, instead of the usual upper-left. + /// Given an n-by-m input matrix, r has dimensions min(n,m)-by-m, and q has dimensions n-by-min(n,m). + /// + /// From GLM_GTX_matrix_factorisation extension. + template + GLM_FUNC_DISCARD_DECL void rq_decompose(mat const& in, mat<(C < R ? C : R), R, T, Q>& r, mat& q); + + /// @} +} + +#include "matrix_factorisation.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_factorisation.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_factorisation.inl new file mode 100644 index 0000000..6f1683c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_factorisation.inl @@ -0,0 +1,84 @@ +/// @ref gtx_matrix_factorisation + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat flipud(mat const& in) + { + mat tin = transpose(in); + tin = fliplr(tin); + mat out = transpose(tin); + + return out; + } + + template + GLM_FUNC_QUALIFIER mat fliplr(mat const& in) + { + mat out; + for (length_t i = 0; i < C; i++) + { + out[i] = in[(C - i) - 1]; + } + + return out; + } + + template + GLM_FUNC_QUALIFIER void qr_decompose(mat const& in, mat<(C < R ? C : R), R, T, Q>& q, mat& r) + { + // Uses modified Gram-Schmidt method + // Source: https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process + // And https://en.wikipedia.org/wiki/QR_decomposition + + //For all the linearly independs columns of the input... + // (there can be no more linearly independents columns than there are rows.) + for (length_t i = 0; i < (C < R ? C : R); i++) + { + //Copy in Q the input's i-th column. + q[i] = in[i]; + + //j = [0,i[ + // Make that column orthogonal to all the previous ones by substracting to it the non-orthogonal projection of all the previous columns. + // Also: Fill the zero elements of R + for (length_t j = 0; j < i; j++) + { + q[i] -= dot(q[i], q[j])*q[j]; + r[j][i] = 0; + } + + //Now, Q i-th column is orthogonal to all the previous columns. Normalize it. + q[i] = normalize(q[i]); + + //j = [i,C[ + //Finally, compute the corresponding coefficients of R by computing the projection of the resulting column on the other columns of the input. + for (length_t j = i; j < C; j++) + { + r[j][i] = dot(in[j], q[i]); + } + } + } + + template + GLM_FUNC_QUALIFIER void rq_decompose(mat const& in, mat<(C < R ? C : R), R, T, Q>& r, mat& q) + { + // From https://en.wikipedia.org/wiki/QR_decomposition: + // The RQ decomposition transforms a matrix A into the product of an upper triangular matrix R (also known as right-triangular) and an orthogonal matrix Q. The only difference from QR decomposition is the order of these matrices. + // QR decomposition is Gram-Schmidt orthogonalization of columns of A, started from the first column. + // RQ decomposition is Gram-Schmidt orthogonalization of rows of A, started from the last row. + + mat tin = transpose(in); + tin = fliplr(tin); + + mat tr; + mat<(C < R ? C : R), C, T, Q> tq; + qr_decompose(tin, tq, tr); + + tr = fliplr(tr); + r = transpose(tr); + r = fliplr(r); + + tq = fliplr(tq); + q = transpose(tq); + } +} //namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_interpolation.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_interpolation.hpp new file mode 100644 index 0000000..e2767c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_interpolation.hpp @@ -0,0 +1,58 @@ +/// @ref gtx_matrix_interpolation +/// @file glm/gtx/matrix_interpolation.hpp +/// @author Ghenadii Ursachi (the.asteroth@gmail.com) +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_interpolation GLM_GTX_matrix_interpolation +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Allows to directly interpolate two matrices. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_matrix_interpolation is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_interpolation extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_interpolation + /// @{ + + /// Get the axis and angle of the rotation from a matrix. + /// From GLM_GTX_matrix_interpolation extension. + template + GLM_FUNC_DISCARD_DECL void axisAngle( + mat<4, 4, T, Q> const& Mat, vec<3, T, Q> & Axis, T & Angle); + + /// Build a matrix from axis and angle. + /// From GLM_GTX_matrix_interpolation extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> axisAngleMatrix( + vec<3, T, Q> const& Axis, T const Angle); + + /// Extracts the rotation part of a matrix. + /// From GLM_GTX_matrix_interpolation extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> extractMatrixRotation( + mat<4, 4, T, Q> const& Mat); + + /// Build a interpolation of 4 * 4 matrixes. + /// From GLM_GTX_matrix_interpolation extension. + /// Warning! works only with rotation and/or translation matrixes, scale will generate unexpected results. + template + GLM_FUNC_DECL mat<4, 4, T, Q> interpolate( + mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2, T const Delta); + + /// @} +}//namespace glm + +#include "matrix_interpolation.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_interpolation.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_interpolation.inl new file mode 100644 index 0000000..f4ba3a6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_interpolation.inl @@ -0,0 +1,146 @@ +/// @ref gtx_matrix_interpolation + +#include "../ext/scalar_constants.hpp" + +#include + +namespace glm +{ + template + GLM_FUNC_QUALIFIER void axisAngle(mat<4, 4, T, Q> const& m, vec<3, T, Q>& axis, T& angle) + { + T const epsilon = + std::numeric_limits::epsilon() * static_cast(1e2); + + bool const nearSymmetrical = + abs(m[1][0] - m[0][1]) < epsilon && + abs(m[2][0] - m[0][2]) < epsilon && + abs(m[2][1] - m[1][2]) < epsilon; + + if(nearSymmetrical) + { + bool const nearIdentity = + abs(m[1][0] + m[0][1]) < epsilon && + abs(m[2][0] + m[0][2]) < epsilon && + abs(m[2][1] + m[1][2]) < epsilon && + abs(m[0][0] + m[1][1] + m[2][2] - T(3.0)) < epsilon; + if (nearIdentity) + { + angle = static_cast(0.0); + axis = vec<3, T, Q>( + static_cast(1.0), static_cast(0.0), static_cast(0.0)); + return; + } + angle = pi(); + T xx = (m[0][0] + static_cast(1.0)) * static_cast(0.5); + T yy = (m[1][1] + static_cast(1.0)) * static_cast(0.5); + T zz = (m[2][2] + static_cast(1.0)) * static_cast(0.5); + T xy = (m[1][0] + m[0][1]) * static_cast(0.25); + T xz = (m[2][0] + m[0][2]) * static_cast(0.25); + T yz = (m[2][1] + m[1][2]) * static_cast(0.25); + if((xx > yy) && (xx > zz)) + { + if(xx < epsilon) + { + axis.x = static_cast(0.0); + axis.y = static_cast(0.7071); + axis.z = static_cast(0.7071); + } + else + { + axis.x = sqrt(xx); + axis.y = xy / axis.x; + axis.z = xz / axis.x; + } + } + else if (yy > zz) + { + if(yy < epsilon) + { + axis.x = static_cast(0.7071); + axis.y = static_cast(0.0); + axis.z = static_cast(0.7071); + } + else + { + axis.y = sqrt(yy); + axis.x = xy / axis.y; + axis.z = yz / axis.y; + } + } + else + { + if (zz < epsilon) + { + axis.x = static_cast(0.7071); + axis.y = static_cast(0.7071); + axis.z = static_cast(0.0); + } + else + { + axis.z = sqrt(zz); + axis.x = xz / axis.z; + axis.y = yz / axis.z; + } + } + return; + } + + T const angleCos = (m[0][0] + m[1][1] + m[2][2] - static_cast(1)) * static_cast(0.5); + if(angleCos >= static_cast(1.0)) + { + angle = static_cast(0.0); + } + else if (angleCos <= static_cast(-1.0)) + { + angle = pi(); + } + else + { + angle = acos(angleCos); + } + + axis = glm::normalize(glm::vec<3, T, Q>( + m[1][2] - m[2][1], m[2][0] - m[0][2], m[0][1] - m[1][0])); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> axisAngleMatrix(vec<3, T, Q> const& axis, T const angle) + { + T c = cos(angle); + T s = sin(angle); + T t = static_cast(1) - c; + vec<3, T, Q> n = normalize(axis); + + return mat<4, 4, T, Q>( + t * n.x * n.x + c, t * n.x * n.y + n.z * s, t * n.x * n.z - n.y * s, static_cast(0.0), + t * n.x * n.y - n.z * s, t * n.y * n.y + c, t * n.y * n.z + n.x * s, static_cast(0.0), + t * n.x * n.z + n.y * s, t * n.y * n.z - n.x * s, t * n.z * n.z + c, static_cast(0.0), + static_cast(0.0), static_cast(0.0), static_cast(0.0), static_cast(1.0)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> extractMatrixRotation(mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + m[0][0], m[0][1], m[0][2], static_cast(0.0), + m[1][0], m[1][1], m[1][2], static_cast(0.0), + m[2][0], m[2][1], m[2][2], static_cast(0.0), + static_cast(0.0), static_cast(0.0), static_cast(0.0), static_cast(1.0)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> interpolate(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2, T const delta) + { + mat<4, 4, T, Q> m1rot = extractMatrixRotation(m1); + mat<4, 4, T, Q> dltRotation = m2 * transpose(m1rot); + vec<3, T, Q> dltAxis; + T dltAngle; + axisAngle(dltRotation, dltAxis, dltAngle); + mat<4, 4, T, Q> out = axisAngleMatrix(dltAxis, dltAngle * delta) * m1rot; + out[3][0] = m1[3][0] + delta * (m2[3][0] - m1[3][0]); + out[3][1] = m1[3][1] + delta * (m2[3][1] - m1[3][1]); + out[3][2] = m1[3][2] + delta * (m2[3][2] - m1[3][2]); + return out; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_major_storage.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_major_storage.hpp new file mode 100644 index 0000000..f518578 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_major_storage.hpp @@ -0,0 +1,117 @@ +/// @ref gtx_matrix_major_storage +/// @file glm/gtx/matrix_major_storage.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_matrix_major_storage GLM_GTX_matrix_major_storage +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Build matrices with specific matrix order, row or column + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_matrix_major_storage is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_major_storage extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_major_storage + /// @{ + + //! Build a row major matrix from row vectors. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<2, 2, T, Q> rowMajor2( + vec<2, T, Q> const& v1, + vec<2, T, Q> const& v2); + + //! Build a row major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<2, 2, T, Q> rowMajor2( + mat<2, 2, T, Q> const& m); + + //! Build a row major matrix from row vectors. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> rowMajor3( + vec<3, T, Q> const& v1, + vec<3, T, Q> const& v2, + vec<3, T, Q> const& v3); + + //! Build a row major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> rowMajor3( + mat<3, 3, T, Q> const& m); + + //! Build a row major matrix from row vectors. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> rowMajor4( + vec<4, T, Q> const& v1, + vec<4, T, Q> const& v2, + vec<4, T, Q> const& v3, + vec<4, T, Q> const& v4); + + //! Build a row major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> rowMajor4( + mat<4, 4, T, Q> const& m); + + //! Build a column major matrix from column vectors. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<2, 2, T, Q> colMajor2( + vec<2, T, Q> const& v1, + vec<2, T, Q> const& v2); + + //! Build a column major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<2, 2, T, Q> colMajor2( + mat<2, 2, T, Q> const& m); + + //! Build a column major matrix from column vectors. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> colMajor3( + vec<3, T, Q> const& v1, + vec<3, T, Q> const& v2, + vec<3, T, Q> const& v3); + + //! Build a column major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> colMajor3( + mat<3, 3, T, Q> const& m); + + //! Build a column major matrix from column vectors. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> colMajor4( + vec<4, T, Q> const& v1, + vec<4, T, Q> const& v2, + vec<4, T, Q> const& v3, + vec<4, T, Q> const& v4); + + //! Build a column major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> colMajor4( + mat<4, 4, T, Q> const& m); + + /// @} +}//namespace glm + +#include "matrix_major_storage.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_major_storage.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_major_storage.inl new file mode 100644 index 0000000..279dd34 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_major_storage.inl @@ -0,0 +1,166 @@ +/// @ref gtx_matrix_major_storage + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> rowMajor2 + ( + vec<2, T, Q> const& v1, + vec<2, T, Q> const& v2 + ) + { + mat<2, 2, T, Q> Result; + Result[0][0] = v1.x; + Result[1][0] = v1.y; + Result[0][1] = v2.x; + Result[1][1] = v2.y; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> rowMajor2( + const mat<2, 2, T, Q>& m) + { + mat<2, 2, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> rowMajor3( + const vec<3, T, Q>& v1, + const vec<3, T, Q>& v2, + const vec<3, T, Q>& v3) + { + mat<3, 3, T, Q> Result; + Result[0][0] = v1.x; + Result[1][0] = v1.y; + Result[2][0] = v1.z; + Result[0][1] = v2.x; + Result[1][1] = v2.y; + Result[2][1] = v2.z; + Result[0][2] = v3.x; + Result[1][2] = v3.y; + Result[2][2] = v3.z; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> rowMajor3( + const mat<3, 3, T, Q>& m) + { + mat<3, 3, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rowMajor4( + const vec<4, T, Q>& v1, + const vec<4, T, Q>& v2, + const vec<4, T, Q>& v3, + const vec<4, T, Q>& v4) + { + mat<4, 4, T, Q> Result; + Result[0][0] = v1.x; + Result[1][0] = v1.y; + Result[2][0] = v1.z; + Result[3][0] = v1.w; + Result[0][1] = v2.x; + Result[1][1] = v2.y; + Result[2][1] = v2.z; + Result[3][1] = v2.w; + Result[0][2] = v3.x; + Result[1][2] = v3.y; + Result[2][2] = v3.z; + Result[3][2] = v3.w; + Result[0][3] = v4.x; + Result[1][3] = v4.y; + Result[2][3] = v4.z; + Result[3][3] = v4.w; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rowMajor4( + const mat<4, 4, T, Q>& m) + { + mat<4, 4, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[0][3] = m[3][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[1][3] = m[3][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + Result[2][3] = m[3][2]; + Result[3][0] = m[0][3]; + Result[3][1] = m[1][3]; + Result[3][2] = m[2][3]; + Result[3][3] = m[3][3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> colMajor2( + const vec<2, T, Q>& v1, + const vec<2, T, Q>& v2) + { + return mat<2, 2, T, Q>(v1, v2); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> colMajor2( + const mat<2, 2, T, Q>& m) + { + return mat<2, 2, T, Q>(m); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> colMajor3( + const vec<3, T, Q>& v1, + const vec<3, T, Q>& v2, + const vec<3, T, Q>& v3) + { + return mat<3, 3, T, Q>(v1, v2, v3); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> colMajor3( + const mat<3, 3, T, Q>& m) + { + return mat<3, 3, T, Q>(m); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> colMajor4( + const vec<4, T, Q>& v1, + const vec<4, T, Q>& v2, + const vec<4, T, Q>& v3, + const vec<4, T, Q>& v4) + { + return mat<4, 4, T, Q>(v1, v2, v3, v4); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> colMajor4( + const mat<4, 4, T, Q>& m) + { + return mat<4, 4, T, Q>(m); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_operation.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_operation.hpp new file mode 100644 index 0000000..07ed8e8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_operation.hpp @@ -0,0 +1,101 @@ +/// @ref gtx_matrix_operation +/// @file glm/gtx/matrix_operation.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_operation GLM_GTX_matrix_operation +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Build diagonal matrices from vectors. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_matrix_operation is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_operation extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_operation + /// @{ + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<2, 2, T, Q> diagonal2x2( + vec<2, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<2, 3, T, Q> diagonal2x3( + vec<2, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<2, 4, T, Q> diagonal2x4( + vec<2, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<3, 2, T, Q> diagonal3x2( + vec<2, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> diagonal3x3( + vec<3, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<3, 4, T, Q> diagonal3x4( + vec<3, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<4, 2, T, Q> diagonal4x2( + vec<2, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<4, 3, T, Q> diagonal4x3( + vec<3, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> diagonal4x4( + vec<4, T, Q> const& v); + + /// Build an adjugate matrix. + /// From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<2, 2, T, Q> adjugate(mat<2, 2, T, Q> const& m); + + /// Build an adjugate matrix. + /// From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> adjugate(mat<3, 3, T, Q> const& m); + + /// Build an adjugate matrix. + /// From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> adjugate(mat<4, 4, T, Q> const& m); + + /// @} +}//namespace glm + +#include "matrix_operation.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_operation.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_operation.inl new file mode 100644 index 0000000..a4f4a85 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_operation.inl @@ -0,0 +1,176 @@ +/// @ref gtx_matrix_operation + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> diagonal2x2 + ( + vec<2, T, Q> const& v + ) + { + mat<2, 2, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> diagonal2x3 + ( + vec<2, T, Q> const& v + ) + { + mat<2, 3, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> diagonal2x4 + ( + vec<2, T, Q> const& v + ) + { + mat<2, 4, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> diagonal3x2 + ( + vec<2, T, Q> const& v + ) + { + mat<3, 2, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> diagonal3x3 + ( + vec<3, T, Q> const& v + ) + { + mat<3, 3, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> diagonal3x4 + ( + vec<3, T, Q> const& v + ) + { + mat<3, 4, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> diagonal4x4 + ( + vec<4, T, Q> const& v + ) + { + mat<4, 4, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + Result[3][3] = v[3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> diagonal4x3 + ( + vec<3, T, Q> const& v + ) + { + mat<4, 3, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> diagonal4x2 + ( + vec<2, T, Q> const& v + ) + { + mat<4, 2, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> adjugate(mat<2, 2, T, Q> const& m) + { + return mat<2, 2, T, Q>( + +m[1][1], -m[0][1], + -m[1][0], +m[0][0]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> adjugate(mat<3, 3, T, Q> const& m) + { + T const m00 = determinant(mat<2, 2, T, Q>(m[1][1], m[2][1], m[1][2], m[2][2])); + T const m01 = determinant(mat<2, 2, T, Q>(m[0][1], m[2][1], m[0][2], m[2][2])); + T const m02 = determinant(mat<2, 2, T, Q>(m[0][1], m[1][1], m[0][2], m[1][2])); + + T const m10 = determinant(mat<2, 2, T, Q>(m[1][0], m[2][0], m[1][2], m[2][2])); + T const m11 = determinant(mat<2, 2, T, Q>(m[0][0], m[2][0], m[0][2], m[2][2])); + T const m12 = determinant(mat<2, 2, T, Q>(m[0][0], m[1][0], m[0][2], m[1][2])); + + T const m20 = determinant(mat<2, 2, T, Q>(m[1][0], m[2][0], m[1][1], m[2][1])); + T const m21 = determinant(mat<2, 2, T, Q>(m[0][0], m[2][0], m[0][1], m[2][1])); + T const m22 = determinant(mat<2, 2, T, Q>(m[0][0], m[1][0], m[0][1], m[1][1])); + + return mat<3, 3, T, Q>( + +m00, -m01, +m02, + -m10, +m11, -m12, + +m20, -m21, +m22); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> adjugate(mat<4, 4, T, Q> const& m) + { + T const m00 = determinant(mat<3, 3, T, Q>(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3])); + T const m01 = determinant(mat<3, 3, T, Q>(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3])); + T const m02 = determinant(mat<3, 3, T, Q>(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3])); + T const m03 = determinant(mat<3, 3, T, Q>(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2])); + + T const m10 = determinant(mat<3, 3, T, Q>(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3])); + T const m11 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3])); + T const m12 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3])); + T const m13 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2])); + + T const m20 = determinant(mat<3, 3, T, Q>(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], m[3][3])); + T const m21 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], m[3][3])); + T const m22 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], m[3][3])); + T const m23 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], m[3][2])); + + T const m30 = determinant(mat<3, 3, T, Q>(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3])); + T const m31 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3])); + T const m32 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3])); + T const m33 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2])); + + return mat<4, 4, T, Q>( + +m00, -m10, +m20, -m30, + -m01, +m11, -m21, +m31, + +m02, -m12, +m22, -m32, + -m03, +m13, -m23, +m33); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_query.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_query.hpp new file mode 100644 index 0000000..de8c655 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_query.hpp @@ -0,0 +1,75 @@ +/// @ref gtx_matrix_query +/// @file glm/gtx/matrix_query.hpp +/// +/// @see core (dependence) +/// @see gtx_vector_query (dependence) +/// +/// @defgroup gtx_matrix_query GLM_GTX_matrix_query +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Query to evaluate matrix properties + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/vector_query.hpp" +#include + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_matrix_query is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_query extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_query + /// @{ + + /// Return whether a matrix a null matrix. + /// From GLM_GTX_matrix_query extension. + template + GLM_FUNC_DECL bool isNull(mat<2, 2, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix a null matrix. + /// From GLM_GTX_matrix_query extension. + template + GLM_FUNC_DECL bool isNull(mat<3, 3, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix is a null matrix. + /// From GLM_GTX_matrix_query extension. + template + GLM_FUNC_DECL bool isNull(mat<4, 4, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix is an identity matrix. + /// From GLM_GTX_matrix_query extension. + template class matType> + GLM_FUNC_DECL bool isIdentity(matType const& m, T const& epsilon); + + /// Return whether a matrix is a normalized matrix. + /// From GLM_GTX_matrix_query extension. + template + GLM_FUNC_DECL bool isNormalized(mat<2, 2, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix is a normalized matrix. + /// From GLM_GTX_matrix_query extension. + template + GLM_FUNC_DECL bool isNormalized(mat<3, 3, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix is a normalized matrix. + /// From GLM_GTX_matrix_query extension. + template + GLM_FUNC_DECL bool isNormalized(mat<4, 4, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix is an orthonormalized matrix. + /// From GLM_GTX_matrix_query extension. + template class matType> + GLM_FUNC_DECL bool isOrthogonal(matType const& m, T const& epsilon); + + /// @} +}//namespace glm + +#include "matrix_query.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_query.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_query.inl new file mode 100644 index 0000000..dc3ec84 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_query.inl @@ -0,0 +1,119 @@ +/// @ref gtx_matrix_query + +namespace glm +{ + template + GLM_FUNC_QUALIFIER bool isNull(mat<2, 2, T, Q> const& m, T const& epsilon) + { + bool result = true; + for(length_t i = 0; result && i < m.length() ; ++i) + result = isNull(m[i], epsilon); + return result; + } + + template + GLM_FUNC_QUALIFIER bool isNull(mat<3, 3, T, Q> const& m, T const& epsilon) + { + bool result = true; + for(length_t i = 0; result && i < m.length() ; ++i) + result = isNull(m[i], epsilon); + return result; + } + + template + GLM_FUNC_QUALIFIER bool isNull(mat<4, 4, T, Q> const& m, T const& epsilon) + { + bool result = true; + for(length_t i = 0; result && i < m.length() ; ++i) + result = isNull(m[i], epsilon); + return result; + } + + template + GLM_FUNC_QUALIFIER bool isIdentity(mat const& m, T const& epsilon) + { + bool result = true; + for(length_t i = 0; result && i < m.length(); ++i) + { + for(length_t j = 0; result && j < glm::min(i, m[0].length()); ++j) + result = abs(m[i][j]) <= epsilon; + if(result && i < m[0].length()) + result = abs(m[i][i] - 1) <= epsilon; + for(length_t j = i + 1; result && j < m[0].length(); ++j) + result = abs(m[i][j]) <= epsilon; + } + return result; + } + + template + GLM_FUNC_QUALIFIER bool isNormalized(mat<2, 2, T, Q> const& m, T const& epsilon) + { + bool result(true); + for(length_t i = 0; result && i < m.length(); ++i) + result = isNormalized(m[i], epsilon); + for(length_t i = 0; result && i < m.length(); ++i) + { + typename mat<2, 2, T, Q>::col_type v; + for(length_t j = 0; j < m.length(); ++j) + v[j] = m[j][i]; + result = isNormalized(v, epsilon); + } + return result; + } + + template + GLM_FUNC_QUALIFIER bool isNormalized(mat<3, 3, T, Q> const& m, T const& epsilon) + { + bool result(true); + for(length_t i = 0; result && i < m.length(); ++i) + result = isNormalized(m[i], epsilon); + for(length_t i = 0; result && i < m.length(); ++i) + { + typename mat<3, 3, T, Q>::col_type v; + for(length_t j = 0; j < m.length(); ++j) + v[j] = m[j][i]; + result = isNormalized(v, epsilon); + } + return result; + } + + template + GLM_FUNC_QUALIFIER bool isNormalized(mat<4, 4, T, Q> const& m, T const& epsilon) + { + bool result(true); + for(length_t i = 0; result && i < m.length(); ++i) + result = isNormalized(m[i], epsilon); + for(length_t i = 0; result && i < m.length(); ++i) + { + typename mat<4, 4, T, Q>::col_type v; + for(length_t j = 0; j < m.length(); ++j) + v[j] = m[j][i]; + result = isNormalized(v, epsilon); + } + return result; + } + + template + GLM_FUNC_QUALIFIER bool isOrthogonal(mat const& m, T const& epsilon) + { + bool result = true; + for(length_t i(0); result && i < m.length(); ++i) + { + result = isNormalized(m[i], epsilon); + for(length_t j(i + 1); result && j < m.length(); ++j) + result = abs(dot(m[i], m[j])) <= epsilon; + } + + if(result) + { + mat tmp = transpose(m); + for(length_t i(0); result && i < m.length(); ++i) + { + result = isNormalized(tmp[i], epsilon); + for(length_t j(i + 1); result && j < m.length(); ++j) + result = abs(dot(tmp[i], tmp[j])) <= epsilon; + } + } + return result; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_transform_2d.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_transform_2d.hpp new file mode 100644 index 0000000..deb8da2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_transform_2d.hpp @@ -0,0 +1,79 @@ +/// @ref gtx_matrix_transform_2d +/// @file glm/gtx/matrix_transform_2d.hpp +/// @author Miguel Ángel Pérez Martínez +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_transform_2d GLM_GTX_matrix_transform_2d +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defines functions that generate common 2d transformation matrices. + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" +#include "../vec2.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_matrix_transform_2d is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_transform_2d extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_transform_2d + /// @{ + + /// Builds a translation 3 * 3 matrix created from a vector of 2 components. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param v Coordinates of a translation vector. + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> translate( + mat<3, 3, T, Q> const& m, + vec<2, T, Q> const& v); + + /// Builds a rotation 3 * 3 matrix created from an angle. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param angle Rotation angle expressed in radians. + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> rotate( + mat<3, 3, T, Q> const& m, + T angle); + + /// Builds a scale 3 * 3 matrix created from a vector of 2 components. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param v Coordinates of a scale vector. + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> scale( + mat<3, 3, T, Q> const& m, + vec<2, T, Q> const& v); + + /// Builds an horizontal (parallel to the x axis) shear 3 * 3 matrix. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param y Shear factor. + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> shearX( + mat<3, 3, T, Q> const& m, + T y); + + /// Builds a vertical (parallel to the y axis) shear 3 * 3 matrix. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param x Shear factor. + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> shearY( + mat<3, 3, T, Q> const& m, + T x); + + /// @} +}//namespace glm + +#include "matrix_transform_2d.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_transform_2d.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_transform_2d.inl new file mode 100644 index 0000000..a68d24d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_transform_2d.inl @@ -0,0 +1,68 @@ +/// @ref gtx_matrix_transform_2d +/// @author Miguel Ángel Pérez Martínez + +#include "../trigonometric.hpp" + +namespace glm +{ + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> translate( + mat<3, 3, T, Q> const& m, + vec<2, T, Q> const& v) + { + mat<3, 3, T, Q> Result(m); + Result[2] = m[0] * v[0] + m[1] * v[1] + m[2]; + return Result; + } + + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> rotate( + mat<3, 3, T, Q> const& m, + T angle) + { + T const a = angle; + T const c = cos(a); + T const s = sin(a); + + mat<3, 3, T, Q> Result; + Result[0] = m[0] * c + m[1] * s; + Result[1] = m[0] * -s + m[1] * c; + Result[2] = m[2]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> scale( + mat<3, 3, T, Q> const& m, + vec<2, T, Q> const& v) + { + mat<3, 3, T, Q> Result; + Result[0] = m[0] * v[0]; + Result[1] = m[1] * v[1]; + Result[2] = m[2]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> shearX( + mat<3, 3, T, Q> const& m, + T y) + { + mat<3, 3, T, Q> Result(1); + Result[0][1] = y; + return m * Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> shearY( + mat<3, 3, T, Q> const& m, + T x) + { + mat<3, 3, T, Q> Result(1); + Result[1][0] = x; + return m * Result; + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/mixed_product.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/mixed_product.hpp new file mode 100644 index 0000000..a091274 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/mixed_product.hpp @@ -0,0 +1,39 @@ +/// @ref gtx_mixed_product +/// @file glm/gtx/mixed_product.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_mixed_product GLM_GTX_mixed_producte +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Mixed product of 3 vectors. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_mixed_product is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_mixed_product extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_mixed_product + /// @{ + + /// @brief Mixed product of 3 vectors (from GLM_GTX_mixed_product extension) + template + GLM_FUNC_DECL T mixedProduct( + vec<3, T, Q> const& v1, + vec<3, T, Q> const& v2, + vec<3, T, Q> const& v3); + + /// @} +}// namespace glm + +#include "mixed_product.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/mixed_product.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/mixed_product.inl new file mode 100644 index 0000000..e5cdbdb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/mixed_product.inl @@ -0,0 +1,15 @@ +/// @ref gtx_mixed_product + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T mixedProduct + ( + vec<3, T, Q> const& v1, + vec<3, T, Q> const& v2, + vec<3, T, Q> const& v3 + ) + { + return dot(cross(v1, v2), v3); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/norm.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/norm.hpp new file mode 100644 index 0000000..d6724a8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/norm.hpp @@ -0,0 +1,86 @@ +/// @ref gtx_norm +/// @file glm/gtx/norm.hpp +/// +/// @see core (dependence) +/// @see gtx_quaternion (dependence) +/// @see gtx_component_wise (dependence) +/// +/// @defgroup gtx_norm GLM_GTX_norm +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Various ways to compute vector norms. + +#pragma once + +// Dependency: +#include "../geometric.hpp" +#include "../gtx/quaternion.hpp" +#include "../gtx/component_wise.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_norm is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_norm extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_norm + /// @{ + + /// Returns the squared length of x. + /// From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T length2(vec const& x); + + /// Returns the squared distance between p0 and p1, i.e., length2(p0 - p1). + /// From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T distance2(vec const& p0, vec const& p1); + + //! Returns the L1 norm between x and y. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T l1Norm(vec<3, T, Q> const& x, vec<3, T, Q> const& y); + + //! Returns the L1 norm of v. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T l1Norm(vec<3, T, Q> const& v); + + //! Returns the L2 norm between x and y. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T l2Norm(vec<3, T, Q> const& x, vec<3, T, Q> const& y); + + //! Returns the L2 norm of v. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T l2Norm(vec<3, T, Q> const& x); + + //! Returns the L norm between x and y. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T lxNorm(vec<3, T, Q> const& x, vec<3, T, Q> const& y, unsigned int Depth); + + //! Returns the L norm of v. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T lxNorm(vec<3, T, Q> const& x, unsigned int Depth); + + //! Returns the LMax norm between x and y. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T lMaxNorm(vec<3, T, Q> const& x, vec<3, T, Q> const& y); + + //! Returns the LMax norm of v. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T lMaxNorm(vec<3, T, Q> const& x); + + /// @} +}//namespace glm + +#include "norm.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/norm.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/norm.inl new file mode 100644 index 0000000..4a9f796 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/norm.inl @@ -0,0 +1,95 @@ +/// @ref gtx_norm + +#include "../detail/qualifier.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_length2 + { + GLM_FUNC_QUALIFIER static T call(vec const& v) + { + return dot(v, v); + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER genType length2(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'length2' accepts only floating-point inputs"); + return x * x; + } + + template + GLM_FUNC_QUALIFIER T length2(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'length2' accepts only floating-point inputs"); + return detail::compute_length2::value>::call(v); + } + + template + GLM_FUNC_QUALIFIER T distance2(T p0, T p1) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'distance2' accepts only floating-point inputs"); + return length2(p1 - p0); + } + + template + GLM_FUNC_QUALIFIER T distance2(vec const& p0, vec const& p1) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'distance2' accepts only floating-point inputs"); + return length2(p1 - p0); + } + + template + GLM_FUNC_QUALIFIER T l1Norm(vec<3, T, Q> const& a, vec<3, T, Q> const& b) + { + return abs(b.x - a.x) + abs(b.y - a.y) + abs(b.z - a.z); + } + + template + GLM_FUNC_QUALIFIER T l1Norm(vec<3, T, Q> const& v) + { + return abs(v.x) + abs(v.y) + abs(v.z); + } + + template + GLM_FUNC_QUALIFIER T l2Norm(vec<3, T, Q> const& a, vec<3, T, Q> const& b + ) + { + return length(b - a); + } + + template + GLM_FUNC_QUALIFIER T l2Norm(vec<3, T, Q> const& v) + { + return length(v); + } + + template + GLM_FUNC_QUALIFIER T lxNorm(vec<3, T, Q> const& x, vec<3, T, Q> const& y, unsigned int Depth) + { + return pow(pow(abs(y.x - x.x), T(Depth)) + pow(abs(y.y - x.y), T(Depth)) + pow(abs(y.z - x.z), T(Depth)), T(1) / T(Depth)); + } + + template + GLM_FUNC_QUALIFIER T lxNorm(vec<3, T, Q> const& v, unsigned int Depth) + { + return pow(pow(abs(v.x), T(Depth)) + pow(abs(v.y), T(Depth)) + pow(abs(v.z), T(Depth)), T(1) / T(Depth)); + } + + template + GLM_FUNC_QUALIFIER T lMaxNorm(vec<3, T, Q> const& a, vec<3, T, Q> const& b) + { + return compMax(abs(b - a)); + } + + template + GLM_FUNC_QUALIFIER T lMaxNorm(vec<3, T, Q> const& v) + { + return compMax(abs(v)); + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normal.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normal.hpp new file mode 100644 index 0000000..8b3a4b5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normal.hpp @@ -0,0 +1,39 @@ +/// @ref gtx_normal +/// @file glm/gtx/normal.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_normal GLM_GTX_normal +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Compute the normal of a triangle. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_normal is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_normal extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_normal + /// @{ + + /// Computes triangle normal from triangle points. + /// + /// @see gtx_normal + template + GLM_FUNC_DECL vec<3, T, Q> triangleNormal(vec<3, T, Q> const& p1, vec<3, T, Q> const& p2, vec<3, T, Q> const& p3); + + /// @} +}//namespace glm + +#include "normal.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normal.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normal.inl new file mode 100644 index 0000000..74f9fc9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normal.inl @@ -0,0 +1,15 @@ +/// @ref gtx_normal + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> triangleNormal + ( + vec<3, T, Q> const& p1, + vec<3, T, Q> const& p2, + vec<3, T, Q> const& p3 + ) + { + return normalize(cross(p1 - p2, p1 - p3)); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normalize_dot.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normalize_dot.hpp new file mode 100644 index 0000000..04a6b08 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normalize_dot.hpp @@ -0,0 +1,47 @@ +/// @ref gtx_normalize_dot +/// @file glm/gtx/normalize_dot.hpp +/// +/// @see core (dependence) +/// @see gtx_fast_square_root (dependence) +/// +/// @defgroup gtx_normalize_dot GLM_GTX_normalize_dot +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Dot product of vectors that need to be normalize with a single square root. + +#pragma once + +// Dependency: +#include "../gtx/fast_square_root.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_normalize_dot is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_normalize_dot extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_normalize_dot + /// @{ + + /// Normalize parameters and returns the dot product of x and y. + /// It's faster that dot(normalize(x), normalize(y)). + /// + /// @see gtx_normalize_dot extension. + template + GLM_FUNC_DECL T normalizeDot(vec const& x, vec const& y); + + /// Normalize parameters and returns the dot product of x and y. + /// Faster that dot(fastNormalize(x), fastNormalize(y)). + /// + /// @see gtx_normalize_dot extension. + template + GLM_FUNC_DECL T fastNormalizeDot(vec const& x, vec const& y); + + /// @} +}//namespace glm + +#include "normalize_dot.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normalize_dot.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normalize_dot.inl new file mode 100644 index 0000000..7bcd9a5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normalize_dot.inl @@ -0,0 +1,16 @@ +/// @ref gtx_normalize_dot + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T normalizeDot(vec const& x, vec const& y) + { + return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y)); + } + + template + GLM_FUNC_QUALIFIER T fastNormalizeDot(vec const& x, vec const& y) + { + return glm::dot(x, y) * glm::fastInverseSqrt(glm::dot(x, x) * glm::dot(y, y)); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/number_precision.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/number_precision.hpp new file mode 100644 index 0000000..5b9663e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/number_precision.hpp @@ -0,0 +1,44 @@ +/// @ref gtx_number_precision +/// @file glm/gtx/number_precision.hpp +/// +/// @see core (dependence) +/// @see gtc_type_precision (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_number_precision GLM_GTX_number_precision +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defined size types. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/type_precision.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_number_precision is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_number_precision extension included") +#endif + +namespace glm{ + ///////////////////////////// + // Unsigned int vector types + + /// @addtogroup gtx_number_precision + /// @{ + + ////////////////////// + // Float matrix types + + typedef f32 f32mat1; //!< \brief Single-qualifier floating-point scalar. (from GLM_GTX_number_precision extension) + typedef f32 f32mat1x1; //!< \brief Single-qualifier floating-point scalar. (from GLM_GTX_number_precision extension) + typedef f64 f64mat1; //!< \brief Double-qualifier floating-point scalar. (from GLM_GTX_number_precision extension) + typedef f64 f64mat1x1; //!< \brief Double-qualifier floating-point scalar. (from GLM_GTX_number_precision extension) + + /// @} +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/optimum_pow.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/optimum_pow.hpp new file mode 100644 index 0000000..ac34e7e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/optimum_pow.hpp @@ -0,0 +1,50 @@ +/// @ref gtx_optimum_pow +/// @file glm/gtx/optimum_pow.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_optimum_pow GLM_GTX_optimum_pow +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Integer exponentiation of power functions. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_optimum_pow is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_optimum_pow extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_optimum_pow + /// @{ + + /// Returns x raised to the power of 2. + /// + /// @see gtx_optimum_pow + template + GLM_FUNC_DECL genType pow2(genType const& x); + + /// Returns x raised to the power of 3. + /// + /// @see gtx_optimum_pow + template + GLM_FUNC_DECL genType pow3(genType const& x); + + /// Returns x raised to the power of 4. + /// + /// @see gtx_optimum_pow + template + GLM_FUNC_DECL genType pow4(genType const& x); + + /// @} +}//namespace glm + +#include "optimum_pow.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/optimum_pow.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/optimum_pow.inl new file mode 100644 index 0000000..a26c19c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/optimum_pow.inl @@ -0,0 +1,22 @@ +/// @ref gtx_optimum_pow + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType pow2(genType const& x) + { + return x * x; + } + + template + GLM_FUNC_QUALIFIER genType pow3(genType const& x) + { + return x * x * x; + } + + template + GLM_FUNC_QUALIFIER genType pow4(genType const& x) + { + return (x * x) * (x * x); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/orthonormalize.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/orthonormalize.hpp new file mode 100644 index 0000000..801b755 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/orthonormalize.hpp @@ -0,0 +1,47 @@ +/// @ref gtx_orthonormalize +/// @file glm/gtx/orthonormalize.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_orthonormalize GLM_GTX_orthonormalize +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Orthonormalize matrices. + +#pragma once + +// Dependency: +#include "../vec3.hpp" +#include "../mat3x3.hpp" +#include "../geometric.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_orthonormalize is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_orthonormalize extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_orthonormalize + /// @{ + + /// Returns the orthonormalized matrix of m. + /// + /// @see gtx_orthonormalize + template + GLM_FUNC_DECL mat<3, 3, T, Q> orthonormalize(mat<3, 3, T, Q> const& m); + + /// Orthonormalizes x according y. + /// + /// @see gtx_orthonormalize + template + GLM_FUNC_DECL vec<3, T, Q> orthonormalize(vec<3, T, Q> const& x, vec<3, T, Q> const& y); + + /// @} +}//namespace glm + +#include "orthonormalize.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/orthonormalize.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/orthonormalize.inl new file mode 100644 index 0000000..cb553ba --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/orthonormalize.inl @@ -0,0 +1,29 @@ +/// @ref gtx_orthonormalize + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> orthonormalize(mat<3, 3, T, Q> const& m) + { + mat<3, 3, T, Q> r = m; + + r[0] = normalize(r[0]); + + T d0 = dot(r[0], r[1]); + r[1] -= r[0] * d0; + r[1] = normalize(r[1]); + + T d1 = dot(r[1], r[2]); + d0 = dot(r[0], r[2]); + r[2] -= r[0] * d0 + r[1] * d1; + r[2] = normalize(r[2]); + + return r; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> orthonormalize(vec<3, T, Q> const& x, vec<3, T, Q> const& y) + { + return normalize(x - y * dot(y, x)); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/pca.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/pca.hpp new file mode 100644 index 0000000..26f9aec --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/pca.hpp @@ -0,0 +1,112 @@ +/// @ref gtx_pca +/// @file glm/gtx/pca.hpp +/// +/// @see core (dependence) +/// @see ext_scalar_relational (dependence) +/// +/// @defgroup gtx_pca GLM_GTX_pca +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Implements functions required for fundamental 'princple component analysis' in 2D, 3D, and 4D: +/// 1) Computing a covariance matrics from a list of _relative_ position vectors +/// 2) Compute the eigenvalues and eigenvectors of the covariance matrics +/// This is useful, e.g., to compute an object-aligned bounding box from vertices of an object. +/// https://en.wikipedia.org/wiki/Principal_component_analysis +/// +/// Example: +/// ``` +/// std::vector ptData; +/// // ... fill ptData with some point data, e.g. vertices +/// +/// glm::dvec3 center = computeCenter(ptData); +/// +/// glm::dmat3 covarMat = glm::computeCovarianceMatrix(ptData.data(), ptData.size(), center); +/// +/// glm::dvec3 evals; +/// glm::dmat3 evecs; +/// int evcnt = glm::findEigenvaluesSymReal(covarMat, evals, evecs); +/// +/// if(evcnt != 3) +/// // ... error handling +/// +/// glm::sortEigenvalues(evals, evecs); +/// +/// // ... now evecs[0] points in the direction (symmetric) of the largest spatial distribution within ptData +/// ``` + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../ext/scalar_relational.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_pca is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_pca extension included") +#endif + +namespace glm { + /// @addtogroup gtx_pca + /// @{ + + /// Compute a covariance matrix form an array of relative coordinates `v` (e.g., relative to the center of gravity of the object) + /// @param v Points to a memory holding `n` times vectors + /// @param n Number of points in v + template + GLM_INLINE mat computeCovarianceMatrix(vec const* v, size_t n); + + /// Compute a covariance matrix form an array of absolute coordinates `v` and a precomputed center of gravity `c` + /// @param v Points to a memory holding `n` times vectors + /// @param n Number of points in v + /// @param c Precomputed center of gravity + template + GLM_INLINE mat computeCovarianceMatrix(vec const* v, size_t n, vec const& c); + + /// Compute a covariance matrix form a pair of iterators `b` (begin) and `e` (end) of a container with relative coordinates (e.g., relative to the center of gravity of the object) + /// Dereferencing an iterator of type I must yield a `vec<D, T, Q%gt;` + template + GLM_FUNC_DECL mat computeCovarianceMatrix(I const& b, I const& e); + + /// Compute a covariance matrix form a pair of iterators `b` (begin) and `e` (end) of a container with absolute coordinates and a precomputed center of gravity `c` + /// Dereferencing an iterator of type I must yield a `vec<D, T, Q%gt;` + template + GLM_FUNC_DECL mat computeCovarianceMatrix(I const& b, I const& e, vec const& c); + + /// Assuming the provided covariance matrix `covarMat` is symmetric and real-valued, this function find the `D` Eigenvalues of the matrix, and also provides the corresponding Eigenvectors. + /// Note: the data in `outEigenvalues` and `outEigenvectors` are in matching order, i.e. `outEigenvector[i]` is the Eigenvector of the Eigenvalue `outEigenvalue[i]`. + /// This is a numeric implementation to find the Eigenvalues, using 'QL decomposition` (variant of QR decomposition: https://en.wikipedia.org/wiki/QR_decomposition). + /// + /// @param[in] covarMat A symmetric, real-valued covariance matrix, e.g. computed from computeCovarianceMatrix + /// @param[out] outEigenvalues Vector to receive the found eigenvalues + /// @param[out] outEigenvectors Matrix to receive the found eigenvectors corresponding to the found eigenvalues, as column vectors + /// @return The number of eigenvalues found, usually D if the precondition of the covariance matrix is met. + template + GLM_FUNC_DECL unsigned int findEigenvaluesSymReal + ( + mat const& covarMat, + vec& outEigenvalues, + mat& outEigenvectors + ); + + /// Sorts a group of Eigenvalues&Eigenvectors, for largest Eigenvalue to smallest Eigenvalue. + /// The data in `outEigenvalues` and `outEigenvectors` are assumed to be matching order, i.e. `outEigenvector[i]` is the Eigenvector of the Eigenvalue `outEigenvalue[i]`. + template + GLM_FUNC_DISCARD_DECL void sortEigenvalues(vec<2, T, Q>& eigenvalues, mat<2, 2, T, Q>& eigenvectors); + + /// Sorts a group of Eigenvalues&Eigenvectors, for largest Eigenvalue to smallest Eigenvalue. + /// The data in `outEigenvalues` and `outEigenvectors` are assumed to be matching order, i.e. `outEigenvector[i]` is the Eigenvector of the Eigenvalue `outEigenvalue[i]`. + template + GLM_FUNC_DISCARD_DECL void sortEigenvalues(vec<3, T, Q>& eigenvalues, mat<3, 3, T, Q>& eigenvectors); + + /// Sorts a group of Eigenvalues&Eigenvectors, for largest Eigenvalue to smallest Eigenvalue. + /// The data in `outEigenvalues` and `outEigenvectors` are assumed to be matching order, i.e. `outEigenvector[i]` is the Eigenvector of the Eigenvalue `outEigenvalue[i]`. + template + GLM_FUNC_DISCARD_DECL void sortEigenvalues(vec<4, T, Q>& eigenvalues, mat<4, 4, T, Q>& eigenvectors); + + /// @} +}//namespace glm + +#include "pca.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/pca.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/pca.inl new file mode 100644 index 0000000..94cae94 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/pca.inl @@ -0,0 +1,343 @@ +/// @ref gtx_pca + +#ifndef GLM_HAS_CXX11_STL +#include +#else +#include +#endif + +namespace glm { + + + template + GLM_FUNC_QUALIFIER mat computeCovarianceMatrix(vec const* v, size_t n) + { + return computeCovarianceMatrix const*>(v, v + n); + } + + + template + GLM_FUNC_QUALIFIER mat computeCovarianceMatrix(vec const* v, size_t n, vec const& c) + { + return computeCovarianceMatrix const*>(v, v + n, c); + } + + + template + GLM_FUNC_QUALIFIER mat computeCovarianceMatrix(I const& b, I const& e) + { + glm::mat m(0); + + size_t cnt = 0; + for(I i = b; i != e; i++) + { + vec const& v = *i; + for(length_t x = 0; x < D; ++x) + for(length_t y = 0; y < D; ++y) + m[x][y] += static_cast(v[x] * v[y]); + cnt++; + } + if(cnt > 0) + m /= static_cast(cnt); + + return m; + } + + + template + GLM_FUNC_QUALIFIER mat computeCovarianceMatrix(I const& b, I const& e, vec const& c) + { + glm::mat m(0); + glm::vec v; + + size_t cnt = 0; + for(I i = b; i != e; i++) + { + v = *i - c; + for(length_t x = 0; x < D; ++x) + for(length_t y = 0; y < D; ++y) + m[x][y] += static_cast(v[x] * v[y]); + cnt++; + } + if(cnt > 0) + m /= static_cast(cnt); + + return m; + } + + namespace _internal_ + { + + template + GLM_FUNC_QUALIFIER static T transferSign(T const& v, T const& s) + { + return ((s) >= 0 ? glm::abs(v) : -glm::abs(v)); + } + + template + GLM_FUNC_QUALIFIER static T pythag(T const& a, T const& b) { + static const T epsilon = static_cast(0.0000001); + T absa = glm::abs(a); + T absb = glm::abs(b); + if(absa > absb) { + absb /= absa; + absb *= absb; + return absa * glm::sqrt(static_cast(1) + absb); + } + if(glm::equal(absb, 0, epsilon)) return static_cast(0); + absa /= absb; + absa *= absa; + return absb * glm::sqrt(static_cast(1) + absa); + } + + } + + template + GLM_FUNC_QUALIFIER unsigned int findEigenvaluesSymReal + ( + mat const& covarMat, + vec& outEigenvalues, + mat& outEigenvectors + ) + { + using _internal_::transferSign; + using _internal_::pythag; + + T a[D * D]; // matrix -- input and workspace for algorithm (will be changed inplace) + T d[D]; // diagonal elements + T e[D]; // off-diagonal elements + + for(length_t r = 0; r < D; r++) + for(length_t c = 0; c < D; c++) + a[(r) * D + (c)] = covarMat[c][r]; + + // 1. Householder reduction. + length_t l, k, j, i; + T scale, hh, h, g, f; + static const T epsilon = static_cast(0.0000001); + + for(i = D; i >= 2; i--) + { + l = i - 1; + h = scale = 0; + if(l > 1) + { + for(k = 1; k <= l; k++) + { + scale += glm::abs(a[(i - 1) * D + (k - 1)]); + } + if(glm::equal(scale, 0, epsilon)) + { + e[i - 1] = a[(i - 1) * D + (l - 1)]; + } + else + { + for(k = 1; k <= l; k++) + { + a[(i - 1) * D + (k - 1)] /= scale; + h += a[(i - 1) * D + (k - 1)] * a[(i - 1) * D + (k - 1)]; + } + f = a[(i - 1) * D + (l - 1)]; + g = ((f >= 0) ? -glm::sqrt(h) : glm::sqrt(h)); + e[i - 1] = scale * g; + h -= f * g; + a[(i - 1) * D + (l - 1)] = f - g; + f = 0; + for(j = 1; j <= l; j++) + { + a[(j - 1) * D + (i - 1)] = a[(i - 1) * D + (j - 1)] / h; + g = 0; + for(k = 1; k <= j; k++) + { + g += a[(j - 1) * D + (k - 1)] * a[(i - 1) * D + (k - 1)]; + } + for(k = j + 1; k <= l; k++) + { + g += a[(k - 1) * D + (j - 1)] * a[(i - 1) * D + (k - 1)]; + } + e[j - 1] = g / h; + f += e[j - 1] * a[(i - 1) * D + (j - 1)]; + } + hh = f / (h + h); + for(j = 1; j <= l; j++) + { + f = a[(i - 1) * D + (j - 1)]; + e[j - 1] = g = e[j - 1] - hh * f; + for(k = 1; k <= j; k++) + { + a[(j - 1) * D + (k - 1)] -= (f * e[k - 1] + g * a[(i - 1) * D + (k - 1)]); + } + } + } + } + else + { + e[i - 1] = a[(i - 1) * D + (l - 1)]; + } + d[i - 1] = h; + } + d[0] = 0; + e[0] = 0; + for(i = 1; i <= D; i++) + { + l = i - 1; + if(!glm::equal(d[i - 1], 0, epsilon)) + { + for(j = 1; j <= l; j++) + { + g = 0; + for(k = 1; k <= l; k++) + { + g += a[(i - 1) * D + (k - 1)] * a[(k - 1) * D + (j - 1)]; + } + for(k = 1; k <= l; k++) + { + a[(k - 1) * D + (j - 1)] -= g * a[(k - 1) * D + (i - 1)]; + } + } + } + d[i - 1] = a[(i - 1) * D + (i - 1)]; + a[(i - 1) * D + (i - 1)] = 1; + for(j = 1; j <= l; j++) + { + a[(j - 1) * D + (i - 1)] = a[(i - 1) * D + (j - 1)] = 0; + } + } + + // 2. Calculation of eigenvalues and eigenvectors (QL algorithm) + length_t m, iter; + T s, r, p, dd, c, b; + const length_t MAX_ITER = 30; + + for(i = 2; i <= D; i++) + { + e[i - 2] = e[i - 1]; + } + e[D - 1] = 0; + + for(l = 1; l <= D; l++) + { + iter = 0; + do + { + for(m = l; m <= D - 1; m++) + { + dd = glm::abs(d[m - 1]) + glm::abs(d[m - 1 + 1]); + if(glm::equal(glm::abs(e[m - 1]) + dd, dd, epsilon)) + break; + } + if(m != l) + { + if(iter++ == MAX_ITER) + { + return 0; // Too many iterations in FindEigenvalues + } + g = (d[l - 1 + 1] - d[l - 1]) / (2 * e[l - 1]); + r = pythag(g, 1); + g = d[m - 1] - d[l - 1] + e[l - 1] / (g + transferSign(r, g)); + s = c = 1; + p = 0; + for(i = m - 1; i >= l; i--) + { + f = s * e[i - 1]; + b = c * e[i - 1]; + e[i - 1 + 1] = r = pythag(f, g); + if(glm::equal(r, 0, epsilon)) + { + d[i - 1 + 1] -= p; + e[m - 1] = 0; + break; + } + s = f / r; + c = g / r; + g = d[i - 1 + 1] - p; + r = (d[i - 1] - g) * s + 2 * c * b; + d[i - 1 + 1] = g + (p = s * r); + g = c * r - b; + for(k = 1; k <= D; k++) + { + f = a[(k - 1) * D + (i - 1 + 1)]; + a[(k - 1) * D + (i - 1 + 1)] = s * a[(k - 1) * D + (i - 1)] + c * f; + a[(k - 1) * D + (i - 1)] = c * a[(k - 1) * D + (i - 1)] - s * f; + } + } + if(glm::equal(r, 0, epsilon) && (i >= l)) + continue; + d[l - 1] -= p; + e[l - 1] = g; + e[m - 1] = 0; + } + } while(m != l); + } + + // 3. output + for(i = 0; i < D; i++) + outEigenvalues[i] = d[i]; + for(i = 0; i < D; i++) + for(j = 0; j < D; j++) + outEigenvectors[i][j] = a[(j) * D + (i)]; + + return D; + } + + template + GLM_FUNC_QUALIFIER void sortEigenvalues(vec<2, T, Q>& eigenvalues, mat<2, 2, T, Q>& eigenvectors) + { + if (eigenvalues[0] < eigenvalues[1]) + { + std::swap(eigenvalues[0], eigenvalues[1]); + std::swap(eigenvectors[0], eigenvectors[1]); + } + } + + template + GLM_FUNC_QUALIFIER void sortEigenvalues(vec<3, T, Q>& eigenvalues, mat<3, 3, T, Q>& eigenvectors) + { + if (eigenvalues[0] < eigenvalues[1]) + { + std::swap(eigenvalues[0], eigenvalues[1]); + std::swap(eigenvectors[0], eigenvectors[1]); + } + if (eigenvalues[0] < eigenvalues[2]) + { + std::swap(eigenvalues[0], eigenvalues[2]); + std::swap(eigenvectors[0], eigenvectors[2]); + } + if (eigenvalues[1] < eigenvalues[2]) + { + std::swap(eigenvalues[1], eigenvalues[2]); + std::swap(eigenvectors[1], eigenvectors[2]); + } + } + + template + GLM_FUNC_QUALIFIER void sortEigenvalues(vec<4, T, Q>& eigenvalues, mat<4, 4, T, Q>& eigenvectors) + { + if (eigenvalues[0] < eigenvalues[2]) + { + std::swap(eigenvalues[0], eigenvalues[2]); + std::swap(eigenvectors[0], eigenvectors[2]); + } + if (eigenvalues[1] < eigenvalues[3]) + { + std::swap(eigenvalues[1], eigenvalues[3]); + std::swap(eigenvectors[1], eigenvectors[3]); + } + if (eigenvalues[0] < eigenvalues[1]) + { + std::swap(eigenvalues[0], eigenvalues[1]); + std::swap(eigenvectors[0], eigenvectors[1]); + } + if (eigenvalues[2] < eigenvalues[3]) + { + std::swap(eigenvalues[2], eigenvalues[3]); + std::swap(eigenvectors[2], eigenvectors[3]); + } + if (eigenvalues[1] < eigenvalues[2]) + { + std::swap(eigenvalues[1], eigenvalues[2]); + std::swap(eigenvectors[1], eigenvectors[2]); + } + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/perpendicular.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/perpendicular.hpp new file mode 100644 index 0000000..4087ab0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/perpendicular.hpp @@ -0,0 +1,39 @@ +/// @ref gtx_perpendicular +/// @file glm/gtx/perpendicular.hpp +/// +/// @see core (dependence) +/// @see gtx_projection (dependence) +/// +/// @defgroup gtx_perpendicular GLM_GTX_perpendicular +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Perpendicular of a vector from other one + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/projection.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_perpendicular is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_perpendicular extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_perpendicular + /// @{ + + //! Projects x a perpendicular axis of Normal. + //! From GLM_GTX_perpendicular extension. + template + GLM_FUNC_DECL genType perp(genType const& x, genType const& Normal); + + /// @} +}//namespace glm + +#include "perpendicular.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/perpendicular.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/perpendicular.inl new file mode 100644 index 0000000..1e72f33 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/perpendicular.inl @@ -0,0 +1,10 @@ +/// @ref gtx_perpendicular + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType perp(genType const& x, genType const& Normal) + { + return x - proj(x, Normal); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/polar_coordinates.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/polar_coordinates.hpp new file mode 100644 index 0000000..c27aacf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/polar_coordinates.hpp @@ -0,0 +1,46 @@ +/// @ref gtx_polar_coordinates +/// @file glm/gtx/polar_coordinates.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_polar_coordinates GLM_GTX_polar_coordinates +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Conversion from Euclidean space to polar space and revert. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_polar_coordinates is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_polar_coordinates extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_polar_coordinates + /// @{ + + /// Convert Euclidean to Polar coordinates, x is the latitude, y the longitude and z the xz distance. + /// + /// @see gtx_polar_coordinates + template + GLM_FUNC_DECL vec<3, T, Q> polar( + vec<3, T, Q> const& euclidean); + + /// Convert Polar to Euclidean coordinates. + /// + /// @see gtx_polar_coordinates + template + GLM_FUNC_DECL vec<3, T, Q> euclidean( + vec<2, T, Q> const& polar); + + /// @} +}//namespace glm + +#include "polar_coordinates.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/polar_coordinates.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/polar_coordinates.inl new file mode 100644 index 0000000..371c8dd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/polar_coordinates.inl @@ -0,0 +1,36 @@ +/// @ref gtx_polar_coordinates + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> polar + ( + vec<3, T, Q> const& euclidean + ) + { + T const Length(length(euclidean)); + vec<3, T, Q> const tmp(euclidean / Length); + T const xz_dist(sqrt(tmp.x * tmp.x + tmp.z * tmp.z)); + + return vec<3, T, Q>( + asin(tmp.y), // latitude + atan(tmp.x, tmp.z), // longitude + xz_dist); // xz distance + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> euclidean + ( + vec<2, T, Q> const& polar + ) + { + T const latitude(polar.x); + T const longitude(polar.y); + + return vec<3, T, Q>( + cos(latitude) * sin(longitude), + sin(latitude), + cos(latitude) * cos(longitude)); + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/projection.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/projection.hpp new file mode 100644 index 0000000..a438f39 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/projection.hpp @@ -0,0 +1,41 @@ +/// @ref gtx_projection +/// @file glm/gtx/projection.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_projection GLM_GTX_projection +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Projection of a vector to other one + +#pragma once + +// Dependency: +#include "../geometric.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_projection is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_projection extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_projection + /// @{ + + /// Projects x on Normal. + /// + /// @param[in] x A vector to project + /// @param[in] Normal A normal that doesn't need to be of unit length. + /// + /// @see gtx_projection + template + GLM_FUNC_DECL genType proj(genType const& x, genType const& Normal); + + /// @} +}//namespace glm + +#include "projection.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/projection.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/projection.inl new file mode 100644 index 0000000..f23f884 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/projection.inl @@ -0,0 +1,10 @@ +/// @ref gtx_projection + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType proj(genType const& x, genType const& Normal) + { + return glm::dot(x, Normal) / glm::dot(Normal, Normal) * Normal; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/quaternion.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/quaternion.hpp new file mode 100644 index 0000000..f51c521 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/quaternion.hpp @@ -0,0 +1,172 @@ +/// @ref gtx_quaternion +/// @file glm/gtx/quaternion.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_quaternion GLM_GTX_quaternion +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Extended quaternion types and functions + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/constants.hpp" +#include "../gtc/quaternion.hpp" +#include "../ext/quaternion_exponential.hpp" +#include "../gtx/norm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_quaternion is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_quaternion extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_quaternion + /// @{ + + /// Create an identity quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL GLM_CONSTEXPR qua quat_identity(); + + /// Compute a cross product between a quaternion and a vector. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> cross( + qua const& q, + vec<3, T, Q> const& v); + + //! Compute a cross product between a vector and a quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> cross( + vec<3, T, Q> const& v, + qua const& q); + + //! Compute a point on a path according squad equation. + //! q1 and q2 are control points; s1 and s2 are intermediate control points. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL qua squad( + qua const& q1, + qua const& q2, + qua const& s1, + qua const& s2, + T const& h); + + //! Returns an intermediate control point for squad interpolation. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL qua intermediate( + qua const& prev, + qua const& curr, + qua const& next); + + //! Returns quarternion square root. + /// + /// @see gtx_quaternion + //template + //qua sqrt( + // qua const& q); + + //! Rotates a 3 components vector by a quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL vec<3, T, Q> rotate( + qua const& q, + vec<3, T, Q> const& v); + + /// Rotates a 4 components vector by a quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL vec<4, T, Q> rotate( + qua const& q, + vec<4, T, Q> const& v); + + /// Extract the real component of a quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL T extractRealComponent( + qua const& q); + + /// Converts a quaternion to a 3 * 3 matrix. + /// + /// @see gtx_quaternion + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> toMat3( + qua const& x){return mat3_cast(x);} + + /// Converts a quaternion to a 4 * 4 matrix. + /// + /// @see gtx_quaternion + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> toMat4( + qua const& x){return mat4_cast(x);} + + /// Converts a 3 * 3 matrix to a quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_QUALIFIER qua toQuat( + mat<3, 3, T, Q> const& x){return quat_cast(x);} + + /// Converts a 4 * 4 matrix to a quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_QUALIFIER qua toQuat( + mat<4, 4, T, Q> const& x){return quat_cast(x);} + + /// Quaternion interpolation using the rotation short path. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL qua shortMix( + qua const& x, + qua const& y, + T const& a); + + /// Quaternion normalized linear interpolation. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL qua fastMix( + qua const& x, + qua const& y, + T const& a); + + /// Compute the rotation between two vectors. + /// @param orig vector, needs to be normalized + /// @param dest vector, needs to be normalized + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL qua rotation( + vec<3, T, Q> const& orig, + vec<3, T, Q> const& dest); + + /// Returns the squared length of x. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL GLM_CONSTEXPR T length2(qua const& q); + + /// @} +}//namespace glm + +#include "quaternion.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/quaternion.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/quaternion.inl new file mode 100644 index 0000000..5e18899 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/quaternion.inl @@ -0,0 +1,159 @@ +/// @ref gtx_quaternion + +#include +#include "../gtc/constants.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua quat_identity() + { + return qua::wxyz(static_cast(1), static_cast(0), static_cast(0), static_cast(0)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> cross(vec<3, T, Q> const& v, qua const& q) + { + return inverse(q) * v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> cross(qua const& q, vec<3, T, Q> const& v) + { + return q * v; + } + + template + GLM_FUNC_QUALIFIER qua squad + ( + qua const& q1, + qua const& q2, + qua const& s1, + qua const& s2, + T const& h) + { + return mix(mix(q1, q2, h), mix(s1, s2, h), static_cast(2) * (static_cast(1) - h) * h); + } + + template + GLM_FUNC_QUALIFIER qua intermediate + ( + qua const& prev, + qua const& curr, + qua const& next + ) + { + qua invQuat = inverse(curr); + return exp((log(next * invQuat) + log(prev * invQuat)) / static_cast(-4)) * curr; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rotate(qua const& q, vec<3, T, Q> const& v) + { + return q * v; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> rotate(qua const& q, vec<4, T, Q> const& v) + { + return q * v; + } + + template + GLM_FUNC_QUALIFIER T extractRealComponent(qua const& q) + { + T w = static_cast(1) - q.x * q.x - q.y * q.y - q.z * q.z; + if(w < T(0)) + return T(0); + else + return -sqrt(w); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T length2(qua const& q) + { + return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w; + } + + template + GLM_FUNC_QUALIFIER qua shortMix(qua const& x, qua const& y, T const& a) + { + if(a <= static_cast(0)) return x; + if(a >= static_cast(1)) return y; + + T fCos = dot(x, y); + qua y2(y); //BUG!!! qua y2; + if(fCos < static_cast(0)) + { + y2 = -y; + fCos = -fCos; + } + + //if(fCos > 1.0f) // problem + T k0, k1; + if(fCos > (static_cast(1) - epsilon())) + { + k0 = static_cast(1) - a; + k1 = static_cast(0) + a; //BUG!!! 1.0f + a; + } + else + { + T fSin = sqrt(T(1) - fCos * fCos); + T fAngle = atan(fSin, fCos); + T fOneOverSin = static_cast(1) / fSin; + k0 = sin((static_cast(1) - a) * fAngle) * fOneOverSin; + k1 = sin((static_cast(0) + a) * fAngle) * fOneOverSin; + } + + return qua::wxyz( + k0 * x.w + k1 * y2.w, + k0 * x.x + k1 * y2.x, + k0 * x.y + k1 * y2.y, + k0 * x.z + k1 * y2.z); + } + + template + GLM_FUNC_QUALIFIER qua fastMix(qua const& x, qua const& y, T const& a) + { + return glm::normalize(x * (static_cast(1) - a) + (y * a)); + } + + template + GLM_FUNC_QUALIFIER qua rotation(vec<3, T, Q> const& orig, vec<3, T, Q> const& dest) + { + T cosTheta = dot(orig, dest); + vec<3, T, Q> rotationAxis; + + if(cosTheta >= static_cast(1) - epsilon()) { + // orig and dest point in the same direction + return quat_identity(); + } + + if(cosTheta < static_cast(-1) + epsilon()) + { + // special case when vectors in opposite directions : + // there is no "ideal" rotation axis + // So guess one; any will do as long as it's perpendicular to start + // This implementation favors a rotation around the Up axis (Y), + // since it's often what you want to do. + rotationAxis = cross(vec<3, T, Q>(0, 0, 1), orig); + if(length2(rotationAxis) < epsilon()) // bad luck, they were parallel, try again! + rotationAxis = cross(vec<3, T, Q>(1, 0, 0), orig); + + rotationAxis = normalize(rotationAxis); + return angleAxis(pi(), rotationAxis); + } + + // Implementation from Stan Melax's Game Programming Gems 1 article + rotationAxis = cross(orig, dest); + + T s = sqrt((T(1) + cosTheta) * static_cast(2)); + T invs = static_cast(1) / s; + + return qua::wxyz( + s * static_cast(0.5f), + rotationAxis.x * invs, + rotationAxis.y * invs, + rotationAxis.z * invs); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/range.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/range.hpp new file mode 100644 index 0000000..50c5e57 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/range.hpp @@ -0,0 +1,96 @@ +/// @ref gtx_range +/// @file glm/gtx/range.hpp +/// @author Joshua Moerman +/// +/// @defgroup gtx_range GLM_GTX_range +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defines begin and end for vectors and matrices. Useful for range-based for loop. +/// The range is defined over the elements, not over columns or rows (e.g. mat4 has 16 elements). + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_range is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_range extension included") +#endif + +#include "../gtc/type_ptr.hpp" +#include "../gtc/vec1.hpp" + +namespace glm +{ + /// @addtogroup gtx_range + /// @{ + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable : 4100) // unreferenced formal parameter +# endif + + template + inline length_t components(vec<1, T, Q> const& v) + { + return v.length(); + } + + template + inline length_t components(vec<2, T, Q> const& v) + { + return v.length(); + } + + template + inline length_t components(vec<3, T, Q> const& v) + { + return v.length(); + } + + template + inline length_t components(vec<4, T, Q> const& v) + { + return v.length(); + } + + template + inline length_t components(genType const& m) + { + return m.length() * m[0].length(); + } + + template + inline typename genType::value_type const * begin(genType const& v) + { + return value_ptr(v); + } + + template + inline typename genType::value_type const * end(genType const& v) + { + return begin(v) + components(v); + } + + template + inline typename genType::value_type * begin(genType& v) + { + return value_ptr(v); + } + + template + inline typename genType::value_type * end(genType& v) + { + return begin(v) + components(v); + } + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/raw_data.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/raw_data.hpp new file mode 100644 index 0000000..3bc27b9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/raw_data.hpp @@ -0,0 +1,49 @@ +/// @ref gtx_raw_data +/// @file glm/gtx/raw_data.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_raw_data GLM_GTX_raw_data +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Projection of a vector to other one + +#pragma once + +// Dependencies +#include "../ext/scalar_uint_sized.hpp" +#include "../detail/setup.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_raw_data is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_raw_data extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_raw_data + /// @{ + + //! Type for byte numbers. + //! From GLM_GTX_raw_data extension. + typedef detail::uint8 byte; + + //! Type for word numbers. + //! From GLM_GTX_raw_data extension. + typedef detail::uint16 word; + + //! Type for dword numbers. + //! From GLM_GTX_raw_data extension. + typedef detail::uint32 dword; + + //! Type for qword numbers. + //! From GLM_GTX_raw_data extension. + typedef detail::uint64 qword; + + /// @} +}// namespace glm + +#include "raw_data.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/raw_data.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/raw_data.inl new file mode 100644 index 0000000..c740317 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/raw_data.inl @@ -0,0 +1,2 @@ +/// @ref gtx_raw_data + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_normalized_axis.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_normalized_axis.hpp new file mode 100644 index 0000000..02c3f5c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_normalized_axis.hpp @@ -0,0 +1,66 @@ +/// @ref gtx_rotate_normalized_axis +/// @file glm/gtx/rotate_normalized_axis.hpp +/// +/// @see core (dependence) +/// @see gtc_matrix_transform +/// @see gtc_quaternion +/// +/// @defgroup gtx_rotate_normalized_axis GLM_GTX_rotate_normalized_axis +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Quaternions and matrices rotations around normalized axis. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/epsilon.hpp" +#include "../gtc/quaternion.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_rotate_normalized_axis is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_rotate_normalized_axis extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_rotate_normalized_axis + /// @{ + + /// Builds a rotation 4 * 4 matrix created from a normalized axis and an angle. + /// + /// @param m Input matrix multiplied by this rotation matrix. + /// @param angle Rotation angle expressed in radians. + /// @param axis Rotation axis, must be normalized. + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommended), float or double. + /// + /// @see gtx_rotate_normalized_axis + /// @see - rotate(T angle, T x, T y, T z) + /// @see - rotate(mat<4, 4, T, Q> const& m, T angle, T x, T y, T z) + /// @see - rotate(T angle, vec<3, T, Q> const& v) + template + GLM_FUNC_DECL mat<4, 4, T, Q> rotateNormalizedAxis( + mat<4, 4, T, Q> const& m, + T const& angle, + vec<3, T, Q> const& axis); + + /// Rotates a quaternion from a vector of 3 components normalized axis and an angle. + /// + /// @param q Source orientation + /// @param angle Angle expressed in radians. + /// @param axis Normalized axis of the rotation, must be normalized. + /// + /// @see gtx_rotate_normalized_axis + template + GLM_FUNC_DECL qua rotateNormalizedAxis( + qua const& q, + T const& angle, + vec<3, T, Q> const& axis); + + /// @} +}//namespace glm + +#include "rotate_normalized_axis.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_normalized_axis.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_normalized_axis.inl new file mode 100644 index 0000000..352a56c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_normalized_axis.inl @@ -0,0 +1,58 @@ +/// @ref gtx_rotate_normalized_axis + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rotateNormalizedAxis + ( + mat<4, 4, T, Q> const& m, + T const& angle, + vec<3, T, Q> const& v + ) + { + T const a = angle; + T const c = cos(a); + T const s = sin(a); + + vec<3, T, Q> const axis(v); + + vec<3, T, Q> const temp((static_cast(1) - c) * axis); + + mat<4, 4, T, Q> Rotate; + Rotate[0][0] = c + temp[0] * axis[0]; + Rotate[0][1] = 0 + temp[0] * axis[1] + s * axis[2]; + Rotate[0][2] = 0 + temp[0] * axis[2] - s * axis[1]; + + Rotate[1][0] = 0 + temp[1] * axis[0] - s * axis[2]; + Rotate[1][1] = c + temp[1] * axis[1]; + Rotate[1][2] = 0 + temp[1] * axis[2] + s * axis[0]; + + Rotate[2][0] = 0 + temp[2] * axis[0] + s * axis[1]; + Rotate[2][1] = 0 + temp[2] * axis[1] - s * axis[0]; + Rotate[2][2] = c + temp[2] * axis[2]; + + mat<4, 4, T, Q> Result; + Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2]; + Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2]; + Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2]; + Result[3] = m[3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER qua rotateNormalizedAxis + ( + qua const& q, + T const& angle, + vec<3, T, Q> const& v + ) + { + vec<3, T, Q> const Tmp(v); + + T const AngleRad(angle); + T const Sin = sin(AngleRad * T(0.5)); + + return q * qua::wxyz(cos(AngleRad * static_cast(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); + //return gtc::quaternion::cross(q, tquat(cos(AngleRad * T(0.5)), Tmp.x * fSin, Tmp.y * fSin, Tmp.z * fSin)); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_vector.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_vector.hpp new file mode 100644 index 0000000..b7345bf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_vector.hpp @@ -0,0 +1,121 @@ +/// @ref gtx_rotate_vector +/// @file glm/gtx/rotate_vector.hpp +/// +/// @see core (dependence) +/// @see gtx_transform (dependence) +/// +/// @defgroup gtx_rotate_vector GLM_GTX_rotate_vector +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Function to directly rotate a vector + +#pragma once + +// Dependency: +#include "../gtx/transform.hpp" +#include "../gtc/epsilon.hpp" +#include "../ext/vector_relational.hpp" +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_rotate_vector is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_rotate_vector extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_rotate_vector + /// @{ + + /// Returns Spherical interpolation between two vectors + /// + /// @param x A first vector + /// @param y A second vector + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// + /// @see gtx_rotate_vector + template + GLM_FUNC_DECL vec<3, T, Q> slerp( + vec<3, T, Q> const& x, + vec<3, T, Q> const& y, + T const& a); + + //! Rotate a two dimensional vector. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<2, T, Q> rotate( + vec<2, T, Q> const& v, + T const& angle); + + //! Rotate a three dimensional vector around an axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<3, T, Q> rotate( + vec<3, T, Q> const& v, + T const& angle, + vec<3, T, Q> const& normal); + + //! Rotate a four dimensional vector around an axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<4, T, Q> rotate( + vec<4, T, Q> const& v, + T const& angle, + vec<3, T, Q> const& normal); + + //! Rotate a three dimensional vector around the X axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<3, T, Q> rotateX( + vec<3, T, Q> const& v, + T const& angle); + + //! Rotate a three dimensional vector around the Y axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<3, T, Q> rotateY( + vec<3, T, Q> const& v, + T const& angle); + + //! Rotate a three dimensional vector around the Z axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<3, T, Q> rotateZ( + vec<3, T, Q> const& v, + T const& angle); + + //! Rotate a four dimensional vector around the X axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<4, T, Q> rotateX( + vec<4, T, Q> const& v, + T const& angle); + + //! Rotate a four dimensional vector around the Y axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<4, T, Q> rotateY( + vec<4, T, Q> const& v, + T const& angle); + + //! Rotate a four dimensional vector around the Z axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<4, T, Q> rotateZ( + vec<4, T, Q> const& v, + T const& angle); + + //! Build a rotation matrix from a normal and a up vector. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> orientation( + vec<3, T, Q> const& Normal, + vec<3, T, Q> const& Up); + + /// @} +}//namespace glm + +#include "rotate_vector.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_vector.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_vector.inl new file mode 100644 index 0000000..f8136e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_vector.inl @@ -0,0 +1,187 @@ +/// @ref gtx_rotate_vector + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> slerp + ( + vec<3, T, Q> const& x, + vec<3, T, Q> const& y, + T const& a + ) + { + // get cosine of angle between vectors (-1 -> 1) + T CosAlpha = dot(x, y); + // get angle (0 -> pi) + T Alpha = acos(CosAlpha); + // get sine of angle between vectors (0 -> 1) + T SinAlpha = sin(Alpha); + // this breaks down when SinAlpha = 0, i.e. Alpha = 0 or pi + T t1 = sin((static_cast(1) - a) * Alpha) / SinAlpha; + T t2 = sin(a * Alpha) / SinAlpha; + + // interpolate src vectors + return x * t1 + y * t2; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> rotate + ( + vec<2, T, Q> const& v, + T const& angle + ) + { + vec<2, T, Q> Result; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos - v.y * Sin; + Result.y = v.x * Sin + v.y * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rotate + ( + vec<3, T, Q> const& v, + T const& angle, + vec<3, T, Q> const& normal + ) + { + return mat<3, 3, T, Q>(glm::rotate(angle, normal)) * v; + } + /* + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rotateGTX( + const vec<3, T, Q>& x, + T angle, + const vec<3, T, Q>& normal) + { + const T Cos = cos(radians(angle)); + const T Sin = sin(radians(angle)); + return x * Cos + ((x * normal) * (T(1) - Cos)) * normal + cross(x, normal) * Sin; + } + */ + template + GLM_FUNC_QUALIFIER vec<4, T, Q> rotate + ( + vec<4, T, Q> const& v, + T const& angle, + vec<3, T, Q> const& normal + ) + { + return rotate(angle, normal) * v; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rotateX + ( + vec<3, T, Q> const& v, + T const& angle + ) + { + vec<3, T, Q> Result(v); + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.y = v.y * Cos - v.z * Sin; + Result.z = v.y * Sin + v.z * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rotateY + ( + vec<3, T, Q> const& v, + T const& angle + ) + { + vec<3, T, Q> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos + v.z * Sin; + Result.z = -v.x * Sin + v.z * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rotateZ + ( + vec<3, T, Q> const& v, + T const& angle + ) + { + vec<3, T, Q> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos - v.y * Sin; + Result.y = v.x * Sin + v.y * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> rotateX + ( + vec<4, T, Q> const& v, + T const& angle + ) + { + vec<4, T, Q> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.y = v.y * Cos - v.z * Sin; + Result.z = v.y * Sin + v.z * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> rotateY + ( + vec<4, T, Q> const& v, + T const& angle + ) + { + vec<4, T, Q> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos + v.z * Sin; + Result.z = -v.x * Sin + v.z * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> rotateZ + ( + vec<4, T, Q> const& v, + T const& angle + ) + { + vec<4, T, Q> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos - v.y * Sin; + Result.y = v.x * Sin + v.y * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> orientation + ( + vec<3, T, Q> const& Normal, + vec<3, T, Q> const& Up + ) + { + if(all(equal(Normal, Up, epsilon()))) + return mat<4, 4, T, Q>(static_cast(1)); + + vec<3, T, Q> RotationAxis = cross(Up, Normal); + T Angle = acos(dot(Normal, Up)); + + return rotate(Angle, RotationAxis); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/scalar_multiplication.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/scalar_multiplication.hpp new file mode 100644 index 0000000..97df000 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/scalar_multiplication.hpp @@ -0,0 +1,80 @@ +/// @ref gtx_scalar_multiplication +/// @file glm/gtx/scalar_multiplication.hpp +/// @author Joshua Moerman +/// +/// @defgroup gtx_scalar_multiplication GLM_GTX_scalar_multiplication +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Enables scalar multiplication for all types +/// +/// Since GLSL is very strict about types, the following (often used) combinations do not work: +/// double * vec4 +/// int * vec4 +/// vec4 / int +/// So we'll fix that! Of course "float * vec4" should remain the same (hence the enable_if magic) + +#pragma once + +#include "../detail/setup.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_scalar_multiplication is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_scalar_multiplication extension included") +#endif + +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../mat2x2.hpp" +#include + +namespace glm +{ + /// @addtogroup gtx_scalar_multiplication + /// @{ + + template + using return_type_scalar_multiplication = typename std::enable_if< + !std::is_same::value // T may not be a float + && std::is_arithmetic::value, Vec // But it may be an int or double (no vec3 or mat3, ...) + >::type; + +#define GLM_IMPLEMENT_SCAL_MULT(Vec) \ + template \ + return_type_scalar_multiplication \ + operator*(T const& s, Vec rh){ \ + return rh *= static_cast(s); \ + } \ + \ + template \ + return_type_scalar_multiplication \ + operator*(Vec lh, T const& s){ \ + return lh *= static_cast(s); \ + } \ + \ + template \ + return_type_scalar_multiplication \ + operator/(Vec lh, T const& s){ \ + return lh *= 1.0f / static_cast(s); \ + } + +GLM_IMPLEMENT_SCAL_MULT(vec2) +GLM_IMPLEMENT_SCAL_MULT(vec3) +GLM_IMPLEMENT_SCAL_MULT(vec4) + +GLM_IMPLEMENT_SCAL_MULT(mat2) +GLM_IMPLEMENT_SCAL_MULT(mat2x3) +GLM_IMPLEMENT_SCAL_MULT(mat2x4) +GLM_IMPLEMENT_SCAL_MULT(mat3x2) +GLM_IMPLEMENT_SCAL_MULT(mat3) +GLM_IMPLEMENT_SCAL_MULT(mat3x4) +GLM_IMPLEMENT_SCAL_MULT(mat4x2) +GLM_IMPLEMENT_SCAL_MULT(mat4x3) +GLM_IMPLEMENT_SCAL_MULT(mat4) + +#undef GLM_IMPLEMENT_SCAL_MULT + /// @} +} // namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/scalar_relational.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/scalar_relational.hpp new file mode 100644 index 0000000..e840932 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/scalar_relational.hpp @@ -0,0 +1,34 @@ +/// @ref gtx_scalar_relational +/// @file glm/gtx/scalar_relational.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_scalar_relational GLM_GTX_scalar_relational +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Extend a position from a source to a position at a defined length. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_scalar_relational is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_scalar_relational extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_scalar_relational + /// @{ + + + + /// @} +}//namespace glm + +#include "scalar_relational.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/scalar_relational.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/scalar_relational.inl new file mode 100644 index 0000000..c2a121c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/scalar_relational.inl @@ -0,0 +1,88 @@ +/// @ref gtx_scalar_relational + +namespace glm +{ + template + GLM_FUNC_QUALIFIER bool lessThan + ( + T const& x, + T const& y + ) + { + return x < y; + } + + template + GLM_FUNC_QUALIFIER bool lessThanEqual + ( + T const& x, + T const& y + ) + { + return x <= y; + } + + template + GLM_FUNC_QUALIFIER bool greaterThan + ( + T const& x, + T const& y + ) + { + return x > y; + } + + template + GLM_FUNC_QUALIFIER bool greaterThanEqual + ( + T const& x, + T const& y + ) + { + return x >= y; + } + + template + GLM_FUNC_QUALIFIER bool equal + ( + T const& x, + T const& y + ) + { + return detail::compute_equal::is_iec559>::call(x, y); + } + + template + GLM_FUNC_QUALIFIER bool notEqual + ( + T const& x, + T const& y + ) + { + return !detail::compute_equal::is_iec559>::call(x, y); + } + + GLM_FUNC_QUALIFIER bool any + ( + bool const& x + ) + { + return x; + } + + GLM_FUNC_QUALIFIER bool all + ( + bool const& x + ) + { + return x; + } + + GLM_FUNC_QUALIFIER bool not_ + ( + bool const& x + ) + { + return !x; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/spline.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/spline.hpp new file mode 100644 index 0000000..8df5584 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/spline.hpp @@ -0,0 +1,63 @@ +/// @ref gtx_spline +/// @file glm/gtx/spline.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_spline GLM_GTX_spline +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Spline functions + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/optimum_pow.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_spline is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_spline extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_spline + /// @{ + + /// Return a point from a catmull rom curve. + /// @see gtx_spline extension. + template + GLM_FUNC_DECL genType catmullRom( + genType const& v1, + genType const& v2, + genType const& v3, + genType const& v4, + typename genType::value_type const& s); + + /// Return a point from a hermite curve. + /// @see gtx_spline extension. + template + GLM_FUNC_DECL genType hermite( + genType const& v1, + genType const& t1, + genType const& v2, + genType const& t2, + typename genType::value_type const& s); + + /// Return a point from a cubic curve. + /// @see gtx_spline extension. + template + GLM_FUNC_DECL genType cubic( + genType const& v1, + genType const& v2, + genType const& v3, + genType const& v4, + typename genType::value_type const& s); + + /// @} +}//namespace glm + +#include "spline.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/spline.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/spline.inl new file mode 100644 index 0000000..c3fd056 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/spline.inl @@ -0,0 +1,60 @@ +/// @ref gtx_spline + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType catmullRom + ( + genType const& v1, + genType const& v2, + genType const& v3, + genType const& v4, + typename genType::value_type const& s + ) + { + typename genType::value_type s2 = pow2(s); + typename genType::value_type s3 = pow3(s); + + typename genType::value_type f1 = -s3 + typename genType::value_type(2) * s2 - s; + typename genType::value_type f2 = typename genType::value_type(3) * s3 - typename genType::value_type(5) * s2 + typename genType::value_type(2); + typename genType::value_type f3 = typename genType::value_type(-3) * s3 + typename genType::value_type(4) * s2 + s; + typename genType::value_type f4 = s3 - s2; + + return (f1 * v1 + f2 * v2 + f3 * v3 + f4 * v4) / typename genType::value_type(2); + + } + + template + GLM_FUNC_QUALIFIER genType hermite + ( + genType const& v1, + genType const& t1, + genType const& v2, + genType const& t2, + typename genType::value_type const& s + ) + { + typename genType::value_type s2 = pow2(s); + typename genType::value_type s3 = pow3(s); + + typename genType::value_type f1 = typename genType::value_type(2) * s3 - typename genType::value_type(3) * s2 + typename genType::value_type(1); + typename genType::value_type f2 = typename genType::value_type(-2) * s3 + typename genType::value_type(3) * s2; + typename genType::value_type f3 = s3 - typename genType::value_type(2) * s2 + s; + typename genType::value_type f4 = s3 - s2; + + return f1 * v1 + f2 * v2 + f3 * t1 + f4 * t2; + } + + template + GLM_FUNC_QUALIFIER genType cubic + ( + genType const& v1, + genType const& v2, + genType const& v3, + genType const& v4, + typename genType::value_type const& s + ) + { + return ((v1 * s + v2) * s + v3) * s + v4; + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/std_based_type.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/std_based_type.hpp new file mode 100644 index 0000000..864885d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/std_based_type.hpp @@ -0,0 +1,66 @@ +/// @ref gtx_std_based_type +/// @file glm/gtx/std_based_type.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_std_based_type GLM_GTX_std_based_type +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Adds vector types based on STL value types. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_std_based_type is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_std_based_type extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_std_based_type + /// @{ + + /// Vector type based of one std::size_t component. + /// @see GLM_GTX_std_based_type + typedef vec<1, std::size_t, defaultp> size1; + + /// Vector type based of two std::size_t components. + /// @see GLM_GTX_std_based_type + typedef vec<2, std::size_t, defaultp> size2; + + /// Vector type based of three std::size_t components. + /// @see GLM_GTX_std_based_type + typedef vec<3, std::size_t, defaultp> size3; + + /// Vector type based of four std::size_t components. + /// @see GLM_GTX_std_based_type + typedef vec<4, std::size_t, defaultp> size4; + + /// Vector type based of one std::size_t component. + /// @see GLM_GTX_std_based_type + typedef vec<1, std::size_t, defaultp> size1_t; + + /// Vector type based of two std::size_t components. + /// @see GLM_GTX_std_based_type + typedef vec<2, std::size_t, defaultp> size2_t; + + /// Vector type based of three std::size_t components. + /// @see GLM_GTX_std_based_type + typedef vec<3, std::size_t, defaultp> size3_t; + + /// Vector type based of four std::size_t components. + /// @see GLM_GTX_std_based_type + typedef vec<4, std::size_t, defaultp> size4_t; + + /// @} +}//namespace glm + +#include "std_based_type.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/std_based_type.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/std_based_type.inl new file mode 100644 index 0000000..9c34bdb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/std_based_type.inl @@ -0,0 +1,6 @@ +/// @ref gtx_std_based_type + +namespace glm +{ + +} diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/string_cast.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/string_cast.hpp new file mode 100644 index 0000000..2958edc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/string_cast.hpp @@ -0,0 +1,45 @@ +/// @ref gtx_string_cast +/// @file glm/gtx/string_cast.hpp +/// +/// @see core (dependence) +/// @see gtx_integer (dependence) +/// @see gtx_quaternion (dependence) +/// +/// @defgroup gtx_string_cast GLM_GTX_string_cast +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Setup strings for GLM type values + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/type_precision.hpp" +#include "../gtc/quaternion.hpp" +#include "../gtx/dual_quaternion.hpp" +#include +#include +#include + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_string_cast is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_string_cast extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_string_cast + /// @{ + + /// Create a string from a GLM vector or matrix typed variable. + /// @see gtx_string_cast extension. + template + GLM_FUNC_DECL std::string to_string(genType const& x); + + /// @} +}//namespace glm + +#include "string_cast.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/string_cast.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/string_cast.inl new file mode 100644 index 0000000..875f2be --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/string_cast.inl @@ -0,0 +1,497 @@ +/// @ref gtx_string_cast + +#include +#include + +namespace glm{ +namespace detail +{ + template + struct cast + { + typedef T value_type; + }; + + template <> + struct cast + { + typedef double value_type; + }; + + GLM_FUNC_QUALIFIER std::string format(const char* message, ...) { + std::size_t const STRING_BUFFER(4096); + + assert(message != NULL); + assert(strlen(message) < STRING_BUFFER); + + char buffer[STRING_BUFFER]; + va_list list; + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wformat-nonliteral" +#endif + + va_start(list, message); + vsnprintf(buffer, STRING_BUFFER, message, list); + va_end(list); + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +#endif + + return buffer; + } + + static const char* LabelTrue = "true"; + static const char* LabelFalse = "false"; + + template + struct literal + { + GLM_FUNC_QUALIFIER static char const * value() {return "%d";} + }; + + template + struct literal + { + GLM_FUNC_QUALIFIER static char const * value() {return "%f";} + }; + +# if GLM_MODEL == GLM_MODEL_32 && GLM_COMPILER && GLM_COMPILER_VC + template<> + struct literal + { + GLM_FUNC_QUALIFIER static char const * value() {return "%lld";} + }; + + template<> + struct literal + { + GLM_FUNC_QUALIFIER static char const * value() {return "%lld";} + }; +# endif//GLM_MODEL == GLM_MODEL_32 && GLM_COMPILER && GLM_COMPILER_VC + + template + struct prefix{}; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "d";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "b";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "u8";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "i8";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "u16";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "i16";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "u";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "i";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "u64";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "i64";} + }; + + template + struct compute_to_string + {}; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<1, bool, Q> const& x) + { + return detail::format("bvec1(%s)", + x[0] ? detail::LabelTrue : detail::LabelFalse); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<2, bool, Q> const& x) + { + return detail::format("bvec2(%s, %s)", + x[0] ? detail::LabelTrue : detail::LabelFalse, + x[1] ? detail::LabelTrue : detail::LabelFalse); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<3, bool, Q> const& x) + { + return detail::format("bvec3(%s, %s, %s)", + x[0] ? detail::LabelTrue : detail::LabelFalse, + x[1] ? detail::LabelTrue : detail::LabelFalse, + x[2] ? detail::LabelTrue : detail::LabelFalse); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<4, bool, Q> const& x) + { + return detail::format("bvec4(%s, %s, %s, %s)", + x[0] ? detail::LabelTrue : detail::LabelFalse, + x[1] ? detail::LabelTrue : detail::LabelFalse, + x[2] ? detail::LabelTrue : detail::LabelFalse, + x[3] ? detail::LabelTrue : detail::LabelFalse); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<1, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%svec1(%s)", + PrefixStr, + LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<2, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%svec2(%s, %s)", + PrefixStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0]), + static_cast::value_type>(x[1])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<3, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%svec3(%s, %s, %s)", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0]), + static_cast::value_type>(x[1]), + static_cast::value_type>(x[2])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<4, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%svec4(%s, %s, %s, %s)", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0]), + static_cast::value_type>(x[1]), + static_cast::value_type>(x[2]), + static_cast::value_type>(x[3])); + } + }; + + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<2, 2, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat2x2((%s, %s), (%s, %s))", + PrefixStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<2, 3, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat2x3((%s, %s, %s), (%s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), static_cast::value_type>(x[0][2]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), static_cast::value_type>(x[1][2])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<2, 4, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat2x4((%s, %s, %s, %s), (%s, %s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), static_cast::value_type>(x[0][2]), static_cast::value_type>(x[0][3]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), static_cast::value_type>(x[1][2]), static_cast::value_type>(x[1][3])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<3, 2, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat3x2((%s, %s), (%s, %s), (%s, %s))", + PrefixStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), + static_cast::value_type>(x[2][0]), static_cast::value_type>(x[2][1])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<3, 3, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat3x3((%s, %s, %s), (%s, %s, %s), (%s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), static_cast::value_type>(x[0][2]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), static_cast::value_type>(x[1][2]), + static_cast::value_type>(x[2][0]), static_cast::value_type>(x[2][1]), static_cast::value_type>(x[2][2])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<3, 4, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat3x4((%s, %s, %s, %s), (%s, %s, %s, %s), (%s, %s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), static_cast::value_type>(x[0][2]), static_cast::value_type>(x[0][3]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), static_cast::value_type>(x[1][2]), static_cast::value_type>(x[1][3]), + static_cast::value_type>(x[2][0]), static_cast::value_type>(x[2][1]), static_cast::value_type>(x[2][2]), static_cast::value_type>(x[2][3])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<4, 2, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat4x2((%s, %s), (%s, %s), (%s, %s), (%s, %s))", + PrefixStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), + static_cast::value_type>(x[2][0]), static_cast::value_type>(x[2][1]), + static_cast::value_type>(x[3][0]), static_cast::value_type>(x[3][1])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<4, 3, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat4x3((%s, %s, %s), (%s, %s, %s), (%s, %s, %s), (%s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), static_cast::value_type>(x[0][2]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), static_cast::value_type>(x[1][2]), + static_cast::value_type>(x[2][0]), static_cast::value_type>(x[2][1]), static_cast::value_type>(x[2][2]), + static_cast::value_type>(x[3][0]), static_cast::value_type>(x[3][1]), static_cast::value_type>(x[3][2])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<4, 4, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat4x4((%s, %s, %s, %s), (%s, %s, %s, %s), (%s, %s, %s, %s), (%s, %s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), static_cast::value_type>(x[0][2]), static_cast::value_type>(x[0][3]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), static_cast::value_type>(x[1][2]), static_cast::value_type>(x[1][3]), + static_cast::value_type>(x[2][0]), static_cast::value_type>(x[2][1]), static_cast::value_type>(x[2][2]), static_cast::value_type>(x[2][3]), + static_cast::value_type>(x[3][0]), static_cast::value_type>(x[3][1]), static_cast::value_type>(x[3][2]), static_cast::value_type>(x[3][3])); + } + }; + + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(qua const& q) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%squat(%s, {%s, %s, %s})", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(q.w), + static_cast::value_type>(q.x), + static_cast::value_type>(q.y), + static_cast::value_type>(q.z)); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(tdualquat const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%sdualquat((%s, {%s, %s, %s}), (%s, {%s, %s, %s}))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x.real.w), + static_cast::value_type>(x.real.x), + static_cast::value_type>(x.real.y), + static_cast::value_type>(x.real.z), + static_cast::value_type>(x.dual.w), + static_cast::value_type>(x.dual.x), + static_cast::value_type>(x.dual.y), + static_cast::value_type>(x.dual.z)); + } + }; + +}//namespace detail + +template +GLM_FUNC_QUALIFIER std::string to_string(matType const& x) +{ + return detail::compute_to_string::call(x); +} + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/texture.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/texture.hpp new file mode 100644 index 0000000..608c6ad --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/texture.hpp @@ -0,0 +1,44 @@ +/// @ref gtx_texture +/// @file glm/gtx/texture.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_texture GLM_GTX_texture +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Wrapping mode of texture coordinates. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/integer.hpp" +#include "../gtx/component_wise.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_texture is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_texture extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_texture + /// @{ + + /// Compute the number of mipmaps levels necessary to create a mipmap complete texture + /// + /// @param Extent Extent of the texture base level mipmap + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + template + T levels(vec const& Extent); + + /// @} +}// namespace glm + +#include "texture.inl" + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/texture.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/texture.inl new file mode 100644 index 0000000..593c826 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/texture.inl @@ -0,0 +1,17 @@ +/// @ref gtx_texture + +namespace glm +{ + template + inline T levels(vec const& Extent) + { + return glm::log2(compMax(Extent)) + static_cast(1); + } + + template + inline T levels(T Extent) + { + return vec<1, T, defaultp>(Extent).x; + } +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform.hpp new file mode 100644 index 0000000..9707b50 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform.hpp @@ -0,0 +1,58 @@ +/// @ref gtx_transform +/// @file glm/gtx/transform.hpp +/// +/// @see core (dependence) +/// @see gtc_matrix_transform (dependence) +/// @see gtx_transform +/// @see gtx_transform2 +/// +/// @defgroup gtx_transform GLM_GTX_transform +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Add transformation matrices + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/matrix_transform.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_transform is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_transform extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_transform + /// @{ + + /// Transforms a matrix with a translation 4 * 4 matrix created from 3 scalars. + /// @see gtc_matrix_transform + /// @see gtx_transform + template + GLM_FUNC_DECL mat<4, 4, T, Q> translate( + vec<3, T, Q> const& v); + + /// Builds a rotation 4 * 4 matrix created from an axis of 3 scalars and an angle expressed in radians. + /// @see gtc_matrix_transform + /// @see gtx_transform + template + GLM_FUNC_DECL mat<4, 4, T, Q> rotate( + T angle, + vec<3, T, Q> const& v); + + /// Transforms a matrix with a scale 4 * 4 matrix created from a vector of 3 components. + /// @see gtc_matrix_transform + /// @see gtx_transform + template + GLM_FUNC_DECL mat<4, 4, T, Q> scale( + vec<3, T, Q> const& v); + + /// @} +}// namespace glm + +#include "transform.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform.inl new file mode 100644 index 0000000..48ee680 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform.inl @@ -0,0 +1,23 @@ +/// @ref gtx_transform + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> translate(vec<3, T, Q> const& v) + { + return translate(mat<4, 4, T, Q>(static_cast(1)), v); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rotate(T angle, vec<3, T, Q> const& v) + { + return rotate(mat<4, 4, T, Q>(static_cast(1)), angle, v); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> scale(vec<3, T, Q> const& v) + { + return scale(mat<4, 4, T, Q>(static_cast(1)), v); + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform2.hpp new file mode 100644 index 0000000..9604a92 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform2.hpp @@ -0,0 +1,87 @@ +/// @ref gtx_transform2 +/// @file glm/gtx/transform2.hpp +/// +/// @see core (dependence) +/// @see gtx_transform (dependence) +/// +/// @defgroup gtx_transform2 GLM_GTX_transform2 +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Add extra transformation matrices + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/transform.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_transform2 is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_transform2 extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_transform2 + /// @{ + + //! Transforms a matrix with a shearing on X axis. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> shearX2D(mat<3, 3, T, Q> const& m, T y); + + //! Transforms a matrix with a shearing on Y axis. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> shearY2D(mat<3, 3, T, Q> const& m, T x); + + //! Transforms a matrix with a shearing on X axis + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> shearX3D(mat<4, 4, T, Q> const& m, T y, T z); + + //! Transforms a matrix with a shearing on Y axis. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> shearY3D(mat<4, 4, T, Q> const& m, T x, T z); + + //! Transforms a matrix with a shearing on Z axis. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> shearZ3D(mat<4, 4, T, Q> const& m, T x, T y); + + //template GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shear(const mat<4, 4, T, Q> & m, shearPlane, planePoint, angle) + // Identity + tan(angle) * cross(Normal, OnPlaneVector) 0 + // - dot(PointOnPlane, normal) * OnPlaneVector 1 + + // Reflect functions seem to don't work + //template mat<3, 3, T, Q> reflect2D(const mat<3, 3, T, Q> & m, const vec<3, T, Q>& normal){return reflect2DGTX(m, normal);} //!< \brief Build a reflection matrix (from GLM_GTX_transform2 extension) + //template mat<4, 4, T, Q> reflect3D(const mat<4, 4, T, Q> & m, const vec<3, T, Q>& normal){return reflect3DGTX(m, normal);} //!< \brief Build a reflection matrix (from GLM_GTX_transform2 extension) + + //! Build planar projection matrix along normal axis. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> proj2D(mat<3, 3, T, Q> const& m, vec<3, T, Q> const& normal); + + //! Build planar projection matrix along normal axis. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> proj3D(mat<4, 4, T, Q> const & m, vec<3, T, Q> const& normal); + + //! Build a scale bias matrix. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> scaleBias(T scale, T bias); + + //! Build a scale bias matrix. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> scaleBias(mat<4, 4, T, Q> const& m, T scale, T bias); + + /// @} +}// namespace glm + +#include "transform2.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform2.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform2.inl new file mode 100644 index 0000000..0118ab0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform2.inl @@ -0,0 +1,125 @@ +/// @ref gtx_transform2 + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> shearX2D(mat<3, 3, T, Q> const& m, T s) + { + mat<3, 3, T, Q> r(1); + r[1][0] = s; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> shearY2D(mat<3, 3, T, Q> const& m, T s) + { + mat<3, 3, T, Q> r(1); + r[0][1] = s; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shearX3D(mat<4, 4, T, Q> const& m, T s, T t) + { + mat<4, 4, T, Q> r(1); + r[0][1] = s; + r[0][2] = t; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shearY3D(mat<4, 4, T, Q> const& m, T s, T t) + { + mat<4, 4, T, Q> r(1); + r[1][0] = s; + r[1][2] = t; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shearZ3D(mat<4, 4, T, Q> const& m, T s, T t) + { + mat<4, 4, T, Q> r(1); + r[2][0] = s; + r[2][1] = t; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> reflect2D(mat<3, 3, T, Q> const& m, vec<3, T, Q> const& normal) + { + mat<3, 3, T, Q> r(static_cast(1)); + r[0][0] = static_cast(1) - static_cast(2) * normal.x * normal.x; + r[0][1] = -static_cast(2) * normal.x * normal.y; + r[1][0] = -static_cast(2) * normal.x * normal.y; + r[1][1] = static_cast(1) - static_cast(2) * normal.y * normal.y; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> reflect3D(mat<4, 4, T, Q> const& m, vec<3, T, Q> const& normal) + { + mat<4, 4, T, Q> r(static_cast(1)); + r[0][0] = static_cast(1) - static_cast(2) * normal.x * normal.x; + r[0][1] = -static_cast(2) * normal.x * normal.y; + r[0][2] = -static_cast(2) * normal.x * normal.z; + + r[1][0] = -static_cast(2) * normal.x * normal.y; + r[1][1] = static_cast(1) - static_cast(2) * normal.y * normal.y; + r[1][2] = -static_cast(2) * normal.y * normal.z; + + r[2][0] = -static_cast(2) * normal.x * normal.z; + r[2][1] = -static_cast(2) * normal.y * normal.z; + r[2][2] = static_cast(1) - static_cast(2) * normal.z * normal.z; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> proj2D( + const mat<3, 3, T, Q>& m, + const vec<3, T, Q>& normal) + { + mat<3, 3, T, Q> r(static_cast(1)); + r[0][0] = static_cast(1) - normal.x * normal.x; + r[0][1] = - normal.x * normal.y; + r[1][0] = - normal.x * normal.y; + r[1][1] = static_cast(1) - normal.y * normal.y; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> proj3D( + const mat<4, 4, T, Q>& m, + const vec<3, T, Q>& normal) + { + mat<4, 4, T, Q> r(static_cast(1)); + r[0][0] = static_cast(1) - normal.x * normal.x; + r[0][1] = - normal.x * normal.y; + r[0][2] = - normal.x * normal.z; + r[1][0] = - normal.x * normal.y; + r[1][1] = static_cast(1) - normal.y * normal.y; + r[1][2] = - normal.y * normal.z; + r[2][0] = - normal.x * normal.z; + r[2][1] = - normal.y * normal.z; + r[2][2] = static_cast(1) - normal.z * normal.z; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> scaleBias(T scale, T bias) + { + mat<4, 4, T, Q> result; + result[3] = vec<4, T, Q>(vec<3, T, Q>(bias), static_cast(1)); + result[0][0] = scale; + result[1][1] = scale; + result[2][2] = scale; + return result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> scaleBias(mat<4, 4, T, Q> const& m, T scale, T bias) + { + return m * scaleBias(scale, bias); + } +}//namespace glm + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_aligned.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_aligned.hpp new file mode 100644 index 0000000..ec40935 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_aligned.hpp @@ -0,0 +1,980 @@ +/// @ref gtx_type_aligned +/// @file glm/gtx/type_aligned.hpp +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_type_aligned GLM_GTX_type_aligned +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defines aligned types. + +#pragma once + +// Dependency: +#include "../gtc/type_precision.hpp" +#include "../gtc/quaternion.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_type_aligned is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_type_aligned extension included") +#endif + +namespace glm +{ + /////////////////////////// + // Signed int vector types + + /// @addtogroup gtx_type_aligned + /// @{ + + /// Low qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int8, aligned_lowp_int8, 1); + + /// Low qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int16, aligned_lowp_int16, 2); + + /// Low qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int32, aligned_lowp_int32, 4); + + /// Low qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int64, aligned_lowp_int64, 8); + + + /// Low qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int8_t, aligned_lowp_int8_t, 1); + + /// Low qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int16_t, aligned_lowp_int16_t, 2); + + /// Low qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int32_t, aligned_lowp_int32_t, 4); + + /// Low qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int64_t, aligned_lowp_int64_t, 8); + + + /// Low qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_i8, aligned_lowp_i8, 1); + + /// Low qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_i16, aligned_lowp_i16, 2); + + /// Low qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_i32, aligned_lowp_i32, 4); + + /// Low qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_i64, aligned_lowp_i64, 8); + + + /// Medium qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int8, aligned_mediump_int8, 1); + + /// Medium qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int16, aligned_mediump_int16, 2); + + /// Medium qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int32, aligned_mediump_int32, 4); + + /// Medium qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int64, aligned_mediump_int64, 8); + + + /// Medium qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int8_t, aligned_mediump_int8_t, 1); + + /// Medium qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int16_t, aligned_mediump_int16_t, 2); + + /// Medium qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int32_t, aligned_mediump_int32_t, 4); + + /// Medium qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int64_t, aligned_mediump_int64_t, 8); + + + /// Medium qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_i8, aligned_mediump_i8, 1); + + /// Medium qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_i16, aligned_mediump_i16, 2); + + /// Medium qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_i32, aligned_mediump_i32, 4); + + /// Medium qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_i64, aligned_mediump_i64, 8); + + + /// High qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int8, aligned_highp_int8, 1); + + /// High qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int16, aligned_highp_int16, 2); + + /// High qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int32, aligned_highp_int32, 4); + + /// High qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int64, aligned_highp_int64, 8); + + + /// High qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int8_t, aligned_highp_int8_t, 1); + + /// High qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int16_t, aligned_highp_int16_t, 2); + + /// High qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int32_t, aligned_highp_int32_t, 4); + + /// High qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int64_t, aligned_highp_int64_t, 8); + + + /// High qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_i8, aligned_highp_i8, 1); + + /// High qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_i16, aligned_highp_i16, 2); + + /// High qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_i32, aligned_highp_i32, 4); + + /// High qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_i64, aligned_highp_i64, 8); + + + /// Default qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int8, aligned_int8, 1); + + /// Default qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int16, aligned_int16, 2); + + /// Default qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int32, aligned_int32, 4); + + /// Default qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int64, aligned_int64, 8); + + + /// Default qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int8_t, aligned_int8_t, 1); + + /// Default qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int16_t, aligned_int16_t, 2); + + /// Default qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int32_t, aligned_int32_t, 4); + + /// Default qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int64_t, aligned_int64_t, 8); + + + /// Default qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8, aligned_i8, 1); + + /// Default qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16, aligned_i16, 2); + + /// Default qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32, aligned_i32, 4); + + /// Default qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64, aligned_i64, 8); + + + /// Default qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(ivec1, aligned_ivec1, 4); + + /// Default qualifier 32 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(ivec2, aligned_ivec2, 8); + + /// Default qualifier 32 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(ivec3, aligned_ivec3, 16); + + /// Default qualifier 32 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(ivec4, aligned_ivec4, 16); + + + /// Default qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8vec1, aligned_i8vec1, 1); + + /// Default qualifier 8 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8vec2, aligned_i8vec2, 2); + + /// Default qualifier 8 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8vec3, aligned_i8vec3, 4); + + /// Default qualifier 8 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8vec4, aligned_i8vec4, 4); + + + /// Default qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16vec1, aligned_i16vec1, 2); + + /// Default qualifier 16 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16vec2, aligned_i16vec2, 4); + + /// Default qualifier 16 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16vec3, aligned_i16vec3, 8); + + /// Default qualifier 16 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16vec4, aligned_i16vec4, 8); + + + /// Default qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32vec1, aligned_i32vec1, 4); + + /// Default qualifier 32 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32vec2, aligned_i32vec2, 8); + + /// Default qualifier 32 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32vec3, aligned_i32vec3, 16); + + /// Default qualifier 32 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32vec4, aligned_i32vec4, 16); + + + /// Default qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64vec1, aligned_i64vec1, 8); + + /// Default qualifier 64 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64vec2, aligned_i64vec2, 16); + + /// Default qualifier 64 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64vec3, aligned_i64vec3, 32); + + /// Default qualifier 64 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64vec4, aligned_i64vec4, 32); + + + ///////////////////////////// + // Unsigned int vector types + + /// Low qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint8, aligned_lowp_uint8, 1); + + /// Low qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint16, aligned_lowp_uint16, 2); + + /// Low qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint32, aligned_lowp_uint32, 4); + + /// Low qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint64, aligned_lowp_uint64, 8); + + + /// Low qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint8_t, aligned_lowp_uint8_t, 1); + + /// Low qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint16_t, aligned_lowp_uint16_t, 2); + + /// Low qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint32_t, aligned_lowp_uint32_t, 4); + + /// Low qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint64_t, aligned_lowp_uint64_t, 8); + + + /// Low qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_u8, aligned_lowp_u8, 1); + + /// Low qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_u16, aligned_lowp_u16, 2); + + /// Low qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_u32, aligned_lowp_u32, 4); + + /// Low qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_u64, aligned_lowp_u64, 8); + + + /// Medium qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint8, aligned_mediump_uint8, 1); + + /// Medium qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint16, aligned_mediump_uint16, 2); + + /// Medium qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint32, aligned_mediump_uint32, 4); + + /// Medium qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint64, aligned_mediump_uint64, 8); + + + /// Medium qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint8_t, aligned_mediump_uint8_t, 1); + + /// Medium qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint16_t, aligned_mediump_uint16_t, 2); + + /// Medium qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint32_t, aligned_mediump_uint32_t, 4); + + /// Medium qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint64_t, aligned_mediump_uint64_t, 8); + + + /// Medium qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_u8, aligned_mediump_u8, 1); + + /// Medium qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_u16, aligned_mediump_u16, 2); + + /// Medium qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_u32, aligned_mediump_u32, 4); + + /// Medium qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_u64, aligned_mediump_u64, 8); + + + /// High qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint8, aligned_highp_uint8, 1); + + /// High qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint16, aligned_highp_uint16, 2); + + /// High qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint32, aligned_highp_uint32, 4); + + /// High qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint64, aligned_highp_uint64, 8); + + + /// High qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint8_t, aligned_highp_uint8_t, 1); + + /// High qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint16_t, aligned_highp_uint16_t, 2); + + /// High qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint32_t, aligned_highp_uint32_t, 4); + + /// High qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint64_t, aligned_highp_uint64_t, 8); + + + /// High qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_u8, aligned_highp_u8, 1); + + /// High qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_u16, aligned_highp_u16, 2); + + /// High qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_u32, aligned_highp_u32, 4); + + /// High qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_u64, aligned_highp_u64, 8); + + + /// Default qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint8, aligned_uint8, 1); + + /// Default qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint16, aligned_uint16, 2); + + /// Default qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint32, aligned_uint32, 4); + + /// Default qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint64, aligned_uint64, 8); + + + /// Default qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint8_t, aligned_uint8_t, 1); + + /// Default qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint16_t, aligned_uint16_t, 2); + + /// Default qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint32_t, aligned_uint32_t, 4); + + /// Default qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint64_t, aligned_uint64_t, 8); + + + /// Default qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8, aligned_u8, 1); + + /// Default qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16, aligned_u16, 2); + + /// Default qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32, aligned_u32, 4); + + /// Default qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64, aligned_u64, 8); + + + /// Default qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uvec1, aligned_uvec1, 4); + + /// Default qualifier 32 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uvec2, aligned_uvec2, 8); + + /// Default qualifier 32 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uvec3, aligned_uvec3, 16); + + /// Default qualifier 32 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uvec4, aligned_uvec4, 16); + + + /// Default qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8vec1, aligned_u8vec1, 1); + + /// Default qualifier 8 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8vec2, aligned_u8vec2, 2); + + /// Default qualifier 8 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8vec3, aligned_u8vec3, 4); + + /// Default qualifier 8 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8vec4, aligned_u8vec4, 4); + + + /// Default qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16vec1, aligned_u16vec1, 2); + + /// Default qualifier 16 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16vec2, aligned_u16vec2, 4); + + /// Default qualifier 16 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16vec3, aligned_u16vec3, 8); + + /// Default qualifier 16 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16vec4, aligned_u16vec4, 8); + + + /// Default qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32vec1, aligned_u32vec1, 4); + + /// Default qualifier 32 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32vec2, aligned_u32vec2, 8); + + /// Default qualifier 32 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32vec3, aligned_u32vec3, 16); + + /// Default qualifier 32 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32vec4, aligned_u32vec4, 16); + + + /// Default qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64vec1, aligned_u64vec1, 8); + + /// Default qualifier 64 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64vec2, aligned_u64vec2, 16); + + /// Default qualifier 64 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64vec3, aligned_u64vec3, 32); + + /// Default qualifier 64 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64vec4, aligned_u64vec4, 32); + + + ////////////////////// + // Float vector types + + /// 32 bit single-qualifier floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float32, aligned_float32, 4); + + /// 32 bit single-qualifier floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float32_t, aligned_float32_t, 4); + + /// 32 bit single-qualifier floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float32, aligned_f32, 4); + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// 64 bit double-qualifier floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float64, aligned_float64, 8); + + /// 64 bit double-qualifier floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float64_t, aligned_float64_t, 8); + + /// 64 bit double-qualifier floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float64, aligned_f64, 8); + +# endif//GLM_FORCE_SINGLE_ONLY + + + /// Single-qualifier floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(vec1, aligned_vec1, 4); + + /// Single-qualifier floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(vec2, aligned_vec2, 8); + + /// Single-qualifier floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(vec3, aligned_vec3, 16); + + /// Single-qualifier floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(vec4, aligned_vec4, 16); + + + /// Single-qualifier floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fvec1, aligned_fvec1, 4); + + /// Single-qualifier floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fvec2, aligned_fvec2, 8); + + /// Single-qualifier floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fvec3, aligned_fvec3, 16); + + /// Single-qualifier floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fvec4, aligned_fvec4, 16); + + + /// Single-qualifier floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32vec1, aligned_f32vec1, 4); + + /// Single-qualifier floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32vec2, aligned_f32vec2, 8); + + /// Single-qualifier floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32vec3, aligned_f32vec3, 16); + + /// Single-qualifier floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32vec4, aligned_f32vec4, 16); + + + /// Double-qualifier floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dvec1, aligned_dvec1, 8); + + /// Double-qualifier floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dvec2, aligned_dvec2, 16); + + /// Double-qualifier floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dvec3, aligned_dvec3, 32); + + /// Double-qualifier floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dvec4, aligned_dvec4, 32); + + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// Double-qualifier floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64vec1, aligned_f64vec1, 8); + + /// Double-qualifier floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64vec2, aligned_f64vec2, 16); + + /// Double-qualifier floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64vec3, aligned_f64vec3, 32); + + /// Double-qualifier floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64vec4, aligned_f64vec4, 32); + +# endif//GLM_FORCE_SINGLE_ONLY + + ////////////////////// + // Float matrix types + + /// Single-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1 mat1; + + /// Single-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat2, aligned_mat2, 16); + + /// Single-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat3, aligned_mat3, 16); + + /// Single-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat4, aligned_mat4, 16); + + + /// Single-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1x1 mat1; + + /// Single-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat2x2, aligned_mat2x2, 16); + + /// Single-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat3x3, aligned_mat3x3, 16); + + /// Single-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat4x4, aligned_mat4x4, 16); + + + /// Single-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1x1 fmat1; + + /// Single-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat2x2, aligned_fmat2, 16); + + /// Single-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat3x3, aligned_fmat3, 16); + + /// Single-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat4x4, aligned_fmat4, 16); + + + /// Single-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef f32 fmat1x1; + + /// Single-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat2x2, aligned_fmat2x2, 16); + + /// Single-qualifier floating-point aligned 2x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat2x3, aligned_fmat2x3, 16); + + /// Single-qualifier floating-point aligned 2x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat2x4, aligned_fmat2x4, 16); + + /// Single-qualifier floating-point aligned 3x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat3x2, aligned_fmat3x2, 16); + + /// Single-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat3x3, aligned_fmat3x3, 16); + + /// Single-qualifier floating-point aligned 3x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat3x4, aligned_fmat3x4, 16); + + /// Single-qualifier floating-point aligned 4x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat4x2, aligned_fmat4x2, 16); + + /// Single-qualifier floating-point aligned 4x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat4x3, aligned_fmat4x3, 16); + + /// Single-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat4x4, aligned_fmat4x4, 16); + + + /// Single-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1x1 f32mat1; + + /// Single-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat2x2, aligned_f32mat2, 16); + + /// Single-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat3x3, aligned_f32mat3, 16); + + /// Single-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat4x4, aligned_f32mat4, 16); + + + /// Single-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef f32 f32mat1x1; + + /// Single-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat2x2, aligned_f32mat2x2, 16); + + /// Single-qualifier floating-point aligned 2x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat2x3, aligned_f32mat2x3, 16); + + /// Single-qualifier floating-point aligned 2x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat2x4, aligned_f32mat2x4, 16); + + /// Single-qualifier floating-point aligned 3x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat3x2, aligned_f32mat3x2, 16); + + /// Single-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat3x3, aligned_f32mat3x3, 16); + + /// Single-qualifier floating-point aligned 3x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat3x4, aligned_f32mat3x4, 16); + + /// Single-qualifier floating-point aligned 4x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat4x2, aligned_f32mat4x2, 16); + + /// Single-qualifier floating-point aligned 4x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat4x3, aligned_f32mat4x3, 16); + + /// Single-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat4x4, aligned_f32mat4x4, 16); + + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// Double-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1x1 f64mat1; + + /// Double-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat2x2, aligned_f64mat2, 32); + + /// Double-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat3x3, aligned_f64mat3, 32); + + /// Double-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat4x4, aligned_f64mat4, 32); + + + /// Double-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef f64 f64mat1x1; + + /// Double-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat2x2, aligned_f64mat2x2, 32); + + /// Double-qualifier floating-point aligned 2x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat2x3, aligned_f64mat2x3, 32); + + /// Double-qualifier floating-point aligned 2x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat2x4, aligned_f64mat2x4, 32); + + /// Double-qualifier floating-point aligned 3x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat3x2, aligned_f64mat3x2, 32); + + /// Double-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat3x3, aligned_f64mat3x3, 32); + + /// Double-qualifier floating-point aligned 3x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat3x4, aligned_f64mat3x4, 32); + + /// Double-qualifier floating-point aligned 4x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat4x2, aligned_f64mat4x2, 32); + + /// Double-qualifier floating-point aligned 4x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat4x3, aligned_f64mat4x3, 32); + + /// Double-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat4x4, aligned_f64mat4x4, 32); + +# endif//GLM_FORCE_SINGLE_ONLY + + + ////////////////////////// + // Quaternion types + + /// Single-qualifier floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(quat, aligned_quat, 16); + + /// Single-qualifier floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(quat, aligned_fquat, 16); + + /// Double-qualifier floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dquat, aligned_dquat, 32); + + /// Single-qualifier floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32quat, aligned_f32quat, 16); + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// Double-qualifier floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64quat, aligned_f64quat, 32); + +# endif//GLM_FORCE_SINGLE_ONLY + + /// @} +}//namespace glm + +#include "type_aligned.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_aligned.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_aligned.inl new file mode 100644 index 0000000..54c1b81 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_aligned.inl @@ -0,0 +1,6 @@ +/// @ref gtc_type_aligned + +namespace glm +{ + +} diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_trait.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_trait.hpp new file mode 100644 index 0000000..17ddbad --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_trait.hpp @@ -0,0 +1,83 @@ +/// @ref gtx_type_trait +/// @file glm/gtx/type_trait.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_type_trait GLM_GTX_type_trait +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defines traits for each type. + +#pragma once + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_type_trait is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_type_trait extension included") +#endif + +// Dependency: +#include "../detail/qualifier.hpp" +#include "../gtc/quaternion.hpp" +#include "../gtx/dual_quaternion.hpp" + +namespace glm +{ + /// @addtogroup gtx_type_trait + /// @{ + + template + struct type + { + static bool const is_vec = false; + static bool const is_mat = false; + static bool const is_quat = false; + static length_t const components = 0; + static length_t const cols = 0; + static length_t const rows = 0; + }; + + template + struct type > + { + static bool const is_vec = true; + static bool const is_mat = false; + static bool const is_quat = false; + static length_t const components = L; + }; + + template + struct type > + { + static bool const is_vec = false; + static bool const is_mat = true; + static bool const is_quat = false; + static length_t const components = C; + static length_t const cols = C; + static length_t const rows = R; + }; + + template + struct type > + { + static bool const is_vec = false; + static bool const is_mat = false; + static bool const is_quat = true; + static length_t const components = 4; + }; + + template + struct type > + { + static bool const is_vec = false; + static bool const is_mat = false; + static bool const is_quat = true; + static length_t const components = 8; + }; + + /// @} +}//namespace glm + +#include "type_trait.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_trait.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_trait.inl new file mode 100644 index 0000000..045de95 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_trait.inl @@ -0,0 +1,61 @@ +/// @ref gtx_type_trait + +namespace glm +{ + template + bool const type::is_vec; + template + bool const type::is_mat; + template + bool const type::is_quat; + template + length_t const type::components; + template + length_t const type::cols; + template + length_t const type::rows; + + // vec + template + bool const type >::is_vec; + template + bool const type >::is_mat; + template + bool const type >::is_quat; + template + length_t const type >::components; + + // mat + template + bool const type >::is_vec; + template + bool const type >::is_mat; + template + bool const type >::is_quat; + template + length_t const type >::components; + template + length_t const type >::cols; + template + length_t const type >::rows; + + // tquat + template + bool const type >::is_vec; + template + bool const type >::is_mat; + template + bool const type >::is_quat; + template + length_t const type >::components; + + // tdualquat + template + bool const type >::is_vec; + template + bool const type >::is_mat; + template + bool const type >::is_quat; + template + length_t const type >::components; +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vec_swizzle.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vec_swizzle.hpp new file mode 100644 index 0000000..2dafa64 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vec_swizzle.hpp @@ -0,0 +1,2784 @@ +/// @ref gtx_vec_swizzle +/// @file glm/gtx/vec_swizzle.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_vec_swizzle GLM_GTX_vec_swizzle +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Functions to perform swizzle operation. + +#pragma once + +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_vec_swizzle is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_vec_swizzle extension included") +#endif + +namespace glm { + /// @addtogroup gtx_vec_swizzle + /// @{ + + // xx + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> xx(const glm::vec<1, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> xx(const glm::vec<2, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> xx(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> xx(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.x); + } + + // xy + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> xy(const glm::vec<2, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> xy(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> xy(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.y); + } + + // xz + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> xz(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> xz(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.z); + } + + // xw + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> xw(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.w); + } + + // yx + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> yx(const glm::vec<2, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> yx(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> yx(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.x); + } + + // yy + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> yy(const glm::vec<2, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> yy(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> yy(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.y); + } + + // yz + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> yz(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> yz(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.z); + } + + // yw + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> yw(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.w); + } + + // zx + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> zx(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> zx(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.x); + } + + // zy + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> zy(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> zy(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.y); + } + + // zz + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> zz(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> zz(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.z); + } + + // zw + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> zw(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.w); + } + + // wx + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> wx(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.w, v.x); + } + + // wy + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> wy(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.w, v.y); + } + + // wz + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> wz(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.w, v.z); + } + + // ww + template + GLM_FUNC_QUALIFIER glm::vec<2, T, Q> ww(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.w, v.w); + } + + // xxx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xxx(const glm::vec<1, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xxx(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xxx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xxx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.x); + } + + // xxy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xxy(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xxy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xxy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.y); + } + + // xxz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xxz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xxz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.z); + } + + // xxw + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xxw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.w); + } + + // xyx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xyx(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xyx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xyx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.x); + } + + // xyy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xyy(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xyy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xyy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.y); + } + + // xyz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xyz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xyz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.z); + } + + // xyw + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xyw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.w); + } + + // xzx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xzx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xzx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.x); + } + + // xzy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xzy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xzy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.y); + } + + // xzz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xzz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xzz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.z); + } + + // xzw + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xzw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.w); + } + + // xwx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xwx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.w, v.x); + } + + // xwy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xwy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.w, v.y); + } + + // xwz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xwz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.w, v.z); + } + + // xww + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> xww(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.w, v.w); + } + + // yxx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yxx(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yxx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yxx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.x); + } + + // yxy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yxy(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yxy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yxy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.y); + } + + // yxz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yxz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yxz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.z); + } + + // yxw + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yxw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.w); + } + + // yyx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yyx(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yyx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yyx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.x); + } + + // yyy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yyy(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yyy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yyy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.y); + } + + // yyz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yyz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yyz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.z); + } + + // yyw + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yyw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.w); + } + + // yzx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yzx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yzx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.x); + } + + // yzy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yzy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yzy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.y); + } + + // yzz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yzz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yzz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.z); + } + + // yzw + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yzw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.w); + } + + // ywx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> ywx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.w, v.x); + } + + // ywy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> ywy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.w, v.y); + } + + // ywz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> ywz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.w, v.z); + } + + // yww + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> yww(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.w, v.w); + } + + // zxx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zxx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zxx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.x); + } + + // zxy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zxy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zxy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.y); + } + + // zxz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zxz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zxz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.z); + } + + // zxw + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zxw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.w); + } + + // zyx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zyx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zyx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.x); + } + + // zyy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zyy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zyy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.y); + } + + // zyz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zyz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zyz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.z); + } + + // zyw + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zyw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.w); + } + + // zzx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zzx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zzx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.x); + } + + // zzy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zzy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zzy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.y); + } + + // zzz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zzz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zzz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.z); + } + + // zzw + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zzw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.w); + } + + // zwx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zwx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.w, v.x); + } + + // zwy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zwy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.w, v.y); + } + + // zwz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zwz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.w, v.z); + } + + // zww + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> zww(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.w, v.w); + } + + // wxx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wxx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.x, v.x); + } + + // wxy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wxy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.x, v.y); + } + + // wxz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wxz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.x, v.z); + } + + // wxw + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wxw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.x, v.w); + } + + // wyx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wyx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.y, v.x); + } + + // wyy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wyy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.y, v.y); + } + + // wyz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wyz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.y, v.z); + } + + // wyw + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wyw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.y, v.w); + } + + // wzx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wzx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.z, v.x); + } + + // wzy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wzy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.z, v.y); + } + + // wzz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wzz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.z, v.z); + } + + // wzw + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wzw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.z, v.w); + } + + // wwx + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wwx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.w, v.x); + } + + // wwy + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wwy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.w, v.y); + } + + // wwz + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> wwz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.w, v.z); + } + + // www + template + GLM_FUNC_QUALIFIER glm::vec<3, T, Q> www(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.w, v.w); + } + + // xxxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxxx(const glm::vec<1, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxxx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.x); + } + + // xxxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxxy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.y); + } + + // xxxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.z); + } + + // xxxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.w); + } + + // xxyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxyx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.x); + } + + // xxyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxyy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.y); + } + + // xxyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.z); + } + + // xxyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.w); + } + + // xxzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.x); + } + + // xxzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.y); + } + + // xxzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.z); + } + + // xxzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.w); + } + + // xxwx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.w, v.x); + } + + // xxwy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.w, v.y); + } + + // xxwz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.w, v.z); + } + + // xxww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xxww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.w, v.w); + } + + // xyxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyxx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.x); + } + + // xyxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyxy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.y); + } + + // xyxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.z); + } + + // xyxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.w); + } + + // xyyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyyx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.x); + } + + // xyyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyyy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.y); + } + + // xyyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.z); + } + + // xyyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.w); + } + + // xyzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.x); + } + + // xyzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.y); + } + + // xyzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.z); + } + + // xyzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.w); + } + + // xywx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xywx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.w, v.x); + } + + // xywy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xywy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.w, v.y); + } + + // xywz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xywz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.w, v.z); + } + + // xyww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xyww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.w, v.w); + } + + // xzxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.x); + } + + // xzxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.y); + } + + // xzxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.z); + } + + // xzxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.w); + } + + // xzyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.x); + } + + // xzyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.y); + } + + // xzyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.z); + } + + // xzyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.w); + } + + // xzzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.x); + } + + // xzzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.y); + } + + // xzzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.z); + } + + // xzzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.w); + } + + // xzwx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.w, v.x); + } + + // xzwy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.w, v.y); + } + + // xzwz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.w, v.z); + } + + // xzww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xzww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.w, v.w); + } + + // xwxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.x, v.x); + } + + // xwxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.x, v.y); + } + + // xwxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.x, v.z); + } + + // xwxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.x, v.w); + } + + // xwyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.y, v.x); + } + + // xwyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.y, v.y); + } + + // xwyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.y, v.z); + } + + // xwyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.y, v.w); + } + + // xwzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.z, v.x); + } + + // xwzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.z, v.y); + } + + // xwzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.z, v.z); + } + + // xwzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.z, v.w); + } + + // xwwx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.w, v.x); + } + + // xwwy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.w, v.y); + } + + // xwwz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.w, v.z); + } + + // xwww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> xwww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.w, v.w); + } + + // yxxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxxx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.x); + } + + // yxxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxxy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.y); + } + + // yxxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.z); + } + + // yxxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.w); + } + + // yxyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxyx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.x); + } + + // yxyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxyy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.y); + } + + // yxyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.z); + } + + // yxyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.w); + } + + // yxzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.x); + } + + // yxzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.y); + } + + // yxzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.z); + } + + // yxzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.w); + } + + // yxwx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.w, v.x); + } + + // yxwy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.w, v.y); + } + + // yxwz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.w, v.z); + } + + // yxww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yxww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.w, v.w); + } + + // yyxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyxx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.x); + } + + // yyxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyxy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.y); + } + + // yyxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.z); + } + + // yyxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.w); + } + + // yyyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyyx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.x); + } + + // yyyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyyy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.y); + } + + // yyyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.z); + } + + // yyyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.w); + } + + // yyzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.x); + } + + // yyzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.y); + } + + // yyzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.z); + } + + // yyzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.w); + } + + // yywx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yywx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.w, v.x); + } + + // yywy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yywy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.w, v.y); + } + + // yywz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yywz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.w, v.z); + } + + // yyww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yyww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.w, v.w); + } + + // yzxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.x); + } + + // yzxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.y); + } + + // yzxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.z); + } + + // yzxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.w); + } + + // yzyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.x); + } + + // yzyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.y); + } + + // yzyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.z); + } + + // yzyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.w); + } + + // yzzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.x); + } + + // yzzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.y); + } + + // yzzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.z); + } + + // yzzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.w); + } + + // yzwx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.w, v.x); + } + + // yzwy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.w, v.y); + } + + // yzwz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.w, v.z); + } + + // yzww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> yzww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.w, v.w); + } + + // ywxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.x, v.x); + } + + // ywxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.x, v.y); + } + + // ywxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.x, v.z); + } + + // ywxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.x, v.w); + } + + // ywyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.y, v.x); + } + + // ywyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.y, v.y); + } + + // ywyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.y, v.z); + } + + // ywyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.y, v.w); + } + + // ywzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.z, v.x); + } + + // ywzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.z, v.y); + } + + // ywzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.z, v.z); + } + + // ywzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.z, v.w); + } + + // ywwx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.w, v.x); + } + + // ywwy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.w, v.y); + } + + // ywwz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.w, v.z); + } + + // ywww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> ywww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.w, v.w); + } + + // zxxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.x); + } + + // zxxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.y); + } + + // zxxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.z); + } + + // zxxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.w); + } + + // zxyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.x); + } + + // zxyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.y); + } + + // zxyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.z); + } + + // zxyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.w); + } + + // zxzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.x); + } + + // zxzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.y); + } + + // zxzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.z); + } + + // zxzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.w); + } + + // zxwx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.w, v.x); + } + + // zxwy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.w, v.y); + } + + // zxwz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.w, v.z); + } + + // zxww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zxww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.w, v.w); + } + + // zyxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.x); + } + + // zyxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.y); + } + + // zyxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.z); + } + + // zyxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.w); + } + + // zyyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.x); + } + + // zyyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.y); + } + + // zyyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.z); + } + + // zyyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.w); + } + + // zyzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.x); + } + + // zyzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.y); + } + + // zyzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.z); + } + + // zyzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.w); + } + + // zywx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zywx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.w, v.x); + } + + // zywy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zywy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.w, v.y); + } + + // zywz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zywz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.w, v.z); + } + + // zyww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zyww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.w, v.w); + } + + // zzxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.x); + } + + // zzxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.y); + } + + // zzxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.z); + } + + // zzxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.w); + } + + // zzyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.x); + } + + // zzyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.y); + } + + // zzyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.z); + } + + // zzyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.w); + } + + // zzzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.x); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.x); + } + + // zzzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.y); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.y); + } + + // zzzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.z); + } + + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.z); + } + + // zzzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.w); + } + + // zzwx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.w, v.x); + } + + // zzwy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.w, v.y); + } + + // zzwz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.w, v.z); + } + + // zzww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zzww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.w, v.w); + } + + // zwxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.x, v.x); + } + + // zwxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.x, v.y); + } + + // zwxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.x, v.z); + } + + // zwxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.x, v.w); + } + + // zwyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.y, v.x); + } + + // zwyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.y, v.y); + } + + // zwyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.y, v.z); + } + + // zwyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.y, v.w); + } + + // zwzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.z, v.x); + } + + // zwzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.z, v.y); + } + + // zwzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.z, v.z); + } + + // zwzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.z, v.w); + } + + // zwwx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.w, v.x); + } + + // zwwy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.w, v.y); + } + + // zwwz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.w, v.z); + } + + // zwww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> zwww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.w, v.w); + } + + // wxxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.x, v.x); + } + + // wxxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.x, v.y); + } + + // wxxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.x, v.z); + } + + // wxxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.x, v.w); + } + + // wxyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.y, v.x); + } + + // wxyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.y, v.y); + } + + // wxyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.y, v.z); + } + + // wxyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.y, v.w); + } + + // wxzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.z, v.x); + } + + // wxzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.z, v.y); + } + + // wxzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.z, v.z); + } + + // wxzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.z, v.w); + } + + // wxwx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.w, v.x); + } + + // wxwy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.w, v.y); + } + + // wxwz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.w, v.z); + } + + // wxww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wxww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.w, v.w); + } + + // wyxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.x, v.x); + } + + // wyxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.x, v.y); + } + + // wyxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.x, v.z); + } + + // wyxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.x, v.w); + } + + // wyyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.y, v.x); + } + + // wyyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.y, v.y); + } + + // wyyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.y, v.z); + } + + // wyyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.y, v.w); + } + + // wyzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.z, v.x); + } + + // wyzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.z, v.y); + } + + // wyzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.z, v.z); + } + + // wyzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.z, v.w); + } + + // wywx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wywx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.w, v.x); + } + + // wywy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wywy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.w, v.y); + } + + // wywz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wywz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.w, v.z); + } + + // wyww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wyww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.w, v.w); + } + + // wzxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.x, v.x); + } + + // wzxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.x, v.y); + } + + // wzxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.x, v.z); + } + + // wzxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.x, v.w); + } + + // wzyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.y, v.x); + } + + // wzyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.y, v.y); + } + + // wzyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.y, v.z); + } + + // wzyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.y, v.w); + } + + // wzzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.z, v.x); + } + + // wzzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.z, v.y); + } + + // wzzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.z, v.z); + } + + // wzzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.z, v.w); + } + + // wzwx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.w, v.x); + } + + // wzwy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.w, v.y); + } + + // wzwz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.w, v.z); + } + + // wzww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wzww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.w, v.w); + } + + // wwxx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.x, v.x); + } + + // wwxy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.x, v.y); + } + + // wwxz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.x, v.z); + } + + // wwxw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.x, v.w); + } + + // wwyx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.y, v.x); + } + + // wwyy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.y, v.y); + } + + // wwyz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.y, v.z); + } + + // wwyw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.y, v.w); + } + + // wwzx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.z, v.x); + } + + // wwzy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.z, v.y); + } + + // wwzz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.z, v.z); + } + + // wwzw + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.z, v.w); + } + + // wwwx + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.w, v.x); + } + + // wwwy + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.w, v.y); + } + + // wwwz + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.w, v.z); + } + + // wwww + template + GLM_FUNC_QUALIFIER glm::vec<4, T, Q> wwww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.w, v.w); + } + + /// @} +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_angle.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_angle.hpp new file mode 100644 index 0000000..9ff4127 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_angle.hpp @@ -0,0 +1,55 @@ +/// @ref gtx_vector_angle +/// @file glm/gtx/vector_angle.hpp +/// +/// @see core (dependence) +/// @see gtx_quaternion (dependence) +/// @see gtx_epsilon (dependence) +/// +/// @defgroup gtx_vector_angle GLM_GTX_vector_angle +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Compute angle between vectors + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/epsilon.hpp" +#include "../gtx/quaternion.hpp" +#include "../gtx/rotate_vector.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_vector_angle is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_vector_angle extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_vector_angle + /// @{ + + //! Returns the absolute angle between two vectors. + //! Parameters need to be normalized. + /// @see gtx_vector_angle extension. + template + GLM_FUNC_DECL T angle(vec const& x, vec const& y); + + //! Returns the oriented angle between two 2d vectors. + //! Parameters need to be normalized. + /// @see gtx_vector_angle extension. + template + GLM_FUNC_DECL T orientedAngle(vec<2, T, Q> const& x, vec<2, T, Q> const& y); + + //! Returns the oriented angle between two 3d vectors based from a reference axis. + //! Parameters need to be normalized. + /// @see gtx_vector_angle extension. + template + GLM_FUNC_DECL T orientedAngle(vec<3, T, Q> const& x, vec<3, T, Q> const& y, vec<3, T, Q> const& ref); + + /// @} +}// namespace glm + +#include "vector_angle.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_angle.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_angle.inl new file mode 100644 index 0000000..11e1a21 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_angle.inl @@ -0,0 +1,45 @@ +/// @ref gtx_vector_angle + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType angle + ( + genType const& x, + genType const& y + ) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'angle' only accept floating-point inputs"); + return acos(clamp(dot(x, y), genType(-1), genType(1))); + } + + template + GLM_FUNC_QUALIFIER T angle(vec const& x, vec const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'angle' only accept floating-point inputs"); + return acos(clamp(dot(x, y), T(-1), T(1))); + } + + template + GLM_FUNC_QUALIFIER T orientedAngle(vec<2, T, Q> const& x, vec<2, T, Q> const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'orientedAngle' only accept floating-point inputs"); + T const Angle(acos(clamp(dot(x, y), T(-1), T(1)))); + + T const partialCross = x.x * y.y - y.x * x.y; + + if (partialCross > T(0)) + return Angle; + else + return -Angle; + } + + template + GLM_FUNC_QUALIFIER T orientedAngle(vec<3, T, Q> const& x, vec<3, T, Q> const& y, vec<3, T, Q> const& ref) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'orientedAngle' only accept floating-point inputs"); + + T const Angle(acos(clamp(dot(x, y), T(-1), T(1)))); + return mix(Angle, -Angle, dot(ref, cross(x, y)) < T(0)); + } +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_query.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_query.hpp new file mode 100644 index 0000000..ab52df0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_query.hpp @@ -0,0 +1,64 @@ +/// @ref gtx_vector_query +/// @file glm/gtx/vector_query.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_vector_query GLM_GTX_vector_query +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Query information of vector types + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include +#include + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_vector_query is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_vector_query extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_vector_query + /// @{ + + //! Check whether two vectors are collinears. + /// @see gtx_vector_query extensions. + template + GLM_FUNC_DECL bool areCollinear(vec const& v0, vec const& v1, T const& epsilon); + + //! Check whether two vectors are orthogonals. + /// @see gtx_vector_query extensions. + template + GLM_FUNC_DECL bool areOrthogonal(vec const& v0, vec const& v1, T const& epsilon); + + //! Check whether a vector is normalized. + /// @see gtx_vector_query extensions. + template + GLM_FUNC_DECL bool isNormalized(vec const& v, T const& epsilon); + + //! Check whether a vector is null. + /// @see gtx_vector_query extensions. + template + GLM_FUNC_DECL bool isNull(vec const& v, T const& epsilon); + + //! Check whether a each component of a vector is null. + /// @see gtx_vector_query extensions. + template + GLM_FUNC_DECL vec isCompNull(vec const& v, T const& epsilon); + + //! Check whether two vectors are orthonormal. + /// @see gtx_vector_query extensions. + template + GLM_FUNC_DECL bool areOrthonormal(vec const& v0, vec const& v1, T const& epsilon); + + /// @} +}// namespace glm + +#include "vector_query.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_query.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_query.inl new file mode 100644 index 0000000..d1a5c9b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_query.inl @@ -0,0 +1,154 @@ +/// @ref gtx_vector_query + +#include + +namespace glm{ +namespace detail +{ + template + struct compute_areCollinear{}; + + template + struct compute_areCollinear<2, T, Q> + { + GLM_FUNC_QUALIFIER static bool call(vec<2, T, Q> const& v0, vec<2, T, Q> const& v1, T const& epsilon) + { + return length(cross(vec<3, T, Q>(v0, static_cast(0)), vec<3, T, Q>(v1, static_cast(0)))) < epsilon; + } + }; + + template + struct compute_areCollinear<3, T, Q> + { + GLM_FUNC_QUALIFIER static bool call(vec<3, T, Q> const& v0, vec<3, T, Q> const& v1, T const& epsilon) + { + return length(cross(v0, v1)) < epsilon; + } + }; + + template + struct compute_areCollinear<4, T, Q> + { + GLM_FUNC_QUALIFIER static bool call(vec<4, T, Q> const& v0, vec<4, T, Q> const& v1, T const& epsilon) + { + return length(cross(vec<3, T, Q>(v0), vec<3, T, Q>(v1))) < epsilon; + } + }; + + template + struct compute_isCompNull{}; + + template + struct compute_isCompNull<2, T, Q> + { + GLM_FUNC_QUALIFIER static vec<2, bool, Q> call(vec<2, T, Q> const& v, T const& epsilon) + { + return vec<2, bool, Q>( + (abs(v.x) < epsilon), + (abs(v.y) < epsilon)); + } + }; + + template + struct compute_isCompNull<3, T, Q> + { + GLM_FUNC_QUALIFIER static vec<3, bool, Q> call(vec<3, T, Q> const& v, T const& epsilon) + { + return vec<3, bool, Q>( + (abs(v.x) < epsilon), + (abs(v.y) < epsilon), + (abs(v.z) < epsilon)); + } + }; + + template + struct compute_isCompNull<4, T, Q> + { + GLM_FUNC_QUALIFIER static vec<4, bool, Q> call(vec<4, T, Q> const& v, T const& epsilon) + { + return vec<4, bool, Q>( + (abs(v.x) < epsilon), + (abs(v.y) < epsilon), + (abs(v.z) < epsilon), + (abs(v.w) < epsilon)); + } + }; + +}//namespace detail + + template + GLM_FUNC_QUALIFIER bool areCollinear(vec const& v0, vec const& v1, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'areCollinear' only accept floating-point inputs"); + + return detail::compute_areCollinear::call(v0, v1, epsilon); + } + + template + GLM_FUNC_QUALIFIER bool areOrthogonal(vec const& v0, vec const& v1, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'areOrthogonal' only accept floating-point inputs"); + + return abs(dot(v0, v1)) <= max( + static_cast(1), + length(v0)) * max(static_cast(1), length(v1)) * epsilon; + } + + template + GLM_FUNC_QUALIFIER bool isNormalized(vec const& v, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isNormalized' only accept floating-point inputs"); + + return abs(length(v) - static_cast(1)) <= static_cast(2) * epsilon; + } + + template + GLM_FUNC_QUALIFIER bool isNull(vec const& v, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isNull' only accept floating-point inputs"); + + return length(v) <= epsilon; + } + + template + GLM_FUNC_QUALIFIER vec isCompNull(vec const& v, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isCompNull' only accept floating-point inputs"); + + return detail::compute_isCompNull::call(v, epsilon); + } + + template + GLM_FUNC_QUALIFIER vec<2, bool, Q> isCompNull(vec<2, T, Q> const& v, T const& epsilon) + { + return vec<2, bool, Q>( + abs(v.x) < epsilon, + abs(v.y) < epsilon); + } + + template + GLM_FUNC_QUALIFIER vec<3, bool, Q> isCompNull(vec<3, T, Q> const& v, T const& epsilon) + { + return vec<3, bool, Q>( + abs(v.x) < epsilon, + abs(v.y) < epsilon, + abs(v.z) < epsilon); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> isCompNull(vec<4, T, Q> const& v, T const& epsilon) + { + return vec<4, bool, Q>( + abs(v.x) < epsilon, + abs(v.y) < epsilon, + abs(v.z) < epsilon, + abs(v.w) < epsilon); + } + + template + GLM_FUNC_QUALIFIER bool areOrthonormal(vec const& v0, vec const& v1, T const& epsilon) + { + return isNormalized(v0, epsilon) && isNormalized(v1, epsilon) && (abs(dot(v0, v1)) <= epsilon); + } + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/wrap.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/wrap.hpp new file mode 100644 index 0000000..b7ac5af --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/wrap.hpp @@ -0,0 +1,35 @@ +/// @ref gtx_wrap +/// @file glm/gtx/wrap.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_wrap GLM_GTX_wrap +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Wrapping mode of texture coordinates. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../ext/scalar_common.hpp" +#include "../ext/vector_common.hpp" +#include "../gtc/vec1.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_wrap is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_wrap extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_wrap + /// @{ + + /// @} +}// namespace glm + +#include "wrap.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/wrap.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/wrap.inl new file mode 100644 index 0000000..4be3b4c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/wrap.inl @@ -0,0 +1,6 @@ +/// @ref gtx_wrap + +namespace glm +{ + +}//namespace glm diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/integer.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/integer.hpp new file mode 100644 index 0000000..36c67be --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/integer.hpp @@ -0,0 +1,212 @@ +/// @ref core +/// @file glm/integer.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.8 Integer Functions +/// +/// @defgroup core_func_integer Integer functions +/// @ingroup core +/// +/// Provides GLSL functions on integer types +/// +/// These all operate component-wise. The description is per component. +/// The notation [a, b] means the set of bits from bit-number a through bit-number +/// b, inclusive. The lowest-order bit is bit 0. +/// +/// Include to use these core features. + +#pragma once + +#include "detail/qualifier.hpp" +#include "common.hpp" +#include "vector_relational.hpp" + +namespace glm +{ + /// @addtogroup core_func_integer + /// @{ + + /// Adds 32-bit unsigned integer x and y, returning the sum + /// modulo pow(2, 32). The value carry is set to 0 if the sum was + /// less than pow(2, 32), or to 1 otherwise. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL uaddCarry man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec uaddCarry( + vec const& x, + vec const& y, + vec & carry); + + /// Subtracts the 32-bit unsigned integer y from x, returning + /// the difference if non-negative, or pow(2, 32) plus the difference + /// otherwise. The value borrow is set to 0 if x >= y, or to 1 otherwise. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL usubBorrow man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec usubBorrow( + vec const& x, + vec const& y, + vec & borrow); + + /// Multiplies 32-bit integers x and y, producing a 64-bit + /// result. The 32 least-significant bits are returned in lsb. + /// The 32 most-significant bits are returned in msb. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL umulExtended man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DISCARD_DECL void umulExtended( + vec const& x, + vec const& y, + vec & msb, + vec & lsb); + + /// Multiplies 32-bit integers x and y, producing a 64-bit + /// result. The 32 least-significant bits are returned in lsb. + /// The 32 most-significant bits are returned in msb. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL imulExtended man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DISCARD_DECL void imulExtended( + vec const& x, + vec const& y, + vec & msb, + vec & lsb); + + /// Extracts bits [offset, offset + bits - 1] from value, + /// returning them in the least significant bits of the result. + /// For unsigned data types, the most significant bits of the + /// result will be set to zero. For signed data types, the + /// most significant bits will be set to the value of bit offset + base - 1. + /// + /// If bits is zero, the result will be zero. The result will be + /// undefined if offset or bits is negative, or if the sum of + /// offset and bits is greater than the number of bits used + /// to store the operand. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar types. + /// + /// @see GLSL bitfieldExtract man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec bitfieldExtract( + vec const& Value, + int Offset, + int Bits); + + /// Returns the insertion the bits least-significant bits of insert into base. + /// + /// The result will have bits [offset, offset + bits - 1] taken + /// from bits [0, bits - 1] of insert, and all other bits taken + /// directly from the corresponding bits of base. If bits is + /// zero, the result will simply be base. The result will be + /// undefined if offset or bits is negative, or if the sum of + /// offset and bits is greater than the number of bits used to + /// store the operand. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar or vector types. + /// + /// @see GLSL bitfieldInsert man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec bitfieldInsert( + vec const& Base, + vec const& Insert, + int Offset, + int Bits); + + /// Returns the reversal of the bits of value. + /// The bit numbered n of the result will be taken from bit (bits - 1) - n of value, + /// where bits is the total number of bits used to represent value. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar or vector types. + /// + /// @see GLSL bitfieldReverse man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec bitfieldReverse(vec const& v); + + /// Returns the number of bits set to 1 in the binary representation of value. + /// + /// @tparam genType Signed or unsigned integer scalar or vector types. + /// + /// @see GLSL bitCount man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL int bitCount(genType v); + + /// Returns the number of bits set to 1 in the binary representation of value. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar or vector types. + /// + /// @see GLSL bitCount man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec bitCount(vec const& v); + + /// Returns the bit number of the least significant bit set to + /// 1 in the binary representation of value. + /// If value is zero, -1 will be returned. + /// + /// @tparam genIUType Signed or unsigned integer scalar types. + /// + /// @see GLSL findLSB man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL int findLSB(genIUType x); + + /// Returns the bit number of the least significant bit set to + /// 1 in the binary representation of value. + /// If value is zero, -1 will be returned. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar types. + /// + /// @see GLSL findLSB man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec findLSB(vec const& v); + + /// Returns the bit number of the most significant bit in the binary representation of value. + /// For positive integers, the result will be the bit number of the most significant bit set to 1. + /// For negative integers, the result will be the bit number of the most significant + /// bit set to 0. For a value of zero or negative one, -1 will be returned. + /// + /// @tparam genIUType Signed or unsigned integer scalar types. + /// + /// @see GLSL findMSB man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL int findMSB(genIUType x); + + /// Returns the bit number of the most significant bit in the binary representation of value. + /// For positive integers, the result will be the bit number of the most significant bit set to 1. + /// For negative integers, the result will be the bit number of the most significant + /// bit set to 0. For a value of zero or negative one, -1 will be returned. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar types. + /// + /// @see GLSL findMSB man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec findMSB(vec const& v); + + /// @} +}//namespace glm + +#include "detail/func_integer.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat2x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat2x2.hpp new file mode 100644 index 0000000..96bec96 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat2x2.hpp @@ -0,0 +1,9 @@ +/// @ref core +/// @file glm/mat2x2.hpp + +#pragma once +#include "./ext/matrix_double2x2.hpp" +#include "./ext/matrix_double2x2_precision.hpp" +#include "./ext/matrix_float2x2.hpp" +#include "./ext/matrix_float2x2_precision.hpp" + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat2x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat2x3.hpp new file mode 100644 index 0000000..d68dc25 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat2x3.hpp @@ -0,0 +1,9 @@ +/// @ref core +/// @file glm/mat2x3.hpp + +#pragma once +#include "./ext/matrix_double2x3.hpp" +#include "./ext/matrix_double2x3_precision.hpp" +#include "./ext/matrix_float2x3.hpp" +#include "./ext/matrix_float2x3_precision.hpp" + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat2x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat2x4.hpp new file mode 100644 index 0000000..b04b738 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat2x4.hpp @@ -0,0 +1,9 @@ +/// @ref core +/// @file glm/mat2x4.hpp + +#pragma once +#include "./ext/matrix_double2x4.hpp" +#include "./ext/matrix_double2x4_precision.hpp" +#include "./ext/matrix_float2x4.hpp" +#include "./ext/matrix_float2x4_precision.hpp" + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat3x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat3x2.hpp new file mode 100644 index 0000000..c853153 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat3x2.hpp @@ -0,0 +1,9 @@ +/// @ref core +/// @file glm/mat3x2.hpp + +#pragma once +#include "./ext/matrix_double3x2.hpp" +#include "./ext/matrix_double3x2_precision.hpp" +#include "./ext/matrix_float3x2.hpp" +#include "./ext/matrix_float3x2_precision.hpp" + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat3x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat3x3.hpp new file mode 100644 index 0000000..fd4fa31 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat3x3.hpp @@ -0,0 +1,8 @@ +/// @ref core +/// @file glm/mat3x3.hpp + +#pragma once +#include "./ext/matrix_double3x3.hpp" +#include "./ext/matrix_double3x3_precision.hpp" +#include "./ext/matrix_float3x3.hpp" +#include "./ext/matrix_float3x3_precision.hpp" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat3x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat3x4.hpp new file mode 100644 index 0000000..6342bf5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat3x4.hpp @@ -0,0 +1,8 @@ +/// @ref core +/// @file glm/mat3x4.hpp + +#pragma once +#include "./ext/matrix_double3x4.hpp" +#include "./ext/matrix_double3x4_precision.hpp" +#include "./ext/matrix_float3x4.hpp" +#include "./ext/matrix_float3x4_precision.hpp" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat4x2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat4x2.hpp new file mode 100644 index 0000000..e013e46 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat4x2.hpp @@ -0,0 +1,9 @@ +/// @ref core +/// @file glm/mat4x2.hpp + +#pragma once +#include "./ext/matrix_double4x2.hpp" +#include "./ext/matrix_double4x2_precision.hpp" +#include "./ext/matrix_float4x2.hpp" +#include "./ext/matrix_float4x2_precision.hpp" + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat4x3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat4x3.hpp new file mode 100644 index 0000000..205725a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat4x3.hpp @@ -0,0 +1,8 @@ +/// @ref core +/// @file glm/mat4x3.hpp + +#pragma once +#include "./ext/matrix_double4x3.hpp" +#include "./ext/matrix_double4x3_precision.hpp" +#include "./ext/matrix_float4x3.hpp" +#include "./ext/matrix_float4x3_precision.hpp" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat4x4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat4x4.hpp new file mode 100644 index 0000000..3515f7f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/mat4x4.hpp @@ -0,0 +1,9 @@ +/// @ref core +/// @file glm/mat4x4.hpp + +#pragma once +#include "./ext/matrix_double4x4.hpp" +#include "./ext/matrix_double4x4_precision.hpp" +#include "./ext/matrix_float4x4.hpp" +#include "./ext/matrix_float4x4_precision.hpp" + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/matrix.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/matrix.hpp new file mode 100644 index 0000000..4584c92 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/matrix.hpp @@ -0,0 +1,161 @@ +/// @ref core +/// @file glm/matrix.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions +/// +/// @defgroup core_func_matrix Matrix functions +/// @ingroup core +/// +/// Provides GLSL matrix functions. +/// +/// Include to use these core features. + +#pragma once + +// Dependencies +#include "detail/qualifier.hpp" +#include "detail/setup.hpp" +#include "vec2.hpp" +#include "vec3.hpp" +#include "vec4.hpp" +#include "mat2x2.hpp" +#include "mat2x3.hpp" +#include "mat2x4.hpp" +#include "mat3x2.hpp" +#include "mat3x3.hpp" +#include "mat3x4.hpp" +#include "mat4x2.hpp" +#include "mat4x3.hpp" +#include "mat4x4.hpp" + +namespace glm { +namespace detail +{ + template + struct outerProduct_trait{}; + + template + struct outerProduct_trait<2, 2, T, Q> + { + typedef mat<2, 2, T, Q> type; + }; + + template + struct outerProduct_trait<2, 3, T, Q> + { + typedef mat<3, 2, T, Q> type; + }; + + template + struct outerProduct_trait<2, 4, T, Q> + { + typedef mat<4, 2, T, Q> type; + }; + + template + struct outerProduct_trait<3, 2, T, Q> + { + typedef mat<2, 3, T, Q> type; + }; + + template + struct outerProduct_trait<3, 3, T, Q> + { + typedef mat<3, 3, T, Q> type; + }; + + template + struct outerProduct_trait<3, 4, T, Q> + { + typedef mat<4, 3, T, Q> type; + }; + + template + struct outerProduct_trait<4, 2, T, Q> + { + typedef mat<2, 4, T, Q> type; + }; + + template + struct outerProduct_trait<4, 3, T, Q> + { + typedef mat<3, 4, T, Q> type; + }; + + template + struct outerProduct_trait<4, 4, T, Q> + { + typedef mat<4, 4, T, Q> type; + }; +}//namespace detail + + /// @addtogroup core_func_matrix + /// @{ + + /// Multiply matrix x by matrix y component-wise, i.e., + /// result[i][j] is the scalar product of x[i][j] and y[i][j]. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL matrixCompMult man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL mat matrixCompMult(mat const& x, mat const& y); + + /// Treats the first parameter c as a column vector + /// and the second parameter r as a row vector + /// and does a linear algebraic matrix multiply c * r. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL outerProduct man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL typename detail::outerProduct_trait::type outerProduct(vec const& c, vec const& r); + + /// Returns the transposed matrix of x + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL transpose man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL typename mat::transpose_type transpose(mat const& x); + + /// Return the determinant of a squared matrix. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL determinant man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL T determinant(mat const& m); + + /// Return the inverse of a squared matrix. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL inverse man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL mat inverse(mat const& m); + + /// @} +}//namespace glm + +#include "detail/func_matrix.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/packing.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/packing.hpp new file mode 100644 index 0000000..ca83ac1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/packing.hpp @@ -0,0 +1,173 @@ +/// @ref core +/// @file glm/packing.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions +/// @see gtc_packing +/// +/// @defgroup core_func_packing Floating-Point Pack and Unpack Functions +/// @ingroup core +/// +/// Provides GLSL functions to pack and unpack half, single and double-precision floating point values into more compact integer types. +/// +/// These functions do not operate component-wise, rather as described in each case. +/// +/// Include to use these core features. + +#pragma once + +#include "./ext/vector_uint2.hpp" +#include "./ext/vector_float2.hpp" +#include "./ext/vector_float4.hpp" + +namespace glm +{ + /// @addtogroup core_func_packing + /// @{ + + /// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm2x16: round(clamp(c, 0, +1) * 65535.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see GLSL packUnorm2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint packUnorm2x16(vec2 const& v); + + /// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm2x16: round(clamp(v, -1, +1) * 32767.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see GLSL packSnorm2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint packSnorm2x16(vec2 const& v); + + /// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm4x8: round(clamp(c, 0, +1) * 255.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see GLSL packUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint packUnorm4x8(vec4 const& v); + + /// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm4x8: round(clamp(c, -1, +1) * 127.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see GLSL packSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint packSnorm4x8(vec4 const& v); + + /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm2x16: f / 65535.0 + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see GLSL unpackUnorm2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec2 unpackUnorm2x16(uint p); + + /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm2x16: clamp(f / 32767.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see GLSL unpackSnorm2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec2 unpackSnorm2x16(uint p); + + /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm4x8: f / 255.0 + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see GLSL unpackUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec4 unpackUnorm4x8(uint p); + + /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm4x8: clamp(f / 127.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see GLSL unpackSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec4 unpackSnorm4x8(uint p); + + /// Returns a double-qualifier value obtained by packing the components of v into a 64-bit value. + /// If an IEEE 754 Inf or NaN is created, it will not signal, and the resulting floating point value is unspecified. + /// Otherwise, the bit- level representation of v is preserved. + /// The first vector component specifies the 32 least significant bits; + /// the second component specifies the 32 most significant bits. + /// + /// @see GLSL packDouble2x32 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL double packDouble2x32(uvec2 const& v); + + /// Returns a two-component unsigned integer vector representation of v. + /// The bit-level representation of v is preserved. + /// The first component of the vector contains the 32 least significant bits of the double; + /// the second component consists the 32 most significant bits. + /// + /// @see GLSL unpackDouble2x32 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uvec2 unpackDouble2x32(double v); + + /// Returns an unsigned integer obtained by converting the components of a two-component floating-point vector + /// to the 16-bit floating-point representation found in the OpenGL Specification, + /// and then packing these two 16- bit integers into a 32-bit unsigned integer. + /// The first vector component specifies the 16 least-significant bits of the result; + /// the second component specifies the 16 most-significant bits. + /// + /// @see GLSL packHalf2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint packHalf2x16(vec2 const& v); + + /// Returns a two-component floating-point vector with components obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values, + /// interpreting those values as 16-bit floating-point numbers according to the OpenGL Specification, + /// and converting them to 32-bit floating-point values. + /// The first component of the vector is obtained from the 16 least-significant bits of v; + /// the second component is obtained from the 16 most-significant bits of v. + /// + /// @see GLSL unpackHalf2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec2 unpackHalf2x16(uint v); + + /// @} +}//namespace glm + +#include "detail/func_packing.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/common.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/common.h new file mode 100644 index 0000000..a580a1f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/common.h @@ -0,0 +1,240 @@ +/// @ref simd +/// @file glm/simd/common.h + +#pragma once + +#include "platform.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_add(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_add_ps(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec1_add(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_add_ss(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_sub(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_sub_ps(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec1_sub(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_sub_ss(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_mul(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_mul_ps(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec1_mul(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_mul_ss(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_div(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_div_ps(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec1_div(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_div_ss(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_div_lowp(glm_f32vec4 a, glm_f32vec4 b) +{ + return glm_vec4_mul(a, _mm_rcp_ps(b)); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_swizzle_xyzw(glm_f32vec4 a) +{ +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + return _mm_permute_ps(a, _MM_SHUFFLE(3, 2, 1, 0)); +# else + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 2, 1, 0)); +# endif +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec1_fma(glm_f32vec4 a, glm_f32vec4 b, glm_f32vec4 c) +{ +# if (GLM_ARCH & GLM_ARCH_AVX2_BIT) && !(GLM_COMPILER & GLM_COMPILER_CLANG) + return _mm_fmadd_ss(a, b, c); +# else + return _mm_add_ss(_mm_mul_ss(a, b), c); +# endif +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_fma(glm_f32vec4 a, glm_f32vec4 b, glm_f32vec4 c) +{ +# if (GLM_ARCH & GLM_ARCH_AVX2_BIT) && !(GLM_COMPILER & GLM_COMPILER_CLANG) + return _mm_fmadd_ps(a, b, c); +# else + return glm_vec4_add(glm_vec4_mul(a, b), c); +# endif +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_abs(glm_f32vec4 x) +{ + return _mm_and_ps(x, _mm_castsi128_ps(_mm_set1_epi32(0x7FFFFFFF))); +} + +GLM_FUNC_QUALIFIER glm_ivec4 glm_ivec4_abs(glm_ivec4 x) +{ +# if GLM_ARCH & GLM_ARCH_SSSE3_BIT + return _mm_sign_epi32(x, x); +# else + glm_ivec4 const sgn0 = _mm_srai_epi32(x, 31); + glm_ivec4 const inv0 = _mm_xor_si128(x, sgn0); + glm_ivec4 const sub0 = _mm_sub_epi32(inv0, sgn0); + return sub0; +# endif +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_sign(glm_vec4 x) +{ + glm_vec4 const zro0 = _mm_setzero_ps(); + glm_vec4 const cmp0 = _mm_cmplt_ps(x, zro0); + glm_vec4 const cmp1 = _mm_cmpgt_ps(x, zro0); + glm_vec4 const and0 = _mm_and_ps(cmp0, _mm_set1_ps(-1.0f)); + glm_vec4 const and1 = _mm_and_ps(cmp1, _mm_set1_ps(1.0f)); + glm_vec4 const or0 = _mm_or_ps(and0, and1); + return or0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_round(glm_vec4 x) +{ +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + return _mm_round_ps(x, _MM_FROUND_TO_NEAREST_INT); +# else + glm_vec4 const sgn0 = _mm_castsi128_ps(_mm_set1_epi32(int(0x80000000))); + glm_vec4 const and0 = _mm_and_ps(sgn0, x); + glm_vec4 const or0 = _mm_or_ps(and0, _mm_set_ps1(8388608.0f)); + glm_vec4 const add0 = glm_vec4_add(x, or0); + glm_vec4 const sub0 = glm_vec4_sub(add0, or0); + return sub0; +# endif +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_floor(glm_vec4 x) +{ +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + return _mm_floor_ps(x); +# else + glm_vec4 const rnd0 = glm_vec4_round(x); + glm_vec4 const cmp0 = _mm_cmplt_ps(x, rnd0); + glm_vec4 const and0 = _mm_and_ps(cmp0, _mm_set1_ps(1.0f)); + glm_vec4 const sub0 = glm_vec4_sub(rnd0, and0); + return sub0; +# endif +} + +/* trunc TODO +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_trunc(glm_vec4 x) +{ + return glm_vec4(); +} +*/ + +//roundEven +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_roundEven(glm_vec4 x) +{ + glm_vec4 const sgn0 = _mm_castsi128_ps(_mm_set1_epi32(int(0x80000000))); + glm_vec4 const and0 = _mm_and_ps(sgn0, x); + glm_vec4 const or0 = _mm_or_ps(and0, _mm_set_ps1(8388608.0f)); + glm_vec4 const add0 = glm_vec4_add(x, or0); + glm_vec4 const sub0 = glm_vec4_sub(add0, or0); + return sub0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_ceil(glm_vec4 x) +{ +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + return _mm_ceil_ps(x); +# else + glm_vec4 const rnd0 = glm_vec4_round(x); + glm_vec4 const cmp0 = _mm_cmpgt_ps(x, rnd0); + glm_vec4 const and0 = _mm_and_ps(cmp0, _mm_set1_ps(1.0f)); + glm_vec4 const add0 = glm_vec4_add(rnd0, and0); + return add0; +# endif +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_fract(glm_vec4 x) +{ + glm_vec4 const flr0 = glm_vec4_floor(x); + glm_vec4 const sub0 = glm_vec4_sub(x, flr0); + return sub0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_mod(glm_vec4 x, glm_vec4 y) +{ + glm_vec4 const div0 = glm_vec4_div(x, y); + glm_vec4 const flr0 = glm_vec4_floor(div0); + glm_vec4 const mul0 = glm_vec4_mul(y, flr0); + glm_vec4 const sub0 = glm_vec4_sub(x, mul0); + return sub0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_clamp(glm_vec4 v, glm_vec4 minVal, glm_vec4 maxVal) +{ + glm_vec4 const min0 = _mm_min_ps(v, maxVal); + glm_vec4 const max0 = _mm_max_ps(min0, minVal); + return max0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_mix(glm_vec4 v1, glm_vec4 v2, glm_vec4 a) +{ + glm_vec4 const sub0 = glm_vec4_sub(_mm_set1_ps(1.0f), a); + glm_vec4 const mul0 = glm_vec4_mul(v1, sub0); + glm_vec4 const mad0 = glm_vec4_fma(v2, a, mul0); + return mad0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_step(glm_vec4 edge, glm_vec4 x) +{ + glm_vec4 const cmp = _mm_cmple_ps(x, edge); + return _mm_movemask_ps(cmp) == 0 ? _mm_set1_ps(1.0f) : _mm_setzero_ps(); +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_smoothstep(glm_vec4 edge0, glm_vec4 edge1, glm_vec4 x) +{ + glm_vec4 const sub0 = glm_vec4_sub(x, edge0); + glm_vec4 const sub1 = glm_vec4_sub(edge1, edge0); + glm_vec4 const div0 = glm_vec4_div(sub0, sub1); + glm_vec4 const clp0 = glm_vec4_clamp(div0, _mm_setzero_ps(), _mm_set1_ps(1.0f)); + glm_vec4 const mul0 = glm_vec4_mul(_mm_set1_ps(2.0f), clp0); + glm_vec4 const sub2 = glm_vec4_sub(_mm_set1_ps(3.0f), mul0); + glm_vec4 const mul1 = glm_vec4_mul(clp0, clp0); + glm_vec4 const mul2 = glm_vec4_mul(mul1, sub2); + return mul2; +} + +// Agner Fog method +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_nan(glm_vec4 x) +{ + glm_ivec4 const t1 = _mm_castps_si128(x); // reinterpret as 32-bit integer + glm_ivec4 const t2 = _mm_sll_epi32(t1, _mm_cvtsi32_si128(1)); // shift out sign bit + glm_ivec4 const t3 = _mm_set1_epi32(int(0xFF000000)); // exponent mask + glm_ivec4 const t4 = _mm_and_si128(t2, t3); // exponent + glm_ivec4 const t5 = _mm_andnot_si128(t3, t2); // fraction + glm_ivec4 const Equal = _mm_cmpeq_epi32(t3, t4); + glm_ivec4 const Nequal = _mm_cmpeq_epi32(t5, _mm_setzero_si128()); + glm_ivec4 const And = _mm_and_si128(Equal, Nequal); + return _mm_castsi128_ps(And); // exponent = all 1s and fraction != 0 +} + +// Agner Fog method +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_inf(glm_vec4 x) +{ + glm_ivec4 const t1 = _mm_castps_si128(x); // reinterpret as 32-bit integer + glm_ivec4 const t2 = _mm_sll_epi32(t1, _mm_cvtsi32_si128(1)); // shift out sign bit + return _mm_castsi128_ps(_mm_cmpeq_epi32(t2, _mm_set1_epi32(int(0xFF000000)))); // exponent is all 1s, fraction is 0 +} + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/exponential.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/exponential.h new file mode 100644 index 0000000..bc351d0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/exponential.h @@ -0,0 +1,20 @@ +/// @ref simd +/// @file glm/simd/experimental.h + +#pragma once + +#include "platform.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec1_sqrt_lowp(glm_f32vec4 x) +{ + return _mm_mul_ss(_mm_rsqrt_ss(x), x); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_sqrt_lowp(glm_f32vec4 x) +{ + return _mm_mul_ps(_mm_rsqrt_ps(x), x); +} + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/geometric.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/geometric.h new file mode 100644 index 0000000..afbe590 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/geometric.h @@ -0,0 +1,130 @@ +/// @ref simd +/// @file glm/simd/geometric.h + +#pragma once + +#include "common.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +GLM_FUNC_DECL glm_vec4 glm_vec4_dot(glm_vec4 v1, glm_vec4 v2); +GLM_FUNC_DECL glm_vec4 glm_vec1_dot(glm_vec4 v1, glm_vec4 v2); + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_length(glm_vec4 x) +{ + glm_vec4 const dot0 = glm_vec4_dot(x, x); + glm_vec4 const sqt0 = _mm_sqrt_ps(dot0); + return sqt0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_distance(glm_vec4 p0, glm_vec4 p1) +{ + glm_vec4 const sub0 = _mm_sub_ps(p0, p1); + glm_vec4 const len0 = glm_vec4_length(sub0); + return len0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_dot(glm_vec4 v1, glm_vec4 v2) +{ +# if GLM_ARCH & GLM_ARCH_AVX_BIT + return _mm_dp_ps(v1, v2, 0xff); +# elif GLM_ARCH & GLM_ARCH_SSE3_BIT + glm_vec4 const mul0 = _mm_mul_ps(v1, v2); + glm_vec4 const hadd0 = _mm_hadd_ps(mul0, mul0); + glm_vec4 const hadd1 = _mm_hadd_ps(hadd0, hadd0); + return hadd1; +# else + glm_vec4 const mul0 = _mm_mul_ps(v1, v2); + glm_vec4 const swp0 = _mm_shuffle_ps(mul0, mul0, _MM_SHUFFLE(2, 3, 0, 1)); + glm_vec4 const add0 = _mm_add_ps(mul0, swp0); + glm_vec4 const swp1 = _mm_shuffle_ps(add0, add0, _MM_SHUFFLE(0, 1, 2, 3)); + glm_vec4 const add1 = _mm_add_ps(add0, swp1); + return add1; +# endif +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec1_dot(glm_vec4 v1, glm_vec4 v2) +{ +# if GLM_ARCH & GLM_ARCH_AVX_BIT + return _mm_dp_ps(v1, v2, 0xff); +# elif GLM_ARCH & GLM_ARCH_SSE3_BIT + glm_vec4 const mul0 = _mm_mul_ps(v1, v2); + glm_vec4 const had0 = _mm_hadd_ps(mul0, mul0); + glm_vec4 const had1 = _mm_hadd_ps(had0, had0); + return had1; +# else + glm_vec4 const mul0 = _mm_mul_ps(v1, v2); + glm_vec4 const mov0 = _mm_movehl_ps(mul0, mul0); + glm_vec4 const add0 = _mm_add_ps(mov0, mul0); + glm_vec4 const swp1 = _mm_shuffle_ps(add0, add0, 1); + glm_vec4 const add1 = _mm_add_ss(add0, swp1); + return add1; +# endif +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_cross(glm_vec4 v1, glm_vec4 v2) +{ + glm_vec4 const swp0 = _mm_shuffle_ps(v1, v1, _MM_SHUFFLE(3, 0, 2, 1)); + glm_vec4 const swp1 = _mm_shuffle_ps(v1, v1, _MM_SHUFFLE(3, 1, 0, 2)); + glm_vec4 const swp2 = _mm_shuffle_ps(v2, v2, _MM_SHUFFLE(3, 0, 2, 1)); + glm_vec4 const swp3 = _mm_shuffle_ps(v2, v2, _MM_SHUFFLE(3, 1, 0, 2)); + glm_vec4 const mul0 = _mm_mul_ps(swp0, swp3); + glm_vec4 const mul1 = _mm_mul_ps(swp1, swp2); + glm_vec4 const sub0 = _mm_sub_ps(mul0, mul1); + return sub0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_normalize(glm_vec4 v) +{ + glm_vec4 const dot0 = glm_vec4_dot(v, v); + glm_vec4 const isr0 = _mm_rsqrt_ps(dot0); + glm_vec4 const mul0 = _mm_mul_ps(v, isr0); + return mul0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_faceforward(glm_vec4 N, glm_vec4 I, glm_vec4 Nref) +{ + glm_vec4 const dot0 = glm_vec4_dot(Nref, I); + glm_vec4 const sgn0 = glm_vec4_sign(dot0); + glm_vec4 const mul0 = _mm_mul_ps(sgn0, _mm_set1_ps(-1.0f)); + glm_vec4 const mul1 = _mm_mul_ps(N, mul0); + return mul1; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_reflect(glm_vec4 I, glm_vec4 N) +{ + glm_vec4 const dot0 = glm_vec4_dot(N, I); + glm_vec4 const mul0 = _mm_mul_ps(N, dot0); + glm_vec4 const mul1 = _mm_mul_ps(mul0, _mm_set1_ps(2.0f)); + glm_vec4 const sub0 = _mm_sub_ps(I, mul1); + return sub0; +} + +GLM_FUNC_QUALIFIER __m128 glm_vec4_refract(glm_vec4 I, glm_vec4 N, glm_vec4 eta) +{ + // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)); + // if (k < 0.0) + // R = genType(0.0); // or genDType(0.0) + // else + // R = eta * I - (eta * dot(N, I) + sqrt(k)) * N; + + glm_vec4 const dot0 = glm_vec4_dot(N, I); // dot(N, I) + glm_vec4 const mul0 = _mm_mul_ps(eta, eta); // eta * eta + glm_vec4 const mul1 = _mm_mul_ps(dot0, dot0); // dot(N, I) * dot(N, I) + glm_vec4 const sub1 = _mm_sub_ps(_mm_set1_ps(1.0f), mul1); // (1.0 - dot(N, I) * dot(N, I)) + glm_vec4 const mul2 = _mm_mul_ps(mul0, sub1); // eta * eta * (1.0 - dot(N, I) * dot(N, I)) + glm_vec4 const sub0 = _mm_sub_ps(_mm_set1_ps(1.0f), mul2); // 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) + + if(_mm_movemask_ps(_mm_cmplt_ss(sub0, _mm_set1_ps(0.0f))) == 0) + return _mm_set1_ps(0.0f); + + glm_vec4 const sqt0 = _mm_sqrt_ps(sub0); + glm_vec4 const mad0 = glm_vec4_fma(eta, dot0, sqt0); + glm_vec4 const mul4 = _mm_mul_ps(mad0, N); + glm_vec4 const mul5 = _mm_mul_ps(eta, I); + glm_vec4 const sub2 = _mm_sub_ps(mul5, mul4); + + return sub2; +} + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/integer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/integer.h new file mode 100644 index 0000000..9381418 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/integer.h @@ -0,0 +1,115 @@ +/// @ref simd +/// @file glm/simd/integer.h + +#pragma once + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +GLM_FUNC_QUALIFIER glm_uvec4 glm_i128_interleave(glm_uvec4 x) +{ + glm_uvec4 const Mask4 = _mm_set1_epi32(0x0000FFFF); + glm_uvec4 const Mask3 = _mm_set1_epi32(0x00FF00FF); + glm_uvec4 const Mask2 = _mm_set1_epi32(0x0F0F0F0F); + glm_uvec4 const Mask1 = _mm_set1_epi32(0x33333333); + glm_uvec4 const Mask0 = _mm_set1_epi32(0x55555555); + + glm_uvec4 Reg1; + glm_uvec4 Reg2; + + // REG1 = x; + // REG2 = y; + //Reg1 = _mm_unpacklo_epi64(x, y); + Reg1 = x; + + //REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x0000FFFF0000FFFF); + //REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x0000FFFF0000FFFF); + Reg2 = _mm_slli_si128(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask4); + + //REG1 = ((REG1 << 8) | REG1) & glm::uint64(0x00FF00FF00FF00FF); + //REG2 = ((REG2 << 8) | REG2) & glm::uint64(0x00FF00FF00FF00FF); + Reg2 = _mm_slli_si128(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask3); + + //REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x0F0F0F0F0F0F0F0F); + //REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x0F0F0F0F0F0F0F0F); + Reg2 = _mm_slli_epi32(Reg1, 4); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask2); + + //REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x3333333333333333); + //REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x3333333333333333); + Reg2 = _mm_slli_epi32(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask1); + + //REG1 = ((REG1 << 1) | REG1) & glm::uint64(0x5555555555555555); + //REG2 = ((REG2 << 1) | REG2) & glm::uint64(0x5555555555555555); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask0); + + //return REG1 | (REG2 << 1); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg2 = _mm_srli_si128(Reg2, 8); + Reg1 = _mm_or_si128(Reg1, Reg2); + + return Reg1; +} + +GLM_FUNC_QUALIFIER glm_uvec4 glm_i128_interleave2(glm_uvec4 x, glm_uvec4 y) +{ + glm_uvec4 const Mask4 = _mm_set1_epi32(0x0000FFFF); + glm_uvec4 const Mask3 = _mm_set1_epi32(0x00FF00FF); + glm_uvec4 const Mask2 = _mm_set1_epi32(0x0F0F0F0F); + glm_uvec4 const Mask1 = _mm_set1_epi32(0x33333333); + glm_uvec4 const Mask0 = _mm_set1_epi32(0x55555555); + + glm_uvec4 Reg1; + glm_uvec4 Reg2; + + // REG1 = x; + // REG2 = y; + Reg1 = _mm_unpacklo_epi64(x, y); + + //REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x0000FFFF0000FFFF); + //REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x0000FFFF0000FFFF); + Reg2 = _mm_slli_si128(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask4); + + //REG1 = ((REG1 << 8) | REG1) & glm::uint64(0x00FF00FF00FF00FF); + //REG2 = ((REG2 << 8) | REG2) & glm::uint64(0x00FF00FF00FF00FF); + Reg2 = _mm_slli_si128(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask3); + + //REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x0F0F0F0F0F0F0F0F); + //REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x0F0F0F0F0F0F0F0F); + Reg2 = _mm_slli_epi32(Reg1, 4); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask2); + + //REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x3333333333333333); + //REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x3333333333333333); + Reg2 = _mm_slli_epi32(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask1); + + //REG1 = ((REG1 << 1) | REG1) & glm::uint64(0x5555555555555555); + //REG2 = ((REG2 << 1) | REG2) & glm::uint64(0x5555555555555555); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask0); + + //return REG1 | (REG2 << 1); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg2 = _mm_srli_si128(Reg2, 8); + Reg1 = _mm_or_si128(Reg1, Reg2); + + return Reg1; +} + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/matrix.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/matrix.h new file mode 100644 index 0000000..b6c42ea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/matrix.h @@ -0,0 +1,1028 @@ +/// @ref simd +/// @file glm/simd/matrix.h + +#pragma once + +#include "geometric.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +GLM_FUNC_QUALIFIER void glm_mat4_matrixCompMult(glm_vec4 const in1[4], glm_vec4 const in2[4], glm_vec4 out[4]) +{ + out[0] = _mm_mul_ps(in1[0], in2[0]); + out[1] = _mm_mul_ps(in1[1], in2[1]); + out[2] = _mm_mul_ps(in1[2], in2[2]); + out[3] = _mm_mul_ps(in1[3], in2[3]); +} + +GLM_FUNC_QUALIFIER void glm_mat4_add(glm_vec4 const in1[4], glm_vec4 const in2[4], glm_vec4 out[4]) +{ + out[0] = _mm_add_ps(in1[0], in2[0]); + out[1] = _mm_add_ps(in1[1], in2[1]); + out[2] = _mm_add_ps(in1[2], in2[2]); + out[3] = _mm_add_ps(in1[3], in2[3]); +} + +GLM_FUNC_QUALIFIER void glm_mat4_sub(glm_vec4 const in1[4], glm_vec4 const in2[4], glm_vec4 out[4]) +{ + out[0] = _mm_sub_ps(in1[0], in2[0]); + out[1] = _mm_sub_ps(in1[1], in2[1]); + out[2] = _mm_sub_ps(in1[2], in2[2]); + out[3] = _mm_sub_ps(in1[3], in2[3]); +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_mat4_mul_vec4(glm_vec4 const m[4], glm_vec4 v) +{ + __m128 v0 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 v1 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 v2 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 v3 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(m[0], v0); + __m128 m1 = _mm_mul_ps(m[1], v1); + __m128 m2 = _mm_mul_ps(m[2], v2); + __m128 m3 = _mm_mul_ps(m[3], v3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + return a2; +} + +GLM_FUNC_QUALIFIER __m128 glm_vec4_mul_mat4(glm_vec4 v, glm_vec4 const m[4]) +{ + __m128 i0 = m[0]; + __m128 i1 = m[1]; + __m128 i2 = m[2]; + __m128 i3 = m[3]; + + __m128 m0 = _mm_mul_ps(v, i0); + __m128 m1 = _mm_mul_ps(v, i1); + __m128 m2 = _mm_mul_ps(v, i2); + __m128 m3 = _mm_mul_ps(v, i3); + + __m128 u0 = _mm_unpacklo_ps(m0, m1); + __m128 u1 = _mm_unpackhi_ps(m0, m1); + __m128 a0 = _mm_add_ps(u0, u1); + + __m128 u2 = _mm_unpacklo_ps(m2, m3); + __m128 u3 = _mm_unpackhi_ps(m2, m3); + __m128 a1 = _mm_add_ps(u2, u3); + + __m128 f0 = _mm_movelh_ps(a0, a1); + __m128 f1 = _mm_movehl_ps(a1, a0); + __m128 f2 = _mm_add_ps(f0, f1); + + return f2; +} + +GLM_FUNC_QUALIFIER void glm_mat4_mul(glm_vec4 const in1[4], glm_vec4 const in2[4], glm_vec4 out[4]) +{ + { + __m128 e0 = _mm_shuffle_ps(in2[0], in2[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(in2[0], in2[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(in2[0], in2[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(in2[0], in2[0], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(in1[0], e0); + __m128 m1 = _mm_mul_ps(in1[1], e1); + __m128 m2 = _mm_mul_ps(in1[2], e2); + __m128 m3 = _mm_mul_ps(in1[3], e3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + out[0] = a2; + } + + { + __m128 e0 = _mm_shuffle_ps(in2[1], in2[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(in2[1], in2[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(in2[1], in2[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(in2[1], in2[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(in1[0], e0); + __m128 m1 = _mm_mul_ps(in1[1], e1); + __m128 m2 = _mm_mul_ps(in1[2], e2); + __m128 m3 = _mm_mul_ps(in1[3], e3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + out[1] = a2; + } + + { + __m128 e0 = _mm_shuffle_ps(in2[2], in2[2], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(in2[2], in2[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(in2[2], in2[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(in2[2], in2[2], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(in1[0], e0); + __m128 m1 = _mm_mul_ps(in1[1], e1); + __m128 m2 = _mm_mul_ps(in1[2], e2); + __m128 m3 = _mm_mul_ps(in1[3], e3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + out[2] = a2; + } + + { + //(__m128&)_mm_shuffle_epi32(__m128i&)in2[0], _MM_SHUFFLE(3, 3, 3, 3)) + __m128 e0 = _mm_shuffle_ps(in2[3], in2[3], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(in2[3], in2[3], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(in2[3], in2[3], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(in2[3], in2[3], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(in1[0], e0); + __m128 m1 = _mm_mul_ps(in1[1], e1); + __m128 m2 = _mm_mul_ps(in1[2], e2); + __m128 m3 = _mm_mul_ps(in1[3], e3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + out[3] = a2; + } +} + +GLM_FUNC_QUALIFIER void glm_mat4_transpose(glm_vec4 const in[4], glm_vec4 out[4]) +{ + __m128 tmp0 = _mm_shuffle_ps(in[0], in[1], 0x44); + __m128 tmp2 = _mm_shuffle_ps(in[0], in[1], 0xEE); + __m128 tmp1 = _mm_shuffle_ps(in[2], in[3], 0x44); + __m128 tmp3 = _mm_shuffle_ps(in[2], in[3], 0xEE); + + out[0] = _mm_shuffle_ps(tmp0, tmp1, 0x88); + out[1] = _mm_shuffle_ps(tmp0, tmp1, 0xDD); + out[2] = _mm_shuffle_ps(tmp2, tmp3, 0x88); + out[3] = _mm_shuffle_ps(tmp2, tmp3, 0xDD); +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_mat4_determinant_highp(glm_vec4 const in[4]) +{ + __m128 Fac0; + { + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + // valType SubFactor13 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac0 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac1; + { + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + // valType SubFactor14 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac1 = _mm_sub_ps(Mul00, Mul01); + } + + + __m128 Fac2; + { + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + // valType SubFactor15 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac2 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac3; + { + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + // valType SubFactor16 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac3 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac4; + { + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + // valType SubFactor17 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac4 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac5; + { + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor12 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + // valType SubFactor18 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac5 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 SignA = _mm_set_ps( 1.0f,-1.0f, 1.0f,-1.0f); + __m128 SignB = _mm_set_ps(-1.0f, 1.0f,-1.0f, 1.0f); + + // m[1][0] + // m[0][0] + // m[0][0] + // m[0][0] + __m128 Temp0 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Vec0 = _mm_shuffle_ps(Temp0, Temp0, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][1] + // m[0][1] + // m[0][1] + // m[0][1] + __m128 Temp1 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Vec1 = _mm_shuffle_ps(Temp1, Temp1, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][2] + // m[0][2] + // m[0][2] + // m[0][2] + __m128 Temp2 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Vec2 = _mm_shuffle_ps(Temp2, Temp2, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][3] + // m[0][3] + // m[0][3] + // m[0][3] + __m128 Temp3 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Vec3 = _mm_shuffle_ps(Temp3, Temp3, _MM_SHUFFLE(2, 2, 2, 0)); + + // col0 + // + (Vec1[0] * Fac0[0] - Vec2[0] * Fac1[0] + Vec3[0] * Fac2[0]), + // - (Vec1[1] * Fac0[1] - Vec2[1] * Fac1[1] + Vec3[1] * Fac2[1]), + // + (Vec1[2] * Fac0[2] - Vec2[2] * Fac1[2] + Vec3[2] * Fac2[2]), + // - (Vec1[3] * Fac0[3] - Vec2[3] * Fac1[3] + Vec3[3] * Fac2[3]), + __m128 Mul00 = _mm_mul_ps(Vec1, Fac0); + __m128 Mul01 = _mm_mul_ps(Vec2, Fac1); + __m128 Mul02 = _mm_mul_ps(Vec3, Fac2); + __m128 Sub00 = _mm_sub_ps(Mul00, Mul01); + __m128 Add00 = _mm_add_ps(Sub00, Mul02); + __m128 Inv0 = _mm_mul_ps(SignB, Add00); + + // col1 + // - (Vec0[0] * Fac0[0] - Vec2[0] * Fac3[0] + Vec3[0] * Fac4[0]), + // + (Vec0[0] * Fac0[1] - Vec2[1] * Fac3[1] + Vec3[1] * Fac4[1]), + // - (Vec0[0] * Fac0[2] - Vec2[2] * Fac3[2] + Vec3[2] * Fac4[2]), + // + (Vec0[0] * Fac0[3] - Vec2[3] * Fac3[3] + Vec3[3] * Fac4[3]), + __m128 Mul03 = _mm_mul_ps(Vec0, Fac0); + __m128 Mul04 = _mm_mul_ps(Vec2, Fac3); + __m128 Mul05 = _mm_mul_ps(Vec3, Fac4); + __m128 Sub01 = _mm_sub_ps(Mul03, Mul04); + __m128 Add01 = _mm_add_ps(Sub01, Mul05); + __m128 Inv1 = _mm_mul_ps(SignA, Add01); + + // col2 + // + (Vec0[0] * Fac1[0] - Vec1[0] * Fac3[0] + Vec3[0] * Fac5[0]), + // - (Vec0[0] * Fac1[1] - Vec1[1] * Fac3[1] + Vec3[1] * Fac5[1]), + // + (Vec0[0] * Fac1[2] - Vec1[2] * Fac3[2] + Vec3[2] * Fac5[2]), + // - (Vec0[0] * Fac1[3] - Vec1[3] * Fac3[3] + Vec3[3] * Fac5[3]), + __m128 Mul06 = _mm_mul_ps(Vec0, Fac1); + __m128 Mul07 = _mm_mul_ps(Vec1, Fac3); + __m128 Mul08 = _mm_mul_ps(Vec3, Fac5); + __m128 Sub02 = _mm_sub_ps(Mul06, Mul07); + __m128 Add02 = _mm_add_ps(Sub02, Mul08); + __m128 Inv2 = _mm_mul_ps(SignB, Add02); + + // col3 + // - (Vec1[0] * Fac2[0] - Vec1[0] * Fac4[0] + Vec2[0] * Fac5[0]), + // + (Vec1[0] * Fac2[1] - Vec1[1] * Fac4[1] + Vec2[1] * Fac5[1]), + // - (Vec1[0] * Fac2[2] - Vec1[2] * Fac4[2] + Vec2[2] * Fac5[2]), + // + (Vec1[0] * Fac2[3] - Vec1[3] * Fac4[3] + Vec2[3] * Fac5[3])); + __m128 Mul09 = _mm_mul_ps(Vec0, Fac2); + __m128 Mul10 = _mm_mul_ps(Vec1, Fac4); + __m128 Mul11 = _mm_mul_ps(Vec2, Fac5); + __m128 Sub03 = _mm_sub_ps(Mul09, Mul10); + __m128 Add03 = _mm_add_ps(Sub03, Mul11); + __m128 Inv3 = _mm_mul_ps(SignA, Add03); + + __m128 Row0 = _mm_shuffle_ps(Inv0, Inv1, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row1 = _mm_shuffle_ps(Inv2, Inv3, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row2 = _mm_shuffle_ps(Row0, Row1, _MM_SHUFFLE(2, 0, 2, 0)); + + // valType Determinant = m[0][0] * Inverse[0][0] + // + m[0][1] * Inverse[1][0] + // + m[0][2] * Inverse[2][0] + // + m[0][3] * Inverse[3][0]; + __m128 Det0 = glm_vec4_dot(in[0], Row2); + return Det0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_mat4_determinant_lowp(glm_vec4 const m[4]) +{ + // _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128( + + //T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + //T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + //T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + //T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + //T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + //T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + + // First 2 columns + __m128 Swp2A = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[2]), _MM_SHUFFLE(0, 1, 1, 2))); + __m128 Swp3A = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[3]), _MM_SHUFFLE(3, 2, 3, 3))); + __m128 MulA = _mm_mul_ps(Swp2A, Swp3A); + + // Second 2 columns + __m128 Swp2B = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[2]), _MM_SHUFFLE(3, 2, 3, 3))); + __m128 Swp3B = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[3]), _MM_SHUFFLE(0, 1, 1, 2))); + __m128 MulB = _mm_mul_ps(Swp2B, Swp3B); + + // Columns subtraction + __m128 SubE = _mm_sub_ps(MulA, MulB); + + // Last 2 rows + __m128 Swp2C = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[2]), _MM_SHUFFLE(0, 0, 1, 2))); + __m128 Swp3C = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[3]), _MM_SHUFFLE(1, 2, 0, 0))); + __m128 MulC = _mm_mul_ps(Swp2C, Swp3C); + __m128 SubF = _mm_sub_ps(_mm_movehl_ps(MulC, MulC), MulC); + + //vec<4, T, Q> DetCof( + // + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), + // - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), + // + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), + // - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05)); + + __m128 SubFacA = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(SubE), _MM_SHUFFLE(2, 1, 0, 0))); + __m128 SwpFacA = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[1]), _MM_SHUFFLE(0, 0, 0, 1))); + __m128 MulFacA = _mm_mul_ps(SwpFacA, SubFacA); + + __m128 SubTmpB = _mm_shuffle_ps(SubE, SubF, _MM_SHUFFLE(0, 0, 3, 1)); + __m128 SubFacB = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(SubTmpB), _MM_SHUFFLE(3, 1, 1, 0)));//SubF[0], SubE[3], SubE[3], SubE[1]; + __m128 SwpFacB = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[1]), _MM_SHUFFLE(1, 1, 2, 2))); + __m128 MulFacB = _mm_mul_ps(SwpFacB, SubFacB); + + __m128 SubRes = _mm_sub_ps(MulFacA, MulFacB); + + __m128 SubTmpC = _mm_shuffle_ps(SubE, SubF, _MM_SHUFFLE(1, 0, 2, 2)); + __m128 SubFacC = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(SubTmpC), _MM_SHUFFLE(3, 3, 2, 0))); + __m128 SwpFacC = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[1]), _MM_SHUFFLE(2, 3, 3, 3))); + __m128 MulFacC = _mm_mul_ps(SwpFacC, SubFacC); + + __m128 AddRes = _mm_add_ps(SubRes, MulFacC); + __m128 DetCof = _mm_mul_ps(AddRes, _mm_setr_ps( 1.0f,-1.0f, 1.0f,-1.0f)); + + //return m[0][0] * DetCof[0] + // + m[0][1] * DetCof[1] + // + m[0][2] * DetCof[2] + // + m[0][3] * DetCof[3]; + + return glm_vec4_dot(m[0], DetCof); +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_mat4_determinant(glm_vec4 const m[4]) +{ + // _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(add) + + //T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + //T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + //T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + //T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + //T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + //T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + + // First 2 columns + __m128 Swp2A = _mm_shuffle_ps(m[2], m[2], _MM_SHUFFLE(0, 1, 1, 2)); + __m128 Swp3A = _mm_shuffle_ps(m[3], m[3], _MM_SHUFFLE(3, 2, 3, 3)); + __m128 MulA = _mm_mul_ps(Swp2A, Swp3A); + + // Second 2 columns + __m128 Swp2B = _mm_shuffle_ps(m[2], m[2], _MM_SHUFFLE(3, 2, 3, 3)); + __m128 Swp3B = _mm_shuffle_ps(m[3], m[3], _MM_SHUFFLE(0, 1, 1, 2)); + __m128 MulB = _mm_mul_ps(Swp2B, Swp3B); + + // Columns subtraction + __m128 SubE = _mm_sub_ps(MulA, MulB); + + // Last 2 rows + __m128 Swp2C = _mm_shuffle_ps(m[2], m[2], _MM_SHUFFLE(0, 0, 1, 2)); + __m128 Swp3C = _mm_shuffle_ps(m[3], m[3], _MM_SHUFFLE(1, 2, 0, 0)); + __m128 MulC = _mm_mul_ps(Swp2C, Swp3C); + __m128 SubF = _mm_sub_ps(_mm_movehl_ps(MulC, MulC), MulC); + + //vec<4, T, Q> DetCof( + // + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), + // - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), + // + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), + // - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05)); + + __m128 SubFacA = _mm_shuffle_ps(SubE, SubE, _MM_SHUFFLE(2, 1, 0, 0)); + __m128 SwpFacA = _mm_shuffle_ps(m[1], m[1], _MM_SHUFFLE(0, 0, 0, 1)); + __m128 MulFacA = _mm_mul_ps(SwpFacA, SubFacA); + + __m128 SubTmpB = _mm_shuffle_ps(SubE, SubF, _MM_SHUFFLE(0, 0, 3, 1)); + __m128 SubFacB = _mm_shuffle_ps(SubTmpB, SubTmpB, _MM_SHUFFLE(3, 1, 1, 0));//SubF[0], SubE[3], SubE[3], SubE[1]; + __m128 SwpFacB = _mm_shuffle_ps(m[1], m[1], _MM_SHUFFLE(1, 1, 2, 2)); + __m128 MulFacB = _mm_mul_ps(SwpFacB, SubFacB); + + __m128 SubRes = _mm_sub_ps(MulFacA, MulFacB); + + __m128 SubTmpC = _mm_shuffle_ps(SubE, SubF, _MM_SHUFFLE(1, 0, 2, 2)); + __m128 SubFacC = _mm_shuffle_ps(SubTmpC, SubTmpC, _MM_SHUFFLE(3, 3, 2, 0)); + __m128 SwpFacC = _mm_shuffle_ps(m[1], m[1], _MM_SHUFFLE(2, 3, 3, 3)); + __m128 MulFacC = _mm_mul_ps(SwpFacC, SubFacC); + + __m128 AddRes = _mm_add_ps(SubRes, MulFacC); + __m128 DetCof = _mm_mul_ps(AddRes, _mm_setr_ps( 1.0f,-1.0f, 1.0f,-1.0f)); + + //return m[0][0] * DetCof[0] + // + m[0][1] * DetCof[1] + // + m[0][2] * DetCof[2] + // + m[0][3] * DetCof[3]; + + return glm_vec4_dot(m[0], DetCof); +} + +GLM_FUNC_QUALIFIER void glm_mat4_inverse(glm_vec4 const in[4], glm_vec4 out[4]) +{ + __m128 Fac0; + { + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + // valType SubFactor13 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac0 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac1; + { + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + // valType SubFactor14 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac1 = _mm_sub_ps(Mul00, Mul01); + } + + + __m128 Fac2; + { + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + // valType SubFactor15 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac2 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac3; + { + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + // valType SubFactor16 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac3 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac4; + { + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + // valType SubFactor17 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac4 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac5; + { + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor12 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + // valType SubFactor18 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac5 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 SignA = _mm_set_ps( 1.0f,-1.0f, 1.0f,-1.0f); + __m128 SignB = _mm_set_ps(-1.0f, 1.0f,-1.0f, 1.0f); + + // m[1][0] + // m[0][0] + // m[0][0] + // m[0][0] + __m128 Temp0 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Vec0 = _mm_shuffle_ps(Temp0, Temp0, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][1] + // m[0][1] + // m[0][1] + // m[0][1] + __m128 Temp1 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Vec1 = _mm_shuffle_ps(Temp1, Temp1, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][2] + // m[0][2] + // m[0][2] + // m[0][2] + __m128 Temp2 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Vec2 = _mm_shuffle_ps(Temp2, Temp2, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][3] + // m[0][3] + // m[0][3] + // m[0][3] + __m128 Temp3 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Vec3 = _mm_shuffle_ps(Temp3, Temp3, _MM_SHUFFLE(2, 2, 2, 0)); + + // col0 + // + (Vec1[0] * Fac0[0] - Vec2[0] * Fac1[0] + Vec3[0] * Fac2[0]), + // - (Vec1[1] * Fac0[1] - Vec2[1] * Fac1[1] + Vec3[1] * Fac2[1]), + // + (Vec1[2] * Fac0[2] - Vec2[2] * Fac1[2] + Vec3[2] * Fac2[2]), + // - (Vec1[3] * Fac0[3] - Vec2[3] * Fac1[3] + Vec3[3] * Fac2[3]), + __m128 Mul00 = _mm_mul_ps(Vec1, Fac0); + __m128 Mul01 = _mm_mul_ps(Vec2, Fac1); + __m128 Mul02 = _mm_mul_ps(Vec3, Fac2); + __m128 Sub00 = _mm_sub_ps(Mul00, Mul01); + __m128 Add00 = _mm_add_ps(Sub00, Mul02); + __m128 Inv0 = _mm_mul_ps(SignB, Add00); + + // col1 + // - (Vec0[0] * Fac0[0] - Vec2[0] * Fac3[0] + Vec3[0] * Fac4[0]), + // + (Vec0[0] * Fac0[1] - Vec2[1] * Fac3[1] + Vec3[1] * Fac4[1]), + // - (Vec0[0] * Fac0[2] - Vec2[2] * Fac3[2] + Vec3[2] * Fac4[2]), + // + (Vec0[0] * Fac0[3] - Vec2[3] * Fac3[3] + Vec3[3] * Fac4[3]), + __m128 Mul03 = _mm_mul_ps(Vec0, Fac0); + __m128 Mul04 = _mm_mul_ps(Vec2, Fac3); + __m128 Mul05 = _mm_mul_ps(Vec3, Fac4); + __m128 Sub01 = _mm_sub_ps(Mul03, Mul04); + __m128 Add01 = _mm_add_ps(Sub01, Mul05); + __m128 Inv1 = _mm_mul_ps(SignA, Add01); + + // col2 + // + (Vec0[0] * Fac1[0] - Vec1[0] * Fac3[0] + Vec3[0] * Fac5[0]), + // - (Vec0[0] * Fac1[1] - Vec1[1] * Fac3[1] + Vec3[1] * Fac5[1]), + // + (Vec0[0] * Fac1[2] - Vec1[2] * Fac3[2] + Vec3[2] * Fac5[2]), + // - (Vec0[0] * Fac1[3] - Vec1[3] * Fac3[3] + Vec3[3] * Fac5[3]), + __m128 Mul06 = _mm_mul_ps(Vec0, Fac1); + __m128 Mul07 = _mm_mul_ps(Vec1, Fac3); + __m128 Mul08 = _mm_mul_ps(Vec3, Fac5); + __m128 Sub02 = _mm_sub_ps(Mul06, Mul07); + __m128 Add02 = _mm_add_ps(Sub02, Mul08); + __m128 Inv2 = _mm_mul_ps(SignB, Add02); + + // col3 + // - (Vec1[0] * Fac2[0] - Vec1[0] * Fac4[0] + Vec2[0] * Fac5[0]), + // + (Vec1[0] * Fac2[1] - Vec1[1] * Fac4[1] + Vec2[1] * Fac5[1]), + // - (Vec1[0] * Fac2[2] - Vec1[2] * Fac4[2] + Vec2[2] * Fac5[2]), + // + (Vec1[0] * Fac2[3] - Vec1[3] * Fac4[3] + Vec2[3] * Fac5[3])); + __m128 Mul09 = _mm_mul_ps(Vec0, Fac2); + __m128 Mul10 = _mm_mul_ps(Vec1, Fac4); + __m128 Mul11 = _mm_mul_ps(Vec2, Fac5); + __m128 Sub03 = _mm_sub_ps(Mul09, Mul10); + __m128 Add03 = _mm_add_ps(Sub03, Mul11); + __m128 Inv3 = _mm_mul_ps(SignA, Add03); + + __m128 Row0 = _mm_shuffle_ps(Inv0, Inv1, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row1 = _mm_shuffle_ps(Inv2, Inv3, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row2 = _mm_shuffle_ps(Row0, Row1, _MM_SHUFFLE(2, 0, 2, 0)); + + // valType Determinant = m[0][0] * Inverse[0][0] + // + m[0][1] * Inverse[1][0] + // + m[0][2] * Inverse[2][0] + // + m[0][3] * Inverse[3][0]; + __m128 Det0 = glm_vec4_dot(in[0], Row2); + __m128 Rcp0 = _mm_div_ps(_mm_set1_ps(1.0f), Det0); + //__m128 Rcp0 = _mm_rcp_ps(Det0); + + // Inverse /= Determinant; + out[0] = _mm_mul_ps(Inv0, Rcp0); + out[1] = _mm_mul_ps(Inv1, Rcp0); + out[2] = _mm_mul_ps(Inv2, Rcp0); + out[3] = _mm_mul_ps(Inv3, Rcp0); +} + +GLM_FUNC_QUALIFIER void glm_mat4_inverse_lowp(glm_vec4 const in[4], glm_vec4 out[4]) +{ + __m128 Fac0; + { + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + // valType SubFactor13 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac0 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac1; + { + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + // valType SubFactor14 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac1 = _mm_sub_ps(Mul00, Mul01); + } + + + __m128 Fac2; + { + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + // valType SubFactor15 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac2 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac3; + { + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + // valType SubFactor16 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac3 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac4; + { + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + // valType SubFactor17 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac4 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac5; + { + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor12 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + // valType SubFactor18 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac5 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 SignA = _mm_set_ps( 1.0f,-1.0f, 1.0f,-1.0f); + __m128 SignB = _mm_set_ps(-1.0f, 1.0f,-1.0f, 1.0f); + + // m[1][0] + // m[0][0] + // m[0][0] + // m[0][0] + __m128 Temp0 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Vec0 = _mm_shuffle_ps(Temp0, Temp0, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][1] + // m[0][1] + // m[0][1] + // m[0][1] + __m128 Temp1 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Vec1 = _mm_shuffle_ps(Temp1, Temp1, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][2] + // m[0][2] + // m[0][2] + // m[0][2] + __m128 Temp2 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Vec2 = _mm_shuffle_ps(Temp2, Temp2, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][3] + // m[0][3] + // m[0][3] + // m[0][3] + __m128 Temp3 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Vec3 = _mm_shuffle_ps(Temp3, Temp3, _MM_SHUFFLE(2, 2, 2, 0)); + + // col0 + // + (Vec1[0] * Fac0[0] - Vec2[0] * Fac1[0] + Vec3[0] * Fac2[0]), + // - (Vec1[1] * Fac0[1] - Vec2[1] * Fac1[1] + Vec3[1] * Fac2[1]), + // + (Vec1[2] * Fac0[2] - Vec2[2] * Fac1[2] + Vec3[2] * Fac2[2]), + // - (Vec1[3] * Fac0[3] - Vec2[3] * Fac1[3] + Vec3[3] * Fac2[3]), + __m128 Mul00 = _mm_mul_ps(Vec1, Fac0); + __m128 Mul01 = _mm_mul_ps(Vec2, Fac1); + __m128 Mul02 = _mm_mul_ps(Vec3, Fac2); + __m128 Sub00 = _mm_sub_ps(Mul00, Mul01); + __m128 Add00 = _mm_add_ps(Sub00, Mul02); + __m128 Inv0 = _mm_mul_ps(SignB, Add00); + + // col1 + // - (Vec0[0] * Fac0[0] - Vec2[0] * Fac3[0] + Vec3[0] * Fac4[0]), + // + (Vec0[0] * Fac0[1] - Vec2[1] * Fac3[1] + Vec3[1] * Fac4[1]), + // - (Vec0[0] * Fac0[2] - Vec2[2] * Fac3[2] + Vec3[2] * Fac4[2]), + // + (Vec0[0] * Fac0[3] - Vec2[3] * Fac3[3] + Vec3[3] * Fac4[3]), + __m128 Mul03 = _mm_mul_ps(Vec0, Fac0); + __m128 Mul04 = _mm_mul_ps(Vec2, Fac3); + __m128 Mul05 = _mm_mul_ps(Vec3, Fac4); + __m128 Sub01 = _mm_sub_ps(Mul03, Mul04); + __m128 Add01 = _mm_add_ps(Sub01, Mul05); + __m128 Inv1 = _mm_mul_ps(SignA, Add01); + + // col2 + // + (Vec0[0] * Fac1[0] - Vec1[0] * Fac3[0] + Vec3[0] * Fac5[0]), + // - (Vec0[0] * Fac1[1] - Vec1[1] * Fac3[1] + Vec3[1] * Fac5[1]), + // + (Vec0[0] * Fac1[2] - Vec1[2] * Fac3[2] + Vec3[2] * Fac5[2]), + // - (Vec0[0] * Fac1[3] - Vec1[3] * Fac3[3] + Vec3[3] * Fac5[3]), + __m128 Mul06 = _mm_mul_ps(Vec0, Fac1); + __m128 Mul07 = _mm_mul_ps(Vec1, Fac3); + __m128 Mul08 = _mm_mul_ps(Vec3, Fac5); + __m128 Sub02 = _mm_sub_ps(Mul06, Mul07); + __m128 Add02 = _mm_add_ps(Sub02, Mul08); + __m128 Inv2 = _mm_mul_ps(SignB, Add02); + + // col3 + // - (Vec1[0] * Fac2[0] - Vec1[0] * Fac4[0] + Vec2[0] * Fac5[0]), + // + (Vec1[0] * Fac2[1] - Vec1[1] * Fac4[1] + Vec2[1] * Fac5[1]), + // - (Vec1[0] * Fac2[2] - Vec1[2] * Fac4[2] + Vec2[2] * Fac5[2]), + // + (Vec1[0] * Fac2[3] - Vec1[3] * Fac4[3] + Vec2[3] * Fac5[3])); + __m128 Mul09 = _mm_mul_ps(Vec0, Fac2); + __m128 Mul10 = _mm_mul_ps(Vec1, Fac4); + __m128 Mul11 = _mm_mul_ps(Vec2, Fac5); + __m128 Sub03 = _mm_sub_ps(Mul09, Mul10); + __m128 Add03 = _mm_add_ps(Sub03, Mul11); + __m128 Inv3 = _mm_mul_ps(SignA, Add03); + + __m128 Row0 = _mm_shuffle_ps(Inv0, Inv1, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row1 = _mm_shuffle_ps(Inv2, Inv3, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row2 = _mm_shuffle_ps(Row0, Row1, _MM_SHUFFLE(2, 0, 2, 0)); + + // valType Determinant = m[0][0] * Inverse[0][0] + // + m[0][1] * Inverse[1][0] + // + m[0][2] * Inverse[2][0] + // + m[0][3] * Inverse[3][0]; + __m128 Det0 = glm_vec4_dot(in[0], Row2); + __m128 Rcp0 = _mm_rcp_ps(Det0); + //__m128 Rcp0 = _mm_div_ps(one, Det0); + // Inverse /= Determinant; + out[0] = _mm_mul_ps(Inv0, Rcp0); + out[1] = _mm_mul_ps(Inv1, Rcp0); + out[2] = _mm_mul_ps(Inv2, Rcp0); + out[3] = _mm_mul_ps(Inv3, Rcp0); +} +/* +GLM_FUNC_QUALIFIER void glm_mat4_rotate(__m128 const in[4], float Angle, float const v[3], __m128 out[4]) +{ + float a = glm::radians(Angle); + float c = cos(a); + float s = sin(a); + + glm::vec4 AxisA(v[0], v[1], v[2], float(0)); + __m128 AxisB = _mm_set_ps(AxisA.w, AxisA.z, AxisA.y, AxisA.x); + __m128 AxisC = detail::sse_nrm_ps(AxisB); + + __m128 Cos0 = _mm_set_ss(c); + __m128 CosA = _mm_shuffle_ps(Cos0, Cos0, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Sin0 = _mm_set_ss(s); + __m128 SinA = _mm_shuffle_ps(Sin0, Sin0, _MM_SHUFFLE(0, 0, 0, 0)); + + // vec<3, T, Q> temp = (valType(1) - c) * axis; + __m128 Temp0 = _mm_sub_ps(one, CosA); + __m128 Temp1 = _mm_mul_ps(Temp0, AxisC); + + //Rotate[0][0] = c + temp[0] * axis[0]; + //Rotate[0][1] = 0 + temp[0] * axis[1] + s * axis[2]; + //Rotate[0][2] = 0 + temp[0] * axis[2] - s * axis[1]; + __m128 Axis0 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 TmpA0 = _mm_mul_ps(Axis0, AxisC); + __m128 CosA0 = _mm_shuffle_ps(Cos0, Cos0, _MM_SHUFFLE(1, 1, 1, 0)); + __m128 TmpA1 = _mm_add_ps(CosA0, TmpA0); + __m128 SinA0 = SinA;//_mm_set_ps(0.0f, s, -s, 0.0f); + __m128 TmpA2 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(3, 1, 2, 3)); + __m128 TmpA3 = _mm_mul_ps(SinA0, TmpA2); + __m128 TmpA4 = _mm_add_ps(TmpA1, TmpA3); + + //Rotate[1][0] = 0 + temp[1] * axis[0] - s * axis[2]; + //Rotate[1][1] = c + temp[1] * axis[1]; + //Rotate[1][2] = 0 + temp[1] * axis[2] + s * axis[0]; + __m128 Axis1 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 TmpB0 = _mm_mul_ps(Axis1, AxisC); + __m128 CosA1 = _mm_shuffle_ps(Cos0, Cos0, _MM_SHUFFLE(1, 1, 0, 1)); + __m128 TmpB1 = _mm_add_ps(CosA1, TmpB0); + __m128 SinB0 = SinA;//_mm_set_ps(-s, 0.0f, s, 0.0f); + __m128 TmpB2 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(3, 0, 3, 2)); + __m128 TmpB3 = _mm_mul_ps(SinA0, TmpB2); + __m128 TmpB4 = _mm_add_ps(TmpB1, TmpB3); + + //Rotate[2][0] = 0 + temp[2] * axis[0] + s * axis[1]; + //Rotate[2][1] = 0 + temp[2] * axis[1] - s * axis[0]; + //Rotate[2][2] = c + temp[2] * axis[2]; + __m128 Axis2 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 TmpC0 = _mm_mul_ps(Axis2, AxisC); + __m128 CosA2 = _mm_shuffle_ps(Cos0, Cos0, _MM_SHUFFLE(1, 0, 1, 1)); + __m128 TmpC1 = _mm_add_ps(CosA2, TmpC0); + __m128 SinC0 = SinA;//_mm_set_ps(s, -s, 0.0f, 0.0f); + __m128 TmpC2 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(3, 3, 0, 1)); + __m128 TmpC3 = _mm_mul_ps(SinA0, TmpC2); + __m128 TmpC4 = _mm_add_ps(TmpC1, TmpC3); + + __m128 Result[4]; + Result[0] = TmpA4; + Result[1] = TmpB4; + Result[2] = TmpC4; + Result[3] = _mm_set_ps(1, 0, 0, 0); + + //mat<4, 4, valType> Result; + //Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2]; + //Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2]; + //Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2]; + //Result[3] = m[3]; + //return Result; + sse_mul_ps(in, Result, out); +} +*/ +GLM_FUNC_QUALIFIER void glm_mat4_outerProduct(__m128 const& c, __m128 const& r, __m128 out[4]) +{ + out[0] = _mm_mul_ps(c, _mm_shuffle_ps(r, r, _MM_SHUFFLE(0, 0, 0, 0))); + out[1] = _mm_mul_ps(c, _mm_shuffle_ps(r, r, _MM_SHUFFLE(1, 1, 1, 1))); + out[2] = _mm_mul_ps(c, _mm_shuffle_ps(r, r, _MM_SHUFFLE(2, 2, 2, 2))); + out[3] = _mm_mul_ps(c, _mm_shuffle_ps(r, r, _MM_SHUFFLE(3, 3, 3, 3))); +} + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/neon.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/neon.h new file mode 100644 index 0000000..f85947f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/neon.h @@ -0,0 +1,155 @@ +/// @ref simd_neon +/// @file glm/simd/neon.h + +#pragma once + +#if GLM_ARCH & GLM_ARCH_NEON_BIT +#include + +namespace glm { + namespace neon { + static inline float32x4_t dupq_lane(float32x4_t vsrc, int lane) { + switch(lane) { +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + case 0: return vdupq_laneq_f32(vsrc, 0); + case 1: return vdupq_laneq_f32(vsrc, 1); + case 2: return vdupq_laneq_f32(vsrc, 2); + case 3: return vdupq_laneq_f32(vsrc, 3); +#else + case 0: return vdupq_n_f32(vgetq_lane_f32(vsrc, 0)); + case 1: return vdupq_n_f32(vgetq_lane_f32(vsrc, 1)); + case 2: return vdupq_n_f32(vgetq_lane_f32(vsrc, 2)); + case 3: return vdupq_n_f32(vgetq_lane_f32(vsrc, 3)); +#endif + } + assert(!"Unreachable code executed!"); + return vdupq_n_f32(0.0f); + } + + static inline float32x2_t dup_lane(float32x4_t vsrc, int lane) { + switch(lane) { +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + case 0: return vdup_laneq_f32(vsrc, 0); + case 1: return vdup_laneq_f32(vsrc, 1); + case 2: return vdup_laneq_f32(vsrc, 2); + case 3: return vdup_laneq_f32(vsrc, 3); +#else + case 0: return vdup_n_f32(vgetq_lane_f32(vsrc, 0)); + case 1: return vdup_n_f32(vgetq_lane_f32(vsrc, 1)); + case 2: return vdup_n_f32(vgetq_lane_f32(vsrc, 2)); + case 3: return vdup_n_f32(vgetq_lane_f32(vsrc, 3)); +#endif + } + assert(!"Unreachable code executed!"); + return vdup_n_f32(0.0f); + } + + static inline float32x4_t copy_lane(float32x4_t vdst, int dlane, float32x4_t vsrc, int slane) { +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + switch(dlane) { + case 0: + switch(slane) { + case 0: return vcopyq_laneq_f32(vdst, 0, vsrc, 0); + case 1: return vcopyq_laneq_f32(vdst, 0, vsrc, 1); + case 2: return vcopyq_laneq_f32(vdst, 0, vsrc, 2); + case 3: return vcopyq_laneq_f32(vdst, 0, vsrc, 3); + } + assert(!"Unreachable code executed!"); + case 1: + switch(slane) { + case 0: return vcopyq_laneq_f32(vdst, 1, vsrc, 0); + case 1: return vcopyq_laneq_f32(vdst, 1, vsrc, 1); + case 2: return vcopyq_laneq_f32(vdst, 1, vsrc, 2); + case 3: return vcopyq_laneq_f32(vdst, 1, vsrc, 3); + } + assert(!"Unreachable code executed!"); + case 2: + switch(slane) { + case 0: return vcopyq_laneq_f32(vdst, 2, vsrc, 0); + case 1: return vcopyq_laneq_f32(vdst, 2, vsrc, 1); + case 2: return vcopyq_laneq_f32(vdst, 2, vsrc, 2); + case 3: return vcopyq_laneq_f32(vdst, 2, vsrc, 3); + } + assert(!"Unreachable code executed!"); + case 3: + switch(slane) { + case 0: return vcopyq_laneq_f32(vdst, 3, vsrc, 0); + case 1: return vcopyq_laneq_f32(vdst, 3, vsrc, 1); + case 2: return vcopyq_laneq_f32(vdst, 3, vsrc, 2); + case 3: return vcopyq_laneq_f32(vdst, 3, vsrc, 3); + } + assert(!"Unreachable code executed!"); + } +#else + + float l; + switch(slane) { + case 0: l = vgetq_lane_f32(vsrc, 0); break; + case 1: l = vgetq_lane_f32(vsrc, 1); break; + case 2: l = vgetq_lane_f32(vsrc, 2); break; + case 3: l = vgetq_lane_f32(vsrc, 3); break; + default: + assert(!"Unreachable code executed!"); + } + switch(dlane) { + case 0: return vsetq_lane_f32(l, vdst, 0); + case 1: return vsetq_lane_f32(l, vdst, 1); + case 2: return vsetq_lane_f32(l, vdst, 2); + case 3: return vsetq_lane_f32(l, vdst, 3); + } +#endif + assert(!"Unreachable code executed!"); + return vdupq_n_f32(0.0f); + } + + static inline float32x4_t mul_lane(float32x4_t v, float32x4_t vlane, int lane) { +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + switch(lane) { + case 0: return vmulq_laneq_f32(v, vlane, 0); break; + case 1: return vmulq_laneq_f32(v, vlane, 1); break; + case 2: return vmulq_laneq_f32(v, vlane, 2); break; + case 3: return vmulq_laneq_f32(v, vlane, 3); break; + default: + assert(!"Unreachable code executed!"); + } + assert(!"Unreachable code executed!"); + return vdupq_n_f32(0.0f); +#else + return vmulq_f32(v, dupq_lane(vlane, lane)); +#endif + } + + static inline float32x4_t madd_lane(float32x4_t acc, float32x4_t v, float32x4_t vlane, int lane) { +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT +#ifdef GLM_CONFIG_FORCE_FMA +# define FMADD_LANE(acc, x, y, L) do { asm volatile ("fmla %0.4s, %1.4s, %2.4s" : "+w"(acc) : "w"(x), "w"(dup_lane(y, L))); } while(0) +#else +# define FMADD_LANE(acc, x, y, L) do { acc = vmlaq_laneq_f32(acc, x, y, L); } while(0) +#endif + + switch(lane) { + case 0: + FMADD_LANE(acc, v, vlane, 0); + return acc; + case 1: + FMADD_LANE(acc, v, vlane, 1); + return acc; + case 2: + FMADD_LANE(acc, v, vlane, 2); + return acc; + case 3: + FMADD_LANE(acc, v, vlane, 3); + return acc; + default: + assert(!"Unreachable code executed!"); + } + assert(!"Unreachable code executed!"); + return vdupq_n_f32(0.0f); +# undef FMADD_LANE +#else + return vaddq_f32(acc, vmulq_f32(v, dupq_lane(vlane, lane))); +#endif + } + } //namespace neon +} // namespace glm +#endif // GLM_ARCH & GLM_ARCH_NEON_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/packing.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/packing.h new file mode 100644 index 0000000..609163e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/packing.h @@ -0,0 +1,8 @@ +/// @ref simd +/// @file glm/simd/packing.h + +#pragma once + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/platform.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/platform.h new file mode 100644 index 0000000..a318b09 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/platform.h @@ -0,0 +1,469 @@ +#pragma once + +/////////////////////////////////////////////////////////////////////////////////// +// Platform + +#define GLM_PLATFORM_UNKNOWN 0x00000000 +#define GLM_PLATFORM_WINDOWS 0x00010000 +#define GLM_PLATFORM_LINUX 0x00020000 +#define GLM_PLATFORM_APPLE 0x00040000 +//#define GLM_PLATFORM_IOS 0x00080000 +#define GLM_PLATFORM_ANDROID 0x00100000 +#define GLM_PLATFORM_CHROME_NACL 0x00200000 +#define GLM_PLATFORM_UNIX 0x00400000 +#define GLM_PLATFORM_QNXNTO 0x00800000 +#define GLM_PLATFORM_WINCE 0x01000000 +#define GLM_PLATFORM_CYGWIN 0x02000000 + +#ifdef GLM_FORCE_PLATFORM_UNKNOWN +# define GLM_PLATFORM GLM_PLATFORM_UNKNOWN +#elif defined(__CYGWIN__) +# define GLM_PLATFORM GLM_PLATFORM_CYGWIN +#elif defined(__QNXNTO__) +# define GLM_PLATFORM GLM_PLATFORM_QNXNTO +#elif defined(__APPLE__) +# define GLM_PLATFORM GLM_PLATFORM_APPLE +#elif defined(WINCE) +# define GLM_PLATFORM GLM_PLATFORM_WINCE +#elif defined(_WIN32) +# define GLM_PLATFORM GLM_PLATFORM_WINDOWS +#elif defined(__native_client__) +# define GLM_PLATFORM GLM_PLATFORM_CHROME_NACL +#elif defined(__ANDROID__) +# define GLM_PLATFORM GLM_PLATFORM_ANDROID +#elif defined(__linux) +# define GLM_PLATFORM GLM_PLATFORM_LINUX +#elif defined(__unix) +# define GLM_PLATFORM GLM_PLATFORM_UNIX +#else +# define GLM_PLATFORM GLM_PLATFORM_UNKNOWN +#endif// + +/////////////////////////////////////////////////////////////////////////////////// +// Compiler + +#define GLM_COMPILER_UNKNOWN 0x00000000 + +// Intel +#define GLM_COMPILER_INTEL 0x00100000 +#define GLM_COMPILER_INTEL14 0x00100040 +#define GLM_COMPILER_INTEL15 0x00100050 +#define GLM_COMPILER_INTEL16 0x00100060 +#define GLM_COMPILER_INTEL17 0x00100070 +#define GLM_COMPILER_INTEL18 0x00100080 +#define GLM_COMPILER_INTEL19 0x00100090 +#define GLM_COMPILER_INTEL21 0x001000A0 + +// Visual C++ defines +#define GLM_COMPILER_VC 0x01000000 +#define GLM_COMPILER_VC12 0x01000001 // Visual Studio 2013 +#define GLM_COMPILER_VC14 0x01000002 // Visual Studio 2015 +#define GLM_COMPILER_VC15 0x01000003 // Visual Studio 2017 +#define GLM_COMPILER_VC15_3 0x01000004 +#define GLM_COMPILER_VC15_5 0x01000005 +#define GLM_COMPILER_VC15_6 0x01000006 +#define GLM_COMPILER_VC15_7 0x01000007 +#define GLM_COMPILER_VC15_8 0x01000008 +#define GLM_COMPILER_VC15_9 0x01000009 +#define GLM_COMPILER_VC16 0x0100000A // Visual Studio 2019 +#define GLM_COMPILER_VC17 0x0100000B // Visual Studio 2022 + +// GCC defines +#define GLM_COMPILER_GCC 0x02000000 +#define GLM_COMPILER_GCC46 0x020000D0 +#define GLM_COMPILER_GCC47 0x020000E0 +#define GLM_COMPILER_GCC48 0x020000F0 +#define GLM_COMPILER_GCC49 0x02000100 +#define GLM_COMPILER_GCC5 0x02000200 +#define GLM_COMPILER_GCC6 0x02000300 +#define GLM_COMPILER_GCC61 0x02000800 +#define GLM_COMPILER_GCC7 0x02000400 +#define GLM_COMPILER_GCC8 0x02000500 +#define GLM_COMPILER_GCC9 0x02000600 +#define GLM_COMPILER_GCC10 0x02000700 +#define GLM_COMPILER_GCC11 0x02000800 +#define GLM_COMPILER_GCC12 0x02000900 +#define GLM_COMPILER_GCC13 0x02000A00 +#define GLM_COMPILER_GCC14 0x02000B00 + +// CUDA +#define GLM_COMPILER_CUDA 0x10000000 +#define GLM_COMPILER_CUDA75 0x10000001 +#define GLM_COMPILER_CUDA80 0x10000002 +#define GLM_COMPILER_CUDA90 0x10000004 +#define GLM_COMPILER_CUDA_RTC 0x10000100 + +// Clang +#define GLM_COMPILER_CLANG 0x20000000 +#define GLM_COMPILER_CLANG34 0x20000050 +#define GLM_COMPILER_CLANG35 0x20000060 +#define GLM_COMPILER_CLANG36 0x20000070 +#define GLM_COMPILER_CLANG37 0x20000080 +#define GLM_COMPILER_CLANG38 0x20000090 +#define GLM_COMPILER_CLANG39 0x200000A0 +#define GLM_COMPILER_CLANG4 0x200000B0 +#define GLM_COMPILER_CLANG5 0x200000C0 +#define GLM_COMPILER_CLANG6 0x200000D0 +#define GLM_COMPILER_CLANG7 0x200000E0 +#define GLM_COMPILER_CLANG8 0x200000F0 +#define GLM_COMPILER_CLANG9 0x20000100 +#define GLM_COMPILER_CLANG10 0x20000200 +#define GLM_COMPILER_CLANG11 0x20000300 +#define GLM_COMPILER_CLANG12 0x20000400 +#define GLM_COMPILER_CLANG13 0x20000500 +#define GLM_COMPILER_CLANG14 0x20000600 +#define GLM_COMPILER_CLANG15 0x20000700 +#define GLM_COMPILER_CLANG16 0x20000800 +#define GLM_COMPILER_CLANG17 0x20000900 +#define GLM_COMPILER_CLANG18 0x20000A00 +#define GLM_COMPILER_CLANG19 0x20000B00 + +// HIP +#define GLM_COMPILER_HIP 0x40000000 + +// Build model +#define GLM_MODEL_32 0x00000010 +#define GLM_MODEL_64 0x00000020 + +// Force generic C++ compiler +#ifdef GLM_FORCE_COMPILER_UNKNOWN +# define GLM_COMPILER GLM_COMPILER_UNKNOWN + +#elif defined(__INTEL_COMPILER) +# if __INTEL_COMPILER >= 2021 +# define GLM_COMPILER GLM_COMPILER_INTEL21 +# elif __INTEL_COMPILER >= 1900 +# define GLM_COMPILER GLM_COMPILER_INTEL19 +# elif __INTEL_COMPILER >= 1800 +# define GLM_COMPILER GLM_COMPILER_INTEL18 +# elif __INTEL_COMPILER >= 1700 +# define GLM_COMPILER GLM_COMPILER_INTEL17 +# elif __INTEL_COMPILER >= 1600 +# define GLM_COMPILER GLM_COMPILER_INTEL16 +# elif __INTEL_COMPILER >= 1500 +# define GLM_COMPILER GLM_COMPILER_INTEL15 +# elif __INTEL_COMPILER >= 1400 +# define GLM_COMPILER GLM_COMPILER_INTEL14 +# elif __INTEL_COMPILER < 1400 +# error "GLM requires ICC 2013 SP1 or newer" +# endif + +// CUDA +#elif defined(__CUDACC__) +# if !defined(CUDA_VERSION) && !defined(GLM_FORCE_CUDA) +# include // make sure version is defined since nvcc does not define it itself! +# endif +# if defined(__CUDACC_RTC__) +# define GLM_COMPILER GLM_COMPILER_CUDA_RTC +# elif CUDA_VERSION >= 8000 +# define GLM_COMPILER GLM_COMPILER_CUDA80 +# elif CUDA_VERSION >= 7500 +# define GLM_COMPILER GLM_COMPILER_CUDA75 +# elif CUDA_VERSION >= 7000 +# define GLM_COMPILER GLM_COMPILER_CUDA70 +# elif CUDA_VERSION < 7000 +# error "GLM requires CUDA 7.0 or higher" +# endif + +// HIP +#elif defined(__HIP__) +# define GLM_COMPILER GLM_COMPILER_HIP + +// Clang +#elif defined(__clang__) +# if defined(__apple_build_version__) +# if (__clang_major__ < 6) +# error "GLM requires Clang 3.4 / Apple Clang 6.0 or higher" +# elif __clang_major__ == 6 && __clang_minor__ == 0 +# define GLM_COMPILER GLM_COMPILER_CLANG35 +# elif __clang_major__ == 6 && __clang_minor__ >= 1 +# define GLM_COMPILER GLM_COMPILER_CLANG36 +# elif __clang_major__ >= 7 +# define GLM_COMPILER GLM_COMPILER_CLANG37 +# endif +# else +# if ((__clang_major__ == 3) && (__clang_minor__ < 4)) || (__clang_major__ < 3) +# error "GLM requires Clang 3.4 or higher" +# elif __clang_major__ == 3 && __clang_minor__ == 4 +# define GLM_COMPILER GLM_COMPILER_CLANG34 +# elif __clang_major__ == 3 && __clang_minor__ == 5 +# define GLM_COMPILER GLM_COMPILER_CLANG35 +# elif __clang_major__ == 3 && __clang_minor__ == 6 +# define GLM_COMPILER GLM_COMPILER_CLANG36 +# elif __clang_major__ == 3 && __clang_minor__ == 7 +# define GLM_COMPILER GLM_COMPILER_CLANG37 +# elif __clang_major__ == 3 && __clang_minor__ == 8 +# define GLM_COMPILER GLM_COMPILER_CLANG38 +# elif __clang_major__ == 3 && __clang_minor__ >= 9 +# define GLM_COMPILER GLM_COMPILER_CLANG39 +# elif __clang_major__ == 4 && __clang_minor__ == 0 +# define GLM_COMPILER GLM_COMPILER_CLANG4 +# elif __clang_major__ == 5 +# define GLM_COMPILER GLM_COMPILER_CLANG5 +# elif __clang_major__ == 6 +# define GLM_COMPILER GLM_COMPILER_CLANG6 +# elif __clang_major__ == 7 +# define GLM_COMPILER GLM_COMPILER_CLANG7 +# elif __clang_major__ == 8 +# define GLM_COMPILER GLM_COMPILER_CLANG8 +# elif __clang_major__ == 9 +# define GLM_COMPILER GLM_COMPILER_CLANG9 +# elif __clang_major__ == 10 +# define GLM_COMPILER GLM_COMPILER_CLANG10 +# elif __clang_major__ == 11 +# define GLM_COMPILER GLM_COMPILER_CLANG11 +# elif __clang_major__ == 12 +# define GLM_COMPILER GLM_COMPILER_CLANG12 +# elif __clang_major__ == 13 +# define GLM_COMPILER GLM_COMPILER_CLANG13 +# elif __clang_major__ == 14 +# define GLM_COMPILER GLM_COMPILER_CLANG14 +# elif __clang_major__ == 15 +# define GLM_COMPILER GLM_COMPILER_CLANG15 +# elif __clang_major__ == 16 +# define GLM_COMPILER GLM_COMPILER_CLANG16 +# elif __clang_major__ == 17 +# define GLM_COMPILER GLM_COMPILER_CLANG17 +# elif __clang_major__ == 18 +# define GLM_COMPILER GLM_COMPILER_CLANG18 +# elif __clang_major__ >= 19 +# define GLM_COMPILER GLM_COMPILER_CLANG19 +# endif +# endif + +// Visual C++ +#elif defined(_MSC_VER) +# if _MSC_VER >= 1930 +# define GLM_COMPILER GLM_COMPILER_VC17 +# elif _MSC_VER >= 1920 +# define GLM_COMPILER GLM_COMPILER_VC16 +# elif _MSC_VER >= 1916 +# define GLM_COMPILER GLM_COMPILER_VC15_9 +# elif _MSC_VER >= 1915 +# define GLM_COMPILER GLM_COMPILER_VC15_8 +# elif _MSC_VER >= 1914 +# define GLM_COMPILER GLM_COMPILER_VC15_7 +# elif _MSC_VER >= 1913 +# define GLM_COMPILER GLM_COMPILER_VC15_6 +# elif _MSC_VER >= 1912 +# define GLM_COMPILER GLM_COMPILER_VC15_5 +# elif _MSC_VER >= 1911 +# define GLM_COMPILER GLM_COMPILER_VC15_3 +# elif _MSC_VER >= 1910 +# define GLM_COMPILER GLM_COMPILER_VC15 +# elif _MSC_VER >= 1900 +# define GLM_COMPILER GLM_COMPILER_VC14 +# elif _MSC_VER >= 1800 +# define GLM_COMPILER GLM_COMPILER_VC12 +# elif _MSC_VER < 1800 +# error "GLM requires Visual C++ 12 - 2013 or higher" +# endif//_MSC_VER + +// G++ +#elif defined(__GNUC__) || defined(__MINGW32__) +# if __GNUC__ >= 14 +# define GLM_COMPILER GLM_COMPILER_GCC14 +# elif __GNUC__ >= 13 +# define GLM_COMPILER GLM_COMPILER_GCC13 +# elif __GNUC__ >= 12 +# define GLM_COMPILER GLM_COMPILER_GCC12 +# elif __GNUC__ >= 11 +# define GLM_COMPILER GLM_COMPILER_GCC11 +# elif __GNUC__ >= 10 +# define GLM_COMPILER GLM_COMPILER_GCC10 +# elif __GNUC__ >= 9 +# define GLM_COMPILER GLM_COMPILER_GCC9 +# elif __GNUC__ >= 8 +# define GLM_COMPILER GLM_COMPILER_GCC8 +# elif __GNUC__ >= 7 +# define GLM_COMPILER GLM_COMPILER_GCC7 +# elif __GNUC__ >= 6 +# define GLM_COMPILER GLM_COMPILER_GCC6 +# elif __GNUC__ >= 5 +# define GLM_COMPILER GLM_COMPILER_GCC5 +# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9 +# define GLM_COMPILER GLM_COMPILER_GCC49 +# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 8 +# define GLM_COMPILER GLM_COMPILER_GCC48 +# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 7 +# define GLM_COMPILER GLM_COMPILER_GCC47 +# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 6 +# define GLM_COMPILER GLM_COMPILER_GCC46 +# elif ((__GNUC__ == 4) && (__GNUC_MINOR__ < 6)) || (__GNUC__ < 4) +# error "GLM requires GCC 4.6 or higher" +# endif + +#else +# define GLM_COMPILER GLM_COMPILER_UNKNOWN +#endif + +#ifndef GLM_COMPILER +# error "GLM_COMPILER undefined, your compiler may not be supported by GLM. Add #define GLM_COMPILER 0 to ignore this message." +#endif//GLM_COMPILER + +/////////////////////////////////////////////////////////////////////////////////// +// Instruction sets + +// User defines: GLM_FORCE_PURE GLM_FORCE_INTRINSICS GLM_FORCE_SSE2 GLM_FORCE_SSE3 GLM_FORCE_AVX GLM_FORCE_AVX2 GLM_FORCE_AVX2 + +#define GLM_ARCH_MIPS_BIT (0x10000000) +#define GLM_ARCH_PPC_BIT (0x20000000) +#define GLM_ARCH_ARM_BIT (0x40000000) +#define GLM_ARCH_ARMV8_BIT (0x01000000) +#define GLM_ARCH_X86_BIT (0x80000000) + +#define GLM_ARCH_SIMD_BIT (0x00001000) + +#define GLM_ARCH_NEON_BIT (0x00000001) +#define GLM_ARCH_SSE_BIT (0x00000002) +#define GLM_ARCH_SSE2_BIT (0x00000004) +#define GLM_ARCH_SSE3_BIT (0x00000008) +#define GLM_ARCH_SSSE3_BIT (0x00000010) +#define GLM_ARCH_SSE41_BIT (0x00000020) +#define GLM_ARCH_SSE42_BIT (0x00000040) +#define GLM_ARCH_AVX_BIT (0x00000080) +#define GLM_ARCH_AVX2_BIT (0x00000100) + +#define GLM_ARCH_UNKNOWN (0) +#define GLM_ARCH_X86 (GLM_ARCH_X86_BIT) +#define GLM_ARCH_SSE (GLM_ARCH_SSE_BIT | GLM_ARCH_SIMD_BIT | GLM_ARCH_X86) +#define GLM_ARCH_SSE2 (GLM_ARCH_SSE2_BIT | GLM_ARCH_SSE) +#define GLM_ARCH_SSE3 (GLM_ARCH_SSE3_BIT | GLM_ARCH_SSE2) +#define GLM_ARCH_SSSE3 (GLM_ARCH_SSSE3_BIT | GLM_ARCH_SSE3) +#define GLM_ARCH_SSE41 (GLM_ARCH_SSE41_BIT | GLM_ARCH_SSSE3) +#define GLM_ARCH_SSE42 (GLM_ARCH_SSE42_BIT | GLM_ARCH_SSE41) +#define GLM_ARCH_AVX (GLM_ARCH_AVX_BIT | GLM_ARCH_SSE42) +#define GLM_ARCH_AVX2 (GLM_ARCH_AVX2_BIT | GLM_ARCH_AVX) +#define GLM_ARCH_ARM (GLM_ARCH_ARM_BIT) +#define GLM_ARCH_ARMV8 (GLM_ARCH_NEON_BIT | GLM_ARCH_SIMD_BIT | GLM_ARCH_ARM | GLM_ARCH_ARMV8_BIT) +#define GLM_ARCH_NEON (GLM_ARCH_NEON_BIT | GLM_ARCH_SIMD_BIT | GLM_ARCH_ARM) +#define GLM_ARCH_MIPS (GLM_ARCH_MIPS_BIT) +#define GLM_ARCH_PPC (GLM_ARCH_PPC_BIT) + +#if defined(GLM_FORCE_ARCH_UNKNOWN) || defined(GLM_FORCE_PURE) +# define GLM_ARCH GLM_ARCH_UNKNOWN +#elif defined(GLM_FORCE_NEON) +# if __ARM_ARCH >= 8 +# define GLM_ARCH (GLM_ARCH_ARMV8) +# else +# define GLM_ARCH (GLM_ARCH_NEON) +# endif +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_AVX2) +# define GLM_ARCH (GLM_ARCH_AVX2) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_AVX) +# define GLM_ARCH (GLM_ARCH_AVX) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_SSE42) +# define GLM_ARCH (GLM_ARCH_SSE42) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_SSE41) +# define GLM_ARCH (GLM_ARCH_SSE41) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_SSSE3) +# define GLM_ARCH (GLM_ARCH_SSSE3) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_SSE3) +# define GLM_ARCH (GLM_ARCH_SSE3) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_SSE2) +# define GLM_ARCH (GLM_ARCH_SSE2) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_SSE) +# define GLM_ARCH (GLM_ARCH_SSE) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_INTRINSICS) && !defined(GLM_FORCE_XYZW_ONLY) +# if defined(__AVX2__) +# define GLM_ARCH (GLM_ARCH_AVX2) +# elif defined(__AVX__) +# define GLM_ARCH (GLM_ARCH_AVX) +# elif defined(__SSE4_2__) +# define GLM_ARCH (GLM_ARCH_SSE42) +# elif defined(__SSE4_1__) +# define GLM_ARCH (GLM_ARCH_SSE41) +# elif defined(__SSSE3__) +# define GLM_ARCH (GLM_ARCH_SSSE3) +# elif defined(__SSE3__) +# define GLM_ARCH (GLM_ARCH_SSE3) +# elif defined(__SSE2__) || defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86_FP) +# define GLM_ARCH (GLM_ARCH_SSE2) +# elif defined(__i386__) +# define GLM_ARCH (GLM_ARCH_X86) +# elif defined(__ARM_ARCH) && (__ARM_ARCH >= 8) +# define GLM_ARCH (GLM_ARCH_ARMV8) +# elif defined(__ARM_NEON) +# define GLM_ARCH (GLM_ARCH_ARM | GLM_ARCH_NEON) +# elif defined(__arm__ ) || defined(_M_ARM) +# define GLM_ARCH (GLM_ARCH_ARM) +# elif defined(__mips__ ) +# define GLM_ARCH (GLM_ARCH_MIPS) +# elif defined(__powerpc__ ) || defined(_M_PPC) +# define GLM_ARCH (GLM_ARCH_PPC) +# else +# define GLM_ARCH (GLM_ARCH_UNKNOWN) +# endif +#else +# if defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86) || defined(__i386__) +# define GLM_ARCH (GLM_ARCH_X86) +# elif defined(__arm__) || defined(_M_ARM) +# define GLM_ARCH (GLM_ARCH_ARM) +# elif defined(__powerpc__) || defined(_M_PPC) +# define GLM_ARCH (GLM_ARCH_PPC) +# elif defined(__mips__) +# define GLM_ARCH (GLM_ARCH_MIPS) +# else +# define GLM_ARCH (GLM_ARCH_UNKNOWN) +# endif +#endif + +#if GLM_ARCH & GLM_ARCH_AVX2_BIT +# include +#elif GLM_ARCH & GLM_ARCH_AVX_BIT +# include +#elif GLM_ARCH & GLM_ARCH_SSE42_BIT +# if GLM_COMPILER & GLM_COMPILER_CLANG +# include +# endif +# include +#elif GLM_ARCH & GLM_ARCH_SSE41_BIT +# include +#elif GLM_ARCH & GLM_ARCH_SSSE3_BIT +# include +#elif GLM_ARCH & GLM_ARCH_SSE3_BIT +# include +#elif GLM_ARCH & GLM_ARCH_SSE2_BIT +# include +#elif GLM_ARCH & GLM_ARCH_NEON_BIT +# include "neon.h" +#endif//GLM_ARCH + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + typedef __m128 glm_f32vec4; + typedef __m128i glm_i32vec4; + typedef __m128i glm_u32vec4; + typedef __m128d glm_f64vec2; + typedef __m128i glm_i64vec2; + typedef __m128i glm_u64vec2; + + typedef glm_f32vec4 glm_vec4; + typedef glm_i32vec4 glm_ivec4; + typedef glm_u32vec4 glm_uvec4; + typedef glm_f64vec2 glm_dvec2; +#endif + +#if GLM_ARCH & GLM_ARCH_AVX_BIT + typedef __m256d glm_f64vec4; + typedef glm_f64vec4 glm_dvec4; +#endif + +#if GLM_ARCH & GLM_ARCH_AVX2_BIT + typedef __m256i glm_i64vec4; + typedef __m256i glm_u64vec4; +#endif + +#if GLM_ARCH & GLM_ARCH_NEON_BIT + typedef float32x4_t glm_f32vec4; + typedef int32x4_t glm_i32vec4; + typedef uint32x4_t glm_u32vec4; +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/trigonometric.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/trigonometric.h new file mode 100644 index 0000000..739b796 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/trigonometric.h @@ -0,0 +1,9 @@ +/// @ref simd +/// @file glm/simd/trigonometric.h + +#pragma once + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/vector_relational.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/vector_relational.h new file mode 100644 index 0000000..f7385e9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/vector_relational.h @@ -0,0 +1,8 @@ +/// @ref simd +/// @file glm/simd/vector_relational.h + +#pragma once + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/trigonometric.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/trigonometric.hpp new file mode 100644 index 0000000..51d49c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/trigonometric.hpp @@ -0,0 +1,210 @@ +/// @ref core +/// @file glm/trigonometric.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions +/// +/// @defgroup core_func_trigonometric Angle and Trigonometry Functions +/// @ingroup core +/// +/// Function parameters specified as angle are assumed to be in units of radians. +/// In no case will any of these functions result in a divide by zero error. If +/// the divisor of a ratio is 0, then results will be undefined. +/// +/// These all operate component-wise. The description is per component. +/// +/// Include to use these core features. +/// +/// @see ext_vector_trigonometric + +#pragma once + +#include "detail/setup.hpp" +#include "detail/qualifier.hpp" + +namespace glm +{ + /// @addtogroup core_func_trigonometric + /// @{ + + /// Converts degrees to radians and returns the result. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL radians man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec radians(vec const& degrees); + + /// Converts radians to degrees and returns the result. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL degrees man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec degrees(vec const& radians); + + /// The standard trigonometric sine function. + /// The values returned by this function will range from [-1, 1]. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL sin man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec sin(vec const& angle); + + /// The standard trigonometric cosine function. + /// The values returned by this function will range from [-1, 1]. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL cos man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec cos(vec const& angle); + + /// The standard trigonometric tangent function. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL tan man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec tan(vec const& angle); + + /// Arc sine. Returns an angle whose sine is x. + /// The range of values returned by this function is [-PI/2, PI/2]. + /// Results are undefined if |x| > 1. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL asin man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec asin(vec const& x); + + /// Arc cosine. Returns an angle whose cosine is x. + /// The range of values returned by this function is [0, PI]. + /// Results are undefined if |x| > 1. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL acos man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec acos(vec const& x); + + /// Arc tangent. Returns an angle whose tangent is y/x. + /// The signs of x and y are used to determine what + /// quadrant the angle is in. The range of values returned + /// by this function is [-PI, PI]. Results are undefined + /// if x and y are both 0. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL atan man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec atan(vec const& y, vec const& x); + + /// Arc tangent. Returns an angle whose tangent is y_over_x. + /// The range of values returned by this function is [-PI/2, PI/2]. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL atan man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec atan(vec const& y_over_x); + + /// Returns the hyperbolic sine function, (exp(x) - exp(-x)) / 2 + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL sinh man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec sinh(vec const& angle); + + /// Returns the hyperbolic cosine function, (exp(x) + exp(-x)) / 2 + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL cosh man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec cosh(vec const& angle); + + /// Returns the hyperbolic tangent function, sinh(angle) / cosh(angle) + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL tanh man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec tanh(vec const& angle); + + /// Arc hyperbolic sine; returns the inverse of sinh. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL asinh man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec asinh(vec const& x); + + /// Arc hyperbolic cosine; returns the non-negative inverse + /// of cosh. Results are undefined if x < 1. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL acosh man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec acosh(vec const& x); + + /// Arc hyperbolic tangent; returns the inverse of tanh. + /// Results are undefined if abs(x) >= 1. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL atanh man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec atanh(vec const& x); + + /// @} +}//namespace glm + +#include "detail/func_trigonometric.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vec2.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vec2.hpp new file mode 100644 index 0000000..cd4e070 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vec2.hpp @@ -0,0 +1,14 @@ +/// @ref core +/// @file glm/vec2.hpp + +#pragma once +#include "./ext/vector_bool2.hpp" +#include "./ext/vector_bool2_precision.hpp" +#include "./ext/vector_float2.hpp" +#include "./ext/vector_float2_precision.hpp" +#include "./ext/vector_double2.hpp" +#include "./ext/vector_double2_precision.hpp" +#include "./ext/vector_int2.hpp" +#include "./ext/vector_int2_sized.hpp" +#include "./ext/vector_uint2.hpp" +#include "./ext/vector_uint2_sized.hpp" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vec3.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vec3.hpp new file mode 100644 index 0000000..f5a927d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vec3.hpp @@ -0,0 +1,14 @@ +/// @ref core +/// @file glm/vec3.hpp + +#pragma once +#include "./ext/vector_bool3.hpp" +#include "./ext/vector_bool3_precision.hpp" +#include "./ext/vector_float3.hpp" +#include "./ext/vector_float3_precision.hpp" +#include "./ext/vector_double3.hpp" +#include "./ext/vector_double3_precision.hpp" +#include "./ext/vector_int3.hpp" +#include "./ext/vector_int3_sized.hpp" +#include "./ext/vector_uint3.hpp" +#include "./ext/vector_uint3_sized.hpp" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vec4.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vec4.hpp new file mode 100644 index 0000000..c6ea9f1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vec4.hpp @@ -0,0 +1,15 @@ +/// @ref core +/// @file glm/vec4.hpp + +#pragma once +#include "./ext/vector_bool4.hpp" +#include "./ext/vector_bool4_precision.hpp" +#include "./ext/vector_float4.hpp" +#include "./ext/vector_float4_precision.hpp" +#include "./ext/vector_double4.hpp" +#include "./ext/vector_double4_precision.hpp" +#include "./ext/vector_int4.hpp" +#include "./ext/vector_int4_sized.hpp" +#include "./ext/vector_uint4.hpp" +#include "./ext/vector_uint4_sized.hpp" + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vector_relational.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vector_relational.hpp new file mode 100644 index 0000000..a0fe17e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vector_relational.hpp @@ -0,0 +1,121 @@ +/// @ref core +/// @file glm/vector_relational.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions +/// +/// @defgroup core_func_vector_relational Vector Relational Functions +/// @ingroup core +/// +/// Relational and equality operators (<, <=, >, >=, ==, !=) are defined to +/// operate on scalars and produce scalar Boolean results. For vector results, +/// use the following built-in functions. +/// +/// In all cases, the sizes of all the input and return vectors for any particular +/// call must match. +/// +/// Include to use these core features. +/// +/// @see ext_vector_relational + +#pragma once + +#include "detail/qualifier.hpp" +#include "detail/setup.hpp" + +namespace glm +{ + /// @addtogroup core_func_vector_relational + /// @{ + + /// Returns the component-wise comparison result of x < y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T A floating-point or integer scalar type. + /// + /// @see GLSL lessThan man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec lessThan(vec const& x, vec const& y); + + /// Returns the component-wise comparison of result x <= y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T A floating-point or integer scalar type. + /// + /// @see GLSL lessThanEqual man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec lessThanEqual(vec const& x, vec const& y); + + /// Returns the component-wise comparison of result x > y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T A floating-point or integer scalar type. + /// + /// @see GLSL greaterThan man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec greaterThan(vec const& x, vec const& y); + + /// Returns the component-wise comparison of result x >= y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T A floating-point or integer scalar type. + /// + /// @see GLSL greaterThanEqual man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec greaterThanEqual(vec const& x, vec const& y); + + /// Returns the component-wise comparison of result x == y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T A floating-point, integer or bool scalar type. + /// + /// @see GLSL equal man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(vec const& x, vec const& y); + + /// Returns the component-wise comparison of result x != y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T A floating-point, integer or bool scalar type. + /// + /// @see GLSL notEqual man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y); + + /// Returns true if any component of x is true. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL any man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR bool any(vec const& v); + + /// Returns true if all components of x are true. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL all man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR bool all(vec const& v); + + /// Returns the component-wise logical complement of x. + /// /!\ Because of language incompatibilities between C++ and GLSL, GLM defines the function not but not_ instead. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL not man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec not_(vec const& v); + + /// @} +}//namespace glm + +#include "detail/func_vector_relational.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/mikktspace/mikktspace.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/mikktspace/mikktspace.h new file mode 100644 index 0000000..52c44a7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/mikktspace/mikktspace.h @@ -0,0 +1,145 @@ +/** \file mikktspace/mikktspace.h + * \ingroup mikktspace + */ +/** + * Copyright (C) 2011 by Morten S. Mikkelsen + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef __MIKKTSPACE_H__ +#define __MIKKTSPACE_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Author: Morten S. Mikkelsen + * Version: 1.0 + * + * The files mikktspace.h and mikktspace.c are designed to be + * stand-alone files and it is important that they are kept this way. + * Not having dependencies on structures/classes/libraries specific + * to the program, in which they are used, allows them to be copied + * and used as is into any tool, program or plugin. + * The code is designed to consistently generate the same + * tangent spaces, for a given mesh, in any tool in which it is used. + * This is done by performing an internal welding step and subsequently an order-independent evaluation + * of tangent space for meshes consisting of triangles and quads. + * This means faces can be received in any order and the same is true for + * the order of vertices of each face. The generated result will not be affected + * by such reordering. Additionally, whether degenerate (vertices or texture coordinates) + * primitives are present or not will not affect the generated results either. + * Once tangent space calculation is done the vertices of degenerate primitives will simply + * inherit tangent space from neighboring non degenerate primitives. + * The analysis behind this implementation can be found in my master's thesis + * which is available for download --> http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf + * Note that though the tangent spaces at the vertices are generated in an order-independent way, + * by this implementation, the interpolated tangent space is still affected by which diagonal is + * chosen to split each quad. A sensible solution is to have your tools pipeline always + * split quads by the shortest diagonal. This choice is order-independent and works with mirroring. + * If these have the same length then compare the diagonals defined by the texture coordinates. + * XNormal which is a tool for baking normal maps allows you to write your own tangent space plugin + * and also quad triangulator plugin. + */ + + +typedef int tbool; +typedef struct SMikkTSpaceContext SMikkTSpaceContext; + +typedef struct { + // Returns the number of faces (triangles/quads) on the mesh to be processed. + int (*m_getNumFaces)(const SMikkTSpaceContext * pContext); + + // Returns the number of vertices on face number iFace + // iFace is a number in the range {0, 1, ..., getNumFaces()-1} + int (*m_getNumVerticesOfFace)(const SMikkTSpaceContext * pContext, const int iFace); + + // returns the position/normal/texcoord of the referenced face of vertex number iVert. + // iVert is in the range {0,1,2} for triangles and {0,1,2,3} for quads. + void (*m_getPosition)(const SMikkTSpaceContext * pContext, float fvPosOut[], const int iFace, const int iVert); + void (*m_getNormal)(const SMikkTSpaceContext * pContext, float fvNormOut[], const int iFace, const int iVert); + void (*m_getTexCoord)(const SMikkTSpaceContext * pContext, float fvTexcOut[], const int iFace, const int iVert); + + // either (or both) of the two setTSpace callbacks can be set. + // The call-back m_setTSpaceBasic() is sufficient for basic normal mapping. + + // This function is used to return the tangent and fSign to the application. + // fvTangent is a unit length vector. + // For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level. + // bitangent = fSign * cross(vN, tangent); + // Note that the results are returned unindexed. It is possible to generate a new index list + // But averaging/overwriting tangent spaces by using an already existing index list WILL produce INCRORRECT results. + // DO NOT! use an already existing index list. + void (*m_setTSpaceBasic)(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert); + + // This function is used to return tangent space results to the application. + // fvTangent and fvBiTangent are unit length vectors and fMagS and fMagT are their + // true magnitudes which can be used for relief mapping effects. + // fvBiTangent is the "real" bitangent and thus may not be perpendicular to fvTangent. + // However, both are perpendicular to the vertex normal. + // For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level. + // fSign = bIsOrientationPreserving ? 1.0f : (-1.0f); + // bitangent = fSign * cross(vN, tangent); + // Note that the results are returned unindexed. It is possible to generate a new index list + // But averaging/overwriting tangent spaces by using an already existing index list WILL produce INCRORRECT results. + // DO NOT! use an already existing index list. + void (*m_setTSpace)(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, + const tbool bIsOrientationPreserving, const int iFace, const int iVert); +} SMikkTSpaceInterface; + +struct SMikkTSpaceContext +{ + SMikkTSpaceInterface * m_pInterface; // initialized with callback functions + void * m_pUserData; // pointer to client side mesh data etc. (passed as the first parameter with every interface call) +}; + +// these are both thread safe! +tbool genTangSpaceDefault(const SMikkTSpaceContext * pContext); // Default (recommended) fAngularThreshold is 180 degrees (which means threshold disabled) +tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThreshold); + + +// To avoid visual errors (distortions/unwanted hard edges in lighting), when using sampled normal maps, the +// normal map sampler must use the exact inverse of the pixel shader transformation. +// The most efficient transformation we can possibly do in the pixel shader is +// achieved by using, directly, the "unnormalized" interpolated tangent, bitangent and vertex normal: vT, vB and vN. +// pixel shader (fast transform out) +// vNout = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); +// where vNt is the tangent space normal. The normal map sampler must likewise use the +// interpolated and "unnormalized" tangent, bitangent and vertex normal to be compliant with the pixel shader. +// sampler does (exact inverse of pixel shader): +// float3 row0 = cross(vB, vN); +// float3 row1 = cross(vN, vT); +// float3 row2 = cross(vT, vB); +// float fSign = dot(vT, row0)<0 ? -1 : 1; +// vNt = normalize( fSign * float3(dot(vNout,row0), dot(vNout,row1), dot(vNout,row2)) ); +// where vNout is the sampled normal in some chosen 3D space. +// +// Should you choose to reconstruct the bitangent in the pixel shader instead +// of the vertex shader, as explained earlier, then be sure to do this in the normal map sampler also. +// Finally, beware of quad triangulations. If the normal map sampler doesn't use the same triangulation of +// quads as your renderer then problems will occur since the interpolated tangent spaces will differ +// eventhough the vertex level tangent spaces match. This can be solved either by triangulating before +// sampling/exporting or by using the order-independent choice of diagonal for splitting quads suggested earlier. +// However, this must be used both by the sampler and your tools/rendering pipeline. + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/nonstd/expected.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/nonstd/expected.hpp new file mode 100644 index 0000000..305f3ab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/nonstd/expected.hpp @@ -0,0 +1,3555 @@ +// This version targets C++11 and later. +// +// Copyright (C) 2016-2020 Martin Moene. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// expected lite is based on: +// A proposal to add a utility class to represent expected monad +// by Vicente J. Botet Escriba and Pierre Talbot. http:://wg21.link/p0323 + +#ifndef NONSTD_EXPECTED_LITE_HPP +#define NONSTD_EXPECTED_LITE_HPP + +#define expected_lite_MAJOR 0 +#define expected_lite_MINOR 8 +#define expected_lite_PATCH 0 + +#define expected_lite_VERSION expected_STRINGIFY(expected_lite_MAJOR) "." expected_STRINGIFY(expected_lite_MINOR) "." expected_STRINGIFY(expected_lite_PATCH) + +#define expected_STRINGIFY( x ) expected_STRINGIFY_( x ) +#define expected_STRINGIFY_( x ) #x + +// expected-lite configuration: + +#define nsel_EXPECTED_DEFAULT 0 +#define nsel_EXPECTED_NONSTD 1 +#define nsel_EXPECTED_STD 2 + +// tweak header support: + +#ifdef __has_include +# if __has_include() +# include +# endif +#define expected_HAVE_TWEAK_HEADER 1 +#else +#define expected_HAVE_TWEAK_HEADER 0 +//# pragma message("expected.hpp: Note: Tweak header not supported.") +#endif + +// expected selection and configuration: + +#if !defined( nsel_CONFIG_SELECT_EXPECTED ) +# define nsel_CONFIG_SELECT_EXPECTED ( nsel_HAVE_STD_EXPECTED ? nsel_EXPECTED_STD : nsel_EXPECTED_NONSTD ) +#endif + +// Proposal revisions: +// +// DXXXXR0: -- +// N4015 : -2 (2014-05-26) +// N4109 : -1 (2014-06-29) +// P0323R0: 0 (2016-05-28) +// P0323R1: 1 (2016-10-12) +// -------: +// P0323R2: 2 (2017-06-15) +// P0323R3: 3 (2017-10-15) +// P0323R4: 4 (2017-11-26) +// P0323R5: 5 (2018-02-08) +// P0323R6: 6 (2018-04-02) +// P0323R7: 7 (2018-06-22) * +// +// expected-lite uses 2 and higher + +#ifndef nsel_P0323R +# define nsel_P0323R 7 +#endif + +// Monadic operations proposal revisions: +// +// P2505R0: 0 (2021-12-12) +// P2505R1: 1 (2022-02-10) +// P2505R2: 2 (2022-04-15) +// P2505R3: 3 (2022-06-05) +// P2505R4: 4 (2022-06-15) +// P2505R5: 5 (2022-09-20) * +// +// expected-lite uses 5 + +#ifndef nsel_P2505R +# define nsel_P2505R 5 +#endif + +// Control presence of C++ exception handling (try and auto discover): + +#ifndef nsel_CONFIG_NO_EXCEPTIONS +# if defined(_MSC_VER) +# include // for _HAS_EXCEPTIONS +# endif +# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) +# define nsel_CONFIG_NO_EXCEPTIONS 0 +# else +# define nsel_CONFIG_NO_EXCEPTIONS 1 +# endif +#endif + +// at default use SEH with MSVC for no C++ exceptions + +#ifndef nsel_CONFIG_NO_EXCEPTIONS_SEH +# define nsel_CONFIG_NO_EXCEPTIONS_SEH ( nsel_CONFIG_NO_EXCEPTIONS && _MSC_VER ) +#endif + +// C++ language version detection (C++23 is speculative): +// Note: VC14.0/1900 (VS2015) lacks too much from C++14. + +#ifndef nsel_CPLUSPLUS +# if defined(_MSVC_LANG ) && !defined(__clang__) +# define nsel_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) +# else +# define nsel_CPLUSPLUS __cplusplus +# endif +#endif + +#define nsel_CPP98_OR_GREATER ( nsel_CPLUSPLUS >= 199711L ) +#define nsel_CPP11_OR_GREATER ( nsel_CPLUSPLUS >= 201103L ) +#define nsel_CPP14_OR_GREATER ( nsel_CPLUSPLUS >= 201402L ) +#define nsel_CPP17_OR_GREATER ( nsel_CPLUSPLUS >= 201703L ) +#define nsel_CPP20_OR_GREATER ( nsel_CPLUSPLUS >= 202002L ) +#define nsel_CPP23_OR_GREATER ( nsel_CPLUSPLUS >= 202300L ) + +// Use C++23 std::expected if available and requested: + +#if nsel_CPP23_OR_GREATER && defined(__has_include ) +# if __has_include( ) +# define nsel_HAVE_STD_EXPECTED 1 +# else +# define nsel_HAVE_STD_EXPECTED 0 +# endif +#else +# define nsel_HAVE_STD_EXPECTED 0 +#endif + +#define nsel_USES_STD_EXPECTED ( (nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_STD) || ((nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_DEFAULT) && nsel_HAVE_STD_EXPECTED) ) + +// +// in_place: code duplicated in any-lite, expected-lite, expected-lite, value-ptr-lite, variant-lite: +// + +#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES +#define nonstd_lite_HAVE_IN_PLACE_TYPES 1 + +// C++17 std::in_place in : + +#if nsel_CPP17_OR_GREATER + +#include + +namespace nonstd { + +using std::in_place; +using std::in_place_type; +using std::in_place_index; +using std::in_place_t; +using std::in_place_type_t; +using std::in_place_index_t; + +#define nonstd_lite_in_place_t( T) std::in_place_t +#define nonstd_lite_in_place_type_t( T) std::in_place_type_t +#define nonstd_lite_in_place_index_t(K) std::in_place_index_t + +#define nonstd_lite_in_place( T) std::in_place_t{} +#define nonstd_lite_in_place_type( T) std::in_place_type_t{} +#define nonstd_lite_in_place_index(K) std::in_place_index_t{} + +} // namespace nonstd + +#else // nsel_CPP17_OR_GREATER + +#include + +namespace nonstd { +namespace detail { + +template< class T > +struct in_place_type_tag {}; + +template< std::size_t K > +struct in_place_index_tag {}; + +} // namespace detail + +struct in_place_t {}; + +template< class T > +inline in_place_t in_place( detail::in_place_type_tag = detail::in_place_type_tag() ) +{ + return in_place_t(); +} + +template< std::size_t K > +inline in_place_t in_place( detail::in_place_index_tag = detail::in_place_index_tag() ) +{ + return in_place_t(); +} + +template< class T > +inline in_place_t in_place_type( detail::in_place_type_tag = detail::in_place_type_tag() ) +{ + return in_place_t(); +} + +template< std::size_t K > +inline in_place_t in_place_index( detail::in_place_index_tag = detail::in_place_index_tag() ) +{ + return in_place_t(); +} + +// mimic templated typedef: + +#define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag ) +#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag ) +#define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag ) + +#define nonstd_lite_in_place( T) nonstd::in_place_type +#define nonstd_lite_in_place_type( T) nonstd::in_place_type +#define nonstd_lite_in_place_index(K) nonstd::in_place_index + +} // namespace nonstd + +#endif // nsel_CPP17_OR_GREATER +#endif // nonstd_lite_HAVE_IN_PLACE_TYPES + +// +// Using std::expected: +// + +#if nsel_USES_STD_EXPECTED + +#include + +namespace nonstd { + + using std::expected; + using std::unexpected; + using std::bad_expected_access; + using std::unexpect_t; + using std::unexpect; + + //[[deprecated("replace unexpected_type with unexpected")]] + + template< typename E > + using unexpected_type = unexpected; + + // Unconditionally provide make_unexpected(): + + template< typename E> + constexpr auto make_unexpected( E && value ) -> unexpected< typename std::decay::type > + { + return unexpected< typename std::decay::type >( std::forward(value) ); + } +} // namespace nonstd + +#else // nsel_USES_STD_EXPECTED + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// additional includes: + +#if nsel_CONFIG_NO_EXCEPTIONS +# if nsel_CONFIG_NO_EXCEPTIONS_SEH +# include // for ExceptionCodes +# else +// already included: +# endif +#else +# include +#endif + +// C++ feature usage: + +#if nsel_CPP11_OR_GREATER +# define nsel_constexpr constexpr +#else +# define nsel_constexpr /*constexpr*/ +#endif + +#if nsel_CPP14_OR_GREATER +# define nsel_constexpr14 constexpr +#else +# define nsel_constexpr14 /*constexpr*/ +#endif + +#if nsel_CPP17_OR_GREATER +# define nsel_inline17 inline +#else +# define nsel_inline17 /*inline*/ +#endif + +// Compiler versions: +// +// MSVC++ 6.0 _MSC_VER == 1200 nsel_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0) +// MSVC++ 7.0 _MSC_VER == 1300 nsel_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002) +// MSVC++ 7.1 _MSC_VER == 1310 nsel_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) +// MSVC++ 8.0 _MSC_VER == 1400 nsel_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) +// MSVC++ 9.0 _MSC_VER == 1500 nsel_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008) +// MSVC++ 10.0 _MSC_VER == 1600 nsel_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010) +// MSVC++ 11.0 _MSC_VER == 1700 nsel_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) +// MSVC++ 12.0 _MSC_VER == 1800 nsel_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) +// MSVC++ 14.0 _MSC_VER == 1900 nsel_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) +// MSVC++ 14.1 _MSC_VER >= 1910 nsel_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) +// MSVC++ 14.2 _MSC_VER >= 1920 nsel_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) + +#if defined(_MSC_VER) && !defined(__clang__) +# define nsel_COMPILER_MSVC_VER (_MSC_VER ) +# define nsel_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900)) ) +#else +# define nsel_COMPILER_MSVC_VER 0 +# define nsel_COMPILER_MSVC_VERSION 0 +#endif + +#define nsel_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) ) + +#if defined(__clang__) +# define nsel_COMPILER_CLANG_VERSION nsel_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) +#else +# define nsel_COMPILER_CLANG_VERSION 0 +#endif + +#if defined(__GNUC__) && !defined(__clang__) +# define nsel_COMPILER_GNUC_VERSION nsel_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#else +# define nsel_COMPILER_GNUC_VERSION 0 +#endif + +// half-open range [lo..hi): +//#define nsel_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) + +// Method enabling + +#define nsel_REQUIRES_0(...) \ + template< bool B = (__VA_ARGS__), typename std::enable_if::type = 0 > + +#define nsel_REQUIRES_T(...) \ + , typename std::enable_if< (__VA_ARGS__), int >::type = 0 + +#define nsel_REQUIRES_R(R, ...) \ + typename std::enable_if< (__VA_ARGS__), R>::type + +#define nsel_REQUIRES_A(...) \ + , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr + +// Clang, GNUC, MSVC warning suppression macros: + +#ifdef __clang__ +# pragma clang diagnostic push +#elif defined __GNUC__ +# pragma GCC diagnostic push +#endif // __clang__ + +#if nsel_COMPILER_MSVC_VERSION >= 140 +# define nsel_DISABLE_MSVC_WARNINGS(codes) __pragma( warning(push) ) __pragma( warning(disable: codes) ) +#else +# define nsel_DISABLE_MSVC_WARNINGS(codes) +#endif + +#ifdef __clang__ +# define nsel_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") +# define nsel_RESTORE_MSVC_WARNINGS() +#elif defined __GNUC__ +# define nsel_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") +# define nsel_RESTORE_MSVC_WARNINGS() +#elif nsel_COMPILER_MSVC_VERSION >= 140 +# define nsel_RESTORE_WARNINGS() __pragma( warning( pop ) ) +# define nsel_RESTORE_MSVC_WARNINGS() nsel_RESTORE_WARNINGS() +#else +# define nsel_RESTORE_WARNINGS() +# define nsel_RESTORE_MSVC_WARNINGS() +#endif + +// Suppress the following MSVC (GSL) warnings: +// - C26409: Avoid calling new and delete explicitly, use std::make_unique instead (r.11) + +nsel_DISABLE_MSVC_WARNINGS( 26409 ) + +// Presence of language and library features: + +#ifdef _HAS_CPP0X +# define nsel_HAS_CPP0X _HAS_CPP0X +#else +# define nsel_HAS_CPP0X 0 +#endif + +// Presence of language and library features: + +#define nsel_CPP17_000 (nsel_CPP17_OR_GREATER) + +// Presence of C++17 language features: + +#define nsel_HAVE_DEPRECATED nsel_CPP17_000 + +// C++ feature usage: + +#if nsel_HAVE_DEPRECATED +# define nsel_deprecated(msg) [[deprecated(msg)]] +#else +# define nsel_deprecated(msg) /*[[deprecated]]*/ +#endif + +// +// expected: +// + +namespace nonstd { namespace expected_lite { + +// type traits C++17: + +namespace std17 { + +#if nsel_CPP17_OR_GREATER + +using std::conjunction; +using std::is_swappable; +using std::is_nothrow_swappable; + +#else // nsel_CPP17_OR_GREATER + +namespace detail { + +using std::swap; + +struct is_swappable +{ + template< typename T, typename = decltype( swap( std::declval(), std::declval() ) ) > + static std::true_type test( int /* unused */); + + template< typename > + static std::false_type test(...); +}; + +struct is_nothrow_swappable +{ + // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015): + + template< typename T > + static constexpr bool satisfies() + { + return noexcept( swap( std::declval(), std::declval() ) ); + } + + template< typename T > + static auto test( int ) -> std::integral_constant()>{} + + template< typename > + static auto test(...) -> std::false_type; +}; +} // namespace detail + +// is [nothrow] swappable: + +template< typename T > +struct is_swappable : decltype( detail::is_swappable::test(0) ){}; + +template< typename T > +struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test(0) ){}; + +// conjunction: + +template< typename... > struct conjunction : std::true_type{}; +template< typename B1 > struct conjunction : B1{}; + +template< typename B1, typename... Bn > +struct conjunction : std::conditional, B1>::type{}; + +#endif // nsel_CPP17_OR_GREATER + +} // namespace std17 + +// type traits C++20: + +namespace std20 { + +#if defined(__cpp_lib_remove_cvref) + +using std::remove_cvref; + +#else + +template< typename T > +struct remove_cvref +{ + typedef typename std::remove_cv< typename std::remove_reference::type >::type type; +}; + +#endif + +} // namespace std20 + +// forward declaration: + +template< typename T, typename E > +class expected; + +namespace detail { + +#if nsel_P2505R >= 3 +template< typename T > +struct is_expected : std::false_type {}; + +template< typename T, typename E > +struct is_expected< expected< T, E > > : std::true_type {}; +#endif // nsel_P2505R >= 3 + +/// discriminated union to hold value or 'error'. + +template< typename T, typename E > +class storage_t_noncopy_nonmove_impl +{ + template< typename, typename > friend class nonstd::expected_lite::expected; + +public: + using value_type = T; + using error_type = E; + + // no-op construction + storage_t_noncopy_nonmove_impl() {} + ~storage_t_noncopy_nonmove_impl() {} + + explicit storage_t_noncopy_nonmove_impl( bool has_value ) + : m_has_value( has_value ) + {} + + void construct_value() + { + new( &m_value ) value_type(); + } + + // void construct_value( value_type const & e ) + // { + // new( &m_value ) value_type( e ); + // } + + // void construct_value( value_type && e ) + // { + // new( &m_value ) value_type( std::move( e ) ); + // } + + template< class... Args > + void emplace_value( Args&&... args ) + { + new( &m_value ) value_type( std::forward(args)...); + } + + template< class U, class... Args > + void emplace_value( std::initializer_list il, Args&&... args ) + { + new( &m_value ) value_type( il, std::forward(args)... ); + } + + void destruct_value() + { + m_value.~value_type(); + } + + // void construct_error( error_type const & e ) + // { + // // new( &m_error ) error_type( e ); + // } + + // void construct_error( error_type && e ) + // { + // // new( &m_error ) error_type( std::move( e ) ); + // } + + template< class... Args > + void emplace_error( Args&&... args ) + { + new( &m_error ) error_type( std::forward(args)...); + } + + template< class U, class... Args > + void emplace_error( std::initializer_list il, Args&&... args ) + { + new( &m_error ) error_type( il, std::forward(args)... ); + } + + void destruct_error() + { + m_error.~error_type(); + } + + constexpr value_type const & value() const & + { + return m_value; + } + + value_type & value() & + { + return m_value; + } + + constexpr value_type const && value() const && + { + return std::move( m_value ); + } + + nsel_constexpr14 value_type && value() && + { + return std::move( m_value ); + } + + value_type const * value_ptr() const + { + return &m_value; + } + + value_type * value_ptr() + { + return &m_value; + } + + error_type const & error() const & + { + return m_error; + } + + error_type & error() & + { + return m_error; + } + + constexpr error_type const && error() const && + { + return std::move( m_error ); + } + + nsel_constexpr14 error_type && error() && + { + return std::move( m_error ); + } + + bool has_value() const + { + return m_has_value; + } + + void set_has_value( bool v ) + { + m_has_value = v; + } + +private: + union + { + value_type m_value; + error_type m_error; + }; + + bool m_has_value = false; +}; + +template< typename T, typename E > +class storage_t_impl +{ + template< typename, typename > friend class nonstd::expected_lite::expected; + +public: + using value_type = T; + using error_type = E; + + // no-op construction + storage_t_impl() {} + ~storage_t_impl() {} + + explicit storage_t_impl( bool has_value ) + : m_has_value( has_value ) + {} + + void construct_value() + { + new( &m_value ) value_type(); + } + + void construct_value( value_type const & e ) + { + new( &m_value ) value_type( e ); + } + + void construct_value( value_type && e ) + { + new( &m_value ) value_type( std::move( e ) ); + } + + template< class... Args > + void emplace_value( Args&&... args ) + { + new( &m_value ) value_type( std::forward(args)...); + } + + template< class U, class... Args > + void emplace_value( std::initializer_list il, Args&&... args ) + { + new( &m_value ) value_type( il, std::forward(args)... ); + } + + void destruct_value() + { + m_value.~value_type(); + } + + void construct_error( error_type const & e ) + { + new( &m_error ) error_type( e ); + } + + void construct_error( error_type && e ) + { + new( &m_error ) error_type( std::move( e ) ); + } + + template< class... Args > + void emplace_error( Args&&... args ) + { + new( &m_error ) error_type( std::forward(args)...); + } + + template< class U, class... Args > + void emplace_error( std::initializer_list il, Args&&... args ) + { + new( &m_error ) error_type( il, std::forward(args)... ); + } + + void destruct_error() + { + m_error.~error_type(); + } + + constexpr value_type const & value() const & + { + return m_value; + } + + value_type & value() & + { + return m_value; + } + + constexpr value_type const && value() const && + { + return std::move( m_value ); + } + + nsel_constexpr14 value_type && value() && + { + return std::move( m_value ); + } + + value_type const * value_ptr() const + { + return &m_value; + } + + value_type * value_ptr() + { + return &m_value; + } + + error_type const & error() const & + { + return m_error; + } + + error_type & error() & + { + return m_error; + } + + constexpr error_type const && error() const && + { + return std::move( m_error ); + } + + nsel_constexpr14 error_type && error() && + { + return std::move( m_error ); + } + + bool has_value() const + { + return m_has_value; + } + + void set_has_value( bool v ) + { + m_has_value = v; + } + +private: + union + { + value_type m_value; + error_type m_error; + }; + + bool m_has_value = false; +}; + +/// discriminated union to hold only 'error'. + +template< typename E > +struct storage_t_impl +{ + template< typename, typename > friend class nonstd::expected_lite::expected; + +public: + using value_type = void; + using error_type = E; + + // no-op construction + storage_t_impl() {} + ~storage_t_impl() {} + + explicit storage_t_impl( bool has_value ) + : m_has_value( has_value ) + {} + + void construct_error( error_type const & e ) + { + new( &m_error ) error_type( e ); + } + + void construct_error( error_type && e ) + { + new( &m_error ) error_type( std::move( e ) ); + } + + template< class... Args > + void emplace_error( Args&&... args ) + { + new( &m_error ) error_type( std::forward(args)...); + } + + template< class U, class... Args > + void emplace_error( std::initializer_list il, Args&&... args ) + { + new( &m_error ) error_type( il, std::forward(args)... ); + } + + void destruct_error() + { + m_error.~error_type(); + } + + error_type const & error() const & + { + return m_error; + } + + error_type & error() & + { + return m_error; + } + + constexpr error_type const && error() const && + { + return std::move( m_error ); + } + + nsel_constexpr14 error_type && error() && + { + return std::move( m_error ); + } + + bool has_value() const + { + return m_has_value; + } + + void set_has_value( bool v ) + { + m_has_value = v; + } + +private: + union + { + char m_dummy; + error_type m_error; + }; + + bool m_has_value = false; +}; + +template< typename T, typename E, bool isConstructable, bool isMoveable > +class storage_t +{ +public: +}; + +template< typename T, typename E > +class storage_t : public storage_t_noncopy_nonmove_impl +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_noncopy_nonmove_impl( has_value ) + {} + + storage_t( storage_t const & other ) = delete; + storage_t( storage_t && other ) = delete; + +}; + +template< typename T, typename E > +class storage_t : public storage_t_impl +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl( has_value ) + {} + + storage_t( storage_t const & other ) + : storage_t_impl( other.has_value() ) + { + if ( this->has_value() ) this->construct_value( other.value() ); + else this->construct_error( other.error() ); + } + + storage_t(storage_t && other ) + : storage_t_impl( other.has_value() ) + { + if ( this->has_value() ) this->construct_value( std::move( other.value() ) ); + else this->construct_error( std::move( other.error() ) ); + } +}; + +template< typename E > +class storage_t : public storage_t_impl +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl( has_value ) + {} + + storage_t( storage_t const & other ) + : storage_t_impl( other.has_value() ) + { + if ( this->has_value() ) ; + else this->construct_error( other.error() ); + } + + storage_t(storage_t && other ) + : storage_t_impl( other.has_value() ) + { + if ( this->has_value() ) ; + else this->construct_error( std::move( other.error() ) ); + } +}; + +template< typename T, typename E > +class storage_t : public storage_t_impl +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl( has_value ) + {} + + storage_t( storage_t const & other ) + : storage_t_impl(other.has_value()) + { + if ( this->has_value() ) this->construct_value( other.value() ); + else this->construct_error( other.error() ); + } + + storage_t( storage_t && other ) = delete; +}; + +template< typename E > +class storage_t : public storage_t_impl +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl( has_value ) + {} + + storage_t( storage_t const & other ) + : storage_t_impl(other.has_value()) + { + if ( this->has_value() ) ; + else this->construct_error( other.error() ); + } + + storage_t( storage_t && other ) = delete; +}; + +template< typename T, typename E > +class storage_t : public storage_t_impl +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl( has_value ) + {} + + storage_t( storage_t const & other ) = delete; + + storage_t( storage_t && other ) + : storage_t_impl( other.has_value() ) + { + if ( this->has_value() ) this->construct_value( std::move( other.value() ) ); + else this->construct_error( std::move( other.error() ) ); + } +}; + +template< typename E > +class storage_t : public storage_t_impl +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl( has_value ) + {} + + storage_t( storage_t const & other ) = delete; + + storage_t( storage_t && other ) + : storage_t_impl( other.has_value() ) + { + if ( this->has_value() ) ; + else this->construct_error( std::move( other.error() ) ); + } +}; + +#if nsel_P2505R >= 3 +// C++11 invoke implementation +template< typename > +struct is_reference_wrapper : std::false_type {}; +template< typename T > +struct is_reference_wrapper< std::reference_wrapper< T > > : std::true_type {}; + +template< typename FnT, typename ClassT, typename ObjectT, typename... Args + nsel_REQUIRES_T( + std::is_function::value + && ( std::is_same< ClassT, typename std20::remove_cvref< ObjectT >::type >::value + || std::is_base_of< ClassT, typename std20::remove_cvref< ObjectT >::type >::value ) + ) +> +nsel_constexpr auto invoke_member_function_impl( FnT ClassT::* memfnptr, ObjectT && obj, Args && ... args ) + noexcept( noexcept( (std::forward< ObjectT >( obj ).*memfnptr)( std::forward< Args >( args )... ) ) ) + -> decltype( (std::forward< ObjectT >( obj ).*memfnptr)( std::forward< Args >( args )...) ) +{ + return (std::forward< ObjectT >( obj ).*memfnptr)( std::forward< Args >( args )... ); +} + +template< typename FnT, typename ClassT, typename ObjectT, typename... Args + nsel_REQUIRES_T( + std::is_function::value + && is_reference_wrapper< typename std20::remove_cvref< ObjectT >::type >::value + ) +> +nsel_constexpr auto invoke_member_function_impl( FnT ClassT::* memfnptr, ObjectT && obj, Args && ... args ) + noexcept( noexcept( (obj.get().*memfnptr)( std::forward< Args >( args ) ... ) ) ) + -> decltype( (obj.get().*memfnptr)( std::forward< Args >( args ) ... ) ) +{ + return (obj.get().*memfnptr)( std::forward< Args >( args ) ... ); +} + +template< typename FnT, typename ClassT, typename ObjectT, typename... Args + nsel_REQUIRES_T( + std::is_function::value + && !std::is_same< ClassT, typename std20::remove_cvref< ObjectT >::type >::value + && !std::is_base_of< ClassT, typename std20::remove_cvref< ObjectT >::type >::value + && !is_reference_wrapper< typename std20::remove_cvref< ObjectT >::type >::value + ) +> +nsel_constexpr auto invoke_member_function_impl( FnT ClassT::* memfnptr, ObjectT && obj, Args && ... args ) + noexcept( noexcept( ((*std::forward< ObjectT >( obj )).*memfnptr)( std::forward< Args >( args ) ... ) ) ) + -> decltype( ((*std::forward< ObjectT >( obj )).*memfnptr)( std::forward< Args >( args ) ... ) ) +{ + return ((*std::forward(obj)).*memfnptr)( std::forward< Args >( args ) ... ); +} + +template< typename MemberT, typename ClassT, typename ObjectT + nsel_REQUIRES_T( + std::is_same< ClassT, typename std20::remove_cvref< ObjectT >::type >::value + || std::is_base_of< ClassT, typename std20::remove_cvref< ObjectT >::type >::value + ) +> +nsel_constexpr auto invoke_member_object_impl( MemberT ClassT::* memobjptr, ObjectT && obj ) + noexcept( noexcept( std::forward< ObjectT >( obj ).*memobjptr ) ) + -> decltype( std::forward< ObjectT >( obj ).*memobjptr ) +{ + return std::forward< ObjectT >( obj ).*memobjptr; +} + +template< typename MemberT, typename ClassT, typename ObjectT + nsel_REQUIRES_T( + is_reference_wrapper< typename std20::remove_cvref< ObjectT >::type >::value + ) +> +nsel_constexpr auto invoke_member_object_impl( MemberT ClassT::* memobjptr, ObjectT && obj ) + noexcept( noexcept( obj.get().*memobjptr ) ) + -> decltype( obj.get().*memobjptr ) +{ + return obj.get().*memobjptr; +} + +template< typename MemberT, typename ClassT, typename ObjectT + nsel_REQUIRES_T( + !std::is_same< ClassT, typename std20::remove_cvref< ObjectT >::type >::value + && !std::is_base_of< ClassT, typename std20::remove_cvref< ObjectT >::type >::value + && !is_reference_wrapper< typename std20::remove_cvref< ObjectT >::type >::value + ) +> +nsel_constexpr auto invoke_member_object_impl( MemberT ClassT::* memobjptr, ObjectT && obj ) + noexcept( noexcept( (*std::forward< ObjectT >( obj )).*memobjptr ) ) + -> decltype( (*std::forward< ObjectT >( obj )).*memobjptr ) +{ + return (*std::forward< ObjectT >( obj )).*memobjptr; +} + +template< typename F, typename... Args + nsel_REQUIRES_T( + std::is_member_function_pointer< typename std20::remove_cvref< F >::type >::value + ) +> +nsel_constexpr auto invoke( F && f, Args && ... args ) + noexcept( noexcept( invoke_member_function_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ) ) ) + -> decltype( invoke_member_function_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ) ) +{ + return invoke_member_function_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ); +} + +template< typename F, typename... Args + nsel_REQUIRES_T( + std::is_member_object_pointer< typename std20::remove_cvref< F >::type >::value + ) +> +nsel_constexpr auto invoke( F && f, Args && ... args ) + noexcept( noexcept( invoke_member_object_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ) ) ) + -> decltype( invoke_member_object_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ) ) +{ + return invoke_member_object_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ); +} + +template< typename F, typename... Args + nsel_REQUIRES_T( + !std::is_member_function_pointer< typename std20::remove_cvref< F >::type >::value + && !std::is_member_object_pointer< typename std20::remove_cvref< F >::type >::value + ) +> +nsel_constexpr auto invoke( F && f, Args && ... args ) + noexcept( noexcept( std::forward< F >( f )( std::forward< Args >( args ) ... ) ) ) + -> decltype( std::forward< F >( f )( std::forward< Args >( args ) ... ) ) +{ + return std::forward< F >( f )( std::forward< Args >( args ) ... ); +} + +template< typename F, typename ... Args > +using invoke_result_nocvref_t = typename std20::remove_cvref< decltype( invoke( std::declval< F >(), std::declval< Args >()... ) ) >::type; + +#if nsel_P2505R >= 5 +template< typename F, typename ... Args > +using transform_invoke_result_t = typename std::remove_cv< decltype( invoke( std::declval< F >(), std::declval< Args >()... ) ) >::type; +#else +template< typename F, typename ... Args > +using transform_invoke_result_t = invoke_result_nocvref_t +#endif // nsel_P2505R >= 5 + +template< typename T > +struct valid_expected_value_type : std::integral_constant< bool, std::is_destructible< T >::value && !std::is_reference< T >::value && !std::is_array< T >::value > {}; + +#endif // nsel_P2505R >= 3 +} // namespace detail + +/// x.x.5 Unexpected object type; unexpected_type; C++17 and later can also use aliased type unexpected. + +#if nsel_P0323R <= 2 +template< typename E = std::exception_ptr > +class unexpected_type +#else +template< typename E > +class unexpected_type +#endif // nsel_P0323R +{ +public: + using error_type = E; + + // x.x.5.2.1 Constructors + +// unexpected_type() = delete; + + constexpr unexpected_type( unexpected_type const & ) = default; + constexpr unexpected_type( unexpected_type && ) = default; + + template< typename... Args + nsel_REQUIRES_T( + std::is_constructible::value + ) + > + constexpr explicit unexpected_type( nonstd_lite_in_place_t(E), Args &&... args ) + : m_error( std::forward( args )...) + {} + + template< typename U, typename... Args + nsel_REQUIRES_T( + std::is_constructible, Args&&...>::value + ) + > + constexpr explicit unexpected_type( nonstd_lite_in_place_t(E), std::initializer_list il, Args &&... args ) + : m_error( il, std::forward( args )...) + {} + + template< typename E2 + nsel_REQUIRES_T( + std::is_constructible::value + && !std::is_same< typename std20::remove_cvref::type, nonstd_lite_in_place_t(E2) >::value + && !std::is_same< typename std20::remove_cvref::type, unexpected_type >::value + ) + > + constexpr explicit unexpected_type( E2 && error ) + : m_error( std::forward( error ) ) + {} + + template< typename E2 + nsel_REQUIRES_T( + std::is_constructible< E, E2>::value + && !std::is_constructible & >::value + && !std::is_constructible >::value + && !std::is_constructible const & >::value + && !std::is_constructible const >::value + && !std::is_convertible< unexpected_type &, E>::value + && !std::is_convertible< unexpected_type , E>::value + && !std::is_convertible< unexpected_type const &, E>::value + && !std::is_convertible< unexpected_type const , E>::value + && !std::is_convertible< E2 const &, E>::value /*=> explicit */ + ) + > + constexpr explicit unexpected_type( unexpected_type const & error ) + : m_error( E{ error.error() } ) + {} + + template< typename E2 + nsel_REQUIRES_T( + std::is_constructible< E, E2>::value + && !std::is_constructible & >::value + && !std::is_constructible >::value + && !std::is_constructible const & >::value + && !std::is_constructible const >::value + && !std::is_convertible< unexpected_type &, E>::value + && !std::is_convertible< unexpected_type , E>::value + && !std::is_convertible< unexpected_type const &, E>::value + && !std::is_convertible< unexpected_type const , E>::value + && std::is_convertible< E2 const &, E>::value /*=> explicit */ + ) + > + constexpr /*non-explicit*/ unexpected_type( unexpected_type const & error ) + : m_error( error.error() ) + {} + + template< typename E2 + nsel_REQUIRES_T( + std::is_constructible< E, E2>::value + && !std::is_constructible & >::value + && !std::is_constructible >::value + && !std::is_constructible const & >::value + && !std::is_constructible const >::value + && !std::is_convertible< unexpected_type &, E>::value + && !std::is_convertible< unexpected_type , E>::value + && !std::is_convertible< unexpected_type const &, E>::value + && !std::is_convertible< unexpected_type const , E>::value + && !std::is_convertible< E2 const &, E>::value /*=> explicit */ + ) + > + constexpr explicit unexpected_type( unexpected_type && error ) + : m_error( E{ std::move( error.error() ) } ) + {} + + template< typename E2 + nsel_REQUIRES_T( + std::is_constructible< E, E2>::value + && !std::is_constructible & >::value + && !std::is_constructible >::value + && !std::is_constructible const & >::value + && !std::is_constructible const >::value + && !std::is_convertible< unexpected_type &, E>::value + && !std::is_convertible< unexpected_type , E>::value + && !std::is_convertible< unexpected_type const &, E>::value + && !std::is_convertible< unexpected_type const , E>::value + && std::is_convertible< E2 const &, E>::value /*=> non-explicit */ + ) + > + constexpr /*non-explicit*/ unexpected_type( unexpected_type && error ) + : m_error( std::move( error.error() ) ) + {} + + // x.x.5.2.2 Assignment + + nsel_constexpr14 unexpected_type& operator=( unexpected_type const & ) = default; + nsel_constexpr14 unexpected_type& operator=( unexpected_type && ) = default; + + template< typename E2 = E > + nsel_constexpr14 unexpected_type & operator=( unexpected_type const & other ) + { + unexpected_type{ other.error() }.swap( *this ); + return *this; + } + + template< typename E2 = E > + nsel_constexpr14 unexpected_type & operator=( unexpected_type && other ) + { + unexpected_type{ std::move( other.error() ) }.swap( *this ); + return *this; + } + + // x.x.5.2.3 Observers + + nsel_constexpr14 E & error() & noexcept + { + return m_error; + } + + constexpr E const & error() const & noexcept + { + return m_error; + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + nsel_constexpr14 E && error() && noexcept + { + return std::move( m_error ); + } + + constexpr E const && error() const && noexcept + { + return std::move( m_error ); + } + +#endif + + // x.x.5.2.3 Observers - deprecated + + nsel_deprecated("replace value() with error()") + + nsel_constexpr14 E & value() & noexcept + { + return m_error; + } + + nsel_deprecated("replace value() with error()") + + constexpr E const & value() const & noexcept + { + return m_error; + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + nsel_deprecated("replace value() with error()") + + nsel_constexpr14 E && value() && noexcept + { + return std::move( m_error ); + } + + nsel_deprecated("replace value() with error()") + + constexpr E const && value() const && noexcept + { + return std::move( m_error ); + } + +#endif + + // x.x.5.2.4 Swap + + template< typename U=E > + nsel_REQUIRES_R( void, + std17::is_swappable::value + ) + swap( unexpected_type & other ) noexcept ( + std17::is_nothrow_swappable::value + ) + { + using std::swap; + swap( m_error, other.m_error ); + } + + // TODO: ??? unexpected_type: in-class friend operator==, != + +private: + error_type m_error; +}; + +#if nsel_CPP17_OR_GREATER + +/// template deduction guide: + +template< typename E > +unexpected_type( E ) -> unexpected_type< E >; + +#endif + +/// class unexpected_type, std::exception_ptr specialization (P0323R2) + +#if !nsel_CONFIG_NO_EXCEPTIONS +#if nsel_P0323R <= 2 + +// TODO: Should expected be specialized for particular E types such as exception_ptr and how? +// See p0323r7 2.1. Ergonomics, http://wg21.link/p0323 +template<> +class unexpected_type< std::exception_ptr > +{ +public: + using error_type = std::exception_ptr; + + unexpected_type() = delete; + + ~unexpected_type(){} + + explicit unexpected_type( std::exception_ptr const & error ) + : m_error( error ) + {} + + explicit unexpected_type(std::exception_ptr && error ) + : m_error( std::move( error ) ) + {} + + template< typename E > + explicit unexpected_type( E error ) + : m_error( std::make_exception_ptr( error ) ) + {} + + std::exception_ptr const & value() const + { + return m_error; + } + + std::exception_ptr & value() + { + return m_error; + } + +private: + std::exception_ptr m_error; +}; + +#endif // nsel_P0323R +#endif // !nsel_CONFIG_NO_EXCEPTIONS + +/// x.x.4, Unexpected equality operators + +template< typename E1, typename E2 > +constexpr bool operator==( unexpected_type const & x, unexpected_type const & y ) +{ + return x.error() == y.error(); +} + +template< typename E1, typename E2 > +constexpr bool operator!=( unexpected_type const & x, unexpected_type const & y ) +{ + return ! ( x == y ); +} + +#if nsel_P0323R <= 2 + +template< typename E > +constexpr bool operator<( unexpected_type const & x, unexpected_type const & y ) +{ + return x.error() < y.error(); +} + +template< typename E > +constexpr bool operator>( unexpected_type const & x, unexpected_type const & y ) +{ + return ( y < x ); +} + +template< typename E > +constexpr bool operator<=( unexpected_type const & x, unexpected_type const & y ) +{ + return ! ( y < x ); +} + +template< typename E > +constexpr bool operator>=( unexpected_type const & x, unexpected_type const & y ) +{ + return ! ( x < y ); +} + +#endif // nsel_P0323R + +/// x.x.5 Specialized algorithms + +template< typename E + nsel_REQUIRES_T( + std17::is_swappable::value + ) +> +void swap( unexpected_type & x, unexpected_type & y) noexcept ( noexcept ( x.swap(y) ) ) +{ + x.swap( y ); +} + +#if nsel_P0323R <= 2 + +// unexpected: relational operators for std::exception_ptr: + +inline constexpr bool operator<( unexpected_type const & /*x*/, unexpected_type const & /*y*/ ) +{ + return false; +} + +inline constexpr bool operator>( unexpected_type const & /*x*/, unexpected_type const & /*y*/ ) +{ + return false; +} + +inline constexpr bool operator<=( unexpected_type const & x, unexpected_type const & y ) +{ + return ( x == y ); +} + +inline constexpr bool operator>=( unexpected_type const & x, unexpected_type const & y ) +{ + return ( x == y ); +} + +#endif // nsel_P0323R + +// unexpected: traits + +#if nsel_P0323R <= 3 + +template< typename E> +struct is_unexpected : std::false_type {}; + +template< typename E> +struct is_unexpected< unexpected_type > : std::true_type {}; + +#endif // nsel_P0323R + +// unexpected: factory + +// keep make_unexpected() removed in p0323r2 for pre-C++17: + +template< typename E> +nsel_constexpr14 auto +make_unexpected( E && value ) -> unexpected_type< typename std::decay::type > +{ + return unexpected_type< typename std::decay::type >( std::forward(value) ); +} + +#if nsel_P0323R <= 3 + +/*nsel_constexpr14*/ auto inline +make_unexpected_from_current_exception() -> unexpected_type< std::exception_ptr > +{ + return unexpected_type< std::exception_ptr >( std::current_exception() ); +} + +#endif // nsel_P0323R + +/// x.x.6, x.x.7 expected access error + +template< typename E > +class bad_expected_access; + +/// x.x.7 bad_expected_access: expected access error + +template <> +class bad_expected_access< void > : public std::exception +{ +public: + explicit bad_expected_access() + : std::exception() + {} +}; + +/// x.x.6 bad_expected_access: expected access error + +#if !nsel_CONFIG_NO_EXCEPTIONS + +template< typename E > +class bad_expected_access : public bad_expected_access< void > +{ +public: + using error_type = E; + + explicit bad_expected_access( error_type error ) + : m_error( error ) + {} + + virtual char const * what() const noexcept override + { + return "bad_expected_access"; + } + + nsel_constexpr14 error_type & error() & + { + return m_error; + } + + constexpr error_type const & error() const & + { + return m_error; + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + nsel_constexpr14 error_type && error() && + { + return std::move( m_error ); + } + + constexpr error_type const && error() const && + { + return std::move( m_error ); + } + +#endif + +private: + error_type m_error; +}; + +#endif // nsel_CONFIG_NO_EXCEPTIONS + +/// x.x.8 unexpect tag, in_place_unexpected tag: construct an error + +struct unexpect_t{}; +using in_place_unexpected_t = unexpect_t; + +nsel_inline17 constexpr unexpect_t unexpect{}; +nsel_inline17 constexpr unexpect_t in_place_unexpected{}; + +/// class error_traits + +#if nsel_CONFIG_NO_EXCEPTIONS + +namespace detail { + inline bool text( char const * /*text*/ ) { return true; } +} + +template< typename Error > +struct error_traits +{ + static void rethrow( Error const & /*e*/ ) + { +#if nsel_CONFIG_NO_EXCEPTIONS_SEH + RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 0, NULL ); +#else + assert( false && detail::text("throw bad_expected_access{ e };") ); +#endif + } +}; + +template<> +struct error_traits< std::exception_ptr > +{ + static void rethrow( std::exception_ptr const & /*e*/ ) + { +#if nsel_CONFIG_NO_EXCEPTIONS_SEH + RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 0, NULL ); +#else + assert( false && detail::text("throw bad_expected_access{ e };") ); +#endif + } +}; + +template<> +struct error_traits< std::error_code > +{ + static void rethrow( std::error_code const & /*e*/ ) + { +#if nsel_CONFIG_NO_EXCEPTIONS_SEH + RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 0, NULL ); +#else + assert( false && detail::text("throw std::system_error( e );") ); +#endif + } +}; + +#else // nsel_CONFIG_NO_EXCEPTIONS + +template< typename Error > +struct error_traits +{ + static void rethrow( Error const & e ) + { + throw bad_expected_access{ e }; + } +}; + +template<> +struct error_traits< std::exception_ptr > +{ + static void rethrow( std::exception_ptr const & e ) + { + std::rethrow_exception( e ); + } +}; + +template<> +struct error_traits< std::error_code > +{ + static void rethrow( std::error_code const & e ) + { + throw std::system_error( e ); + } +}; + +#endif // nsel_CONFIG_NO_EXCEPTIONS + +#if nsel_P2505R >= 3 +namespace detail { + +// from https://en.cppreference.com/w/cpp/utility/expected/unexpected: +// "the type of the unexpected value. The type must not be an array type, a non-object type, a specialization of std::unexpected, or a cv-qualified type." +template< typename T > +struct valid_unexpected_type : std::integral_constant< bool, + std::is_same< T, typename std20::remove_cvref< T >::type >::value + && std::is_object< T >::value + && !std::is_array< T >::value +> {}; + +template< typename T > +struct valid_unexpected_type< unexpected_type< T > > : std::false_type {}; + +} // namespace detail +#endif // nsel_P2505R >= 3 + +} // namespace expected_lite + +// provide nonstd::unexpected_type: + +using expected_lite::unexpected_type; + +namespace expected_lite { + +/// class expected + +#if nsel_P0323R <= 2 +template< typename T, typename E = std::exception_ptr > +class expected +#else +template< typename T, typename E > +class expected +#endif // nsel_P0323R +{ +private: + template< typename, typename > friend class expected; + +public: + using value_type = T; + using error_type = E; + using unexpected_type = nonstd::unexpected_type; + + template< typename U > + struct rebind + { + using type = expected; + }; + + // x.x.4.1 constructors + + nsel_REQUIRES_0( + std::is_default_constructible::value + ) + nsel_constexpr14 expected() + : contained( true ) + { + contained.construct_value(); + } + + nsel_constexpr14 expected( expected const & ) = default; + nsel_constexpr14 expected( expected && ) = default; + + template< typename U, typename G + nsel_REQUIRES_T( + std::is_constructible< T, U const &>::value + && std::is_constructible::value + && !std::is_constructible & >::value + && !std::is_constructible && >::value + && !std::is_constructible const & >::value + && !std::is_constructible const && >::value + && !std::is_convertible< expected & , T>::value + && !std::is_convertible< expected &&, T>::value + && !std::is_convertible< expected const & , T>::value + && !std::is_convertible< expected const &&, T>::value + && (!std::is_convertible::value || !std::is_convertible::value ) /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( expected const & other ) + : contained( other.has_value() ) + { + if ( has_value() ) contained.construct_value( T{ other.contained.value() } ); + else contained.construct_error( E{ other.contained.error() } ); + } + + template< typename U, typename G + nsel_REQUIRES_T( + std::is_constructible< T, U const &>::value + && std::is_constructible::value + && !std::is_constructible & >::value + && !std::is_constructible && >::value + && !std::is_constructible const & >::value + && !std::is_constructible const && >::value + && !std::is_convertible< expected & , T>::value + && !std::is_convertible< expected &&, T>::value + && !std::is_convertible< expected const &, T>::value + && !std::is_convertible< expected const &&, T>::value + && !(!std::is_convertible::value || !std::is_convertible::value ) /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( expected const & other ) + : contained( other.has_value() ) + { + if ( has_value() ) contained.construct_value( other.contained.value() ); + else contained.construct_error( other.contained.error() ); + } + + template< typename U, typename G + nsel_REQUIRES_T( + std::is_constructible< T, U>::value + && std::is_constructible::value + && !std::is_constructible & >::value + && !std::is_constructible && >::value + && !std::is_constructible const & >::value + && !std::is_constructible const && >::value + && !std::is_convertible< expected & , T>::value + && !std::is_convertible< expected &&, T>::value + && !std::is_convertible< expected const & , T>::value + && !std::is_convertible< expected const &&, T>::value + && (!std::is_convertible::value || !std::is_convertible::value ) /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( expected && other ) + : contained( other.has_value() ) + { + if ( has_value() ) contained.construct_value( T{ std::move( other.contained.value() ) } ); + else contained.construct_error( E{ std::move( other.contained.error() ) } ); + } + + template< typename U, typename G + nsel_REQUIRES_T( + std::is_constructible< T, U>::value + && std::is_constructible::value + && !std::is_constructible & >::value + && !std::is_constructible && >::value + && !std::is_constructible const & >::value + && !std::is_constructible const && >::value + && !std::is_convertible< expected & , T>::value + && !std::is_convertible< expected &&, T>::value + && !std::is_convertible< expected const & , T>::value + && !std::is_convertible< expected const &&, T>::value + && !(!std::is_convertible::value || !std::is_convertible::value ) /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( expected && other ) + : contained( other.has_value() ) + { + if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) ); + else contained.construct_error( std::move( other.contained.error() ) ); + } + + template< typename U = T + nsel_REQUIRES_T( + std::is_copy_constructible::value + ) + > + nsel_constexpr14 expected( value_type const & value ) + : contained( true ) + { + contained.construct_value( value ); + } + + template< typename U = T + nsel_REQUIRES_T( + std::is_constructible::value + && !std::is_same::type, nonstd_lite_in_place_t(U)>::value + && !std::is_same< expected , typename std20::remove_cvref::type>::value + && !std::is_same, typename std20::remove_cvref::type>::value + && !std::is_convertible::value /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( U && value ) noexcept + ( + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value + ) + : contained( true ) + { + contained.construct_value( T{ std::forward( value ) } ); + } + + template< typename U = T + nsel_REQUIRES_T( + std::is_constructible::value + && !std::is_same::type, nonstd_lite_in_place_t(U)>::value + && !std::is_same< expected , typename std20::remove_cvref::type>::value + && !std::is_same, typename std20::remove_cvref::type>::value + && std::is_convertible::value /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( U && value ) noexcept + ( + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value + ) + : contained( true ) + { + contained.construct_value( std::forward( value ) ); + } + + // construct error: + + template< typename G = E + nsel_REQUIRES_T( + std::is_constructible::value + && !std::is_convertible< G const &, E>::value /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( nonstd::unexpected_type const & error ) + : contained( false ) + { + contained.construct_error( E{ error.error() } ); + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_constructible::value + && std::is_convertible< G const &, E>::value /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type const & error ) + : contained( false ) + { + contained.construct_error( error.error() ); + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_constructible::value + && !std::is_convertible< G&&, E>::value /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( nonstd::unexpected_type && error ) + : contained( false ) + { + contained.construct_error( E{ std::move( error.error() ) } ); + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_constructible::value + && std::is_convertible< G&&, E>::value /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type && error ) + : contained( false ) + { + contained.construct_error( std::move( error.error() ) ); + } + + // in-place construction, value + + template< typename... Args + nsel_REQUIRES_T( + std::is_constructible::value + ) + > + nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), Args&&... args ) + : contained( true ) + { + contained.emplace_value( std::forward( args )... ); + } + + template< typename U, typename... Args + nsel_REQUIRES_T( + std::is_constructible, Args&&...>::value + ) + > + nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), std::initializer_list il, Args&&... args ) + : contained( true ) + { + contained.emplace_value( il, std::forward( args )... ); + } + + // in-place construction, error + + template< typename... Args + nsel_REQUIRES_T( + std::is_constructible::value + ) + > + nsel_constexpr14 explicit expected( unexpect_t, Args&&... args ) + : contained( false ) + { + contained.emplace_error( std::forward( args )... ); + } + + template< typename U, typename... Args + nsel_REQUIRES_T( + std::is_constructible, Args&&...>::value + ) + > + nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list il, Args&&... args ) + : contained( false ) + { + contained.emplace_error( il, std::forward( args )... ); + } + + // x.x.4.2 destructor + + // TODO: ~expected: triviality + // Effects: If T is not cv void and is_trivially_destructible_v is false and bool(*this), calls val.~T(). If is_trivially_destructible_v is false and !bool(*this), calls unexpect.~unexpected(). + // Remarks: If either T is cv void or is_trivially_destructible_v is true, and is_trivially_destructible_v is true, then this destructor shall be a trivial destructor. + + ~expected() + { + if ( has_value() ) contained.destruct_value(); + else contained.destruct_error(); + } + + // x.x.4.3 assignment + + expected & operator=( expected const & other ) + { + expected( other ).swap( *this ); + return *this; + } + + expected & operator=( expected && other ) noexcept + ( + std::is_nothrow_move_constructible< T>::value + && std::is_nothrow_move_assignable< T>::value + && std::is_nothrow_move_constructible::value // added for missing + && std::is_nothrow_move_assignable< E>::value ) // nothrow above + { + expected( std::move( other ) ).swap( *this ); + return *this; + } + + template< typename U + nsel_REQUIRES_T( + !std::is_same, typename std20::remove_cvref::type>::value + && std17::conjunction, std::is_same> >::value + && std::is_constructible::value + && std::is_assignable< T&,U>::value + && std::is_nothrow_move_constructible::value ) + > + expected & operator=( U && value ) + { + expected( std::forward( value ) ).swap( *this ); + return *this; + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_constructible::value && + std::is_copy_constructible::value // TODO: std::is_nothrow_copy_constructible + && std::is_copy_assignable::value + ) + > + expected & operator=( nonstd::unexpected_type const & error ) + { + expected( unexpect, error.error() ).swap( *this ); + return *this; + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_constructible::value && + std::is_move_constructible::value // TODO: std::is_nothrow_move_constructible + && std::is_move_assignable::value + ) + > + expected & operator=( nonstd::unexpected_type && error ) + { + expected( unexpect, std::move( error.error() ) ).swap( *this ); + return *this; + } + + template< typename... Args + nsel_REQUIRES_T( + std::is_nothrow_constructible::value + ) + > + value_type & emplace( Args &&... args ) + { + expected( nonstd_lite_in_place(T), std::forward(args)... ).swap( *this ); + return value(); + } + + template< typename U, typename... Args + nsel_REQUIRES_T( + std::is_nothrow_constructible&, Args&&...>::value + ) + > + value_type & emplace( std::initializer_list il, Args &&... args ) + { + expected( nonstd_lite_in_place(T), il, std::forward(args)... ).swap( *this ); + return value(); + } + + // x.x.4.4 swap + + template< typename U=T, typename G=E > + nsel_REQUIRES_R( void, + std17::is_swappable< U>::value + && std17::is_swappable::value + && ( std::is_move_constructible::value || std::is_move_constructible::value ) + ) + swap( expected & other ) noexcept + ( + std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && + std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value + ) + { + using std::swap; + + if ( bool(*this) && bool(other) ) { swap( contained.value(), other.contained.value() ); } + else if ( ! bool(*this) && ! bool(other) ) { swap( contained.error(), other.contained.error() ); } + else if ( bool(*this) && ! bool(other) ) { error_type t( std::move( other.error() ) ); + other.contained.destruct_error(); + other.contained.construct_value( std::move( contained.value() ) ); + contained.destruct_value(); + contained.construct_error( std::move( t ) ); + bool has_value = contained.has_value(); + bool other_has_value = other.has_value(); + other.contained.set_has_value(has_value); + contained.set_has_value(other_has_value); + } + else if ( ! bool(*this) && bool(other) ) { other.swap( *this ); } + } + + // x.x.4.5 observers + + constexpr value_type const * operator ->() const + { + return assert( has_value() ), contained.value_ptr(); + } + + value_type * operator ->() + { + return assert( has_value() ), contained.value_ptr(); + } + + constexpr value_type const & operator *() const & + { + return assert( has_value() ), contained.value(); + } + + value_type & operator *() & + { + return assert( has_value() ), contained.value(); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + constexpr value_type const && operator *() const && + { + return std::move( ( assert( has_value() ), contained.value() ) ); + } + + nsel_constexpr14 value_type && operator *() && + { + return std::move( ( assert( has_value() ), contained.value() ) ); + } + +#endif + + constexpr explicit operator bool() const noexcept + { + return has_value(); + } + + constexpr bool has_value() const noexcept + { + return contained.has_value(); + } + + nsel_DISABLE_MSVC_WARNINGS( 4702 ) // warning C4702: unreachable code, see issue 65. + + constexpr value_type const & value() const & + { + return has_value() + ? ( contained.value() ) + : ( error_traits::rethrow( contained.error() ), contained.value() ); + } + + value_type & value() & + { + return has_value() + ? ( contained.value() ) + : ( error_traits::rethrow( contained.error() ), contained.value() ); + } + nsel_RESTORE_MSVC_WARNINGS() + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + constexpr value_type const && value() const && + { + return std::move( has_value() + ? ( contained.value() ) + : ( error_traits::rethrow( contained.error() ), contained.value() ) ); + } + + nsel_constexpr14 value_type && value() && + { + return std::move( has_value() + ? ( contained.value() ) + : ( error_traits::rethrow( contained.error() ), contained.value() ) ); + } + +#endif + + constexpr error_type const & error() const & + { + return assert( ! has_value() ), contained.error(); + } + + error_type & error() & + { + return assert( ! has_value() ), contained.error(); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + constexpr error_type const && error() const && + { + return std::move( ( assert( ! has_value() ), contained.error() ) ); + } + + error_type && error() && + { + return std::move( ( assert( ! has_value() ), contained.error() ) ); + } + +#endif + + constexpr unexpected_type get_unexpected() const + { + return make_unexpected( contained.error() ); + } + + template< typename Ex > + bool has_exception() const + { + using ContainedEx = typename std::remove_reference< decltype( get_unexpected().value() ) >::type; + return ! has_value() && std::is_base_of< Ex, ContainedEx>::value; + } + + template< typename U + nsel_REQUIRES_T( + std::is_copy_constructible< T>::value + && std::is_convertible::value + ) + > + value_type value_or( U && v ) const & + { + return has_value() + ? contained.value() + : static_cast( std::forward( v ) ); + } + + template< typename U + nsel_REQUIRES_T( + std::is_move_constructible< T>::value + && std::is_convertible::value + ) + > + value_type value_or( U && v ) && + { + return has_value() + ? std::move( contained.value() ) + : static_cast( std::forward( v ) ); + } + +#if nsel_P2505R >= 4 + template< typename G = E + nsel_REQUIRES_T( + std::is_copy_constructible< E >::value + && std::is_convertible< G, E >::value + ) + > + nsel_constexpr error_type error_or( G && e ) const & + { + return has_value() + ? static_cast< E >( std::forward< G >( e ) ) + : contained.error(); + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_move_constructible< E >::value + && std::is_convertible< G, E >::value + ) + > + nsel_constexpr14 error_type error_or( G && e ) && + { + return has_value() + ? static_cast< E >( std::forward< G >( e ) ) + : std::move( contained.error() ); + } +#endif // nsel_P2505R >= 4 + +#if nsel_P2505R >= 3 + // Monadic operations (P2505) + template< typename F + nsel_REQUIRES_T( + detail::is_expected < detail::invoke_result_nocvref_t< F, value_type & > > ::value + && std::is_same< typename detail::invoke_result_nocvref_t< F, value_type & >::error_type, error_type >::value + && std::is_constructible< error_type, error_type & >::value + ) + > + nsel_constexpr14 detail::invoke_result_nocvref_t< F, value_type & > and_then( F && f ) & + { + return has_value() + ? detail::invoke_result_nocvref_t< F, value_type & >( detail::invoke( std::forward< F >( f ), value() ) ) + : detail::invoke_result_nocvref_t< F, value_type & >( unexpect, error() ); + } + + template >::value + && std::is_same< typename detail::invoke_result_nocvref_t< F, const value_type & >::error_type, error_type >::value + && std::is_constructible< error_type, const error_type & >::value + ) + > + nsel_constexpr detail::invoke_result_nocvref_t< F, const value_type & > and_then( F && f ) const & + { + return has_value() + ? detail::invoke_result_nocvref_t< F, const value_type & >( detail::invoke( std::forward< F >( f ), value() ) ) + : detail::invoke_result_nocvref_t< F, const value_type & >( unexpect, error() ); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template >::value + && std::is_same< typename detail::invoke_result_nocvref_t< F, value_type && >::error_type, error_type >::value + && std::is_constructible< error_type, error_type && >::value + ) + > + nsel_constexpr14 detail::invoke_result_nocvref_t< F, value_type && > and_then( F && f ) && + { + return has_value() + ? detail::invoke_result_nocvref_t< F, value_type && >( detail::invoke( std::forward< F >( f ), std::move( value() ) ) ) + : detail::invoke_result_nocvref_t< F, value_type && >( unexpect, std::move( error() ) ); + } + + template >::value + && std::is_same< typename detail::invoke_result_nocvref_t< F, const value_type & >::error_type, error_type >::value + && std::is_constructible< error_type, const error_type && >::value + ) + > + nsel_constexpr detail::invoke_result_nocvref_t< F, const value_type && > and_then( F && f ) const && + { + return has_value() + ? detail::invoke_result_nocvref_t< F, const value_type && >( detail::invoke( std::forward< F >( f ), std::move( value() ) ) ) + : detail::invoke_result_nocvref_t< F, const value_type && >( unexpect, std::move( error() ) ); + } +#endif + + template >::value + && std::is_same< typename detail::invoke_result_nocvref_t< F, error_type & >::value_type, value_type >::value + && std::is_constructible< value_type, value_type & >::value + ) + > + nsel_constexpr14 detail::invoke_result_nocvref_t< F, error_type & > or_else( F && f ) & + { + return has_value() + ? detail::invoke_result_nocvref_t< F, error_type & >( value() ) + : detail::invoke_result_nocvref_t< F, error_type & >( detail::invoke( std::forward< F >( f ), error() ) ); + } + + template >::value + && std::is_same< typename detail::invoke_result_nocvref_t< F, const error_type & >::value_type, value_type >::value + && std::is_constructible< value_type, const value_type & >::value + ) + > + nsel_constexpr detail::invoke_result_nocvref_t< F, const error_type & > or_else( F && f ) const & + { + return has_value() + ? detail::invoke_result_nocvref_t< F, const error_type & >( value() ) + : detail::invoke_result_nocvref_t< F, const error_type & >( detail::invoke( std::forward< F >( f ), error() ) ); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template >::value + && std::is_same< typename detail::invoke_result_nocvref_t< F, error_type && >::value_type, value_type >::value + && std::is_constructible< value_type, value_type && >::value + ) + > + nsel_constexpr14 detail::invoke_result_nocvref_t< F, error_type && > or_else( F && f ) && + { + return has_value() + ? detail::invoke_result_nocvref_t< F, error_type && >( std::move( value() ) ) + : detail::invoke_result_nocvref_t< F, error_type && >( detail::invoke( std::forward< F >( f ), std::move( error() ) ) ); + } + + template >::value + && std::is_same< typename detail::invoke_result_nocvref_t< F, const error_type && >::value_type, value_type >::value + && std::is_constructible< value_type, const value_type && >::value + ) + > + nsel_constexpr detail::invoke_result_nocvref_t< F, const error_type && > or_else( F && f ) const && + { + return has_value() + ? detail::invoke_result_nocvref_t< F, const error_type && >( std::move( value() ) ) + : detail::invoke_result_nocvref_t< F, const error_type && >( detail::invoke( std::forward< F >( f ), std::move( error() ) ) ); + } +#endif + + template::value + && !std::is_void< detail::transform_invoke_result_t< F, value_type & > >::value + && detail::valid_expected_value_type< detail::transform_invoke_result_t< F, value_type & > >::value + ) + > + nsel_constexpr14 expected< detail::transform_invoke_result_t< F, value_type & >, error_type > transform( F && f ) & + { + return has_value() + ? expected< detail::transform_invoke_result_t< F, value_type & >, error_type >( detail::invoke( std::forward< F >( f ), **this ) ) + : make_unexpected( error() ); + } + + template::value + && std::is_void< detail::transform_invoke_result_t< F, value_type & > >::value + ) + > + nsel_constexpr14 expected< void, error_type > transform( F && f ) & + { + return has_value() + ? ( detail::invoke( std::forward< F >( f ), **this ), expected< void, error_type >() ) + : make_unexpected( error() ); + } + + template::value + && !std::is_void< detail::transform_invoke_result_t< F, const value_type & > >::value + && detail::valid_expected_value_type< detail::transform_invoke_result_t< F, const value_type & > >::value + ) + > + nsel_constexpr expected< detail::transform_invoke_result_t< F, const value_type & >, error_type > transform( F && f ) const & + { + return has_value() + ? expected< detail::transform_invoke_result_t< F, const value_type & >, error_type >( detail::invoke( std::forward< F >( f ), **this ) ) + : make_unexpected( error() ); + } + + template::value + && std::is_void< detail::transform_invoke_result_t< F, const value_type & > >::value + ) + > + nsel_constexpr expected< void, error_type > transform( F && f ) const & + { + return has_value() + ? ( detail::invoke( std::forward< F >( f ), **this ), expected< void, error_type >() ) + : make_unexpected( error() ); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template::value + && !std::is_void< detail::transform_invoke_result_t< F, value_type && > >::value + && detail::valid_expected_value_type< detail::transform_invoke_result_t< F, value_type && > >::value + ) + > + nsel_constexpr14 expected< detail::transform_invoke_result_t< F, value_type && >, error_type > transform( F && f ) && + { + return has_value() + ? expected< detail::transform_invoke_result_t< F, value_type && >, error_type >( detail::invoke( std::forward< F >( f ), std::move( **this ) ) ) + : make_unexpected( std::move( error() ) ); + } + + template::value + && std::is_void< detail::transform_invoke_result_t< F, value_type && > >::value + ) + > + nsel_constexpr14 expected< void, error_type > transform( F && f ) && + { + return has_value() + ? ( detail::invoke( std::forward< F >( f ), **this ), expected< void, error_type >() ) + : make_unexpected( std::move( error() ) ); + } + + template::value + && !std::is_void< detail::transform_invoke_result_t< F, const value_type && > >::value + && detail::valid_expected_value_type< detail::transform_invoke_result_t< F, const value_type && > >::value + ) + > + nsel_constexpr expected< detail::transform_invoke_result_t< F, const value_type && >, error_type > transform( F && f ) const && + { + return has_value() + ? expected< detail::transform_invoke_result_t< F, const value_type && >, error_type >( detail::invoke( std::forward< F >( f ), std::move( **this ) ) ) + : make_unexpected( std::move( error() ) ); + } + + template::value + && std::is_void< detail::transform_invoke_result_t< F, const value_type && > >::value + ) + > + nsel_constexpr expected< void, error_type > transform( F && f ) const && + { + return has_value() + ? ( detail::invoke( std::forward< F >( f ), **this ), expected< void, error_type >() ) + : make_unexpected( std::move( error() ) ); + } +#endif + + template >::value + && std::is_constructible< value_type, value_type & >::value + ) + > + nsel_constexpr14 expected< value_type, detail::transform_invoke_result_t< F, error_type & > > transform_error( F && f ) & + { + return has_value() + ? expected< value_type, detail::transform_invoke_result_t< F, error_type & > >( in_place, **this ) + : make_unexpected( detail::invoke( std::forward< F >( f ), error() ) ); + } + + template >::value + && std::is_constructible< value_type, const value_type & >::value + ) + > + nsel_constexpr expected< value_type, detail::transform_invoke_result_t< F, const error_type & > > transform_error( F && f ) const & + { + return has_value() + ? expected< value_type, detail::transform_invoke_result_t< F, const error_type & > >( in_place, **this ) + : make_unexpected( detail::invoke( std::forward< F >( f ), error() ) ); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template >::value + && std::is_constructible< value_type, value_type && >::value + ) + > + nsel_constexpr14 expected< value_type, detail::transform_invoke_result_t< F, error_type && > > transform_error( F && f ) && + { + return has_value() + ? expected< value_type, detail::transform_invoke_result_t< F, error_type && > >( in_place, std::move( **this ) ) + : make_unexpected( detail::invoke( std::forward< F >( f ), std::move( error() ) ) ); + } + + template >::value + && std::is_constructible< value_type, const value_type && >::value + ) + > + nsel_constexpr expected< value_type, detail::transform_invoke_result_t< F, const error_type && > > transform_error( F && f ) const && + { + return has_value() + ? expected< value_type, detail::transform_invoke_result_t< F, const error_type && > >( in_place, std::move( **this ) ) + : make_unexpected( detail::invoke( std::forward< F >( f ), std::move( error() ) ) ); + } +#endif +#endif // nsel_P2505R >= 3 + // unwrap() + +// template +// constexpr expected expected,E>::unwrap() const&; + +// template +// constexpr expected expected::unwrap() const&; + +// template +// expected expected, E>::unwrap() &&; + +// template +// template expected expected::unwrap() &&; + + // factories + +// template< typename Ex, typename F> +// expected catch_exception(F&& f); + +// template< typename F> +// expected())),E> map(F&& func) ; + +// template< typename F> +// 'see below' bind(F&& func); + +// template< typename F> +// expected catch_error(F&& f); + +// template< typename F> +// 'see below' then(F&& func); + +private: + detail::storage_t + < + T + ,E + , std::is_copy_constructible::value && std::is_copy_constructible::value + , std::is_move_constructible::value && std::is_move_constructible::value + > + contained; +}; + +/// class expected, void specialization + +template< typename E > +class expected +{ +private: + template< typename, typename > friend class expected; + +public: + using value_type = void; + using error_type = E; + using unexpected_type = nonstd::unexpected_type; + + // x.x.4.1 constructors + + constexpr expected() noexcept + : contained( true ) + {} + + nsel_constexpr14 expected( expected const & other ) = default; + nsel_constexpr14 expected( expected && other ) = default; + + constexpr explicit expected( nonstd_lite_in_place_t(void) ) + : contained( true ) + {} + + template< typename G = E + nsel_REQUIRES_T( + !std::is_convertible::value /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( nonstd::unexpected_type const & error ) + : contained( false ) + { + contained.construct_error( E{ error.error() } ); + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_convertible::value /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type const & error ) + : contained( false ) + { + contained.construct_error( error.error() ); + } + + template< typename G = E + nsel_REQUIRES_T( + !std::is_convertible::value /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( nonstd::unexpected_type && error ) + : contained( false ) + { + contained.construct_error( E{ std::move( error.error() ) } ); + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_convertible::value /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type && error ) + : contained( false ) + { + contained.construct_error( std::move( error.error() ) ); + } + + template< typename... Args + nsel_REQUIRES_T( + std::is_constructible::value + ) + > + nsel_constexpr14 explicit expected( unexpect_t, Args&&... args ) + : contained( false ) + { + contained.emplace_error( std::forward( args )... ); + } + + template< typename U, typename... Args + nsel_REQUIRES_T( + std::is_constructible, Args&&...>::value + ) + > + nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list il, Args&&... args ) + : contained( false ) + { + contained.emplace_error( il, std::forward( args )... ); + } + + // destructor + + ~expected() + { + if ( ! has_value() ) + { + contained.destruct_error(); + } + } + + // x.x.4.3 assignment + + expected & operator=( expected const & other ) + { + expected( other ).swap( *this ); + return *this; + } + + expected & operator=( expected && other ) noexcept + ( + std::is_nothrow_move_assignable::value && + std::is_nothrow_move_constructible::value ) + { + expected( std::move( other ) ).swap( *this ); + return *this; + } + + void emplace() + { + expected().swap( *this ); + } + + // x.x.4.4 swap + + template< typename G = E > + nsel_REQUIRES_R( void, + std17::is_swappable::value + && std::is_move_constructible::value + ) + swap( expected & other ) noexcept + ( + std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value + ) + { + using std::swap; + + if ( ! bool(*this) && ! bool(other) ) { swap( contained.error(), other.contained.error() ); } + else if ( bool(*this) && ! bool(other) ) { contained.construct_error( std::move( other.error() ) ); + bool has_value = contained.has_value(); + bool other_has_value = other.has_value(); + other.contained.set_has_value(has_value); + contained.set_has_value(other_has_value); + } + else if ( ! bool(*this) && bool(other) ) { other.swap( *this ); } + } + + // x.x.4.5 observers + + constexpr explicit operator bool() const noexcept + { + return has_value(); + } + + constexpr bool has_value() const noexcept + { + return contained.has_value(); + } + + void value() const + { + if ( ! has_value() ) + { + error_traits::rethrow( contained.error() ); + } + } + + constexpr error_type const & error() const & + { + return assert( ! has_value() ), contained.error(); + } + + error_type & error() & + { + return assert( ! has_value() ), contained.error(); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + constexpr error_type const && error() const && + { + return std::move( ( assert( ! has_value() ), contained.error() ) ); + } + + error_type && error() && + { + return std::move( ( assert( ! has_value() ), contained.error() ) ); + } + +#endif + + constexpr unexpected_type get_unexpected() const + { + return make_unexpected( contained.error() ); + } + + template< typename Ex > + bool has_exception() const + { + using ContainedEx = typename std::remove_reference< decltype( get_unexpected().value() ) >::type; + return ! has_value() && std::is_base_of< Ex, ContainedEx>::value; + } + +#if nsel_P2505R >= 4 + template< typename G = E + nsel_REQUIRES_T( + std::is_copy_constructible< E >::value + && std::is_convertible< G, E >::value + ) + > + nsel_constexpr error_type error_or( G && e ) const & + { + return has_value() + ? static_cast< E >( std::forward< G >( e ) ) + : contained.error(); + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_move_constructible< E >::value + && std::is_convertible< G, E >::value + ) + > + nsel_constexpr14 error_type error_or( G && e ) && + { + return has_value() + ? static_cast< E >( std::forward< G >( e ) ) + : std::move( contained.error() ); + } +#endif // nsel_P2505R >= 4 + +#if nsel_P2505R >= 3 + // Monadic operations (P2505) + template >::value + && std::is_same< typename detail::invoke_result_nocvref_t< F >::error_type, error_type >::value + && std::is_constructible< error_type, error_type & >::value + ) + > + nsel_constexpr14 detail::invoke_result_nocvref_t< F > and_then( F && f ) & + { + return has_value() + ? detail::invoke_result_nocvref_t< F >( detail::invoke( std::forward< F >( f ) ) ) + : detail::invoke_result_nocvref_t< F >( unexpect, error() ); + } + + template >::value + && std::is_same< typename detail::invoke_result_nocvref_t< F >::error_type, error_type >::value + && std::is_constructible< error_type, const error_type & >::value + ) + > + nsel_constexpr detail::invoke_result_nocvref_t< F > and_then( F && f ) const & + { + return has_value() + ? detail::invoke_result_nocvref_t< F >( detail::invoke( std::forward< F >( f ) ) ) + : detail::invoke_result_nocvref_t< F >( unexpect, error() ); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template >::value + && std::is_same< typename detail::invoke_result_nocvref_t< F >::error_type, error_type >::value + && std::is_constructible< error_type, error_type && >::value + ) + > + nsel_constexpr14 detail::invoke_result_nocvref_t< F > and_then( F && f ) && + { + return has_value() + ? detail::invoke_result_nocvref_t< F >( detail::invoke( std::forward< F >( f ) ) ) + : detail::invoke_result_nocvref_t< F >( unexpect, std::move( error() ) ); + } + + template >::value + && std::is_same< typename detail::invoke_result_nocvref_t< F >::error_type, error_type >::value + && std::is_constructible< error_type, const error_type && >::value + ) + > + nsel_constexpr detail::invoke_result_nocvref_t< F > and_then( F && f ) const && + { + return has_value() + ? detail::invoke_result_nocvref_t< F >( detail::invoke( std::forward< F >( f ) ) ) + : detail::invoke_result_nocvref_t< F >( unexpect, std::move( error() ) ); + } +#endif + + template >::value + && std::is_void< typename detail::invoke_result_nocvref_t< F, error_type & >::value_type >::value + ) + > + nsel_constexpr14 detail::invoke_result_nocvref_t< F, error_type & > or_else( F && f ) & + { + return has_value() + ? detail::invoke_result_nocvref_t< F, error_type & >() + : detail::invoke_result_nocvref_t< F, error_type & >( detail::invoke( std::forward< F >( f ), error() ) ); + } + + template >::value + && std::is_void< typename detail::invoke_result_nocvref_t< F, const error_type & >::value_type >::value + ) + > + nsel_constexpr detail::invoke_result_nocvref_t< F, const error_type & > or_else( F && f ) const & + { + return has_value() + ? detail::invoke_result_nocvref_t< F, const error_type & >() + : detail::invoke_result_nocvref_t< F, const error_type & >( detail::invoke( std::forward< F >( f ), error() ) ); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template >::value + && std::is_void< typename detail::invoke_result_nocvref_t< F, error_type && >::value_type >::value + ) + > + nsel_constexpr14 detail::invoke_result_nocvref_t< F, error_type && > or_else( F && f ) && + { + return has_value() + ? detail::invoke_result_nocvref_t< F, error_type && >() + : detail::invoke_result_nocvref_t< F, error_type && >( detail::invoke( std::forward< F >( f ), std::move( error() ) ) ); + } + + template >::value + && std::is_void< typename detail::invoke_result_nocvref_t< F, const error_type && >::value_type >::value + ) + > + nsel_constexpr detail::invoke_result_nocvref_t< F, const error_type && > or_else( F && f ) const && + { + return has_value() + ? detail::invoke_result_nocvref_t< F, const error_type && >() + : detail::invoke_result_nocvref_t< F, const error_type && >( detail::invoke( std::forward< F >( f ), std::move( error() ) ) ); + } +#endif + + template::value + && !std::is_void< detail::transform_invoke_result_t< F > >::value + ) + > + nsel_constexpr14 expected< detail::transform_invoke_result_t< F >, error_type > transform( F && f ) & + { + return has_value() + ? expected< detail::transform_invoke_result_t< F >, error_type >( detail::invoke( std::forward< F >( f ) ) ) + : make_unexpected( error() ); + } + + template::value + && std::is_void< detail::transform_invoke_result_t< F > >::value + ) + > + nsel_constexpr14 expected< void, error_type > transform( F && f ) & + { + return has_value() + ? ( detail::invoke( std::forward< F >( f ) ), expected< void, error_type >() ) + : make_unexpected( error() ); + } + + template::value + && !std::is_void< detail::transform_invoke_result_t< F > >::value + ) + > + nsel_constexpr expected< detail::transform_invoke_result_t< F >, error_type > transform( F && f ) const & + { + return has_value() + ? expected< detail::transform_invoke_result_t< F >, error_type >( detail::invoke( std::forward< F >( f ) ) ) + : make_unexpected( error() ); + } + + template::value + && std::is_void< detail::transform_invoke_result_t< F > >::value + ) + > + nsel_constexpr expected< void, error_type > transform( F && f ) const & + { + return has_value() + ? ( detail::invoke( std::forward< F >( f ) ), expected< void, error_type >() ) + : make_unexpected( error() ); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template::value + && !std::is_void< detail::transform_invoke_result_t< F > >::value + ) + > + nsel_constexpr14 expected< detail::transform_invoke_result_t< F >, error_type > transform( F && f ) && + { + return has_value() + ? expected< detail::transform_invoke_result_t< F >, error_type >( detail::invoke( std::forward< F >( f ) ) ) + : make_unexpected( error() ); + } + + template::value + && std::is_void< detail::transform_invoke_result_t< F > >::value + ) + > + nsel_constexpr14 expected< void, error_type > transform( F && f ) && + { + return has_value() + ? ( detail::invoke( std::forward< F >( f ) ), expected< void, error_type >() ) + : make_unexpected( error() ); + } + + template::value + && !std::is_void< detail::transform_invoke_result_t< F > >::value + ) + > + nsel_constexpr expected< detail::transform_invoke_result_t< F >, error_type > transform( F && f ) const && + { + return has_value() + ? expected< detail::transform_invoke_result_t< F >, error_type >( detail::invoke( std::forward< F >( f ) ) ) + : make_unexpected( error() ); + } + + template::value + && std::is_void< detail::transform_invoke_result_t< F > >::value + ) + > + nsel_constexpr expected< void, error_type > transform( F && f ) const && + { + return has_value() + ? ( detail::invoke( std::forward< F >( f ) ), expected< void, error_type >() ) + : make_unexpected( error() ); + } +#endif + + template >::value + ) + > + nsel_constexpr14 expected< void, detail::transform_invoke_result_t< F, error_type & > > transform_error( F && f ) & + { + return has_value() + ? expected< void, detail::transform_invoke_result_t< F, error_type & > >() + : make_unexpected( detail::invoke( std::forward< F >( f ), error() ) ); + } + + template >::value + ) + > + nsel_constexpr expected< void, detail::transform_invoke_result_t< F, const error_type & > > transform_error( F && f ) const & + { + return has_value() + ? expected< void, detail::transform_invoke_result_t< F, const error_type & > >() + : make_unexpected( detail::invoke( std::forward< F >( f ), error() ) ); + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + template >::value + ) + > + nsel_constexpr14 expected< void, detail::transform_invoke_result_t< F, error_type && > > transform_error( F && f ) && + { + return has_value() + ? expected< void, detail::transform_invoke_result_t< F, error_type && > >() + : make_unexpected( detail::invoke( std::forward< F >( f ), std::move( error() ) ) ); + } + + template >::value + ) + > + nsel_constexpr expected< void, detail::transform_invoke_result_t< F, const error_type && > > transform_error( F && f ) const && + { + return has_value() + ? expected< void, detail::transform_invoke_result_t< F, const error_type && > >() + : make_unexpected( detail::invoke( std::forward< F >( f ), std::move( error() ) ) ); + } +#endif +#endif // nsel_P2505R >= 3 + +// template constexpr 'see below' unwrap() const&; +// +// template 'see below' unwrap() &&; + + // factories + +// template< typename Ex, typename F> +// expected catch_exception(F&& f); +// +// template< typename F> +// expected map(F&& func) ; +// +// template< typename F> +// 'see below' bind(F&& func) ; +// +// template< typename F> +// expected catch_error(F&& f); +// +// template< typename F> +// 'see below' then(F&& func); + +private: + detail::storage_t + < + void + , E + , std::is_copy_constructible::value + , std::is_move_constructible::value + > + contained; +}; + +// x.x.4.6 expected<>: comparison operators + +template< typename T1, typename E1, typename T2, typename E2 + nsel_REQUIRES_T( + !std::is_void::value && !std::is_void::value + ) +> +constexpr bool operator==( expected const & x, expected const & y ) +{ + return bool(x) != bool(y) ? false : bool(x) ? *x == *y : x.error() == y.error(); +} + +template< typename T1, typename E1, typename T2, typename E2 + nsel_REQUIRES_T( + std::is_void::value && std::is_void::value + ) +> +constexpr bool operator==( expected const & x, expected const & y ) +{ + return bool(x) != bool(y) ? false : bool(x) || static_cast( x.error() == y.error() ); +} + +template< typename T1, typename E1, typename T2, typename E2 > +constexpr bool operator!=( expected const & x, expected const & y ) +{ + return !(x == y); +} + +#if nsel_P0323R <= 2 + +template< typename T, typename E > +constexpr bool operator<( expected const & x, expected const & y ) +{ + return (!y) ? false : (!x) ? true : *x < *y; +} + +template< typename T, typename E > +constexpr bool operator>( expected const & x, expected const & y ) +{ + return (y < x); +} + +template< typename T, typename E > +constexpr bool operator<=( expected const & x, expected const & y ) +{ + return !(y < x); +} + +template< typename T, typename E > +constexpr bool operator>=( expected const & x, expected const & y ) +{ + return !(x < y); +} + +#endif + +// x.x.4.7 expected: comparison with T + +template< typename T1, typename E1, typename T2 + nsel_REQUIRES_T( + !std::is_void::value + ) +> +constexpr bool operator==( expected const & x, T2 const & v ) +{ + return bool(x) ? *x == v : false; +} + +template< typename T1, typename E1, typename T2 + nsel_REQUIRES_T( + !std::is_void::value + ) +> +constexpr bool operator==(T2 const & v, expected const & x ) +{ + return bool(x) ? v == *x : false; +} + +template< typename T1, typename E1, typename T2 > +constexpr bool operator!=( expected const & x, T2 const & v ) +{ + return bool(x) ? *x != v : true; +} + +template< typename T1, typename E1, typename T2 > +constexpr bool operator!=( T2 const & v, expected const & x ) +{ + return bool(x) ? v != *x : true; +} + +#if nsel_P0323R <= 2 + +template< typename T, typename E > +constexpr bool operator<( expected const & x, T const & v ) +{ + return bool(x) ? *x < v : true; +} + +template< typename T, typename E > +constexpr bool operator<( T const & v, expected const & x ) +{ + return bool(x) ? v < *x : false; +} + +template< typename T, typename E > +constexpr bool operator>( T const & v, expected const & x ) +{ + return bool(x) ? *x < v : false; +} + +template< typename T, typename E > +constexpr bool operator>( expected const & x, T const & v ) +{ + return bool(x) ? v < *x : false; +} + +template< typename T, typename E > +constexpr bool operator<=( T const & v, expected const & x ) +{ + return bool(x) ? ! ( *x < v ) : false; +} + +template< typename T, typename E > +constexpr bool operator<=( expected const & x, T const & v ) +{ + return bool(x) ? ! ( v < *x ) : true; +} + +template< typename T, typename E > +constexpr bool operator>=( expected const & x, T const & v ) +{ + return bool(x) ? ! ( *x < v ) : false; +} + +template< typename T, typename E > +constexpr bool operator>=( T const & v, expected const & x ) +{ + return bool(x) ? ! ( v < *x ) : true; +} + +#endif // nsel_P0323R + +// x.x.4.8 expected: comparison with unexpected_type + +template< typename T1, typename E1 , typename E2 > +constexpr bool operator==( expected const & x, unexpected_type const & u ) +{ + return (!x) ? x.get_unexpected() == u : false; +} + +template< typename T1, typename E1 , typename E2 > +constexpr bool operator==( unexpected_type const & u, expected const & x ) +{ + return ( x == u ); +} + +template< typename T1, typename E1 , typename E2 > +constexpr bool operator!=( expected const & x, unexpected_type const & u ) +{ + return ! ( x == u ); +} + +template< typename T1, typename E1 , typename E2 > +constexpr bool operator!=( unexpected_type const & u, expected const & x ) +{ + return ! ( x == u ); +} + +#if nsel_P0323R <= 2 + +template< typename T, typename E > +constexpr bool operator<( expected const & x, unexpected_type const & u ) +{ + return (!x) ? ( x.get_unexpected() < u ) : false; +} + +template< typename T, typename E > +constexpr bool operator<( unexpected_type const & u, expected const & x ) +{ + return (!x) ? ( u < x.get_unexpected() ) : true ; +} + +template< typename T, typename E > +constexpr bool operator>( expected const & x, unexpected_type const & u ) +{ + return ( u < x ); +} + +template< typename T, typename E > +constexpr bool operator>( unexpected_type const & u, expected const & x ) +{ + return ( x < u ); +} + +template< typename T, typename E > +constexpr bool operator<=( expected const & x, unexpected_type const & u ) +{ + return ! ( u < x ); +} + +template< typename T, typename E > +constexpr bool operator<=( unexpected_type const & u, expected const & x) +{ + return ! ( x < u ); +} + +template< typename T, typename E > +constexpr bool operator>=( expected const & x, unexpected_type const & u ) +{ + return ! ( u > x ); +} + +template< typename T, typename E > +constexpr bool operator>=( unexpected_type const & u, expected const & x ) +{ + return ! ( x > u ); +} + +#endif // nsel_P0323R + +/// x.x.x Specialized algorithms + +template< typename T, typename E + nsel_REQUIRES_T( + ( std::is_void::value || std::is_move_constructible::value ) + && std::is_move_constructible::value + && std17::is_swappable::value + && std17::is_swappable::value ) +> +void swap( expected & x, expected & y ) noexcept ( noexcept ( x.swap(y) ) ) +{ + x.swap( y ); +} + +#if nsel_P0323R <= 3 + +template< typename T > +constexpr auto make_expected( T && v ) -> expected< typename std::decay::type > +{ + return expected< typename std::decay::type >( std::forward( v ) ); +} + +// expected specialization: + +auto inline make_expected() -> expected +{ + return expected( in_place ); +} + +template< typename T > +constexpr auto make_expected_from_current_exception() -> expected +{ + return expected( make_unexpected_from_current_exception() ); +} + +template< typename T > +auto make_expected_from_exception( std::exception_ptr v ) -> expected +{ + return expected( unexpected_type( std::forward( v ) ) ); +} + +template< typename T, typename E > +constexpr auto make_expected_from_error( E e ) -> expected::type> +{ + return expected::type>( make_unexpected( e ) ); +} + +template< typename F + nsel_REQUIRES_T( ! std::is_same::type, void>::value ) +> +/*nsel_constexpr14*/ +auto make_expected_from_call( F f ) -> expected< typename std::result_of::type > +{ + try + { + return make_expected( f() ); + } + catch (...) + { + return make_unexpected_from_current_exception(); + } +} + +template< typename F + nsel_REQUIRES_T( std::is_same::type, void>::value ) +> +/*nsel_constexpr14*/ +auto make_expected_from_call( F f ) -> expected +{ + try + { + f(); + return make_expected(); + } + catch (...) + { + return make_unexpected_from_current_exception(); + } +} + +#endif // nsel_P0323R + +} // namespace expected_lite + +using namespace expected_lite; + +// using expected_lite::expected; +// using ... + +} // namespace nonstd + +namespace std { + +// expected: hash support + +template< typename T, typename E > +struct hash< nonstd::expected > +{ + using result_type = std::size_t; + using argument_type = nonstd::expected; + + constexpr result_type operator()(argument_type const & arg) const + { + return arg ? std::hash{}(*arg) : result_type{}; + } +}; + +// TBD - ?? remove? see spec. +template< typename T, typename E > +struct hash< nonstd::expected > +{ + using result_type = std::size_t; + using argument_type = nonstd::expected; + + constexpr result_type operator()(argument_type const & arg) const + { + return arg ? std::hash{}(*arg) : result_type{}; + } +}; + +// TBD - implement +// bool(e), hash>()(e) shall evaluate to the hashing true; +// otherwise it evaluates to an unspecified value if E is exception_ptr or +// a combination of hashing false and hash()(e.error()). + +template< typename E > +struct hash< nonstd::expected > +{ +}; + +} // namespace std + +namespace nonstd { + +// void unexpected() is deprecated && removed in C++17 + +#if nsel_CPP17_OR_GREATER || nsel_COMPILER_MSVC_VERSION > 141 +template< typename E > +using unexpected = unexpected_type; +#endif + +} // namespace nonstd + +#undef nsel_REQUIRES +#undef nsel_REQUIRES_0 +#undef nsel_REQUIRES_T + +nsel_RESTORE_WARNINGS() + +#endif // nsel_USES_STD_EXPECTED + +#endif // NONSTD_EXPECTED_LITE_HPP diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/allocators.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/allocators.h new file mode 100644 index 0000000..35650af --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/allocators.h @@ -0,0 +1,693 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ALLOCATORS_H_ +#define RAPIDJSON_ALLOCATORS_H_ + +#include "rapidjson.h" +#include "internal/meta.h" + +#include +#include + +#if RAPIDJSON_HAS_CXX11 +#include +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Allocator + +/*! \class rapidjson::Allocator + \brief Concept for allocating, resizing and freeing memory block. + + Note that Malloc() and Realloc() are non-static but Free() is static. + + So if an allocator need to support Free(), it needs to put its pointer in + the header of memory block. + +\code +concept Allocator { + static const bool kNeedFree; //!< Whether this allocator needs to call Free(). + + // Allocate a memory block. + // \param size of the memory block in bytes. + // \returns pointer to the memory block. + void* Malloc(size_t size); + + // Resize a memory block. + // \param originalPtr The pointer to current memory block. Null pointer is permitted. + // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) + // \param newSize the new size in bytes. + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // Free a memory block. + // \param pointer to the memory block. Null pointer is permitted. + static void Free(void *ptr); +}; +\endcode +*/ + + +/*! \def RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY + \ingroup RAPIDJSON_CONFIG + \brief User-defined kDefaultChunkCapacity definition. + + User can define this as any \c size that is a power of 2. +*/ + +#ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY +#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024) +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// CrtAllocator + +//! C-runtime library allocator. +/*! This class is just wrapper for standard C library memory routines. + \note implements Allocator concept +*/ +class CrtAllocator { +public: + static const bool kNeedFree = true; + void* Malloc(size_t size) { + if (size) // behavior of malloc(0) is implementation defined. + return RAPIDJSON_MALLOC(size); + else + return NULL; // standardize to returning NULL. + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + (void)originalSize; + if (newSize == 0) { + RAPIDJSON_FREE(originalPtr); + return NULL; + } + return RAPIDJSON_REALLOC(originalPtr, newSize); + } + static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); } + + bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT { + return true; + } + bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT { + return false; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// MemoryPoolAllocator + +//! Default memory allocator used by the parser and DOM. +/*! This allocator allocate memory blocks from pre-allocated memory chunks. + + It does not free memory blocks. And Realloc() only allocate new memory. + + The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. + + User may also supply a buffer as the first chunk. + + If the user-buffer is full then additional chunks are allocated by BaseAllocator. + + The user-buffer is not deallocated by this allocator. + + \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. + \note implements Allocator concept +*/ +template +class MemoryPoolAllocator { + //! Chunk header for perpending to each chunk. + /*! Chunks are stored as a singly linked list. + */ + struct ChunkHeader { + size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). + size_t size; //!< Current size of allocated memory in bytes. + ChunkHeader *next; //!< Next chunk in the linked list. + }; + + struct SharedData { + ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation. + BaseAllocator* ownBaseAllocator; //!< base allocator created by this object. + size_t refcount; + bool ownBuffer; + }; + + static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData)); + static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader)); + + static inline ChunkHeader *GetChunkHead(SharedData *shared) + { + return reinterpret_cast(reinterpret_cast(shared) + SIZEOF_SHARED_DATA); + } + static inline uint8_t *GetChunkBuffer(SharedData *shared) + { + return reinterpret_cast(shared->chunkHead) + SIZEOF_CHUNK_HEADER; + } + + static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity. + +public: + static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + static const bool kRefCounted = true; //!< Tell users that this allocator is reference counted on copy + + //! Constructor with chunkSize. + /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + explicit + MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunk_capacity_(chunkSize), + baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()), + shared_(static_cast(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0)) + { + RAPIDJSON_ASSERT(baseAllocator_ != 0); + RAPIDJSON_ASSERT(shared_ != 0); + if (baseAllocator) { + shared_->ownBaseAllocator = 0; + } + else { + shared_->ownBaseAllocator = baseAllocator_; + } + shared_->chunkHead = GetChunkHead(shared_); + shared_->chunkHead->capacity = 0; + shared_->chunkHead->size = 0; + shared_->chunkHead->next = 0; + shared_->ownBuffer = true; + shared_->refcount = 1; + } + + //! Constructor with user-supplied buffer. + /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. + + The user buffer will not be deallocated when this allocator is destructed. + + \param buffer User supplied buffer. + \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). + \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunk_capacity_(chunkSize), + baseAllocator_(baseAllocator), + shared_(static_cast(AlignBuffer(buffer, size))) + { + RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER); + shared_->chunkHead = GetChunkHead(shared_); + shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER; + shared_->chunkHead->size = 0; + shared_->chunkHead->next = 0; + shared_->ownBaseAllocator = 0; + shared_->ownBuffer = false; + shared_->refcount = 1; + } + + MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT : + chunk_capacity_(rhs.chunk_capacity_), + baseAllocator_(rhs.baseAllocator_), + shared_(rhs.shared_) + { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + ++shared_->refcount; + } + MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + ++rhs.shared_->refcount; + this->~MemoryPoolAllocator(); + baseAllocator_ = rhs.baseAllocator_; + chunk_capacity_ = rhs.chunk_capacity_; + shared_ = rhs.shared_; + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT : + chunk_capacity_(rhs.chunk_capacity_), + baseAllocator_(rhs.baseAllocator_), + shared_(rhs.shared_) + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + rhs.shared_ = 0; + } + MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + this->~MemoryPoolAllocator(); + baseAllocator_ = rhs.baseAllocator_; + chunk_capacity_ = rhs.chunk_capacity_; + shared_ = rhs.shared_; + rhs.shared_ = 0; + return *this; + } +#endif + + //! Destructor. + /*! This deallocates all memory chunks, excluding the user-supplied buffer. + */ + ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT { + if (!shared_) { + // do nothing if moved + return; + } + if (shared_->refcount > 1) { + --shared_->refcount; + return; + } + Clear(); + BaseAllocator *a = shared_->ownBaseAllocator; + if (shared_->ownBuffer) { + baseAllocator_->Free(shared_); + } + RAPIDJSON_DELETE(a); + } + + //! Deallocates all memory chunks, excluding the first/user one. + void Clear() RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + for (;;) { + ChunkHeader* c = shared_->chunkHead; + if (!c->next) { + break; + } + shared_->chunkHead = c->next; + baseAllocator_->Free(c); + } + shared_->chunkHead->size = 0; + } + + //! Computes the total capacity of allocated memory chunks. + /*! \return total capacity in bytes. + */ + size_t Capacity() const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + size_t capacity = 0; + for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next) + capacity += c->capacity; + return capacity; + } + + //! Computes the memory blocks allocated. + /*! \return total used bytes. + */ + size_t Size() const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + size_t size = 0; + for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next) + size += c->size; + return size; + } + + //! Whether the allocator is shared. + /*! \return true or false. + */ + bool Shared() const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + return shared_->refcount > 1; + } + + //! Allocates a memory block. (concept Allocator) + void* Malloc(size_t size) { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + if (!size) + return NULL; + + size = RAPIDJSON_ALIGN(size); + if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity)) + if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size)) + return NULL; + + void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size; + shared_->chunkHead->size += size; + return buffer; + } + + //! Resizes a memory block (concept Allocator) + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + if (originalPtr == 0) + return Malloc(newSize); + + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + if (newSize == 0) + return NULL; + + originalSize = RAPIDJSON_ALIGN(originalSize); + newSize = RAPIDJSON_ALIGN(newSize); + + // Do not shrink if new size is smaller than original + if (originalSize >= newSize) + return originalPtr; + + // Simply expand it if it is the last allocation and there is sufficient space + if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) { + size_t increment = static_cast(newSize - originalSize); + if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) { + shared_->chunkHead->size += increment; + return originalPtr; + } + } + + // Realloc process: allocate and copy memory, do not free original buffer. + if (void* newBuffer = Malloc(newSize)) { + if (originalSize) + std::memcpy(newBuffer, originalPtr, originalSize); + return newBuffer; + } + else + return NULL; + } + + //! Frees a memory block (concept Allocator) + static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing + + //! Compare (equality) with another MemoryPoolAllocator + bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + return shared_ == rhs.shared_; + } + //! Compare (inequality) with another MemoryPoolAllocator + bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT { + return !operator==(rhs); + } + +private: + //! Creates a new chunk. + /*! \param capacity Capacity of the chunk in bytes. + \return true if success. + */ + bool AddChunk(size_t capacity) { + if (!baseAllocator_) + shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)(); + if (ChunkHeader* chunk = static_cast(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) { + chunk->capacity = capacity; + chunk->size = 0; + chunk->next = shared_->chunkHead; + shared_->chunkHead = chunk; + return true; + } + else + return false; + } + + static inline void* AlignBuffer(void* buf, size_t &size) + { + RAPIDJSON_NOEXCEPT_ASSERT(buf != 0); + const uintptr_t mask = sizeof(void*) - 1; + const uintptr_t ubuf = reinterpret_cast(buf); + if (RAPIDJSON_UNLIKELY(ubuf & mask)) { + const uintptr_t abuf = (ubuf + mask) & ~mask; + RAPIDJSON_ASSERT(size >= abuf - ubuf); + buf = reinterpret_cast(abuf); + size -= abuf - ubuf; + } + return buf; + } + + size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. + BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. + SharedData *shared_; //!< The shared data of the allocator +}; + +namespace internal { + template + struct IsRefCounted : + public FalseType + { }; + template + struct IsRefCounted::Type> : + public TrueType + { }; +} + +template +inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n) +{ + RAPIDJSON_NOEXCEPT_ASSERT(old_n <= (std::numeric_limits::max)() / sizeof(T) && new_n <= (std::numeric_limits::max)() / sizeof(T)); + return static_cast(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T))); +} + +template +inline T *Malloc(A& a, size_t n = 1) +{ + return Realloc(a, NULL, 0, n); +} + +template +inline void Free(A& a, T *p, size_t n = 1) +{ + static_cast(Realloc(a, p, n, 0)); +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited +#endif + +template +class StdAllocator : + public std::allocator +{ + typedef std::allocator allocator_type; +#if RAPIDJSON_HAS_CXX11 + typedef std::allocator_traits traits_type; +#else + typedef allocator_type traits_type; +#endif + +public: + typedef BaseAllocator BaseAllocatorType; + + StdAllocator() RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_() + { } + + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + template + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(std::move(rhs)), + baseAllocator_(std::move(rhs.baseAllocator_)) + { } +#endif +#if RAPIDJSON_HAS_CXX11 + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_swap = std::true_type; +#endif + + /* implicit */ + StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_(allocator) + { } + + ~StdAllocator() RAPIDJSON_NOEXCEPT + { } + + template + struct rebind { + typedef StdAllocator other; + }; + + typedef typename traits_type::size_type size_type; + typedef typename traits_type::difference_type difference_type; + + typedef typename traits_type::value_type value_type; + typedef typename traits_type::pointer pointer; + typedef typename traits_type::const_pointer const_pointer; + +#if RAPIDJSON_HAS_CXX11 + + typedef typename std::add_lvalue_reference::type &reference; + typedef typename std::add_lvalue_reference::type>::type &const_reference; + + pointer address(reference r) const RAPIDJSON_NOEXCEPT + { + return std::addressof(r); + } + const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT + { + return std::addressof(r); + } + + size_type max_size() const RAPIDJSON_NOEXCEPT + { + return traits_type::max_size(*this); + } + + template + void construct(pointer p, Args&&... args) + { + traits_type::construct(*this, p, std::forward(args)...); + } + void destroy(pointer p) + { + traits_type::destroy(*this, p); + } + +#else // !RAPIDJSON_HAS_CXX11 + + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + + pointer address(reference r) const RAPIDJSON_NOEXCEPT + { + return allocator_type::address(r); + } + const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT + { + return allocator_type::address(r); + } + + size_type max_size() const RAPIDJSON_NOEXCEPT + { + return allocator_type::max_size(); + } + + void construct(pointer p, const_reference r) + { + allocator_type::construct(p, r); + } + void destroy(pointer p) + { + allocator_type::destroy(p); + } + +#endif // !RAPIDJSON_HAS_CXX11 + + template + U* allocate(size_type n = 1, const void* = 0) + { + return RAPIDJSON_NAMESPACE::Malloc(baseAllocator_, n); + } + template + void deallocate(U* p, size_type n = 1) + { + RAPIDJSON_NAMESPACE::Free(baseAllocator_, p, n); + } + + pointer allocate(size_type n = 1, const void* = 0) + { + return allocate(n); + } + void deallocate(pointer p, size_type n = 1) + { + deallocate(p, n); + } + +#if RAPIDJSON_HAS_CXX11 + using is_always_equal = std::is_empty; +#endif + + template + bool operator==(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT + { + return baseAllocator_ == rhs.baseAllocator_; + } + template + bool operator!=(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT + { + return !operator==(rhs); + } + + //! rapidjson Allocator concept + static const bool kNeedFree = BaseAllocator::kNeedFree; + static const bool kRefCounted = internal::IsRefCounted::Value; + void* Malloc(size_t size) + { + return baseAllocator_.Malloc(size); + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) + { + return baseAllocator_.Realloc(originalPtr, originalSize, newSize); + } + static void Free(void *ptr) RAPIDJSON_NOEXCEPT + { + BaseAllocator::Free(ptr); + } + +private: + template + friend class StdAllocator; // access to StdAllocator.* + + BaseAllocator baseAllocator_; +}; + +#if !RAPIDJSON_HAS_CXX17 // std::allocator deprecated in C++17 +template +class StdAllocator : + public std::allocator +{ + typedef std::allocator allocator_type; + +public: + typedef BaseAllocator BaseAllocatorType; + + StdAllocator() RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_() + { } + + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + template + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + /* implicit */ + StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_(baseAllocator) + { } + + ~StdAllocator() RAPIDJSON_NOEXCEPT + { } + + template + struct rebind { + typedef StdAllocator other; + }; + + typedef typename allocator_type::value_type value_type; + +private: + template + friend class StdAllocator; // access to StdAllocator.* + + BaseAllocator baseAllocator_; +}; +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/cursorstreamwrapper.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/cursorstreamwrapper.h new file mode 100644 index 0000000..fd6513d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/cursorstreamwrapper.h @@ -0,0 +1,78 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_ +#define RAPIDJSON_CURSORSTREAMWRAPPER_H_ + +#include "stream.h" + +#if defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4702) // unreachable code +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + + +//! Cursor stream wrapper for counting line and column number if error exists. +/*! + \tparam InputStream Any stream that implements Stream Concept +*/ +template > +class CursorStreamWrapper : public GenericStreamWrapper { +public: + typedef typename Encoding::Ch Ch; + + CursorStreamWrapper(InputStream& is): + GenericStreamWrapper(is), line_(1), col_(0) {} + + // counting line and column number + Ch Take() { + Ch ch = this->is_.Take(); + if(ch == '\n') { + line_ ++; + col_ = 0; + } else { + col_ ++; + } + return ch; + } + + //! Get the error line number, if error exists. + size_t GetLine() const { return line_; } + //! Get the error column number, if error exists. + size_t GetColumn() const { return col_; } + +private: + size_t line_; //!< Current Line + size_t col_; //!< Current Column +}; + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +RAPIDJSON_DIAG_POP +#endif + +#if defined(__GNUC__) +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/document.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/document.h new file mode 100644 index 0000000..2cd9a70 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/document.h @@ -0,0 +1,3043 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_DOCUMENT_H_ +#define RAPIDJSON_DOCUMENT_H_ + +/*! \file document.h */ + +#include "reader.h" +#include "internal/meta.h" +#include "internal/strfunc.h" +#include "memorystream.h" +#include "encodedstream.h" +#include // placement new +#include +#ifdef __cpp_lib_three_way_comparison +#include +#endif + +RAPIDJSON_DIAG_PUSH +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(c++98-compat) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_OFF(effc++) +#endif // __GNUC__ + +#ifdef GetObject +// see https://github.com/Tencent/rapidjson/issues/1448 +// a former included windows.h might have defined a macro called GetObject, which affects +// GetObject defined here. This ensures the macro does not get applied +#pragma push_macro("GetObject") +#define RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED +#undef GetObject +#endif + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS +#include // std::random_access_iterator_tag +#endif + +#if RAPIDJSON_USE_MEMBERSMAP +#include // std::multimap +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +// Forward declaration. +template +class GenericValue; + +template +class GenericDocument; + +/*! \def RAPIDJSON_DEFAULT_ALLOCATOR + \ingroup RAPIDJSON_CONFIG + \brief Allows to choose default allocator. + + User can define this to use CrtAllocator or MemoryPoolAllocator. +*/ +#ifndef RAPIDJSON_DEFAULT_ALLOCATOR +#define RAPIDJSON_DEFAULT_ALLOCATOR ::RAPIDJSON_NAMESPACE::MemoryPoolAllocator<::RAPIDJSON_NAMESPACE::CrtAllocator> +#endif + +/*! \def RAPIDJSON_DEFAULT_STACK_ALLOCATOR + \ingroup RAPIDJSON_CONFIG + \brief Allows to choose default stack allocator for Document. + + User can define this to use CrtAllocator or MemoryPoolAllocator. +*/ +#ifndef RAPIDJSON_DEFAULT_STACK_ALLOCATOR +#define RAPIDJSON_DEFAULT_STACK_ALLOCATOR ::RAPIDJSON_NAMESPACE::CrtAllocator +#endif + +/*! \def RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY + \ingroup RAPIDJSON_CONFIG + \brief User defined kDefaultObjectCapacity value. + + User can define this as any natural number. +*/ +#ifndef RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY +// number of objects that rapidjson::Value allocates memory for by default +#define RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY 16 +#endif + +/*! \def RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY + \ingroup RAPIDJSON_CONFIG + \brief User defined kDefaultArrayCapacity value. + + User can define this as any natural number. +*/ +#ifndef RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY +// number of array elements that rapidjson::Value allocates memory for by default +#define RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY 16 +#endif + +//! Name-value pair in a JSON object value. +/*! + This class was internal to GenericValue. It used to be a inner struct. + But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct. + https://code.google.com/p/rapidjson/issues/detail?id=64 +*/ +template +class GenericMember { +public: + GenericValue name; //!< name of member (must be a string) + GenericValue value; //!< value of member. + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericMember(GenericMember&& rhs) RAPIDJSON_NOEXCEPT + : name(std::move(rhs.name)), + value(std::move(rhs.value)) + { + } + + //! Move assignment in C++11 + GenericMember& operator=(GenericMember&& rhs) RAPIDJSON_NOEXCEPT { + return *this = static_cast(rhs); + } +#endif + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. Its name and value will become a null value after assignment. + */ + GenericMember& operator=(GenericMember& rhs) RAPIDJSON_NOEXCEPT { + if (RAPIDJSON_LIKELY(this != &rhs)) { + name = rhs.name; + value = rhs.value; + } + return *this; + } + + // swap() for std::sort() and other potential use in STL. + friend inline void swap(GenericMember& a, GenericMember& b) RAPIDJSON_NOEXCEPT { + a.name.Swap(b.name); + a.value.Swap(b.value); + } + +private: + //! Copy constructor is not permitted. + GenericMember(const GenericMember& rhs); +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericMemberIterator + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS + +//! (Constant) member iterator for a JSON object value +/*! + \tparam Const Is this a constant iterator? + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. + + This class implements a Random Access Iterator for GenericMember elements + of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements]. + + \note This iterator implementation is mainly intended to avoid implicit + conversions from iterator values to \c NULL, + e.g. from GenericValue::FindMember. + + \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a + pointer-based implementation, if your platform doesn't provide + the C++ header. + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ +template +class GenericMemberIterator { + + friend class GenericValue; + template friend class GenericMemberIterator; + + typedef GenericMember PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + +public: + //! Iterator type itself + typedef GenericMemberIterator Iterator; + //! Constant iterator type + typedef GenericMemberIterator ConstIterator; + //! Non-constant iterator type + typedef GenericMemberIterator NonConstIterator; + + /** \name std::iterator_traits support */ + //@{ + typedef ValueType value_type; + typedef ValueType * pointer; + typedef ValueType & reference; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; + //@} + + //! Pointer to (const) GenericMember + typedef pointer Pointer; + //! Reference to (const) GenericMember + typedef reference Reference; + //! Signed integer type (e.g. \c ptrdiff_t) + typedef difference_type DifferenceType; + + //! Default constructor (singular value) + /*! Creates an iterator pointing to no element. + \note All operations, except for comparisons, are undefined on such values. + */ + GenericMemberIterator() : ptr_() {} + + //! Iterator conversions to more const + /*! + \param it (Non-const) iterator to copy from + + Allows the creation of an iterator from another GenericMemberIterator + that is "less const". Especially, creating a non-constant iterator + from a constant iterator are disabled: + \li const -> non-const (not ok) + \li const -> const (ok) + \li non-const -> const (ok) + \li non-const -> non-const (ok) + + \note If the \c Const template parameter is already \c false, this + constructor effectively defines a regular copy-constructor. + Otherwise, the copy constructor is implicitly defined. + */ + GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} + Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; } + + //! @name stepping + //@{ + Iterator& operator++(){ ++ptr_; return *this; } + Iterator& operator--(){ --ptr_; return *this; } + Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } + Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } + //@} + + //! @name increment/decrement + //@{ + Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } + Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } + + Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; } + Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } + //@} + + //! @name relations + //@{ + template bool operator==(const GenericMemberIterator& that) const { return ptr_ == that.ptr_; } + template bool operator!=(const GenericMemberIterator& that) const { return ptr_ != that.ptr_; } + template bool operator<=(const GenericMemberIterator& that) const { return ptr_ <= that.ptr_; } + template bool operator>=(const GenericMemberIterator& that) const { return ptr_ >= that.ptr_; } + template bool operator< (const GenericMemberIterator& that) const { return ptr_ < that.ptr_; } + template bool operator> (const GenericMemberIterator& that) const { return ptr_ > that.ptr_; } + +#ifdef __cpp_lib_three_way_comparison + template std::strong_ordering operator<=>(const GenericMemberIterator& that) const { return ptr_ <=> that.ptr_; } +#endif + //@} + + //! @name dereference + //@{ + Reference operator*() const { return *ptr_; } + Pointer operator->() const { return ptr_; } + Reference operator[](DifferenceType n) const { return ptr_[n]; } + //@} + + //! Distance + DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; } + +private: + //! Internal constructor from plain pointer + explicit GenericMemberIterator(Pointer p) : ptr_(p) {} + + Pointer ptr_; //!< raw pointer +}; + +#else // RAPIDJSON_NOMEMBERITERATORCLASS + +// class-based member iterator implementation disabled, use plain pointers + +template +class GenericMemberIterator; + +//! non-const GenericMemberIterator +template +class GenericMemberIterator { +public: + //! use plain pointer as iterator type + typedef GenericMember* Iterator; +}; +//! const GenericMemberIterator +template +class GenericMemberIterator { +public: + //! use plain const pointer as iterator type + typedef const GenericMember* Iterator; +}; + +#endif // RAPIDJSON_NOMEMBERITERATORCLASS + +/////////////////////////////////////////////////////////////////////////////// +// GenericStringRef + +//! Reference to a constant string (not taking a copy) +/*! + \tparam CharType character type of the string + + This helper class is used to automatically infer constant string + references for string literals, especially from \c const \b (!) + character arrays. + + The main use is for creating JSON string values without copying the + source string via an \ref Allocator. This requires that the referenced + string pointers have a sufficient lifetime, which exceeds the lifetime + of the associated GenericValue. + + \b Example + \code + Value v("foo"); // ok, no need to copy & calculate length + const char foo[] = "foo"; + v.SetString(foo); // ok + + const char* bar = foo; + // Value x(bar); // not ok, can't rely on bar's lifetime + Value x(StringRef(bar)); // lifetime explicitly guaranteed by user + Value y(StringRef(bar, 3)); // ok, explicitly pass length + \endcode + + \see StringRef, GenericValue::SetString +*/ +template +struct GenericStringRef { + typedef CharType Ch; //!< character type of the string + + //! Create string reference from \c const character array +#ifndef __clang__ // -Wdocumentation + /*! + This constructor implicitly creates a constant string reference from + a \c const character array. It has better performance than + \ref StringRef(const CharType*) by inferring the string \ref length + from the array length, and also supports strings containing null + characters. + + \tparam N length of the string, automatically inferred + + \param str Constant character array, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note Constant complexity. + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ +#endif + template + GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT + : s(str), length(N-1) {} + + //! Explicitly create string reference from \c const character pointer +#ifndef __clang__ // -Wdocumentation + /*! + This constructor can be used to \b explicitly create a reference to + a constant string pointer. + + \see StringRef(const CharType*) + + \param str Constant character pointer, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ +#endif + explicit GenericStringRef(const CharType* str) + : s(str), length(NotNullStrLen(str)) {} + + //! Create constant string reference from pointer and length +#ifndef __clang__ // -Wdocumentation + /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param len length of the string, excluding the trailing NULL terminator + + \post \ref s == str && \ref length == len + \note Constant complexity. + */ +#endif + GenericStringRef(const CharType* str, SizeType len) + : s(RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { RAPIDJSON_ASSERT(str != 0 || len == 0u); } + + GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} + + //! implicit conversion to plain CharType pointer + operator const Ch *() const { return s; } + + const Ch* const s; //!< plain CharType pointer + const SizeType length; //!< length of the string (excluding the trailing NULL terminator) + +private: + SizeType NotNullStrLen(const CharType* str) { + RAPIDJSON_ASSERT(str != 0); + return internal::StrLen(str); + } + + /// Empty string - used when passing in a NULL pointer + static const Ch emptyString[]; + + //! Disallow construction from non-const array + template + GenericStringRef(CharType (&str)[N]) /* = delete */; + //! Copy assignment operator not permitted - immutable type + GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */; +}; + +template +const CharType GenericStringRef::emptyString[] = { CharType() }; + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + \tparam CharType Character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + + \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember +*/ +template +inline GenericStringRef StringRef(const CharType* str) { + return GenericStringRef(str); +} + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + This version has better performance with supplied length, and also + supports string containing null characters. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param length The length of source string. + \return GenericStringRef string reference object + \relatesalso GenericStringRef +*/ +template +inline GenericStringRef StringRef(const CharType* str, size_t length) { + return GenericStringRef(str, SizeType(length)); +} + +#if RAPIDJSON_HAS_STDSTRING +//! Mark a string object as constant string +/*! Mark a string object (e.g. \c std::string) as a "string literal". + This function can be used to avoid copying a string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. +*/ +template +inline GenericStringRef StringRef(const std::basic_string& str) { + return GenericStringRef(str.data(), SizeType(str.size())); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue type traits +namespace internal { + +template +struct IsGenericValueImpl : FalseType {}; + +// select candidates according to nested encoding and allocator types +template struct IsGenericValueImpl::Type, typename Void::Type> + : IsBaseOf, T>::Type {}; + +// helper to match arbitrary GenericValue instantiations, including derived classes +template struct IsGenericValue : IsGenericValueImpl::Type {}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// TypeHelper + +namespace internal { + +template +struct TypeHelper {}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsBool(); } + static bool Get(const ValueType& v) { return v.GetBool(); } + static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); } + static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt(); } + static int Get(const ValueType& v) { return v.GetInt(); } + static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); } + static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint(); } + static unsigned Get(const ValueType& v) { return v.GetUint(); } + static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); } + static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } +}; + +#ifdef _MSC_VER +RAPIDJSON_STATIC_ASSERT(sizeof(long) == sizeof(int)); +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt(); } + static long Get(const ValueType& v) { return v.GetInt(); } + static ValueType& Set(ValueType& v, long data) { return v.SetInt(data); } + static ValueType& Set(ValueType& v, long data, typename ValueType::AllocatorType&) { return v.SetInt(data); } +}; + +RAPIDJSON_STATIC_ASSERT(sizeof(unsigned long) == sizeof(unsigned)); +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint(); } + static unsigned long Get(const ValueType& v) { return v.GetUint(); } + static ValueType& Set(ValueType& v, unsigned long data) { return v.SetUint(data); } + static ValueType& Set(ValueType& v, unsigned long data, typename ValueType::AllocatorType&) { return v.SetUint(data); } +}; +#endif + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt64(); } + static int64_t Get(const ValueType& v) { return v.GetInt64(); } + static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); } + static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint64(); } + static uint64_t Get(const ValueType& v) { return v.GetUint64(); } + static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); } + static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsDouble(); } + static double Get(const ValueType& v) { return v.GetDouble(); } + static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); } + static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsFloat(); } + static float Get(const ValueType& v) { return v.GetFloat(); } + static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); } + static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); } +}; + +template +struct TypeHelper { + typedef const typename ValueType::Ch* StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return v.GetString(); } + static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); } + static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; + +#if RAPIDJSON_HAS_STDSTRING +template +struct TypeHelper > { + typedef std::basic_string StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); } + static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; +#endif + +template +struct TypeHelper { + typedef typename ValueType::Array ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(ValueType& v) { return v.GetArray(); } + static ValueType& Set(ValueType& v, ArrayType data) { return v = data; } + static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; } +}; + +template +struct TypeHelper { + typedef typename ValueType::ConstArray ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(const ValueType& v) { return v.GetArray(); } +}; + +template +struct TypeHelper { + typedef typename ValueType::Object ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(ValueType& v) { return v.GetObject(); } + static ValueType& Set(ValueType& v, ObjectType data) { return v = data; } + static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; } +}; + +template +struct TypeHelper { + typedef typename ValueType::ConstObject ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(const ValueType& v) { return v.GetObject(); } +}; + +} // namespace internal + +// Forward declarations +template class GenericArray; +template class GenericObject; + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue + +//! Represents a JSON value. Use Value for UTF8 encoding and default allocator. +/*! + A JSON value can be one of 7 types. This class is a variant type supporting + these types. + + Use the Value if UTF8 and default allocator + + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. +*/ +template +class GenericValue { +public: + //! Name-value pair in an object. + typedef GenericMember Member; + typedef Encoding EncodingType; //!< Encoding type from template parameter. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericStringRef StringRefType; //!< Reference to a constant string + typedef typename GenericMemberIterator::Iterator MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. + typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + typedef GenericValue ValueType; //!< Value type of itself. + typedef GenericArray Array; + typedef GenericArray ConstArray; + typedef GenericObject Object; + typedef GenericObject ConstObject; + + //!@name Constructors and destructor. + //@{ + + //! Default constructor creates a null value. + GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) { + rhs.data_.f.flags = kNullFlag; // give up contents + } +#endif + +private: + //! Copy constructor is not permitted. + GenericValue(const GenericValue& rhs); + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Moving from a GenericDocument is not permitted. + template + GenericValue(GenericDocument&& rhs); + + //! Move assignment from a GenericDocument is not permitted. + template + GenericValue& operator=(GenericDocument&& rhs); +#endif + +public: + + //! Constructor with JSON value type. + /*! This creates a Value of specified type with default content. + \param type Type of the value. + \note Default content for number is zero. + */ + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() { + static const uint16_t defaultFlags[] = { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, + kNumberAnyFlag + }; + RAPIDJSON_NOEXCEPT_ASSERT(type >= kNullType && type <= kNumberType); + data_.f.flags = defaultFlags[type]; + + // Use ShortString to store empty string. + if (type == kStringType) + data_.ss.SetLength(0); + } + + //! Explicit copy constructor (with allocator) + /*! Creates a copy of a Value by using the given Allocator + \tparam SourceAllocator allocator of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). + \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer) + \see CopyFrom() + */ + template + GenericValue(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings = false) { + switch (rhs.GetType()) { + case kObjectType: + DoCopyMembers(rhs, allocator, copyConstStrings); + break; + case kArrayType: { + SizeType count = rhs.data_.a.size; + GenericValue* le = reinterpret_cast(allocator.Malloc(count * sizeof(GenericValue))); + const GenericValue* re = rhs.GetElementsPointer(); + for (SizeType i = 0; i < count; i++) + new (&le[i]) GenericValue(re[i], allocator, copyConstStrings); + data_.f.flags = kArrayFlag; + data_.a.size = data_.a.capacity = count; + SetElementsPointer(le); + } + break; + case kStringType: + if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) { + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast(&rhs.data_); + } + else + SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); + break; + default: + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast(&rhs.data_); + break; + } + } + + //! Constructor for boolean value. + /*! \param b Boolean value + \note This constructor is limited to \em real boolean values and rejects + implicitly converted types like arbitrary pointers. Use an explicit cast + to \c bool, if you want to construct a boolean JSON value in such cases. + */ +#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen + template + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) RAPIDJSON_NOEXCEPT // See #472 +#else + explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT +#endif + : data_() { + // safe-guard against failing SFINAE + RAPIDJSON_STATIC_ASSERT((internal::IsSame::Value)); + data_.f.flags = b ? kTrueFlag : kFalseFlag; + } + + //! Constructor for int value. + explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() { + data_.n.i64 = i; + data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag; + } + + //! Constructor for unsigned value. + explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() { + data_.n.u64 = u; + data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag); + } + + //! Constructor for int64_t value. + explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() { + data_.n.i64 = i64; + data_.f.flags = kNumberInt64Flag; + if (i64 >= 0) { + data_.f.flags |= kNumberUint64Flag; + if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + else if (i64 >= static_cast(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + + //! Constructor for uint64_t value. + explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() { + data_.n.u64 = u64; + data_.f.flags = kNumberUint64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) + data_.f.flags |= kInt64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + + //! Constructor for double value. + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } + + //! Constructor for float value. + explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast(f); data_.f.flags = kNumberDoubleFlag; } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); } + + //! Constructor for constant string (i.e. do not make a copy of string) + explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor for copy-string from a string object (i.e. do make a copy of string) + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue(const std::basic_string& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } +#endif + + //! Constructor for Array. + /*! + \param a An array obtained by \c GetArray(). + \note \c Array is always pass-by-value. + \note the source array is moved into this value and the sourec array becomes empty. + */ + GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) { + a.value_.data_ = Data(); + a.value_.data_.f.flags = kArrayFlag; + } + + //! Constructor for Object. + /*! + \param o An object obtained by \c GetObject(). + \note \c Object is always pass-by-value. + \note the source object is moved into this value and the sourec object becomes empty. + */ + GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) { + o.value_.data_ = Data(); + o.value_.data_.f.flags = kObjectFlag; + } + + //! Destructor. + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() { + // With RAPIDJSON_USE_MEMBERSMAP, the maps need to be destroyed to release + // their Allocator if it's refcounted (e.g. MemoryPoolAllocator). + if (Allocator::kNeedFree || (RAPIDJSON_USE_MEMBERSMAP+0 && + internal::IsRefCounted::Value)) { + switch(data_.f.flags) { + case kArrayFlag: + { + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + Allocator::Free(e); + } + } + break; + + case kObjectFlag: + DoFreeMembers(); + break; + + case kCopyStringFlag: + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + Allocator::Free(const_cast(GetStringPointer())); + } + break; + + default: + break; // Do nothing for other types. + } + } + } + + //@} + + //!@name Assignment operators + //@{ + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. It will become a null value after assignment. + */ + GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + if (RAPIDJSON_LIKELY(this != &rhs)) { + // Can't destroy "this" before assigning "rhs", otherwise "rhs" + // could be used after free if it's an sub-Value of "this", + // hence the temporary danse. + GenericValue temp; + temp.RawAssign(rhs); + this->~GenericValue(); + RawAssign(temp); + } + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT { + return *this = rhs.Move(); + } +#endif + + //! Assignment of constant string reference (no copy) + /*! \param str Constant string reference to be assigned + \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. + \see GenericStringRef, operator=(T) + */ + GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT { + GenericValue s(str); + return *this = s; + } + + //! Assignment with primitive types. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value The value to be assigned. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref SetString(const Ch*, Allocator&) (for copying) or + \ref StringRef() (to explicitly mark the pointer as constant) instead. + All other pointer types would implicitly convert to \c bool, + use \ref SetBool() instead. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer), (GenericValue&)) + operator=(T value) { + GenericValue v(value); + return *this = v; + } + + //! Deep-copy assignment from Value + /*! Assigns a \b copy of the Value to the current Value object + \tparam SourceAllocator Allocator type of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying + \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer) + */ + template + GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings = false) { + RAPIDJSON_ASSERT(static_cast(this) != static_cast(&rhs)); + this->~GenericValue(); + new (this) GenericValue(rhs, allocator, copyConstStrings); + return *this; + } + + //! Exchange the contents of this value with those of other. + /*! + \param other Another value. + \note Constant complexity. + */ + GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { + GenericValue temp; + temp.RawAssign(*this); + RawAssign(other); + other.RawAssign(temp); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.value, b.value); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Prepare Value for move semantics + /*! \return *this */ + GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } + //@} + + //!@name Equal-to and not-equal-to operators + //@{ + //! Equal-to operator + /*! + \note If an object contains duplicated named member, comparing equality with any object is always \c false. + \note Complexity is quadratic in Object's member number and linear for the rest (number of all values in the subtree and total lengths of all strings). + */ + template + bool operator==(const GenericValue& rhs) const { + typedef GenericValue RhsType; + if (GetType() != rhs.GetType()) + return false; + + switch (GetType()) { + case kObjectType: // Warning: O(n^2) inner-loop + if (data_.o.size != rhs.data_.o.size) + return false; + for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { + typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); + if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) + return false; + } + return true; + + case kArrayType: + if (data_.a.size != rhs.data_.a.size) + return false; + for (SizeType i = 0; i < data_.a.size; i++) + if ((*this)[i] != rhs[i]) + return false; + return true; + + case kStringType: + return StringEqual(rhs); + + case kNumberType: + if (IsDouble() || rhs.IsDouble()) { + double a = GetDouble(); // May convert from integer to double. + double b = rhs.GetDouble(); // Ditto + return a >= b && a <= b; // Prevent -Wfloat-equal + } + else + return data_.n.u64 == rhs.data_.n.u64; + + default: + return true; + } + } + + //! Equal-to operator with const C-string pointer + bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); } + +#if RAPIDJSON_HAS_STDSTRING + //! Equal-to operator with string object + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + bool operator==(const std::basic_string& rhs) const { return *this == GenericValue(StringRef(rhs)); } +#endif + + //! Equal-to operator with primitive types + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr,internal::IsGenericValue >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } + +#ifndef __cpp_impl_three_way_comparison + //! Not-equal-to operator + /*! \return !(*this == rhs) + */ + template + bool operator!=(const GenericValue& rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with const C-string pointer + bool operator!=(const Ch* rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with arbitrary types + /*! \return !(*this == rhs) + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } + + //! Equal-to operator with arbitrary types (symmetric version) + /*! \return (rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } + + //! Not-Equal-to operator with arbitrary types (symmetric version) + /*! \return !(rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } + //@} +#endif + + //!@name Type + //@{ + + Type GetType() const { return static_cast(data_.f.flags & kTypeMask); } + bool IsNull() const { return data_.f.flags == kNullFlag; } + bool IsFalse() const { return data_.f.flags == kFalseFlag; } + bool IsTrue() const { return data_.f.flags == kTrueFlag; } + bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; } + bool IsObject() const { return data_.f.flags == kObjectFlag; } + bool IsArray() const { return data_.f.flags == kArrayFlag; } + bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; } + bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; } + bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; } + bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; } + bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; } + bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; } + bool IsString() const { return (data_.f.flags & kStringFlag) != 0; } + + // Checks whether a number can be losslessly converted to a double. + bool IsLosslessDouble() const { + if (!IsNumber()) return false; + if (IsUint64()) { + uint64_t u = GetUint64(); + volatile double d = static_cast(u); + return (d >= 0.0) + && (d < static_cast((std::numeric_limits::max)())) + && (u == static_cast(d)); + } + if (IsInt64()) { + int64_t i = GetInt64(); + volatile double d = static_cast(i); + return (d >= static_cast((std::numeric_limits::min)())) + && (d < static_cast((std::numeric_limits::max)())) + && (i == static_cast(d)); + } + return true; // double, int, uint are always lossless + } + + // Checks whether a number is a float (possible lossy). + bool IsFloat() const { + if ((data_.f.flags & kDoubleFlag) == 0) + return false; + double d = GetDouble(); + return d >= -3.4028234e38 && d <= 3.4028234e38; + } + // Checks whether a number can be losslessly converted to a float. + bool IsLosslessFloat() const { + if (!IsNumber()) return false; + double a = GetDouble(); + if (a < static_cast(-(std::numeric_limits::max)()) + || a > static_cast((std::numeric_limits::max)())) + return false; + double b = static_cast(static_cast(a)); + return a >= b && a <= b; // Prevent -Wfloat-equal + } + + //@} + + //!@name Null + //@{ + + GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } + + //@} + + //!@name Bool + //@{ + + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; } + //!< Set boolean value + /*! \post IsBool() == true */ + GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } + + //@} + + //!@name Object + //@{ + + //! Set this value as an empty object. + /*! \post IsObject() == true */ + GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } + + //! Get the number of members in the object. + SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } + + //! Get the capacity of object. + SizeType MemberCapacity() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.capacity; } + + //! Check whether the object is empty. + bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) + \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. + Since 0.2, if the name is not correct, it will assert. + If user is unsure whether a member exists, user should use HasMember() first. + A better approach is to use FindMember(). + \note Linear time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(GenericValue&)) operator[](T* name) { + GenericValue n(StringRef(name)); + return (*this)[n]; + } + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast(*this)[name]; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam SourceAllocator Allocator of the \c name value + + \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). + And it can also handle strings with embedded null characters. + + \note Linear time complexity. + */ + template + GenericValue& operator[](const GenericValue& name) { + MemberIterator member = FindMember(name); + if (member != MemberEnd()) + return member->value; + else { + RAPIDJSON_ASSERT(false); // see above note + +#if RAPIDJSON_HAS_CXX11 + // Use thread-local storage to prevent races between threads. + // Use static buffer and placement-new to prevent destruction, with + // alignas() to ensure proper alignment. + alignas(GenericValue) thread_local static char buffer[sizeof(GenericValue)]; + return *new (buffer) GenericValue(); +#elif defined(_MSC_VER) && _MSC_VER < 1900 + // There's no way to solve both thread locality and proper alignment + // simultaneously. + __declspec(thread) static char buffer[sizeof(GenericValue)]; + return *new (buffer) GenericValue(); +#elif defined(__GNUC__) || defined(__clang__) + // This will generate -Wexit-time-destructors in clang, but that's + // better than having under-alignment. + __thread static GenericValue buffer; + return buffer; +#else + // Don't know what compiler this is, so don't know how to ensure + // thread-locality. + static GenericValue buffer; + return buffer; +#endif + } + } + template + const GenericValue& operator[](const GenericValue& name) const { return const_cast(*this)[name]; } + +#if RAPIDJSON_HAS_STDSTRING + //! Get a value from an object associated with name (string object). + GenericValue& operator[](const std::basic_string& name) { return (*this)[GenericValue(StringRef(name))]; } + const GenericValue& operator[](const std::basic_string& name) const { return (*this)[GenericValue(StringRef(name))]; } +#endif + + //! Const member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); } + //! Const \em past-the-end member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); } + //! Member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); } + //! \em Past-the-end member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } + + //! Request the object to have enough capacity to store members. + /*! \param newCapacity The capacity that the object at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue& MemberReserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsObject()); + DoReserveMembers(newCapacity, allocator); + return *this; + } + + //! Check whether a member exists in the object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } + +#if RAPIDJSON_HAS_STDSTRING + //! Check whether a member exists in the object with string object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const std::basic_string& name) const { return FindMember(name) != MemberEnd(); } +#endif + + //! Check whether a member exists in the object with GenericValue name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + template + bool HasMember(const GenericValue& name) const { return FindMember(name) != MemberEnd(); } + + //! Find member by name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + MemberIterator FindMember(const Ch* name) { + GenericValue n(StringRef(name)); + return FindMember(n); + } + + ConstMemberIterator FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } + + //! Find member by name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + template + MemberIterator FindMember(const GenericValue& name) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + return DoFindMember(name); + } + template ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast(*this).FindMember(name); } + +#if RAPIDJSON_HAS_STDSTRING + //! Find member by string object name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + */ + MemberIterator FindMember(const std::basic_string& name) { return FindMember(GenericValue(StringRef(name))); } + ConstMemberIterator FindMember(const std::basic_string& name) const { return FindMember(GenericValue(StringRef(name))); } +#endif + + //! Add a member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c name and \c value will be transferred to this object on success. + \pre IsObject() && name.IsString() + \post name.IsNull() && value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + DoAddMember(name, value, allocator); + return *this; + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Add a string object as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, std::basic_string& value, Allocator& allocator) { + GenericValue v(value, allocator); + return AddMember(name, v, allocator); + } +#endif + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A string value as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + AddMember(GenericValue& name, T value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + + //! Add a member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this object on success. + \pre IsObject() + \post value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A constant string reference as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + AddMember(StringRefType name, T value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Remove all members in the object. + /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void RemoveAllMembers() { + RAPIDJSON_ASSERT(IsObject()); + DoClearMembers(); + } + + //! Remove a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Linear time complexity. + */ + bool RemoveMember(const Ch* name) { + GenericValue n(StringRef(name)); + return RemoveMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) { return RemoveMember(GenericValue(StringRef(name))); } +#endif + + template + bool RemoveMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + RemoveMember(m); + return true; + } + else + return false; + } + + //! Remove a member in object by iterator. + /*! \param m member iterator (obtained by FindMember() or MemberBegin()). + \return the new iterator after removal. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Constant time complexity. + */ + MemberIterator RemoveMember(MemberIterator m) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); + return DoRemoveMember(m); + } + + //! Remove a member from an object by iterator. + /*! \param pos iterator to the member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd() + \return Iterator following the removed element. + If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned. + \note This function preserves the relative order of the remaining object + members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator). + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator pos) { + return EraseMember(pos, pos +1); + } + + //! Remove members in the range [first, last) from an object. + /*! \param first iterator to the first member to remove + \param last iterator following the last member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() + \return Iterator following the last removed element. + \note This function preserves the relative order of the remaining object + members. + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(first >= MemberBegin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= MemberEnd()); + return DoEraseMembers(first, last); + } + + //! Erase a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note Linear time complexity. + */ + bool EraseMember(const Ch* name) { + GenericValue n(StringRef(name)); + return EraseMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string& name) { return EraseMember(GenericValue(StringRef(name))); } +#endif + + template + bool EraseMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + EraseMember(m); + return true; + } + else + return false; + } + + Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } + Object GetObj() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } + ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } + ConstObject GetObj() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } + + //@} + + //!@name Array + //@{ + + //! Set this value as an empty array. + /*! \post IsArray == true */ + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + + //! Get the number of elements in array. + SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } + + //! Get the capacity of array. + SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } + + //! Check whether the array is empty. + bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } + + //! Remove all elements in the array. + /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void Clear() { + RAPIDJSON_ASSERT(IsArray()); + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + data_.a.size = 0; + } + + //! Get an element from array by index. + /*! \pre IsArray() == true + \param index Zero-based index of element. + \see operator[](T*) + */ + GenericValue& operator[](SizeType index) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return GetElementsPointer()[index]; + } + const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } + + //! Element iterator + /*! \pre IsArray() == true */ + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); } + //! \em Past-the-end element iterator + /*! \pre IsArray() == true */ + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; } + //! Constant element iterator + /*! \pre IsArray() == true */ + ConstValueIterator Begin() const { return const_cast(*this).Begin(); } + //! Constant \em past-the-end element iterator + /*! \pre IsArray() == true */ + ConstValueIterator End() const { return const_cast(*this).End(); } + + //! Request the array to have enough capacity to store elements. + /*! \param newCapacity The capacity that the array at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (newCapacity > data_.a.capacity) { + SetElementsPointer(reinterpret_cast(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)))); + data_.a.capacity = newCapacity; + } + return *this; + } + + //! Append a GenericValue at the end of the array. + /*! \param value Value to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \post value.IsNull() == true + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this array on success. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + */ + GenericValue& PushBack(GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (data_.a.size >= data_.a.capacity) + Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); + GetElementsPointer()[data_.a.size++].RawAssign(value); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { + return PushBack(value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + //! Append a constant string reference at the end of the array. + /*! \param value Constant string reference to be appended. + \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + \see GenericStringRef + */ + GenericValue& PushBack(StringRefType value, Allocator& allocator) { + return (*this).template PushBack(value, allocator); + } + + //! Append a primitive value at the end of the array. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value Value of primitive type T to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref PushBack(GenericValue&, Allocator&) or \ref + PushBack(StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + PushBack(T value, Allocator& allocator) { + GenericValue v(value); + return PushBack(v, allocator); + } + + //! Remove the last element in the array. + /*! + \note Constant time complexity. + */ + GenericValue& PopBack() { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(!Empty()); + GetElementsPointer()[--data_.a.size].~GenericValue(); + return *this; + } + + //! Remove an element of array by iterator. + /*! + \param pos iterator to the element to remove + \pre IsArray() == true && \ref Begin() <= \c pos < \ref End() + \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator pos) { + return Erase(pos, pos + 1); + } + + //! Remove elements in the range [first, last) of the array. + /*! + \param first iterator to the first element to remove + \param last iterator following the last element to remove + \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End() + \return Iterator following the last removed element. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(data_.a.size > 0); + RAPIDJSON_ASSERT(GetElementsPointer() != 0); + RAPIDJSON_ASSERT(first >= Begin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= End()); + ValueIterator pos = Begin() + (first - Begin()); + for (ValueIterator itr = pos; itr != last; ++itr) + itr->~GenericValue(); + std::memmove(static_cast(pos), last, static_cast(End() - last) * sizeof(GenericValue)); + data_.a.size -= static_cast(last - first); + return pos; + } + + Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } + ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } + + //@} + + //!@name Number + //@{ + + int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; } + unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; } + int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; } + uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; } + + //! Get the value as double type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless. + */ + double GetDouble() const { + RAPIDJSON_ASSERT(IsNumber()); + if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. + if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double + if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double + if ((data_.f.flags & kInt64Flag) != 0) return static_cast(data_.n.i64); // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast(data_.n.u64); // uint64_t -> double (may lose precision) + } + + //! Get the value as float type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless. + */ + float GetFloat() const { + return static_cast(GetDouble()); + } + + GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } + GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } + GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } + GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } + GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } + GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(static_cast(f)); return *this; } + + //@} + + //!@name String + //@{ + + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return DataString(data_); } + + //! Get the length of string. + /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). + */ + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return DataStringLength(data_); } + + //! Set this value as a string without copying source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string pointer. + \param length The length of source string, excluding the trailing null terminator. + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == length + \see SetString(StringRefType) + */ + GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); } + + //! Set this value as a string without copying source string. + /*! \param s source string reference + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == s.length + */ + GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; } + + //! Set this value as a string by copying from source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string. + \param length The length of source string, excluding the trailing null terminator. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { return SetString(StringRef(s, length), allocator); } + + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(StringRef(s), allocator); } + + //! Set this value as a string by copying from source string. + /*! \param s source string reference + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(StringRefType s, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; } + +#if RAPIDJSON_HAS_STDSTRING + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue& SetString(const std::basic_string& s, Allocator& allocator) { return SetString(StringRef(s), allocator); } +#endif + + //@} + + //!@name Array + //@{ + + //! Templated version for checking whether this value is type T. + /*! + \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string + */ + template + bool Is() const { return internal::TypeHelper::Is(*this); } + + template + T Get() const { return internal::TypeHelper::Get(*this); } + + template + T Get() { return internal::TypeHelper::Get(*this); } + + template + ValueType& Set(const T& data) { return internal::TypeHelper::Set(*this, data); } + + template + ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper::Set(*this, data, allocator); } + + //@} + + //! Generate events of this value to a Handler. + /*! This function adopts the GoF visitor pattern. + Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. + It can also be used to deep clone this value via GenericDocument, which is also a Handler. + \tparam Handler type of handler. + \param handler An object implementing concept Handler. + */ + template + bool Accept(Handler& handler) const { + switch(GetType()) { + case kNullType: return handler.Null(); + case kFalseType: return handler.Bool(false); + case kTrueType: return handler.Bool(true); + + case kObjectType: + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) + return false; + for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { + RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. + if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0))) + return false; + if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler))) + return false; + } + return handler.EndObject(data_.o.size); + + case kArrayType: + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + return false; + for (ConstValueIterator v = Begin(); v != End(); ++v) + if (RAPIDJSON_UNLIKELY(!v->Accept(handler))) + return false; + return handler.EndArray(data_.a.size); + + case kStringType: + return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0); + + default: + RAPIDJSON_ASSERT(GetType() == kNumberType); + if (IsDouble()) return handler.Double(data_.n.d); + else if (IsInt()) return handler.Int(data_.n.i.i); + else if (IsUint()) return handler.Uint(data_.n.u.u); + else if (IsInt64()) return handler.Int64(data_.n.i64); + else return handler.Uint64(data_.n.u64); + } + } + +private: + template friend class GenericValue; + template friend class GenericDocument; + + enum { + kBoolFlag = 0x0008, + kNumberFlag = 0x0010, + kIntFlag = 0x0020, + kUintFlag = 0x0040, + kInt64Flag = 0x0080, + kUint64Flag = 0x0100, + kDoubleFlag = 0x0200, + kStringFlag = 0x0400, + kCopyFlag = 0x0800, + kInlineStrFlag = 0x1000, + + // Initial flags of different types. + kNullFlag = kNullType, + // These casts are added to suppress the warning on MSVC about bitwise operations between enums of different types. + kTrueFlag = static_cast(kTrueType) | static_cast(kBoolFlag), + kFalseFlag = static_cast(kFalseType) | static_cast(kBoolFlag), + kNumberIntFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kIntFlag | kInt64Flag), + kNumberUintFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag), + kNumberInt64Flag = static_cast(kNumberType) | static_cast(kNumberFlag | kInt64Flag), + kNumberUint64Flag = static_cast(kNumberType) | static_cast(kNumberFlag | kUint64Flag), + kNumberDoubleFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kDoubleFlag), + kNumberAnyFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag), + kConstStringFlag = static_cast(kStringType) | static_cast(kStringFlag), + kCopyStringFlag = static_cast(kStringType) | static_cast(kStringFlag | kCopyFlag), + kShortStringFlag = static_cast(kStringType) | static_cast(kStringFlag | kCopyFlag | kInlineStrFlag), + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, + + kTypeMask = 0x07 + }; + + static const SizeType kDefaultArrayCapacity = RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY; + static const SizeType kDefaultObjectCapacity = RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY; + + struct Flag { +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION + char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer +#elif RAPIDJSON_64BIT + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes +#else + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes +#endif + uint16_t flags; + }; + + struct String { + SizeType length; + SizeType hashcode; //!< reserved + const Ch* str; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars + // (excluding the terminating zero) and store a value to determine the length of the contained + // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string + // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as + // the string terminator as well. For getting the string length back from that value just use + // "MaxSize - str[LenPos]". + // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode, + // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings). + struct ShortString { + enum { MaxChars = sizeof(static_cast(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; + Ch str[MaxChars]; + + inline static bool Usable(SizeType len) { return (MaxSize >= len); } + inline void SetLength(SizeType len) { str[LenPos] = static_cast(MaxSize - len); } + inline SizeType GetLength() const { return static_cast(MaxSize - str[LenPos]); } + }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // By using proper binary layout, retrieval of different integer types do not need conversions. + union Number { +#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN + struct I { + int i; + char padding[4]; + }i; + struct U { + unsigned u; + char padding2[4]; + }u; +#else + struct I { + char padding[4]; + int i; + }i; + struct U { + char padding2[4]; + unsigned u; + }u; +#endif + int64_t i64; + uint64_t u64; + double d; + }; // 8 bytes + + struct ObjectData { + SizeType size; + SizeType capacity; + Member* members; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + struct ArrayData { + SizeType size; + SizeType capacity; + GenericValue* elements; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + union Data { + String s; + ShortString ss; + Number n; + ObjectData o; + ArrayData a; + Flag f; + }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION + + static RAPIDJSON_FORCEINLINE const Ch* DataString(const Data& data) { + return (data.f.flags & kInlineStrFlag) ? data.ss.str : RAPIDJSON_GETPOINTER(Ch, data.s.str); + } + static RAPIDJSON_FORCEINLINE SizeType DataStringLength(const Data& data) { + return (data.f.flags & kInlineStrFlag) ? data.ss.GetLength() : data.s.length; + } + + RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); } + RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); } + RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); } + RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); } + RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); } + RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); } + +#if RAPIDJSON_USE_MEMBERSMAP + + struct MapTraits { + struct Less { + bool operator()(const Data& s1, const Data& s2) const { + SizeType n1 = DataStringLength(s1), n2 = DataStringLength(s2); + int cmp = std::memcmp(DataString(s1), DataString(s2), sizeof(Ch) * (n1 < n2 ? n1 : n2)); + return cmp < 0 || (cmp == 0 && n1 < n2); + } + }; + typedef std::pair Pair; + typedef std::multimap > Map; + typedef typename Map::iterator Iterator; + }; + typedef typename MapTraits::Map Map; + typedef typename MapTraits::Less MapLess; + typedef typename MapTraits::Pair MapPair; + typedef typename MapTraits::Iterator MapIterator; + + // + // Layout of the members' map/array, re(al)located according to the needed capacity: + // + // {Map*}<>{capacity}<>{Member[capacity]}<>{MapIterator[capacity]} + // + // (where <> stands for the RAPIDJSON_ALIGN-ment, if needed) + // + + static RAPIDJSON_FORCEINLINE size_t GetMapLayoutSize(SizeType capacity) { + return RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType)) + + RAPIDJSON_ALIGN(capacity * sizeof(Member)) + + capacity * sizeof(MapIterator); + } + + static RAPIDJSON_FORCEINLINE SizeType &GetMapCapacity(Map* &map) { + return *reinterpret_cast(reinterpret_cast(&map) + + RAPIDJSON_ALIGN(sizeof(Map*))); + } + + static RAPIDJSON_FORCEINLINE Member* GetMapMembers(Map* &map) { + return reinterpret_cast(reinterpret_cast(&map) + + RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType))); + } + + static RAPIDJSON_FORCEINLINE MapIterator* GetMapIterators(Map* &map) { + return reinterpret_cast(reinterpret_cast(&map) + + RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType)) + + RAPIDJSON_ALIGN(GetMapCapacity(map) * sizeof(Member))); + } + + static RAPIDJSON_FORCEINLINE Map* &GetMap(Member* members) { + RAPIDJSON_ASSERT(members != 0); + return *reinterpret_cast(reinterpret_cast(members) - + RAPIDJSON_ALIGN(sizeof(SizeType)) - + RAPIDJSON_ALIGN(sizeof(Map*))); + } + + // Some compilers' debug mechanisms want all iterators to be destroyed, for their accounting.. + RAPIDJSON_FORCEINLINE MapIterator DropMapIterator(MapIterator& rhs) { +#if RAPIDJSON_HAS_CXX11 + MapIterator ret = std::move(rhs); +#else + MapIterator ret = rhs; +#endif + rhs.~MapIterator(); + return ret; + } + + Map* &DoReallocMap(Map** oldMap, SizeType newCapacity, Allocator& allocator) { + Map **newMap = static_cast(allocator.Malloc(GetMapLayoutSize(newCapacity))); + GetMapCapacity(*newMap) = newCapacity; + if (!oldMap) { + *newMap = new (allocator.Malloc(sizeof(Map))) Map(MapLess(), allocator); + } + else { + *newMap = *oldMap; + size_t count = (*oldMap)->size(); + std::memcpy(static_cast(GetMapMembers(*newMap)), + static_cast(GetMapMembers(*oldMap)), + count * sizeof(Member)); + MapIterator *oldIt = GetMapIterators(*oldMap), + *newIt = GetMapIterators(*newMap); + while (count--) { + new (&newIt[count]) MapIterator(DropMapIterator(oldIt[count])); + } + Allocator::Free(oldMap); + } + return *newMap; + } + + RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) { + return GetMapMembers(DoReallocMap(0, capacity, allocator)); + } + + void DoReserveMembers(SizeType newCapacity, Allocator& allocator) { + ObjectData& o = data_.o; + if (newCapacity > o.capacity) { + Member* oldMembers = GetMembersPointer(); + Map **oldMap = oldMembers ? &GetMap(oldMembers) : 0, + *&newMap = DoReallocMap(oldMap, newCapacity, allocator); + RAPIDJSON_SETPOINTER(Member, o.members, GetMapMembers(newMap)); + o.capacity = newCapacity; + } + } + + template + MemberIterator DoFindMember(const GenericValue& name) { + if (Member* members = GetMembersPointer()) { + Map* &map = GetMap(members); + MapIterator mit = map->find(reinterpret_cast(name.data_)); + if (mit != map->end()) { + return MemberIterator(&members[mit->second]); + } + } + return MemberEnd(); + } + + void DoClearMembers() { + if (Member* members = GetMembersPointer()) { + Map* &map = GetMap(members); + MapIterator* mit = GetMapIterators(map); + for (SizeType i = 0; i < data_.o.size; i++) { + map->erase(DropMapIterator(mit[i])); + members[i].~Member(); + } + data_.o.size = 0; + } + } + + void DoFreeMembers() { + if (Member* members = GetMembersPointer()) { + GetMap(members)->~Map(); + for (SizeType i = 0; i < data_.o.size; i++) { + members[i].~Member(); + } + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + Map** map = &GetMap(members); + Allocator::Free(*map); + Allocator::Free(map); + } + } + } + +#else // !RAPIDJSON_USE_MEMBERSMAP + + RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) { + return Malloc(allocator, capacity); + } + + void DoReserveMembers(SizeType newCapacity, Allocator& allocator) { + ObjectData& o = data_.o; + if (newCapacity > o.capacity) { + Member* newMembers = Realloc(allocator, GetMembersPointer(), o.capacity, newCapacity); + RAPIDJSON_SETPOINTER(Member, o.members, newMembers); + o.capacity = newCapacity; + } + } + + template + MemberIterator DoFindMember(const GenericValue& name) { + MemberIterator member = MemberBegin(); + for ( ; member != MemberEnd(); ++member) + if (name.StringEqual(member->name)) + break; + return member; + } + + void DoClearMembers() { + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + data_.o.size = 0; + } + + void DoFreeMembers() { + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + Allocator::Free(GetMembersPointer()); + } + +#endif // !RAPIDJSON_USE_MEMBERSMAP + + void DoAddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + ObjectData& o = data_.o; + if (o.size >= o.capacity) + DoReserveMembers(o.capacity ? (o.capacity + (o.capacity + 1) / 2) : kDefaultObjectCapacity, allocator); + Member* members = GetMembersPointer(); + Member* m = members + o.size; + m->name.RawAssign(name); + m->value.RawAssign(value); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(members); + MapIterator* mit = GetMapIterators(map); + new (&mit[o.size]) MapIterator(map->insert(MapPair(m->name.data_, o.size))); +#endif + ++o.size; + } + + MemberIterator DoRemoveMember(MemberIterator m) { + ObjectData& o = data_.o; + Member* members = GetMembersPointer(); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(members); + MapIterator* mit = GetMapIterators(map); + SizeType mpos = static_cast(&*m - members); + map->erase(DropMapIterator(mit[mpos])); +#endif + MemberIterator last(members + (o.size - 1)); + if (o.size > 1 && m != last) { +#if RAPIDJSON_USE_MEMBERSMAP + new (&mit[mpos]) MapIterator(DropMapIterator(mit[&*last - members])); + mit[mpos]->second = mpos; +#endif + *m = *last; // Move the last one to this place + } + else { + m->~Member(); // Only one left, just destroy + } + --o.size; + return m; + } + + MemberIterator DoEraseMembers(ConstMemberIterator first, ConstMemberIterator last) { + ObjectData& o = data_.o; + MemberIterator beg = MemberBegin(), + pos = beg + (first - beg), + end = MemberEnd(); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(GetMembersPointer()); + MapIterator* mit = GetMapIterators(map); +#endif + for (MemberIterator itr = pos; itr != last; ++itr) { +#if RAPIDJSON_USE_MEMBERSMAP + map->erase(DropMapIterator(mit[itr - beg])); +#endif + itr->~Member(); + } +#if RAPIDJSON_USE_MEMBERSMAP + if (first != last) { + // Move remaining members/iterators + MemberIterator next = pos + (last - first); + for (MemberIterator itr = pos; next != end; ++itr, ++next) { + std::memcpy(static_cast(&*itr), &*next, sizeof(Member)); + SizeType mpos = static_cast(itr - beg); + new (&mit[mpos]) MapIterator(DropMapIterator(mit[next - beg])); + mit[mpos]->second = mpos; + } + } +#else + std::memmove(static_cast(&*pos), &*last, + static_cast(end - last) * sizeof(Member)); +#endif + o.size -= static_cast(last - first); + return pos; + } + + template + void DoCopyMembers(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings) { + RAPIDJSON_ASSERT(rhs.GetType() == kObjectType); + + data_.f.flags = kObjectFlag; + SizeType count = rhs.data_.o.size; + Member* lm = DoAllocMembers(count, allocator); + const typename GenericValue::Member* rm = rhs.GetMembersPointer(); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(lm); + MapIterator* mit = GetMapIterators(map); +#endif + for (SizeType i = 0; i < count; i++) { + new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings); + new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings); +#if RAPIDJSON_USE_MEMBERSMAP + new (&mit[i]) MapIterator(map->insert(MapPair(lm[i].name.data_, i))); +#endif + } + data_.o.size = data_.o.capacity = count; + SetMembersPointer(lm); + } + + // Initialize this value as array with initial data, without calling destructor. + void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { + data_.f.flags = kArrayFlag; + if (count) { + GenericValue* e = static_cast(allocator.Malloc(count * sizeof(GenericValue))); + SetElementsPointer(e); + std::memcpy(static_cast(e), values, count * sizeof(GenericValue)); + } + else + SetElementsPointer(0); + data_.a.size = data_.a.capacity = count; + } + + //! Initialize this value as object with initial data, without calling destructor. + void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { + data_.f.flags = kObjectFlag; + if (count) { + Member* m = DoAllocMembers(count, allocator); + SetMembersPointer(m); + std::memcpy(static_cast(m), members, count * sizeof(Member)); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(m); + MapIterator* mit = GetMapIterators(map); + for (SizeType i = 0; i < count; i++) { + new (&mit[i]) MapIterator(map->insert(MapPair(m[i].name.data_, i))); + } +#endif + } + else + SetMembersPointer(0); + data_.o.size = data_.o.capacity = count; + } + + //! Initialize this value as constant string, without calling destructor. + void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { + data_.f.flags = kConstStringFlag; + SetStringPointer(s); + data_.s.length = s.length; + } + + //! Initialize this value as copy string with initial data, without calling destructor. + void SetStringRaw(StringRefType s, Allocator& allocator) { + Ch* str = 0; + if (ShortString::Usable(s.length)) { + data_.f.flags = kShortStringFlag; + data_.ss.SetLength(s.length); + str = data_.ss.str; + } else { + data_.f.flags = kCopyStringFlag; + data_.s.length = s.length; + str = static_cast(allocator.Malloc((s.length + 1) * sizeof(Ch))); + SetStringPointer(str); + } + std::memcpy(str, s, s.length * sizeof(Ch)); + str[s.length] = '\0'; + } + + //! Assignment without calling destructor + void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + data_ = rhs.data_; + // data_.f.flags = rhs.data_.f.flags; + rhs.data_.f.flags = kNullFlag; + } + + template + bool StringEqual(const GenericValue& rhs) const { + RAPIDJSON_ASSERT(IsString()); + RAPIDJSON_ASSERT(rhs.IsString()); + + const SizeType len1 = GetStringLength(); + const SizeType len2 = rhs.GetStringLength(); + if(len1 != len2) { return false; } + + const Ch* const str1 = GetString(); + const Ch* const str2 = rhs.GetString(); + if(str1 == str2) { return true; } // fast path for constant string + + return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); + } + + Data data_; +}; + +//! GenericValue with UTF8 encoding +typedef GenericValue > Value; + +/////////////////////////////////////////////////////////////////////////////// +// GenericDocument + +//! A document for parsing JSON text as DOM. +/*! + \note implements Handler concept + \tparam Encoding Encoding for both parsing and string storage. + \tparam Allocator Allocator for allocating memory for the DOM + \tparam StackAllocator Allocator for allocating memory for stack during parsing. + \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue. +*/ +template +class GenericDocument : public GenericValue { +public: + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue ValueType; //!< Value type of the document. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef StackAllocator StackAllocatorType; //!< StackAllocator type from template parameter. + + //! Constructor + /*! Creates an empty document of specified type. + \param type Mandatory type of object to create. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + GenericValue(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + } + + //! Constructor + /*! Creates an empty document which type is Null. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + : ValueType(std::forward(rhs)), // explicit cast to avoid prohibited move from Document + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(std::move(rhs.stack_)), + parseResult_(rhs.parseResult_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + } +#endif + + ~GenericDocument() { + // Clear the ::ValueType before ownAllocator is destroyed, ~ValueType() + // runs last and may access its elements or members which would be freed + // with an allocator like MemoryPoolAllocator (CrtAllocator does not + // free its data when destroyed, but MemoryPoolAllocator does). + if (ownAllocator_) { + ValueType::SetNull(); + } + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + { + // The cast to ValueType is necessary here, because otherwise it would + // attempt to call GenericValue's templated assignment operator. + ValueType::operator=(std::forward(rhs)); + + // Calling the destructor here would prematurely call stack_'s destructor + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = std::move(rhs.stack_); + parseResult_ = rhs.parseResult_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + + return *this; + } +#endif + + //! Exchange the contents of this document with those of another. + /*! + \param rhs Another document. + \note Constant complexity. + \see GenericValue::Swap + */ + GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { + ValueType::Swap(rhs); + stack_.Swap(rhs.stack_); + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(parseResult_, rhs.parseResult_); + return *this; + } + + // Allow Swap with ValueType. + // Refer to Effective C++ 3rd Edition/Item 33: Avoid hiding inherited names. + using ValueType::Swap; + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.doc, b.doc); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Populate this document by a generator which produces SAX events. + /*! \tparam Generator A functor with bool f(Handler) prototype. + \param g Generator functor which sends SAX events to the parameter. + \return The document itself for fluent API. + */ + template + GenericDocument& Populate(Generator& g) { + ClearStackOnExit scope(*this); + if (g(*this)) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } + return *this; + } + + //!@name Parse from stream + //!@{ + + //! Parse JSON text from an input stream (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Encoding of input stream + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + GenericReader reader( + stack_.HasAllocator() ? &stack_.GetAllocator() : 0); + ClearStackOnExit scope(*this); + parseResult_ = reader.template Parse(is, *this); + if (parseResult_) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } + return *this; + } + + //! Parse JSON text from an input stream + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); + } + + //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); + } + //!@} + + //!@name Parse in-place from mutable string + //!@{ + + //! Parse JSON text from a mutable string + /*! \tparam parseFlags Combination of \ref ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseInsitu(Ch* str) { + GenericInsituStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) + /*! \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + GenericDocument& ParseInsitu(Ch* str) { + return ParseInsitu(str); + } + //!@} + + //!@name Parse from read-only string + //!@{ + + //! Parse JSON text from a read-only string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \tparam SourceEncoding Transcoding from input Encoding + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const typename SourceEncoding::Ch* str) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a read-only string + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const Ch* str) { + return Parse(str); + } + + //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) + /*! \param str Read-only zero-terminated string to be parsed. + */ + GenericDocument& Parse(const Ch* str) { + return Parse(str); + } + + template + GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + MemoryStream ms(reinterpret_cast(str), length * sizeof(typename SourceEncoding::Ch)); + EncodedInputStream is(ms); + ParseStream(is); + return *this; + } + + template + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse(str, length); + } + + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + template + GenericDocument& Parse(const std::basic_string& str) { + // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t) + return Parse(str.c_str()); + } + + template + GenericDocument& Parse(const std::basic_string& str) { + return Parse(str.c_str()); + } + + GenericDocument& Parse(const std::basic_string& str) { + return Parse(str); + } +#endif // RAPIDJSON_HAS_STDSTRING + + //!@} + + //!@name Handling parse errors + //!@{ + + //! Whether a parse error has occurred in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseError() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + + //! Implicit conversion to get the last parse result +#ifndef __clang // -Wdocumentation + /*! \return \ref ParseResult of the last parse operation + + \code + Document doc; + ParseResult ok = doc.Parse(json); + if (!ok) + printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset()); + \endcode + */ +#endif + operator ParseResult() const { return parseResult_; } + //!@} + + //! Get the allocator of this document. + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + //! Get the capacity of stack in bytes. + size_t GetStackCapacity() const { return stack_.GetCapacity(); } + +private: + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} + ~ClearStackOnExit() { d_.ClearStack(); } + private: + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + GenericDocument& d_; + }; + + // callers of the following private Handler functions + // template friend class GenericReader; // for parsing + template friend class GenericValue; // for deep copying + +public: + // Implementation of Handler + bool Null() { new (stack_.template Push()) ValueType(); return true; } + bool Bool(bool b) { new (stack_.template Push()) ValueType(b); return true; } + bool Int(int i) { new (stack_.template Push()) ValueType(i); return true; } + bool Uint(unsigned i) { new (stack_.template Push()) ValueType(i); return true; } + bool Int64(int64_t i) { new (stack_.template Push()) ValueType(i); return true; } + bool Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); return true; } + bool Double(double d) { new (stack_.template Push()) ValueType(d); return true; } + + bool RawNumber(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + return true; + } + + bool String(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + return true; + } + + bool StartObject() { new (stack_.template Push()) ValueType(kObjectType); return true; } + + bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount) { + typename ValueType::Member* members = stack_.template Pop(memberCount); + stack_.template Top()->SetObjectRaw(members, memberCount, GetAllocator()); + return true; + } + + bool StartArray() { new (stack_.template Push()) ValueType(kArrayType); return true; } + + bool EndArray(SizeType elementCount) { + ValueType* elements = stack_.template Pop(elementCount); + stack_.template Top()->SetArrayRaw(elements, elementCount, GetAllocator()); + return true; + } + +private: + //! Prohibit copying + GenericDocument(const GenericDocument&); + //! Prohibit assignment + GenericDocument& operator=(const GenericDocument&); + + void ClearStack() { + if (Allocator::kNeedFree) + while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) + (stack_.template Pop(1))->~ValueType(); + else + stack_.Clear(); + stack_.ShrinkToFit(); + } + + void Destroy() { + RAPIDJSON_DELETE(ownAllocator_); + } + + static const size_t kDefaultStackCapacity = 1024; + Allocator* allocator_; + Allocator* ownAllocator_; + internal::Stack stack_; + ParseResult parseResult_; +}; + +//! GenericDocument with UTF8 encoding +typedef GenericDocument > Document; + + +//! Helper class for accessing Value of array type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetArray(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template +class GenericArray { +public: + typedef GenericArray ConstArray; + typedef GenericArray Array; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef ValueType* ValueIterator; // This may be const or non-const iterator + typedef const ValueT* ConstValueIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + + template + friend class GenericValue; + + GenericArray(const GenericArray& rhs) : value_(rhs.value_) {} + GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; } + ~GenericArray() {} + + operator ValueType&() const { return value_; } + SizeType Size() const { return value_.Size(); } + SizeType Capacity() const { return value_.Capacity(); } + bool Empty() const { return value_.Empty(); } + void Clear() const { value_.Clear(); } + ValueType& operator[](SizeType index) const { return value_[index]; } + ValueIterator Begin() const { return value_.Begin(); } + ValueIterator End() const { return value_.End(); } + GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; } + GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + GenericArray PopBack() const { value_.PopBack(); return *this; } + ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); } + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + ValueIterator begin() const { return value_.Begin(); } + ValueIterator end() const { return value_.End(); } +#endif + +private: + GenericArray(); + GenericArray(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +//! Helper class for accessing Value of object type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetObject(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template +class GenericObject { +public: + typedef GenericObject ConstObject; + typedef GenericObject Object; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef GenericMemberIterator MemberIterator; // This may be const or non-const iterator + typedef GenericMemberIterator ConstMemberIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename ValueType::Ch Ch; + + template + friend class GenericValue; + + GenericObject(const GenericObject& rhs) : value_(rhs.value_) {} + GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; } + ~GenericObject() {} + + operator ValueType&() const { return value_; } + SizeType MemberCount() const { return value_.MemberCount(); } + SizeType MemberCapacity() const { return value_.MemberCapacity(); } + bool ObjectEmpty() const { return value_.ObjectEmpty(); } + template ValueType& operator[](T* name) const { return value_[name]; } + template ValueType& operator[](const GenericValue& name) const { return value_[name]; } +#if RAPIDJSON_HAS_STDSTRING + ValueType& operator[](const std::basic_string& name) const { return value_[name]; } +#endif + MemberIterator MemberBegin() const { return value_.MemberBegin(); } + MemberIterator MemberEnd() const { return value_.MemberEnd(); } + GenericObject MemberReserve(SizeType newCapacity, AllocatorType &allocator) const { value_.MemberReserve(newCapacity, allocator); return *this; } + bool HasMember(const Ch* name) const { return value_.HasMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool HasMember(const std::basic_string& name) const { return value_.HasMember(name); } +#endif + template bool HasMember(const GenericValue& name) const { return value_.HasMember(name); } + MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); } + template MemberIterator FindMember(const GenericValue& name) const { return value_.FindMember(name); } +#if RAPIDJSON_HAS_STDSTRING + MemberIterator FindMember(const std::basic_string& name) const { return value_.FindMember(name); } +#endif + GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_STDSTRING + GenericObject AddMember(ValueType& name, std::basic_string& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + void RemoveAllMembers() { value_.RemoveAllMembers(); } + bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) const { return value_.RemoveMember(name); } +#endif + template bool RemoveMember(const GenericValue& name) const { return value_.RemoveMember(name); } + MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); } + MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); } + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); } + bool EraseMember(const Ch* name) const { return value_.EraseMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string& name) const { return EraseMember(ValueType(StringRef(name))); } +#endif + template bool EraseMember(const GenericValue& name) const { return value_.EraseMember(name); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + MemberIterator begin() const { return value_.MemberBegin(); } + MemberIterator end() const { return value_.MemberEnd(); } +#endif + +private: + GenericObject(); + GenericObject(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +RAPIDJSON_NAMESPACE_END +RAPIDJSON_DIAG_POP + +#ifdef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED +#pragma pop_macro("GetObject") +#undef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED +#endif + +#endif // RAPIDJSON_DOCUMENT_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/encodedstream.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/encodedstream.h new file mode 100644 index 0000000..cf046b8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/encodedstream.h @@ -0,0 +1,299 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ENCODEDSTREAM_H_ +#define RAPIDJSON_ENCODEDSTREAM_H_ + +#include "stream.h" +#include "memorystream.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Input byte stream wrapper with a statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam InputByteStream Type of input byte stream. For example, FileReadStream. +*/ +template +class EncodedInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedInputStream(InputByteStream& is) : is_(is) { + current_ = Encoding::TakeBOM(is_); + } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); + + InputByteStream& is_; + Ch current_; +}; + +//! Specialized for UTF8 MemoryStream. +template <> +class EncodedInputStream, MemoryStream> { +public: + typedef UTF8<>::Ch Ch; + + EncodedInputStream(MemoryStream& is) : is_(is) { + if (static_cast(is_.Peek()) == 0xEFu) is_.Take(); + if (static_cast(is_.Peek()) == 0xBBu) is_.Take(); + if (static_cast(is_.Peek()) == 0xBFu) is_.Take(); + } + Ch Peek() const { return is_.Peek(); } + Ch Take() { return is_.Take(); } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) {} + void Flush() {} + Ch* PutBegin() { return 0; } + size_t PutEnd(Ch*) { return 0; } + + MemoryStream& is_; + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); +}; + +//! Output byte stream wrapper with statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream. +*/ +template +class EncodedOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { + if (putBOM) + Encoding::PutBOM(os_); + } + + void Put(Ch c) { Encoding::Put(os_, c); } + void Flush() { os_.Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedOutputStream(const EncodedOutputStream&); + EncodedOutputStream& operator=(const EncodedOutputStream&); + + OutputByteStream& os_; +}; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + +//! Input stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for reading. + \tparam InputByteStream type of input byte stream to be wrapped. +*/ +template +class AutoUTFInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param is input stream to be wrapped. + \param type UTF encoding type if it is not detected from the stream. + */ + AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + DetectType(); + static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; + takeFunc_ = f[type_]; + current_ = takeFunc_(*is_); + } + + UTFType GetType() const { return type_; } + bool HasBOM() const { return hasBOM_; } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } + size_t Tell() const { return is_->Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFInputStream(const AutoUTFInputStream&); + AutoUTFInputStream& operator=(const AutoUTFInputStream&); + + // Detect encoding type with BOM or RFC 4627 + void DetectType() { + // BOM (Byte Order Mark): + // 00 00 FE FF UTF-32BE + // FF FE 00 00 UTF-32LE + // FE FF UTF-16BE + // FF FE UTF-16LE + // EF BB BF UTF-8 + + const unsigned char* c = reinterpret_cast(is_->Peek4()); + if (!c) + return; + + unsigned bom = static_cast(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)); + hasBOM_ = false; + if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); } + + // RFC 4627: Section 3 + // "Since the first two characters of a JSON text will always be ASCII + // characters [RFC0020], it is possible to determine whether an octet + // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking + // at the pattern of nulls in the first four octets." + // 00 00 00 xx UTF-32BE + // 00 xx 00 xx UTF-16BE + // xx 00 00 00 UTF-32LE + // xx 00 xx 00 UTF-16LE + // xx xx xx xx UTF-8 + + if (!hasBOM_) { + int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); + switch (pattern) { + case 0x08: type_ = kUTF32BE; break; + case 0x0A: type_ = kUTF16BE; break; + case 0x01: type_ = kUTF32LE; break; + case 0x05: type_ = kUTF16LE; break; + case 0x0F: type_ = kUTF8; break; + default: break; // Use type defined by user. + } + } + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + } + + typedef Ch (*TakeFunc)(InputByteStream& is); + InputByteStream* is_; + UTFType type_; + Ch current_; + TakeFunc takeFunc_; + bool hasBOM_; +}; + +//! Output stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for writing. + \tparam OutputByteStream type of output byte stream to be wrapped. +*/ +template +class AutoUTFOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param os output stream to be wrapped. + \param type UTF encoding type. + \param putBOM Whether to write BOM at the beginning of the stream. + */ + AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + + static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) }; + putFunc_ = f[type_]; + + if (putBOM) + PutBOM(); + } + + UTFType GetType() const { return type_; } + + void Put(Ch c) { putFunc_(*os_, c); } + void Flush() { os_->Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFOutputStream(const AutoUTFOutputStream&); + AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); + + void PutBOM() { + typedef void (*PutBOMFunc)(OutputByteStream&); + static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; + f[type_](*os_); + } + + typedef void (*PutFunc)(OutputByteStream&, Ch); + + OutputByteStream* os_; + UTFType type_; + PutFunc putFunc_; +}; + +#undef RAPIDJSON_ENCODINGS_FUNC + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/encodings.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/encodings.h new file mode 100644 index 0000000..50ad18b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/encodings.h @@ -0,0 +1,716 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ENCODINGS_H_ +#define RAPIDJSON_ENCODINGS_H_ + +#include "rapidjson.h" + +#if defined(_MSC_VER) && !defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#elif defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(overflow) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Encoding + +/*! \class rapidjson::Encoding + \brief Concept for encoding of Unicode characters. + +\code +concept Encoding { + typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition. + + enum { supportUnicode = 1 }; // or 0 if not supporting unicode + + //! \brief Encode a Unicode codepoint to an output stream. + //! \param os Output stream. + //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. + template + static void Encode(OutputStream& os, unsigned codepoint); + + //! \brief Decode a Unicode codepoint from an input stream. + //! \param is Input stream. + //! \param codepoint Output of the unicode codepoint. + //! \return true if a valid codepoint can be decoded from the stream. + template + static bool Decode(InputStream& is, unsigned* codepoint); + + //! \brief Validate one Unicode codepoint from an encoded stream. + //! \param is Input stream to obtain codepoint. + //! \param os Output for copying one codepoint. + //! \return true if it is valid. + //! \note This function just validating and copying the codepoint without actually decode it. + template + static bool Validate(InputStream& is, OutputStream& os); + + // The following functions are deal with byte streams. + + //! Take a character from input byte stream, skip BOM if exist. + template + static CharType TakeBOM(InputByteStream& is); + + //! Take a character from input byte stream. + template + static Ch Take(InputByteStream& is); + + //! Put BOM to output byte stream. + template + static void PutBOM(OutputByteStream& os); + + //! Put a character to output byte stream. + template + static void Put(OutputByteStream& os, Ch c); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// UTF8 + +//! UTF-8 encoding. +/*! http://en.wikipedia.org/wiki/UTF-8 + http://tools.ietf.org/html/rfc3629 + \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. + \note implements Encoding concept +*/ +template +struct UTF8 { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + os.Put(static_cast(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + os.Put(static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + os.Put(static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + } + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + PutUnsafe(os, static_cast(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + PutUnsafe(os, static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + PutUnsafe(os, static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); + } + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { +#define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast(c) & 0x3Fu) +#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) +#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) + typename InputStream::Ch c = is.Take(); + if (!(c & 0x80)) { + *codepoint = static_cast(c); + return true; + } + + unsigned char type = GetRange(static_cast(c)); + if (type >= 32) { + *codepoint = 0; + } else { + *codepoint = (0xFFu >> type) & static_cast(c); + } + bool result = true; + switch (type) { + case 2: RAPIDJSON_TAIL(); return result; + case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result; + case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result; + case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + default: return false; + } +#undef RAPIDJSON_COPY +#undef RAPIDJSON_TRANS +#undef RAPIDJSON_TAIL + } + + template + static bool Validate(InputStream& is, OutputStream& os) { +#define RAPIDJSON_COPY() os.Put(c = is.Take()) +#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) +#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) + Ch c; + RAPIDJSON_COPY(); + if (!(c & 0x80)) + return true; + + bool result = true; + switch (GetRange(static_cast(c))) { + case 2: RAPIDJSON_TAIL(); return result; + case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result; + case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result; + case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + default: return false; + } +#undef RAPIDJSON_COPY +#undef RAPIDJSON_TRANS +#undef RAPIDJSON_TAIL + } + + static unsigned char GetRange(unsigned char c) { + // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. + static const unsigned char type[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + }; + return type[c]; + } + + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + typename InputByteStream::Ch c = Take(is); + if (static_cast(c) != 0xEFu) return c; + c = is.Take(); + if (static_cast(c) != 0xBBu) return c; + c = is.Take(); + if (static_cast(c) != 0xBFu) return c; + c = is.Take(); + return c; + } + + template + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast(is.Take()); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xEFu)); + os.Put(static_cast(0xBBu)); + os.Put(static_cast(0xBFu)); + } + + template + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF16 + +//! UTF-16 encoding. +/*! http://en.wikipedia.org/wiki/UTF-16 + http://tools.ietf.org/html/rfc2781 + \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF16LE and UTF16BE, which handle endianness. +*/ +template +struct UTF16 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + os.Put(static_cast(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + os.Put(static_cast((v >> 10) | 0xD800)); + os.Put(static_cast((v & 0x3FF) | 0xDC00)); + } + } + + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + PutUnsafe(os, static_cast(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + PutUnsafe(os, static_cast((v >> 10) | 0xD800)); + PutUnsafe(os, static_cast((v & 0x3FF) | 0xDC00)); + } + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + typename InputStream::Ch c = is.Take(); + if (c < 0xD800 || c > 0xDFFF) { + *codepoint = static_cast(c); + return true; + } + else if (c <= 0xDBFF) { + *codepoint = (static_cast(c) & 0x3FF) << 10; + c = is.Take(); + *codepoint |= (static_cast(c) & 0x3FF); + *codepoint += 0x10000; + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + typename InputStream::Ch c; + os.Put(static_cast(c = is.Take())); + if (c < 0xD800 || c > 0xDFFF) + return true; + else if (c <= 0xDBFF) { + os.Put(c = is.Take()); + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } +}; + +//! UTF-16 little endian encoding. +template +struct UTF16LE : UTF16 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0xFEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(static_cast(c) & 0xFFu)); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); + } +}; + +//! UTF-16 big endian encoding. +template +struct UTF16BE : UTF16 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0xFEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())); + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); + os.Put(static_cast(static_cast(c) & 0xFFu)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF32 + +//! UTF-32 encoding. +/*! http://en.wikipedia.org/wiki/UTF-32 + \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF32LE and UTF32BE, which handle endianness. +*/ +template +struct UTF32 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(codepoint); + } + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, codepoint); + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c = is.Take(); + *codepoint = c; + return c <= 0x10FFFF; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c; + os.Put(c = is.Take()); + return c <= 0x10FFFF; + } +}; + +//! UTF-32 little endian enocoding. +template +struct UTF32LE : UTF32 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 24; + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 24) & 0xFFu)); + } +}; + +//! UTF-32 big endian encoding. +template +struct UTF32BE : UTF32 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(static_cast(is.Take())) << 24; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())); + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast((c >> 24) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast(c & 0xFFu)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// ASCII + +//! ASCII encoding. +/*! http://en.wikipedia.org/wiki/ASCII + \tparam CharType Code unit for storing 7-bit ASCII data. Default is char. + \note implements Encoding concept +*/ +template +struct ASCII { + typedef CharType Ch; + + enum { supportUnicode = 0 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + os.Put(static_cast(codepoint & 0xFF)); + } + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + PutUnsafe(os, static_cast(codepoint & 0xFF)); + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + uint8_t c = static_cast(is.Take()); + *codepoint = c; + return c <= 0X7F; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + uint8_t c = static_cast(is.Take()); + os.Put(static_cast(c)); + return c <= 0x7F; + } + + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + uint8_t c = static_cast(Take(is)); + return static_cast(c); + } + + template + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast(is.Take()); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + (void)os; + } + + template + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// AutoUTF + +//! Runtime-specified UTF encoding type of a stream. +enum UTFType { + kUTF8 = 0, //!< UTF-8. + kUTF16LE = 1, //!< UTF-16 little endian. + kUTF16BE = 2, //!< UTF-16 big endian. + kUTF32LE = 3, //!< UTF-32 little endian. + kUTF32BE = 4 //!< UTF-32 big endian. +}; + +//! Dynamically select encoding according to stream's runtime-specified UTF encoding type. +/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType(). +*/ +template +struct AutoUTF { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + + template + static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) }; + (*f[os.GetType()])(os, codepoint); + } + + template + static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) }; + (*f[os.GetType()])(os, codepoint); + } + + template + static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) { + typedef bool (*DecodeFunc)(InputStream&, unsigned*); + static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) }; + return (*f[is.GetType()])(is, codepoint); + } + + template + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { + typedef bool (*ValidateFunc)(InputStream&, OutputStream&); + static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) }; + return (*f[is.GetType()])(is, os); + } + +#undef RAPIDJSON_ENCODINGS_FUNC +}; + +/////////////////////////////////////////////////////////////////////////////// +// Transcoder + +//! Encoding conversion. +template +struct Transcoder { + //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. + template + static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::Encode(os, codepoint); + return true; + } + + template + static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::EncodeUnsafe(os, codepoint); + return true; + } + + //! Validate one Unicode codepoint from an encoded stream. + template + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { + return Transcode(is, os); // Since source/target encoding is different, must transcode. + } +}; + +// Forward declaration. +template +inline void PutUnsafe(Stream& stream, typename Stream::Ch c); + +//! Specialization of Transcoder with same source and target encoding. +template +struct Transcoder { + template + static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { + os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template + static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { + return Encoding::Validate(is, os); // source/target encoding are the same + } +}; + +RAPIDJSON_NAMESPACE_END + +#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__)) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/error/en.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/error/en.h new file mode 100644 index 0000000..c87b04e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/error/en.h @@ -0,0 +1,176 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ERROR_EN_H_ +#define RAPIDJSON_ERROR_EN_H_ + +#include "error.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(covered-switch-default) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Maps error code of parsing into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param parseErrorCode Error code obtained in parsing. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { + switch (parseErrorCode) { + case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); + case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values."); + + case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); + + case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); + case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); + case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); + + case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); + + case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); + case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); + case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); + case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); + case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); + + case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); + case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); + case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); + + case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); + case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +//! Maps error code of validation into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param validateErrorCode Error code obtained from validator. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) { + switch (validateErrorCode) { + case kValidateErrors: return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred"); + case kValidateErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kValidateErrorMultipleOf: return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'."); + case kValidateErrorMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'."); + case kValidateErrorExclusiveMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'."); + case kValidateErrorMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'."); + case kValidateErrorExclusiveMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'."); + + case kValidateErrorMaxLength: return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'."); + case kValidateErrorMinLength: return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'."); + case kValidateErrorPattern: return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression."); + + case kValidateErrorMaxItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'."); + case kValidateErrorMinItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'."); + case kValidateErrorUniqueItems: return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true."); + case kValidateErrorAdditionalItems: return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema."); + + case kValidateErrorMaxProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'."); + case kValidateErrorMinProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'."); + case kValidateErrorRequired: return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'."); + case kValidateErrorAdditionalProperties: return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema."); + case kValidateErrorPatternProperties: return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema."); + case kValidateErrorDependencies: return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors."); + + case kValidateErrorEnum: return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values."); + case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'."); + + case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors."); + case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf', indices '%matches'."); + case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors."); + case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors."); + case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'."); + + case kValidateErrorReadOnly: return RAPIDJSON_ERROR_STRING("Property is read-only but has been provided when validation is for writing."); + case kValidateErrorWriteOnly: return RAPIDJSON_ERROR_STRING("Property is write-only but has been provided when validation is for reading."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +//! Maps error code of schema document compilation into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param schemaErrorCode Error code obtained from compiling the schema document. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ + inline const RAPIDJSON_ERROR_CHARTYPE* GetSchemaError_En(SchemaErrorCode schemaErrorCode) { + switch (schemaErrorCode) { + case kSchemaErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kSchemaErrorStartUnknown: return RAPIDJSON_ERROR_STRING("Pointer '%value' to start of schema does not resolve to a location in the document."); + case kSchemaErrorRefPlainName: return RAPIDJSON_ERROR_STRING("$ref fragment '%value' must be a JSON pointer."); + case kSchemaErrorRefInvalid: return RAPIDJSON_ERROR_STRING("$ref must not be an empty string."); + case kSchemaErrorRefPointerInvalid: return RAPIDJSON_ERROR_STRING("$ref fragment '%value' is not a valid JSON pointer at offset '%offset'."); + case kSchemaErrorRefUnknown: return RAPIDJSON_ERROR_STRING("$ref '%value' does not resolve to a location in the target document."); + case kSchemaErrorRefCyclical: return RAPIDJSON_ERROR_STRING("$ref '%value' is cyclical."); + case kSchemaErrorRefNoRemoteProvider: return RAPIDJSON_ERROR_STRING("$ref is remote but there is no remote provider."); + case kSchemaErrorRefNoRemoteSchema: return RAPIDJSON_ERROR_STRING("$ref '%value' is remote but the remote provider did not return a schema."); + case kSchemaErrorRegexInvalid: return RAPIDJSON_ERROR_STRING("Invalid regular expression '%value' in 'pattern' or 'patternProperties'."); + case kSchemaErrorSpecUnknown: return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not recognized."); + case kSchemaErrorSpecUnsupported: return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not supported."); + case kSchemaErrorSpecIllegal: return RAPIDJSON_ERROR_STRING("Both JSON schema draft and OpenAPI version found in document."); + case kSchemaErrorReadOnlyAndWriteOnly: return RAPIDJSON_ERROR_STRING("Property must not be both 'readOnly' and 'writeOnly'."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } + } + +//! Maps error code of pointer parse into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param pointerParseErrorCode Error code obtained from pointer parse. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetPointerParseError_En(PointerParseErrorCode pointerParseErrorCode) { + switch (pointerParseErrorCode) { + case kPointerParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kPointerParseErrorTokenMustBeginWithSolidus: return RAPIDJSON_ERROR_STRING("A token must begin with a '/'."); + case kPointerParseErrorInvalidEscape: return RAPIDJSON_ERROR_STRING("Invalid escape."); + case kPointerParseErrorInvalidPercentEncoding: return RAPIDJSON_ERROR_STRING("Invalid percent encoding in URI fragment."); + case kPointerParseErrorCharacterMustPercentEncode: return RAPIDJSON_ERROR_STRING("A character must be percent encoded in a URI fragment."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_EN_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/error/error.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/error/error.h new file mode 100644 index 0000000..cae345d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/error/error.h @@ -0,0 +1,285 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ERROR_ERROR_H_ +#define RAPIDJSON_ERROR_ERROR_H_ + +#include "../rapidjson.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +/*! \file error.h */ + +/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_CHARTYPE + +//! Character type of error messages. +/*! \ingroup RAPIDJSON_ERRORS + The default character type is \c char. + On Windows, user can define this macro as \c TCHAR for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_CHARTYPE +#define RAPIDJSON_ERROR_CHARTYPE char +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_STRING + +//! Macro for converting string literal to \ref RAPIDJSON_ERROR_CHARTYPE[]. +/*! \ingroup RAPIDJSON_ERRORS + By default this conversion macro does nothing. + On Windows, user can define this macro as \c _T(x) for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_STRING +#define RAPIDJSON_ERROR_STRING(x) x +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseErrorCode + +//! Error code of parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericReader::Parse, GenericReader::GetParseErrorCode +*/ +enum ParseErrorCode { + kParseErrorNone = 0, //!< No error. + + kParseErrorDocumentEmpty, //!< The document is empty. + kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. + + kParseErrorValueInvalid, //!< Invalid value. + + kParseErrorObjectMissName, //!< Missing a name for object member. + kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. + kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. + + kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. + + kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. + kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. + kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. + kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. + kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. + + kParseErrorNumberTooBig, //!< Number too big to be stored in double. + kParseErrorNumberMissFraction, //!< Miss fraction part in number. + kParseErrorNumberMissExponent, //!< Miss exponent in number. + + kParseErrorTermination, //!< Parsing was terminated. + kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. +}; + +//! Result of parsing (wraps ParseErrorCode) +/*! + \ingroup RAPIDJSON_ERRORS + \code + Document doc; + ParseResult ok = doc.Parse("[42]"); + if (!ok) { + fprintf(stderr, "JSON parse error: %s (%u)", + GetParseError_En(ok.Code()), ok.Offset()); + exit(EXIT_FAILURE); + } + \endcode + \see GenericReader::Parse, GenericDocument::Parse +*/ +struct ParseResult { + //!! Unspecified boolean type + typedef bool (ParseResult::*BooleanType)() const; +public: + //! Default constructor, no error. + ParseResult() : code_(kParseErrorNone), offset_(0) {} + //! Constructor to set an error. + ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} + + //! Get the error code. + ParseErrorCode Code() const { return code_; } + //! Get the error offset, if \ref IsError(), 0 otherwise. + size_t Offset() const { return offset_; } + + //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError(). + operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; } + //! Whether the result is an error. + bool IsError() const { return code_ != kParseErrorNone; } + + bool operator==(const ParseResult& that) const { return code_ == that.code_; } + bool operator==(ParseErrorCode code) const { return code_ == code; } + friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } + + bool operator!=(const ParseResult& that) const { return !(*this == that); } + bool operator!=(ParseErrorCode code) const { return !(*this == code); } + friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; } + + //! Reset error code. + void Clear() { Set(kParseErrorNone); } + //! Update error code and offset. + void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } + +private: + ParseErrorCode code_; + size_t offset_; +}; + +//! Function pointer type of GetParseError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetParseError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetParseErrorFunc GetParseError = GetParseError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); + +/////////////////////////////////////////////////////////////////////////////// +// ValidateErrorCode + +//! Error codes when validating. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericSchemaValidator +*/ +enum ValidateErrorCode { + kValidateErrors = -1, //!< Top level error code when kValidateContinueOnErrorsFlag set. + kValidateErrorNone = 0, //!< No error. + + kValidateErrorMultipleOf, //!< Number is not a multiple of the 'multipleOf' value. + kValidateErrorMaximum, //!< Number is greater than the 'maximum' value. + kValidateErrorExclusiveMaximum, //!< Number is greater than or equal to the 'maximum' value. + kValidateErrorMinimum, //!< Number is less than the 'minimum' value. + kValidateErrorExclusiveMinimum, //!< Number is less than or equal to the 'minimum' value. + + kValidateErrorMaxLength, //!< String is longer than the 'maxLength' value. + kValidateErrorMinLength, //!< String is longer than the 'maxLength' value. + kValidateErrorPattern, //!< String does not match the 'pattern' regular expression. + + kValidateErrorMaxItems, //!< Array is longer than the 'maxItems' value. + kValidateErrorMinItems, //!< Array is shorter than the 'minItems' value. + kValidateErrorUniqueItems, //!< Array has duplicate items but 'uniqueItems' is true. + kValidateErrorAdditionalItems, //!< Array has additional items that are not allowed by the schema. + + kValidateErrorMaxProperties, //!< Object has more members than 'maxProperties' value. + kValidateErrorMinProperties, //!< Object has less members than 'minProperties' value. + kValidateErrorRequired, //!< Object is missing one or more members required by the schema. + kValidateErrorAdditionalProperties, //!< Object has additional members that are not allowed by the schema. + kValidateErrorPatternProperties, //!< See other errors. + kValidateErrorDependencies, //!< Object has missing property or schema dependencies. + + kValidateErrorEnum, //!< Property has a value that is not one of its allowed enumerated values. + kValidateErrorType, //!< Property has a type that is not allowed by the schema. + + kValidateErrorOneOf, //!< Property did not match any of the sub-schemas specified by 'oneOf'. + kValidateErrorOneOfMatch, //!< Property matched more than one of the sub-schemas specified by 'oneOf'. + kValidateErrorAllOf, //!< Property did not match all of the sub-schemas specified by 'allOf'. + kValidateErrorAnyOf, //!< Property did not match any of the sub-schemas specified by 'anyOf'. + kValidateErrorNot, //!< Property matched the sub-schema specified by 'not'. + + kValidateErrorReadOnly, //!< Property is read-only but has been provided when validation is for writing + kValidateErrorWriteOnly //!< Property is write-only but has been provided when validation is for reading +}; + +//! Function pointer type of GetValidateError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetValidateError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetValidateErrorFunc GetValidateError = GetValidateError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetValidateError(validator.GetInvalidSchemaCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode); + +/////////////////////////////////////////////////////////////////////////////// +// SchemaErrorCode + +//! Error codes when validating. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericSchemaValidator +*/ +enum SchemaErrorCode { + kSchemaErrorNone = 0, //!< No error. + + kSchemaErrorStartUnknown, //!< Pointer to start of schema does not resolve to a location in the document + kSchemaErrorRefPlainName, //!< $ref fragment must be a JSON pointer + kSchemaErrorRefInvalid, //!< $ref must not be an empty string + kSchemaErrorRefPointerInvalid, //!< $ref fragment is not a valid JSON pointer at offset + kSchemaErrorRefUnknown, //!< $ref does not resolve to a location in the target document + kSchemaErrorRefCyclical, //!< $ref is cyclical + kSchemaErrorRefNoRemoteProvider, //!< $ref is remote but there is no remote provider + kSchemaErrorRefNoRemoteSchema, //!< $ref is remote but the remote provider did not return a schema + kSchemaErrorRegexInvalid, //!< Invalid regular expression in 'pattern' or 'patternProperties' + kSchemaErrorSpecUnknown, //!< JSON schema draft or OpenAPI version is not recognized + kSchemaErrorSpecUnsupported, //!< JSON schema draft or OpenAPI version is not supported + kSchemaErrorSpecIllegal, //!< Both JSON schema draft and OpenAPI version found in document + kSchemaErrorReadOnlyAndWriteOnly //!< Property must not be both 'readOnly' and 'writeOnly' +}; + +//! Function pointer type of GetSchemaError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetSchemaError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetSchemaErrorFunc GetSchemaError = GetSchemaError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetSchemaError(validator.GetInvalidSchemaCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetSchemaErrorFunc)(SchemaErrorCode); + +/////////////////////////////////////////////////////////////////////////////// +// PointerParseErrorCode + +//! Error code of JSON pointer parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode +*/ +enum PointerParseErrorCode { + kPointerParseErrorNone = 0, //!< The parse is successful + + kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/' + kPointerParseErrorInvalidEscape, //!< Invalid escape + kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment + kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment +}; + +//! Function pointer type of GetPointerParseError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetPointerParseError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetPointerParseErrorFunc GetPointerParseError = GetPointerParseError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetPointerParseError(pointer.GetParseErrorCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetPointerParseErrorFunc)(PointerParseErrorCode); + + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_ERROR_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/filereadstream.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/filereadstream.h new file mode 100644 index 0000000..f8bb43c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/filereadstream.h @@ -0,0 +1,99 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FILEREADSTREAM_H_ +#define RAPIDJSON_FILEREADSTREAM_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! File byte stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileReadStream { +public: + typedef char Ch; //!< Character type (byte). + + //! Constructor. + /*! + \param fp File pointer opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(fp_ != 0); + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); + } + + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast(current_ - buffer_); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; + } + +private: + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = std::fread(buffer_, 1, bufferSize_, fp_); + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + + if (readCount_ < bufferSize_) { + buffer_[readCount_] = '\0'; + ++bufferLast_; + eof_ = true; + } + } + } + + std::FILE* fp_; + Ch *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/filewritestream.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/filewritestream.h new file mode 100644 index 0000000..5d89588 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/filewritestream.h @@ -0,0 +1,104 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FILEWRITESTREAM_H_ +#define RAPIDJSON_FILEWRITESTREAM_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of C file stream for output using fwrite(). +/*! + \note implements Stream concept +*/ +class FileWriteStream { +public: + typedef char Ch; //!< Character type. Only support char. + + FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { + RAPIDJSON_ASSERT(fp_ != 0); + } + + void Put(char c) { + if (current_ >= bufferEnd_) + Flush(); + + *current_++ = c; + } + + void PutN(char c, size_t n) { + size_t avail = static_cast(bufferEnd_ - current_); + while (n > avail) { + std::memset(current_, c, avail); + current_ += avail; + Flush(); + n -= avail; + avail = static_cast(bufferEnd_ - current_); + } + + if (n > 0) { + std::memset(current_, c, n); + current_ += n; + } + } + + void Flush() { + if (current_ != buffer_) { + size_t result = std::fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); + if (result < static_cast(current_ - buffer_)) { + // failure deliberately ignored at this time + // added to avoid warn_unused_result build errors + } + current_ = buffer_; + } + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + // Prohibit copy constructor & assignment operator. + FileWriteStream(const FileWriteStream&); + FileWriteStream& operator=(const FileWriteStream&); + + std::FILE* fp_; + char *buffer_; + char *bufferEnd_; + char *current_; +}; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(FileWriteStream& stream, char c, size_t n) { + stream.PutN(c, n); +} + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/fwd.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/fwd.h new file mode 100644 index 0000000..d62f77f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/fwd.h @@ -0,0 +1,151 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FWD_H_ +#define RAPIDJSON_FWD_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +// encodings.h + +template struct UTF8; +template struct UTF16; +template struct UTF16BE; +template struct UTF16LE; +template struct UTF32; +template struct UTF32BE; +template struct UTF32LE; +template struct ASCII; +template struct AutoUTF; + +template +struct Transcoder; + +// allocators.h + +class CrtAllocator; + +template +class MemoryPoolAllocator; + +// stream.h + +template +struct GenericStringStream; + +typedef GenericStringStream > StringStream; + +template +struct GenericInsituStringStream; + +typedef GenericInsituStringStream > InsituStringStream; + +// stringbuffer.h + +template +class GenericStringBuffer; + +typedef GenericStringBuffer, CrtAllocator> StringBuffer; + +// filereadstream.h + +class FileReadStream; + +// filewritestream.h + +class FileWriteStream; + +// memorybuffer.h + +template +struct GenericMemoryBuffer; + +typedef GenericMemoryBuffer MemoryBuffer; + +// memorystream.h + +struct MemoryStream; + +// reader.h + +template +struct BaseReaderHandler; + +template +class GenericReader; + +typedef GenericReader, UTF8, CrtAllocator> Reader; + +// writer.h + +template +class Writer; + +// prettywriter.h + +template +class PrettyWriter; + +// document.h + +template +class GenericMember; + +template +class GenericMemberIterator; + +template +struct GenericStringRef; + +template +class GenericValue; + +typedef GenericValue, MemoryPoolAllocator > Value; + +template +class GenericDocument; + +typedef GenericDocument, MemoryPoolAllocator, CrtAllocator> Document; + +// pointer.h + +template +class GenericPointer; + +typedef GenericPointer Pointer; + +// schema.h + +template +class IGenericRemoteSchemaDocumentProvider; + +template +class GenericSchemaDocument; + +typedef GenericSchemaDocument SchemaDocument; +typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; + +template < + typename SchemaDocumentType, + typename OutputHandler, + typename StateAllocator> +class GenericSchemaValidator; + +typedef GenericSchemaValidator, void>, CrtAllocator> SchemaValidator; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSONFWD_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/biginteger.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/biginteger.h new file mode 100644 index 0000000..4930043 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/biginteger.h @@ -0,0 +1,297 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_BIGINTEGER_H_ +#define RAPIDJSON_BIGINTEGER_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_M_AMD64) +#include // for _umul128 +#if !defined(_ARM64EC_) +#pragma intrinsic(_umul128) +#else +#pragma comment(lib,"softintrin") +#endif +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class BigInteger { +public: + typedef uint64_t Type; + + BigInteger(const BigInteger& rhs) : count_(rhs.count_) { + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + + explicit BigInteger(uint64_t u) : count_(1) { + digits_[0] = u; + } + + template + BigInteger(const Ch* decimals, size_t length) : count_(1) { + RAPIDJSON_ASSERT(length > 0); + digits_[0] = 0; + size_t i = 0; + const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19 + while (length >= kMaxDigitPerIteration) { + AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); + length -= kMaxDigitPerIteration; + i += kMaxDigitPerIteration; + } + + if (length > 0) + AppendDecimal64(decimals + i, decimals + i + length); + } + + BigInteger& operator=(const BigInteger &rhs) + { + if (this != &rhs) { + count_ = rhs.count_; + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + return *this; + } + + BigInteger& operator=(uint64_t u) { + digits_[0] = u; + count_ = 1; + return *this; + } + + BigInteger& operator+=(uint64_t u) { + Type backup = digits_[0]; + digits_[0] += u; + for (size_t i = 0; i < count_ - 1; i++) { + if (digits_[i] >= backup) + return *this; // no carry + backup = digits_[i + 1]; + digits_[i + 1] += 1; + } + + // Last carry + if (digits_[count_ - 1] < backup) + PushBack(1); + + return *this; + } + + BigInteger& operator*=(uint64_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + uint64_t hi; + digits_[i] = MulAdd64(digits_[i], u, k, &hi); + k = hi; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator*=(uint32_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + const uint64_t c = digits_[i] >> 32; + const uint64_t d = digits_[i] & 0xFFFFFFFF; + const uint64_t uc = u * c; + const uint64_t ud = u * d; + const uint64_t p0 = ud + k; + const uint64_t p1 = uc + (p0 >> 32); + digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); + k = p1 >> 32; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator<<=(size_t shift) { + if (IsZero() || shift == 0) return *this; + + size_t offset = shift / kTypeBit; + size_t interShift = shift % kTypeBit; + RAPIDJSON_ASSERT(count_ + offset <= kCapacity); + + if (interShift == 0) { + std::memmove(digits_ + offset, digits_, count_ * sizeof(Type)); + count_ += offset; + } + else { + digits_[count_] = 0; + for (size_t i = count_; i > 0; i--) + digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); + digits_[offset] = digits_[0] << interShift; + count_ += offset; + if (digits_[count_]) + count_++; + } + + std::memset(digits_, 0, offset * sizeof(Type)); + + return *this; + } + + bool operator==(const BigInteger& rhs) const { + return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; + } + + bool operator==(const Type rhs) const { + return count_ == 1 && digits_[0] == rhs; + } + + BigInteger& MultiplyPow5(unsigned exp) { + static const uint32_t kPow5[12] = { + 5, + 5 * 5, + 5 * 5 * 5, + 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 + }; + if (exp == 0) return *this; + for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 + for (; exp >= 13; exp -= 13) *this *= static_cast(1220703125u); // 5^13 + if (exp > 0) *this *= kPow5[exp - 1]; + return *this; + } + + // Compute absolute difference of this and rhs. + // Assume this != rhs + bool Difference(const BigInteger& rhs, BigInteger* out) const { + int cmp = Compare(rhs); + RAPIDJSON_ASSERT(cmp != 0); + const BigInteger *a, *b; // Makes a > b + bool ret; + if (cmp < 0) { a = &rhs; b = this; ret = true; } + else { a = this; b = &rhs; ret = false; } + + Type borrow = 0; + for (size_t i = 0; i < a->count_; i++) { + Type d = a->digits_[i] - borrow; + if (i < b->count_) + d -= b->digits_[i]; + borrow = (d > a->digits_[i]) ? 1 : 0; + out->digits_[i] = d; + if (d != 0) + out->count_ = i + 1; + } + + return ret; + } + + int Compare(const BigInteger& rhs) const { + if (count_ != rhs.count_) + return count_ < rhs.count_ ? -1 : 1; + + for (size_t i = count_; i-- > 0;) + if (digits_[i] != rhs.digits_[i]) + return digits_[i] < rhs.digits_[i] ? -1 : 1; + + return 0; + } + + size_t GetCount() const { return count_; } + Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } + bool IsZero() const { return count_ == 1 && digits_[0] == 0; } + +private: + template + void AppendDecimal64(const Ch* begin, const Ch* end) { + uint64_t u = ParseUint64(begin, end); + if (IsZero()) + *this = u; + else { + unsigned exp = static_cast(end - begin); + (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u + } + } + + void PushBack(Type digit) { + RAPIDJSON_ASSERT(count_ < kCapacity); + digits_[count_++] = digit; + } + + template + static uint64_t ParseUint64(const Ch* begin, const Ch* end) { + uint64_t r = 0; + for (const Ch* p = begin; p != end; ++p) { + RAPIDJSON_ASSERT(*p >= Ch('0') && *p <= Ch('9')); + r = r * 10u + static_cast(*p - Ch('0')); + } + return r; + } + + // Assume a * b + k < 2^128 + static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t low = _umul128(a, b, outHigh) + k; + if (low < k) + (*outHigh)++; + return low; +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast(a) * static_cast(b); + p += k; + *outHigh = static_cast(p >> 64); + return static_cast(p); +#else + const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; + uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; + x1 += (x0 >> 32); // can't give carry + x1 += x2; + if (x1 < x2) + x3 += (static_cast(1) << 32); + uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); + uint64_t hi = x3 + (x1 >> 32); + + lo += k; + if (lo < k) + hi++; + *outHigh = hi; + return lo; +#endif + } + + static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000 + static const size_t kCapacity = kBitCount / sizeof(Type); + static const size_t kTypeBit = sizeof(Type) * 8; + + Type digits_[kCapacity]; + size_t count_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_BIGINTEGER_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/clzll.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/clzll.h new file mode 100644 index 0000000..8fc5118 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/clzll.h @@ -0,0 +1,71 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_CLZLL_H_ +#define RAPIDJSON_CLZLL_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && !defined(UNDER_CE) +#include +#if defined(_WIN64) +#pragma intrinsic(_BitScanReverse64) +#else +#pragma intrinsic(_BitScanReverse) +#endif +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline uint32_t clzll(uint64_t x) { + // Passing 0 to __builtin_clzll is UB in GCC and results in an + // infinite loop in the software implementation. + RAPIDJSON_ASSERT(x != 0); + +#if defined(_MSC_VER) && !defined(UNDER_CE) + unsigned long r = 0; +#if defined(_WIN64) + _BitScanReverse64(&r, x); +#else + // Scan the high 32 bits. + if (_BitScanReverse(&r, static_cast(x >> 32))) + return 63 - (r + 32); + + // Scan the low 32 bits. + _BitScanReverse(&r, static_cast(x & 0xFFFFFFFF)); +#endif // _WIN64 + + return 63 - r; +#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll) + // __builtin_clzll wrapper + return static_cast(__builtin_clzll(x)); +#else + // naive version + uint32_t r = 0; + while (!(x & (static_cast(1) << 63))) { + x <<= 1; + ++r; + } + + return r; +#endif // _MSC_VER +} + +#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_CLZLL_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/diyfp.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/diyfp.h new file mode 100644 index 0000000..1f60fb6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/diyfp.h @@ -0,0 +1,261 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DIYFP_H_ +#define RAPIDJSON_DIYFP_H_ + +#include "../rapidjson.h" +#include "clzll.h" +#include + +#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER) +#include +#if !defined(_ARM64EC_) +#pragma intrinsic(_umul128) +#else +#pragma comment(lib,"softintrin") +#endif +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +struct DiyFp { + DiyFp() : f(), e() {} + + DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} + + explicit DiyFp(double d) { + union { + double d; + uint64_t u64; + } u = { d }; + + int biased_e = static_cast((u.u64 & kDpExponentMask) >> kDpSignificandSize); + uint64_t significand = (u.u64 & kDpSignificandMask); + if (biased_e != 0) { + f = significand + kDpHiddenBit; + e = biased_e - kDpExponentBias; + } + else { + f = significand; + e = kDpMinExponent + 1; + } + } + + DiyFp operator-(const DiyFp& rhs) const { + return DiyFp(f - rhs.f, e); + } + + DiyFp operator*(const DiyFp& rhs) const { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t h; + uint64_t l = _umul128(f, rhs.f, &h); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast(f) * static_cast(rhs.f); + uint64_t h = static_cast(p >> 64); + uint64_t l = static_cast(p); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#else + const uint64_t M32 = 0xFFFFFFFF; + const uint64_t a = f >> 32; + const uint64_t b = f & M32; + const uint64_t c = rhs.f >> 32; + const uint64_t d = rhs.f & M32; + const uint64_t ac = a * c; + const uint64_t bc = b * c; + const uint64_t ad = a * d; + const uint64_t bd = b * d; + uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); + tmp += 1U << 31; /// mult_round + return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); +#endif + } + + DiyFp Normalize() const { + int s = static_cast(clzll(f)); + return DiyFp(f << s, e - s); + } + + DiyFp NormalizeBoundary() const { + DiyFp res = *this; + while (!(res.f & (kDpHiddenBit << 1))) { + res.f <<= 1; + res.e--; + } + res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); + res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); + return res; + } + + void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { + DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); + DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); + mi.f <<= mi.e - pl.e; + mi.e = pl.e; + *plus = pl; + *minus = mi; + } + + double ToDouble() const { + union { + double d; + uint64_t u64; + }u; + RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask); + if (e < kDpDenormalExponent) { + // Underflow. + return 0.0; + } + if (e >= kDpMaxExponent) { + // Overflow. + return std::numeric_limits::infinity(); + } + const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : + static_cast(e + kDpExponentBias); + u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); + return u.d; + } + + static const int kDiySignificandSize = 64; + static const int kDpSignificandSize = 52; + static const int kDpExponentBias = 0x3FF + kDpSignificandSize; + static const int kDpMaxExponent = 0x7FF - kDpExponentBias; + static const int kDpMinExponent = -kDpExponentBias; + static const int kDpDenormalExponent = -kDpExponentBias + 1; + static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + uint64_t f; + int e; +}; + +inline DiyFp GetCachedPowerByIndex(size_t index) { + // 10^-348, 10^-340, ..., 10^340 + static const uint64_t kCachedPowers_F[] = { + RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), + RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea), + RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df), + RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f), + RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c), + RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5), + RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d), + RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637), + RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7), + RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5), + RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b), + RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996), + RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6), + RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8), + RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053), + RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd), + RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94), + RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b), + RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac), + RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3), + RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb), + RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c), + RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000), + RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984), + RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70), + RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245), + RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8), + RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a), + RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea), + RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85), + RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2), + RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3), + RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25), + RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece), + RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5), + RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a), + RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c), + RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a), + RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129), + RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429), + RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d), + RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841), + RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9), + RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b) + }; + static const int16_t kCachedPowers_E[] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, + -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, + -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, + -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, + -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, + 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, + 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, + 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, + 907, 933, 960, 986, 1013, 1039, 1066 + }; + RAPIDJSON_ASSERT(index < 87); + return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); +} + +inline DiyFp GetCachedPower(int e, int* K) { + + //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; + double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive + int k = static_cast(dk); + if (dk - k > 0.0) + k++; + + unsigned index = static_cast((k >> 3) + 1); + *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table + + return GetCachedPowerByIndex(index); +} + +inline DiyFp GetCachedPower10(int exp, int *outExp) { + RAPIDJSON_ASSERT(exp >= -348); + unsigned index = static_cast(exp + 348) / 8u; + *outExp = -348 + static_cast(index) * 8; + return GetCachedPowerByIndex(index); +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +RAPIDJSON_DIAG_OFF(padded) +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DIYFP_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/dtoa.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/dtoa.h new file mode 100644 index 0000000..cd45672 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/dtoa.h @@ -0,0 +1,249 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DTOA_ +#define RAPIDJSON_DTOA_ + +#include "itoa.h" // GetDigitsLut() +#include "diyfp.h" +#include "ieee754.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 +#endif + +inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { + while (rest < wp_w && delta - rest >= ten_kappa && + (rest + ten_kappa < wp_w || /// closer + wp_w - rest > rest + ten_kappa - wp_w)) { + buffer[len - 1]--; + rest += ten_kappa; + } +} + +inline int CountDecimalDigit32(uint32_t n) { + // Simple pure C++ implementation was faster than __builtin_clz version in this situation. + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + if (n < 10000000) return 7; + if (n < 100000000) return 8; + // Will not reach 10 digits in DigitGen() + //if (n < 1000000000) return 9; + //return 10; + return 9; +} + +inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { + static const uint64_t kPow10[] = { 1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL, 1000000ULL, 10000000ULL, 100000000ULL, + 1000000000ULL, 10000000000ULL, 100000000000ULL, 1000000000000ULL, + 10000000000000ULL, 100000000000000ULL, 1000000000000000ULL, + 10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL, + 10000000000000000000ULL }; + const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); + const DiyFp wp_w = Mp - W; + uint32_t p1 = static_cast(Mp.f >> -one.e); + uint64_t p2 = Mp.f & (one.f - 1); + int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] + *len = 0; + + while (kappa > 0) { + uint32_t d = 0; + switch (kappa) { + case 9: d = p1 / 100000000; p1 %= 100000000; break; + case 8: d = p1 / 10000000; p1 %= 10000000; break; + case 7: d = p1 / 1000000; p1 %= 1000000; break; + case 6: d = p1 / 100000; p1 %= 100000; break; + case 5: d = p1 / 10000; p1 %= 10000; break; + case 4: d = p1 / 1000; p1 %= 1000; break; + case 3: d = p1 / 100; p1 %= 100; break; + case 2: d = p1 / 10; p1 %= 10; break; + case 1: d = p1; p1 = 0; break; + default:; + } + if (d || *len) + buffer[(*len)++] = static_cast('0' + static_cast(d)); + kappa--; + uint64_t tmp = (static_cast(p1) << -one.e) + p2; + if (tmp <= delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, tmp, kPow10[kappa] << -one.e, wp_w.f); + return; + } + } + + // kappa = 0 + for (;;) { + p2 *= 10; + delta *= 10; + char d = static_cast(p2 >> -one.e); + if (d || *len) + buffer[(*len)++] = static_cast('0' + d); + p2 &= one.f - 1; + kappa--; + if (p2 < delta) { + *K += kappa; + int index = -kappa; + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 20 ? kPow10[index] : 0)); + return; + } + } +} + +inline void Grisu2(double value, char* buffer, int* length, int* K) { + const DiyFp v(value); + DiyFp w_m, w_p; + v.NormalizedBoundaries(&w_m, &w_p); + + const DiyFp c_mk = GetCachedPower(w_p.e, K); + const DiyFp W = v.Normalize() * c_mk; + DiyFp Wp = w_p * c_mk; + DiyFp Wm = w_m * c_mk; + Wm.f++; + Wp.f--; + DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); +} + +inline char* WriteExponent(int K, char* buffer) { + if (K < 0) { + *buffer++ = '-'; + K = -K; + } + + if (K >= 100) { + *buffer++ = static_cast('0' + static_cast(K / 100)); + K %= 100; + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else if (K >= 10) { + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else + *buffer++ = static_cast('0' + static_cast(K)); + + return buffer; +} + +inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { + const int kk = length + k; // 10^(kk-1) <= v < 10^kk + + if (0 <= k && kk <= 21) { + // 1234e7 -> 12340000000 + for (int i = length; i < kk; i++) + buffer[i] = '0'; + buffer[kk] = '.'; + buffer[kk + 1] = '0'; + return &buffer[kk + 2]; + } + else if (0 < kk && kk <= 21) { + // 1234e-2 -> 12.34 + std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk)); + buffer[kk] = '.'; + if (0 > k + maxDecimalPlaces) { + // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1 + // Remove extra trailing zeros (at least one) after truncation. + for (int i = kk + maxDecimalPlaces; i > kk + 1; i--) + if (buffer[i] != '0') + return &buffer[i + 1]; + return &buffer[kk + 2]; // Reserve one zero + } + else + return &buffer[length + 1]; + } + else if (-6 < kk && kk <= 0) { + // 1234e-6 -> 0.001234 + const int offset = 2 - kk; + std::memmove(&buffer[offset], &buffer[0], static_cast(length)); + buffer[0] = '0'; + buffer[1] = '.'; + for (int i = 2; i < offset; i++) + buffer[i] = '0'; + if (length - kk > maxDecimalPlaces) { + // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1 + // Remove extra trailing zeros (at least one) after truncation. + for (int i = maxDecimalPlaces + 1; i > 2; i--) + if (buffer[i] != '0') + return &buffer[i + 1]; + return &buffer[3]; // Reserve one zero + } + else + return &buffer[length + offset]; + } + else if (kk < -maxDecimalPlaces) { + // Truncate to zero + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else if (length == 1) { + // 1e30 + buffer[1] = 'e'; + return WriteExponent(kk - 1, &buffer[2]); + } + else { + // 1234e30 -> 1.234e33 + std::memmove(&buffer[2], &buffer[1], static_cast(length - 1)); + buffer[1] = '.'; + buffer[length + 1] = 'e'; + return WriteExponent(kk - 1, &buffer[0 + length + 2]); + } +} + +inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) { + RAPIDJSON_ASSERT(maxDecimalPlaces >= 1); + Double d(value); + if (d.IsZero()) { + if (d.Sign()) + *buffer++ = '-'; // -0.0, Issue #289 + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else { + if (value < 0) { + *buffer++ = '-'; + value = -value; + } + int length, K; + Grisu2(value, buffer, &length, &K); + return Prettify(buffer, length, K, maxDecimalPlaces); + } +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DTOA_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/ieee754.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/ieee754.h new file mode 100644 index 0000000..68c9e96 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/ieee754.h @@ -0,0 +1,78 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_IEEE754_ +#define RAPIDJSON_IEEE754_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class Double { +public: + Double() {} + Double(double d) : d_(d) {} + Double(uint64_t u) : u_(u) {} + + double Value() const { return d_; } + uint64_t Uint64Value() const { return u_; } + + double NextPositiveDouble() const { + RAPIDJSON_ASSERT(!Sign()); + return Double(u_ + 1).Value(); + } + + bool Sign() const { return (u_ & kSignMask) != 0; } + uint64_t Significand() const { return u_ & kSignificandMask; } + int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } + + bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } + bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } + bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } + bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } + bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } + + uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } + int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } + uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } + + static int EffectiveSignificandSize(int order) { + if (order >= -1021) + return 53; + else if (order <= -1074) + return 0; + else + return order + 1074; + } + +private: + static const int kSignificandSize = 52; + static const int kExponentBias = 0x3FF; + static const int kDenormalExponent = 1 - kExponentBias; + static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); + static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + union { + double d_; + uint64_t u_; + }; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_IEEE754_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/itoa.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/itoa.h new file mode 100644 index 0000000..9fe8c93 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/itoa.h @@ -0,0 +1,308 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ITOA_ +#define RAPIDJSON_ITOA_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline const char* GetDigitsLut() { + static const char cDigitsLut[200] = { + '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', + '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', + '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', + '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', + '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', + '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', + '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', + '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', + '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', + '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' + }; + return cDigitsLut; +} + +inline char* u32toa(uint32_t value, char* buffer) { + RAPIDJSON_ASSERT(buffer != 0); + + const char* cDigitsLut = GetDigitsLut(); + + if (value < 10000) { + const uint32_t d1 = (value / 100) << 1; + const uint32_t d2 = (value % 100) << 1; + + if (value >= 1000) + *buffer++ = cDigitsLut[d1]; + if (value >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else if (value < 100000000) { + // value = bbbbcccc + const uint32_t b = value / 10000; + const uint32_t c = value % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + else { + // value = aabbbbcccc in decimal + + const uint32_t a = value / 100000000; // 1 to 42 + value %= 100000000; + + if (a >= 10) { + const unsigned i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else + *buffer++ = static_cast('0' + static_cast(a)); + + const uint32_t b = value / 10000; // 0 to 9999 + const uint32_t c = value % 10000; // 0 to 9999 + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + return buffer; +} + +inline char* i32toa(int32_t value, char* buffer) { + RAPIDJSON_ASSERT(buffer != 0); + uint32_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u32toa(u, buffer); +} + +inline char* u64toa(uint64_t value, char* buffer) { + RAPIDJSON_ASSERT(buffer != 0); + const char* cDigitsLut = GetDigitsLut(); + const uint64_t kTen8 = 100000000; + const uint64_t kTen9 = kTen8 * 10; + const uint64_t kTen10 = kTen8 * 100; + const uint64_t kTen11 = kTen8 * 1000; + const uint64_t kTen12 = kTen8 * 10000; + const uint64_t kTen13 = kTen8 * 100000; + const uint64_t kTen14 = kTen8 * 1000000; + const uint64_t kTen15 = kTen8 * 10000000; + const uint64_t kTen16 = kTen8 * kTen8; + + if (value < kTen8) { + uint32_t v = static_cast(value); + if (v < 10000) { + const uint32_t d1 = (v / 100) << 1; + const uint32_t d2 = (v % 100) << 1; + + if (v >= 1000) + *buffer++ = cDigitsLut[d1]; + if (v >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (v >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else { + // value = bbbbcccc + const uint32_t b = v / 10000; + const uint32_t c = v % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + } + else if (value < kTen16) { + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + if (value >= kTen15) + *buffer++ = cDigitsLut[d1]; + if (value >= kTen14) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= kTen13) + *buffer++ = cDigitsLut[d2]; + if (value >= kTen12) + *buffer++ = cDigitsLut[d2 + 1]; + if (value >= kTen11) + *buffer++ = cDigitsLut[d3]; + if (value >= kTen10) + *buffer++ = cDigitsLut[d3 + 1]; + if (value >= kTen9) + *buffer++ = cDigitsLut[d4]; + + *buffer++ = cDigitsLut[d4 + 1]; + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + else { + const uint32_t a = static_cast(value / kTen16); // 1 to 1844 + value %= kTen16; + + if (a < 10) + *buffer++ = static_cast('0' + static_cast(a)); + else if (a < 100) { + const uint32_t i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else if (a < 1000) { + *buffer++ = static_cast('0' + static_cast(a / 100)); + + const uint32_t i = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else { + const uint32_t i = (a / 100) << 1; + const uint32_t j = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + *buffer++ = cDigitsLut[j]; + *buffer++ = cDigitsLut[j + 1]; + } + + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + + return buffer; +} + +inline char* i64toa(int64_t value, char* buffer) { + RAPIDJSON_ASSERT(buffer != 0); + uint64_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u64toa(u, buffer); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ITOA_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/meta.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/meta.h new file mode 100644 index 0000000..27092dc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/meta.h @@ -0,0 +1,186 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_META_H_ +#define RAPIDJSON_INTERNAL_META_H_ + +#include "../rapidjson.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(6334) +#endif + +#if RAPIDJSON_HAS_CXX11_TYPETRAITS +#include +#endif + +//@cond RAPIDJSON_INTERNAL +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching +template struct Void { typedef void Type; }; + +/////////////////////////////////////////////////////////////////////////////// +// BoolType, TrueType, FalseType +// +template struct BoolType { + static const bool Value = Cond; + typedef BoolType Type; +}; +typedef BoolType TrueType; +typedef BoolType FalseType; + + +/////////////////////////////////////////////////////////////////////////////// +// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr +// + +template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; }; +template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; }; +template struct SelectIfCond : SelectIfImpl::template Apply {}; +template struct SelectIf : SelectIfCond {}; + +template struct AndExprCond : FalseType {}; +template <> struct AndExprCond : TrueType {}; +template struct OrExprCond : TrueType {}; +template <> struct OrExprCond : FalseType {}; + +template struct BoolExpr : SelectIf::Type {}; +template struct NotExpr : SelectIf::Type {}; +template struct AndExpr : AndExprCond::Type {}; +template struct OrExpr : OrExprCond::Type {}; + + +/////////////////////////////////////////////////////////////////////////////// +// AddConst, MaybeAddConst, RemoveConst +template struct AddConst { typedef const T Type; }; +template struct MaybeAddConst : SelectIfCond {}; +template struct RemoveConst { typedef T Type; }; +template struct RemoveConst { typedef T Type; }; + + +/////////////////////////////////////////////////////////////////////////////// +// IsSame, IsConst, IsMoreConst, IsPointer +// +template struct IsSame : FalseType {}; +template struct IsSame : TrueType {}; + +template struct IsConst : FalseType {}; +template struct IsConst : TrueType {}; + +template +struct IsMoreConst + : AndExpr::Type, typename RemoveConst::Type>, + BoolType::Value >= IsConst::Value> >::Type {}; + +template struct IsPointer : FalseType {}; +template struct IsPointer : TrueType {}; + +/////////////////////////////////////////////////////////////////////////////// +// IsBaseOf +// +#if RAPIDJSON_HAS_CXX11_TYPETRAITS + +template struct IsBaseOf + : BoolType< ::std::is_base_of::value> {}; + +#else // simplified version adopted from Boost + +template struct IsBaseOfImpl { + RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); + RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); + + typedef char (&Yes)[1]; + typedef char (&No) [2]; + + template + static Yes Check(const D*, T); + static No Check(const B*, int); + + struct Host { + operator const B*() const; + operator const D*(); + }; + + enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; +}; + +template struct IsBaseOf + : OrExpr, BoolExpr > >::Type {}; + +#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS + + +////////////////////////////////////////////////////////////////////////// +// EnableIf / DisableIf +// +template struct EnableIfCond { typedef T Type; }; +template struct EnableIfCond { /* empty */ }; + +template struct DisableIfCond { typedef T Type; }; +template struct DisableIfCond { /* empty */ }; + +template +struct EnableIf : EnableIfCond {}; + +template +struct DisableIf : DisableIfCond {}; + +// SFINAE helpers +struct SfinaeTag {}; +template struct RemoveSfinaeTag; +template struct RemoveSfinaeTag { typedef T Type; }; + +#define RAPIDJSON_REMOVEFPTR_(type) \ + typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ + < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type + +#define RAPIDJSON_ENABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type * = NULL + +#define RAPIDJSON_DISABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type * = NULL + +#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type + +#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type + +} // namespace internal +RAPIDJSON_NAMESPACE_END +//@endcond + +#if defined(_MSC_VER) && !defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_META_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/pow10.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/pow10.h new file mode 100644 index 0000000..eae1a43 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/pow10.h @@ -0,0 +1,55 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_POW10_ +#define RAPIDJSON_POW10_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Computes integer powers of 10 in double (10.0^n). +/*! This function uses lookup table for fast and accurate results. + \param n non-negative exponent. Must <= 308. + \return 10.0^n +*/ +inline double Pow10(int n) { + static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes + 1e+0, + 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, + 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, + 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, + 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, + 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, + 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, + 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, + 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, + 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, + 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, + 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, + 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, + 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, + 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, + 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, + 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 + }; + RAPIDJSON_ASSERT(n >= 0 && n <= 308); + return e[n]; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_POW10_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/regex.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/regex.h new file mode 100644 index 0000000..6446c40 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/regex.h @@ -0,0 +1,739 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_REGEX_H_ +#define RAPIDJSON_INTERNAL_REGEX_H_ + +#include "../allocators.h" +#include "../stream.h" +#include "stack.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifndef RAPIDJSON_REGEX_VERBOSE +#define RAPIDJSON_REGEX_VERBOSE 0 +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// DecodedStream + +template +class DecodedStream { +public: + DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); } + unsigned Peek() { return codepoint_; } + unsigned Take() { + unsigned c = codepoint_; + if (c) // No further decoding when '\0' + Decode(); + return c; + } + +private: + void Decode() { + if (!Encoding::Decode(ss_, &codepoint_)) + codepoint_ = 0; + } + + SourceStream& ss_; + unsigned codepoint_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericRegex + +static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 +static const SizeType kRegexInvalidRange = ~SizeType(0); + +template +class GenericRegexSearch; + +//! Regular expression engine with subset of ECMAscript grammar. +/*! + Supported regular expression syntax: + - \c ab Concatenation + - \c a|b Alternation + - \c a? Zero or one + - \c a* Zero or more + - \c a+ One or more + - \c a{3} Exactly 3 times + - \c a{3,} At least 3 times + - \c a{3,5} 3 to 5 times + - \c (ab) Grouping + - \c ^a At the beginning + - \c a$ At the end + - \c . Any character + - \c [abc] Character classes + - \c [a-c] Character class range + - \c [a-z0-9_] Character class combination + - \c [^abc] Negated character classes + - \c [^a-c] Negated character class range + - \c [\b] Backspace (U+0008) + - \c \\| \\\\ ... Escape characters + - \c \\f Form feed (U+000C) + - \c \\n Line feed (U+000A) + - \c \\r Carriage return (U+000D) + - \c \\t Tab (U+0009) + - \c \\v Vertical tab (U+000B) + + \note This is a Thompson NFA engine, implemented with reference to + Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).", + https://swtch.com/~rsc/regexp/regexp1.html +*/ +template +class GenericRegex { +public: + typedef Encoding EncodingType; + typedef typename Encoding::Ch Ch; + template friend class GenericRegexSearch; + + GenericRegex(const Ch* source, Allocator* allocator = 0) : + ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_), + states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), + anchorBegin_(), anchorEnd_() + { + GenericStringStream ss(source); + DecodedStream, Encoding> ds(ss); + Parse(ds); + } + + ~GenericRegex() + { + RAPIDJSON_DELETE(ownAllocator_); + } + + bool IsValid() const { + return root_ != kRegexInvalidState; + } + +private: + enum Operator { + kZeroOrOne, + kZeroOrMore, + kOneOrMore, + kConcatenation, + kAlternation, + kLeftParenthesis + }; + + static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.' + static const unsigned kRangeCharacterClass = 0xFFFFFFFE; + static const unsigned kRangeNegationFlag = 0x80000000; + + struct Range { + unsigned start; // + unsigned end; + SizeType next; + }; + + struct State { + SizeType out; //!< Equals to kInvalid for matching state + SizeType out1; //!< Equals to non-kInvalid for split + SizeType rangeStart; + unsigned codepoint; + }; + + struct Frag { + Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {} + SizeType start; + SizeType out; //!< link-list of all output states + SizeType minIndex; + }; + + State& GetState(SizeType index) { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom()[index]; + } + + const State& GetState(SizeType index) const { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom()[index]; + } + + Range& GetRange(SizeType index) { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom()[index]; + } + + const Range& GetRange(SizeType index) const { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom()[index]; + } + + template + void Parse(DecodedStream& ds) { + Stack operandStack(allocator_, 256); // Frag + Stack operatorStack(allocator_, 256); // Operator + Stack atomCountStack(allocator_, 256); // unsigned (Atom per parenthesis) + + *atomCountStack.template Push() = 0; + + unsigned codepoint; + while (ds.Peek() != 0) { + switch (codepoint = ds.Take()) { + case '^': + anchorBegin_ = true; + break; + + case '$': + anchorEnd_ = true; + break; + + case '|': + while (!operatorStack.Empty() && *operatorStack.template Top() < kAlternation) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + *operatorStack.template Push() = kAlternation; + *atomCountStack.template Top() = 0; + break; + + case '(': + *operatorStack.template Push() = kLeftParenthesis; + *atomCountStack.template Push() = 0; + break; + + case ')': + while (!operatorStack.Empty() && *operatorStack.template Top() != kLeftParenthesis) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + if (operatorStack.Empty()) + return; + operatorStack.template Pop(1); + atomCountStack.template Pop(1); + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '?': + if (!Eval(operandStack, kZeroOrOne)) + return; + break; + + case '*': + if (!Eval(operandStack, kZeroOrMore)) + return; + break; + + case '+': + if (!Eval(operandStack, kOneOrMore)) + return; + break; + + case '{': + { + unsigned n, m; + if (!ParseUnsigned(ds, &n)) + return; + + if (ds.Peek() == ',') { + ds.Take(); + if (ds.Peek() == '}') + m = kInfinityQuantifier; + else if (!ParseUnsigned(ds, &m) || m < n) + return; + } + else + m = n; + + if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}') + return; + ds.Take(); + } + break; + + case '.': + PushOperand(operandStack, kAnyCharacterClass); + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '[': + { + SizeType range; + if (!ParseRange(ds, &range)) + return; + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass); + GetState(s).rangeStart = range; + *operandStack.template Push() = Frag(s, s, s); + } + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '\\': // Escape character + if (!CharacterEscape(ds, &codepoint)) + return; // Unsupported escape character + // fall through to default + RAPIDJSON_DELIBERATE_FALLTHROUGH; + + default: // Pattern character + PushOperand(operandStack, codepoint); + ImplicitConcatenation(atomCountStack, operatorStack); + } + } + + while (!operatorStack.Empty()) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + + // Link the operand to matching state. + if (operandStack.GetSize() == sizeof(Frag)) { + Frag* e = operandStack.template Pop(1); + Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0)); + root_ = e->start; + +#if RAPIDJSON_REGEX_VERBOSE + printf("root: %d\n", root_); + for (SizeType i = 0; i < stateCount_ ; i++) { + State& s = GetState(i); + printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint); + } + printf("\n"); +#endif + } + } + + SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) { + State* s = states_.template Push(); + s->out = out; + s->out1 = out1; + s->codepoint = codepoint; + s->rangeStart = kRegexInvalidRange; + return stateCount_++; + } + + void PushOperand(Stack& operandStack, unsigned codepoint) { + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint); + *operandStack.template Push() = Frag(s, s, s); + } + + void ImplicitConcatenation(Stack& atomCountStack, Stack& operatorStack) { + if (*atomCountStack.template Top()) + *operatorStack.template Push() = kConcatenation; + (*atomCountStack.template Top())++; + } + + SizeType Append(SizeType l1, SizeType l2) { + SizeType old = l1; + while (GetState(l1).out != kRegexInvalidState) + l1 = GetState(l1).out; + GetState(l1).out = l2; + return old; + } + + void Patch(SizeType l, SizeType s) { + for (SizeType next; l != kRegexInvalidState; l = next) { + next = GetState(l).out; + GetState(l).out = s; + } + } + + bool Eval(Stack& operandStack, Operator op) { + switch (op) { + case kConcatenation: + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2); + { + Frag e2 = *operandStack.template Pop(1); + Frag e1 = *operandStack.template Pop(1); + Patch(e1.out, e2.start); + *operandStack.template Push() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex)); + } + return true; + + case kAlternation: + if (operandStack.GetSize() >= sizeof(Frag) * 2) { + Frag e2 = *operandStack.template Pop(1); + Frag e1 = *operandStack.template Pop(1); + SizeType s = NewState(e1.start, e2.start, 0); + *operandStack.template Push() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex)); + return true; + } + return false; + + case kZeroOrOne: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + *operandStack.template Push() = Frag(s, Append(e.out, s), e.minIndex); + return true; + } + return false; + + case kZeroOrMore: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push() = Frag(s, s, e.minIndex); + return true; + } + return false; + + case kOneOrMore: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push() = Frag(e.start, s, e.minIndex); + return true; + } + return false; + + default: + // syntax error (e.g. unclosed kLeftParenthesis) + return false; + } + } + + bool EvalQuantifier(Stack& operandStack, unsigned n, unsigned m) { + RAPIDJSON_ASSERT(n <= m); + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag)); + + if (n == 0) { + if (m == 0) // a{0} not support + return false; + else if (m == kInfinityQuantifier) + Eval(operandStack, kZeroOrMore); // a{0,} -> a* + else { + Eval(operandStack, kZeroOrOne); // a{0,5} -> a? + for (unsigned i = 0; i < m - 1; i++) + CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a? + for (unsigned i = 0; i < m - 1; i++) + Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a? + } + return true; + } + + for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a + CloneTopOperand(operandStack); + + if (m == kInfinityQuantifier) + Eval(operandStack, kOneOrMore); // a{3,} -> a a a+ + else if (m > n) { + CloneTopOperand(operandStack); // a{3,5} -> a a a a + Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a? + for (unsigned i = n; i < m - 1; i++) + CloneTopOperand(operandStack); // a{3,5} -> a a a a? a? + for (unsigned i = n; i < m; i++) + Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a? + } + + for (unsigned i = 0; i < n - 1; i++) + Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a? + + return true; + } + + static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; } + + void CloneTopOperand(Stack& operandStack) { + const Frag src = *operandStack.template Top(); // Copy constructor to prevent invalidation + SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_) + State* s = states_.template Push(count); + memcpy(s, &GetState(src.minIndex), count * sizeof(State)); + for (SizeType j = 0; j < count; j++) { + if (s[j].out != kRegexInvalidState) + s[j].out += count; + if (s[j].out1 != kRegexInvalidState) + s[j].out1 += count; + } + *operandStack.template Push() = Frag(src.start + count, src.out + count, src.minIndex + count); + stateCount_ += count; + } + + template + bool ParseUnsigned(DecodedStream& ds, unsigned* u) { + unsigned r = 0; + if (ds.Peek() < '0' || ds.Peek() > '9') + return false; + while (ds.Peek() >= '0' && ds.Peek() <= '9') { + if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295 + return false; // overflow + r = r * 10 + (ds.Take() - '0'); + } + *u = r; + return true; + } + + template + bool ParseRange(DecodedStream& ds, SizeType* range) { + bool isBegin = true; + bool negate = false; + int step = 0; + SizeType start = kRegexInvalidRange; + SizeType current = kRegexInvalidRange; + unsigned codepoint; + while ((codepoint = ds.Take()) != 0) { + if (isBegin) { + isBegin = false; + if (codepoint == '^') { + negate = true; + continue; + } + } + + switch (codepoint) { + case ']': + if (start == kRegexInvalidRange) + return false; // Error: nothing inside [] + if (step == 2) { // Add trailing '-' + SizeType r = NewRange('-'); + RAPIDJSON_ASSERT(current != kRegexInvalidRange); + GetRange(current).next = r; + } + if (negate) + GetRange(start).start |= kRangeNegationFlag; + *range = start; + return true; + + case '\\': + if (ds.Peek() == 'b') { + ds.Take(); + codepoint = 0x0008; // Escape backspace character + } + else if (!CharacterEscape(ds, &codepoint)) + return false; + // fall through to default + RAPIDJSON_DELIBERATE_FALLTHROUGH; + + default: + switch (step) { + case 1: + if (codepoint == '-') { + step++; + break; + } + // fall through to step 0 for other characters + RAPIDJSON_DELIBERATE_FALLTHROUGH; + + case 0: + { + SizeType r = NewRange(codepoint); + if (current != kRegexInvalidRange) + GetRange(current).next = r; + if (start == kRegexInvalidRange) + start = r; + current = r; + } + step = 1; + break; + + default: + RAPIDJSON_ASSERT(step == 2); + GetRange(current).end = codepoint; + step = 0; + } + } + } + return false; + } + + SizeType NewRange(unsigned codepoint) { + Range* r = ranges_.template Push(); + r->start = r->end = codepoint; + r->next = kRegexInvalidRange; + return rangeCount_++; + } + + template + bool CharacterEscape(DecodedStream& ds, unsigned* escapedCodepoint) { + unsigned codepoint; + switch (codepoint = ds.Take()) { + case '^': + case '$': + case '|': + case '(': + case ')': + case '?': + case '*': + case '+': + case '.': + case '[': + case ']': + case '{': + case '}': + case '\\': + *escapedCodepoint = codepoint; return true; + case 'f': *escapedCodepoint = 0x000C; return true; + case 'n': *escapedCodepoint = 0x000A; return true; + case 'r': *escapedCodepoint = 0x000D; return true; + case 't': *escapedCodepoint = 0x0009; return true; + case 'v': *escapedCodepoint = 0x000B; return true; + default: + return false; // Unsupported escape character + } + } + + Allocator* ownAllocator_; + Allocator* allocator_; + Stack states_; + Stack ranges_; + SizeType root_; + SizeType stateCount_; + SizeType rangeCount_; + + static const unsigned kInfinityQuantifier = ~0u; + + // For SearchWithAnchoring() + bool anchorBegin_; + bool anchorEnd_; +}; + +template +class GenericRegexSearch { +public: + typedef typename RegexType::EncodingType Encoding; + typedef typename Encoding::Ch Ch; + + GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : + regex_(regex), allocator_(allocator), ownAllocator_(0), + state0_(allocator, 0), state1_(allocator, 0), stateSet_() + { + RAPIDJSON_ASSERT(regex_.IsValid()); + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + stateSet_ = static_cast(allocator_->Malloc(GetStateSetSize())); + state0_.template Reserve(regex_.stateCount_); + state1_.template Reserve(regex_.stateCount_); + } + + ~GenericRegexSearch() { + Allocator::Free(stateSet_); + RAPIDJSON_DELETE(ownAllocator_); + } + + template + bool Match(InputStream& is) { + return SearchWithAnchoring(is, true, true); + } + + bool Match(const Ch* s) { + GenericStringStream is(s); + return Match(is); + } + + template + bool Search(InputStream& is) { + return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_); + } + + bool Search(const Ch* s) { + GenericStringStream is(s); + return Search(is); + } + +private: + typedef typename RegexType::State State; + typedef typename RegexType::Range Range; + + template + bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) { + DecodedStream ds(is); + + state0_.Clear(); + Stack *current = &state0_, *next = &state1_; + const size_t stateSetSize = GetStateSetSize(); + std::memset(stateSet_, 0, stateSetSize); + + bool matched = AddState(*current, regex_.root_); + unsigned codepoint; + while (!current->Empty() && (codepoint = ds.Take()) != 0) { + std::memset(stateSet_, 0, stateSetSize); + next->Clear(); + matched = false; + for (const SizeType* s = current->template Bottom(); s != current->template End(); ++s) { + const State& sr = regex_.GetState(*s); + if (sr.codepoint == codepoint || + sr.codepoint == RegexType::kAnyCharacterClass || + (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) + { + matched = AddState(*next, sr.out) || matched; + if (!anchorEnd && matched) + return true; + } + if (!anchorBegin) + AddState(*next, regex_.root_); + } + internal::Swap(current, next); + } + + return matched; + } + + size_t GetStateSetSize() const { + return (regex_.stateCount_ + 31) / 32 * 4; + } + + // Return whether the added states is a match state + bool AddState(Stack& l, SizeType index) { + RAPIDJSON_ASSERT(index != kRegexInvalidState); + + const State& s = regex_.GetState(index); + if (s.out1 != kRegexInvalidState) { // Split + bool matched = AddState(l, s.out); + return AddState(l, s.out1) || matched; + } + else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) { + stateSet_[index >> 5] |= (1u << (index & 31)); + *l.template PushUnsafe() = index; + } + return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation. + } + + bool MatchRange(SizeType rangeIndex, unsigned codepoint) const { + bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0; + while (rangeIndex != kRegexInvalidRange) { + const Range& r = regex_.GetRange(rangeIndex); + if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end) + return yes; + rangeIndex = r.next; + } + return !yes; + } + + const RegexType& regex_; + Allocator* allocator_; + Allocator* ownAllocator_; + Stack state0_; + Stack state1_; + uint32_t* stateSet_; +}; + +typedef GenericRegex > Regex; +typedef GenericRegexSearch RegexSearch; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_REGEX_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/stack.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/stack.h new file mode 100644 index 0000000..73abd70 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/stack.h @@ -0,0 +1,232 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_STACK_H_ +#define RAPIDJSON_INTERNAL_STACK_H_ + +#include "../allocators.h" +#include "swap.h" +#include + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// Stack + +//! A type-unsafe stack for storing different types of data. +/*! \tparam Allocator Allocator for allocating stack memory. +*/ +template +class Stack { +public: + // Optimization note: Do not allocate memory for stack_ in constructor. + // Do it lazily when first Push() -> Expand() -> Resize(). + Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack(Stack&& rhs) + : allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(rhs.stack_), + stackTop_(rhs.stackTop_), + stackEnd_(rhs.stackEnd_), + initialCapacity_(rhs.initialCapacity_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } +#endif + + ~Stack() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack& operator=(Stack&& rhs) { + if (&rhs != this) + { + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = rhs.stack_; + stackTop_ = rhs.stackTop_; + stackEnd_ = rhs.stackEnd_; + initialCapacity_ = rhs.initialCapacity_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } + return *this; + } +#endif + + void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(stack_, rhs.stack_); + internal::Swap(stackTop_, rhs.stackTop_); + internal::Swap(stackEnd_, rhs.stackEnd_); + internal::Swap(initialCapacity_, rhs.initialCapacity_); + } + + void Clear() { stackTop_ = stack_; } + + void ShrinkToFit() { + if (Empty()) { + // If the stack is empty, completely deallocate the memory. + Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc) + stack_ = 0; + stackTop_ = 0; + stackEnd_ = 0; + } + else + Resize(GetSize()); + } + + // Optimization note: try to minimize the size of this function for force inline. + // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. + template + RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { + // Expand the stack if needed + if (RAPIDJSON_UNLIKELY(static_cast(sizeof(T) * count) > (stackEnd_ - stackTop_))) + Expand(count); + } + + template + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { + Reserve(count); + return PushUnsafe(count); + } + + template + RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { + RAPIDJSON_ASSERT(stackTop_); + RAPIDJSON_ASSERT(static_cast(sizeof(T) * count) <= (stackEnd_ - stackTop_)); + T* ret = reinterpret_cast(stackTop_); + stackTop_ += sizeof(T) * count; + return ret; + } + + template + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stackTop_ -= count * sizeof(T); + return reinterpret_cast(stackTop_); + } + + template + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } + + template + const T* Top() const { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } + + template + T* End() { return reinterpret_cast(stackTop_); } + + template + const T* End() const { return reinterpret_cast(stackTop_); } + + template + T* Bottom() { return reinterpret_cast(stack_); } + + template + const T* Bottom() const { return reinterpret_cast(stack_); } + + bool HasAllocator() const { + return allocator_ != 0; + } + + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + bool Empty() const { return stackTop_ == stack_; } + size_t GetSize() const { return static_cast(stackTop_ - stack_); } + size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } + +private: + template + void Expand(size_t count) { + // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. + size_t newCapacity; + if (stack_ == 0) { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + newCapacity = initialCapacity_; + } else { + newCapacity = GetCapacity(); + newCapacity += (newCapacity + 1) / 2; + } + size_t newSize = GetSize() + sizeof(T) * count; + if (newCapacity < newSize) + newCapacity = newSize; + + Resize(newCapacity); + } + + void Resize(size_t newCapacity) { + const size_t size = GetSize(); // Backup the current size + stack_ = static_cast(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); + stackTop_ = stack_ + size; + stackEnd_ = stack_ + newCapacity; + } + + void Destroy() { + Allocator::Free(stack_); + RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack + } + + // Prohibit copy constructor & assignment operator. + Stack(const Stack&); + Stack& operator=(const Stack&); + + Allocator* allocator_; + Allocator* ownAllocator_; + char *stack_; + char *stackTop_; + char *stackEnd_; + size_t initialCapacity_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_STACK_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/strfunc.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/strfunc.h new file mode 100644 index 0000000..b698a8f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/strfunc.h @@ -0,0 +1,83 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ +#define RAPIDJSON_INTERNAL_STRFUNC_H_ + +#include "../stream.h" +#include + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom strlen() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s Null-terminated input string. + \return Number of characters in the string. + \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. +*/ +template +inline SizeType StrLen(const Ch* s) { + RAPIDJSON_ASSERT(s != 0); + const Ch* p = s; + while (*p) ++p; + return SizeType(p - s); +} + +template <> +inline SizeType StrLen(const char* s) { + return SizeType(std::strlen(s)); +} + +template <> +inline SizeType StrLen(const wchar_t* s) { + return SizeType(std::wcslen(s)); +} + +//! Custom strcmpn() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s1 Null-terminated input string. + \param s2 Null-terminated input string. + \return 0 if equal +*/ +template +inline int StrCmp(const Ch* s1, const Ch* s2) { + RAPIDJSON_ASSERT(s1 != 0); + RAPIDJSON_ASSERT(s2 != 0); + while(*s1 && (*s1 == *s2)) { s1++; s2++; } + return static_cast(*s1) < static_cast(*s2) ? -1 : static_cast(*s1) > static_cast(*s2); +} + +//! Returns number of code points in a encoded string. +template +bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { + RAPIDJSON_ASSERT(s != 0); + RAPIDJSON_ASSERT(outCount != 0); + GenericStringStream is(s); + const typename Encoding::Ch* end = s + length; + SizeType count = 0; + while (is.src_ < end) { + unsigned codepoint; + if (!Encoding::Decode(is, &codepoint)) + return false; + count++; + } + *outCount = count; + return true; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_INTERNAL_STRFUNC_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/strtod.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/strtod.h new file mode 100644 index 0000000..55f0e38 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/strtod.h @@ -0,0 +1,293 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_STRTOD_ +#define RAPIDJSON_STRTOD_ + +#include "ieee754.h" +#include "biginteger.h" +#include "diyfp.h" +#include "pow10.h" +#include +#include + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline double FastPath(double significand, int exp) { + if (exp < -308) + return 0.0; + else if (exp >= 0) + return significand * internal::Pow10(exp); + else + return significand / internal::Pow10(-exp); +} + +inline double StrtodNormalPrecision(double d, int p) { + if (p < -308) { + // Prevent expSum < -308, making Pow10(p) = 0 + d = FastPath(d, -308); + d = FastPath(d, p + 308); + } + else + d = FastPath(d, p); + return d; +} + +template +inline T Min3(T a, T b, T c) { + T m = a; + if (m > b) m = b; + if (m > c) m = c; + return m; +} + +inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { + const Double db(b); + const uint64_t bInt = db.IntegerSignificand(); + const int bExp = db.IntegerExponent(); + const int hExp = bExp - 1; + + int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; + + // Adjust for decimal exponent + if (dExp >= 0) { + dS_Exp2 += dExp; + dS_Exp5 += dExp; + } + else { + bS_Exp2 -= dExp; + bS_Exp5 -= dExp; + hS_Exp2 -= dExp; + hS_Exp5 -= dExp; + } + + // Adjust for binary exponent + if (bExp >= 0) + bS_Exp2 += bExp; + else { + dS_Exp2 -= bExp; + hS_Exp2 -= bExp; + } + + // Adjust for half ulp exponent + if (hExp >= 0) + hS_Exp2 += hExp; + else { + dS_Exp2 -= hExp; + bS_Exp2 -= hExp; + } + + // Remove common power of two factor from all three scaled values + int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); + dS_Exp2 -= common_Exp2; + bS_Exp2 -= common_Exp2; + hS_Exp2 -= common_Exp2; + + BigInteger dS = d; + dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); + + BigInteger bS(bInt); + bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); + + BigInteger hS(1); + hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); + + BigInteger delta(0); + dS.Difference(bS, &delta); + + return delta.Compare(hS); +} + +inline bool StrtodFast(double d, int p, double* result) { + // Use fast path for string-to-double conversion if possible + // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ + if (p > 22 && p < 22 + 16) { + // Fast Path Cases In Disguise + d *= internal::Pow10(p - 22); + p = 22; + } + + if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 + *result = FastPath(d, p); + return true; + } + else + return false; +} + +// Compute an approximation and see if it is within 1/2 ULP +template +inline bool StrtodDiyFp(const Ch* decimals, int dLen, int dExp, double* result) { + uint64_t significand = 0; + int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 + for (; i < dLen; i++) { + if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || + (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > Ch('5'))) + break; + significand = significand * 10u + static_cast(decimals[i] - Ch('0')); + } + + if (i < dLen && decimals[i] >= Ch('5')) // Rounding + significand++; + + int remaining = dLen - i; + const int kUlpShift = 3; + const int kUlp = 1 << kUlpShift; + int64_t error = (remaining == 0) ? 0 : kUlp / 2; + + DiyFp v(significand, 0); + v = v.Normalize(); + error <<= -v.e; + + dExp += remaining; + + int actualExp; + DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); + if (actualExp != dExp) { + static const DiyFp kPow10[] = { + DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60), // 10^1 + DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57), // 10^2 + DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54), // 10^3 + DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50), // 10^4 + DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47), // 10^5 + DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44), // 10^6 + DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40) // 10^7 + }; + int adjustment = dExp - actualExp; + RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8); + v = v * kPow10[adjustment - 1]; + if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit + error += kUlp / 2; + } + + v = v * cachedPower; + + error += kUlp + (error == 0 ? 0 : 1); + + const int oldExp = v.e; + v = v.Normalize(); + error <<= oldExp - v.e; + + const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); + int precisionSize = 64 - effectiveSignificandSize; + if (precisionSize + kUlpShift >= 64) { + int scaleExp = (precisionSize + kUlpShift) - 63; + v.f >>= scaleExp; + v.e += scaleExp; + error = (error >> scaleExp) + 1 + kUlp; + precisionSize -= scaleExp; + } + + DiyFp rounded(v.f >> precisionSize, v.e + precisionSize); + const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; + const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; + if (precisionBits >= halfWay + static_cast(error)) { + rounded.f++; + if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) + rounded.f >>= 1; + rounded.e++; + } + } + + *result = rounded.ToDouble(); + + return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error); +} + +template +inline double StrtodBigInteger(double approx, const Ch* decimals, int dLen, int dExp) { + RAPIDJSON_ASSERT(dLen >= 0); + const BigInteger dInt(decimals, static_cast(dLen)); + Double a(approx); + int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); + if (cmp < 0) + return a.Value(); // within half ULP + else if (cmp == 0) { + // Round towards even + if (a.Significand() & 1) + return a.NextPositiveDouble(); + else + return a.Value(); + } + else // adjustment + return a.NextPositiveDouble(); +} + +template +inline double StrtodFullPrecision(double d, int p, const Ch* decimals, size_t length, size_t decimalPosition, int exp) { + RAPIDJSON_ASSERT(d >= 0.0); + RAPIDJSON_ASSERT(length >= 1); + + double result = 0.0; + if (StrtodFast(d, p, &result)) + return result; + + RAPIDJSON_ASSERT(length <= INT_MAX); + int dLen = static_cast(length); + + RAPIDJSON_ASSERT(length >= decimalPosition); + RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX); + int dExpAdjust = static_cast(length - decimalPosition); + + RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust); + int dExp = exp - dExpAdjust; + + // Make sure length+dExp does not overflow + RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen); + + // Trim leading zeros + while (dLen > 0 && *decimals == '0') { + dLen--; + decimals++; + } + + // Trim trailing zeros + while (dLen > 0 && decimals[dLen - 1] == '0') { + dLen--; + dExp++; + } + + if (dLen == 0) { // Buffer only contains zeros. + return 0.0; + } + + // Trim right-most digits + const int kMaxDecimalDigit = 767 + 1; + if (dLen > kMaxDecimalDigit) { + dExp += dLen - kMaxDecimalDigit; + dLen = kMaxDecimalDigit; + } + + // If too small, underflow to zero. + // Any x <= 10^-324 is interpreted as zero. + if (dLen + dExp <= -324) + return 0.0; + + // If too large, overflow to infinity. + // Any x >= 10^309 is interpreted as +infinity. + if (dLen + dExp > 309) + return std::numeric_limits::infinity(); + + if (StrtodDiyFp(decimals, dLen, dExp, &result)) + return result; + + // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison + return StrtodBigInteger(result, decimals, dLen, dExp); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STRTOD_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/swap.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/swap.h new file mode 100644 index 0000000..2cf92f9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/internal/swap.h @@ -0,0 +1,46 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_SWAP_H_ +#define RAPIDJSON_INTERNAL_SWAP_H_ + +#include "../rapidjson.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom swap() to avoid dependency on C++ header +/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. + \note This has the same semantics as std::swap(). +*/ +template +inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { + T tmp = a; + a = b; + b = tmp; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_SWAP_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/istreamwrapper.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/istreamwrapper.h new file mode 100644 index 0000000..01437ec --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/istreamwrapper.h @@ -0,0 +1,128 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ISTREAMWRAPPER_H_ +#define RAPIDJSON_ISTREAMWRAPPER_H_ + +#include "stream.h" +#include +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept. +/*! + The classes can be wrapped including but not limited to: + + - \c std::istringstream + - \c std::stringstream + - \c std::wistringstream + - \c std::wstringstream + - \c std::ifstream + - \c std::fstream + - \c std::wifstream + - \c std::wfstream + + \tparam StreamType Class derived from \c std::basic_istream. +*/ + +template +class BasicIStreamWrapper { +public: + typedef typename StreamType::char_type Ch; + + //! Constructor. + /*! + \param stream stream opened for read. + */ + BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + Read(); + } + + //! Constructor. + /*! + \param stream stream opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); + } + + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast(current_ - buffer_); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; + } + +private: + BasicIStreamWrapper(); + BasicIStreamWrapper(const BasicIStreamWrapper&); + BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); + + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = bufferSize_; + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + + if (!stream_.read(buffer_, static_cast(bufferSize_))) { + readCount_ = static_cast(stream_.gcount()); + *(bufferLast_ = buffer_ + readCount_) = '\0'; + eof_ = true; + } + } + } + + StreamType &stream_; + Ch peekBuffer_[4], *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; +}; + +typedef BasicIStreamWrapper IStreamWrapper; +typedef BasicIStreamWrapper WIStreamWrapper; + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ISTREAMWRAPPER_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/memorybuffer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/memorybuffer.h new file mode 100644 index 0000000..ffbc41e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/memorybuffer.h @@ -0,0 +1,70 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_MEMORYBUFFER_H_ +#define RAPIDJSON_MEMORYBUFFER_H_ + +#include "stream.h" +#include "internal/stack.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output byte stream. +/*! + This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. + + It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. + + Differences between MemoryBuffer and StringBuffer: + 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. + 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. + + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template +struct GenericMemoryBuffer { + typedef char Ch; // byte + + GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + + void Put(Ch c) { *stack_.template Push() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { stack_.ShrinkToFit(); } + Ch* Push(size_t count) { return stack_.template Push(count); } + void Pop(size_t count) { stack_.template Pop(count); } + + const Ch* GetBuffer() const { + return stack_.template Bottom(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; +}; + +typedef GenericMemoryBuffer<> MemoryBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { + std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/memorystream.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/memorystream.h new file mode 100644 index 0000000..77af6c9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/memorystream.h @@ -0,0 +1,71 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_MEMORYSTREAM_H_ +#define RAPIDJSON_MEMORYSTREAM_H_ + +#include "stream.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory input byte stream. +/*! + This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. + + It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. + + Differences between MemoryStream and StringStream: + 1. StringStream has encoding but MemoryStream is a byte stream. + 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. + 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). + \note implements Stream concept +*/ +struct MemoryStream { + typedef char Ch; // byte + + MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} + + Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; } + Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; } + size_t Tell() const { return static_cast(src_ - begin_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return Tell() + 4 <= size_ ? src_ : 0; + } + + const Ch* src_; //!< Current read position. + const Ch* begin_; //!< Original head of the string. + const Ch* end_; //!< End of stream. + size_t size_; //!< Size of the stream. +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/msinttypes/inttypes.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/msinttypes/inttypes.h new file mode 100644 index 0000000..1811128 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/msinttypes/inttypes.h @@ -0,0 +1,316 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// miloyip: VC supports inttypes.h since VC2013 +#if _MSC_VER >= 1800 +#include +#else + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + +#endif // _MSC_VER >= 1800 + +#endif // _MSC_INTTYPES_H_ ] diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/msinttypes/stdint.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/msinttypes/stdint.h new file mode 100644 index 0000000..3d4477b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/msinttypes/stdint.h @@ -0,0 +1,300 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. +#if _MSC_VER >= 1600 // [ +#include + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +#undef INT8_C +#undef INT16_C +#undef INT32_C +#undef INT64_C +#undef UINT8_C +#undef UINT16_C +#undef UINT32_C +#undef UINT64_C + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#else // ] _MSC_VER >= 1700 [ + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we have to wrap include with 'extern "C++" {}' +// or compiler would give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#if defined(__cplusplus) && !defined(_M_ARM) +extern "C" { +#endif +# include +#if defined(__cplusplus) && !defined(_M_ARM) +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#endif // _MSC_VER >= 1600 ] + +#endif // _MSC_STDINT_H_ ] diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/ostreamwrapper.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/ostreamwrapper.h new file mode 100644 index 0000000..11ed4d3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/ostreamwrapper.h @@ -0,0 +1,81 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_OSTREAMWRAPPER_H_ +#define RAPIDJSON_OSTREAMWRAPPER_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept. +/*! + The classes can be wrapped including but not limited to: + + - \c std::ostringstream + - \c std::stringstream + - \c std::wpstringstream + - \c std::wstringstream + - \c std::ifstream + - \c std::fstream + - \c std::wofstream + - \c std::wfstream + + \tparam StreamType Class derived from \c std::basic_ostream. +*/ + +template +class BasicOStreamWrapper { +public: + typedef typename StreamType::char_type Ch; + BasicOStreamWrapper(StreamType& stream) : stream_(stream) {} + + void Put(Ch c) { + stream_.put(c); + } + + void Flush() { + stream_.flush(); + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + BasicOStreamWrapper(const BasicOStreamWrapper&); + BasicOStreamWrapper& operator=(const BasicOStreamWrapper&); + + StreamType& stream_; +}; + +typedef BasicOStreamWrapper OStreamWrapper; +typedef BasicOStreamWrapper WOStreamWrapper; + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_OSTREAMWRAPPER_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/pointer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/pointer.h new file mode 100644 index 0000000..6f4ef38 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/pointer.h @@ -0,0 +1,1476 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_POINTER_H_ +#define RAPIDJSON_POINTER_H_ + +#include "document.h" +#include "uri.h" +#include "internal/itoa.h" +#include "error/error.h" // PointerParseErrorCode + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token + +/////////////////////////////////////////////////////////////////////////////// +// GenericPointer + +//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator. +/*! + This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" + (https://tools.ietf.org/html/rfc6901). + + A JSON pointer is for identifying a specific value in a JSON document + (GenericDocument). It can simplify coding of DOM tree manipulation, because it + can access multiple-level depth of DOM tree with single API call. + + After it parses a string representation (e.g. "/foo/0" or URI fragment + representation (e.g. "#/foo/0") into its internal representation (tokens), + it can be used to resolve a specific value in multiple documents, or sub-tree + of documents. + + Contrary to GenericValue, Pointer can be copy constructed and copy assigned. + Apart from assignment, a Pointer cannot be modified after construction. + + Although Pointer is very convenient, please aware that constructing Pointer + involves parsing and dynamic memory allocation. A special constructor with user- + supplied tokens eliminates these. + + GenericPointer depends on GenericDocument and GenericValue. + + \tparam ValueType The value type of the DOM tree. E.g. GenericValue > + \tparam Allocator The allocator type for allocating memory for internal representation. + + \note GenericPointer uses same encoding of ValueType. + However, Allocator of GenericPointer is independent of Allocator of Value. +*/ +template +class GenericPointer { +public: + typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value + typedef typename ValueType::Ch Ch; //!< Character type from Value + typedef GenericUri UriType; + + + //! A token is the basic units of internal representation. + /*! + A JSON pointer string representation "/foo/123" is parsed to two tokens: + "foo" and 123. 123 will be represented in both numeric form and string form. + They are resolved according to the actual value type (object or array). + + For token that are not numbers, or the numeric value is out of bound + (greater than limits of SizeType), they are only treated as string form + (i.e. the token's index will be equal to kPointerInvalidIndex). + + This struct is public so that user can create a Pointer without parsing and + allocation, using a special constructor. + */ + struct Token { + const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character. + SizeType length; //!< Length of the name. + SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex. + }; + + //!@name Constructors and destructor. + //@{ + + //! Default constructor. + GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A null-terminated, string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + */ + explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source, internal::StrLen(source)); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + explicit GenericPointer(const std::basic_string& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source.c_str(), source.size()); + } +#endif + + //! Constructor that parses a string or URI fragment representation, with length of the source string. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param length Length of source. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Slightly faster than the overload without length. + */ + GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source, length); + } + + //! Constructor with user-supplied tokens. + /*! + This constructor let user supplies const array of tokens. + This prevents the parsing process and eliminates allocation. + This is preferred for memory constrained environments. + + \param tokens An constant array of tokens representing the JSON pointer. + \param tokenCount Number of tokens. + + \b Example + \code + #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } + #define INDEX(i) { #i, sizeof(#i) - 1, i } + + static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; + static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + // Equivalent to static const Pointer p("/foo/123"); + + #undef NAME + #undef INDEX + \endcode + */ + GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + + //! Copy constructor. + GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + *this = rhs; + } + + //! Copy constructor. + GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + *this = rhs; + } + + //! Destructor. + ~GenericPointer() { + if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. + Allocator::Free(tokens_); + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Assignment operator. + GenericPointer& operator=(const GenericPointer& rhs) { + if (this != &rhs) { + // Do not delete ownAllcator + if (nameBuffer_) + Allocator::Free(tokens_); + + tokenCount_ = rhs.tokenCount_; + parseErrorOffset_ = rhs.parseErrorOffset_; + parseErrorCode_ = rhs.parseErrorCode_; + + if (rhs.nameBuffer_) + CopyFromRaw(rhs); // Normally parsed tokens. + else { + tokens_ = rhs.tokens_; // User supplied const tokens. + nameBuffer_ = 0; + } + } + return *this; + } + + //! Swap the content of this pointer with an other. + /*! + \param other The pointer to swap with. + \note Constant complexity. + */ + GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT { + internal::Swap(allocator_, other.allocator_); + internal::Swap(ownAllocator_, other.ownAllocator_); + internal::Swap(nameBuffer_, other.nameBuffer_); + internal::Swap(tokens_, other.tokens_); + internal::Swap(tokenCount_, other.tokenCount_); + internal::Swap(parseErrorOffset_, other.parseErrorOffset_); + internal::Swap(parseErrorCode_, other.parseErrorCode_); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.pointer, b.pointer); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //@} + + //!@name Append token + //@{ + + //! Append a token and return a new Pointer + /*! + \param token Token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Token& token, Allocator* allocator = 0) const { + GenericPointer r; + r.allocator_ = allocator; + Ch *p = r.CopyFromRaw(*this, 1, token.length + 1); + std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); + r.tokens_[tokenCount_].name = p; + r.tokens_[tokenCount_].length = token.length; + r.tokens_[tokenCount_].index = token.index; + return r; + } + + //! Append a name token with length, and return a new Pointer + /*! + \param name Name to be appended. + \param length Length of name. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const { + Token token = { name, length, kPointerInvalidIndex }; + return Append(token, allocator); + } + + //! Append a name token without length, and return a new Pointer + /*! + \param name Name (const Ch*) to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >), (GenericPointer)) + Append(T* name, Allocator* allocator = 0) const { + return Append(name, internal::StrLen(name), allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Append a name token, and return a new Pointer + /*! + \param name Name to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const std::basic_string& name, Allocator* allocator = 0) const { + return Append(name.c_str(), static_cast(name.size()), allocator); + } +#endif + + //! Append a index token, and return a new Pointer + /*! + \param index Index to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(SizeType index, Allocator* allocator = 0) const { + char buffer[21]; + char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer); + SizeType length = static_cast(end - buffer); + buffer[length] = '\0'; + + if (sizeof(Ch) == 1) { + Token token = { reinterpret_cast(buffer), length, index }; + return Append(token, allocator); + } + else { + Ch name[21]; + for (size_t i = 0; i <= length; i++) + name[i] = static_cast(buffer[i]); + Token token = { name, length, index }; + return Append(token, allocator); + } + } + + //! Append a token by value, and return a new Pointer + /*! + \param token token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const { + if (token.IsString()) + return Append(token.GetString(), token.GetStringLength(), allocator); + else { + RAPIDJSON_ASSERT(token.IsUint64()); + RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0)); + return Append(static_cast(token.GetUint64()), allocator); + } + } + + //!@name Handling Parse Error + //@{ + + //! Check whether this is a valid pointer. + bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; } + + //! Get the parsing error offset in code unit. + size_t GetParseErrorOffset() const { return parseErrorOffset_; } + + //! Get the parsing error code. + PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } + + //@} + + //! Get the allocator of this pointer. + Allocator& GetAllocator() { return *allocator_; } + + //!@name Tokens + //@{ + + //! Get the token array (const version only). + const Token* GetTokens() const { return tokens_; } + + //! Get the number of tokens. + size_t GetTokenCount() const { return tokenCount_; } + + //@} + + //!@name Equality/inequality operators + //@{ + + //! Equality operator. + /*! + \note When any pointers are invalid, always returns false. + */ + bool operator==(const GenericPointer& rhs) const { + if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_) + return false; + + for (size_t i = 0; i < tokenCount_; i++) { + if (tokens_[i].index != rhs.tokens_[i].index || + tokens_[i].length != rhs.tokens_[i].length || + (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0)) + { + return false; + } + } + + return true; + } + + //! Inequality operator. + /*! + \note When any pointers are invalid, always returns true. + */ + bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } + + //! Less than operator. + /*! + \note Invalid pointers are always greater than valid ones. + */ + bool operator<(const GenericPointer& rhs) const { + if (!IsValid()) + return false; + if (!rhs.IsValid()) + return true; + + if (tokenCount_ != rhs.tokenCount_) + return tokenCount_ < rhs.tokenCount_; + + for (size_t i = 0; i < tokenCount_; i++) { + if (tokens_[i].index != rhs.tokens_[i].index) + return tokens_[i].index < rhs.tokens_[i].index; + + if (tokens_[i].length != rhs.tokens_[i].length) + return tokens_[i].length < rhs.tokens_[i].length; + + if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length)) + return cmp < 0; + } + + return false; + } + + //@} + + //!@name Stringify + //@{ + + //! Stringify the pointer into string representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template + bool Stringify(OutputStream& os) const { + return Stringify(os); + } + + //! Stringify the pointer into URI fragment representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template + bool StringifyUriFragment(OutputStream& os) const { + return Stringify(os); + } + + //@} + + //!@name Create value + //@{ + + //! Create a value in a subtree. + /*! + If the value is not exist, it creates all parent values and a JSON Null value. + So it always succeed and return the newly created or existing value. + + Remind that it may change types of parents according to tokens, so it + potentially removes previously stored values. For example, if a document + was an array, and "/foo" is used to create a value, then the document + will be changed to an object, and all existing array elements are lost. + + \param root Root value of a DOM subtree to be resolved. It can be any value other than document root. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created (a JSON Null value), or already exists value. + */ + ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + bool exist = true; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + if (v->IsArray() && t->name[0] == '-' && t->length == 1) { + v->PushBack(ValueType().Move(), allocator); + v = &((*v)[v->Size() - 1]); + exist = false; + } + else { + if (t->index == kPointerInvalidIndex) { // must be object name + if (!v->IsObject()) + v->SetObject(); // Change to Object + } + else { // object name or array index + if (!v->IsArray() && !v->IsObject()) + v->SetArray(); // Change to Array + } + + if (v->IsArray()) { + if (t->index >= v->Size()) { + v->Reserve(t->index + 1, allocator); + while (t->index >= v->Size()) + v->PushBack(ValueType().Move(), allocator); + exist = false; + } + v = &((*v)[t->index]); + } + else { + typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) { + v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator); + m = v->MemberEnd(); + v = &(--m)->value; // Assumes AddMember() appends at the end + exist = false; + } + else + v = &m->value; + } + } + } + + if (alreadyExist) + *alreadyExist = exist; + + return *v; + } + + //! Creates a value in a document. + /*! + \param document A document to be resolved. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created, or already exists value. + */ + template + ValueType& Create(GenericDocument& document, bool* alreadyExist = 0) const { + return Create(document, document.GetAllocator(), alreadyExist); + } + + //@} + + //!@name Compute URI + //@{ + + //! Compute the in-scope URI for a subtree. + // For use with JSON pointers into JSON schema documents. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param rootUri Root URI + \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. + \param allocator Allocator for Uris + \return Uri if it can be resolved. Otherwise null. + + \note + There are only 3 situations when a URI cannot be resolved: + 1. A value in the path is not an array nor object. + 2. An object value does not contain the token. + 3. A token is out of range of an array value. + + Use unresolvedTokenIndex to retrieve the token index. + */ + UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const { + static const Ch kIdString[] = { 'i', 'd', '\0' }; + static const ValueType kIdValue(kIdString, 2); + UriType base = UriType(rootUri, allocator); + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + switch (v->GetType()) { + case kObjectType: + { + // See if we have an id, and if so resolve with the current base + typename ValueType::MemberIterator m = v->FindMember(kIdValue); + if (m != v->MemberEnd() && (m->value).IsString()) { + UriType here = UriType(m->value, allocator).Resolve(base, allocator); + base = here; + } + m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) + break; + v = &m->value; + } + continue; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + break; + v = &((*v)[t->index]); + continue; + default: + break; + } + + // Error: unresolved token + if (unresolvedTokenIndex) + *unresolvedTokenIndex = static_cast(t - tokens_); + return UriType(allocator); + } + return base; + } + + UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const { + return GetUri(const_cast(root), rootUri, unresolvedTokenIndex, allocator); + } + + + //!@name Query value + //@{ + + //! Query a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. + \return Pointer to the value if it can be resolved. Otherwise null. + + \note + There are only 3 situations when a value cannot be resolved: + 1. A value in the path is not an array nor object. + 2. An object value does not contain the token. + 3. A token is out of range of an array value. + + Use unresolvedTokenIndex to retrieve the token index. + */ + ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) + break; + v = &m->value; + } + continue; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + break; + v = &((*v)[t->index]); + continue; + default: + break; + } + + // Error: unresolved token + if (unresolvedTokenIndex) + *unresolvedTokenIndex = static_cast(t - tokens_); + return 0; + } + return v; + } + + //! Query a const value in a const subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Pointer to the value if it can be resolved. Otherwise null. + */ + const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { + return Get(const_cast(root), unresolvedTokenIndex); + } + + //@} + + //!@name Query a value with default + //@{ + + //! Query a value in a subtree with default value. + /*! + Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value. + So that this function always succeed. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param defaultValue Default value to be cloned if the value was not exists. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + ValueType& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.CopyFrom(defaultValue, allocator); + } + + //! Query a value in a subtree with default null-terminated string. + ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + ValueType& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Query a value in a subtree with default std::basic_string. + ValueType& GetWithDefault(ValueType& root, const std::basic_string& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + ValueType& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } +#endif + + //! Query a value in a subtree with default primitive value. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { + return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); + } + + //! Query a value in a document with default value. + template + ValueType& GetWithDefault(GenericDocument& document, const ValueType& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //! Query a value in a document with default null-terminated string. + template + ValueType& GetWithDefault(GenericDocument& document, const Ch* defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Query a value in a document with default std::basic_string. + template + ValueType& GetWithDefault(GenericDocument& document, const std::basic_string& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } +#endif + + //! Query a value in a document with default primitive value. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(GenericDocument& document, T defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //@} + + //!@name Set a value + //@{ + + //! Set a value in a subtree, with move semantics. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be set. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = value; + } + + //! Set a value in a subtree, with copy semantics. + ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).CopyFrom(value, allocator); + } + + //! Set a null-terminated string in a subtree. + ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Set a std::basic_string in a subtree. + ValueType& Set(ValueType& root, const std::basic_string& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } +#endif + + //! Set a primitive value in a subtree. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value).Move(); + } + + //! Set a value in a document, with move semantics. + template + ValueType& Set(GenericDocument& document, ValueType& value) const { + return Create(document) = value; + } + + //! Set a value in a document, with copy semantics. + template + ValueType& Set(GenericDocument& document, const ValueType& value) const { + return Create(document).CopyFrom(value, document.GetAllocator()); + } + + //! Set a null-terminated string in a document. + template + ValueType& Set(GenericDocument& document, const Ch* value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Sets a std::basic_string in a document. + template + ValueType& Set(GenericDocument& document, const std::basic_string& value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } +#endif + + //! Set a primitive value in a document. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(GenericDocument& document, T value) const { + return Create(document) = value; + } + + //@} + + //!@name Swap a value + //@{ + + //! Swap a value with a value in a subtree. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be swapped. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).Swap(value); + } + + //! Swap a value with a value in a document. + template + ValueType& Swap(GenericDocument& document, ValueType& value) const { + return Create(document).Swap(value); + } + + //@} + + //! Erase a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Whether the resolved value is found and erased. + + \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false. + */ + bool Erase(ValueType& root) const { + RAPIDJSON_ASSERT(IsValid()); + if (tokenCount_ == 0) // Cannot erase the root + return false; + + ValueType* v = &root; + const Token* last = tokens_ + (tokenCount_ - 1); + for (const Token *t = tokens_; t != last; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) + return false; + v = &m->value; + } + break; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + return false; + v = &((*v)[t->index]); + break; + default: + return false; + } + } + + switch (v->GetType()) { + case kObjectType: + return v->EraseMember(GenericStringRef(last->name, last->length)); + case kArrayType: + if (last->index == kPointerInvalidIndex || last->index >= v->Size()) + return false; + v->Erase(v->Begin() + last->index); + return true; + default: + return false; + } + } + +private: + //! Clone the content from rhs to this. + /*! + \param rhs Source pointer. + \param extraToken Extra tokens to be allocated. + \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated. + \return Start of non-occupied name buffer, for storing extra names. + */ + Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { + if (!allocator_) // allocator is independently owned. + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens + for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) + nameBufferSize += t->length; + + tokenCount_ = rhs.tokenCount_ + extraToken; + tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); + nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); + if (rhs.tokenCount_ > 0) { + std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); + } + if (nameBufferSize > 0) { + std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); + } + + // The names of each token point to a string in the nameBuffer_. The + // previous memcpy copied over string pointers into the rhs.nameBuffer_, + // but they should point to the strings in the new nameBuffer_. + for (size_t i = 0; i < rhs.tokenCount_; ++i) { + // The offset between the string address and the name buffer should + // still be constant, so we can just get this offset and set each new + // token name according the new buffer start + the known offset. + std::ptrdiff_t name_offset = rhs.tokens_[i].name - rhs.nameBuffer_; + tokens_[i].name = nameBuffer_ + name_offset; + } + + return nameBuffer_ + nameBufferSize; + } + + //! Check whether a character should be percent-encoded. + /*! + According to RFC 3986 2.3 Unreserved Characters. + \param c The character (code unit) to be tested. + */ + bool NeedPercentEncode(Ch c) const { + return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~'); + } + + //! Parse a JSON String or its URI fragment representation into tokens. +#ifndef __clang__ // -Wdocumentation + /*! + \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. + \param length Length of the source string. + \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. + */ +#endif + void Parse(const Ch* source, size_t length) { + RAPIDJSON_ASSERT(source != NULL); + RAPIDJSON_ASSERT(nameBuffer_ == 0); + RAPIDJSON_ASSERT(tokens_ == 0); + + // Create own allocator if user did not supply. + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + // Count number of '/' as tokenCount + tokenCount_ = 0; + for (const Ch* s = source; s != source + length; s++) + if (*s == '/') + tokenCount_++; + + Token* token = tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); + Ch* name = nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); + size_t i = 0; + + // Detect if it is a URI fragment + bool uriFragment = false; + if (source[i] == '#') { + uriFragment = true; + i++; + } + + if (i != length && source[i] != '/') { + parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; + goto error; + } + + while (i < length) { + RAPIDJSON_ASSERT(source[i] == '/'); + i++; // consumes '/' + + token->name = name; + bool isNumber = true; + + while (i < length && source[i] != '/') { + Ch c = source[i]; + if (uriFragment) { + // Decoding percent-encoding for URI fragment + if (c == '%') { + PercentDecodeStream is(&source[i], source + length); + GenericInsituStringStream os(name); + Ch* begin = os.PutBegin(); + if (!Transcoder, EncodingType>().Validate(is, os) || !is.IsValid()) { + parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; + goto error; + } + size_t len = os.PutEnd(begin); + i += is.Tell() - 1; + if (len == 1) + c = *name; + else { + name += len; + isNumber = false; + i++; + continue; + } + } + else if (NeedPercentEncode(c)) { + parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode; + goto error; + } + } + + i++; + + // Escaping "~0" -> '~', "~1" -> '/' + if (c == '~') { + if (i < length) { + c = source[i]; + if (c == '0') c = '~'; + else if (c == '1') c = '/'; + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + i++; + } + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + } + + // First check for index: all of characters are digit + if (c < '0' || c > '9') + isNumber = false; + + *name++ = c; + } + token->length = static_cast(name - token->name); + if (token->length == 0) + isNumber = false; + *name++ = '\0'; // Null terminator + + // Second check for index: more than one digit cannot have leading zero + if (isNumber && token->length > 1 && token->name[0] == '0') + isNumber = false; + + // String to SizeType conversion + SizeType n = 0; + if (isNumber) { + for (size_t j = 0; j < token->length; j++) { + SizeType m = n * 10 + static_cast(token->name[j] - '0'); + if (m < n) { // overflow detection + isNumber = false; + break; + } + n = m; + } + } + + token->index = isNumber ? n : kPointerInvalidIndex; + token++; + } + + RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer + parseErrorCode_ = kPointerParseErrorNone; + return; + + error: + Allocator::Free(tokens_); + nameBuffer_ = 0; + tokens_ = 0; + tokenCount_ = 0; + parseErrorOffset_ = i; + return; + } + + //! Stringify to string or URI fragment representation. + /*! + \tparam uriFragment True for stringifying to URI fragment representation. False for string representation. + \tparam OutputStream type of output stream. + \param os The output stream. + */ + template + bool Stringify(OutputStream& os) const { + RAPIDJSON_ASSERT(IsValid()); + + if (uriFragment) + os.Put('#'); + + for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + os.Put('/'); + for (size_t j = 0; j < t->length; j++) { + Ch c = t->name[j]; + if (c == '~') { + os.Put('~'); + os.Put('0'); + } + else if (c == '/') { + os.Put('~'); + os.Put('1'); + } + else if (uriFragment && NeedPercentEncode(c)) { + // Transcode to UTF8 sequence + GenericStringStream source(&t->name[j]); + PercentEncodeStream target(os); + if (!Transcoder >().Validate(source, target)) + return false; + j += source.Tell() - 1; + } + else + os.Put(c); + } + } + return true; + } + + //! A helper stream for decoding a percent-encoded sequence into code unit. + /*! + This stream decodes %XY triplet into code unit (0-255). + If it encounters invalid characters, it sets output code unit as 0 and + mark invalid, and to be checked by IsValid(). + */ + class PercentDecodeStream { + public: + typedef typename ValueType::Ch Ch; + + //! Constructor + /*! + \param source Start of the stream + \param end Past-the-end of the stream. + */ + PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {} + + Ch Take() { + if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet + valid_ = false; + return 0; + } + src_++; + Ch c = 0; + for (int j = 0; j < 2; j++) { + c = static_cast(c << 4); + Ch h = *src_; + if (h >= '0' && h <= '9') c = static_cast(c + h - '0'); + else if (h >= 'A' && h <= 'F') c = static_cast(c + h - 'A' + 10); + else if (h >= 'a' && h <= 'f') c = static_cast(c + h - 'a' + 10); + else { + valid_ = false; + return 0; + } + src_++; + } + return c; + } + + size_t Tell() const { return static_cast(src_ - head_); } + bool IsValid() const { return valid_; } + + private: + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. + const Ch* end_; //!< Past-the-end position. + bool valid_; //!< Whether the parsing is valid. + }; + + //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence. + template + class PercentEncodeStream { + public: + PercentEncodeStream(OutputStream& os) : os_(os) {} + void Put(char c) { // UTF-8 must be byte + unsigned char u = static_cast(c); + static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + os_.Put('%'); + os_.Put(static_cast(hexDigits[u >> 4])); + os_.Put(static_cast(hexDigits[u & 15])); + } + private: + OutputStream& os_; + }; + + Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. + Allocator* ownAllocator_; //!< Allocator owned by this Pointer. + Ch* nameBuffer_; //!< A buffer containing all names in tokens. + Token* tokens_; //!< A list of tokens. + size_t tokenCount_; //!< Number of tokens in tokens_. + size_t parseErrorOffset_; //!< Offset in code unit when parsing fail. + PointerParseErrorCode parseErrorCode_; //!< Parsing error code. +}; + +//! GenericPointer for Value (UTF-8, default allocator). +typedef GenericPointer Pointer; + +//!@name Helper functions for GenericPointer +//@{ + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer, typename T::AllocatorType& a) { + return pointer.Create(root, a); +} + +template +typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Create(root, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer& pointer) { + return pointer.Create(document); +} + +template +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Create(document); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); +} + +template +typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const std::basic_string& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string& defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const std::basic_string& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, T2 defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const std::basic_string& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const GenericPointer& pointer, T2 value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* value) { + return pointer.Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const std::basic_string& value) { + return pointer.Set(document, value); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const GenericPointer& pointer, T2 value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string& value) { + return GenericPointer(source, N - 1).Set(document, value); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Swap(root, value, a); +} + +template +typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Swap(root, value, a); +} + +template +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { + return pointer.Swap(document, value); +} + +template +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Swap(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template +bool EraseValueByPointer(T& root, const GenericPointer& pointer) { + return pointer.Erase(root); +} + +template +bool EraseValueByPointer(T& root, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Erase(root); +} + +//@} + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_POINTER_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/prettywriter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/prettywriter.h new file mode 100644 index 0000000..fe45df1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/prettywriter.h @@ -0,0 +1,277 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_PRETTYWRITER_H_ +#define RAPIDJSON_PRETTYWRITER_H_ + +#include "writer.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Combination of PrettyWriter format flags. +/*! \see PrettyWriter::SetFormatOptions + */ +enum PrettyFormatOptions { + kFormatDefault = 0, //!< Default pretty formatting. + kFormatSingleLineArray = 1 //!< Format arrays on a single line. +}; + +//! Writer with indentation and spacing. +/*! + \tparam OutputStream Type of output os. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. +*/ +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class PrettyWriter : public Writer { +public: + typedef Writer Base; + typedef typename Base::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} + + + explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + PrettyWriter(PrettyWriter&& rhs) : + Base(std::forward(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {} +#endif + + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). + \param indentCharCount Number of indent characters for each indentation level. + \note The default indentation is 4 spaces. + */ + PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { + RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); + indentChar_ = indentChar; + indentCharCount_ = indentCharCount; + return *this; + } + + //! Set pretty writer formatting options. + /*! \param options Formatting options. + */ + PrettyWriter& SetFormatOptions(PrettyFormatOptions options) { + formatOptions_ = options; + return *this; + } + + /*! @name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { PrettyPrefix(kNullType); return Base::EndValue(Base::WriteNull()); } + bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); } + bool Int(int i) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); } + bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); } + bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); } + bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64)); } + bool Double(double d) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + PrettyPrefix(kNumberType); + return Base::EndValue(Base::WriteString(str, length)); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + PrettyPrefix(kStringType); + return Base::EndValue(Base::WriteString(str, length)); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + PrettyPrefix(kObjectType); + new (Base::level_stack_.template Push()) typename Base::Level(false); + return Base::WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + +#if RAPIDJSON_HAS_STDSTRING + bool Key(const std::basic_string& str) { + return Key(str.data(), SizeType(str.size())); + } +#endif + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object + RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top()->valueCount % 2); // Object has a Key without a Value + + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::EndValue(Base::WriteEndObject()); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::Flush(); + return true; + } + + bool StartArray() { + PrettyPrefix(kArrayType); + new (Base::level_stack_.template Push()) typename Base::Level(true); + return Base::WriteStartArray(); + } + + bool EndArray(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty && !(formatOptions_ & kFormatSingleLineArray)) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::EndValue(Base::WriteEndArray()); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::Flush(); + return true; + } + + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + \note When using PrettyWriter::RawValue(), the result json may not be indented correctly. + */ + bool RawValue(const Ch* json, size_t length, Type type) { + RAPIDJSON_ASSERT(json != 0); + PrettyPrefix(type); + return Base::EndValue(Base::WriteRawValue(json, length)); + } + +protected: + void PrettyPrefix(Type type) { + (void)type; + if (Base::level_stack_.GetSize() != 0) { // this value is not at root + typename Base::Level* level = Base::level_stack_.template Top(); + + if (level->inArray) { + if (level->valueCount > 0) { + Base::os_->Put(','); // add comma if it is not the first element in array + if (formatOptions_ & kFormatSingleLineArray) + Base::os_->Put(' '); + } + + if (!(formatOptions_ & kFormatSingleLineArray)) { + Base::os_->Put('\n'); + WriteIndent(); + } + } + else { // in object + if (level->valueCount > 0) { + if (level->valueCount % 2 == 0) { + Base::os_->Put(','); + Base::os_->Put('\n'); + } + else { + Base::os_->Put(':'); + Base::os_->Put(' '); + } + } + else + Base::os_->Put('\n'); + + if (level->valueCount % 2 == 0) + WriteIndent(); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. + Base::hasRoot_ = true; + } + } + + void WriteIndent() { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; + PutN(*Base::os_, static_cast(indentChar_), count); + } + + Ch indentChar_; + unsigned indentCharCount_; + PrettyFormatOptions formatOptions_; + +private: + // Prohibit copy constructor & assignment operator. + PrettyWriter(const PrettyWriter&); + PrettyWriter& operator=(const PrettyWriter&); +}; + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/rapidjson.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/rapidjson.h new file mode 100644 index 0000000..5ea6947 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/rapidjson.h @@ -0,0 +1,741 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_RAPIDJSON_H_ +#define RAPIDJSON_RAPIDJSON_H_ + +/*!\file rapidjson.h + \brief common definitions and configuration + + \see RAPIDJSON_CONFIG + */ + +/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration + \brief Configuration macros for library features + + Some RapidJSON features are configurable to adapt the library to a wide + variety of platforms, environments and usage scenarios. Most of the + features can be configured in terms of overridden or predefined + preprocessor macros at compile-time. + + Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs. + + \note These macros should be given on the compiler command-line + (where applicable) to avoid inconsistent values when compiling + different translation units of a single application. + */ + +#include // malloc(), realloc(), free(), size_t +#include // memset(), memcpy(), memmove(), memcmp() + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_VERSION_STRING +// +// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt. +// + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +// token stringification +#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) +#define RAPIDJSON_DO_STRINGIFY(x) #x + +// token concatenation +#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y) +#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y) +#define RAPIDJSON_DO_JOIN2(X, Y) X##Y +//!@endcond + +/*! \def RAPIDJSON_MAJOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Major version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_MINOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Minor version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_PATCH_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Patch version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_VERSION_STRING + \ingroup RAPIDJSON_CONFIG + \brief Version of RapidJSON in ".." string format. +*/ +#define RAPIDJSON_MAJOR_VERSION 1 +#define RAPIDJSON_MINOR_VERSION 1 +#define RAPIDJSON_PATCH_VERSION 0 +#define RAPIDJSON_VERSION_STRING \ + RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NAMESPACE_(BEGIN|END) +/*! \def RAPIDJSON_NAMESPACE + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace + + In order to avoid symbol clashes and/or "One Definition Rule" errors + between multiple inclusions of (different versions of) RapidJSON in + a single binary, users can customize the name of the main RapidJSON + namespace. + + In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE + to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple + levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref + RAPIDJSON_NAMESPACE_END need to be defined as well: + + \code + // in some .cpp file + #define RAPIDJSON_NAMESPACE my::rapidjson + #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson { + #define RAPIDJSON_NAMESPACE_END } } + #include "rapidjson/..." + \endcode + + \see rapidjson + */ +/*! \def RAPIDJSON_NAMESPACE_BEGIN + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (opening expression) + \see RAPIDJSON_NAMESPACE +*/ +/*! \def RAPIDJSON_NAMESPACE_END + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (closing expression) + \see RAPIDJSON_NAMESPACE +*/ +#ifndef RAPIDJSON_NAMESPACE +#define RAPIDJSON_NAMESPACE rapidjson +#endif +#ifndef RAPIDJSON_NAMESPACE_BEGIN +#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE { +#endif +#ifndef RAPIDJSON_NAMESPACE_END +#define RAPIDJSON_NAMESPACE_END } +#endif + +/////////////////////////////////////////////////////////////////////////////// +// __cplusplus macro + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +#if defined(_MSC_VER) +#define RAPIDJSON_CPLUSPLUS _MSVC_LANG +#else +#define RAPIDJSON_CPLUSPLUS __cplusplus +#endif + +//!@endcond + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_HAS_STDSTRING +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation +#else +#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default +#endif +/*! \def RAPIDJSON_HAS_STDSTRING + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for \c std::string + + By defining this preprocessor symbol to \c 1, several convenience functions for using + \ref rapidjson::GenericValue with \c std::string are enabled, especially + for construction and comparison. + + \hideinitializer +*/ +#endif // !defined(RAPIDJSON_HAS_STDSTRING) + +#if RAPIDJSON_HAS_STDSTRING +#include +#endif // RAPIDJSON_HAS_STDSTRING + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_USE_MEMBERSMAP + +/*! \def RAPIDJSON_USE_MEMBERSMAP + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for object members handling in a \c std::multimap + + By defining this preprocessor symbol to \c 1, \ref rapidjson::GenericValue object + members are stored in a \c std::multimap for faster lookup and deletion times, a + trade off with a slightly slower insertion time and a small object allocat(or)ed + memory overhead. + + \hideinitializer +*/ +#ifndef RAPIDJSON_USE_MEMBERSMAP +#define RAPIDJSON_USE_MEMBERSMAP 0 // not by default +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_INT64DEFINE + +/*! \def RAPIDJSON_NO_INT64DEFINE + \ingroup RAPIDJSON_CONFIG + \brief Use external 64-bit integer types. + + RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types + to be available at global scope. + + If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to + prevent RapidJSON from defining its own types. +*/ +#ifndef RAPIDJSON_NO_INT64DEFINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 +#include "msinttypes/stdint.h" +#include "msinttypes/inttypes.h" +#else +// Other compilers should have this. +#include +#include +#endif +//!@endcond +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_INT64DEFINE +#endif +#endif // RAPIDJSON_NO_INT64TYPEDEF + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_FORCEINLINE + +#ifndef RAPIDJSON_FORCEINLINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __forceinline +#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) +#else +#define RAPIDJSON_FORCEINLINE +#endif +//!@endcond +#endif // RAPIDJSON_FORCEINLINE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ENDIAN +#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine +#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine + +//! Endianness of the machine. +/*! + \def RAPIDJSON_ENDIAN + \ingroup RAPIDJSON_CONFIG + + GCC 4.6 provided macro for detecting endianness of the target machine. But other + compilers may not have this. User can define RAPIDJSON_ENDIAN to either + \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN. + + Default detection implemented with reference to + \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html + \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp +*/ +#ifndef RAPIDJSON_ENDIAN +// Detect with GCC 4.6's macro +# ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __BYTE_ORDER__ +// Detect with GLIBC's endian.h +# elif defined(__GLIBC__) +# include +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __GLIBC__ +// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +// Detect with architecture macros +# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64)) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(RAPIDJSON_DOXYGEN_RUNNING) +# define RAPIDJSON_ENDIAN +# else +# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. +# endif +#endif // RAPIDJSON_ENDIAN + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_64BIT + +//! Whether using 64-bit architecture +#ifndef RAPIDJSON_64BIT +#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__) +#define RAPIDJSON_64BIT 1 +#else +#define RAPIDJSON_64BIT 0 +#endif +#endif // RAPIDJSON_64BIT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ALIGN + +//! Data alignment of the machine. +/*! \ingroup RAPIDJSON_CONFIG + \param x pointer to align + + Some machines require strict data alignment. The default is 8 bytes. + User can customize by defining the RAPIDJSON_ALIGN function macro. +*/ +#ifndef RAPIDJSON_ALIGN +#define RAPIDJSON_ALIGN(x) (((x) + static_cast(7u)) & ~static_cast(7u)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_UINT64_C2 + +//! Construct a 64-bit literal by a pair of 32-bit integer. +/*! + 64-bit literal with or without ULL suffix is prone to compiler warnings. + UINT64_C() is C macro which cause compilation problems. + Use this macro to define 64-bit constants by a pair of 32-bit integer. +*/ +#ifndef RAPIDJSON_UINT64_C2 +#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast(high32) << 32) | static_cast(low32)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_48BITPOINTER_OPTIMIZATION + +//! Use only lower 48-bit address for some pointers. +/*! + \ingroup RAPIDJSON_CONFIG + + This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address. + The higher 16-bit can be used for storing other data. + \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture. +*/ +#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1 +#else +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0 +#endif +#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION + +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1 +#if RAPIDJSON_64BIT != 1 +#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1 +#endif +#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast((reinterpret_cast(p) & static_cast(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast(reinterpret_cast(x)))) +#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast(reinterpret_cast(p) & static_cast(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF)))) +#else +#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x)) +#define RAPIDJSON_GETPOINTER(type, p) (p) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD + +/*! \def RAPIDJSON_SIMD + \ingroup RAPIDJSON_CONFIG + \brief Enable SSE2/SSE4.2/Neon optimization. + + RapidJSON supports optimized implementations for some parsing operations + based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel + or ARM compatible processors. + + To enable these optimizations, three different symbols can be defined; + \code + // Enable SSE2 optimization. + #define RAPIDJSON_SSE2 + + // Enable SSE4.2 optimization. + #define RAPIDJSON_SSE42 + \endcode + + // Enable ARM Neon optimization. + #define RAPIDJSON_NEON + \endcode + + \c RAPIDJSON_SSE42 takes precedence over SSE2, if both are defined. + + If any of these symbols is defined, RapidJSON defines the macro + \c RAPIDJSON_SIMD to indicate the availability of the optimized code. +*/ +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \ + || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING) +#define RAPIDJSON_SIMD +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_SIZETYPEDEFINE + +#ifndef RAPIDJSON_NO_SIZETYPEDEFINE +/*! \def RAPIDJSON_NO_SIZETYPEDEFINE + \ingroup RAPIDJSON_CONFIG + \brief User-provided \c SizeType definition. + + In order to avoid using 32-bit size types for indexing strings and arrays, + define this preprocessor symbol and provide the type rapidjson::SizeType + before including RapidJSON: + \code + #define RAPIDJSON_NO_SIZETYPEDEFINE + namespace rapidjson { typedef ::std::size_t SizeType; } + #include "rapidjson/..." + \endcode + + \see rapidjson::SizeType +*/ +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_SIZETYPEDEFINE +#endif +RAPIDJSON_NAMESPACE_BEGIN +//! Size type (for string lengths, array sizes, etc.) +/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms, + instead of using \c size_t. Users may override the SizeType by defining + \ref RAPIDJSON_NO_SIZETYPEDEFINE. +*/ +typedef unsigned SizeType; +RAPIDJSON_NAMESPACE_END +#endif + +// always import std::size_t to rapidjson namespace +RAPIDJSON_NAMESPACE_BEGIN +using std::size_t; +RAPIDJSON_NAMESPACE_END + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ASSERT + +//! Assertion. +/*! \ingroup RAPIDJSON_CONFIG + By default, rapidjson uses C \c assert() for internal assertions. + User can override it by defining RAPIDJSON_ASSERT(x) macro. + + \note Parsing errors are handled and can be customized by the + \ref RAPIDJSON_ERRORS APIs. +*/ +#ifndef RAPIDJSON_ASSERT +#include +#define RAPIDJSON_ASSERT(x) assert(x) +#endif // RAPIDJSON_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_STATIC_ASSERT + +// Prefer C++11 static_assert, if available +#ifndef RAPIDJSON_STATIC_ASSERT +#if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 ) +#define RAPIDJSON_STATIC_ASSERT(x) \ + static_assert(x, RAPIDJSON_STRINGIFY(x)) +#endif // C++11 +#endif // RAPIDJSON_STATIC_ASSERT + +// Adopt C++03 implementation from boost +#ifndef RAPIDJSON_STATIC_ASSERT +#ifndef __clang__ +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#endif +RAPIDJSON_NAMESPACE_BEGIN +template struct STATIC_ASSERTION_FAILURE; +template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; +template struct StaticAssertTest {}; +RAPIDJSON_NAMESPACE_END + +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) +#else +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif +#ifndef __clang__ +//!@endcond +#endif + +/*! \def RAPIDJSON_STATIC_ASSERT + \brief (Internal) macro to check for conditions at compile-time + \param x compile-time condition + \hideinitializer + */ +#define RAPIDJSON_STATIC_ASSERT(x) \ + typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ + sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE)> \ + RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif // RAPIDJSON_STATIC_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY + +//! Compiler branching hint for expression with high probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression likely to be true. +*/ +#ifndef RAPIDJSON_LIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1) +#else +#define RAPIDJSON_LIKELY(x) (x) +#endif +#endif + +//! Compiler branching hint for expression with low probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression unlikely to be true. +*/ +#ifndef RAPIDJSON_UNLIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define RAPIDJSON_UNLIKELY(x) (x) +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Helpers + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +#define RAPIDJSON_MULTILINEMACRO_BEGIN do { +#define RAPIDJSON_MULTILINEMACRO_END \ +} while((void)0, 0) + +// adopted from Boost +#define RAPIDJSON_VERSION_CODE(x,y,z) \ + (((x)*100000) + ((y)*100) + (z)) + +#if defined(__has_builtin) +#define RAPIDJSON_HAS_BUILTIN(x) __has_builtin(x) +#else +#define RAPIDJSON_HAS_BUILTIN(x) 0 +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF + +#if defined(__GNUC__) +#define RAPIDJSON_GNUC \ + RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) +#endif + +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) + +#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) +#define RAPIDJSON_DIAG_OFF(x) \ + RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) + +// push/pop support in Clang and GCC>=4.6 +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) +#else // GCC >= 4.2, < 4.6 +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ +#endif + +#elif defined(_MSC_VER) + +// pragma (MSVC specific) +#define RAPIDJSON_PRAGMA(x) __pragma(x) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x)) + +#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) + +#else + +#define RAPIDJSON_DIAG_OFF(x) /* ignored */ +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ + +#endif // RAPIDJSON_DIAG_* + +/////////////////////////////////////////////////////////////////////////////// +// C++11 features + +#ifndef RAPIDJSON_HAS_CXX11 +#define RAPIDJSON_HAS_CXX11 (RAPIDJSON_CPLUSPLUS >= 201103L) +#endif + +#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS +#if RAPIDJSON_HAS_CXX11 +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#elif defined(__clang__) +#if __has_feature(cxx_rvalue_references) && \ + (defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1600) || \ + (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) + +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + +#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT +#if RAPIDJSON_HAS_CXX11 +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#elif defined(__clang__) +#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1900) || \ + (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#else +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 +#endif +#endif +#ifndef RAPIDJSON_NOEXCEPT +#if RAPIDJSON_HAS_CXX11_NOEXCEPT +#define RAPIDJSON_NOEXCEPT noexcept +#else +#define RAPIDJSON_NOEXCEPT throw() +#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT +#endif + +// no automatic detection, yet +#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS +#if (defined(_MSC_VER) && _MSC_VER >= 1700) +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 1 +#else +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 +#endif +#endif + +#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1700) || \ + (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 +#else +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR + +/////////////////////////////////////////////////////////////////////////////// +// C++17 features + +#ifndef RAPIDJSON_HAS_CXX17 +#define RAPIDJSON_HAS_CXX17 (RAPIDJSON_CPLUSPLUS >= 201703L) +#endif + +#if RAPIDJSON_HAS_CXX17 +# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]] +#elif defined(__has_cpp_attribute) +# if __has_cpp_attribute(clang::fallthrough) +# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]] +# elif __has_cpp_attribute(fallthrough) +# define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough)) +# else +# define RAPIDJSON_DELIBERATE_FALLTHROUGH +# endif +#else +# define RAPIDJSON_DELIBERATE_FALLTHROUGH +#endif + +//!@endcond + +//! Assertion (in non-throwing contexts). + /*! \ingroup RAPIDJSON_CONFIG + Some functions provide a \c noexcept guarantee, if the compiler supports it. + In these cases, the \ref RAPIDJSON_ASSERT macro cannot be overridden to + throw an exception. This macro adds a separate customization point for + such cases. + + Defaults to C \c assert() (as \ref RAPIDJSON_ASSERT), if \c noexcept is + supported, and to \ref RAPIDJSON_ASSERT otherwise. + */ + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NOEXCEPT_ASSERT + +#ifndef RAPIDJSON_NOEXCEPT_ASSERT +#ifdef RAPIDJSON_ASSERT_THROWS +#include +#define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x) +#else +#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x) +#endif // RAPIDJSON_ASSERT_THROWS +#endif // RAPIDJSON_NOEXCEPT_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// malloc/realloc/free + +#ifndef RAPIDJSON_MALLOC +///! customization point for global \c malloc +#define RAPIDJSON_MALLOC(size) std::malloc(size) +#endif +#ifndef RAPIDJSON_REALLOC +///! customization point for global \c realloc +#define RAPIDJSON_REALLOC(ptr, new_size) std::realloc(ptr, new_size) +#endif +#ifndef RAPIDJSON_FREE +///! customization point for global \c free +#define RAPIDJSON_FREE(ptr) std::free(ptr) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// new/delete + +#ifndef RAPIDJSON_NEW +///! customization point for global \c new +#define RAPIDJSON_NEW(TypeName) new TypeName +#endif +#ifndef RAPIDJSON_DELETE +///! customization point for global \c delete +#define RAPIDJSON_DELETE(x) delete x +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Type + +/*! \namespace rapidjson + \brief main RapidJSON namespace + \see RAPIDJSON_NAMESPACE +*/ +RAPIDJSON_NAMESPACE_BEGIN + +//! Type of JSON value +enum Type { + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6 //!< number +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/reader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/reader.h new file mode 100644 index 0000000..5554660 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/reader.h @@ -0,0 +1,2246 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_READER_H_ +#define RAPIDJSON_READER_H_ + +/*! \file reader.h */ + +#include "allocators.h" +#include "stream.h" +#include "encodedstream.h" +#include "internal/clzll.h" +#include "internal/meta.h" +#include "internal/stack.h" +#include "internal/strtod.h" +#include + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#elif defined(RAPIDJSON_NEON) +#include +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(old-style-cast) +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define RAPIDJSON_NOTHING /* deliberately empty */ +#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \ + RAPIDJSON_MULTILINEMACRO_END +#endif +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING) +//!@endcond + +/*! \def RAPIDJSON_PARSE_ERROR_NORETURN + \ingroup RAPIDJSON_ERRORS + \brief Macro to indicate a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + This macros can be used as a customization point for the internal + error handling mechanism of RapidJSON. + + A common usage model is to throw an exception instead of requiring the + caller to explicitly check the \ref rapidjson::GenericReader::Parse's + return value: + + \code + #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \ + throw ParseException(parseErrorCode, #parseErrorCode, offset) + + #include // std::runtime_error + #include "rapidjson/error/error.h" // rapidjson::ParseResult + + struct ParseException : std::runtime_error, rapidjson::ParseResult { + ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset) + : std::runtime_error(msg), ParseResult(code, offset) {} + }; + + #include "rapidjson/reader.h" + \endcode + + \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse + */ +#ifndef RAPIDJSON_PARSE_ERROR_NORETURN +#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \ + SetParseError(parseErrorCode, offset); \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +/*! \def RAPIDJSON_PARSE_ERROR + \ingroup RAPIDJSON_ERRORS + \brief (Internal) macro to indicate and handle a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing. + + \see RAPIDJSON_PARSE_ERROR_NORETURN + \hideinitializer + */ +#ifndef RAPIDJSON_PARSE_ERROR +#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +#include "error/error.h" // ParseErrorCode, ParseResult + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseFlag + +/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kParseDefaultFlags definition. + + User can define this as any \c ParseFlag combinations. +*/ +#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS +#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags +#endif + +//! Combination of parseFlags +/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream + */ +enum ParseFlag { + kParseNoFlags = 0, //!< No flags are set. + kParseInsituFlag = 1, //!< In-situ(destructive) parsing. + kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. + kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. + kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. + kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). + kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments. + kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings. + kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays. + kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles. + kParseEscapedApostropheFlag = 512, //!< Allow escaped apostrophe in strings. + kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS +}; + +/////////////////////////////////////////////////////////////////////////////// +// Handler + +/*! \class rapidjson::Handler + \brief Concept for receiving events from GenericReader upon parsing. + The functions return true if no error occurs. If they return false, + the event publisher should terminate the process. +\code +concept Handler { + typename Ch; + + bool Null(); + bool Bool(bool b); + bool Int(int i); + bool Uint(unsigned i); + bool Int64(int64_t i); + bool Uint64(uint64_t i); + bool Double(double d); + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType length, bool copy); + bool String(const Ch* str, SizeType length, bool copy); + bool StartObject(); + bool Key(const Ch* str, SizeType length, bool copy); + bool EndObject(SizeType memberCount); + bool StartArray(); + bool EndArray(SizeType elementCount); +}; +\endcode +*/ +/////////////////////////////////////////////////////////////////////////////// +// BaseReaderHandler + +//! Default implementation of Handler. +/*! This can be used as base class of any reader handler. + \note implements Handler concept +*/ +template, typename Derived = void> +struct BaseReaderHandler { + typedef typename Encoding::Ch Ch; + + typedef typename internal::SelectIf, BaseReaderHandler, Derived>::Type Override; + + bool Default() { return true; } + bool Null() { return static_cast(*this).Default(); } + bool Bool(bool) { return static_cast(*this).Default(); } + bool Int(int) { return static_cast(*this).Default(); } + bool Uint(unsigned) { return static_cast(*this).Default(); } + bool Int64(int64_t) { return static_cast(*this).Default(); } + bool Uint64(uint64_t) { return static_cast(*this).Default(); } + bool Double(double) { return static_cast(*this).Default(); } + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } + bool String(const Ch*, SizeType, bool) { return static_cast(*this).Default(); } + bool StartObject() { return static_cast(*this).Default(); } + bool Key(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } + bool EndObject(SizeType) { return static_cast(*this).Default(); } + bool StartArray() { return static_cast(*this).Default(); } + bool EndArray(SizeType) { return static_cast(*this).Default(); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// StreamLocalCopy + +namespace internal { + +template::copyOptimization> +class StreamLocalCopy; + +//! Do copy optimization. +template +class StreamLocalCopy { +public: + StreamLocalCopy(Stream& original) : s(original), original_(original) {} + ~StreamLocalCopy() { original_ = s; } + + Stream s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; + + Stream& original_; +}; + +//! Keep reference. +template +class StreamLocalCopy { +public: + StreamLocalCopy(Stream& original) : s(original) {} + + Stream& s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// SkipWhitespace + +//! Skip the JSON white spaces in a stream. +/*! \param is A input stream for skipping white spaces. + \note This function has SSE2/SSE4.2 specialization. +*/ +template +void SkipWhitespace(InputStream& is) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + typename InputStream::Ch c; + while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t') + s.Take(); +} + +inline const char* SkipWhitespace(const char* p, const char* end) { + while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + return p; +} + +#ifdef RAPIDJSON_SSE42 +//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); + if (r != 16) // some of characters is non-whitespace + return p + r; + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The middle of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); + const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); + if (r != 16) // some of characters is non-whitespace + return p + r; + } + + return SkipWhitespace(p, end); +} + +#elif defined(RAPIDJSON_SSE2) + +//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } + + return SkipWhitespace(p, end); +} + +#elif defined(RAPIDJSON_NEON) + +//! Skip whitespace with ARM Neon instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + const uint8x16_t w0 = vmovq_n_u8(' '); + const uint8x16_t w1 = vmovq_n_u8('\n'); + const uint8x16_t w2 = vmovq_n_u8('\r'); + const uint8x16_t w3 = vmovq_n_u8('\t'); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, w0); + x = vorrq_u8(x, vceqq_u8(s, w1)); + x = vorrq_u8(x, vceqq_u8(s, w2)); + x = vorrq_u8(x, vceqq_u8(s, w3)); + + x = vmvnq_u8(x); // Negate + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + return p + 8 + (lz >> 3); + } + } else { + uint32_t lz = internal::clzll(low); + return p + (lz >> 3); + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + const uint8x16_t w0 = vmovq_n_u8(' '); + const uint8x16_t w1 = vmovq_n_u8('\n'); + const uint8x16_t w2 = vmovq_n_u8('\r'); + const uint8x16_t w3 = vmovq_n_u8('\t'); + + for (; p <= end - 16; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, w0); + x = vorrq_u8(x, vceqq_u8(s, w1)); + x = vorrq_u8(x, vceqq_u8(s, w2)); + x = vorrq_u8(x, vceqq_u8(s, w3)); + + x = vmvnq_u8(x); // Negate + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + return p + 8 + (lz >> 3); + } + } else { + uint32_t lz = internal::clzll(low); + return p + (lz >> 3); + } + } + + return SkipWhitespace(p, end); +} + +#endif // RAPIDJSON_NEON + +#ifdef RAPIDJSON_SIMD +//! Template function specialization for InsituStringStream +template<> inline void SkipWhitespace(InsituStringStream& is) { + is.src_ = const_cast(SkipWhitespace_SIMD(is.src_)); +} + +//! Template function specialization for StringStream +template<> inline void SkipWhitespace(StringStream& is) { + is.src_ = SkipWhitespace_SIMD(is.src_); +} + +template<> inline void SkipWhitespace(EncodedInputStream, MemoryStream>& is) { + is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_); +} +#endif // RAPIDJSON_SIMD + +/////////////////////////////////////////////////////////////////////////////// +// GenericReader + +//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator. +/*! GenericReader parses JSON text from a stream, and send events synchronously to an + object implementing Handler concept. + + It needs to allocate a stack for storing a single decoded string during + non-destructive parsing. + + For in-situ parsing, the decoded string is directly written to the source + text string, no temporary buffer is required. + + A GenericReader object can be reused for parsing multiple JSON text. + + \tparam SourceEncoding Encoding of the input stream. + \tparam TargetEncoding Encoding of the parse output. + \tparam StackAllocator Allocator type for stack. +*/ +template +class GenericReader { +public: + typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type + + //! Constructor. + /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) + \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) + */ + GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : + stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {} + + //! Parse JSON text. + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream& is, Handler& handler) { + if (parseFlags & kParseIterativeFlag) + return IterativeParse(is, handler); + + parseResult_.Clear(); + + ClearStackOnExit scope(*this); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + else { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (!(parseFlags & kParseStopWhenDoneFlag)) { + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + } + } + + return parseResult_; + } + + //! Parse JSON text (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream& is, Handler& handler) { + return Parse(is, handler); + } + + //! Initialize JSON text token-by-token parsing + /*! + */ + void IterativeParseInit() { + parseResult_.Clear(); + state_ = IterativeParsingStartState; + } + + //! Parse one token from JSON text + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + bool IterativeParseNext(InputStream& is, Handler& handler) { + while (RAPIDJSON_LIKELY(is.Peek() != '\0')) { + SkipWhitespaceAndComments(is); + + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state_, t); + IterativeParsingState d = Transit(state_, t, n, is, handler); + + // If we've finished or hit an error... + if (RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d))) { + // Report errors. + if (d == IterativeParsingErrorState) { + HandleError(state_, is); + return false; + } + + // Transition to the finish state. + RAPIDJSON_ASSERT(d == IterativeParsingFinishState); + state_ = d; + + // If StopWhenDone is not set... + if (!(parseFlags & kParseStopWhenDoneFlag)) { + // ... and extra non-whitespace data is found... + SkipWhitespaceAndComments(is); + if (is.Peek() != '\0') { + // ... this is considered an error. + HandleError(state_, is); + return false; + } + } + + // Success! We are done! + return true; + } + + // Transition to the new state. + state_ = d; + + // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now. + if (!IsIterativeParsingDelimiterState(n)) + return true; + } + + // We reached the end of file. + stack_.Clear(); + + if (state_ != IterativeParsingFinishState) { + HandleError(state_, is); + return false; + } + + return true; + } + + //! Check if token-by-token parsing JSON text is complete + /*! \return Whether the JSON has been fully decoded. + */ + RAPIDJSON_FORCEINLINE bool IterativeParseComplete() const { + return IsIterativeParsingCompleteState(state_); + } + + //! Whether a parse error has occurred in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + +protected: + void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); } + +private: + // Prohibit copy constructor & assignment operator. + GenericReader(const GenericReader&); + GenericReader& operator=(const GenericReader&); + + void ClearStack() { stack_.Clear(); } + + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericReader& r) : r_(r) {} + ~ClearStackOnExit() { r_.ClearStack(); } + private: + GenericReader& r_; + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + }; + + template + void SkipWhitespaceAndComments(InputStream& is) { + SkipWhitespace(is); + + if (parseFlags & kParseCommentsFlag) { + while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) { + if (Consume(is, '*')) { + while (true) { + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + else if (Consume(is, '*')) { + if (Consume(is, '/')) + break; + } + else + is.Take(); + } + } + else if (RAPIDJSON_LIKELY(Consume(is, '/'))) + while (is.Peek() != '\0' && is.Take() != '\n') {} + else + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + + SkipWhitespace(is); + } + } + } + + // Parse object: { string : value, ... } + template + void ParseObject(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '{'); + is.Take(); // Skip '{' + + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, '}')) { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType memberCount = 0;;) { + if (RAPIDJSON_UNLIKELY(is.Peek() != '"')) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + + ParseString(is, handler, true); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (RAPIDJSON_UNLIKELY(!Consume(is, ':'))) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++memberCount; + + switch (is.Peek()) { + case ',': + is.Take(); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + break; + case '}': + is.Take(); + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + default: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy + } + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == '}') { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } + } + } + } + + // Parse array: [ value, ... ] + template + void ParseArray(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '['); + is.Take(); // Skip '[' + + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType elementCount = 0;;) { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++elementCount; + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ',')) { + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + } + else if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == ']') { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } + } + } + } + + template + void ParseNull(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'n'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) { + if (RAPIDJSON_UNLIKELY(!handler.Null())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + void ParseTrue(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 't'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(true))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + void ParseFalse(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'f'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(false))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) { + if (RAPIDJSON_LIKELY(is.Peek() == expect)) { + is.Take(); + return true; + } + else + return false; + } + + // Helper function to parse four hexadecimal digits in \uXXXX in ParseString(). + template + unsigned ParseHex4(InputStream& is, size_t escapeOffset) { + unsigned codepoint = 0; + for (int i = 0; i < 4; i++) { + Ch c = is.Peek(); + codepoint <<= 4; + codepoint += static_cast(c); + if (c >= '0' && c <= '9') + codepoint -= '0'; + else if (c >= 'A' && c <= 'F') + codepoint -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + codepoint -= 'a' - 10; + else { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0); + } + is.Take(); + } + return codepoint; + } + + template + class StackStream { + public: + typedef CharType Ch; + + StackStream(internal::Stack& stack) : stack_(stack), length_(0) {} + RAPIDJSON_FORCEINLINE void Put(Ch c) { + *stack_.template Push() = c; + ++length_; + } + + RAPIDJSON_FORCEINLINE void* Push(SizeType count) { + length_ += count; + return stack_.template Push(count); + } + + size_t Length() const { return length_; } + + Ch* Pop() { + return stack_.template Pop(length_); + } + + private: + StackStream(const StackStream&); + StackStream& operator=(const StackStream&); + + internal::Stack& stack_; + SizeType length_; + }; + + // Parse string and generate String event. Different code paths for kParseInsituFlag. + template + void ParseString(InputStream& is, Handler& handler, bool isKey = false) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + RAPIDJSON_ASSERT(s.Peek() == '\"'); + s.Take(); // Skip '\"' + + bool success = false; + if (parseFlags & kParseInsituFlag) { + typename InputStream::Ch *head = s.PutBegin(); + ParseStringToStream(s, s); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + size_t length = s.PutEnd(head) - 1; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); + success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); + } + else { + StackStream stackStream(stack_); + ParseStringToStream(s, stackStream); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SizeType length = static_cast(stackStream.Length()) - 1; + const typename TargetEncoding::Ch* const str = stackStream.Pop(); + success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true)); + } + if (RAPIDJSON_UNLIKELY(!success)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + + // Parse string to an output is + // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. + template + RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) { +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + static const char escape[256] = { + Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', + Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, + 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 + }; +#undef Z16 +//!@endcond + + for (;;) { + // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation. + if (!(parseFlags & kParseValidateEncodingFlag)) + ScanCopyUnescapedString(is, os); + + Ch c = is.Peek(); + if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape + size_t escapeOffset = is.Tell(); // For invalid escaping, report the initial '\\' as error offset + is.Take(); + Ch e = is.Peek(); + if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast(e)])) { + is.Take(); + os.Put(static_cast(escape[static_cast(e)])); + } + else if ((parseFlags & kParseEscapedApostropheFlag) && RAPIDJSON_LIKELY(e == '\'')) { // Allow escaped apostrophe + is.Take(); + os.Put('\''); + } + else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode + is.Take(); + unsigned codepoint = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDFFF)) { + // high surrogate, check if followed by valid low surrogate + if (RAPIDJSON_LIKELY(codepoint <= 0xDBFF)) { + // Handle UTF-16 surrogate pair + if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u'))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + unsigned codepoint2 = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; + } + // single low surrogate + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + } + } + TEncoding::Encode(os, codepoint); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset); + } + else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote + is.Take(); + os.Put('\0'); // null-terminate the string + return; + } + else if (RAPIDJSON_UNLIKELY(static_cast(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + if (c == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell()); + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell()); + } + else { + size_t offset = is.Tell(); + if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? + !Transcoder::Validate(is, os) : + !Transcoder::Transcode(is, os)))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset); + } + } + } + + template + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) { + // Do nothing for generic version + } + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) + // StringStream -> StackStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream& os) { + const char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + return; + } + else + os.Put(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType length; + #ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; + #else + length = static_cast(__builtin_ffs(r) - 1); + #endif + if (length != 0) { + char* q = reinterpret_cast(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + } + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s); + } + + is.src_ = p; + } + + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { + RAPIDJSON_ASSERT(&is == &os); + (void)os; + + if (is.src_ == is.dst_) { + SkipUnescapedString(is); + return; + } + + char* p = is.src_; + char *q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + is.dst_ = q; + return; + } + else + *q++ = *p++; + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16, q += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast(__builtin_ffs(r) - 1); +#endif + for (const char* pend = p + length; p != pend; ) + *q++ = *p++; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s); + } + + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast(__builtin_ffs(r) - 1); +#endif + p += length; + break; + } + } + + is.src_ = is.dst_ = p; + } +#elif defined(RAPIDJSON_NEON) + // StringStream -> StackStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream& os) { + const char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + return; + } + else + os.Put(*p++); + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + SizeType length = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + length = 8 + (lz >> 3); + escaped = true; + } + } else { + uint32_t lz = internal::clzll(low); + length = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + if (length != 0) { + char* q = reinterpret_cast(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + } + break; + } + vst1q_u8(reinterpret_cast(os.Push(16)), s); + } + + is.src_ = p; + } + + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { + RAPIDJSON_ASSERT(&is == &os); + (void)os; + + if (is.src_ == is.dst_) { + SkipUnescapedString(is); + return; + } + + char* p = is.src_; + char *q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + is.dst_ = q; + return; + } + else + *q++ = *p++; + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16, q += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + SizeType length = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + length = 8 + (lz >> 3); + escaped = true; + } + } else { + uint32_t lz = internal::clzll(low); + length = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + for (const char* pend = p + length; p != pend; ) { + *q++ = *p++; + } + break; + } + vst1q_u8(reinterpret_cast(q), s); + } + + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + p += 8 + (lz >> 3); + break; + } + } else { + uint32_t lz = internal::clzll(low); + p += lz >> 3; + break; + } + } + + is.src_ = is.dst_ = p; + } +#endif // RAPIDJSON_NEON + + template + class NumberStream; + + template + class NumberStream { + public: + typedef typename InputStream::Ch Ch; + + NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; } + + RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); } + RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); } + RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); } + RAPIDJSON_FORCEINLINE void Push(char) {} + + size_t Tell() { return is.Tell(); } + size_t Length() { return 0; } + const StackCharacter* Pop() { return 0; } + + protected: + NumberStream& operator=(const NumberStream&); + + InputStream& is; + }; + + template + class NumberStream : public NumberStream { + typedef NumberStream Base; + public: + NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s), stackStream(reader.stack_) {} + + RAPIDJSON_FORCEINLINE Ch TakePush() { + stackStream.Put(static_cast(Base::is.Peek())); + return Base::is.Take(); + } + + RAPIDJSON_FORCEINLINE void Push(StackCharacter c) { + stackStream.Put(c); + } + + size_t Length() { return stackStream.Length(); } + + const StackCharacter* Pop() { + stackStream.Put('\0'); + return stackStream.Pop(); + } + + private: + StackStream stackStream; + }; + + template + class NumberStream : public NumberStream { + typedef NumberStream Base; + public: + NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s) {} + + RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } + }; + + template + void ParseNumber(InputStream& is, Handler& handler) { + typedef typename internal::SelectIf, typename TargetEncoding::Ch, char>::Type NumberCharacter; + + internal::StreamLocalCopy copy(is); + NumberStream s(*this, copy.s); + + size_t startOffset = s.Tell(); + double d = 0.0; + bool useNanOrInf = false; + + // Parse minus + bool minus = Consume(s, '-'); + + // Parse int: zero / ( digit1-9 *DIGIT ) + unsigned i = 0; + uint64_t i64 = 0; + bool use64bit = false; + int significandDigit = 0; + if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) { + i = 0; + s.TakePush(); + } + else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) { + i = static_cast(s.TakePush() - '0'); + + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648 + if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295 + if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + // Parse NaN or Infinity here + else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) { + if (Consume(s, 'N')) { + if (Consume(s, 'a') && Consume(s, 'N')) { + d = std::numeric_limits::quiet_NaN(); + useNanOrInf = true; + } + } + else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) { + if (Consume(s, 'n') && Consume(s, 'f')) { + d = (minus ? -std::numeric_limits::infinity() : std::numeric_limits::infinity()); + useNanOrInf = true; + + if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') + && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + } + } + + if (RAPIDJSON_UNLIKELY(!useNanOrInf)) { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + + // Parse 64bit int + bool useDouble = false; + if (use64bit) { + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) { + d = static_cast(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) { + d = static_cast(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + + // Force double for big integer + if (useDouble) { + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + d = d * 10 + (s.TakePush() - '0'); + } + } + + // Parse frac = decimal-point 1*DIGIT + int expFrac = 0; + size_t decimalPosition; + if (Consume(s, '.')) { + decimalPosition = s.Length(); + + if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9'))) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell()); + + if (!useDouble) { +#if RAPIDJSON_64BIT + // Use i64 to store significand in 64-bit architecture + if (!use64bit) + i64 = i; + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path + break; + else { + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + --expFrac; + if (i64 != 0) + significandDigit++; + } + } + + d = static_cast(i64); +#else + // Use double to store significand in 32-bit architecture + d = static_cast(use64bit ? i64 : i); +#endif + useDouble = true; + } + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (significandDigit < 17) { + d = d * 10.0 + (s.TakePush() - '0'); + --expFrac; + if (RAPIDJSON_LIKELY(d > 0.0)) + significandDigit++; + } + else + s.TakePush(); + } + } + else + decimalPosition = s.Length(); // decimal position at the end of integer. + + // Parse exp = e [ minus / plus ] 1*DIGIT + int exp = 0; + if (Consume(s, 'e') || Consume(s, 'E')) { + if (!useDouble) { + d = static_cast(use64bit ? i64 : i); + useDouble = true; + } + + bool expMinus = false; + if (Consume(s, '+')) + ; + else if (Consume(s, '-')) + expMinus = true; + + if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = static_cast(s.Take() - '0'); + if (expMinus) { + // (exp + expFrac) must not underflow int => we're detecting when -exp gets + // dangerously close to INT_MIN (a pessimistic next digit 9 would push it into + // underflow territory): + // + // -(exp * 10 + 9) + expFrac >= INT_MIN + // <=> exp <= (expFrac - INT_MIN - 9) / 10 + RAPIDJSON_ASSERT(expFrac <= 0); + int maxExp = (expFrac + 2147483639) / 10; + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast(s.Take() - '0'); + if (RAPIDJSON_UNLIKELY(exp > maxExp)) { + while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent + s.Take(); + } + } + } + else { // positive exp + int maxExp = 308 - expFrac; + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast(s.Take() - '0'); + if (RAPIDJSON_UNLIKELY(exp > maxExp)) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + } + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell()); + + if (expMinus) + exp = -exp; + } + + // Finish parsing, call event according to the type of number. + bool cont = true; + + if (parseFlags & kParseNumbersAsStringsFlag) { + if (parseFlags & kParseInsituFlag) { + s.Pop(); // Pop stack no matter if it will be used or not. + typename InputStream::Ch* head = is.PutBegin(); + const size_t length = s.Tell() - startOffset; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + // unable to insert the \0 character here, it will erase the comma after this number + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); + cont = handler.RawNumber(str, SizeType(length), false); + } + else { + SizeType numCharsToCopy = static_cast(s.Length()); + GenericStringStream > srcStream(s.Pop()); + StackStream dstStream(stack_); + while (numCharsToCopy--) { + Transcoder, TargetEncoding>::Transcode(srcStream, dstStream); + } + dstStream.Put('\0'); + const typename TargetEncoding::Ch* str = dstStream.Pop(); + const SizeType length = static_cast(dstStream.Length()) - 1; + cont = handler.RawNumber(str, SizeType(length), true); + } + } + else { + size_t length = s.Length(); + const NumberCharacter* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + + if (useDouble) { + int p = exp + expFrac; + if (parseFlags & kParseFullPrecisionFlag) + d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); + else + d = internal::StrtodNormalPrecision(d, p); + + // Use > max, instead of == inf, to fix bogus warning -Wfloat-equal + if (d > (std::numeric_limits::max)()) { + // Overflow + // TODO: internal::StrtodX should report overflow (or underflow) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + } + + cont = handler.Double(minus ? -d : d); + } + else if (useNanOrInf) { + cont = handler.Double(d); + } + else { + if (use64bit) { + if (minus) + cont = handler.Int64(static_cast(~i64 + 1)); + else + cont = handler.Uint64(i64); + } + else { + if (minus) + cont = handler.Int(static_cast(~i + 1)); + else + cont = handler.Uint(i); + } + } + } + if (RAPIDJSON_UNLIKELY(!cont)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset); + } + + // Parse any JSON value + template + void ParseValue(InputStream& is, Handler& handler) { + switch (is.Peek()) { + case 'n': ParseNull (is, handler); break; + case 't': ParseTrue (is, handler); break; + case 'f': ParseFalse (is, handler); break; + case '"': ParseString(is, handler); break; + case '{': ParseObject(is, handler); break; + case '[': ParseArray (is, handler); break; + default : + ParseNumber(is, handler); + break; + + } + } + + // Iterative Parsing + + // States + enum IterativeParsingState { + IterativeParsingFinishState = 0, // sink states at top + IterativeParsingErrorState, // sink states at top + IterativeParsingStartState, + + // Object states + IterativeParsingObjectInitialState, + IterativeParsingMemberKeyState, + IterativeParsingMemberValueState, + IterativeParsingObjectFinishState, + + // Array states + IterativeParsingArrayInitialState, + IterativeParsingElementState, + IterativeParsingArrayFinishState, + + // Single value state + IterativeParsingValueState, + + // Delimiter states (at bottom) + IterativeParsingElementDelimiterState, + IterativeParsingMemberDelimiterState, + IterativeParsingKeyValueDelimiterState, + + cIterativeParsingStateCount + }; + + // Tokens + enum Token { + LeftBracketToken = 0, + RightBracketToken, + + LeftCurlyBracketToken, + RightCurlyBracketToken, + + CommaToken, + ColonToken, + + StringToken, + FalseToken, + TrueToken, + NullToken, + NumberToken, + + kTokenCount + }; + + RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) const { + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define N NumberToken +#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N + // Maps from ASCII to Token + static const unsigned char tokenMap[256] = { + N16, // 00~0F + N16, // 10~1F + N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F + N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F + N16, // 40~4F + N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F + N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F + N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F + N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF + }; +#undef N +#undef N16 +//!@endcond + + if (sizeof(Ch) == 1 || static_cast(c) < 256) + return static_cast(tokenMap[static_cast(c)]); + else + return NumberToken; + } + + RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) const { + // current state x one lookahead token -> new state + static const char G[cIterativeParsingStateCount][kTokenCount] = { + // Finish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Error(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Start + { + IterativeParsingArrayInitialState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingValueState, // String + IterativeParsingValueState, // False + IterativeParsingValueState, // True + IterativeParsingValueState, // Null + IterativeParsingValueState // Number + }, + // ObjectInitial + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberKey + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingKeyValueDelimiterState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberValue + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingMemberDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ObjectFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ArrayInitial + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // Element + { + IterativeParsingErrorState, // Left bracket + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingElementDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ArrayFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Single Value (sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ElementDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // MemberDelimiter + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // KeyValueDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberValueState, // String + IterativeParsingMemberValueState, // False + IterativeParsingMemberValueState, // True + IterativeParsingMemberValueState, // Null + IterativeParsingMemberValueState // Number + }, + }; // End of G + + return static_cast(G[state][token]); + } + + // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). + // May return a new state on state pop. + template + RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) { + (void)token; + + switch (dst) { + case IterativeParsingErrorState: + return dst; + + case IterativeParsingObjectInitialState: + case IterativeParsingArrayInitialState: + { + // Push the state(Element or MemeberValue) if we are nested in another array or value of member. + // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. + IterativeParsingState n = src; + if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState) + n = IterativeParsingElementState; + else if (src == IterativeParsingKeyValueDelimiterState) + n = IterativeParsingMemberValueState; + // Push current state. + *stack_.template Push(1) = n; + // Initialize and push the member/element count. + *stack_.template Push(1) = 0; + // Call handler + bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray(); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return dst; + } + } + + case IterativeParsingMemberKeyState: + ParseString(is, handler, true); + if (HasParseError()) + return IterativeParsingErrorState; + else + return dst; + + case IterativeParsingKeyValueDelimiterState: + RAPIDJSON_ASSERT(token == ColonToken); + is.Take(); + return dst; + + case IterativeParsingMemberValueState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingElementState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingMemberDelimiterState: + case IterativeParsingElementDelimiterState: + is.Take(); + // Update member/element count. + *stack_.template Top() = *stack_.template Top() + 1; + return dst; + + case IterativeParsingObjectFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell()); + return IterativeParsingErrorState; + } + // Get member count. + SizeType c = *stack_.template Pop(1); + // If the object is not empty, count the last member. + if (src == IterativeParsingMemberValueState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndObject(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + case IterativeParsingArrayFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell()); + return IterativeParsingErrorState; + } + // Get element count. + SizeType c = *stack_.template Pop(1); + // If the array is not empty, count the last element. + if (src == IterativeParsingElementState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndArray(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + default: + // This branch is for IterativeParsingValueState actually. + // Use `default:` rather than + // `case IterativeParsingValueState:` is for code coverage. + + // The IterativeParsingStartState is not enumerated in this switch-case. + // It is impossible for that case. And it can be caught by following assertion. + + // The IterativeParsingFinishState is not enumerated in this switch-case either. + // It is a "derivative" state which cannot triggered from Predict() directly. + // Therefore it cannot happen here. And it can be caught by following assertion. + RAPIDJSON_ASSERT(dst == IterativeParsingValueState); + + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return IterativeParsingFinishState; + } + } + + template + void HandleError(IterativeParsingState src, InputStream& is) { + if (HasParseError()) { + // Error flag has been set. + return; + } + + switch (src) { + case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; + case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; + case IterativeParsingObjectInitialState: + case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; + case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; + case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; + case IterativeParsingKeyValueDelimiterState: + case IterativeParsingArrayInitialState: + case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return; + default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; + } + } + + RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) const { + return s >= IterativeParsingElementDelimiterState; + } + + RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) const { + return s <= IterativeParsingErrorState; + } + + template + ParseResult IterativeParse(InputStream& is, Handler& handler) { + parseResult_.Clear(); + ClearStackOnExit scope(*this); + IterativeParsingState state = IterativeParsingStartState; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + while (is.Peek() != '\0') { + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state, t); + IterativeParsingState d = Transit(state, t, n, is, handler); + + if (d == IterativeParsingErrorState) { + HandleError(state, is); + break; + } + + state = d; + + // Do not further consume streams if a root JSON has been parsed. + if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) + break; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + + // Handle the end of file. + if (state != IterativeParsingFinishState) + HandleError(state, is); + + return parseResult_; + } + + static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + ParseResult parseResult_; + IterativeParsingState state_; +}; // class GenericReader + +//! Reader with UTF8 encoding and default allocator. +typedef GenericReader, UTF8<> > Reader; + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_READER_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/schema.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/schema.h new file mode 100644 index 0000000..439133f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/schema.h @@ -0,0 +1,3262 @@ +// Tencent is pleased to support the open source community by making RapidJSON available-> +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved-> +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License-> You may obtain a copy of the License at +// +// http://opensource->org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied-> See the License for the +// specific language governing permissions and limitations under the License-> + +#ifndef RAPIDJSON_SCHEMA_H_ +#define RAPIDJSON_SCHEMA_H_ + +#include "document.h" +#include "pointer.h" +#include "stringbuffer.h" +#include "error/en.h" +#include "uri.h" +#include // abs, floor + +#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX) +#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1 +#else +#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0 +#endif + +#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)) +#define RAPIDJSON_SCHEMA_USE_STDREGEX 1 +#else +#define RAPIDJSON_SCHEMA_USE_STDREGEX 0 +#endif + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX +#include "internal/regex.h" +#elif RAPIDJSON_SCHEMA_USE_STDREGEX +#include +#endif + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX +#define RAPIDJSON_SCHEMA_HAS_REGEX 1 +#else +#define RAPIDJSON_SCHEMA_HAS_REGEX 0 +#endif + +#ifndef RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_VERBOSE 0 +#endif + +RAPIDJSON_DIAG_PUSH + +#if defined(__GNUC__) +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(weak-vtables) +RAPIDJSON_DIAG_OFF(exit-time-destructors) +RAPIDJSON_DIAG_OFF(c++98-compat-pedantic) +RAPIDJSON_DIAG_OFF(variadic-macros) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Verbose Utilities + +#if RAPIDJSON_SCHEMA_VERBOSE + +namespace internal { + +inline void PrintInvalidKeywordData(const char* keyword) { + printf(" Fail keyword: '%s'\n", keyword); +} + +inline void PrintInvalidKeywordData(const wchar_t* keyword) { + wprintf(L" Fail keyword: '%ls'\n", keyword); +} + +inline void PrintInvalidDocumentData(const char* document) { + printf(" Fail document: '%s'\n", document); +} + +inline void PrintInvalidDocumentData(const wchar_t* document) { + wprintf(L" Fail document: '%ls'\n", document); +} + +inline void PrintValidatorPointersData(const char* s, const char* d, unsigned depth) { + printf(" Sch: %*s'%s'\n Doc: %*s'%s'\n", depth * 4, " ", s, depth * 4, " ", d); +} + +inline void PrintValidatorPointersData(const wchar_t* s, const wchar_t* d, unsigned depth) { + wprintf(L" Sch: %*ls'%ls'\n Doc: %*ls'%ls'\n", depth * 4, L" ", s, depth * 4, L" ", d); +} + +inline void PrintSchemaIdsData(const char* base, const char* local, const char* resolved) { + printf(" Resolving id: Base: '%s', Local: '%s', Resolved: '%s'\n", base, local, resolved); +} + +inline void PrintSchemaIdsData(const wchar_t* base, const wchar_t* local, const wchar_t* resolved) { + wprintf(L" Resolving id: Base: '%ls', Local: '%ls', Resolved: '%ls'\n", base, local, resolved); +} + +inline void PrintMethodData(const char* method) { + printf("%s\n", method); +} + +inline void PrintMethodData(const char* method, bool b) { + printf("%s, Data: '%s'\n", method, b ? "true" : "false"); +} + +inline void PrintMethodData(const char* method, int64_t i) { + printf("%s, Data: '%" PRId64 "'\n", method, i); +} + +inline void PrintMethodData(const char* method, uint64_t u) { + printf("%s, Data: '%" PRIu64 "'\n", method, u); +} + +inline void PrintMethodData(const char* method, double d) { + printf("%s, Data: '%lf'\n", method, d); +} + +inline void PrintMethodData(const char* method, const char* s) { + printf("%s, Data: '%s'\n", method, s); +} + +inline void PrintMethodData(const char* method, const wchar_t* s) { + wprintf(L"%hs, Data: '%ls'\n", method, s); +} + +inline void PrintMethodData(const char* method, const char* s1, const char* s2) { + printf("%s, Data: '%s', '%s'\n", method, s1, s2); +} + +inline void PrintMethodData(const char* method, const wchar_t* s1, const wchar_t* s2) { + wprintf(L"%hs, Data: '%ls', '%ls'\n", method, s1, s2); +} + +} // namespace internal + +#endif // RAPIDJSON_SCHEMA_VERBOSE + +#ifndef RAPIDJSON_SCHEMA_PRINT +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_PRINT(name, ...) internal::Print##name##Data(__VA_ARGS__) +#else +#define RAPIDJSON_SCHEMA_PRINT(name, ...) +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_INVALID_KEYWORD_RETURN + +#define RAPIDJSON_INVALID_KEYWORD_RETURN(code)\ +RAPIDJSON_MULTILINEMACRO_BEGIN\ + context.invalidCode = code;\ + context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString();\ + RAPIDJSON_SCHEMA_PRINT(InvalidKeyword, context.invalidKeyword);\ + return false;\ +RAPIDJSON_MULTILINEMACRO_END + +/////////////////////////////////////////////////////////////////////////////// +// ValidateFlag + +/*! \def RAPIDJSON_VALIDATE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kValidateDefaultFlags definition. + + User can define this as any \c ValidateFlag combinations. +*/ +#ifndef RAPIDJSON_VALIDATE_DEFAULT_FLAGS +#define RAPIDJSON_VALIDATE_DEFAULT_FLAGS kValidateNoFlags +#endif + +//! Combination of validate flags +/*! \see + */ +enum ValidateFlag { + kValidateNoFlags = 0, //!< No flags are set. + kValidateContinueOnErrorFlag = 1, //!< Don't stop after first validation error. + kValidateReadFlag = 2, //!< Validation is for a read semantic. + kValidateWriteFlag = 4, //!< Validation is for a write semantic. + kValidateDefaultFlags = RAPIDJSON_VALIDATE_DEFAULT_FLAGS //!< Default validate flags. Can be customized by defining RAPIDJSON_VALIDATE_DEFAULT_FLAGS +}; + +/////////////////////////////////////////////////////////////////////////////// +// Specification +enum SchemaDraft { + kDraftUnknown = -1, + kDraftNone = 0, + kDraft03 = 3, + kDraftMin = 4, //!< Current minimum supported draft + kDraft04 = 4, + kDraft05 = 5, + kDraftMax = 5, //!< Current maximum supported draft + kDraft06 = 6, + kDraft07 = 7, + kDraft2019_09 = 8, + kDraft2020_12 = 9 +}; + +enum OpenApiVersion { + kVersionUnknown = -1, + kVersionNone = 0, + kVersionMin = 2, //!< Current minimum supported version + kVersion20 = 2, + kVersion30 = 3, + kVersionMax = 3, //!< Current maximum supported version + kVersion31 = 4, +}; + +struct Specification { + Specification(SchemaDraft d) : draft(d), oapi(kVersionNone) {} + Specification(OpenApiVersion o) : oapi(o) { + if (oapi == kVersion20) draft = kDraft04; + else if (oapi == kVersion30) draft = kDraft05; + else if (oapi == kVersion31) draft = kDraft2020_12; + else draft = kDraft04; + } + ~Specification() {} + bool IsSupported() const { + return ((draft >= kDraftMin && draft <= kDraftMax) && ((oapi == kVersionNone) || (oapi >= kVersionMin && oapi <= kVersionMax))); + } + SchemaDraft draft; + OpenApiVersion oapi; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Forward declarations + +template +class GenericSchemaDocument; + +namespace internal { + +template +class Schema; + +/////////////////////////////////////////////////////////////////////////////// +// ISchemaValidator + +class ISchemaValidator { +public: + virtual ~ISchemaValidator() {} + virtual bool IsValid() const = 0; + virtual void SetValidateFlags(unsigned flags) = 0; + virtual unsigned GetValidateFlags() const = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// ISchemaStateFactory + +template +class ISchemaStateFactory { +public: + virtual ~ISchemaStateFactory() {} + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&, const bool inheritContinueOnErrors) = 0; + virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0; + virtual void* CreateHasher() = 0; + virtual uint64_t GetHashCode(void* hasher) = 0; + virtual void DestroryHasher(void* hasher) = 0; + virtual void* MallocState(size_t size) = 0; + virtual void FreeState(void* p) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// IValidationErrorHandler + +template +class IValidationErrorHandler { +public: + typedef typename SchemaType::Ch Ch; + typedef typename SchemaType::SValue SValue; + + virtual ~IValidationErrorHandler() {} + + virtual void NotMultipleOf(int64_t actual, const SValue& expected) = 0; + virtual void NotMultipleOf(uint64_t actual, const SValue& expected) = 0; + virtual void NotMultipleOf(double actual, const SValue& expected) = 0; + virtual void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) = 0; + virtual void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) = 0; + virtual void AboveMaximum(double actual, const SValue& expected, bool exclusive) = 0; + virtual void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) = 0; + virtual void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) = 0; + virtual void BelowMinimum(double actual, const SValue& expected, bool exclusive) = 0; + + virtual void TooLong(const Ch* str, SizeType length, SizeType expected) = 0; + virtual void TooShort(const Ch* str, SizeType length, SizeType expected) = 0; + virtual void DoesNotMatch(const Ch* str, SizeType length) = 0; + + virtual void DisallowedItem(SizeType index) = 0; + virtual void TooFewItems(SizeType actualCount, SizeType expectedCount) = 0; + virtual void TooManyItems(SizeType actualCount, SizeType expectedCount) = 0; + virtual void DuplicateItems(SizeType index1, SizeType index2) = 0; + + virtual void TooManyProperties(SizeType actualCount, SizeType expectedCount) = 0; + virtual void TooFewProperties(SizeType actualCount, SizeType expectedCount) = 0; + virtual void StartMissingProperties() = 0; + virtual void AddMissingProperty(const SValue& name) = 0; + virtual bool EndMissingProperties() = 0; + virtual void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) = 0; + virtual void DisallowedProperty(const Ch* name, SizeType length) = 0; + + virtual void StartDependencyErrors() = 0; + virtual void StartMissingDependentProperties() = 0; + virtual void AddMissingDependentProperty(const SValue& targetName) = 0; + virtual void EndMissingDependentProperties(const SValue& sourceName) = 0; + virtual void AddDependencySchemaError(const SValue& souceName, ISchemaValidator* subvalidator) = 0; + virtual bool EndDependencyErrors() = 0; + + virtual void DisallowedValue(const ValidateErrorCode code) = 0; + virtual void StartDisallowedType() = 0; + virtual void AddExpectedType(const typename SchemaType::ValueType& expectedType) = 0; + virtual void EndDisallowedType(const typename SchemaType::ValueType& actualType) = 0; + virtual void NotAllOf(ISchemaValidator** subvalidators, SizeType count) = 0; + virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0; + virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count) = 0; + virtual void MultipleOneOf(SizeType index1, SizeType index2) = 0; + virtual void Disallowed() = 0; + virtual void DisallowedWhenWriting() = 0; + virtual void DisallowedWhenReading() = 0; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Hasher + +// For comparison of compound value +template +class Hasher { +public: + typedef typename Encoding::Ch Ch; + + Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {} + + bool Null() { return WriteType(kNullType); } + bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); } + bool Int(int i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } + bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } + bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } + bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } + bool Double(double d) { + Number n; + if (d < 0) n.u.i = static_cast(d); + else n.u.u = static_cast(d); + n.d = d; + return WriteNumber(n); + } + + bool RawNumber(const Ch* str, SizeType len, bool) { + WriteBuffer(kNumberType, str, len * sizeof(Ch)); + return true; + } + + bool String(const Ch* str, SizeType len, bool) { + WriteBuffer(kStringType, str, len * sizeof(Ch)); + return true; + } + + bool StartObject() { return true; } + bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); } + bool EndObject(SizeType memberCount) { + uint64_t h = Hash(0, kObjectType); + uint64_t* kv = stack_.template Pop(memberCount * 2); + for (SizeType i = 0; i < memberCount; i++) + h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive + *stack_.template Push() = h; + return true; + } + + bool StartArray() { return true; } + bool EndArray(SizeType elementCount) { + uint64_t h = Hash(0, kArrayType); + uint64_t* e = stack_.template Pop(elementCount); + for (SizeType i = 0; i < elementCount; i++) + h = Hash(h, e[i]); // Use hash to achieve element order sensitive + *stack_.template Push() = h; + return true; + } + + bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); } + + uint64_t GetHashCode() const { + RAPIDJSON_ASSERT(IsValid()); + return *stack_.template Top(); + } + +private: + static const size_t kDefaultSize = 256; + struct Number { + union U { + uint64_t u; + int64_t i; + }u; + double d; + }; + + bool WriteType(Type type) { return WriteBuffer(type, 0, 0); } + + bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); } + + bool WriteBuffer(Type type, const void* data, size_t len) { + // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/ + uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type); + const unsigned char* d = static_cast(data); + for (size_t i = 0; i < len; i++) + h = Hash(h, d[i]); + *stack_.template Push() = h; + return true; + } + + static uint64_t Hash(uint64_t h, uint64_t d) { + static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3); + h ^= d; + h *= kPrime; + return h; + } + + Stack stack_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidationContext + +template +struct SchemaValidationContext { + typedef Schema SchemaType; + typedef ISchemaStateFactory SchemaValidatorFactoryType; + typedef IValidationErrorHandler ErrorHandlerType; + typedef typename SchemaType::ValueType ValueType; + typedef typename ValueType::Ch Ch; + + enum PatternValidatorType { + kPatternValidatorOnly, + kPatternValidatorWithProperty, + kPatternValidatorWithAdditionalProperty + }; + + SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s, unsigned fl = 0) : + factory(f), + error_handler(eh), + schema(s), + flags(fl), + valueSchema(), + invalidKeyword(), + invalidCode(), + hasher(), + arrayElementHashCodes(), + validators(), + validatorCount(), + patternPropertiesValidators(), + patternPropertiesValidatorCount(), + patternPropertiesSchemas(), + patternPropertiesSchemaCount(), + valuePatternValidatorType(kPatternValidatorOnly), + propertyExist(), + inArray(false), + valueUniqueness(false), + arrayUniqueness(false) + { + } + + ~SchemaValidationContext() { + if (hasher) + factory.DestroryHasher(hasher); + if (validators) { + for (SizeType i = 0; i < validatorCount; i++) { + if (validators[i]) { + factory.DestroySchemaValidator(validators[i]); + } + } + factory.FreeState(validators); + } + if (patternPropertiesValidators) { + for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) { + if (patternPropertiesValidators[i]) { + factory.DestroySchemaValidator(patternPropertiesValidators[i]); + } + } + factory.FreeState(patternPropertiesValidators); + } + if (patternPropertiesSchemas) + factory.FreeState(patternPropertiesSchemas); + if (propertyExist) + factory.FreeState(propertyExist); + } + + SchemaValidatorFactoryType& factory; + ErrorHandlerType& error_handler; + const SchemaType* schema; + unsigned flags; + const SchemaType* valueSchema; + const Ch* invalidKeyword; + ValidateErrorCode invalidCode; + void* hasher; // Only validator access + void* arrayElementHashCodes; // Only validator access this + ISchemaValidator** validators; + SizeType validatorCount; + ISchemaValidator** patternPropertiesValidators; + SizeType patternPropertiesValidatorCount; + const SchemaType** patternPropertiesSchemas; + SizeType patternPropertiesSchemaCount; + PatternValidatorType valuePatternValidatorType; + PatternValidatorType objectPatternValidatorType; + SizeType arrayElementIndex; + bool* propertyExist; + bool inArray; + bool valueUniqueness; + bool arrayUniqueness; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Schema + +template +class Schema { +public: + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename SchemaDocumentType::AllocatorType AllocatorType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef SchemaValidationContext Context; + typedef Schema SchemaType; + typedef GenericValue SValue; + typedef IValidationErrorHandler ErrorHandler; + typedef GenericUri UriType; + friend class GenericSchemaDocument; + + Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator, const UriType& id = UriType()) : + allocator_(allocator), + uri_(schemaDocument->GetURI(), *allocator), + id_(id, allocator), + spec_(schemaDocument->GetSpecification()), + pointer_(p, allocator), + typeless_(schemaDocument->GetTypeless()), + enum_(), + enumCount_(), + not_(), + type_((1 << kTotalSchemaType) - 1), // typeless + validatorCount_(), + notValidatorIndex_(), + properties_(), + additionalPropertiesSchema_(), + patternProperties_(), + patternPropertyCount_(), + propertyCount_(), + minProperties_(), + maxProperties_(SizeType(~0)), + additionalProperties_(true), + hasDependencies_(), + hasRequired_(), + hasSchemaDependencies_(), + additionalItemsSchema_(), + itemsList_(), + itemsTuple_(), + itemsTupleCount_(), + minItems_(), + maxItems_(SizeType(~0)), + additionalItems_(true), + uniqueItems_(false), + pattern_(), + minLength_(0), + maxLength_(~SizeType(0)), + exclusiveMinimum_(false), + exclusiveMaximum_(false), + defaultValueLength_(0), + readOnly_(false), + writeOnly_(false), + nullable_(false) + { + GenericStringBuffer sb; + p.StringifyUriFragment(sb); + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Schema", sb.GetString(), id.GetString()); + + typedef typename ValueType::ConstValueIterator ConstValueIterator; + typedef typename ValueType::ConstMemberIterator ConstMemberIterator; + + // PR #1393 + // Early add this Schema and its $ref(s) in schemaDocument's map to avoid infinite + // recursion (with recursive schemas), since schemaDocument->getSchema() is always + // checked before creating a new one. Don't cache typeless_, though. + if (this != typeless_) { + typedef typename SchemaDocumentType::SchemaEntry SchemaEntry; + SchemaEntry *entry = schemaDocument->schemaMap_.template Push(); + new (entry) SchemaEntry(pointer_, this, true, allocator_); + schemaDocument->AddSchemaRefs(this); + } + + if (!value.IsObject()) + return; + + // If we have an id property, resolve it with the in-scope id + // Not supported for open api 2.0 or 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (const ValueType* v = GetMember(value, GetIdString())) { + if (v->IsString()) { + UriType local(*v, allocator); + id_ = local.Resolve(id_, allocator); + RAPIDJSON_SCHEMA_PRINT(SchemaIds, id.GetString(), v->GetString(), id_.GetString()); + } + } + + if (const ValueType* v = GetMember(value, GetTypeString())) { + type_ = 0; + if (v->IsString()) + AddType(*v); + else if (v->IsArray()) + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) + AddType(*itr); + } + + if (const ValueType* v = GetMember(value, GetEnumString())) { + if (v->IsArray() && v->Size() > 0) { + enum_ = static_cast(allocator_->Malloc(sizeof(uint64_t) * v->Size())); + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) { + typedef Hasher > EnumHasherType; + char buffer[256u + 24]; + MemoryPoolAllocator hasherAllocator(buffer, sizeof(buffer)); + EnumHasherType h(&hasherAllocator, 256); + itr->Accept(h); + enum_[enumCount_++] = h.GetHashCode(); + } + } + } + + if (schemaDocument) + AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document); + + // AnyOf, OneOf, Not not supported for open api 2.0 + if (schemaDocument && spec_.oapi != kVersion20) { + AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document); + AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document); + + if (const ValueType* v = GetMember(value, GetNotString())) { + schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document, id_); + notValidatorIndex_ = validatorCount_; + validatorCount_++; + } + } + + // Object + + const ValueType* properties = GetMember(value, GetPropertiesString()); + const ValueType* required = GetMember(value, GetRequiredString()); + const ValueType* dependencies = GetMember(value, GetDependenciesString()); + { + // Gather properties from properties/required/dependencies + SValue allProperties(kArrayType); + + if (properties && properties->IsObject()) + for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) + AddUniqueElement(allProperties, itr->name); + + if (required && required->IsArray()) + for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if (itr->IsString()) + AddUniqueElement(allProperties, *itr); + + // Dependencies not supported for open api 2.0 and 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (dependencies && dependencies->IsObject()) + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + AddUniqueElement(allProperties, itr->name); + if (itr->value.IsArray()) + for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i) + if (i->IsString()) + AddUniqueElement(allProperties, *i); + } + + if (allProperties.Size() > 0) { + propertyCount_ = allProperties.Size(); + properties_ = static_cast(allocator_->Malloc(sizeof(Property) * propertyCount_)); + for (SizeType i = 0; i < propertyCount_; i++) { + new (&properties_[i]) Property(); + properties_[i].name = allProperties[i]; + properties_[i].schema = typeless_; + } + } + } + + if (properties && properties->IsObject()) { + PointerType q = p.Append(GetPropertiesString(), allocator_); + for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) { + SizeType index; + if (FindPropertyIndex(itr->name, &index)) + schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document, id_); + } + } + + // PatternProperties not supported for open api 2.0 and 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) { + PointerType q = p.Append(GetPatternPropertiesString(), allocator_); + patternProperties_ = static_cast(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount())); + patternPropertyCount_ = 0; + + for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) { + new (&patternProperties_[patternPropertyCount_]) PatternProperty(); + PointerType r = q.Append(itr->name, allocator_); + patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name, schemaDocument, r); + schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, r, itr->value, document, id_); + patternPropertyCount_++; + } + } + + if (required && required->IsArray()) + for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if (itr->IsString()) { + SizeType index; + if (FindPropertyIndex(*itr, &index)) { + properties_[index].required = true; + hasRequired_ = true; + } + } + + // Dependencies not supported for open api 2.0 and 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (dependencies && dependencies->IsObject()) { + PointerType q = p.Append(GetDependenciesString(), allocator_); + hasDependencies_ = true; + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + SizeType sourceIndex; + if (FindPropertyIndex(itr->name, &sourceIndex)) { + if (itr->value.IsArray()) { + properties_[sourceIndex].dependencies = static_cast(allocator_->Malloc(sizeof(bool) * propertyCount_)); + std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_); + for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) { + SizeType targetIndex; + if (FindPropertyIndex(*targetItr, &targetIndex)) + properties_[sourceIndex].dependencies[targetIndex] = true; + } + } + else if (itr->value.IsObject()) { + hasSchemaDependencies_ = true; + schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document, id_); + properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_; + validatorCount_++; + } + } + } + } + + if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) { + if (v->IsBool()) + additionalProperties_ = v->GetBool(); + else if (v->IsObject()) + schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document, id_); + } + + AssignIfExist(minProperties_, value, GetMinPropertiesString()); + AssignIfExist(maxProperties_, value, GetMaxPropertiesString()); + + // Array + if (const ValueType* v = GetMember(value, GetItemsString())) { + PointerType q = p.Append(GetItemsString(), allocator_); + if (v->IsObject()) // List validation + schemaDocument->CreateSchema(&itemsList_, q, *v, document, id_); + else if (v->IsArray()) { // Tuple validation + itemsTuple_ = static_cast(allocator_->Malloc(sizeof(const Schema*) * v->Size())); + SizeType index = 0; + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++) + schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document, id_); + } + } + + AssignIfExist(minItems_, value, GetMinItemsString()); + AssignIfExist(maxItems_, value, GetMaxItemsString()); + + // AdditionalItems not supported for openapi 2.0 and 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) { + if (v->IsBool()) + additionalItems_ = v->GetBool(); + else if (v->IsObject()) + schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document, id_); + } + + AssignIfExist(uniqueItems_, value, GetUniqueItemsString()); + + // String + AssignIfExist(minLength_, value, GetMinLengthString()); + AssignIfExist(maxLength_, value, GetMaxLengthString()); + + if (const ValueType* v = GetMember(value, GetPatternString())) + pattern_ = CreatePattern(*v, schemaDocument, p.Append(GetPatternString(), allocator_)); + + // Number + if (const ValueType* v = GetMember(value, GetMinimumString())) + if (v->IsNumber()) + minimum_.CopyFrom(*v, *allocator_); + + if (const ValueType* v = GetMember(value, GetMaximumString())) + if (v->IsNumber()) + maximum_.CopyFrom(*v, *allocator_); + + AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString()); + AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString()); + + if (const ValueType* v = GetMember(value, GetMultipleOfString())) + if (v->IsNumber() && v->GetDouble() > 0.0) + multipleOf_.CopyFrom(*v, *allocator_); + + // Default + if (const ValueType* v = GetMember(value, GetDefaultValueString())) + if (v->IsString()) + defaultValueLength_ = v->GetStringLength(); + + // ReadOnly - open api only (until draft 7 supported) + // WriteOnly - open api 3 only (until draft 7 supported) + // Both can't be true + if (spec_.oapi != kVersionNone) + AssignIfExist(readOnly_, value, GetReadOnlyString()); + if (spec_.oapi >= kVersion30) + AssignIfExist(writeOnly_, value, GetWriteOnlyString()); + if (readOnly_ && writeOnly_) + schemaDocument->SchemaError(kSchemaErrorReadOnlyAndWriteOnly, p); + + // Nullable - open api 3 only + // If true add 'null' as allowable type + if (spec_.oapi >= kVersion30) { + AssignIfExist(nullable_, value, GetNullableString()); + if (nullable_) + AddType(GetNullString()); + } + } + + ~Schema() { + AllocatorType::Free(enum_); + if (properties_) { + for (SizeType i = 0; i < propertyCount_; i++) + properties_[i].~Property(); + AllocatorType::Free(properties_); + } + if (patternProperties_) { + for (SizeType i = 0; i < patternPropertyCount_; i++) + patternProperties_[i].~PatternProperty(); + AllocatorType::Free(patternProperties_); + } + AllocatorType::Free(itemsTuple_); +#if RAPIDJSON_SCHEMA_HAS_REGEX + if (pattern_) { + pattern_->~RegexType(); + AllocatorType::Free(pattern_); + } +#endif + } + + const SValue& GetURI() const { + return uri_; + } + + const UriType& GetId() const { + return id_; + } + + const Specification& GetSpecification() const { + return spec_; + } + + const PointerType& GetPointer() const { + return pointer_; + } + + bool BeginValue(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::BeginValue"); + if (context.inArray) { + if (uniqueItems_) + context.valueUniqueness = true; + + if (itemsList_) + context.valueSchema = itemsList_; + else if (itemsTuple_) { + if (context.arrayElementIndex < itemsTupleCount_) + context.valueSchema = itemsTuple_[context.arrayElementIndex]; + else if (additionalItemsSchema_) + context.valueSchema = additionalItemsSchema_; + else if (additionalItems_) + context.valueSchema = typeless_; + else { + context.error_handler.DisallowedItem(context.arrayElementIndex); + // Must set valueSchema for when kValidateContinueOnErrorFlag is set, else reports spurious type error + context.valueSchema = typeless_; + // Must bump arrayElementIndex for when kValidateContinueOnErrorFlag is set + context.arrayElementIndex++; + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAdditionalItems); + } + } + else + context.valueSchema = typeless_; + + context.arrayElementIndex++; + } + return true; + } + + RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndValue"); + // Only check pattern properties if we have validators + if (context.patternPropertiesValidatorCount > 0) { + bool otherValid = false; + SizeType count = context.patternPropertiesValidatorCount; + if (context.objectPatternValidatorType != Context::kPatternValidatorOnly) + otherValid = context.patternPropertiesValidators[--count]->IsValid(); + + bool patternValid = true; + for (SizeType i = 0; i < count; i++) + if (!context.patternPropertiesValidators[i]->IsValid()) { + patternValid = false; + break; + } + + if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) { + if (!patternValid) { + context.error_handler.PropertyViolations(context.patternPropertiesValidators, count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties); + } + } + else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) { + if (!patternValid || !otherValid) { + context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties); + } + } + else if (!patternValid && !otherValid) { // kPatternValidatorWithAdditionalProperty) + context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties); + } + } + + // For enums only check if we have a hasher + if (enum_ && context.hasher) { + const uint64_t h = context.factory.GetHashCode(context.hasher); + for (SizeType i = 0; i < enumCount_; i++) + if (enum_[i] == h) + goto foundEnum; + context.error_handler.DisallowedValue(kValidateErrorEnum); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorEnum); + foundEnum:; + } + + // Only check allOf etc if we have validators + if (context.validatorCount > 0) { + if (allOf_.schemas) + for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++) + if (!context.validators[i]->IsValid()) { + context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAllOf); + } + + if (anyOf_.schemas) { + for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++) + if (context.validators[i]->IsValid()) + goto foundAny; + context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAnyOf); + foundAny:; + } + + if (oneOf_.schemas) { + bool oneValid = false; + SizeType firstMatch = 0; + for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++) + if (context.validators[i]->IsValid()) { + if (oneValid) { + context.error_handler.MultipleOneOf(firstMatch, i - oneOf_.begin); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch); + } else { + oneValid = true; + firstMatch = i - oneOf_.begin; + } + } + if (!oneValid) { + context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOf); + } + } + + if (not_ && context.validators[notValidatorIndex_]->IsValid()) { + context.error_handler.Disallowed(); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorNot); + } + } + + return true; + } + + bool Null(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Null"); + if (!(type_ & (1 << kNullSchemaType))) { + DisallowedType(context, GetNullString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + return CreateParallelValidator(context); + } + + bool Bool(Context& context, bool b) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Bool", b); + if (!CheckBool(context, b)) + return false; + return CreateParallelValidator(context); + } + + bool Int(Context& context, int i) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Int", (int64_t)i); + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint(Context& context, unsigned u) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Uint", (uint64_t)u); + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Int64(Context& context, int64_t i) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Int64", i); + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint64(Context& context, uint64_t u) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Uint64", u); + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Double(Context& context, double d) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Double", d); + if (!(type_ & (1 << kNumberSchemaType))) { + DisallowedType(context, GetNumberString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d)) + return false; + + if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d)) + return false; + + if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d)) + return false; + + return CreateParallelValidator(context); + } + + bool String(Context& context, const Ch* str, SizeType length, bool) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::String", str); + if (!(type_ & (1 << kStringSchemaType))) { + DisallowedType(context, GetStringString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (minLength_ != 0 || maxLength_ != SizeType(~0)) { + SizeType count; + if (internal::CountStringCodePoint(str, length, &count)) { + if (count < minLength_) { + context.error_handler.TooShort(str, length, minLength_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinLength); + } + if (count > maxLength_) { + context.error_handler.TooLong(str, length, maxLength_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxLength); + } + } + } + + if (pattern_ && !IsPatternMatch(pattern_, str, length)) { + context.error_handler.DoesNotMatch(str, length); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPattern); + } + + return CreateParallelValidator(context); + } + + bool StartObject(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::StartObject"); + if (!(type_ & (1 << kObjectSchemaType))) { + DisallowedType(context, GetObjectString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (hasDependencies_ || hasRequired_) { + context.propertyExist = static_cast(context.factory.MallocState(sizeof(bool) * propertyCount_)); + std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_); + } + + if (patternProperties_) { // pre-allocate schema array + SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType + context.patternPropertiesSchemas = static_cast(context.factory.MallocState(sizeof(const SchemaType*) * count)); + context.patternPropertiesSchemaCount = 0; + std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count); + } + + return CreateParallelValidator(context); + } + + bool Key(Context& context, const Ch* str, SizeType len, bool) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Key", str); + + if (patternProperties_) { + context.patternPropertiesSchemaCount = 0; + for (SizeType i = 0; i < patternPropertyCount_; i++) + if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema; + context.valueSchema = typeless_; + } + } + + SizeType index = 0; + if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { + if (context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; + context.valueSchema = typeless_; + context.valuePatternValidatorType = Context::kPatternValidatorWithProperty; + } + else + context.valueSchema = properties_[index].schema; + + if (context.propertyExist) + context.propertyExist[index] = true; + + return true; + } + + if (additionalPropertiesSchema_) { + if (context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; + context.valueSchema = typeless_; + context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; + } + else + context.valueSchema = additionalPropertiesSchema_; + return true; + } + else if (additionalProperties_) { + context.valueSchema = typeless_; + return true; + } + + if (context.patternPropertiesSchemaCount == 0) { // patternProperties are not additional properties + // Must set valueSchema for when kValidateContinueOnErrorFlag is set, else reports spurious type error + context.valueSchema = typeless_; + context.error_handler.DisallowedProperty(str, len); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAdditionalProperties); + } + + return true; + } + + bool EndObject(Context& context, SizeType memberCount) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndObject"); + if (hasRequired_) { + context.error_handler.StartMissingProperties(); + for (SizeType index = 0; index < propertyCount_; index++) + if (properties_[index].required && !context.propertyExist[index]) + if (properties_[index].schema->defaultValueLength_ == 0 ) + context.error_handler.AddMissingProperty(properties_[index].name); + if (context.error_handler.EndMissingProperties()) + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorRequired); + } + + if (memberCount < minProperties_) { + context.error_handler.TooFewProperties(memberCount, minProperties_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinProperties); + } + + if (memberCount > maxProperties_) { + context.error_handler.TooManyProperties(memberCount, maxProperties_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxProperties); + } + + if (hasDependencies_) { + context.error_handler.StartDependencyErrors(); + for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) { + const Property& source = properties_[sourceIndex]; + if (context.propertyExist[sourceIndex]) { + if (source.dependencies) { + context.error_handler.StartMissingDependentProperties(); + for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++) + if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex]) + context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name); + context.error_handler.EndMissingDependentProperties(source.name); + } + else if (source.dependenciesSchema) { + ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex]; + if (!dependenciesValidator->IsValid()) + context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator); + } + } + } + if (context.error_handler.EndDependencyErrors()) + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorDependencies); + } + + return true; + } + + bool StartArray(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::StartArray"); + context.arrayElementIndex = 0; + context.inArray = true; // Ensure we note that we are in an array + + if (!(type_ & (1 << kArraySchemaType))) { + DisallowedType(context, GetArrayString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + return CreateParallelValidator(context); + } + + bool EndArray(Context& context, SizeType elementCount) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndArray"); + context.inArray = false; + + if (elementCount < minItems_) { + context.error_handler.TooFewItems(elementCount, minItems_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinItems); + } + + if (elementCount > maxItems_) { + context.error_handler.TooManyItems(elementCount, maxItems_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxItems); + } + + return true; + } + + static const ValueType& GetValidateErrorKeyword(ValidateErrorCode validateErrorCode) { + switch (validateErrorCode) { + case kValidateErrorMultipleOf: return GetMultipleOfString(); + case kValidateErrorMaximum: return GetMaximumString(); + case kValidateErrorExclusiveMaximum: return GetMaximumString(); // Same + case kValidateErrorMinimum: return GetMinimumString(); + case kValidateErrorExclusiveMinimum: return GetMinimumString(); // Same + + case kValidateErrorMaxLength: return GetMaxLengthString(); + case kValidateErrorMinLength: return GetMinLengthString(); + case kValidateErrorPattern: return GetPatternString(); + + case kValidateErrorMaxItems: return GetMaxItemsString(); + case kValidateErrorMinItems: return GetMinItemsString(); + case kValidateErrorUniqueItems: return GetUniqueItemsString(); + case kValidateErrorAdditionalItems: return GetAdditionalItemsString(); + + case kValidateErrorMaxProperties: return GetMaxPropertiesString(); + case kValidateErrorMinProperties: return GetMinPropertiesString(); + case kValidateErrorRequired: return GetRequiredString(); + case kValidateErrorAdditionalProperties: return GetAdditionalPropertiesString(); + case kValidateErrorPatternProperties: return GetPatternPropertiesString(); + case kValidateErrorDependencies: return GetDependenciesString(); + + case kValidateErrorEnum: return GetEnumString(); + case kValidateErrorType: return GetTypeString(); + + case kValidateErrorOneOf: return GetOneOfString(); + case kValidateErrorOneOfMatch: return GetOneOfString(); // Same + case kValidateErrorAllOf: return GetAllOfString(); + case kValidateErrorAnyOf: return GetAnyOfString(); + case kValidateErrorNot: return GetNotString(); + + case kValidateErrorReadOnly: return GetReadOnlyString(); + case kValidateErrorWriteOnly: return GetWriteOnlyString(); + + default: return GetNullString(); + } + } + + + // Generate functions for string literal according to Ch +#define RAPIDJSON_STRING_(name, ...) \ + static const ValueType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const ValueType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1));\ + return v;\ + } + + RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') + RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n') + RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't') + RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y') + RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g') + RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r') + RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r') + RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e') + RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm') + RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f') + RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f') + RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f') + RAPIDJSON_STRING_(Not, 'n', 'o', 't') + RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd') + RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's') + RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n') + RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f') + RAPIDJSON_STRING_(DefaultValue, 'd', 'e', 'f', 'a', 'u', 'l', 't') + RAPIDJSON_STRING_(Schema, '$', 's', 'c', 'h', 'e', 'm', 'a') + RAPIDJSON_STRING_(Ref, '$', 'r', 'e', 'f') + RAPIDJSON_STRING_(Id, 'i', 'd') + RAPIDJSON_STRING_(Swagger, 's', 'w', 'a', 'g', 'g', 'e', 'r') + RAPIDJSON_STRING_(OpenApi, 'o', 'p', 'e', 'n', 'a', 'p', 'i') + RAPIDJSON_STRING_(ReadOnly, 'r', 'e', 'a', 'd', 'O', 'n', 'l', 'y') + RAPIDJSON_STRING_(WriteOnly, 'w', 'r', 'i', 't', 'e', 'O', 'n', 'l', 'y') + RAPIDJSON_STRING_(Nullable, 'n', 'u', 'l', 'l', 'a', 'b', 'l', 'e') + +#undef RAPIDJSON_STRING_ + +private: + enum SchemaValueType { + kNullSchemaType, + kBooleanSchemaType, + kObjectSchemaType, + kArraySchemaType, + kStringSchemaType, + kNumberSchemaType, + kIntegerSchemaType, + kTotalSchemaType + }; + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + typedef internal::GenericRegex RegexType; +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + typedef std::basic_regex RegexType; +#else + typedef char RegexType; +#endif + + struct SchemaArray { + SchemaArray() : schemas(), count() {} + ~SchemaArray() { AllocatorType::Free(schemas); } + const SchemaType** schemas; + SizeType begin; // begin index of context.validators + SizeType count; + }; + + template + void AddUniqueElement(V1& a, const V2& v) { + for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) + if (*itr == v) + return; + V1 c(v, *allocator_); + a.PushBack(c, *allocator_); + } + + static const ValueType* GetMember(const ValueType& value, const ValueType& name) { + typename ValueType::ConstMemberIterator itr = value.FindMember(name); + return itr != value.MemberEnd() ? &(itr->value) : 0; + } + + static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) { + if (const ValueType* v = GetMember(value, name)) + if (v->IsBool()) + out = v->GetBool(); + } + + static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) { + if (const ValueType* v = GetMember(value, name)) + if (v->IsUint64() && v->GetUint64() <= SizeType(~0)) + out = static_cast(v->GetUint64()); + } + + void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) { + if (const ValueType* v = GetMember(value, name)) { + if (v->IsArray() && v->Size() > 0) { + PointerType q = p.Append(name, allocator_); + out.count = v->Size(); + out.schemas = static_cast(allocator_->Malloc(out.count * sizeof(const Schema*))); + memset(out.schemas, 0, sizeof(Schema*)* out.count); + for (SizeType i = 0; i < out.count; i++) + schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document, id_); + out.begin = validatorCount_; + validatorCount_ += out.count; + } + } + } + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + template + RegexType* CreatePattern(const ValueType& value, SchemaDocumentType* sd, const PointerType& p) { + if (value.IsString()) { + RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), allocator_); + if (!r->IsValid()) { + sd->SchemaErrorValue(kSchemaErrorRegexInvalid, p, value.GetString(), value.GetStringLength()); + r->~RegexType(); + AllocatorType::Free(r); + r = 0; + } + return r; + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) { + GenericRegexSearch rs(*pattern); + return rs.Search(str); + } +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + template + RegexType* CreatePattern(const ValueType& value, SchemaDocumentType* sd, const PointerType& p) { + if (value.IsString()) { + RegexType *r = static_cast(allocator_->Malloc(sizeof(RegexType))); + try { + return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); + } + catch (const std::regex_error& e) { + sd->SchemaErrorValue(kSchemaErrorRegexInvalid, p, value.GetString(), value.GetStringLength()); + AllocatorType::Free(r); + } + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) { + std::match_results r; + return std::regex_search(str, str + length, r, *pattern); + } +#else + template + RegexType* CreatePattern(const ValueType&) { + return 0; + } + + static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; } +#endif // RAPIDJSON_SCHEMA_USE_STDREGEX + + void AddType(const ValueType& type) { + if (type == GetNullString() ) type_ |= 1 << kNullSchemaType; + else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType; + else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType; + else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType; + else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType; + else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType; + else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); + } + + // Creates parallel validators for allOf, anyOf, oneOf, not and schema dependencies, if required. + // Also creates a hasher for enums and array uniqueness, if required. + // Also a useful place to add type-independent error checks. + bool CreateParallelValidator(Context& context) const { + if (enum_ || context.arrayUniqueness) + context.hasher = context.factory.CreateHasher(); + + if (validatorCount_) { + RAPIDJSON_ASSERT(context.validators == 0); + context.validators = static_cast(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_)); + std::memset(context.validators, 0, sizeof(ISchemaValidator*) * validatorCount_); + context.validatorCount = validatorCount_; + + // Always return after first failure for these sub-validators + if (allOf_.schemas) + CreateSchemaValidators(context, allOf_, false); + + if (anyOf_.schemas) + CreateSchemaValidators(context, anyOf_, false); + + if (oneOf_.schemas) + CreateSchemaValidators(context, oneOf_, false); + + if (not_) + context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_, false); + + if (hasSchemaDependencies_) { + for (SizeType i = 0; i < propertyCount_; i++) + if (properties_[i].dependenciesSchema) + context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema, false); + } + } + + // Add any other type-independent checks here + if (readOnly_ && (context.flags & kValidateWriteFlag)) { + context.error_handler.DisallowedWhenWriting(); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorReadOnly); + } + if (writeOnly_ && (context.flags & kValidateReadFlag)) { + context.error_handler.DisallowedWhenReading(); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorWriteOnly); + } + + return true; + } + + void CreateSchemaValidators(Context& context, const SchemaArray& schemas, const bool inheritContinueOnErrors) const { + for (SizeType i = 0; i < schemas.count; i++) + context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i], inheritContinueOnErrors); + } + + // O(n) + bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const { + SizeType len = name.GetStringLength(); + const Ch* str = name.GetString(); + for (SizeType index = 0; index < propertyCount_; index++) + if (properties_[index].name.GetStringLength() == len && + (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0)) + { + *outIndex = index; + return true; + } + return false; + } + + bool CheckBool(Context& context, bool) const { + if (!(type_ & (1 << kBooleanSchemaType))) { + DisallowedType(context, GetBooleanString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + return true; + } + + bool CheckInt(Context& context, int64_t i) const { + if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) { + DisallowedType(context, GetIntegerString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (!minimum_.IsNull()) { + if (minimum_.IsInt64()) { + if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) { + context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); + } + } + else if (minimum_.IsUint64()) { + context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); // i <= max(int64_t) < minimum.GetUint64() + } + else if (!CheckDoubleMinimum(context, static_cast(i))) + return false; + } + + if (!maximum_.IsNull()) { + if (maximum_.IsInt64()) { + if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) { + context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); + } + } + else if (maximum_.IsUint64()) { } + /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64() + else if (!CheckDoubleMaximum(context, static_cast(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (static_cast(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) { + context.error_handler.NotMultipleOf(i, multipleOf_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); + } + } + else if (!CheckDoubleMultipleOf(context, static_cast(i))) + return false; + } + + return true; + } + + bool CheckUint(Context& context, uint64_t i) const { + if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) { + DisallowedType(context, GetIntegerString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (!minimum_.IsNull()) { + if (minimum_.IsUint64()) { + if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) { + context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); + } + } + else if (minimum_.IsInt64()) + /* do nothing */; // i >= 0 > minimum.Getint64() + else if (!CheckDoubleMinimum(context, static_cast(i))) + return false; + } + + if (!maximum_.IsNull()) { + if (maximum_.IsUint64()) { + if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) { + context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); + } + } + else if (maximum_.IsInt64()) { + context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); // i >= 0 > maximum_ + } + else if (!CheckDoubleMaximum(context, static_cast(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (i % multipleOf_.GetUint64() != 0) { + context.error_handler.NotMultipleOf(i, multipleOf_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); + } + } + else if (!CheckDoubleMultipleOf(context, static_cast(i))) + return false; + } + + return true; + } + + bool CheckDoubleMinimum(Context& context, double d) const { + if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) { + context.error_handler.BelowMinimum(d, minimum_, exclusiveMinimum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); + } + return true; + } + + bool CheckDoubleMaximum(Context& context, double d) const { + if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) { + context.error_handler.AboveMaximum(d, maximum_, exclusiveMaximum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); + } + return true; + } + + bool CheckDoubleMultipleOf(Context& context, double d) const { + double a = std::abs(d), b = std::abs(multipleOf_.GetDouble()); + double q = std::floor(a / b); + double r = a - q * b; + if (r > 0.0) { + context.error_handler.NotMultipleOf(d, multipleOf_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); + } + return true; + } + + void DisallowedType(Context& context, const ValueType& actualType) const { + ErrorHandler& eh = context.error_handler; + eh.StartDisallowedType(); + + if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString()); + if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString()); + if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString()); + if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString()); + if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString()); + + if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString()); + else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString()); + + eh.EndDisallowedType(actualType); + } + + struct Property { + Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {} + ~Property() { AllocatorType::Free(dependencies); } + SValue name; + const SchemaType* schema; + const SchemaType* dependenciesSchema; + SizeType dependenciesValidatorIndex; + bool* dependencies; + bool required; + }; + + struct PatternProperty { + PatternProperty() : schema(), pattern() {} + ~PatternProperty() { + if (pattern) { + pattern->~RegexType(); + AllocatorType::Free(pattern); + } + } + const SchemaType* schema; + RegexType* pattern; + }; + + AllocatorType* allocator_; + SValue uri_; + UriType id_; + Specification spec_; + PointerType pointer_; + const SchemaType* typeless_; + uint64_t* enum_; + SizeType enumCount_; + SchemaArray allOf_; + SchemaArray anyOf_; + SchemaArray oneOf_; + const SchemaType* not_; + unsigned type_; // bitmask of kSchemaType + SizeType validatorCount_; + SizeType notValidatorIndex_; + + Property* properties_; + const SchemaType* additionalPropertiesSchema_; + PatternProperty* patternProperties_; + SizeType patternPropertyCount_; + SizeType propertyCount_; + SizeType minProperties_; + SizeType maxProperties_; + bool additionalProperties_; + bool hasDependencies_; + bool hasRequired_; + bool hasSchemaDependencies_; + + const SchemaType* additionalItemsSchema_; + const SchemaType* itemsList_; + const SchemaType** itemsTuple_; + SizeType itemsTupleCount_; + SizeType minItems_; + SizeType maxItems_; + bool additionalItems_; + bool uniqueItems_; + + RegexType* pattern_; + SizeType minLength_; + SizeType maxLength_; + + SValue minimum_; + SValue maximum_; + SValue multipleOf_; + bool exclusiveMinimum_; + bool exclusiveMaximum_; + + SizeType defaultValueLength_; + + bool readOnly_; + bool writeOnly_; + bool nullable_; +}; + +template +struct TokenHelper { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + *documentStack.template Push() = '/'; + char buffer[21]; + size_t length = static_cast((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer); + for (size_t i = 0; i < length; i++) + *documentStack.template Push() = static_cast(buffer[i]); + } +}; + +// Partial specialized version for char to prevent buffer copying. +template +struct TokenHelper { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + if (sizeof(SizeType) == 4) { + char *buffer = documentStack.template Push(1 + 10); // '/' + uint + *buffer++ = '/'; + const char* end = internal::u32toa(index, buffer); + documentStack.template Pop(static_cast(10 - (end - buffer))); + } + else { + char *buffer = documentStack.template Push(1 + 20); // '/' + uint64 + *buffer++ = '/'; + const char* end = internal::u64toa(index, buffer); + documentStack.template Pop(static_cast(20 - (end - buffer))); + } + } +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// IGenericRemoteSchemaDocumentProvider + +template +class IGenericRemoteSchemaDocumentProvider { +public: + typedef typename SchemaDocumentType::Ch Ch; + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename SchemaDocumentType::AllocatorType AllocatorType; + + virtual ~IGenericRemoteSchemaDocumentProvider() {} + virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0; + virtual const SchemaDocumentType* GetRemoteDocument(const GenericUri uri, Specification& spec) { + // Default implementation just calls through for compatibility + // Following line suppresses unused parameter warning + (void)spec; + // printf("GetRemoteDocument: %d %d\n", spec.draft, spec.oapi); + return GetRemoteDocument(uri.GetBaseString(), uri.GetBaseStringLength()); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericSchemaDocument + +//! JSON schema document. +/*! + A JSON schema document is a compiled version of a JSON schema. + It is basically a tree of internal::Schema. + + \note This is an immutable class (i.e. its instance cannot be modified after construction). + \tparam ValueT Type of JSON value (e.g. \c Value ), which also determine the encoding. + \tparam Allocator Allocator type for allocating memory of this document. +*/ +template +class GenericSchemaDocument { +public: + typedef ValueT ValueType; + typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProviderType; + typedef Allocator AllocatorType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef internal::Schema SchemaType; + typedef GenericPointer PointerType; + typedef GenericValue GValue; + typedef GenericUri UriType; + typedef GenericStringRef StringRefType; + friend class internal::Schema; + template + friend class GenericSchemaValidator; + + //! Constructor. + /*! + Compile a JSON document into schema document. + + \param document A JSON document as source. + \param uri The base URI of this schema document for purposes of violation reporting. + \param uriLength Length of \c name, in code points. + \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null. + \param allocator An optional allocator instance for allocating memory. Can be null. + \param pointer An optional JSON pointer to the start of the schema document + \param spec Optional schema draft or OpenAPI version. Used if no specification in document. Defaults to draft-04. + */ + explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0, + IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0, + const PointerType& pointer = PointerType(), // PR #1393 + const Specification& spec = Specification(kDraft04)) : + remoteProvider_(remoteProvider), + allocator_(allocator), + ownAllocator_(), + root_(), + typeless_(), + schemaMap_(allocator, kInitialSchemaMapSize), + schemaRef_(allocator, kInitialSchemaRefSize), + spec_(spec), + error_(kObjectType), + currentError_() + { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::GenericSchemaDocument"); + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + Ch noUri[1] = {0}; + uri_.SetString(uri ? uri : noUri, uriLength, *allocator_); + docId_ = UriType(uri_, allocator_); + + typeless_ = static_cast(allocator_->Malloc(sizeof(SchemaType))); + new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), allocator_, docId_); + + // Establish the schema draft or open api version. + // We only ever look for '$schema' or 'swagger' or 'openapi' at the root of the document. + SetSchemaSpecification(document); + + // Generate root schema, it will call CreateSchema() to create sub-schemas, + // And call HandleRefSchema() if there are $ref. + // PR #1393 use input pointer if supplied + root_ = typeless_; + if (pointer.GetTokenCount() == 0) { + CreateSchemaRecursive(&root_, pointer, document, document, docId_); + } + else if (const ValueType* v = pointer.Get(document)) { + CreateSchema(&root_, pointer, *v, document, docId_); + } + else { + GenericStringBuffer sb; + pointer.StringifyUriFragment(sb); + SchemaErrorValue(kSchemaErrorStartUnknown, PointerType(), sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch))); + } + + RAPIDJSON_ASSERT(root_ != 0); + + schemaRef_.ShrinkToFit(); // Deallocate all memory for ref + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT : + remoteProvider_(rhs.remoteProvider_), + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + root_(rhs.root_), + typeless_(rhs.typeless_), + schemaMap_(std::move(rhs.schemaMap_)), + schemaRef_(std::move(rhs.schemaRef_)), + uri_(std::move(rhs.uri_)), + docId_(std::move(rhs.docId_)), + spec_(rhs.spec_), + error_(std::move(rhs.error_)), + currentError_(std::move(rhs.currentError_)) + { + rhs.remoteProvider_ = 0; + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.typeless_ = 0; + } +#endif + + //! Destructor + ~GenericSchemaDocument() { + while (!schemaMap_.Empty()) + schemaMap_.template Pop(1)->~SchemaEntry(); + + if (typeless_) { + typeless_->~SchemaType(); + Allocator::Free(typeless_); + } + + // these may contain some allocator data so clear before deleting ownAllocator_ + uri_.SetNull(); + error_.SetNull(); + currentError_.SetNull(); + + RAPIDJSON_DELETE(ownAllocator_); + } + + const GValue& GetURI() const { return uri_; } + + const Specification& GetSpecification() const { return spec_; } + bool IsSupportedSpecification() const { return spec_.IsSupported(); } + + //! Static method to get the specification of any schema document + // Returns kDraftNone if document is silent + static const Specification GetSpecification(const ValueType& document) { + SchemaDraft draft = GetSchemaDraft(document); + if (draft != kDraftNone) + return Specification(draft); + else { + OpenApiVersion oapi = GetOpenApiVersion(document); + if (oapi != kVersionNone) + return Specification(oapi); + } + return Specification(kDraftNone); + } + + //! Get the root schema. + const SchemaType& GetRoot() const { return *root_; } + + //! Gets the error object. + GValue& GetError() { return error_; } + const GValue& GetError() const { return error_; } + + static const StringRefType& GetSchemaErrorKeyword(SchemaErrorCode schemaErrorCode) { + switch (schemaErrorCode) { + case kSchemaErrorStartUnknown: return GetStartUnknownString(); + case kSchemaErrorRefPlainName: return GetRefPlainNameString(); + case kSchemaErrorRefInvalid: return GetRefInvalidString(); + case kSchemaErrorRefPointerInvalid: return GetRefPointerInvalidString(); + case kSchemaErrorRefUnknown: return GetRefUnknownString(); + case kSchemaErrorRefCyclical: return GetRefCyclicalString(); + case kSchemaErrorRefNoRemoteProvider: return GetRefNoRemoteProviderString(); + case kSchemaErrorRefNoRemoteSchema: return GetRefNoRemoteSchemaString(); + case kSchemaErrorRegexInvalid: return GetRegexInvalidString(); + case kSchemaErrorSpecUnknown: return GetSpecUnknownString(); + case kSchemaErrorSpecUnsupported: return GetSpecUnsupportedString(); + case kSchemaErrorSpecIllegal: return GetSpecIllegalString(); + case kSchemaErrorReadOnlyAndWriteOnly: return GetReadOnlyAndWriteOnlyString(); + default: return GetNullString(); + } + } + + //! Default error method + void SchemaError(const SchemaErrorCode code, const PointerType& location) { + currentError_ = GValue(kObjectType); + AddCurrentError(code, location); + } + + //! Method for error with single string value insert + void SchemaErrorValue(const SchemaErrorCode code, const PointerType& location, const Ch* value, SizeType length) { + currentError_ = GValue(kObjectType); + currentError_.AddMember(GetValueString(), GValue(value, length, *allocator_).Move(), *allocator_); + AddCurrentError(code, location); + } + + //! Method for error with invalid pointer + void SchemaErrorPointer(const SchemaErrorCode code, const PointerType& location, const Ch* value, SizeType length, const PointerType& pointer) { + currentError_ = GValue(kObjectType); + currentError_.AddMember(GetValueString(), GValue(value, length, *allocator_).Move(), *allocator_); + currentError_.AddMember(GetOffsetString(), static_cast(pointer.GetParseErrorOffset() / sizeof(Ch)), *allocator_); + AddCurrentError(code, location); + } + + private: + //! Prohibit copying + GenericSchemaDocument(const GenericSchemaDocument&); + //! Prohibit assignment + GenericSchemaDocument& operator=(const GenericSchemaDocument&); + + typedef const PointerType* SchemaRefPtr; // PR #1393 + + struct SchemaEntry { + SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {} + ~SchemaEntry() { + if (owned) { + schema->~SchemaType(); + Allocator::Free(schema); + } + } + PointerType pointer; + SchemaType* schema; + bool owned; + }; + + void AddErrorInstanceLocation(GValue& result, const PointerType& location) { + GenericStringBuffer sb; + location.StringifyUriFragment(sb); + GValue instanceRef(sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch)), *allocator_); + result.AddMember(GetInstanceRefString(), instanceRef, *allocator_); + } + + void AddError(GValue& keyword, GValue& error) { + typename GValue::MemberIterator member = error_.FindMember(keyword); + if (member == error_.MemberEnd()) + error_.AddMember(keyword, error, *allocator_); + else { + if (member->value.IsObject()) { + GValue errors(kArrayType); + errors.PushBack(member->value, *allocator_); + member->value = errors; + } + member->value.PushBack(error, *allocator_); + } + } + + void AddCurrentError(const SchemaErrorCode code, const PointerType& location) { + RAPIDJSON_SCHEMA_PRINT(InvalidKeyword, GetSchemaErrorKeyword(code)); + currentError_.AddMember(GetErrorCodeString(), code, *allocator_); + AddErrorInstanceLocation(currentError_, location); + AddError(GValue(GetSchemaErrorKeyword(code)).Move(), currentError_); + } + +#define RAPIDJSON_STRING_(name, ...) \ + static const StringRefType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const StringRefType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1)); \ + return v;\ + } + + RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f') + RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e') + RAPIDJSON_STRING_(Value, 'v', 'a', 'l', 'u', 'e') + RAPIDJSON_STRING_(Offset, 'o', 'f', 'f', 's', 'e', 't') + + RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') + RAPIDJSON_STRING_(SpecUnknown, 'S', 'p', 'e', 'c', 'U', 'n', 'k', 'n', 'o', 'w', 'n') + RAPIDJSON_STRING_(SpecUnsupported, 'S', 'p', 'e', 'c', 'U', 'n', 's', 'u', 'p', 'p', 'o', 'r', 't', 'e', 'd') + RAPIDJSON_STRING_(SpecIllegal, 'S', 'p', 'e', 'c', 'I', 'l', 'l', 'e', 'g', 'a', 'l') + RAPIDJSON_STRING_(StartUnknown, 'S', 't', 'a', 'r', 't', 'U', 'n', 'k', 'n', 'o', 'w', 'n') + RAPIDJSON_STRING_(RefPlainName, 'R', 'e', 'f', 'P', 'l', 'a', 'i', 'n', 'N', 'a', 'm', 'e') + RAPIDJSON_STRING_(RefInvalid, 'R', 'e', 'f', 'I', 'n', 'v', 'a', 'l', 'i', 'd') + RAPIDJSON_STRING_(RefPointerInvalid, 'R', 'e', 'f', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'I', 'n', 'v', 'a', 'l', 'i', 'd') + RAPIDJSON_STRING_(RefUnknown, 'R', 'e', 'f', 'U', 'n', 'k', 'n', 'o', 'w', 'n') + RAPIDJSON_STRING_(RefCyclical, 'R', 'e', 'f', 'C', 'y', 'c', 'l', 'i', 'c', 'a', 'l') + RAPIDJSON_STRING_(RefNoRemoteProvider, 'R', 'e', 'f', 'N', 'o', 'R', 'e', 'm', 'o', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r') + RAPIDJSON_STRING_(RefNoRemoteSchema, 'R', 'e', 'f', 'N', 'o', 'R', 'e', 'm', 'o', 't', 'e', 'S', 'c', 'h', 'e', 'm', 'a') + RAPIDJSON_STRING_(ReadOnlyAndWriteOnly, 'R', 'e', 'a', 'd', 'O', 'n', 'l', 'y', 'A', 'n', 'd', 'W', 'r', 'i', 't', 'e', 'O', 'n', 'l', 'y') + RAPIDJSON_STRING_(RegexInvalid, 'R', 'e', 'g', 'e', 'x', 'I', 'n', 'v', 'a', 'l', 'i', 'd') + +#undef RAPIDJSON_STRING_ + + // Static method to get schema draft of any schema document + static SchemaDraft GetSchemaDraft(const ValueType& document) { + static const Ch kDraft03String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '3', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft04String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '4', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft05String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '5', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft06String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '6', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft07String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '7', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft2019_09String[] = { 'h', 't', 't', 'p', 's', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '/', '2', '0', '1', '9', '-', '0', '9', '/', 's', 'c', 'h', 'e', 'm', 'a', '\0' }; + static const Ch kDraft2020_12String[] = { 'h', 't', 't', 'p', 's', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '/', '2', '0', '2', '0', '-', '1', '2', '/', 's', 'c', 'h', 'e', 'm', 'a', '\0' }; + + if (!document.IsObject()) { + return kDraftNone; + } + + // Get the schema draft from the $schema keyword at the supplied location + typename ValueType::ConstMemberIterator itr = document.FindMember(SchemaType::GetSchemaString()); + if (itr != document.MemberEnd()) { + if (!itr->value.IsString()) return kDraftUnknown; + const UriType draftUri(itr->value); + // Check base uri for match + if (draftUri.Match(UriType(kDraft04String), false)) return kDraft04; + if (draftUri.Match(UriType(kDraft05String), false)) return kDraft05; + if (draftUri.Match(UriType(kDraft06String), false)) return kDraft06; + if (draftUri.Match(UriType(kDraft07String), false)) return kDraft07; + if (draftUri.Match(UriType(kDraft03String), false)) return kDraft03; + if (draftUri.Match(UriType(kDraft2019_09String), false)) return kDraft2019_09; + if (draftUri.Match(UriType(kDraft2020_12String), false)) return kDraft2020_12; + return kDraftUnknown; + } + // $schema not found + return kDraftNone; + } + + + // Get open api version of any schema document + static OpenApiVersion GetOpenApiVersion(const ValueType& document) { + static const Ch kVersion20String[] = { '2', '.', '0', '\0' }; + static const Ch kVersion30String[] = { '3', '.', '0', '.', '\0' }; // ignore patch level + static const Ch kVersion31String[] = { '3', '.', '1', '.', '\0' }; // ignore patch level + static SizeType len = internal::StrLen(kVersion30String); + + if (!document.IsObject()) { + return kVersionNone; + } + + // Get the open api version from the swagger / openapi keyword at the supplied location + typename ValueType::ConstMemberIterator itr = document.FindMember(SchemaType::GetSwaggerString()); + if (itr == document.MemberEnd()) itr = document.FindMember(SchemaType::GetOpenApiString()); + if (itr != document.MemberEnd()) { + if (!itr->value.IsString()) return kVersionUnknown; + const ValueType kVersion20Value(kVersion20String); + if (kVersion20Value == itr->value) return kVersion20; // must match 2.0 exactly + const ValueType kVersion30Value(kVersion30String); + if (itr->value.GetStringLength() > len && kVersion30Value == ValueType(itr->value.GetString(), len)) return kVersion30; // must match 3.0.x + const ValueType kVersion31Value(kVersion31String); + if (itr->value.GetStringLength() > len && kVersion31Value == ValueType(itr->value.GetString(), len)) return kVersion31; // must match 3.1.x + return kVersionUnknown; + } + // swagger or openapi not found + return kVersionNone; + } + + // Get the draft of the schema or the open api version (which implies the draft). + // Report an error if schema draft or open api version not supported or not recognized, or both in document, and carry on. + void SetSchemaSpecification(const ValueType& document) { + // Look for '$schema', 'swagger' or 'openapi' keyword at document root + SchemaDraft docDraft = GetSchemaDraft(document); + OpenApiVersion docOapi = GetOpenApiVersion(document); + // Error if both in document + if (docDraft != kDraftNone && docOapi != kVersionNone) + SchemaError(kSchemaErrorSpecIllegal, PointerType()); + // Use document draft or open api version if present or use spec from constructor + if (docDraft != kDraftNone) + spec_ = Specification(docDraft); + else if (docOapi != kVersionNone) + spec_ = Specification(docOapi); + // Error if draft or version unknown + if (spec_.draft == kDraftUnknown || spec_.oapi == kVersionUnknown) + SchemaError(kSchemaErrorSpecUnknown, PointerType()); + else if (!spec_.IsSupported()) + SchemaError(kSchemaErrorSpecUnsupported, PointerType()); + } + + // Changed by PR #1393 + void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) { + if (v.GetType() == kObjectType) { + UriType newid = UriType(CreateSchema(schema, pointer, v, document, id), allocator_); + + for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) + CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document, newid); + } + else if (v.GetType() == kArrayType) + for (SizeType i = 0; i < v.Size(); i++) + CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document, id); + } + + // Changed by PR #1393 + const UriType& CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) { + RAPIDJSON_ASSERT(pointer.IsValid()); + GenericStringBuffer sb; + pointer.StringifyUriFragment(sb); + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::CreateSchema", sb.GetString(), id.GetString()); + if (v.IsObject()) { + if (const SchemaType* sc = GetSchema(pointer)) { + if (schema) + *schema = sc; + AddSchemaRefs(const_cast(sc)); + } + else if (!HandleRefSchema(pointer, schema, v, document, id)) { + // The new schema constructor adds itself and its $ref(s) to schemaMap_ + SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_, id); + if (schema) + *schema = s; + return s->GetId(); + } + } + else { + if (schema) + *schema = typeless_; + AddSchemaRefs(typeless_); + } + return id; + } + + // Changed by PR #1393 + // TODO should this return a UriType& ? + bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document, const UriType& id) { + typename ValueType::ConstMemberIterator itr = v.FindMember(SchemaType::GetRefString()); + if (itr == v.MemberEnd()) + return false; + + GenericStringBuffer sb; + source.StringifyUriFragment(sb); + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::HandleRefSchema", sb.GetString(), id.GetString()); + // Resolve the source pointer to the $ref'ed schema (finally) + new (schemaRef_.template Push()) SchemaRefPtr(&source); + + if (itr->value.IsString()) { + SizeType len = itr->value.GetStringLength(); + if (len == 0) + SchemaError(kSchemaErrorRefInvalid, source); + else { + // First resolve $ref against the in-scope id + UriType scopeId = UriType(id, allocator_); + UriType ref = UriType(itr->value, allocator_).Resolve(scopeId, allocator_); + RAPIDJSON_SCHEMA_PRINT(SchemaIds, id.GetString(), itr->value.GetString(), ref.GetString()); + // See if the resolved $ref minus the fragment matches a resolved id in this document + // Search from the root. Returns the subschema in the document and its absolute JSON pointer. + PointerType basePointer = PointerType(); + const ValueType *base = FindId(document, ref, basePointer, docId_, false); + if (!base) { + // Remote reference - call the remote document provider + if (!remoteProvider_) + SchemaError(kSchemaErrorRefNoRemoteProvider, source); + else { + if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(ref, spec_)) { + const Ch* s = ref.GetFragString(); + len = ref.GetFragStringLength(); + if (len <= 1 || s[1] == '/') { + // JSON pointer fragment, absolute in the remote schema + const PointerType pointer(s, len, allocator_); + if (!pointer.IsValid()) + SchemaErrorPointer(kSchemaErrorRefPointerInvalid, source, s, len, pointer); + else { + // Get the subschema + if (const SchemaType *sc = remoteDocument->GetSchema(pointer)) { + if (schema) + *schema = sc; + AddSchemaRefs(const_cast(sc)); + return true; + } else + SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength()); + } + } else + // Plain name fragment, not allowed in remote schema + SchemaErrorValue(kSchemaErrorRefPlainName, source, s, len); + } else + SchemaErrorValue(kSchemaErrorRefNoRemoteSchema, source, ref.GetString(), ref.GetStringLength()); + } + } + else { // Local reference + const Ch* s = ref.GetFragString(); + len = ref.GetFragStringLength(); + if (len <= 1 || s[1] == '/') { + // JSON pointer fragment, relative to the resolved URI + const PointerType relPointer(s, len, allocator_); + if (!relPointer.IsValid()) + SchemaErrorPointer(kSchemaErrorRefPointerInvalid, source, s, len, relPointer); + else { + // Get the subschema + if (const ValueType *pv = relPointer.Get(*base)) { + // Now get the absolute JSON pointer by adding relative to base + PointerType pointer(basePointer, allocator_); + for (SizeType i = 0; i < relPointer.GetTokenCount(); i++) + pointer = pointer.Append(relPointer.GetTokens()[i], allocator_); + if (IsCyclicRef(pointer)) + SchemaErrorValue(kSchemaErrorRefCyclical, source, ref.GetString(), ref.GetStringLength()); + else { + // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there + // TODO: cache pointer <-> id mapping + size_t unresolvedTokenIndex; + scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_); + CreateSchema(schema, pointer, *pv, document, scopeId); + return true; + } + } else + SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength()); + } + } else { + // Plain name fragment, relative to the resolved URI + // Not supported in open api 2.0 and 3.0 + PointerType pointer(allocator_); + if (spec_.oapi == kVersion20 || spec_.oapi == kVersion30) + SchemaErrorValue(kSchemaErrorRefPlainName, source, s, len); + // See if the fragment matches an id in this document. + // Search from the base we just established. Returns the subschema in the document and its absolute JSON pointer. + else if (const ValueType *pv = FindId(*base, ref, pointer, UriType(ref.GetBaseString(), ref.GetBaseStringLength(), allocator_), true, basePointer)) { + if (IsCyclicRef(pointer)) + SchemaErrorValue(kSchemaErrorRefCyclical, source, ref.GetString(), ref.GetStringLength()); + else { + // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there + // TODO: cache pointer <-> id mapping + size_t unresolvedTokenIndex; + scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_); + CreateSchema(schema, pointer, *pv, document, scopeId); + return true; + } + } else + SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength()); + } + } + } + } + + // Invalid/Unknown $ref + if (schema) + *schema = typeless_; + AddSchemaRefs(typeless_); + return true; + } + + //! Find the first subschema with a resolved 'id' that matches the specified URI. + // If full specified use all URI else ignore fragment. + // If found, return a pointer to the subschema and its JSON pointer. + // TODO cache pointer <-> id mapping + ValueType* FindId(const ValueType& doc, const UriType& finduri, PointerType& resptr, const UriType& baseuri, bool full, const PointerType& here = PointerType()) const { + SizeType i = 0; + ValueType* resval = 0; + UriType tempuri = UriType(finduri, allocator_); + UriType localuri = UriType(baseuri, allocator_); + if (doc.GetType() == kObjectType) { + // Establish the base URI of this object + typename ValueType::ConstMemberIterator m = doc.FindMember(SchemaType::GetIdString()); + if (m != doc.MemberEnd() && m->value.GetType() == kStringType) { + localuri = UriType(m->value, allocator_).Resolve(baseuri, allocator_); + } + // See if it matches + if (localuri.Match(finduri, full)) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::FindId (match)", full ? localuri.GetString() : localuri.GetBaseString()); + resval = const_cast(&doc); + resptr = here; + return resval; + } + // No match, continue looking + for (m = doc.MemberBegin(); m != doc.MemberEnd(); ++m) { + if (m->value.GetType() == kObjectType || m->value.GetType() == kArrayType) { + resval = FindId(m->value, finduri, resptr, localuri, full, here.Append(m->name.GetString(), m->name.GetStringLength(), allocator_)); + } + if (resval) break; + } + } else if (doc.GetType() == kArrayType) { + // Continue looking + for (typename ValueType::ConstValueIterator v = doc.Begin(); v != doc.End(); ++v) { + if (v->GetType() == kObjectType || v->GetType() == kArrayType) { + resval = FindId(*v, finduri, resptr, localuri, full, here.Append(i, allocator_)); + } + if (resval) break; + i++; + } + } + return resval; + } + + // Added by PR #1393 + void AddSchemaRefs(SchemaType* schema) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::AddSchemaRefs"); + while (!schemaRef_.Empty()) { + SchemaRefPtr *ref = schemaRef_.template Pop(1); + SchemaEntry *entry = schemaMap_.template Push(); + new (entry) SchemaEntry(**ref, schema, false, allocator_); + } + } + + // Added by PR #1393 + bool IsCyclicRef(const PointerType& pointer) const { + for (const SchemaRefPtr* ref = schemaRef_.template Bottom(); ref != schemaRef_.template End(); ++ref) + if (pointer == **ref) + return true; + return false; + } + + const SchemaType* GetSchema(const PointerType& pointer) const { + for (const SchemaEntry* target = schemaMap_.template Bottom(); target != schemaMap_.template End(); ++target) + if (pointer == target->pointer) + return target->schema; + return 0; + } + + PointerType GetPointer(const SchemaType* schema) const { + for (const SchemaEntry* target = schemaMap_.template Bottom(); target != schemaMap_.template End(); ++target) + if (schema == target->schema) + return target->pointer; + return PointerType(); + } + + const SchemaType* GetTypeless() const { return typeless_; } + + static const size_t kInitialSchemaMapSize = 64; + static const size_t kInitialSchemaRefSize = 64; + + IRemoteSchemaDocumentProviderType* remoteProvider_; + Allocator *allocator_; + Allocator *ownAllocator_; + const SchemaType* root_; //!< Root schema. + SchemaType* typeless_; + internal::Stack schemaMap_; // Stores created Pointer -> Schemas + internal::Stack schemaRef_; // Stores Pointer(s) from $ref(s) until resolved + GValue uri_; // Schema document URI + UriType docId_; + Specification spec_; + GValue error_; + GValue currentError_; +}; + +//! GenericSchemaDocument using Value type. +typedef GenericSchemaDocument SchemaDocument; +//! IGenericRemoteSchemaDocumentProvider using SchemaDocument. +typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; + +/////////////////////////////////////////////////////////////////////////////// +// GenericSchemaValidator + +//! JSON Schema Validator. +/*! + A SAX style JSON schema validator. + It uses a \c GenericSchemaDocument to validate SAX events. + It delegates the incoming SAX events to an output handler. + The default output handler does nothing. + It can be reused multiple times by calling \c Reset(). + + \tparam SchemaDocumentType Type of schema document. + \tparam OutputHandler Type of output handler. Default handler does nothing. + \tparam StateAllocator Allocator for storing the internal validation states. +*/ +template < + typename SchemaDocumentType, + typename OutputHandler = BaseReaderHandler, + typename StateAllocator = CrtAllocator> +class GenericSchemaValidator : + public internal::ISchemaStateFactory, + public internal::ISchemaValidator, + public internal::IValidationErrorHandler { +public: + typedef typename SchemaDocumentType::SchemaType SchemaType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename SchemaType::EncodingType EncodingType; + typedef typename SchemaType::SValue SValue; + typedef typename EncodingType::Ch Ch; + typedef GenericStringRef StringRefType; + typedef GenericValue ValueType; + + //! Constructor without output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + outputHandler_(0), + error_(kObjectType), + currentError_(), + missingDependents_(), + valid_(true), + flags_(kValidateDefaultFlags), + depth_(0) + { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator"); + } + + //! Constructor with output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + OutputHandler& outputHandler, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + outputHandler_(&outputHandler), + error_(kObjectType), + currentError_(), + missingDependents_(), + valid_(true), + flags_(kValidateDefaultFlags), + depth_(0) + { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator (output handler)"); + } + + //! Destructor. + ~GenericSchemaValidator() { + Reset(); + RAPIDJSON_DELETE(ownStateAllocator_); + } + + //! Reset the internal states. + void Reset() { + while (!schemaStack_.Empty()) + PopSchema(); + documentStack_.Clear(); + ResetError(); + } + + //! Reset the error state. + void ResetError() { + error_.SetObject(); + currentError_.SetNull(); + missingDependents_.SetNull(); + valid_ = true; + } + + //! Implementation of ISchemaValidator + void SetValidateFlags(unsigned flags) { + flags_ = flags; + } + virtual unsigned GetValidateFlags() const { + return flags_; + } + + virtual bool IsValid() const { + if (!valid_) return false; + if (GetContinueOnErrors() && !error_.ObjectEmpty()) return false; + return true; + } + //! End of Implementation of ISchemaValidator + + //! Gets the error object. + ValueType& GetError() { return error_; } + const ValueType& GetError() const { return error_; } + + //! Gets the JSON pointer pointed to the invalid schema. + // If reporting all errors, the stack will be empty. + PointerType GetInvalidSchemaPointer() const { + return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer(); + } + + //! Gets the keyword of invalid schema. + // If reporting all errors, the stack will be empty, so return "errors". + const Ch* GetInvalidSchemaKeyword() const { + if (!schemaStack_.Empty()) return CurrentContext().invalidKeyword; + if (GetContinueOnErrors() && !error_.ObjectEmpty()) return (const Ch*)GetErrorsString(); + return 0; + } + + //! Gets the error code of invalid schema. + // If reporting all errors, the stack will be empty, so return kValidateErrors. + ValidateErrorCode GetInvalidSchemaCode() const { + if (!schemaStack_.Empty()) return CurrentContext().invalidCode; + if (GetContinueOnErrors() && !error_.ObjectEmpty()) return kValidateErrors; + return kValidateErrorNone; + } + + //! Gets the JSON pointer pointed to the invalid value. + // If reporting all errors, the stack will be empty. + PointerType GetInvalidDocumentPointer() const { + if (documentStack_.Empty()) { + return PointerType(); + } + else { + return PointerType(documentStack_.template Bottom(), documentStack_.GetSize() / sizeof(Ch)); + } + } + + void NotMultipleOf(int64_t actual, const SValue& expected) { + AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected); + } + void NotMultipleOf(uint64_t actual, const SValue& expected) { + AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected); + } + void NotMultipleOf(double actual, const SValue& expected) { + AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected); + } + void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMaximumString : 0); + } + void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMaximumString : 0); + } + void AboveMaximum(double actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMaximumString : 0); + } + void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMinimumString : 0); + } + void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMinimumString : 0); + } + void BelowMinimum(double actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMinimumString : 0); + } + + void TooLong(const Ch* str, SizeType length, SizeType expected) { + AddNumberError(kValidateErrorMaxLength, + ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move()); + } + void TooShort(const Ch* str, SizeType length, SizeType expected) { + AddNumberError(kValidateErrorMinLength, + ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move()); + } + void DoesNotMatch(const Ch* str, SizeType length) { + currentError_.SetObject(); + currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator()); + AddCurrentError(kValidateErrorPattern); + } + + void DisallowedItem(SizeType index) { + currentError_.SetObject(); + currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator()); + AddCurrentError(kValidateErrorAdditionalItems, true); + } + void TooFewItems(SizeType actualCount, SizeType expectedCount) { + AddNumberError(kValidateErrorMinItems, + ValueType(actualCount).Move(), SValue(expectedCount).Move()); + } + void TooManyItems(SizeType actualCount, SizeType expectedCount) { + AddNumberError(kValidateErrorMaxItems, + ValueType(actualCount).Move(), SValue(expectedCount).Move()); + } + void DuplicateItems(SizeType index1, SizeType index2) { + ValueType duplicates(kArrayType); + duplicates.PushBack(index1, GetStateAllocator()); + duplicates.PushBack(index2, GetStateAllocator()); + currentError_.SetObject(); + currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator()); + AddCurrentError(kValidateErrorUniqueItems, true); + } + + void TooManyProperties(SizeType actualCount, SizeType expectedCount) { + AddNumberError(kValidateErrorMaxProperties, + ValueType(actualCount).Move(), SValue(expectedCount).Move()); + } + void TooFewProperties(SizeType actualCount, SizeType expectedCount) { + AddNumberError(kValidateErrorMinProperties, + ValueType(actualCount).Move(), SValue(expectedCount).Move()); + } + void StartMissingProperties() { + currentError_.SetArray(); + } + void AddMissingProperty(const SValue& name) { + currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator()); + } + bool EndMissingProperties() { + if (currentError_.Empty()) + return false; + ValueType error(kObjectType); + error.AddMember(GetMissingString(), currentError_, GetStateAllocator()); + currentError_ = error; + AddCurrentError(kValidateErrorRequired); + return true; + } + void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) { + for (SizeType i = 0; i < count; ++i) + MergeError(static_cast(subvalidators[i])->GetError()); + } + void DisallowedProperty(const Ch* name, SizeType length) { + currentError_.SetObject(); + currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator()); + AddCurrentError(kValidateErrorAdditionalProperties, true); + } + + void StartDependencyErrors() { + currentError_.SetObject(); + } + void StartMissingDependentProperties() { + missingDependents_.SetArray(); + } + void AddMissingDependentProperty(const SValue& targetName) { + missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator()); + } + void EndMissingDependentProperties(const SValue& sourceName) { + if (!missingDependents_.Empty()) { + // Create equivalent 'required' error + ValueType error(kObjectType); + ValidateErrorCode code = kValidateErrorRequired; + error.AddMember(GetMissingString(), missingDependents_.Move(), GetStateAllocator()); + AddErrorCode(error, code); + AddErrorInstanceLocation(error, false); + // When appending to a pointer ensure its allocator is used + PointerType schemaRef = GetInvalidSchemaPointer().Append(SchemaType::GetValidateErrorKeyword(kValidateErrorDependencies), &GetInvalidSchemaPointer().GetAllocator()); + AddErrorSchemaLocation(error, schemaRef.Append(sourceName.GetString(), sourceName.GetStringLength(), &GetInvalidSchemaPointer().GetAllocator())); + ValueType wrapper(kObjectType); + wrapper.AddMember(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator()).Move(), error, GetStateAllocator()); + currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(), wrapper, GetStateAllocator()); + } + } + void AddDependencySchemaError(const SValue& sourceName, ISchemaValidator* subvalidator) { + currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(), + static_cast(subvalidator)->GetError(), GetStateAllocator()); + } + bool EndDependencyErrors() { + if (currentError_.ObjectEmpty()) + return false; + ValueType error(kObjectType); + error.AddMember(GetErrorsString(), currentError_, GetStateAllocator()); + currentError_ = error; + AddCurrentError(kValidateErrorDependencies); + return true; + } + + void DisallowedValue(const ValidateErrorCode code = kValidateErrorEnum) { + currentError_.SetObject(); + AddCurrentError(code); + } + void StartDisallowedType() { + currentError_.SetArray(); + } + void AddExpectedType(const typename SchemaType::ValueType& expectedType) { + currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator()); + } + void EndDisallowedType(const typename SchemaType::ValueType& actualType) { + ValueType error(kObjectType); + error.AddMember(GetExpectedString(), currentError_, GetStateAllocator()); + error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator()); + currentError_ = error; + AddCurrentError(kValidateErrorType); + } + void NotAllOf(ISchemaValidator** subvalidators, SizeType count) { + // Treat allOf like oneOf and anyOf to match https://rapidjson.org/md_doc_schema.html#allOf-anyOf-oneOf + AddErrorArray(kValidateErrorAllOf, subvalidators, count); + //for (SizeType i = 0; i < count; ++i) { + // MergeError(static_cast(subvalidators[i])->GetError()); + //} + } + void NoneOf(ISchemaValidator** subvalidators, SizeType count) { + AddErrorArray(kValidateErrorAnyOf, subvalidators, count); + } + void NotOneOf(ISchemaValidator** subvalidators, SizeType count) { + AddErrorArray(kValidateErrorOneOf, subvalidators, count); + } + void MultipleOneOf(SizeType index1, SizeType index2) { + ValueType matches(kArrayType); + matches.PushBack(index1, GetStateAllocator()); + matches.PushBack(index2, GetStateAllocator()); + currentError_.SetObject(); + currentError_.AddMember(GetMatchesString(), matches, GetStateAllocator()); + AddCurrentError(kValidateErrorOneOfMatch); + } + void Disallowed() { + currentError_.SetObject(); + AddCurrentError(kValidateErrorNot); + } + void DisallowedWhenWriting() { + currentError_.SetObject(); + AddCurrentError(kValidateErrorReadOnly); + } + void DisallowedWhenReading() { + currentError_.SetObject(); + AddCurrentError(kValidateErrorWriteOnly); + } + +#define RAPIDJSON_STRING_(name, ...) \ + static const StringRefType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const StringRefType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1)); \ + return v;\ + } + + RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f') + RAPIDJSON_STRING_(SchemaRef, 's', 'c', 'h', 'e', 'm', 'a', 'R', 'e', 'f') + RAPIDJSON_STRING_(Expected, 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd') + RAPIDJSON_STRING_(Actual, 'a', 'c', 't', 'u', 'a', 'l') + RAPIDJSON_STRING_(Disallowed, 'd', 'i', 's', 'a', 'l', 'l', 'o', 'w', 'e', 'd') + RAPIDJSON_STRING_(Missing, 'm', 'i', 's', 's', 'i', 'n', 'g') + RAPIDJSON_STRING_(Errors, 'e', 'r', 'r', 'o', 'r', 's') + RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e') + RAPIDJSON_STRING_(ErrorMessage, 'e', 'r', 'r', 'o', 'r', 'M', 'e', 's', 's', 'a', 'g', 'e') + RAPIDJSON_STRING_(Duplicates, 'd', 'u', 'p', 'l', 'i', 'c', 'a', 't', 'e', 's') + RAPIDJSON_STRING_(Matches, 'm', 'a', 't', 'c', 'h', 'e', 's') + +#undef RAPIDJSON_STRING_ + +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ + if (!valid_) return false; \ + if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) {\ + *documentStack_.template Push() = '\0';\ + documentStack_.template Pop(1);\ + RAPIDJSON_SCHEMA_PRINT(InvalidDocument, documentStack_.template Bottom());\ + valid_ = false;\ + return valid_;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ + for (Context* context = schemaStack_.template Bottom(); context != schemaStack_.template End(); context++) {\ + if (context->hasher)\ + static_cast(context->hasher)->method arg2;\ + if (context->validators)\ + for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ + static_cast(context->validators[i_])->method arg2;\ + if (context->patternPropertiesValidators)\ + for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\ + static_cast(context->patternPropertiesValidators[i_])->method arg2;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\ + valid_ = (EndValue() || GetContinueOnErrors()) && (!outputHandler_ || outputHandler_->method arg2);\ + return valid_; + +#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \ + RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\ + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\ + RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2) + + bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ( )); } + bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); } + bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); } + bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); } + bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); } + bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); } + bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); } + bool RawNumber(const Ch* str, SizeType length, bool copy) + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + bool String(const Ch* str, SizeType length, bool copy) + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + + bool StartObject() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::StartObject"); + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ()); + valid_ = !outputHandler_ || outputHandler_->StartObject(); + return valid_; + } + + bool Key(const Ch* str, SizeType len, bool copy) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::Key", str); + if (!valid_) return false; + AppendToken(str, len); + if (!CurrentSchema().Key(CurrentContext(), str, len, copy) && !GetContinueOnErrors()) { + valid_ = false; + return valid_; + } + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy)); + valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy); + return valid_; + } + + bool EndObject(SizeType memberCount) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndObject"); + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount)); + if (!CurrentSchema().EndObject(CurrentContext(), memberCount) && !GetContinueOnErrors()) { + valid_ = false; + return valid_; + } + RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount)); + } + + bool StartArray() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::StartArray"); + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ()); + valid_ = !outputHandler_ || outputHandler_->StartArray(); + return valid_; + } + + bool EndArray(SizeType elementCount) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndArray"); + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount)); + if (!CurrentSchema().EndArray(CurrentContext(), elementCount) && !GetContinueOnErrors()) { + valid_ = false; + return valid_; + } + RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount)); + } + +#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_ +#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_ +#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_ + + // Implementation of ISchemaStateFactory + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root, const bool inheritContinueOnErrors) { + *documentStack_.template Push() = '\0'; + documentStack_.template Pop(1); + ISchemaValidator* sv = new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, documentStack_.template Bottom(), documentStack_.GetSize(), + depth_ + 1, + &GetStateAllocator()); + sv->SetValidateFlags(inheritContinueOnErrors ? GetValidateFlags() : GetValidateFlags() & ~(unsigned)kValidateContinueOnErrorFlag); + return sv; + } + + virtual void DestroySchemaValidator(ISchemaValidator* validator) { + GenericSchemaValidator* v = static_cast(validator); + v->~GenericSchemaValidator(); + StateAllocator::Free(v); + } + + virtual void* CreateHasher() { + return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator()); + } + + virtual uint64_t GetHashCode(void* hasher) { + return static_cast(hasher)->GetHashCode(); + } + + virtual void DestroryHasher(void* hasher) { + HasherType* h = static_cast(hasher); + h->~HasherType(); + StateAllocator::Free(h); + } + + virtual void* MallocState(size_t size) { + return GetStateAllocator().Malloc(size); + } + + virtual void FreeState(void* p) { + StateAllocator::Free(p); + } + // End of implementation of ISchemaStateFactory + +private: + typedef typename SchemaType::Context Context; + typedef GenericValue, StateAllocator> HashCodeArray; + typedef internal::Hasher HasherType; + + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + const SchemaType& root, + const char* basePath, size_t basePathSize, + unsigned depth, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(root), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + outputHandler_(0), + error_(kObjectType), + currentError_(), + missingDependents_(), + valid_(true), + flags_(kValidateDefaultFlags), + depth_(depth) + { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator (internal)", basePath && basePathSize ? basePath : ""); + if (basePath && basePathSize) + memcpy(documentStack_.template Push(basePathSize), basePath, basePathSize); + } + + StateAllocator& GetStateAllocator() { + if (!stateAllocator_) + stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)(); + return *stateAllocator_; + } + + bool GetContinueOnErrors() const { + return flags_ & kValidateContinueOnErrorFlag; + } + + bool BeginValue() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::BeginValue"); + if (schemaStack_.Empty()) + PushSchema(root_); + else { + if (CurrentContext().inArray) + internal::TokenHelper, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex); + + if (!CurrentSchema().BeginValue(CurrentContext()) && !GetContinueOnErrors()) + return false; + + SizeType count = CurrentContext().patternPropertiesSchemaCount; + const SchemaType** sa = CurrentContext().patternPropertiesSchemas; + typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType; + bool valueUniqueness = CurrentContext().valueUniqueness; + RAPIDJSON_ASSERT(CurrentContext().valueSchema); + PushSchema(*CurrentContext().valueSchema); + + if (count > 0) { + CurrentContext().objectPatternValidatorType = patternValidatorType; + ISchemaValidator**& va = CurrentContext().patternPropertiesValidators; + SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount; + va = static_cast(MallocState(sizeof(ISchemaValidator*) * count)); + std::memset(va, 0, sizeof(ISchemaValidator*) * count); + for (SizeType i = 0; i < count; i++) + va[validatorCount++] = CreateSchemaValidator(*sa[i], true); // Inherit continueOnError + } + + CurrentContext().arrayUniqueness = valueUniqueness; + } + return true; + } + + bool EndValue() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndValue"); + if (!CurrentSchema().EndValue(CurrentContext()) && !GetContinueOnErrors()) + return false; + + GenericStringBuffer sb; + schemaDocument_->GetPointer(&CurrentSchema()).StringifyUriFragment(sb); + *documentStack_.template Push() = '\0'; + documentStack_.template Pop(1); + RAPIDJSON_SCHEMA_PRINT(ValidatorPointers, sb.GetString(), documentStack_.template Bottom(), depth_); + void* hasher = CurrentContext().hasher; + uint64_t h = hasher && CurrentContext().arrayUniqueness ? static_cast(hasher)->GetHashCode() : 0; + + PopSchema(); + + if (!schemaStack_.Empty()) { + Context& context = CurrentContext(); + // Only check uniqueness if there is a hasher + if (hasher && context.valueUniqueness) { + HashCodeArray* a = static_cast(context.arrayElementHashCodes); + if (!a) + CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType); + for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr) + if (itr->GetUint64() == h) { + DuplicateItems(static_cast(itr - a->Begin()), a->Size()); + // Cleanup before returning if continuing + if (GetContinueOnErrors()) { + a->PushBack(h, GetStateAllocator()); + while (!documentStack_.Empty() && *documentStack_.template Pop(1) != '/'); + } + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorUniqueItems); + } + a->PushBack(h, GetStateAllocator()); + } + } + + // Remove the last token of document pointer + while (!documentStack_.Empty() && *documentStack_.template Pop(1) != '/') + ; + + return true; + } + + void AppendToken(const Ch* str, SizeType len) { + documentStack_.template Reserve(1 + len * 2); // worst case all characters are escaped as two characters + *documentStack_.template PushUnsafe() = '/'; + for (SizeType i = 0; i < len; i++) { + if (str[i] == '~') { + *documentStack_.template PushUnsafe() = '~'; + *documentStack_.template PushUnsafe() = '0'; + } + else if (str[i] == '/') { + *documentStack_.template PushUnsafe() = '~'; + *documentStack_.template PushUnsafe() = '1'; + } + else + *documentStack_.template PushUnsafe() = str[i]; + } + } + + RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push()) Context(*this, *this, &schema, flags_); } + + RAPIDJSON_FORCEINLINE void PopSchema() { + Context* c = schemaStack_.template Pop(1); + if (HashCodeArray* a = static_cast(c->arrayElementHashCodes)) { + a->~HashCodeArray(); + StateAllocator::Free(a); + } + c->~Context(); + } + + void AddErrorInstanceLocation(ValueType& result, bool parent) { + GenericStringBuffer sb; + PointerType instancePointer = GetInvalidDocumentPointer(); + ((parent && instancePointer.GetTokenCount() > 0) + ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1) + : instancePointer).StringifyUriFragment(sb); + ValueType instanceRef(sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch)), + GetStateAllocator()); + result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator()); + } + + void AddErrorSchemaLocation(ValueType& result, PointerType schema = PointerType()) { + GenericStringBuffer sb; + SizeType len = CurrentSchema().GetURI().GetStringLength(); + if (len) memcpy(sb.Push(len), CurrentSchema().GetURI().GetString(), len * sizeof(Ch)); + if (schema.GetTokenCount()) schema.StringifyUriFragment(sb); + else GetInvalidSchemaPointer().StringifyUriFragment(sb); + ValueType schemaRef(sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch)), + GetStateAllocator()); + result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator()); + } + + void AddErrorCode(ValueType& result, const ValidateErrorCode code) { + result.AddMember(GetErrorCodeString(), code, GetStateAllocator()); + } + + void AddError(ValueType& keyword, ValueType& error) { + typename ValueType::MemberIterator member = error_.FindMember(keyword); + if (member == error_.MemberEnd()) + error_.AddMember(keyword, error, GetStateAllocator()); + else { + if (member->value.IsObject()) { + ValueType errors(kArrayType); + errors.PushBack(member->value, GetStateAllocator()); + member->value = errors; + } + member->value.PushBack(error, GetStateAllocator()); + } + } + + void AddCurrentError(const ValidateErrorCode code, bool parent = false) { + AddErrorCode(currentError_, code); + AddErrorInstanceLocation(currentError_, parent); + AddErrorSchemaLocation(currentError_); + AddError(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator(), false).Move(), currentError_); + } + + void MergeError(ValueType& other) { + for (typename ValueType::MemberIterator it = other.MemberBegin(), end = other.MemberEnd(); it != end; ++it) { + AddError(it->name, it->value); + } + } + + void AddNumberError(const ValidateErrorCode code, ValueType& actual, const SValue& expected, + const typename SchemaType::ValueType& (*exclusive)() = 0) { + currentError_.SetObject(); + currentError_.AddMember(GetActualString(), actual, GetStateAllocator()); + currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator()); + if (exclusive) + currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(), true, GetStateAllocator()); + AddCurrentError(code); + } + + void AddErrorArray(const ValidateErrorCode code, + ISchemaValidator** subvalidators, SizeType count) { + ValueType errors(kArrayType); + for (SizeType i = 0; i < count; ++i) + errors.PushBack(static_cast(subvalidators[i])->GetError(), GetStateAllocator()); + currentError_.SetObject(); + currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator()); + AddCurrentError(code); + } + + const SchemaType& CurrentSchema() const { return *schemaStack_.template Top()->schema; } + Context& CurrentContext() { return *schemaStack_.template Top(); } + const Context& CurrentContext() const { return *schemaStack_.template Top(); } + + static const size_t kDefaultSchemaStackCapacity = 1024; + static const size_t kDefaultDocumentStackCapacity = 256; + const SchemaDocumentType* schemaDocument_; + const SchemaType& root_; + StateAllocator* stateAllocator_; + StateAllocator* ownStateAllocator_; + internal::Stack schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) + internal::Stack documentStack_; //!< stack to store the current path of validating document (Ch) + OutputHandler* outputHandler_; + ValueType error_; + ValueType currentError_; + ValueType missingDependents_; + bool valid_; + unsigned flags_; + unsigned depth_; +}; + +typedef GenericSchemaValidator SchemaValidator; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidatingReader + +//! A helper class for parsing with validation. +/*! + This helper class is a functor, designed as a parameter of \ref GenericDocument::Populate(). + + \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam SourceEncoding Encoding of the input stream. + \tparam SchemaDocumentType Type of schema document. + \tparam StackAllocator Allocator type for stack. +*/ +template < + unsigned parseFlags, + typename InputStream, + typename SourceEncoding, + typename SchemaDocumentType = SchemaDocument, + typename StackAllocator = CrtAllocator> +class SchemaValidatingReader { +public: + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename InputStream::Ch Ch; + typedef GenericValue ValueType; + + //! Constructor + /*! + \param is Input stream. + \param sd Schema document. + */ + SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), invalidSchemaCode_(kValidateErrorNone), error_(kObjectType), isValid_(true) {} + + template + bool operator()(Handler& handler) { + GenericReader reader; + GenericSchemaValidator validator(sd_, handler); + parseResult_ = reader.template Parse(is_, validator); + + isValid_ = validator.IsValid(); + if (isValid_) { + invalidSchemaPointer_ = PointerType(); + invalidSchemaKeyword_ = 0; + invalidDocumentPointer_ = PointerType(); + error_.SetObject(); + } + else { + invalidSchemaPointer_ = validator.GetInvalidSchemaPointer(); + invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword(); + invalidSchemaCode_ = validator.GetInvalidSchemaCode(); + invalidDocumentPointer_ = validator.GetInvalidDocumentPointer(); + error_.CopyFrom(validator.GetError(), allocator_); + } + + return parseResult_; + } + + const ParseResult& GetParseResult() const { return parseResult_; } + bool IsValid() const { return isValid_; } + const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; } + const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; } + const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; } + const ValueType& GetError() const { return error_; } + ValidateErrorCode GetInvalidSchemaCode() const { return invalidSchemaCode_; } + +private: + InputStream& is_; + const SchemaDocumentType& sd_; + + ParseResult parseResult_; + PointerType invalidSchemaPointer_; + const Ch* invalidSchemaKeyword_; + PointerType invalidDocumentPointer_; + ValidateErrorCode invalidSchemaCode_; + StackAllocator allocator_; + ValueType error_; + bool isValid_; +}; + +RAPIDJSON_NAMESPACE_END +RAPIDJSON_DIAG_POP + +#endif // RAPIDJSON_SCHEMA_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/stream.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/stream.h new file mode 100644 index 0000000..1fd7091 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/stream.h @@ -0,0 +1,223 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "rapidjson.h" + +#ifndef RAPIDJSON_STREAM_H_ +#define RAPIDJSON_STREAM_H_ + +#include "encodings.h" + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Stream + +/*! \class rapidjson::Stream + \brief Concept for reading and writing characters. + + For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). + + For write-only stream, only need to implement Put() and Flush(). + +\code +concept Stream { + typename Ch; //!< Character type of the stream. + + //! Read the current character from stream without moving the read cursor. + Ch Peek() const; + + //! Read the current character from stream and moving the read cursor to next character. + Ch Take(); + + //! Get the current read cursor. + //! \return Number of characters read from start. + size_t Tell(); + + //! Begin writing operation at the current read pointer. + //! \return The begin writer pointer. + Ch* PutBegin(); + + //! Write a character. + void Put(Ch c); + + //! Flush the buffer. + void Flush(); + + //! End the writing operation. + //! \param begin The begin write pointer returned by PutBegin(). + //! \return Number of characters written. + size_t PutEnd(Ch* begin); +} +\endcode +*/ + +//! Provides additional information for stream. +/*! + By using traits pattern, this type provides a default configuration for stream. + For custom stream, this type can be specialized for other configuration. + See TEST(Reader, CustomStringStream) in readertest.cpp for example. +*/ +template +struct StreamTraits { + //! Whether to make local copy of stream for optimization during parsing. + /*! + By default, for safety, streams do not use local copy optimization. + Stream that can be copied fast should specialize this, like StreamTraits. + */ + enum { copyOptimization = 0 }; +}; + +//! Reserve n characters for writing to a stream. +template +inline void PutReserve(Stream& stream, size_t count) { + (void)stream; + (void)count; +} + +//! Write character to a stream, presuming buffer is reserved. +template +inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { + stream.Put(c); +} + +//! Put N copies of a character to a stream. +template +inline void PutN(Stream& stream, Ch c, size_t n) { + PutReserve(stream, n); + for (size_t i = 0; i < n; i++) + PutUnsafe(stream, c); +} + +/////////////////////////////////////////////////////////////////////////////// +// GenericStreamWrapper + +//! A Stream Wrapper +/*! \tThis string stream is a wrapper for any stream by just forwarding any + \treceived message to the origin stream. + \note implements Stream concept +*/ + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4702) // unreachable code +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +template > +class GenericStreamWrapper { +public: + typedef typename Encoding::Ch Ch; + GenericStreamWrapper(InputStream& is): is_(is) {} + + Ch Peek() const { return is_.Peek(); } + Ch Take() { return is_.Take(); } + size_t Tell() { return is_.Tell(); } + Ch* PutBegin() { return is_.PutBegin(); } + void Put(Ch ch) { is_.Put(ch); } + void Flush() { is_.Flush(); } + size_t PutEnd(Ch* ch) { return is_.PutEnd(ch); } + + // wrapper for MemoryStream + const Ch* Peek4() const { return is_.Peek4(); } + + // wrapper for AutoUTFInputStream + UTFType GetType() const { return is_.GetType(); } + bool HasBOM() const { return is_.HasBOM(); } + +protected: + InputStream& is_; +}; + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +RAPIDJSON_DIAG_POP +#endif + +/////////////////////////////////////////////////////////////////////////////// +// StringStream + +//! Read-only string stream. +/*! \note implements Stream concept +*/ +template +struct GenericStringStream { + typedef typename Encoding::Ch Ch; + + GenericStringStream(const Ch *src) : src_(src), head_(src) {} + + Ch Peek() const { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() const { return static_cast(src_ - head_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! String stream with UTF8 encoding. +typedef GenericStringStream > StringStream; + +/////////////////////////////////////////////////////////////////////////////// +// InsituStringStream + +//! A read-write string stream. +/*! This string stream is particularly designed for in-situ parsing. + \note implements Stream concept +*/ +template +struct GenericInsituStringStream { + typedef typename Encoding::Ch Ch; + + GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} + + // Read + Ch Peek() { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() { return static_cast(src_ - head_); } + + // Write + void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } + + Ch* PutBegin() { return dst_ = src_; } + size_t PutEnd(Ch* begin) { return static_cast(dst_ - begin); } + void Flush() {} + + Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } + void Pop(size_t count) { dst_ -= count; } + + Ch* src_; + Ch* dst_; + Ch* head_; +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! Insitu string stream with UTF8 encoding. +typedef GenericInsituStringStream > InsituStringStream; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STREAM_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/stringbuffer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/stringbuffer.h new file mode 100644 index 0000000..82ad3ca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/stringbuffer.h @@ -0,0 +1,121 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_STRINGBUFFER_H_ +#define RAPIDJSON_STRINGBUFFER_H_ + +#include "stream.h" +#include "internal/stack.h" + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + +#include "internal/stack.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output stream. +/*! + \tparam Encoding Encoding of the stream. + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template +class GenericStringBuffer { +public: + typedef typename Encoding::Ch Ch; + + GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} + GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { + if (&rhs != this) + stack_ = std::move(rhs.stack_); + return *this; + } +#endif + + void Put(Ch c) { *stack_.template Push() = c; } + void PutUnsafe(Ch c) { *stack_.template PushUnsafe() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.ShrinkToFit(); + stack_.template Pop(1); + } + + void Reserve(size_t count) { stack_.template Reserve(count); } + Ch* Push(size_t count) { return stack_.template Push(count); } + Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe(count); } + void Pop(size_t count) { stack_.template Pop(count); } + + const Ch* GetString() const { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.template Pop(1); + + return stack_.template Bottom(); + } + + //! Get the size of string in bytes in the string buffer. + size_t GetSize() const { return stack_.GetSize(); } + + //! Get the length of string in Ch in the string buffer. + size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; + +private: + // Prohibit copy constructor & assignment operator. + GenericStringBuffer(const GenericStringBuffer&); + GenericStringBuffer& operator=(const GenericStringBuffer&); +}; + +//! String buffer with UTF8 encoding +typedef GenericStringBuffer > StringBuffer; + +template +inline void PutReserve(GenericStringBuffer& stream, size_t count) { + stream.Reserve(count); +} + +template +inline void PutUnsafe(GenericStringBuffer& stream, typename Encoding::Ch c) { + stream.PutUnsafe(c); +} + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { + std::memset(stream.stack_.Push(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/uri.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/uri.h new file mode 100644 index 0000000..f93e508 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/uri.h @@ -0,0 +1,481 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// (C) Copyright IBM Corporation 2021 +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_URI_H_ +#define RAPIDJSON_URI_H_ + +#include "internal/strfunc.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// GenericUri + +template +class GenericUri { +public: + typedef typename ValueType::Ch Ch; +#if RAPIDJSON_HAS_STDSTRING + typedef std::basic_string String; +#endif + + //! Constructors + GenericUri(Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + } + + GenericUri(const Ch* uri, SizeType len, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + Parse(uri, len); + } + + GenericUri(const Ch* uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + Parse(uri, internal::StrLen(uri)); + } + + // Use with specializations of GenericValue + template GenericUri(const T& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + const Ch* u = uri.template Get(); // TypeHelper from document.h + Parse(u, internal::StrLen(u)); + } + +#if RAPIDJSON_HAS_STDSTRING + GenericUri(const String& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + Parse(uri.c_str(), internal::StrLen(uri.c_str())); + } +#endif + + //! Copy constructor + GenericUri(const GenericUri& rhs) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(), ownAllocator_() { + *this = rhs; + } + + //! Copy constructor + GenericUri(const GenericUri& rhs, Allocator* allocator) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + *this = rhs; + } + + //! Destructor. + ~GenericUri() { + Free(); + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Assignment operator + GenericUri& operator=(const GenericUri& rhs) { + if (this != &rhs) { + // Do not delete ownAllocator + Free(); + Allocate(rhs.GetStringLength()); + auth_ = CopyPart(scheme_, rhs.scheme_, rhs.GetSchemeStringLength()); + path_ = CopyPart(auth_, rhs.auth_, rhs.GetAuthStringLength()); + query_ = CopyPart(path_, rhs.path_, rhs.GetPathStringLength()); + frag_ = CopyPart(query_, rhs.query_, rhs.GetQueryStringLength()); + base_ = CopyPart(frag_, rhs.frag_, rhs.GetFragStringLength()); + uri_ = CopyPart(base_, rhs.base_, rhs.GetBaseStringLength()); + CopyPart(uri_, rhs.uri_, rhs.GetStringLength()); + } + return *this; + } + + //! Getters + // Use with specializations of GenericValue + template void Get(T& uri, Allocator& allocator) { + uri.template Set(this->GetString(), allocator); // TypeHelper from document.h + } + + const Ch* GetString() const { return uri_; } + SizeType GetStringLength() const { return uri_ == 0 ? 0 : internal::StrLen(uri_); } + const Ch* GetBaseString() const { return base_; } + SizeType GetBaseStringLength() const { return base_ == 0 ? 0 : internal::StrLen(base_); } + const Ch* GetSchemeString() const { return scheme_; } + SizeType GetSchemeStringLength() const { return scheme_ == 0 ? 0 : internal::StrLen(scheme_); } + const Ch* GetAuthString() const { return auth_; } + SizeType GetAuthStringLength() const { return auth_ == 0 ? 0 : internal::StrLen(auth_); } + const Ch* GetPathString() const { return path_; } + SizeType GetPathStringLength() const { return path_ == 0 ? 0 : internal::StrLen(path_); } + const Ch* GetQueryString() const { return query_; } + SizeType GetQueryStringLength() const { return query_ == 0 ? 0 : internal::StrLen(query_); } + const Ch* GetFragString() const { return frag_; } + SizeType GetFragStringLength() const { return frag_ == 0 ? 0 : internal::StrLen(frag_); } + +#if RAPIDJSON_HAS_STDSTRING + static String Get(const GenericUri& uri) { return String(uri.GetString(), uri.GetStringLength()); } + static String GetBase(const GenericUri& uri) { return String(uri.GetBaseString(), uri.GetBaseStringLength()); } + static String GetScheme(const GenericUri& uri) { return String(uri.GetSchemeString(), uri.GetSchemeStringLength()); } + static String GetAuth(const GenericUri& uri) { return String(uri.GetAuthString(), uri.GetAuthStringLength()); } + static String GetPath(const GenericUri& uri) { return String(uri.GetPathString(), uri.GetPathStringLength()); } + static String GetQuery(const GenericUri& uri) { return String(uri.GetQueryString(), uri.GetQueryStringLength()); } + static String GetFrag(const GenericUri& uri) { return String(uri.GetFragString(), uri.GetFragStringLength()); } +#endif + + //! Equality operators + bool operator==(const GenericUri& rhs) const { + return Match(rhs, true); + } + + bool operator!=(const GenericUri& rhs) const { + return !Match(rhs, true); + } + + bool Match(const GenericUri& uri, bool full = true) const { + Ch* s1; + Ch* s2; + if (full) { + s1 = uri_; + s2 = uri.uri_; + } else { + s1 = base_; + s2 = uri.base_; + } + if (s1 == s2) return true; + if (s1 == 0 || s2 == 0) return false; + return internal::StrCmp(s1, s2) == 0; + } + + //! Resolve this URI against another (base) URI in accordance with URI resolution rules. + // See https://tools.ietf.org/html/rfc3986 + // Use for resolving an id or $ref with an in-scope id. + // Returns a new GenericUri for the resolved URI. + GenericUri Resolve(const GenericUri& baseuri, Allocator* allocator = 0) { + GenericUri resuri; + resuri.allocator_ = allocator; + // Ensure enough space for combining paths + resuri.Allocate(GetStringLength() + baseuri.GetStringLength() + 1); // + 1 for joining slash + + if (!(GetSchemeStringLength() == 0)) { + // Use all of this URI + resuri.auth_ = CopyPart(resuri.scheme_, scheme_, GetSchemeStringLength()); + resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength()); + resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + resuri.RemoveDotSegments(); + } else { + // Use the base scheme + resuri.auth_ = CopyPart(resuri.scheme_, baseuri.scheme_, baseuri.GetSchemeStringLength()); + if (!(GetAuthStringLength() == 0)) { + // Use this auth, path, query + resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength()); + resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + resuri.RemoveDotSegments(); + } else { + // Use the base auth + resuri.path_ = CopyPart(resuri.auth_, baseuri.auth_, baseuri.GetAuthStringLength()); + if (GetPathStringLength() == 0) { + // Use the base path + resuri.query_ = CopyPart(resuri.path_, baseuri.path_, baseuri.GetPathStringLength()); + if (GetQueryStringLength() == 0) { + // Use the base query + resuri.frag_ = CopyPart(resuri.query_, baseuri.query_, baseuri.GetQueryStringLength()); + } else { + // Use this query + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + } + } else { + if (path_[0] == '/') { + // Absolute path - use all of this path + resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); + resuri.RemoveDotSegments(); + } else { + // Relative path - append this path to base path after base path's last slash + size_t pos = 0; + if (!(baseuri.GetAuthStringLength() == 0) && baseuri.GetPathStringLength() == 0) { + resuri.path_[pos] = '/'; + pos++; + } + size_t lastslashpos = baseuri.GetPathStringLength(); + while (lastslashpos > 0) { + if (baseuri.path_[lastslashpos - 1] == '/') break; + lastslashpos--; + } + std::memcpy(&resuri.path_[pos], baseuri.path_, lastslashpos * sizeof(Ch)); + pos += lastslashpos; + resuri.query_ = CopyPart(&resuri.path_[pos], path_, GetPathStringLength()); + resuri.RemoveDotSegments(); + } + // Use this query + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + } + } + } + // Always use this frag + resuri.base_ = CopyPart(resuri.frag_, frag_, GetFragStringLength()); + + // Re-constitute base_ and uri_ + resuri.SetBase(); + resuri.uri_ = resuri.base_ + resuri.GetBaseStringLength() + 1; + resuri.SetUri(); + return resuri; + } + + //! Get the allocator of this GenericUri. + Allocator& GetAllocator() { return *allocator_; } + +private: + // Allocate memory for a URI + // Returns total amount allocated + std::size_t Allocate(std::size_t len) { + // Create own allocator if user did not supply. + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + // Allocate one block containing each part of the URI (5) plus base plus full URI, all null terminated. + // Order: scheme, auth, path, query, frag, base, uri + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + size_t total = (3 * len + 7) * sizeof(Ch); + scheme_ = static_cast(allocator_->Malloc(total)); + *scheme_ = '\0'; + auth_ = scheme_; + auth_++; + *auth_ = '\0'; + path_ = auth_; + path_++; + *path_ = '\0'; + query_ = path_; + query_++; + *query_ = '\0'; + frag_ = query_; + frag_++; + *frag_ = '\0'; + base_ = frag_; + base_++; + *base_ = '\0'; + uri_ = base_; + uri_++; + *uri_ = '\0'; + return total; + } + + // Free memory for a URI + void Free() { + if (scheme_) { + Allocator::Free(scheme_); + scheme_ = 0; + } + } + + // Parse a URI into constituent scheme, authority, path, query, & fragment parts + // Supports URIs that match regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? as per + // https://tools.ietf.org/html/rfc3986 + void Parse(const Ch* uri, std::size_t len) { + std::size_t start = 0, pos1 = 0, pos2 = 0; + Allocate(len); + + // Look for scheme ([^:/?#]+):)? + if (start < len) { + while (pos1 < len) { + if (uri[pos1] == ':') break; + pos1++; + } + if (pos1 != len) { + while (pos2 < len) { + if (uri[pos2] == '/') break; + if (uri[pos2] == '?') break; + if (uri[pos2] == '#') break; + pos2++; + } + if (pos1 < pos2) { + pos1++; + std::memcpy(scheme_, &uri[start], pos1 * sizeof(Ch)); + scheme_[pos1] = '\0'; + start = pos1; + } + } + } + // Look for auth (//([^/?#]*))? + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + auth_ = scheme_ + GetSchemeStringLength(); + auth_++; + *auth_ = '\0'; + if (start < len - 1 && uri[start] == '/' && uri[start + 1] == '/') { + pos2 = start + 2; + while (pos2 < len) { + if (uri[pos2] == '/') break; + if (uri[pos2] == '?') break; + if (uri[pos2] == '#') break; + pos2++; + } + std::memcpy(auth_, &uri[start], (pos2 - start) * sizeof(Ch)); + auth_[pos2 - start] = '\0'; + start = pos2; + } + // Look for path ([^?#]*) + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + path_ = auth_ + GetAuthStringLength(); + path_++; + *path_ = '\0'; + if (start < len) { + pos2 = start; + while (pos2 < len) { + if (uri[pos2] == '?') break; + if (uri[pos2] == '#') break; + pos2++; + } + if (start != pos2) { + std::memcpy(path_, &uri[start], (pos2 - start) * sizeof(Ch)); + path_[pos2 - start] = '\0'; + if (path_[0] == '/') + RemoveDotSegments(); // absolute path - normalize + start = pos2; + } + } + // Look for query (\?([^#]*))? + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + query_ = path_ + GetPathStringLength(); + query_++; + *query_ = '\0'; + if (start < len && uri[start] == '?') { + pos2 = start + 1; + while (pos2 < len) { + if (uri[pos2] == '#') break; + pos2++; + } + if (start != pos2) { + std::memcpy(query_, &uri[start], (pos2 - start) * sizeof(Ch)); + query_[pos2 - start] = '\0'; + start = pos2; + } + } + // Look for fragment (#(.*))? + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + frag_ = query_ + GetQueryStringLength(); + frag_++; + *frag_ = '\0'; + if (start < len && uri[start] == '#') { + std::memcpy(frag_, &uri[start], (len - start) * sizeof(Ch)); + frag_[len - start] = '\0'; + } + + // Re-constitute base_ and uri_ + base_ = frag_ + GetFragStringLength() + 1; + SetBase(); + uri_ = base_ + GetBaseStringLength() + 1; + SetUri(); + } + + // Reconstitute base + void SetBase() { + Ch* next = base_; + std::memcpy(next, scheme_, GetSchemeStringLength() * sizeof(Ch)); + next+= GetSchemeStringLength(); + std::memcpy(next, auth_, GetAuthStringLength() * sizeof(Ch)); + next+= GetAuthStringLength(); + std::memcpy(next, path_, GetPathStringLength() * sizeof(Ch)); + next+= GetPathStringLength(); + std::memcpy(next, query_, GetQueryStringLength() * sizeof(Ch)); + next+= GetQueryStringLength(); + *next = '\0'; + } + + // Reconstitute uri + void SetUri() { + Ch* next = uri_; + std::memcpy(next, base_, GetBaseStringLength() * sizeof(Ch)); + next+= GetBaseStringLength(); + std::memcpy(next, frag_, GetFragStringLength() * sizeof(Ch)); + next+= GetFragStringLength(); + *next = '\0'; + } + + // Copy a part from one GenericUri to another + // Return the pointer to the next part to be copied to + Ch* CopyPart(Ch* to, Ch* from, std::size_t len) { + RAPIDJSON_ASSERT(to != 0); + RAPIDJSON_ASSERT(from != 0); + std::memcpy(to, from, len * sizeof(Ch)); + to[len] = '\0'; + Ch* next = to + len + 1; + return next; + } + + // Remove . and .. segments from the path_ member. + // https://tools.ietf.org/html/rfc3986 + // This is done in place as we are only removing segments. + void RemoveDotSegments() { + std::size_t pathlen = GetPathStringLength(); + std::size_t pathpos = 0; // Position in path_ + std::size_t newpos = 0; // Position in new path_ + + // Loop through each segment in original path_ + while (pathpos < pathlen) { + // Get next segment, bounded by '/' or end + size_t slashpos = 0; + while ((pathpos + slashpos) < pathlen) { + if (path_[pathpos + slashpos] == '/') break; + slashpos++; + } + // Check for .. and . segments + if (slashpos == 2 && path_[pathpos] == '.' && path_[pathpos + 1] == '.') { + // Backup a .. segment in the new path_ + // We expect to find a previously added slash at the end or nothing + RAPIDJSON_ASSERT(newpos == 0 || path_[newpos - 1] == '/'); + size_t lastslashpos = newpos; + // Make sure we don't go beyond the start segment + if (lastslashpos > 1) { + // Find the next to last slash and back up to it + lastslashpos--; + while (lastslashpos > 0) { + if (path_[lastslashpos - 1] == '/') break; + lastslashpos--; + } + // Set the new path_ position + newpos = lastslashpos; + } + } else if (slashpos == 1 && path_[pathpos] == '.') { + // Discard . segment, leaves new path_ unchanged + } else { + // Move any other kind of segment to the new path_ + RAPIDJSON_ASSERT(newpos <= pathpos); + std::memmove(&path_[newpos], &path_[pathpos], slashpos * sizeof(Ch)); + newpos += slashpos; + // Add slash if not at end + if ((pathpos + slashpos) < pathlen) { + path_[newpos] = '/'; + newpos++; + } + } + // Move to next segment + pathpos += slashpos + 1; + } + path_[newpos] = '\0'; + } + + Ch* uri_; // Everything + Ch* base_; // Everything except fragment + Ch* scheme_; // Includes the : + Ch* auth_; // Includes the // + Ch* path_; // Absolute if starts with / + Ch* query_; // Includes the ? + Ch* frag_; // Includes the # + + Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. + Allocator* ownAllocator_; //!< Allocator owned by this Uri. +}; + +//! GenericUri for Value (UTF-8, default allocator). +typedef GenericUri Uri; + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_URI_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/writer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/writer.h new file mode 100644 index 0000000..142230d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/writer.h @@ -0,0 +1,721 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_WRITER_H_ +#define RAPIDJSON_WRITER_H_ + +#include "stream.h" +#include "internal/clzll.h" +#include "internal/meta.h" +#include "internal/stack.h" +#include "internal/strfunc.h" +#include "internal/dtoa.h" +#include "internal/itoa.h" +#include "stringbuffer.h" +#include // placement new + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#elif defined(RAPIDJSON_NEON) +#include +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(c++98-compat) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// WriteFlag + +/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kWriteDefaultFlags definition. + + User can define this as any \c WriteFlag combinations. +*/ +#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS +#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags +#endif + +//! Combination of writeFlags +enum WriteFlag { + kWriteNoFlags = 0, //!< No flags are set. + kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. + kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN. + kWriteNanAndInfNullFlag = 4, //!< Allow writing of Infinity, -Infinity and NaN as null. + kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS +}; + +//! JSON writer +/*! Writer implements the concept Handler. + It generates JSON text by events to an output os. + + User may programmatically calls the functions of a writer to generate JSON text. + + On the other side, a writer can also be passed to objects that generates events, + + for example Reader::Parse() and Document::Accept(). + + \tparam OutputStream Type of output stream. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. + \note implements Handler concept +*/ +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class Writer { +public: + typedef typename SourceEncoding::Ch Ch; + + static const int kDefaultMaxDecimalPlaces = 324; + + //! Constructor + /*! \param os Output stream. + \param stackAllocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit + Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + + explicit + Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Writer(Writer&& rhs) : + os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) { + rhs.os_ = 0; + } +#endif + + //! Reset the writer with a new stream. + /*! + This function reset the writer with a new stream and default settings, + in order to make a Writer object reusable for output multiple JSONs. + + \param os New output stream. + \code + Writer writer(os1); + writer.StartObject(); + // ... + writer.EndObject(); + + writer.Reset(os2); + writer.StartObject(); + // ... + writer.EndObject(); + \endcode + */ + void Reset(OutputStream& os) { + os_ = &os; + hasRoot_ = false; + level_stack_.Clear(); + } + + //! Checks whether the output is a complete JSON. + /*! + A complete JSON has a complete root object or array. + */ + bool IsComplete() const { + return hasRoot_ && level_stack_.Empty(); + } + + int GetMaxDecimalPlaces() const { + return maxDecimalPlaces_; + } + + //! Sets the maximum number of decimal places for double output. + /*! + This setting truncates the output with specified number of decimal places. + + For example, + + \code + writer.SetMaxDecimalPlaces(3); + writer.StartArray(); + writer.Double(0.12345); // "0.123" + writer.Double(0.0001); // "0.0" + writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent) + writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent) + writer.EndArray(); + \endcode + + The default setting does not truncate any decimal places. You can restore to this setting by calling + \code + writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces); + \endcode + */ + void SetMaxDecimalPlaces(int maxDecimalPlaces) { + maxDecimalPlaces_ = maxDecimalPlaces; + } + + /*!@name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { Prefix(kNullType); return EndValue(WriteNull()); } + bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); } + bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); } + bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); } + bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); } + bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); } + + //! Writes the given \c double value to the stream + /*! + \param d The value to be written. + \return Whether it is succeed. + */ + bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + Prefix(kNumberType); + return EndValue(WriteString(str, length)); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + Prefix(kStringType); + return EndValue(WriteString(str, length)); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push()) Level(false); + return WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + +#if RAPIDJSON_HAS_STDSTRING + bool Key(const std::basic_string& str) + { + return Key(str.data(), SizeType(str.size())); + } +#endif + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object + RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == level_stack_.template Top()->valueCount % 2); // Object has a Key without a Value + level_stack_.template Pop(1); + return EndValue(WriteEndObject()); + } + + bool StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push()) Level(true); + return WriteStartArray(); + } + + bool EndArray(SizeType elementCount = 0) { + (void)elementCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + return EndValue(WriteEndArray()); + } + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); } + + //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + */ + bool RawValue(const Ch* json, size_t length, Type type) { + RAPIDJSON_ASSERT(json != 0); + Prefix(type); + return EndValue(WriteRawValue(json, length)); + } + + //! Flush the output stream. + /*! + Allows the user to flush the output stream immediately. + */ + void Flush() { + os_->Flush(); + } + + static const size_t kDefaultLevelDepth = 32; + +protected: + //! Information for each nested level + struct Level { + Level(bool inArray_) : valueCount(0), inArray(inArray_) {} + size_t valueCount; //!< number of values in this level + bool inArray; //!< true if in array, otherwise in object + }; + + bool WriteNull() { + PutReserve(*os_, 4); + PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true; + } + + bool WriteBool(bool b) { + if (b) { + PutReserve(*os_, 4); + PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e'); + } + else { + PutReserve(*os_, 5); + PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e'); + } + return true; + } + + bool WriteInt(int i) { + char buffer[11]; + const char* end = internal::i32toa(i, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteUint(unsigned u) { + char buffer[10]; + const char* end = internal::u32toa(u, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteInt64(int64_t i64) { + char buffer[21]; + const char* end = internal::i64toa(i64, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* end = internal::u64toa(u64, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + if (!(writeFlags & kWriteNanAndInfFlag)) + return false; + if (writeFlags & kWriteNanAndInfNullFlag) { + PutReserve(*os_, 4); + PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); + return true; + } + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + + char buffer[25]; + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + PutReserve(*os_, static_cast(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteString(const Ch* str, SizeType length) { + static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const char escape[256] = { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF +#undef Z16 + }; + + if (TargetEncoding::supportUnicode) + PutReserve(*os_, 2 + length * 6); // "\uxxxx..." + else + PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..." + + PutUnsafe(*os_, '\"'); + GenericStringStream is(str); + while (ScanWriteUnescapedString(is, length)) { + const Ch c = is.Peek(); + if (!TargetEncoding::supportUnicode && static_cast(c) >= 0x80) { + // Unicode escaping + unsigned codepoint; + if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint))) + return false; + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { + PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint ) & 15]); + } + else { + RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); + // Surrogate pair + unsigned s = codepoint - 0x010000; + unsigned lead = (s >> 10) + 0xD800; + unsigned trail = (s & 0x3FF) + 0xDC00; + PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(lead ) & 15]); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(trail ) & 15]); + } + } + else if ((sizeof(Ch) == 1 || static_cast(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast(c)])) { + is.Take(); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, static_cast(escape[static_cast(c)])); + if (escape[static_cast(c)] == 'u') { + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, hexDigits[static_cast(c) >> 4]); + PutUnsafe(*os_, hexDigits[static_cast(c) & 0xF]); + } + } + else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder::Validate(is, *os_) : + Transcoder::TranscodeUnsafe(is, *os_)))) + return false; + } + PutUnsafe(*os_, '\"'); + return true; + } + + bool ScanWriteUnescapedString(GenericStringStream& is, size_t length) { + return RAPIDJSON_LIKELY(is.Tell() < length); + } + + bool WriteStartObject() { os_->Put('{'); return true; } + bool WriteEndObject() { os_->Put('}'); return true; } + bool WriteStartArray() { os_->Put('['); return true; } + bool WriteEndArray() { os_->Put(']'); return true; } + + bool WriteRawValue(const Ch* json, size_t length) { + PutReserve(*os_, length); + GenericStringStream is(json); + while (RAPIDJSON_LIKELY(is.Tell() < length)) { + RAPIDJSON_ASSERT(is.Peek() != '\0'); + if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder::Validate(is, *os_) : + Transcoder::TranscodeUnsafe(is, *os_)))) + return false; + } + return true; + } + + void Prefix(Type type) { + (void)type; + if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root + Level* level = level_stack_.template Top(); + if (level->valueCount > 0) { + if (level->inArray) + os_->Put(','); // add comma if it is not the first element in array + else // in object + os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. + hasRoot_ = true; + } + } + + // Flush the value if it is the top level one. + bool EndValue(bool ret) { + if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text + Flush(); + return ret; + } + + OutputStream* os_; + internal::Stack level_stack_; + int maxDecimalPlaces_; + bool hasRoot_; + +private: + // Prohibit copy constructor & assignment operator. + Writer(const Writer&); + Writer& operator=(const Writer&); +}; + +// Full specialization for StringStream to prevent memory copying + +template<> +inline bool Writer::WriteInt(int i) { + char *buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(static_cast(11 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteUint(unsigned u) { + char *buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(static_cast(10 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteInt64(int64_t i64) { + char *buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(static_cast(21 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteUint64(uint64_t u) { + char *buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(static_cast(20 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). + if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) + return false; + if (kWriteDefaultFlags & kWriteNanAndInfNullFlag) { + PutReserve(*os_, 4); + PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); + return true; + } + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + + char *buffer = os_->Push(25); + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + os_->Pop(static_cast(25 - (end - buffer))); + return true; +} + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) +template<> +inline bool Writer::ScanWriteUnescapedString(StringStream& is, size_t length) { + if (length < 16) + return RAPIDJSON_LIKELY(is.Tell() < length); + + if (!RAPIDJSON_LIKELY(is.Tell() < length)) + return false; + + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + const char* endAligned = reinterpret_cast(reinterpret_cast(end) & static_cast(~15)); + if (nextAligned > end) + return true; + + while (p != nextAligned) + if (*p < 0x20 || *p == '\"' || *p == '\\') { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + os_->PutUnsafe(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (; p != endAligned; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType len; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + len = offset; +#else + len = static_cast(__builtin_ffs(r) - 1); +#endif + char* q = reinterpret_cast(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s); + } + + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); +} +#elif defined(RAPIDJSON_NEON) +template<> +inline bool Writer::ScanWriteUnescapedString(StringStream& is, size_t length) { + if (length < 16) + return RAPIDJSON_LIKELY(is.Tell() < length); + + if (!RAPIDJSON_LIKELY(is.Tell() < length)) + return false; + + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + const char* endAligned = reinterpret_cast(reinterpret_cast(end) & static_cast(~15)); + if (nextAligned > end) + return true; + + while (p != nextAligned) + if (*p < 0x20 || *p == '\"' || *p == '\\') { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + os_->PutUnsafe(*p++); + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (; p != endAligned; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + SizeType len = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + len = 8 + (lz >> 3); + escaped = true; + } + } else { + uint32_t lz = internal::clzll(low); + len = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + char* q = reinterpret_cast(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + vst1q_u8(reinterpret_cast(os_->PushUnsafe(16)), s); + } + + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); +} +#endif // RAPIDJSON_NEON + +RAPIDJSON_NAMESPACE_END + +#if defined(_MSC_VER) || defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/async.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/async.h new file mode 100644 index 0000000..e96abd1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/async.h @@ -0,0 +1,100 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// +// Async logging using global thread pool +// All loggers created here share same global thread pool. +// Each log message is pushed to a queue along with a shared pointer to the +// logger. +// If a logger deleted while having pending messages in the queue, it's actual +// destruction will defer +// until all its messages are processed by the thread pool. +// This is because each message in the queue holds a shared_ptr to the +// originating logger. + +#include +#include +#include + +#include +#include +#include + +namespace spdlog { + +namespace details { +static const size_t default_async_q_size = 8192; +} + +// async logger factory - creates async loggers backed with thread pool. +// if a global thread pool doesn't already exist, create it with default queue +// size of 8192 items and single thread. +template +struct async_factory_impl { + template + static std::shared_ptr create(std::string logger_name, SinkArgs &&...args) { + auto ®istry_inst = details::registry::instance(); + + // create global thread pool if not already exists.. + + auto &mutex = registry_inst.tp_mutex(); + std::lock_guard tp_lock(mutex); + auto tp = registry_inst.get_tp(); + if (tp == nullptr) { + tp = std::make_shared(details::default_async_q_size, 1U); + registry_inst.set_tp(tp); + } + + auto sink = std::make_shared(std::forward(args)...); + auto new_logger = std::make_shared(std::move(logger_name), std::move(sink), + std::move(tp), OverflowPolicy); + registry_inst.initialize_logger(new_logger); + return new_logger; + } +}; + +using async_factory = async_factory_impl; +using async_factory_nonblock = async_factory_impl; + +template +inline std::shared_ptr create_async(std::string logger_name, + SinkArgs &&...sink_args) { + return async_factory::create(std::move(logger_name), + std::forward(sink_args)...); +} + +template +inline std::shared_ptr create_async_nb(std::string logger_name, + SinkArgs &&...sink_args) { + return async_factory_nonblock::create(std::move(logger_name), + std::forward(sink_args)...); +} + +// set global thread pool. +inline void init_thread_pool(size_t q_size, + size_t thread_count, + std::function on_thread_start, + std::function on_thread_stop) { + auto tp = std::make_shared(q_size, thread_count, on_thread_start, + on_thread_stop); + details::registry::instance().set_tp(std::move(tp)); +} + +inline void init_thread_pool(size_t q_size, + size_t thread_count, + std::function on_thread_start) { + init_thread_pool(q_size, thread_count, on_thread_start, [] {}); +} + +inline void init_thread_pool(size_t q_size, size_t thread_count) { + init_thread_pool( + q_size, thread_count, [] {}, [] {}); +} + +// get the global thread pool. +inline std::shared_ptr thread_pool() { + return details::registry::instance().get_tp(); +} +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/async_logger-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/async_logger-inl.h new file mode 100644 index 0000000..1e79479 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/async_logger-inl.h @@ -0,0 +1,84 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +#include +#include + +SPDLOG_INLINE spdlog::async_logger::async_logger(std::string logger_name, + sinks_init_list sinks_list, + std::weak_ptr tp, + async_overflow_policy overflow_policy) + : async_logger(std::move(logger_name), + sinks_list.begin(), + sinks_list.end(), + std::move(tp), + overflow_policy) {} + +SPDLOG_INLINE spdlog::async_logger::async_logger(std::string logger_name, + sink_ptr single_sink, + std::weak_ptr tp, + async_overflow_policy overflow_policy) + : async_logger( + std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy) {} + +// send the log message to the thread pool +SPDLOG_INLINE void spdlog::async_logger::sink_it_(const details::log_msg &msg){ + SPDLOG_TRY{if (auto pool_ptr = thread_pool_.lock()){ + pool_ptr->post_log(shared_from_this(), msg, overflow_policy_); +} +else { + throw_spdlog_ex("async log: thread pool doesn't exist anymore"); +} +} +SPDLOG_LOGGER_CATCH(msg.source) +} + +// send flush request to the thread pool +SPDLOG_INLINE void spdlog::async_logger::flush_(){ + SPDLOG_TRY{if (auto pool_ptr = thread_pool_.lock()){ + pool_ptr->post_flush(shared_from_this(), overflow_policy_); +} +else { + throw_spdlog_ex("async flush: thread pool doesn't exist anymore"); +} +} +SPDLOG_LOGGER_CATCH(source_loc()) +} + +// +// backend functions - called from the thread pool to do the actual job +// +SPDLOG_INLINE void spdlog::async_logger::backend_sink_it_(const details::log_msg &msg) { + for (auto &sink : sinks_) { + if (sink->should_log(msg.level)) { + SPDLOG_TRY { sink->log(msg); } + SPDLOG_LOGGER_CATCH(msg.source) + } + } + + if (should_flush_(msg)) { + backend_flush_(); + } +} + +SPDLOG_INLINE void spdlog::async_logger::backend_flush_() { + for (auto &sink : sinks_) { + SPDLOG_TRY { sink->flush(); } + SPDLOG_LOGGER_CATCH(source_loc()) + } +} + +SPDLOG_INLINE std::shared_ptr spdlog::async_logger::clone(std::string new_name) { + auto cloned = std::make_shared(*this); + cloned->name_ = std::move(new_name); + return cloned; +} diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/async_logger.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/async_logger.h new file mode 100644 index 0000000..846c4c6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/async_logger.h @@ -0,0 +1,74 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Fast asynchronous logger. +// Uses pre allocated queue. +// Creates a single back thread to pop messages from the queue and log them. +// +// Upon each log write the logger: +// 1. Checks if its log level is enough to log the message +// 2. Push a new copy of the message to a queue (or block the caller until +// space is available in the queue) +// Upon destruction, logs all remaining messages in the queue before +// destructing.. + +#include + +namespace spdlog { + +// Async overflow policy - block by default. +enum class async_overflow_policy { + block, // Block until message can be enqueued + overrun_oldest, // Discard oldest message in the queue if full when trying to + // add new item. + discard_new // Discard new message if the queue is full when trying to add new item. +}; + +namespace details { +class thread_pool; +} + +class SPDLOG_API async_logger final : public std::enable_shared_from_this, + public logger { + friend class details::thread_pool; + +public: + template + async_logger(std::string logger_name, + It begin, + It end, + std::weak_ptr tp, + async_overflow_policy overflow_policy = async_overflow_policy::block) + : logger(std::move(logger_name), begin, end), + thread_pool_(std::move(tp)), + overflow_policy_(overflow_policy) {} + + async_logger(std::string logger_name, + sinks_init_list sinks_list, + std::weak_ptr tp, + async_overflow_policy overflow_policy = async_overflow_policy::block); + + async_logger(std::string logger_name, + sink_ptr single_sink, + std::weak_ptr tp, + async_overflow_policy overflow_policy = async_overflow_policy::block); + + std::shared_ptr clone(std::string new_name) override; + +protected: + void sink_it_(const details::log_msg &msg) override; + void flush_() override; + void backend_sink_it_(const details::log_msg &incoming_log_msg); + void backend_flush_(); + +private: + std::weak_ptr thread_pool_; + async_overflow_policy overflow_policy_; +}; +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "async_logger-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/argv.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/argv.h new file mode 100644 index 0000000..7de2f83 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/argv.h @@ -0,0 +1,40 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once +#include +#include + +// +// Init log levels using each argv entry that starts with "SPDLOG_LEVEL=" +// +// set all loggers to debug level: +// example.exe "SPDLOG_LEVEL=debug" + +// set logger1 to trace level +// example.exe "SPDLOG_LEVEL=logger1=trace" + +// turn off all logging except for logger1 and logger2: +// example.exe "SPDLOG_LEVEL=off,logger1=debug,logger2=info" + +namespace spdlog { +namespace cfg { + +// search for SPDLOG_LEVEL= in the args and use it to init the levels +inline void load_argv_levels(int argc, const char **argv) { + const std::string spdlog_level_prefix = "SPDLOG_LEVEL="; + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + if (arg.find(spdlog_level_prefix) == 0) { + auto levels_string = arg.substr(spdlog_level_prefix.size()); + helpers::load_levels(levels_string); + } + } +} + +inline void load_argv_levels(int argc, char **argv) { + load_argv_levels(argc, const_cast(argv)); +} + +} // namespace cfg +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/env.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/env.h new file mode 100644 index 0000000..6e55414 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/env.h @@ -0,0 +1,36 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once +#include +#include +#include + +// +// Init levels and patterns from env variables SPDLOG_LEVEL +// Inspired from Rust's "env_logger" crate (https://crates.io/crates/env_logger). +// Note - fallback to "info" level on unrecognized levels +// +// Examples: +// +// set global level to debug: +// export SPDLOG_LEVEL=debug +// +// turn off all logging except for logger1: +// export SPDLOG_LEVEL="*=off,logger1=debug" +// + +// turn off all logging except for logger1 and logger2: +// export SPDLOG_LEVEL="off,logger1=debug,logger2=info" + +namespace spdlog { +namespace cfg { +inline void load_env_levels() { + auto env_val = details::os::getenv("SPDLOG_LEVEL"); + if (!env_val.empty()) { + helpers::load_levels(env_val); + } +} + +} // namespace cfg +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/helpers-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/helpers-inl.h new file mode 100644 index 0000000..93650a2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/helpers-inl.h @@ -0,0 +1,107 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include +#include + +#include +#include +#include +#include + +namespace spdlog { +namespace cfg { +namespace helpers { + +// inplace convert to lowercase +inline std::string &to_lower_(std::string &str) { + std::transform(str.begin(), str.end(), str.begin(), [](char ch) { + return static_cast((ch >= 'A' && ch <= 'Z') ? ch + ('a' - 'A') : ch); + }); + return str; +} + +// inplace trim spaces +inline std::string &trim_(std::string &str) { + const char *spaces = " \n\r\t"; + str.erase(str.find_last_not_of(spaces) + 1); + str.erase(0, str.find_first_not_of(spaces)); + return str; +} + +// return (name,value) trimmed pair from given "name=value" string. +// return empty string on missing parts +// "key=val" => ("key", "val") +// " key = val " => ("key", "val") +// "key=" => ("key", "") +// "val" => ("", "val") + +inline std::pair extract_kv_(char sep, const std::string &str) { + auto n = str.find(sep); + std::string k, v; + if (n == std::string::npos) { + v = str; + } else { + k = str.substr(0, n); + v = str.substr(n + 1); + } + return std::make_pair(trim_(k), trim_(v)); +} + +// return vector of key/value pairs from sequence of "K1=V1,K2=V2,.." +// "a=AAA,b=BBB,c=CCC,.." => {("a","AAA"),("b","BBB"),("c", "CCC"),...} +inline std::unordered_map extract_key_vals_(const std::string &str) { + std::string token; + std::istringstream token_stream(str); + std::unordered_map rv{}; + while (std::getline(token_stream, token, ',')) { + if (token.empty()) { + continue; + } + auto kv = extract_kv_('=', token); + rv[kv.first] = kv.second; + } + return rv; +} + +SPDLOG_INLINE void load_levels(const std::string &input) { + if (input.empty() || input.size() > 512) { + return; + } + + auto key_vals = extract_key_vals_(input); + std::unordered_map levels; + level::level_enum global_level = level::info; + bool global_level_found = false; + + for (auto &name_level : key_vals) { + auto &logger_name = name_level.first; + auto level_name = to_lower_(name_level.second); + auto level = level::from_str(level_name); + // ignore unrecognized level names + if (level == level::off && level_name != "off") { + continue; + } + if (logger_name.empty()) // no logger name indicate global level + { + global_level_found = true; + global_level = level; + } else { + levels[logger_name] = level; + } + } + + details::registry::instance().set_levels(std::move(levels), + global_level_found ? &global_level : nullptr); +} + +} // namespace helpers +} // namespace cfg +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/helpers.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/helpers.h new file mode 100644 index 0000000..c023818 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/helpers.h @@ -0,0 +1,29 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +namespace spdlog { +namespace cfg { +namespace helpers { +// +// Init levels from given string +// +// Examples: +// +// set global level to debug: "debug" +// turn off all logging except for logger1: "off,logger1=debug" +// turn off all logging except for logger1 and logger2: "off,logger1=debug,logger2=info" +// +SPDLOG_API void load_levels(const std::string &txt); +} // namespace helpers + +} // namespace cfg +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "helpers-inl.h" +#endif // SPDLOG_HEADER_ONLY diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/common-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/common-inl.h new file mode 100644 index 0000000..a8a0453 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/common-inl.h @@ -0,0 +1,68 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +namespace spdlog { +namespace level { + +#if __cplusplus >= 201703L +constexpr +#endif + static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES; + +static const char *short_level_names[] SPDLOG_SHORT_LEVEL_NAMES; + +SPDLOG_INLINE const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT { + return level_string_views[l]; +} + +SPDLOG_INLINE const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT { + return short_level_names[l]; +} + +SPDLOG_INLINE spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT { + auto it = std::find(std::begin(level_string_views), std::end(level_string_views), name); + if (it != std::end(level_string_views)) + return static_cast(std::distance(std::begin(level_string_views), it)); + + // check also for "warn" and "err" before giving up.. + if (name == "warn") { + return level::warn; + } + if (name == "err") { + return level::err; + } + return level::off; +} +} // namespace level + +SPDLOG_INLINE spdlog_ex::spdlog_ex(std::string msg) + : msg_(std::move(msg)) {} + +SPDLOG_INLINE spdlog_ex::spdlog_ex(const std::string &msg, int last_errno) { +#ifdef SPDLOG_USE_STD_FORMAT + msg_ = std::system_error(std::error_code(last_errno, std::generic_category()), msg).what(); +#else + memory_buf_t outbuf; + fmt::format_system_error(outbuf, last_errno, msg.c_str()); + msg_ = fmt::to_string(outbuf); +#endif +} + +SPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT { return msg_.c_str(); } + +SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno) { + SPDLOG_THROW(spdlog_ex(msg, last_errno)); +} + +SPDLOG_INLINE void throw_spdlog_ex(std::string msg) { SPDLOG_THROW(spdlog_ex(std::move(msg))); } + +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/common.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/common.h new file mode 100644 index 0000000..aca483c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/common.h @@ -0,0 +1,411 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SPDLOG_USE_STD_FORMAT + #include + #if __cpp_lib_format >= 202207L + #include + #else + #include + #endif +#endif + +#ifdef SPDLOG_COMPILED_LIB + #undef SPDLOG_HEADER_ONLY + #if defined(SPDLOG_SHARED_LIB) + #if defined(_WIN32) + #ifdef spdlog_EXPORTS + #define SPDLOG_API __declspec(dllexport) + #else // !spdlog_EXPORTS + #define SPDLOG_API __declspec(dllimport) + #endif + #else // !defined(_WIN32) + #define SPDLOG_API __attribute__((visibility("default"))) + #endif + #else // !defined(SPDLOG_SHARED_LIB) + #define SPDLOG_API + #endif + #define SPDLOG_INLINE +#else // !defined(SPDLOG_COMPILED_LIB) + #define SPDLOG_API + #define SPDLOG_HEADER_ONLY + #define SPDLOG_INLINE inline +#endif // #ifdef SPDLOG_COMPILED_LIB + +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) && \ + FMT_VERSION >= 80000 // backward compatibility with fmt versions older than 8 + #define SPDLOG_FMT_RUNTIME(format_string) fmt::runtime(format_string) + #define SPDLOG_FMT_STRING(format_string) FMT_STRING(format_string) + #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) + #include + #endif +#else + #define SPDLOG_FMT_RUNTIME(format_string) format_string + #define SPDLOG_FMT_STRING(format_string) format_string +#endif + +// visual studio up to 2013 does not support noexcept nor constexpr +#if defined(_MSC_VER) && (_MSC_VER < 1900) + #define SPDLOG_NOEXCEPT _NOEXCEPT + #define SPDLOG_CONSTEXPR +#else + #define SPDLOG_NOEXCEPT noexcept + #define SPDLOG_CONSTEXPR constexpr +#endif + +// If building with std::format, can just use constexpr, otherwise if building with fmt +// SPDLOG_CONSTEXPR_FUNC needs to be set the same as FMT_CONSTEXPR to avoid situations where +// a constexpr function in spdlog could end up calling a non-constexpr function in fmt +// depending on the compiler +// If fmt determines it can't use constexpr, we should inline the function instead +#ifdef SPDLOG_USE_STD_FORMAT + #define SPDLOG_CONSTEXPR_FUNC constexpr +#else // Being built with fmt + #if FMT_USE_CONSTEXPR + #define SPDLOG_CONSTEXPR_FUNC FMT_CONSTEXPR + #else + #define SPDLOG_CONSTEXPR_FUNC inline + #endif +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define SPDLOG_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) + #define SPDLOG_DEPRECATED __declspec(deprecated) +#else + #define SPDLOG_DEPRECATED +#endif + +// disable thread local on msvc 2013 +#ifndef SPDLOG_NO_TLS + #if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt) + #define SPDLOG_NO_TLS 1 + #endif +#endif + +#ifndef SPDLOG_FUNCTION + #define SPDLOG_FUNCTION static_cast(__FUNCTION__) +#endif + +#ifdef SPDLOG_NO_EXCEPTIONS + #define SPDLOG_TRY + #define SPDLOG_THROW(ex) \ + do { \ + printf("spdlog fatal error: %s\n", ex.what()); \ + std::abort(); \ + } while (0) + #define SPDLOG_CATCH_STD +#else + #define SPDLOG_TRY try + #define SPDLOG_THROW(ex) throw(ex) + #define SPDLOG_CATCH_STD \ + catch (const std::exception &) { \ + } +#endif + +namespace spdlog { + +class formatter; + +namespace sinks { +class sink; +} + +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) +using filename_t = std::wstring; + // allow macro expansion to occur in SPDLOG_FILENAME_T + #define SPDLOG_FILENAME_T_INNER(s) L##s + #define SPDLOG_FILENAME_T(s) SPDLOG_FILENAME_T_INNER(s) +#else +using filename_t = std::string; + #define SPDLOG_FILENAME_T(s) s +#endif + +using log_clock = std::chrono::system_clock; +using sink_ptr = std::shared_ptr; +using sinks_init_list = std::initializer_list; +using err_handler = std::function; +#ifdef SPDLOG_USE_STD_FORMAT +namespace fmt_lib = std; + +using string_view_t = std::string_view; +using memory_buf_t = std::string; + +template + #if __cpp_lib_format >= 202207L +using format_string_t = std::format_string; + #else +using format_string_t = std::string_view; + #endif + +template +struct is_convertible_to_basic_format_string + : std::integral_constant>::value> {}; + + #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +using wstring_view_t = std::wstring_view; +using wmemory_buf_t = std::wstring; + +template + #if __cpp_lib_format >= 202207L +using wformat_string_t = std::wformat_string; + #else +using wformat_string_t = std::wstring_view; + #endif + #endif + #define SPDLOG_BUF_TO_STRING(x) x +#else // use fmt lib instead of std::format +namespace fmt_lib = fmt; + +using string_view_t = fmt::basic_string_view; +using memory_buf_t = fmt::basic_memory_buffer; + +template +using format_string_t = fmt::format_string; + +template +using remove_cvref_t = typename std::remove_cv::type>::type; + +template + #if FMT_VERSION >= 90101 +using fmt_runtime_string = fmt::runtime_format_string; + #else +using fmt_runtime_string = fmt::basic_runtime; + #endif + +// clang doesn't like SFINAE disabled constructor in std::is_convertible<> so have to repeat the +// condition from basic_format_string here, in addition, fmt::basic_runtime is only +// convertible to basic_format_string but not basic_string_view +template +struct is_convertible_to_basic_format_string + : std::integral_constant>::value || + std::is_same, fmt_runtime_string>::value> { +}; + + #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +using wstring_view_t = fmt::basic_string_view; +using wmemory_buf_t = fmt::basic_memory_buffer; + +template +using wformat_string_t = fmt::wformat_string; + #endif + #define SPDLOG_BUF_TO_STRING(x) fmt::to_string(x) +#endif + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + #ifndef _WIN32 + #error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows + #endif // _WIN32 +#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT + +template +struct is_convertible_to_any_format_string + : std::integral_constant::value || + is_convertible_to_basic_format_string::value> {}; + +#if defined(SPDLOG_NO_ATOMIC_LEVELS) +using level_t = details::null_atomic_int; +#else +using level_t = std::atomic; +#endif + +#define SPDLOG_LEVEL_TRACE 0 +#define SPDLOG_LEVEL_DEBUG 1 +#define SPDLOG_LEVEL_INFO 2 +#define SPDLOG_LEVEL_WARN 3 +#define SPDLOG_LEVEL_ERROR 4 +#define SPDLOG_LEVEL_CRITICAL 5 +#define SPDLOG_LEVEL_OFF 6 + +#if !defined(SPDLOG_ACTIVE_LEVEL) + #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO +#endif + +// Log level enum +namespace level { +enum level_enum : int { + trace = SPDLOG_LEVEL_TRACE, + debug = SPDLOG_LEVEL_DEBUG, + info = SPDLOG_LEVEL_INFO, + warn = SPDLOG_LEVEL_WARN, + err = SPDLOG_LEVEL_ERROR, + critical = SPDLOG_LEVEL_CRITICAL, + off = SPDLOG_LEVEL_OFF, + n_levels +}; + +#define SPDLOG_LEVEL_NAME_TRACE spdlog::string_view_t("trace", 5) +#define SPDLOG_LEVEL_NAME_DEBUG spdlog::string_view_t("debug", 5) +#define SPDLOG_LEVEL_NAME_INFO spdlog::string_view_t("info", 4) +#define SPDLOG_LEVEL_NAME_WARNING spdlog::string_view_t("warning", 7) +#define SPDLOG_LEVEL_NAME_ERROR spdlog::string_view_t("error", 5) +#define SPDLOG_LEVEL_NAME_CRITICAL spdlog::string_view_t("critical", 8) +#define SPDLOG_LEVEL_NAME_OFF spdlog::string_view_t("off", 3) + +#if !defined(SPDLOG_LEVEL_NAMES) + #define SPDLOG_LEVEL_NAMES \ + { \ + SPDLOG_LEVEL_NAME_TRACE, SPDLOG_LEVEL_NAME_DEBUG, SPDLOG_LEVEL_NAME_INFO, \ + SPDLOG_LEVEL_NAME_WARNING, SPDLOG_LEVEL_NAME_ERROR, SPDLOG_LEVEL_NAME_CRITICAL, \ + SPDLOG_LEVEL_NAME_OFF \ + } +#endif + +#if !defined(SPDLOG_SHORT_LEVEL_NAMES) + + #define SPDLOG_SHORT_LEVEL_NAMES \ + { "T", "D", "I", "W", "E", "C", "O" } +#endif + +SPDLOG_API const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT; +SPDLOG_API const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT; +SPDLOG_API spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT; + +} // namespace level + +// +// Color mode used by sinks with color support. +// +enum class color_mode { always, automatic, never }; + +// +// Pattern time - specific time getting to use for pattern_formatter. +// local time by default +// +enum class pattern_time_type { + local, // log localtime + utc // log utc +}; + +// +// Log exception +// +class SPDLOG_API spdlog_ex : public std::exception { +public: + explicit spdlog_ex(std::string msg); + spdlog_ex(const std::string &msg, int last_errno); + const char *what() const SPDLOG_NOEXCEPT override; + +private: + std::string msg_; +}; + +[[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno); +[[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg); + +struct source_loc { + SPDLOG_CONSTEXPR source_loc() = default; + SPDLOG_CONSTEXPR source_loc(const char *filename_in, int line_in, const char *funcname_in) + : filename{filename_in}, + line{line_in}, + funcname{funcname_in} {} + + SPDLOG_CONSTEXPR bool empty() const SPDLOG_NOEXCEPT { return line <= 0; } + const char *filename{nullptr}; + int line{0}; + const char *funcname{nullptr}; +}; + +struct file_event_handlers { + file_event_handlers() + : before_open(nullptr), + after_open(nullptr), + before_close(nullptr), + after_close(nullptr) {} + + std::function before_open; + std::function after_open; + std::function before_close; + std::function after_close; +}; + +namespace details { + +// to_string_view + +SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(const memory_buf_t &buf) + SPDLOG_NOEXCEPT { + return spdlog::string_view_t{buf.data(), buf.size()}; +} + +SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(spdlog::string_view_t str) + SPDLOG_NOEXCEPT { + return str; +} + +#if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(const wmemory_buf_t &buf) + SPDLOG_NOEXCEPT { + return spdlog::wstring_view_t{buf.data(), buf.size()}; +} + +SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(spdlog::wstring_view_t str) + SPDLOG_NOEXCEPT { + return str; +} +#endif + +#ifndef SPDLOG_USE_STD_FORMAT +template +inline fmt::basic_string_view to_string_view(fmt::basic_format_string fmt) { + return fmt; +} +#elif __cpp_lib_format >= 202207L +template +SPDLOG_CONSTEXPR_FUNC std::basic_string_view to_string_view( + std::basic_format_string fmt) SPDLOG_NOEXCEPT { + return fmt.get(); +} +#endif + +// make_unique support for pre c++14 +#if __cplusplus >= 201402L // C++14 and beyond +using std::enable_if_t; +using std::make_unique; +#else +template +using enable_if_t = typename std::enable_if::type; + +template +std::unique_ptr make_unique(Args &&...args) { + static_assert(!std::is_array::value, "arrays not supported"); + return std::unique_ptr(new T(std::forward(args)...)); +} +#endif + +// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) +template ::value, int> = 0> +constexpr T conditional_static_cast(U value) { + return static_cast(value); +} + +template ::value, int> = 0> +constexpr T conditional_static_cast(U value) { + return value; +} + +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "common-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/backtracer-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/backtracer-inl.h new file mode 100644 index 0000000..43d1002 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/backtracer-inl.h @@ -0,0 +1,63 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif +namespace spdlog { +namespace details { +SPDLOG_INLINE backtracer::backtracer(const backtracer &other) { + std::lock_guard lock(other.mutex_); + enabled_ = other.enabled(); + messages_ = other.messages_; +} + +SPDLOG_INLINE backtracer::backtracer(backtracer &&other) SPDLOG_NOEXCEPT { + std::lock_guard lock(other.mutex_); + enabled_ = other.enabled(); + messages_ = std::move(other.messages_); +} + +SPDLOG_INLINE backtracer &backtracer::operator=(backtracer other) { + std::lock_guard lock(mutex_); + enabled_ = other.enabled(); + messages_ = std::move(other.messages_); + return *this; +} + +SPDLOG_INLINE void backtracer::enable(size_t size) { + std::lock_guard lock{mutex_}; + enabled_.store(true, std::memory_order_relaxed); + messages_ = circular_q{size}; +} + +SPDLOG_INLINE void backtracer::disable() { + std::lock_guard lock{mutex_}; + enabled_.store(false, std::memory_order_relaxed); +} + +SPDLOG_INLINE bool backtracer::enabled() const { return enabled_.load(std::memory_order_relaxed); } + +SPDLOG_INLINE void backtracer::push_back(const log_msg &msg) { + std::lock_guard lock{mutex_}; + messages_.push_back(log_msg_buffer{msg}); +} + +SPDLOG_INLINE bool backtracer::empty() const { + std::lock_guard lock{mutex_}; + return messages_.empty(); +} + +// pop all items in the q and apply the given fun on each of them. +SPDLOG_INLINE void backtracer::foreach_pop(std::function fun) { + std::lock_guard lock{mutex_}; + while (!messages_.empty()) { + auto &front_msg = messages_.front(); + fun(front_msg); + messages_.pop_front(); + } +} +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/backtracer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/backtracer.h new file mode 100644 index 0000000..541339c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/backtracer.h @@ -0,0 +1,45 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +#include +#include +#include + +// Store log messages in circular buffer. +// Useful for storing debug data in case of error/warning happens. + +namespace spdlog { +namespace details { +class SPDLOG_API backtracer { + mutable std::mutex mutex_; + std::atomic enabled_{false}; + circular_q messages_; + +public: + backtracer() = default; + backtracer(const backtracer &other); + + backtracer(backtracer &&other) SPDLOG_NOEXCEPT; + backtracer &operator=(backtracer other); + + void enable(size_t size); + void disable(); + bool enabled() const; + void push_back(const log_msg &msg); + bool empty() const; + + // pop all items in the q and apply the given fun on each of them. + void foreach_pop(std::function fun); +}; + +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "backtracer-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/circular_q.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/circular_q.h new file mode 100644 index 0000000..29e9d25 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/circular_q.h @@ -0,0 +1,115 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +// circular q view of std::vector. +#pragma once + +#include +#include + +#include "spdlog/common.h" + +namespace spdlog { +namespace details { +template +class circular_q { + size_t max_items_ = 0; + typename std::vector::size_type head_ = 0; + typename std::vector::size_type tail_ = 0; + size_t overrun_counter_ = 0; + std::vector v_; + +public: + using value_type = T; + + // empty ctor - create a disabled queue with no elements allocated at all + circular_q() = default; + + explicit circular_q(size_t max_items) + : max_items_(max_items + 1) // one item is reserved as marker for full q + , + v_(max_items_) {} + + circular_q(const circular_q &) = default; + circular_q &operator=(const circular_q &) = default; + + // move cannot be default, + // since we need to reset head_, tail_, etc to zero in the moved object + circular_q(circular_q &&other) SPDLOG_NOEXCEPT { copy_moveable(std::move(other)); } + + circular_q &operator=(circular_q &&other) SPDLOG_NOEXCEPT { + copy_moveable(std::move(other)); + return *this; + } + + // push back, overrun (oldest) item if no room left + void push_back(T &&item) { + if (max_items_ > 0) { + v_[tail_] = std::move(item); + tail_ = (tail_ + 1) % max_items_; + + if (tail_ == head_) // overrun last item if full + { + head_ = (head_ + 1) % max_items_; + ++overrun_counter_; + } + } + } + + // Return reference to the front item. + // If there are no elements in the container, the behavior is undefined. + const T &front() const { return v_[head_]; } + + T &front() { return v_[head_]; } + + // Return number of elements actually stored + size_t size() const { + if (tail_ >= head_) { + return tail_ - head_; + } else { + return max_items_ - (head_ - tail_); + } + } + + // Return const reference to item by index. + // If index is out of range 0…size()-1, the behavior is undefined. + const T &at(size_t i) const { + assert(i < size()); + return v_[(head_ + i) % max_items_]; + } + + // Pop item from front. + // If there are no elements in the container, the behavior is undefined. + void pop_front() { head_ = (head_ + 1) % max_items_; } + + bool empty() const { return tail_ == head_; } + + bool full() const { + // head is ahead of the tail by 1 + if (max_items_ > 0) { + return ((tail_ + 1) % max_items_) == head_; + } + return false; + } + + size_t overrun_counter() const { return overrun_counter_; } + + void reset_overrun_counter() { overrun_counter_ = 0; } + +private: + // copy from other&& and reset it to disabled state + void copy_moveable(circular_q &&other) SPDLOG_NOEXCEPT { + max_items_ = other.max_items_; + head_ = other.head_; + tail_ = other.tail_; + overrun_counter_ = other.overrun_counter_; + v_ = std::move(other.v_); + + // put &&other in disabled, but valid state + other.max_items_ = 0; + other.head_ = other.tail_ = 0; + other.overrun_counter_ = 0; + } +}; +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/console_globals.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/console_globals.h new file mode 100644 index 0000000..9c55210 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/console_globals.h @@ -0,0 +1,28 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +namespace spdlog { +namespace details { + +struct console_mutex { + using mutex_t = std::mutex; + static mutex_t &mutex() { + static mutex_t s_mutex; + return s_mutex; + } +}; + +struct console_nullmutex { + using mutex_t = null_mutex; + static mutex_t &mutex() { + static mutex_t s_mutex; + return s_mutex; + } +}; +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/file_helper-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/file_helper-inl.h new file mode 100644 index 0000000..37d1d46 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/file_helper-inl.h @@ -0,0 +1,152 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace spdlog { +namespace details { + +SPDLOG_INLINE file_helper::file_helper(const file_event_handlers &event_handlers) + : event_handlers_(event_handlers) {} + +SPDLOG_INLINE file_helper::~file_helper() { close(); } + +SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate) { + close(); + filename_ = fname; + + auto *mode = SPDLOG_FILENAME_T("ab"); + auto *trunc_mode = SPDLOG_FILENAME_T("wb"); + + if (event_handlers_.before_open) { + event_handlers_.before_open(filename_); + } + for (int tries = 0; tries < open_tries_; ++tries) { + // create containing folder if not exists already. + os::create_dir(os::dir_name(fname)); + if (truncate) { + // Truncate by opening-and-closing a tmp file in "wb" mode, always + // opening the actual log-we-write-to in "ab" mode, since that + // interacts more politely with eternal processes that might + // rotate/truncate the file underneath us. + std::FILE *tmp; + if (os::fopen_s(&tmp, fname, trunc_mode)) { + continue; + } + std::fclose(tmp); + } + if (!os::fopen_s(&fd_, fname, mode)) { + if (event_handlers_.after_open) { + event_handlers_.after_open(filename_, fd_); + } + return; + } + + details::os::sleep_for_millis(open_interval_); + } + + throw_spdlog_ex("Failed opening file " + os::filename_to_str(filename_) + " for writing", + errno); +} + +SPDLOG_INLINE void file_helper::reopen(bool truncate) { + if (filename_.empty()) { + throw_spdlog_ex("Failed re opening file - was not opened before"); + } + this->open(filename_, truncate); +} + +SPDLOG_INLINE void file_helper::flush() { + if (std::fflush(fd_) != 0) { + throw_spdlog_ex("Failed flush to file " + os::filename_to_str(filename_), errno); + } +} + +SPDLOG_INLINE void file_helper::sync() { + if (!os::fsync(fd_)) { + throw_spdlog_ex("Failed to fsync file " + os::filename_to_str(filename_), errno); + } +} + +SPDLOG_INLINE void file_helper::close() { + if (fd_ != nullptr) { + if (event_handlers_.before_close) { + event_handlers_.before_close(filename_, fd_); + } + + std::fclose(fd_); + fd_ = nullptr; + + if (event_handlers_.after_close) { + event_handlers_.after_close(filename_); + } + } +} + +SPDLOG_INLINE void file_helper::write(const memory_buf_t &buf) { + if (fd_ == nullptr) return; + size_t msg_size = buf.size(); + auto data = buf.data(); + if (std::fwrite(data, 1, msg_size, fd_) != msg_size) { + throw_spdlog_ex("Failed writing to file " + os::filename_to_str(filename_), errno); + } +} + +SPDLOG_INLINE size_t file_helper::size() const { + if (fd_ == nullptr) { + throw_spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(filename_)); + } + return os::filesize(fd_); +} + +SPDLOG_INLINE const filename_t &file_helper::filename() const { return filename_; } + +// +// return file path and its extension: +// +// "mylog.txt" => ("mylog", ".txt") +// "mylog" => ("mylog", "") +// "mylog." => ("mylog.", "") +// "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt") +// +// the starting dot in filenames is ignored (hidden files): +// +// ".mylog" => (".mylog". "") +// "my_folder/.mylog" => ("my_folder/.mylog", "") +// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") +SPDLOG_INLINE std::tuple file_helper::split_by_extension( + const filename_t &fname) { + auto ext_index = fname.rfind('.'); + + // no valid extension found - return whole path and empty string as + // extension + if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1) { + return std::make_tuple(fname, filename_t()); + } + + // treat cases like "/etc/rc.d/somelogfile or "/abc/.hiddenfile" + auto folder_index = fname.find_last_of(details::os::folder_seps_filename); + if (folder_index != filename_t::npos && folder_index >= ext_index - 1) { + return std::make_tuple(fname, filename_t()); + } + + // finally - return a valid base and extension tuple + return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index)); +} + +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/file_helper.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/file_helper.h new file mode 100644 index 0000000..f0e5d18 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/file_helper.h @@ -0,0 +1,61 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +namespace spdlog { +namespace details { + +// Helper class for file sinks. +// When failing to open a file, retry several times(5) with a delay interval(10 ms). +// Throw spdlog_ex exception on errors. + +class SPDLOG_API file_helper { +public: + file_helper() = default; + explicit file_helper(const file_event_handlers &event_handlers); + + file_helper(const file_helper &) = delete; + file_helper &operator=(const file_helper &) = delete; + ~file_helper(); + + void open(const filename_t &fname, bool truncate = false); + void reopen(bool truncate); + void flush(); + void sync(); + void close(); + void write(const memory_buf_t &buf); + size_t size() const; + const filename_t &filename() const; + + // + // return file path and its extension: + // + // "mylog.txt" => ("mylog", ".txt") + // "mylog" => ("mylog", "") + // "mylog." => ("mylog.", "") + // "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt") + // + // the starting dot in filenames is ignored (hidden files): + // + // ".mylog" => (".mylog". "") + // "my_folder/.mylog" => ("my_folder/.mylog", "") + // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") + static std::tuple split_by_extension(const filename_t &fname); + +private: + const int open_tries_ = 5; + const unsigned int open_interval_ = 10; + std::FILE *fd_{nullptr}; + filename_t filename_; + file_event_handlers event_handlers_; +}; +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "file_helper-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/fmt_helper.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/fmt_helper.h new file mode 100644 index 0000000..6130600 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/fmt_helper.h @@ -0,0 +1,141 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +#pragma once + +#include +#include +#include +#include +#include + +#ifdef SPDLOG_USE_STD_FORMAT + #include + #include +#endif + +// Some fmt helpers to efficiently format and pad ints and strings +namespace spdlog { +namespace details { +namespace fmt_helper { + +inline void append_string_view(spdlog::string_view_t view, memory_buf_t &dest) { + auto *buf_ptr = view.data(); + dest.append(buf_ptr, buf_ptr + view.size()); +} + +#ifdef SPDLOG_USE_STD_FORMAT +template +inline void append_int(T n, memory_buf_t &dest) { + // Buffer should be large enough to hold all digits (digits10 + 1) and a sign + SPDLOG_CONSTEXPR const auto BUF_SIZE = std::numeric_limits::digits10 + 2; + char buf[BUF_SIZE]; + + auto [ptr, ec] = std::to_chars(buf, buf + BUF_SIZE, n, 10); + if (ec == std::errc()) { + dest.append(buf, ptr); + } else { + throw_spdlog_ex("Failed to format int", static_cast(ec)); + } +} +#else +template +inline void append_int(T n, memory_buf_t &dest) { + fmt::format_int i(n); + dest.append(i.data(), i.data() + i.size()); +} +#endif + +template +SPDLOG_CONSTEXPR_FUNC unsigned int count_digits_fallback(T n) { + // taken from fmt: https://github.com/fmtlib/fmt/blob/8.0.1/include/fmt/format.h#L899-L912 + unsigned int count = 1; + for (;;) { + // Integer division is slow so do it for a group of four digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + if (n < 10) return count; + if (n < 100) return count + 1; + if (n < 1000) return count + 2; + if (n < 10000) return count + 3; + n /= 10000u; + count += 4; + } +} + +template +inline unsigned int count_digits(T n) { + using count_type = + typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type; +#ifdef SPDLOG_USE_STD_FORMAT + return count_digits_fallback(static_cast(n)); +#else + return static_cast(fmt:: + // fmt 7.0.0 renamed the internal namespace to detail. + // See: https://github.com/fmtlib/fmt/issues/1538 + #if FMT_VERSION < 70000 + internal + #else + detail + #endif + ::count_digits(static_cast(n))); +#endif +} + +inline void pad2(int n, memory_buf_t &dest) { + if (n >= 0 && n < 100) // 0-99 + { + dest.push_back(static_cast('0' + n / 10)); + dest.push_back(static_cast('0' + n % 10)); + } else // unlikely, but just in case, let fmt deal with it + { + fmt_lib::format_to(std::back_inserter(dest), SPDLOG_FMT_STRING("{:02}"), n); + } +} + +template +inline void pad_uint(T n, unsigned int width, memory_buf_t &dest) { + static_assert(std::is_unsigned::value, "pad_uint must get unsigned T"); + for (auto digits = count_digits(n); digits < width; digits++) { + dest.push_back('0'); + } + append_int(n, dest); +} + +template +inline void pad3(T n, memory_buf_t &dest) { + static_assert(std::is_unsigned::value, "pad3 must get unsigned T"); + if (n < 1000) { + dest.push_back(static_cast(n / 100 + '0')); + n = n % 100; + dest.push_back(static_cast((n / 10) + '0')); + dest.push_back(static_cast((n % 10) + '0')); + } else { + append_int(n, dest); + } +} + +template +inline void pad6(T n, memory_buf_t &dest) { + pad_uint(n, 6, dest); +} + +template +inline void pad9(T n, memory_buf_t &dest) { + pad_uint(n, 9, dest); +} + +// return fraction of a second of the given time_point. +// e.g. +// fraction(tp) -> will return the millis part of the second +template +inline ToDuration time_fraction(log_clock::time_point tp) { + using std::chrono::duration_cast; + using std::chrono::seconds; + auto duration = tp.time_since_epoch(); + auto secs = duration_cast(duration); + return duration_cast(duration) - duration_cast(secs); +} + +} // namespace fmt_helper +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg-inl.h new file mode 100644 index 0000000..aa3a957 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg-inl.h @@ -0,0 +1,44 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include + +namespace spdlog { +namespace details { + +SPDLOG_INLINE log_msg::log_msg(spdlog::log_clock::time_point log_time, + spdlog::source_loc loc, + string_view_t a_logger_name, + spdlog::level::level_enum lvl, + spdlog::string_view_t msg) + : logger_name(a_logger_name), + level(lvl), + time(log_time) +#ifndef SPDLOG_NO_THREAD_ID + , + thread_id(os::thread_id()) +#endif + , + source(loc), + payload(msg) { +} + +SPDLOG_INLINE log_msg::log_msg(spdlog::source_loc loc, + string_view_t a_logger_name, + spdlog::level::level_enum lvl, + spdlog::string_view_t msg) + : log_msg(os::now(), loc, a_logger_name, lvl, msg) {} + +SPDLOG_INLINE log_msg::log_msg(string_view_t a_logger_name, + spdlog::level::level_enum lvl, + spdlog::string_view_t msg) + : log_msg(os::now(), source_loc{}, a_logger_name, lvl, msg) {} + +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg.h new file mode 100644 index 0000000..87df1e8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg.h @@ -0,0 +1,40 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +namespace spdlog { +namespace details { +struct SPDLOG_API log_msg { + log_msg() = default; + log_msg(log_clock::time_point log_time, + source_loc loc, + string_view_t logger_name, + level::level_enum lvl, + string_view_t msg); + log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg); + log_msg(string_view_t logger_name, level::level_enum lvl, string_view_t msg); + log_msg(const log_msg &other) = default; + log_msg &operator=(const log_msg &other) = default; + + string_view_t logger_name; + level::level_enum level{level::off}; + log_clock::time_point time; + size_t thread_id{0}; + + // wrapping the formatted text with color (updated by pattern_formatter). + mutable size_t color_range_start{0}; + mutable size_t color_range_end{0}; + + source_loc source; + string_view_t payload; +}; +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "log_msg-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg_buffer-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg_buffer-inl.h new file mode 100644 index 0000000..2eb2428 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg_buffer-inl.h @@ -0,0 +1,54 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +namespace spdlog { +namespace details { + +SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg &orig_msg) + : log_msg{orig_msg} { + buffer.append(logger_name.begin(), logger_name.end()); + buffer.append(payload.begin(), payload.end()); + update_string_views(); +} + +SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg_buffer &other) + : log_msg{other} { + buffer.append(logger_name.begin(), logger_name.end()); + buffer.append(payload.begin(), payload.end()); + update_string_views(); +} + +SPDLOG_INLINE log_msg_buffer::log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT + : log_msg{other}, + buffer{std::move(other.buffer)} { + update_string_views(); +} + +SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(const log_msg_buffer &other) { + log_msg::operator=(other); + buffer.clear(); + buffer.append(other.buffer.data(), other.buffer.data() + other.buffer.size()); + update_string_views(); + return *this; +} + +SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT { + log_msg::operator=(other); + buffer = std::move(other.buffer); + update_string_views(); + return *this; +} + +SPDLOG_INLINE void log_msg_buffer::update_string_views() { + logger_name = string_view_t{buffer.data(), logger_name.size()}; + payload = string_view_t{buffer.data() + logger_name.size(), payload.size()}; +} + +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg_buffer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg_buffer.h new file mode 100644 index 0000000..1143b3b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg_buffer.h @@ -0,0 +1,32 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include + +namespace spdlog { +namespace details { + +// Extend log_msg with internal buffer to store its payload. +// This is needed since log_msg holds string_views that points to stack data. + +class SPDLOG_API log_msg_buffer : public log_msg { + memory_buf_t buffer; + void update_string_views(); + +public: + log_msg_buffer() = default; + explicit log_msg_buffer(const log_msg &orig_msg); + log_msg_buffer(const log_msg_buffer &other); + log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT; + log_msg_buffer &operator=(const log_msg_buffer &other); + log_msg_buffer &operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT; +}; + +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "log_msg_buffer-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/mpmc_blocking_q.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/mpmc_blocking_q.h new file mode 100644 index 0000000..5848cca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/mpmc_blocking_q.h @@ -0,0 +1,177 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// multi producer-multi consumer blocking queue. +// enqueue(..) - will block until room found to put the new message. +// enqueue_nowait(..) - will return immediately with false if no room left in +// the queue. +// dequeue_for(..) - will block until the queue is not empty or timeout have +// passed. + +#include + +#include +#include +#include + +namespace spdlog { +namespace details { + +template +class mpmc_blocking_queue { +public: + using item_type = T; + explicit mpmc_blocking_queue(size_t max_items) + : q_(max_items) {} + +#ifndef __MINGW32__ + // try to enqueue and block if no room left + void enqueue(T &&item) { + { + std::unique_lock lock(queue_mutex_); + pop_cv_.wait(lock, [this] { return !this->q_.full(); }); + q_.push_back(std::move(item)); + } + push_cv_.notify_one(); + } + + // enqueue immediately. overrun oldest message in the queue if no room left. + void enqueue_nowait(T &&item) { + { + std::unique_lock lock(queue_mutex_); + q_.push_back(std::move(item)); + } + push_cv_.notify_one(); + } + + void enqueue_if_have_room(T &&item) { + bool pushed = false; + { + std::unique_lock lock(queue_mutex_); + if (!q_.full()) { + q_.push_back(std::move(item)); + pushed = true; + } + } + + if (pushed) { + push_cv_.notify_one(); + } else { + ++discard_counter_; + } + } + + // dequeue with a timeout. + // Return true, if succeeded dequeue item, false otherwise + bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration) { + { + std::unique_lock lock(queue_mutex_); + if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); })) { + return false; + } + popped_item = std::move(q_.front()); + q_.pop_front(); + } + pop_cv_.notify_one(); + return true; + } + + // blocking dequeue without a timeout. + void dequeue(T &popped_item) { + { + std::unique_lock lock(queue_mutex_); + push_cv_.wait(lock, [this] { return !this->q_.empty(); }); + popped_item = std::move(q_.front()); + q_.pop_front(); + } + pop_cv_.notify_one(); + } + +#else + // apparently mingw deadlocks if the mutex is released before cv.notify_one(), + // so release the mutex at the very end each function. + + // try to enqueue and block if no room left + void enqueue(T &&item) { + std::unique_lock lock(queue_mutex_); + pop_cv_.wait(lock, [this] { return !this->q_.full(); }); + q_.push_back(std::move(item)); + push_cv_.notify_one(); + } + + // enqueue immediately. overrun oldest message in the queue if no room left. + void enqueue_nowait(T &&item) { + std::unique_lock lock(queue_mutex_); + q_.push_back(std::move(item)); + push_cv_.notify_one(); + } + + void enqueue_if_have_room(T &&item) { + bool pushed = false; + std::unique_lock lock(queue_mutex_); + if (!q_.full()) { + q_.push_back(std::move(item)); + pushed = true; + } + + if (pushed) { + push_cv_.notify_one(); + } else { + ++discard_counter_; + } + } + + // dequeue with a timeout. + // Return true, if succeeded dequeue item, false otherwise + bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration) { + std::unique_lock lock(queue_mutex_); + if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); })) { + return false; + } + popped_item = std::move(q_.front()); + q_.pop_front(); + pop_cv_.notify_one(); + return true; + } + + // blocking dequeue without a timeout. + void dequeue(T &popped_item) { + std::unique_lock lock(queue_mutex_); + push_cv_.wait(lock, [this] { return !this->q_.empty(); }); + popped_item = std::move(q_.front()); + q_.pop_front(); + pop_cv_.notify_one(); + } + +#endif + + size_t overrun_counter() { + std::lock_guard lock(queue_mutex_); + return q_.overrun_counter(); + } + + size_t discard_counter() { return discard_counter_.load(std::memory_order_relaxed); } + + size_t size() { + std::lock_guard lock(queue_mutex_); + return q_.size(); + } + + void reset_overrun_counter() { + std::lock_guard lock(queue_mutex_); + q_.reset_overrun_counter(); + } + + void reset_discard_counter() { discard_counter_.store(0, std::memory_order_relaxed); } + +private: + std::mutex queue_mutex_; + std::condition_variable push_cv_; + std::condition_variable pop_cv_; + spdlog::details::circular_q q_; + std::atomic discard_counter_{0}; +}; +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/null_mutex.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/null_mutex.h new file mode 100644 index 0000000..e3b3220 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/null_mutex.h @@ -0,0 +1,35 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +// null, no cost dummy "mutex" and dummy "atomic" int + +namespace spdlog { +namespace details { +struct null_mutex { + void lock() const {} + void unlock() const {} +}; + +struct null_atomic_int { + int value; + null_atomic_int() = default; + + explicit null_atomic_int(int new_value) + : value(new_value) {} + + int load(std::memory_order = std::memory_order_relaxed) const { return value; } + + void store(int new_value, std::memory_order = std::memory_order_relaxed) { value = new_value; } + + int exchange(int new_value, std::memory_order = std::memory_order_relaxed) { + std::swap(new_value, value); + return new_value; // return value before the call + } +}; + +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/os-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/os-inl.h new file mode 100644 index 0000000..e4d4771 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/os-inl.h @@ -0,0 +1,594 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #include + #include // for FlushFileBuffers + #include // for _get_osfhandle, _isatty, _fileno + #include // for _get_pid + + #ifdef __MINGW32__ + #include + #endif + + #if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES) + #include + #include + #endif + + #include // for _mkdir/_wmkdir + +#else // unix + + #include + #include + + #ifdef __linux__ + #include //Use gettid() syscall under linux to get thread id + + #elif defined(_AIX) + #include // for pthread_getthrds_np + + #elif defined(__DragonFly__) || defined(__FreeBSD__) + #include // for pthread_getthreadid_np + + #elif defined(__NetBSD__) + #include // for _lwp_self + + #elif defined(__sun) + #include // for thr_self + #endif + +#endif // unix + +#if defined __APPLE__ + #include +#endif + +#ifndef __has_feature // Clang - feature checking macros. + #define __has_feature(x) 0 // Compatibility with non-clang compilers. +#endif + +namespace spdlog { +namespace details { +namespace os { + +SPDLOG_INLINE spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT { +#if defined __linux__ && defined SPDLOG_CLOCK_COARSE + timespec ts; + ::clock_gettime(CLOCK_REALTIME_COARSE, &ts); + return std::chrono::time_point( + std::chrono::duration_cast( + std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec))); + +#else + return log_clock::now(); +#endif +} +SPDLOG_INLINE std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT { +#ifdef _WIN32 + std::tm tm; + ::localtime_s(&tm, &time_tt); +#else + std::tm tm; + ::localtime_r(&time_tt, &tm); +#endif + return tm; +} + +SPDLOG_INLINE std::tm localtime() SPDLOG_NOEXCEPT { + std::time_t now_t = ::time(nullptr); + return localtime(now_t); +} + +SPDLOG_INLINE std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT { +#ifdef _WIN32 + std::tm tm; + ::gmtime_s(&tm, &time_tt); +#else + std::tm tm; + ::gmtime_r(&time_tt, &tm); +#endif + return tm; +} + +SPDLOG_INLINE std::tm gmtime() SPDLOG_NOEXCEPT { + std::time_t now_t = ::time(nullptr); + return gmtime(now_t); +} + +// fopen_s on non windows for writing +SPDLOG_INLINE bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode) { +#ifdef _WIN32 + #ifdef SPDLOG_WCHAR_FILENAMES + *fp = ::_wfsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); + #else + *fp = ::_fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); + #endif + #if defined(SPDLOG_PREVENT_CHILD_FD) + if (*fp != nullptr) { + auto file_handle = reinterpret_cast(_get_osfhandle(::_fileno(*fp))); + if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0)) { + ::fclose(*fp); + *fp = nullptr; + } + } + #endif +#else // unix + #if defined(SPDLOG_PREVENT_CHILD_FD) + const int mode_flag = mode == SPDLOG_FILENAME_T("ab") ? O_APPEND : O_TRUNC; + const int fd = + ::open((filename.c_str()), O_CREAT | O_WRONLY | O_CLOEXEC | mode_flag, mode_t(0644)); + if (fd == -1) { + return true; + } + *fp = ::fdopen(fd, mode.c_str()); + if (*fp == nullptr) { + ::close(fd); + } + #else + *fp = ::fopen((filename.c_str()), mode.c_str()); + #endif +#endif + + return *fp == nullptr; +} + +SPDLOG_INLINE int remove(const filename_t &filename) SPDLOG_NOEXCEPT { +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) + return ::_wremove(filename.c_str()); +#else + return std::remove(filename.c_str()); +#endif +} + +SPDLOG_INLINE int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT { + return path_exists(filename) ? remove(filename) : 0; +} + +SPDLOG_INLINE int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT { +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) + return ::_wrename(filename1.c_str(), filename2.c_str()); +#else + return std::rename(filename1.c_str(), filename2.c_str()); +#endif +} + +// Return true if path exists (file or directory) +SPDLOG_INLINE bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT { +#ifdef _WIN32 + struct _stat buffer; + #ifdef SPDLOG_WCHAR_FILENAMES + return (::_wstat(filename.c_str(), &buffer) == 0); + #else + return (::_stat(filename.c_str(), &buffer) == 0); + #endif +#else // common linux/unix all have the stat system call + struct stat buffer; + return (::stat(filename.c_str(), &buffer) == 0); +#endif +} + +#ifdef _MSC_VER + // avoid warning about unreachable statement at the end of filesize() + #pragma warning(push) + #pragma warning(disable : 4702) +#endif + +// Return file size according to open FILE* object +SPDLOG_INLINE size_t filesize(FILE *f) { + if (f == nullptr) { + throw_spdlog_ex("Failed getting file size. fd is null"); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + int fd = ::_fileno(f); + #if defined(_WIN64) // 64 bits + __int64 ret = ::_filelengthi64(fd); + if (ret >= 0) { + return static_cast(ret); + } + + #else // windows 32 bits + long ret = ::_filelength(fd); + if (ret >= 0) { + return static_cast(ret); + } + #endif + +#else // unix + // OpenBSD and AIX doesn't compile with :: before the fileno(..) + #if defined(__OpenBSD__) || defined(_AIX) + int fd = fileno(f); + #else + int fd = ::fileno(f); + #endif + // 64 bits(but not in osx, linux/musl or cygwin, where fstat64 is deprecated) + #if ((defined(__linux__) && defined(__GLIBC__)) || defined(__sun) || defined(_AIX)) && \ + (defined(__LP64__) || defined(_LP64)) + struct stat64 st; + if (::fstat64(fd, &st) == 0) { + return static_cast(st.st_size); + } + #else // other unix or linux 32 bits or cygwin + struct stat st; + if (::fstat(fd, &st) == 0) { + return static_cast(st.st_size); + } + #endif +#endif + throw_spdlog_ex("Failed getting file size from fd", errno); + return 0; // will not be reached. +} + +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +// Return utc offset in minutes or throw spdlog_ex on failure +SPDLOG_INLINE int utc_minutes_offset(const std::tm &tm) { +#ifdef _WIN32 + #if _WIN32_WINNT < _WIN32_WINNT_WS08 + TIME_ZONE_INFORMATION tzinfo; + auto rv = ::GetTimeZoneInformation(&tzinfo); + #else + DYNAMIC_TIME_ZONE_INFORMATION tzinfo; + auto rv = ::GetDynamicTimeZoneInformation(&tzinfo); + #endif + if (rv == TIME_ZONE_ID_INVALID) throw_spdlog_ex("Failed getting timezone info. ", errno); + + int offset = -tzinfo.Bias; + if (tm.tm_isdst) { + offset -= tzinfo.DaylightBias; + } else { + offset -= tzinfo.StandardBias; + } + return offset; +#else + + #if defined(sun) || defined(__sun) || defined(_AIX) || \ + (defined(__NEWLIB__) && !defined(__TM_GMTOFF)) || \ + (!defined(_BSD_SOURCE) && !defined(_GNU_SOURCE)) + // 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris + struct helper { + static long int calculate_gmt_offset(const std::tm &localtm = details::os::localtime(), + const std::tm &gmtm = details::os::gmtime()) { + int local_year = localtm.tm_year + (1900 - 1); + int gmt_year = gmtm.tm_year + (1900 - 1); + + long int days = ( + // difference in day of year + localtm.tm_yday - + gmtm.tm_yday + + // + intervening leap days + + ((local_year >> 2) - (gmt_year >> 2)) - (local_year / 100 - gmt_year / 100) + + ((local_year / 100 >> 2) - (gmt_year / 100 >> 2)) + + // + difference in years * 365 */ + + static_cast(local_year - gmt_year) * 365); + + long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour); + long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min); + long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec); + + return secs; + } + }; + + auto offset_seconds = helper::calculate_gmt_offset(tm); + #else + auto offset_seconds = tm.tm_gmtoff; + #endif + + return static_cast(offset_seconds / 60); +#endif +} + +// Return current thread id as size_t +// It exists because the std::this_thread::get_id() is much slower(especially +// under VS 2013) +SPDLOG_INLINE size_t _thread_id() SPDLOG_NOEXCEPT { +#ifdef _WIN32 + return static_cast(::GetCurrentThreadId()); +#elif defined(__linux__) + #if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) + #define SYS_gettid __NR_gettid + #endif + return static_cast(::syscall(SYS_gettid)); +#elif defined(_AIX) + struct __pthrdsinfo buf; + int reg_size = 0; + pthread_t pt = pthread_self(); + int retval = pthread_getthrds_np(&pt, PTHRDSINFO_QUERY_TID, &buf, sizeof(buf), NULL, ®_size); + int tid = (!retval) ? buf.__pi_tid : 0; + return static_cast(tid); +#elif defined(__DragonFly__) || defined(__FreeBSD__) + return static_cast(::pthread_getthreadid_np()); +#elif defined(__NetBSD__) + return static_cast(::_lwp_self()); +#elif defined(__OpenBSD__) + return static_cast(::getthrid()); +#elif defined(__sun) + return static_cast(::thr_self()); +#elif __APPLE__ + uint64_t tid; + // There is no pthread_threadid_np prior to Mac OS X 10.6, and it is not supported on any PPC, + // including 10.6.8 Rosetta. __POWERPC__ is Apple-specific define encompassing ppc and ppc64. + #ifdef MAC_OS_X_VERSION_MAX_ALLOWED + { + #if (MAC_OS_X_VERSION_MAX_ALLOWED < 1060) || defined(__POWERPC__) + tid = pthread_mach_thread_np(pthread_self()); + #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + if (&pthread_threadid_np) { + pthread_threadid_np(nullptr, &tid); + } else { + tid = pthread_mach_thread_np(pthread_self()); + } + #else + pthread_threadid_np(nullptr, &tid); + #endif + } + #else + pthread_threadid_np(nullptr, &tid); + #endif + return static_cast(tid); +#else // Default to standard C++11 (other Unix) + return static_cast(std::hash()(std::this_thread::get_id())); +#endif +} + +// Return current thread id as size_t (from thread local storage) +SPDLOG_INLINE size_t thread_id() SPDLOG_NOEXCEPT { +#if defined(SPDLOG_NO_TLS) + return _thread_id(); +#else // cache thread id in tls + static thread_local const size_t tid = _thread_id(); + return tid; +#endif +} + +// This is avoid msvc issue in sleep_for that happens if the clock changes. +// See https://github.com/gabime/spdlog/issues/609 +SPDLOG_INLINE void sleep_for_millis(unsigned int milliseconds) SPDLOG_NOEXCEPT { +#if defined(_WIN32) + ::Sleep(milliseconds); +#else + std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); +#endif +} + +// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined) +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) +SPDLOG_INLINE std::string filename_to_str(const filename_t &filename) { + memory_buf_t buf; + wstr_to_utf8buf(filename, buf); + return SPDLOG_BUF_TO_STRING(buf); +} +#else +SPDLOG_INLINE std::string filename_to_str(const filename_t &filename) { return filename; } +#endif + +SPDLOG_INLINE int pid() SPDLOG_NOEXCEPT { +#ifdef _WIN32 + return conditional_static_cast(::GetCurrentProcessId()); +#else + return conditional_static_cast(::getpid()); +#endif +} + +// Determine if the terminal supports colors +// Based on: https://github.com/agauniyal/rang/ +SPDLOG_INLINE bool is_color_terminal() SPDLOG_NOEXCEPT { +#ifdef _WIN32 + return true; +#else + + static const bool result = []() { + const char *env_colorterm_p = std::getenv("COLORTERM"); + if (env_colorterm_p != nullptr) { + return true; + } + + static constexpr std::array terms = { + {"ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm", "linux", "msys", + "putty", "rxvt", "screen", "vt100", "xterm", "alacritty", "vt102"}}; + + const char *env_term_p = std::getenv("TERM"); + if (env_term_p == nullptr) { + return false; + } + + return std::any_of(terms.begin(), terms.end(), [&](const char *term) { + return std::strstr(env_term_p, term) != nullptr; + }); + }(); + + return result; +#endif +} + +// Determine if the terminal attached +// Source: https://github.com/agauniyal/rang/ +SPDLOG_INLINE bool in_terminal(FILE *file) SPDLOG_NOEXCEPT { +#ifdef _WIN32 + return ::_isatty(_fileno(file)) != 0; +#else + return ::isatty(fileno(file)) != 0; +#endif +} + +#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) +SPDLOG_INLINE void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target) { + if (wstr.size() > static_cast((std::numeric_limits::max)()) / 4 - 1) { + throw_spdlog_ex("UTF-16 string is too big to be converted to UTF-8"); + } + + int wstr_size = static_cast(wstr.size()); + if (wstr_size == 0) { + target.resize(0); + return; + } + + int result_size = static_cast(target.capacity()); + if ((wstr_size + 1) * 4 > result_size) { + result_size = + ::WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr_size, NULL, 0, NULL, NULL); + } + + if (result_size > 0) { + target.resize(result_size); + result_size = ::WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr_size, target.data(), + result_size, NULL, NULL); + + if (result_size > 0) { + target.resize(result_size); + return; + } + } + + throw_spdlog_ex( + fmt_lib::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())); +} + +SPDLOG_INLINE void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target) { + if (str.size() > static_cast((std::numeric_limits::max)()) - 1) { + throw_spdlog_ex("UTF-8 string is too big to be converted to UTF-16"); + } + + int str_size = static_cast(str.size()); + if (str_size == 0) { + target.resize(0); + return; + } + + // find the size to allocate for the result buffer + int result_size = + ::MultiByteToWideChar(CP_UTF8, 0, str.data(), str_size, NULL, 0); + + if (result_size > 0) { + target.resize(result_size); + result_size = ::MultiByteToWideChar(CP_UTF8, 0, str.data(), str_size, target.data(), + result_size); + if (result_size > 0) { + assert(result_size == target.size()); + return; + } + } + + throw_spdlog_ex( + fmt_lib::format("MultiByteToWideChar failed. Last error: {}", ::GetLastError())); +} +#endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && + // defined(_WIN32) + +// return true on success +static SPDLOG_INLINE bool mkdir_(const filename_t &path) { +#ifdef _WIN32 + #ifdef SPDLOG_WCHAR_FILENAMES + return ::_wmkdir(path.c_str()) == 0; + #else + return ::_mkdir(path.c_str()) == 0; + #endif +#else + return ::mkdir(path.c_str(), mode_t(0755)) == 0; +#endif +} + +// create the given directory - and all directories leading to it +// return true on success or if the directory already exists +SPDLOG_INLINE bool create_dir(const filename_t &path) { + if (path_exists(path)) { + return true; + } + + if (path.empty()) { + return false; + } + + size_t search_offset = 0; + do { + auto token_pos = path.find_first_of(folder_seps_filename, search_offset); + // treat the entire path as a folder if no folder separator not found + if (token_pos == filename_t::npos) { + token_pos = path.size(); + } + + auto subdir = path.substr(0, token_pos); +#ifdef _WIN32 + // if subdir is just a drive letter, add a slash e.g. "c:"=>"c:\", + // otherwise path_exists(subdir) returns false (issue #3079) + const bool is_drive = subdir.length() == 2 && subdir[1] == ':'; + if (is_drive) { + subdir += '\\'; + token_pos++; + } +#endif + + if (!subdir.empty() && !path_exists(subdir) && !mkdir_(subdir)) { + return false; // return error if failed creating dir + } + search_offset = token_pos + 1; + } while (search_offset < path.size()); + + return true; +} + +// Return directory name from given path or empty string +// "abc/file" => "abc" +// "abc/" => "abc" +// "abc" => "" +// "abc///" => "abc//" +SPDLOG_INLINE filename_t dir_name(const filename_t &path) { + auto pos = path.find_last_of(folder_seps_filename); + return pos != filename_t::npos ? path.substr(0, pos) : filename_t{}; +} + +std::string SPDLOG_INLINE getenv(const char *field) { +#if defined(_MSC_VER) + #if defined(__cplusplus_winrt) + return std::string{}; // not supported under uwp + #else + size_t len = 0; + char buf[128]; + bool ok = ::getenv_s(&len, buf, sizeof(buf), field) == 0; + return ok ? buf : std::string{}; + #endif +#else // revert to getenv + char *buf = ::getenv(field); + return buf ? buf : std::string{}; +#endif +} + +// Do fsync by FILE handlerpointer +// Return true on success +SPDLOG_INLINE bool fsync(FILE *fp) { +#ifdef _WIN32 + return FlushFileBuffers(reinterpret_cast(_get_osfhandle(_fileno(fp)))) != 0; +#else + return ::fsync(fileno(fp)) == 0; +#endif +} + +} // namespace os +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/os.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/os.h new file mode 100644 index 0000000..b1069ed --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/os.h @@ -0,0 +1,123 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include // std::time_t +#include + +namespace spdlog { +namespace details { +namespace os { + +SPDLOG_API spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT; + +SPDLOG_API std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; + +SPDLOG_API std::tm localtime() SPDLOG_NOEXCEPT; + +SPDLOG_API std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; + +SPDLOG_API std::tm gmtime() SPDLOG_NOEXCEPT; + +// eol definition +#if !defined(SPDLOG_EOL) + #ifdef _WIN32 + #define SPDLOG_EOL "\r\n" + #else + #define SPDLOG_EOL "\n" + #endif +#endif + +SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL; + +// folder separator +#if !defined(SPDLOG_FOLDER_SEPS) + #ifdef _WIN32 + #define SPDLOG_FOLDER_SEPS "\\/" + #else + #define SPDLOG_FOLDER_SEPS "/" + #endif +#endif + +SPDLOG_CONSTEXPR static const char folder_seps[] = SPDLOG_FOLDER_SEPS; +SPDLOG_CONSTEXPR static const filename_t::value_type folder_seps_filename[] = + SPDLOG_FILENAME_T(SPDLOG_FOLDER_SEPS); + +// fopen_s on non windows for writing +SPDLOG_API bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode); + +// Remove filename. return 0 on success +SPDLOG_API int remove(const filename_t &filename) SPDLOG_NOEXCEPT; + +// Remove file if exists. return 0 on success +// Note: Non atomic (might return failure to delete if concurrently deleted by other process/thread) +SPDLOG_API int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT; + +SPDLOG_API int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT; + +// Return if file exists. +SPDLOG_API bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT; + +// Return file size according to open FILE* object +SPDLOG_API size_t filesize(FILE *f); + +// Return utc offset in minutes or throw spdlog_ex on failure +SPDLOG_API int utc_minutes_offset(const std::tm &tm = details::os::localtime()); + +// Return current thread id as size_t +// It exists because the std::this_thread::get_id() is much slower(especially +// under VS 2013) +SPDLOG_API size_t _thread_id() SPDLOG_NOEXCEPT; + +// Return current thread id as size_t (from thread local storage) +SPDLOG_API size_t thread_id() SPDLOG_NOEXCEPT; + +// This is avoid msvc issue in sleep_for that happens if the clock changes. +// See https://github.com/gabime/spdlog/issues/609 +SPDLOG_API void sleep_for_millis(unsigned int milliseconds) SPDLOG_NOEXCEPT; + +SPDLOG_API std::string filename_to_str(const filename_t &filename); + +SPDLOG_API int pid() SPDLOG_NOEXCEPT; + +// Determine if the terminal supports colors +// Source: https://github.com/agauniyal/rang/ +SPDLOG_API bool is_color_terminal() SPDLOG_NOEXCEPT; + +// Determine if the terminal attached +// Source: https://github.com/agauniyal/rang/ +SPDLOG_API bool in_terminal(FILE *file) SPDLOG_NOEXCEPT; + +#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) +SPDLOG_API void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target); + +SPDLOG_API void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target); +#endif + +// Return directory name from given path or empty string +// "abc/file" => "abc" +// "abc/" => "abc" +// "abc" => "" +// "abc///" => "abc//" +SPDLOG_API filename_t dir_name(const filename_t &path); + +// Create a dir from the given path. +// Return true if succeeded or if this dir already exists. +SPDLOG_API bool create_dir(const filename_t &path); + +// non thread safe, cross platform getenv/getenv_s +// return empty string if field not found +SPDLOG_API std::string getenv(const char *field); + +// Do fsync by FILE objectpointer. +// Return true on success. +SPDLOG_API bool fsync(FILE *fp); + +} // namespace os +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "os-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/periodic_worker-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/periodic_worker-inl.h new file mode 100644 index 0000000..18f11fb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/periodic_worker-inl.h @@ -0,0 +1,26 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +namespace spdlog { +namespace details { + +// stop the worker thread and join it +SPDLOG_INLINE periodic_worker::~periodic_worker() { + if (worker_thread_.joinable()) { + { + std::lock_guard lock(mutex_); + active_ = false; + } + cv_.notify_one(); + worker_thread_.join(); + } +} + +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/periodic_worker.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/periodic_worker.h new file mode 100644 index 0000000..d647b66 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/periodic_worker.h @@ -0,0 +1,58 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// periodic worker thread - periodically executes the given callback function. +// +// RAII over the owned thread: +// creates the thread on construction. +// stops and joins the thread on destruction (if the thread is executing a callback, wait for it +// to finish first). + +#include +#include +#include +#include +#include +namespace spdlog { +namespace details { + +class SPDLOG_API periodic_worker { +public: + template + periodic_worker(const std::function &callback_fun, + std::chrono::duration interval) { + active_ = (interval > std::chrono::duration::zero()); + if (!active_) { + return; + } + + worker_thread_ = std::thread([this, callback_fun, interval]() { + for (;;) { + std::unique_lock lock(this->mutex_); + if (this->cv_.wait_for(lock, interval, [this] { return !this->active_; })) { + return; // active_ == false, so exit this thread + } + callback_fun(); + } + }); + } + std::thread &get_thread() { return worker_thread_; } + periodic_worker(const periodic_worker &) = delete; + periodic_worker &operator=(const periodic_worker &) = delete; + // stop the worker thread and join it + ~periodic_worker(); + +private: + bool active_; + std::thread worker_thread_; + std::mutex mutex_; + std::condition_variable cv_; +}; +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "periodic_worker-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/registry-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/registry-inl.h new file mode 100644 index 0000000..f447848 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/registry-inl.h @@ -0,0 +1,261 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include +#include +#include + +#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER + // support for the default stdout color logger + #ifdef _WIN32 + #include + #else + #include + #endif +#endif // SPDLOG_DISABLE_DEFAULT_LOGGER + +#include +#include +#include +#include +#include + +namespace spdlog { +namespace details { + +SPDLOG_INLINE registry::registry() + : formatter_(new pattern_formatter()) { +#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER + // create default logger (ansicolor_stdout_sink_mt or wincolor_stdout_sink_mt in windows). + #ifdef _WIN32 + auto color_sink = std::make_shared(); + #else + auto color_sink = std::make_shared(); + #endif + + const char *default_logger_name = ""; + default_logger_ = std::make_shared(default_logger_name, std::move(color_sink)); + loggers_[default_logger_name] = default_logger_; + +#endif // SPDLOG_DISABLE_DEFAULT_LOGGER +} + +SPDLOG_INLINE registry::~registry() = default; + +SPDLOG_INLINE void registry::register_logger(std::shared_ptr new_logger) { + std::lock_guard lock(logger_map_mutex_); + register_logger_(std::move(new_logger)); +} + +SPDLOG_INLINE void registry::initialize_logger(std::shared_ptr new_logger) { + std::lock_guard lock(logger_map_mutex_); + new_logger->set_formatter(formatter_->clone()); + + if (err_handler_) { + new_logger->set_error_handler(err_handler_); + } + + // set new level according to previously configured level or default level + auto it = log_levels_.find(new_logger->name()); + auto new_level = it != log_levels_.end() ? it->second : global_log_level_; + new_logger->set_level(new_level); + + new_logger->flush_on(flush_level_); + + if (backtrace_n_messages_ > 0) { + new_logger->enable_backtrace(backtrace_n_messages_); + } + + if (automatic_registration_) { + register_logger_(std::move(new_logger)); + } +} + +SPDLOG_INLINE std::shared_ptr registry::get(const std::string &logger_name) { + std::lock_guard lock(logger_map_mutex_); + auto found = loggers_.find(logger_name); + return found == loggers_.end() ? nullptr : found->second; +} + +SPDLOG_INLINE std::shared_ptr registry::default_logger() { + std::lock_guard lock(logger_map_mutex_); + return default_logger_; +} + +// Return raw ptr to the default logger. +// To be used directly by the spdlog default api (e.g. spdlog::info) +// This make the default API faster, but cannot be used concurrently with set_default_logger(). +// e.g do not call set_default_logger() from one thread while calling spdlog::info() from another. +SPDLOG_INLINE logger *registry::get_default_raw() { return default_logger_.get(); } + +// set default logger. +// default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. +SPDLOG_INLINE void registry::set_default_logger(std::shared_ptr new_default_logger) { + std::lock_guard lock(logger_map_mutex_); + if (new_default_logger != nullptr) { + loggers_[new_default_logger->name()] = new_default_logger; + } + default_logger_ = std::move(new_default_logger); +} + +SPDLOG_INLINE void registry::set_tp(std::shared_ptr tp) { + std::lock_guard lock(tp_mutex_); + tp_ = std::move(tp); +} + +SPDLOG_INLINE std::shared_ptr registry::get_tp() { + std::lock_guard lock(tp_mutex_); + return tp_; +} + +// Set global formatter. Each sink in each logger will get a clone of this object +SPDLOG_INLINE void registry::set_formatter(std::unique_ptr formatter) { + std::lock_guard lock(logger_map_mutex_); + formatter_ = std::move(formatter); + for (auto &l : loggers_) { + l.second->set_formatter(formatter_->clone()); + } +} + +SPDLOG_INLINE void registry::enable_backtrace(size_t n_messages) { + std::lock_guard lock(logger_map_mutex_); + backtrace_n_messages_ = n_messages; + + for (auto &l : loggers_) { + l.second->enable_backtrace(n_messages); + } +} + +SPDLOG_INLINE void registry::disable_backtrace() { + std::lock_guard lock(logger_map_mutex_); + backtrace_n_messages_ = 0; + for (auto &l : loggers_) { + l.second->disable_backtrace(); + } +} + +SPDLOG_INLINE void registry::set_level(level::level_enum log_level) { + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) { + l.second->set_level(log_level); + } + global_log_level_ = log_level; +} + +SPDLOG_INLINE void registry::flush_on(level::level_enum log_level) { + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) { + l.second->flush_on(log_level); + } + flush_level_ = log_level; +} + +SPDLOG_INLINE void registry::set_error_handler(err_handler handler) { + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) { + l.second->set_error_handler(handler); + } + err_handler_ = std::move(handler); +} + +SPDLOG_INLINE void registry::apply_all( + const std::function)> &fun) { + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) { + fun(l.second); + } +} + +SPDLOG_INLINE void registry::flush_all() { + std::lock_guard lock(logger_map_mutex_); + for (auto &l : loggers_) { + l.second->flush(); + } +} + +SPDLOG_INLINE void registry::drop(const std::string &logger_name) { + std::lock_guard lock(logger_map_mutex_); + auto is_default_logger = default_logger_ && default_logger_->name() == logger_name; + loggers_.erase(logger_name); + if (is_default_logger) { + default_logger_.reset(); + } +} + +SPDLOG_INLINE void registry::drop_all() { + std::lock_guard lock(logger_map_mutex_); + loggers_.clear(); + default_logger_.reset(); +} + +// clean all resources and threads started by the registry +SPDLOG_INLINE void registry::shutdown() { + { + std::lock_guard lock(flusher_mutex_); + periodic_flusher_.reset(); + } + + drop_all(); + + { + std::lock_guard lock(tp_mutex_); + tp_.reset(); + } +} + +SPDLOG_INLINE std::recursive_mutex ®istry::tp_mutex() { return tp_mutex_; } + +SPDLOG_INLINE void registry::set_automatic_registration(bool automatic_registration) { + std::lock_guard lock(logger_map_mutex_); + automatic_registration_ = automatic_registration; +} + +SPDLOG_INLINE void registry::set_levels(log_levels levels, level::level_enum *global_level) { + std::lock_guard lock(logger_map_mutex_); + log_levels_ = std::move(levels); + auto global_level_requested = global_level != nullptr; + global_log_level_ = global_level_requested ? *global_level : global_log_level_; + + for (auto &logger : loggers_) { + auto logger_entry = log_levels_.find(logger.first); + if (logger_entry != log_levels_.end()) { + logger.second->set_level(logger_entry->second); + } else if (global_level_requested) { + logger.second->set_level(*global_level); + } + } +} + +SPDLOG_INLINE registry ®istry::instance() { + static registry s_instance; + return s_instance; +} + +SPDLOG_INLINE void registry::apply_logger_env_levels(std::shared_ptr new_logger) { + std::lock_guard lock(logger_map_mutex_); + auto it = log_levels_.find(new_logger->name()); + auto new_level = it != log_levels_.end() ? it->second : global_log_level_; + new_logger->set_level(new_level); +} + +SPDLOG_INLINE void registry::throw_if_exists_(const std::string &logger_name) { + if (loggers_.find(logger_name) != loggers_.end()) { + throw_spdlog_ex("logger with name '" + logger_name + "' already exists"); + } +} + +SPDLOG_INLINE void registry::register_logger_(std::shared_ptr new_logger) { + auto logger_name = new_logger->name(); + throw_if_exists_(logger_name); + loggers_[logger_name] = std::move(new_logger); +} + +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/registry.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/registry.h new file mode 100644 index 0000000..8afcbd6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/registry.h @@ -0,0 +1,129 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Loggers registry of unique name->logger pointer +// An attempt to create a logger with an already existing name will result with spdlog_ex exception. +// If user requests a non existing logger, nullptr will be returned +// This class is thread safe + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace spdlog { +class logger; + +namespace details { +class thread_pool; + +class SPDLOG_API registry { +public: + using log_levels = std::unordered_map; + registry(const registry &) = delete; + registry &operator=(const registry &) = delete; + + void register_logger(std::shared_ptr new_logger); + void initialize_logger(std::shared_ptr new_logger); + std::shared_ptr get(const std::string &logger_name); + std::shared_ptr default_logger(); + + // Return raw ptr to the default logger. + // To be used directly by the spdlog default api (e.g. spdlog::info) + // This make the default API faster, but cannot be used concurrently with set_default_logger(). + // e.g do not call set_default_logger() from one thread while calling spdlog::info() from + // another. + logger *get_default_raw(); + + // set default logger and add it to the registry if not registered already. + // default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. + // Note: Make sure to unregister it when no longer needed or before calling again with a new + // logger. + void set_default_logger(std::shared_ptr new_default_logger); + + void set_tp(std::shared_ptr tp); + + std::shared_ptr get_tp(); + + // Set global formatter. Each sink in each logger will get a clone of this object + void set_formatter(std::unique_ptr formatter); + + void enable_backtrace(size_t n_messages); + + void disable_backtrace(); + + void set_level(level::level_enum log_level); + + void flush_on(level::level_enum log_level); + + template + void flush_every(std::chrono::duration interval) { + std::lock_guard lock(flusher_mutex_); + auto clbk = [this]() { this->flush_all(); }; + periodic_flusher_ = details::make_unique(clbk, interval); + } + + std::unique_ptr &get_flusher() { + std::lock_guard lock(flusher_mutex_); + return periodic_flusher_; + } + + void set_error_handler(err_handler handler); + + void apply_all(const std::function)> &fun); + + void flush_all(); + + void drop(const std::string &logger_name); + + void drop_all(); + + // clean all resources and threads started by the registry + void shutdown(); + + std::recursive_mutex &tp_mutex(); + + void set_automatic_registration(bool automatic_registration); + + // set levels for all existing/future loggers. global_level can be null if should not set. + void set_levels(log_levels levels, level::level_enum *global_level); + + static registry &instance(); + + void apply_logger_env_levels(std::shared_ptr new_logger); + +private: + registry(); + ~registry(); + + void throw_if_exists_(const std::string &logger_name); + void register_logger_(std::shared_ptr new_logger); + bool set_level_from_cfg_(logger *logger); + std::mutex logger_map_mutex_, flusher_mutex_; + std::recursive_mutex tp_mutex_; + std::unordered_map> loggers_; + log_levels log_levels_; + std::unique_ptr formatter_; + spdlog::level::level_enum global_log_level_ = level::info; + level::level_enum flush_level_ = level::off; + err_handler err_handler_; + std::shared_ptr tp_; + std::unique_ptr periodic_flusher_; + std::shared_ptr default_logger_; + bool automatic_registration_ = true; + size_t backtrace_n_messages_ = 0; +}; + +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "registry-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/synchronous_factory.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/synchronous_factory.h new file mode 100644 index 0000000..4bd5a51 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/synchronous_factory.h @@ -0,0 +1,22 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include "registry.h" + +namespace spdlog { + +// Default logger factory- creates synchronous loggers +class logger; + +struct synchronous_factory { + template + static std::shared_ptr create(std::string logger_name, SinkArgs &&...args) { + auto sink = std::make_shared(std::forward(args)...); + auto new_logger = std::make_shared(std::move(logger_name), std::move(sink)); + details::registry::instance().initialize_logger(new_logger); + return new_logger; + } +}; +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/tcp_client-windows.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/tcp_client-windows.h new file mode 100644 index 0000000..bf8f7b8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/tcp_client-windows.h @@ -0,0 +1,135 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#define WIN32_LEAN_AND_MEAN +// tcp client helper +#include +#include + +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "Ws2_32.lib") +#pragma comment(lib, "Mswsock.lib") +#pragma comment(lib, "AdvApi32.lib") + +namespace spdlog { +namespace details { +class tcp_client { + SOCKET socket_ = INVALID_SOCKET; + + static void init_winsock_() { + WSADATA wsaData; + auto rv = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (rv != 0) { + throw_winsock_error_("WSAStartup failed", ::WSAGetLastError()); + } + } + + static void throw_winsock_error_(const std::string &msg, int last_error) { + char buf[512]; + ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, + last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, + (sizeof(buf) / sizeof(char)), NULL); + + throw_spdlog_ex(fmt_lib::format("tcp_sink - {}: {}", msg, buf)); + } + +public: + tcp_client() { init_winsock_(); } + + ~tcp_client() { + close(); + ::WSACleanup(); + } + + bool is_connected() const { return socket_ != INVALID_SOCKET; } + + void close() { + ::closesocket(socket_); + socket_ = INVALID_SOCKET; + } + + SOCKET fd() const { return socket_; } + + // try to connect or throw on failure + void connect(const std::string &host, int port) { + if (is_connected()) { + close(); + } + struct addrinfo hints {}; + ZeroMemory(&hints, sizeof(hints)); + + hints.ai_family = AF_UNSPEC; // To work with IPv4, IPv6, and so on + hints.ai_socktype = SOCK_STREAM; // TCP + hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value + hints.ai_protocol = 0; + + auto port_str = std::to_string(port); + struct addrinfo *addrinfo_result; + auto rv = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrinfo_result); + int last_error = 0; + if (rv != 0) { + last_error = ::WSAGetLastError(); + WSACleanup(); + throw_winsock_error_("getaddrinfo failed", last_error); + } + + // Try each address until we successfully connect(2). + + for (auto *rp = addrinfo_result; rp != nullptr; rp = rp->ai_next) { + socket_ = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (socket_ == INVALID_SOCKET) { + last_error = ::WSAGetLastError(); + WSACleanup(); + continue; + } + if (::connect(socket_, rp->ai_addr, (int)rp->ai_addrlen) == 0) { + break; + } else { + last_error = ::WSAGetLastError(); + close(); + } + } + ::freeaddrinfo(addrinfo_result); + if (socket_ == INVALID_SOCKET) { + WSACleanup(); + throw_winsock_error_("connect failed", last_error); + } + + // set TCP_NODELAY + int enable_flag = 1; + ::setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&enable_flag), + sizeof(enable_flag)); + } + + // Send exactly n_bytes of the given data. + // On error close the connection and throw. + void send(const char *data, size_t n_bytes) { + size_t bytes_sent = 0; + while (bytes_sent < n_bytes) { + const int send_flags = 0; + auto write_result = + ::send(socket_, data + bytes_sent, (int)(n_bytes - bytes_sent), send_flags); + if (write_result == SOCKET_ERROR) { + int last_error = ::WSAGetLastError(); + close(); + throw_winsock_error_("send failed", last_error); + } + + if (write_result == 0) // (probably should not happen but in any case..) + { + break; + } + bytes_sent += static_cast(write_result); + } + } +}; +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/tcp_client.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/tcp_client.h new file mode 100644 index 0000000..9d3c40d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/tcp_client.h @@ -0,0 +1,127 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifdef _WIN32 + #error include tcp_client-windows.h instead +#endif + +// tcp client helper +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace spdlog { +namespace details { +class tcp_client { + int socket_ = -1; + +public: + bool is_connected() const { return socket_ != -1; } + + void close() { + if (is_connected()) { + ::close(socket_); + socket_ = -1; + } + } + + int fd() const { return socket_; } + + ~tcp_client() { close(); } + + // try to connect or throw on failure + void connect(const std::string &host, int port) { + close(); + struct addrinfo hints {}; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; // To work with IPv4, IPv6, and so on + hints.ai_socktype = SOCK_STREAM; // TCP + hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value + hints.ai_protocol = 0; + + auto port_str = std::to_string(port); + struct addrinfo *addrinfo_result; + auto rv = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrinfo_result); + if (rv != 0) { + throw_spdlog_ex(fmt_lib::format("::getaddrinfo failed: {}", gai_strerror(rv))); + } + + // Try each address until we successfully connect(2). + int last_errno = 0; + for (auto *rp = addrinfo_result; rp != nullptr; rp = rp->ai_next) { +#if defined(SOCK_CLOEXEC) + const int flags = SOCK_CLOEXEC; +#else + const int flags = 0; +#endif + socket_ = ::socket(rp->ai_family, rp->ai_socktype | flags, rp->ai_protocol); + if (socket_ == -1) { + last_errno = errno; + continue; + } + rv = ::connect(socket_, rp->ai_addr, rp->ai_addrlen); + if (rv == 0) { + break; + } + last_errno = errno; + ::close(socket_); + socket_ = -1; + } + ::freeaddrinfo(addrinfo_result); + if (socket_ == -1) { + throw_spdlog_ex("::connect failed", last_errno); + } + + // set TCP_NODELAY + int enable_flag = 1; + ::setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&enable_flag), + sizeof(enable_flag)); + + // prevent sigpipe on systems where MSG_NOSIGNAL is not available +#if defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL) + ::setsockopt(socket_, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast(&enable_flag), + sizeof(enable_flag)); +#endif + +#if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL) + #error "tcp_sink would raise SIGPIPE since neither SO_NOSIGPIPE nor MSG_NOSIGNAL are available" +#endif + } + + // Send exactly n_bytes of the given data. + // On error close the connection and throw. + void send(const char *data, size_t n_bytes) { + size_t bytes_sent = 0; + while (bytes_sent < n_bytes) { +#if defined(MSG_NOSIGNAL) + const int send_flags = MSG_NOSIGNAL; +#else + const int send_flags = 0; +#endif + auto write_result = + ::send(socket_, data + bytes_sent, n_bytes - bytes_sent, send_flags); + if (write_result < 0) { + close(); + throw_spdlog_ex("write(2) failed", errno); + } + + if (write_result == 0) // (probably should not happen but in any case..) + { + break; + } + bytes_sent += static_cast(write_result); + } + } +}; +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/thread_pool-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/thread_pool-inl.h new file mode 100644 index 0000000..17e01c0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/thread_pool-inl.h @@ -0,0 +1,127 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +namespace spdlog { +namespace details { + +SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, + size_t threads_n, + std::function on_thread_start, + std::function on_thread_stop) + : q_(q_max_items) { + if (threads_n == 0 || threads_n > 1000) { + throw_spdlog_ex( + "spdlog::thread_pool(): invalid threads_n param (valid " + "range is 1-1000)"); + } + for (size_t i = 0; i < threads_n; i++) { + threads_.emplace_back([this, on_thread_start, on_thread_stop] { + on_thread_start(); + this->thread_pool::worker_loop_(); + on_thread_stop(); + }); + } +} + +SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, + size_t threads_n, + std::function on_thread_start) + : thread_pool(q_max_items, threads_n, on_thread_start, [] {}) {} + +SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n) + : thread_pool( + q_max_items, threads_n, [] {}, [] {}) {} + +// message all threads to terminate gracefully join them +SPDLOG_INLINE thread_pool::~thread_pool() { + SPDLOG_TRY { + for (size_t i = 0; i < threads_.size(); i++) { + post_async_msg_(async_msg(async_msg_type::terminate), async_overflow_policy::block); + } + + for (auto &t : threads_) { + t.join(); + } + } + SPDLOG_CATCH_STD +} + +void SPDLOG_INLINE thread_pool::post_log(async_logger_ptr &&worker_ptr, + const details::log_msg &msg, + async_overflow_policy overflow_policy) { + async_msg async_m(std::move(worker_ptr), async_msg_type::log, msg); + post_async_msg_(std::move(async_m), overflow_policy); +} + +void SPDLOG_INLINE thread_pool::post_flush(async_logger_ptr &&worker_ptr, + async_overflow_policy overflow_policy) { + post_async_msg_(async_msg(std::move(worker_ptr), async_msg_type::flush), overflow_policy); +} + +size_t SPDLOG_INLINE thread_pool::overrun_counter() { return q_.overrun_counter(); } + +void SPDLOG_INLINE thread_pool::reset_overrun_counter() { q_.reset_overrun_counter(); } + +size_t SPDLOG_INLINE thread_pool::discard_counter() { return q_.discard_counter(); } + +void SPDLOG_INLINE thread_pool::reset_discard_counter() { q_.reset_discard_counter(); } + +size_t SPDLOG_INLINE thread_pool::queue_size() { return q_.size(); } + +void SPDLOG_INLINE thread_pool::post_async_msg_(async_msg &&new_msg, + async_overflow_policy overflow_policy) { + if (overflow_policy == async_overflow_policy::block) { + q_.enqueue(std::move(new_msg)); + } else if (overflow_policy == async_overflow_policy::overrun_oldest) { + q_.enqueue_nowait(std::move(new_msg)); + } else { + assert(overflow_policy == async_overflow_policy::discard_new); + q_.enqueue_if_have_room(std::move(new_msg)); + } +} + +void SPDLOG_INLINE thread_pool::worker_loop_() { + while (process_next_msg_()) { + } +} + +// process next message in the queue +// return true if this thread should still be active (while no terminate msg +// was received) +bool SPDLOG_INLINE thread_pool::process_next_msg_() { + async_msg incoming_async_msg; + q_.dequeue(incoming_async_msg); + + switch (incoming_async_msg.msg_type) { + case async_msg_type::log: { + incoming_async_msg.worker_ptr->backend_sink_it_(incoming_async_msg); + return true; + } + case async_msg_type::flush: { + incoming_async_msg.worker_ptr->backend_flush_(); + return true; + } + + case async_msg_type::terminate: { + return false; + } + + default: { + assert(false); + } + } + + return true; +} + +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/thread_pool.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/thread_pool.h new file mode 100644 index 0000000..f22b078 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/thread_pool.h @@ -0,0 +1,117 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace spdlog { +class async_logger; + +namespace details { + +using async_logger_ptr = std::shared_ptr; + +enum class async_msg_type { log, flush, terminate }; + +// Async msg to move to/from the queue +// Movable only. should never be copied +struct async_msg : log_msg_buffer { + async_msg_type msg_type{async_msg_type::log}; + async_logger_ptr worker_ptr; + + async_msg() = default; + ~async_msg() = default; + + // should only be moved in or out of the queue.. + async_msg(const async_msg &) = delete; + +// support for vs2013 move +#if defined(_MSC_VER) && _MSC_VER <= 1800 + async_msg(async_msg &&other) + : log_msg_buffer(std::move(other)), + msg_type(other.msg_type), + worker_ptr(std::move(other.worker_ptr)) {} + + async_msg &operator=(async_msg &&other) { + *static_cast(this) = std::move(other); + msg_type = other.msg_type; + worker_ptr = std::move(other.worker_ptr); + return *this; + } +#else // (_MSC_VER) && _MSC_VER <= 1800 + async_msg(async_msg &&) = default; + async_msg &operator=(async_msg &&) = default; +#endif + + // construct from log_msg with given type + async_msg(async_logger_ptr &&worker, async_msg_type the_type, const details::log_msg &m) + : log_msg_buffer{m}, + msg_type{the_type}, + worker_ptr{std::move(worker)} {} + + async_msg(async_logger_ptr &&worker, async_msg_type the_type) + : log_msg_buffer{}, + msg_type{the_type}, + worker_ptr{std::move(worker)} {} + + explicit async_msg(async_msg_type the_type) + : async_msg{nullptr, the_type} {} +}; + +class SPDLOG_API thread_pool { +public: + using item_type = async_msg; + using q_type = details::mpmc_blocking_queue; + + thread_pool(size_t q_max_items, + size_t threads_n, + std::function on_thread_start, + std::function on_thread_stop); + thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start); + thread_pool(size_t q_max_items, size_t threads_n); + + // message all threads to terminate gracefully and join them + ~thread_pool(); + + thread_pool(const thread_pool &) = delete; + thread_pool &operator=(thread_pool &&) = delete; + + void post_log(async_logger_ptr &&worker_ptr, + const details::log_msg &msg, + async_overflow_policy overflow_policy); + void post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy); + size_t overrun_counter(); + void reset_overrun_counter(); + size_t discard_counter(); + void reset_discard_counter(); + size_t queue_size(); + +private: + q_type q_; + + std::vector threads_; + + void post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy); + void worker_loop_(); + + // process next message in the queue + // return true if this thread should still be active (while no terminate msg + // was received) + bool process_next_msg_(); +}; + +} // namespace details +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "thread_pool-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/udp_client-windows.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/udp_client-windows.h new file mode 100644 index 0000000..8b7c223 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/udp_client-windows.h @@ -0,0 +1,98 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Helper RAII over winsock udp client socket. +// Will throw on construction if socket creation failed. + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) + #pragma comment(lib, "Ws2_32.lib") + #pragma comment(lib, "Mswsock.lib") + #pragma comment(lib, "AdvApi32.lib") +#endif + +namespace spdlog { +namespace details { +class udp_client { + static constexpr int TX_BUFFER_SIZE = 1024 * 10; + SOCKET socket_ = INVALID_SOCKET; + sockaddr_in addr_ = {}; + + static void init_winsock_() { + WSADATA wsaData; + auto rv = ::WSAStartup(MAKEWORD(2, 2), &wsaData); + if (rv != 0) { + throw_winsock_error_("WSAStartup failed", ::WSAGetLastError()); + } + } + + static void throw_winsock_error_(const std::string &msg, int last_error) { + char buf[512]; + ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, + last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, + (sizeof(buf) / sizeof(char)), NULL); + + throw_spdlog_ex(fmt_lib::format("udp_sink - {}: {}", msg, buf)); + } + + void cleanup_() { + if (socket_ != INVALID_SOCKET) { + ::closesocket(socket_); + } + socket_ = INVALID_SOCKET; + ::WSACleanup(); + } + +public: + udp_client(const std::string &host, uint16_t port) { + init_winsock_(); + + addr_.sin_family = PF_INET; + addr_.sin_port = htons(port); + addr_.sin_addr.s_addr = INADDR_ANY; + if (InetPtonA(PF_INET, host.c_str(), &addr_.sin_addr.s_addr) != 1) { + int last_error = ::WSAGetLastError(); + ::WSACleanup(); + throw_winsock_error_("error: Invalid address!", last_error); + } + + socket_ = ::socket(PF_INET, SOCK_DGRAM, 0); + if (socket_ == INVALID_SOCKET) { + int last_error = ::WSAGetLastError(); + ::WSACleanup(); + throw_winsock_error_("error: Create Socket failed", last_error); + } + + int option_value = TX_BUFFER_SIZE; + if (::setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, + reinterpret_cast(&option_value), sizeof(option_value)) < 0) { + int last_error = ::WSAGetLastError(); + cleanup_(); + throw_winsock_error_("error: setsockopt(SO_SNDBUF) Failed!", last_error); + } + } + + ~udp_client() { cleanup_(); } + + SOCKET fd() const { return socket_; } + + void send(const char *data, size_t n_bytes) { + socklen_t tolen = sizeof(struct sockaddr); + if (::sendto(socket_, data, static_cast(n_bytes), 0, (struct sockaddr *)&addr_, + tolen) == -1) { + throw_spdlog_ex("sendto(2) failed", errno); + } + } +}; +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/udp_client.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/udp_client.h new file mode 100644 index 0000000..95826f5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/udp_client.h @@ -0,0 +1,81 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Helper RAII over unix udp client socket. +// Will throw on construction if the socket creation failed. + +#ifdef _WIN32 + #error "include udp_client-windows.h instead" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace spdlog { +namespace details { + +class udp_client { + static constexpr int TX_BUFFER_SIZE = 1024 * 10; + int socket_ = -1; + struct sockaddr_in sockAddr_; + + void cleanup_() { + if (socket_ != -1) { + ::close(socket_); + socket_ = -1; + } + } + +public: + udp_client(const std::string &host, uint16_t port) { + socket_ = ::socket(PF_INET, SOCK_DGRAM, 0); + if (socket_ < 0) { + throw_spdlog_ex("error: Create Socket Failed!"); + } + + int option_value = TX_BUFFER_SIZE; + if (::setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, + reinterpret_cast(&option_value), sizeof(option_value)) < 0) { + cleanup_(); + throw_spdlog_ex("error: setsockopt(SO_SNDBUF) Failed!"); + } + + sockAddr_.sin_family = AF_INET; + sockAddr_.sin_port = htons(port); + + if (::inet_aton(host.c_str(), &sockAddr_.sin_addr) == 0) { + cleanup_(); + throw_spdlog_ex("error: Invalid address!"); + } + + ::memset(sockAddr_.sin_zero, 0x00, sizeof(sockAddr_.sin_zero)); + } + + ~udp_client() { cleanup_(); } + + int fd() const { return socket_; } + + // Send exactly n_bytes of the given data. + // On error close the connection and throw. + void send(const char *data, size_t n_bytes) { + ssize_t toslen = 0; + socklen_t tolen = sizeof(struct sockaddr); + if ((toslen = ::sendto(socket_, data, n_bytes, 0, (struct sockaddr *)&sockAddr_, tolen)) == + -1) { + throw_spdlog_ex("sendto(2) failed", errno); + } + } +}; +} // namespace details +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/windows_include.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/windows_include.h new file mode 100644 index 0000000..bbab59b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/windows_include.h @@ -0,0 +1,11 @@ +#pragma once + +#ifndef NOMINMAX + #define NOMINMAX // prevent windows redefining min/max +#endif + +#ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN +#endif + +#include diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bin_to_hex.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bin_to_hex.h new file mode 100644 index 0000000..c2998d5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bin_to_hex.h @@ -0,0 +1,224 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#include +#include + +#if defined(__has_include) + #if __has_include() + #include + #endif +#endif + +#if __cpp_lib_span >= 202002L + #include +#endif + +// +// Support for logging binary data as hex +// format flags, any combination of the following: +// {:X} - print in uppercase. +// {:s} - don't separate each byte with space. +// {:p} - don't print the position on each line start. +// {:n} - don't split the output to lines. +// {:a} - show ASCII if :n is not set + +// +// Examples: +// +// std::vector v(200, 0x0b); +// logger->info("Some buffer {}", spdlog::to_hex(v)); +// char buf[128]; +// logger->info("Some buffer {:X}", spdlog::to_hex(std::begin(buf), std::end(buf))); +// logger->info("Some buffer {:X}", spdlog::to_hex(std::begin(buf), std::end(buf), 16)); + +namespace spdlog { +namespace details { + +template +class dump_info { +public: + dump_info(It range_begin, It range_end, size_t size_per_line) + : begin_(range_begin), + end_(range_end), + size_per_line_(size_per_line) {} + + // do not use begin() and end() to avoid collision with fmt/ranges + It get_begin() const { return begin_; } + It get_end() const { return end_; } + size_t size_per_line() const { return size_per_line_; } + +private: + It begin_, end_; + size_t size_per_line_; +}; +} // namespace details + +// create a dump_info that wraps the given container +template +inline details::dump_info to_hex(const Container &container, + size_t size_per_line = 32) { + static_assert(sizeof(typename Container::value_type) == 1, + "sizeof(Container::value_type) != 1"); + using Iter = typename Container::const_iterator; + return details::dump_info(std::begin(container), std::end(container), size_per_line); +} + +#if __cpp_lib_span >= 202002L + +template +inline details::dump_info::iterator> to_hex( + const std::span &container, size_t size_per_line = 32) { + using Container = std::span; + static_assert(sizeof(typename Container::value_type) == 1, + "sizeof(Container::value_type) != 1"); + using Iter = typename Container::iterator; + return details::dump_info(std::begin(container), std::end(container), size_per_line); +} + +#endif + +// create dump_info from ranges +template +inline details::dump_info to_hex(const It range_begin, + const It range_end, + size_t size_per_line = 32) { + return details::dump_info(range_begin, range_end, size_per_line); +} + +} // namespace spdlog + +namespace +#ifdef SPDLOG_USE_STD_FORMAT + std +#else + fmt +#endif +{ + +template +struct formatter, char> { + const char delimiter = ' '; + bool put_newlines = true; + bool put_delimiters = true; + bool use_uppercase = false; + bool put_positions = true; // position on start of each line + bool show_ascii = false; + + // parse the format string flags + template + SPDLOG_CONSTEXPR_FUNC auto parse(ParseContext &ctx) -> decltype(ctx.begin()) { + auto it = ctx.begin(); + while (it != ctx.end() && *it != '}') { + switch (*it) { + case 'X': + use_uppercase = true; + break; + case 's': + put_delimiters = false; + break; + case 'p': + put_positions = false; + break; + case 'n': + put_newlines = false; + show_ascii = false; + break; + case 'a': + if (put_newlines) { + show_ascii = true; + } + break; + } + + ++it; + } + return it; + } + + // format the given bytes range as hex + template + auto format(const spdlog::details::dump_info &the_range, FormatContext &ctx) const + -> decltype(ctx.out()) { + SPDLOG_CONSTEXPR const char *hex_upper = "0123456789ABCDEF"; + SPDLOG_CONSTEXPR const char *hex_lower = "0123456789abcdef"; + const char *hex_chars = use_uppercase ? hex_upper : hex_lower; + +#if !defined(SPDLOG_USE_STD_FORMAT) && FMT_VERSION < 60000 + auto inserter = ctx.begin(); +#else + auto inserter = ctx.out(); +#endif + + int size_per_line = static_cast(the_range.size_per_line()); + auto start_of_line = the_range.get_begin(); + for (auto i = the_range.get_begin(); i != the_range.get_end(); i++) { + auto ch = static_cast(*i); + + if (put_newlines && + (i == the_range.get_begin() || i - start_of_line >= size_per_line)) { + if (show_ascii && i != the_range.get_begin()) { + *inserter++ = delimiter; + *inserter++ = delimiter; + for (auto j = start_of_line; j < i; j++) { + auto pc = static_cast(*j); + *inserter++ = std::isprint(pc) ? static_cast(*j) : '.'; + } + } + + put_newline(inserter, static_cast(i - the_range.get_begin())); + + // put first byte without delimiter in front of it + *inserter++ = hex_chars[(ch >> 4) & 0x0f]; + *inserter++ = hex_chars[ch & 0x0f]; + start_of_line = i; + continue; + } + + if (put_delimiters && i != the_range.get_begin()) { + *inserter++ = delimiter; + } + + *inserter++ = hex_chars[(ch >> 4) & 0x0f]; + *inserter++ = hex_chars[ch & 0x0f]; + } + if (show_ascii) // add ascii to last line + { + if (the_range.get_end() - the_range.get_begin() > size_per_line) { + auto blank_num = size_per_line - (the_range.get_end() - start_of_line); + while (blank_num-- > 0) { + *inserter++ = delimiter; + *inserter++ = delimiter; + if (put_delimiters) { + *inserter++ = delimiter; + } + } + } + *inserter++ = delimiter; + *inserter++ = delimiter; + for (auto j = start_of_line; j != the_range.get_end(); j++) { + auto pc = static_cast(*j); + *inserter++ = std::isprint(pc) ? static_cast(*j) : '.'; + } + } + return inserter; + } + + // put newline(and position header) + template + void put_newline(It inserter, std::size_t pos) const { +#ifdef _WIN32 + *inserter++ = '\r'; +#endif + *inserter++ = '\n'; + + if (put_positions) { + spdlog::fmt_lib::format_to(inserter, SPDLOG_FMT_STRING("{:04X}: "), pos); + } + } +}; +} // namespace std diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/chrono.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/chrono.h new file mode 100644 index 0000000..a72a5bd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/chrono.h @@ -0,0 +1,23 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's chrono support +// +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) + #if !defined(SPDLOG_FMT_EXTERNAL) + #ifdef SPDLOG_HEADER_ONLY + #ifndef FMT_HEADER_ONLY + #define FMT_HEADER_ONLY + #endif + #endif + #include + #else + #include + #endif +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/compile.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/compile.h new file mode 100644 index 0000000..3c9c25d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/compile.h @@ -0,0 +1,23 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's compile-time support +// +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) + #if !defined(SPDLOG_FMT_EXTERNAL) + #ifdef SPDLOG_HEADER_ONLY + #ifndef FMT_HEADER_ONLY + #define FMT_HEADER_ONLY + #endif + #endif + #include + #else + #include + #endif +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/fmt.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/fmt.h new file mode 100644 index 0000000..7fa6b09 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/fmt.h @@ -0,0 +1,30 @@ +// +// Copyright(c) 2016-2018 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +// +// Include a bundled header-only copy of fmtlib or an external one. +// By default spdlog include its own copy. +// +#include + +#if defined(SPDLOG_USE_STD_FORMAT) // SPDLOG_USE_STD_FORMAT is defined - use std::format + #include +#elif !defined(SPDLOG_FMT_EXTERNAL) + #if !defined(SPDLOG_COMPILED_LIB) && !defined(FMT_HEADER_ONLY) + #define FMT_HEADER_ONLY + #endif + #ifndef FMT_USE_WINDOWS_H + #define FMT_USE_WINDOWS_H 0 + #endif + + #include + #include + +#else // SPDLOG_FMT_EXTERNAL is defined - use external fmtlib + #include + #include +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/ostr.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/ostr.h new file mode 100644 index 0000000..2b90105 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/ostr.h @@ -0,0 +1,23 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's ostream support +// +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) + #if !defined(SPDLOG_FMT_EXTERNAL) + #ifdef SPDLOG_HEADER_ONLY + #ifndef FMT_HEADER_ONLY + #define FMT_HEADER_ONLY + #endif + #endif + #include + #else + #include + #endif +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/ranges.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/ranges.h new file mode 100644 index 0000000..5bb91e9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/ranges.h @@ -0,0 +1,23 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's ranges support +// +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) + #if !defined(SPDLOG_FMT_EXTERNAL) + #ifdef SPDLOG_HEADER_ONLY + #ifndef FMT_HEADER_ONLY + #define FMT_HEADER_ONLY + #endif + #endif + #include + #else + #include + #endif +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/std.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/std.h new file mode 100644 index 0000000..dabe6f6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/std.h @@ -0,0 +1,24 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's std support (for formatting e.g. +// std::filesystem::path, std::thread::id, std::monostate, std::variant, ...) +// +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) + #if !defined(SPDLOG_FMT_EXTERNAL) + #ifdef SPDLOG_HEADER_ONLY + #ifndef FMT_HEADER_ONLY + #define FMT_HEADER_ONLY + #endif + #endif + #include + #else + #include + #endif +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/xchar.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/xchar.h new file mode 100644 index 0000000..2525f05 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/xchar.h @@ -0,0 +1,23 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's xchar support +// +#include + +#if !defined(SPDLOG_USE_STD_FORMAT) + #if !defined(SPDLOG_FMT_EXTERNAL) + #ifdef SPDLOG_HEADER_ONLY + #ifndef FMT_HEADER_ONLY + #define FMT_HEADER_ONLY + #endif + #endif + #include + #else + #include + #endif +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/formatter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/formatter.h new file mode 100644 index 0000000..4d482f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/formatter.h @@ -0,0 +1,17 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +namespace spdlog { + +class formatter { +public: + virtual ~formatter() = default; + virtual void format(const details::log_msg &msg, memory_buf_t &dest) = 0; + virtual std::unique_ptr clone() const = 0; +}; +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fwd.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fwd.h new file mode 100644 index 0000000..647b16b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fwd.h @@ -0,0 +1,18 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +namespace spdlog { +class logger; +class formatter; + +namespace sinks { +class sink; +} + +namespace level { +enum level_enum : int; +} + +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/logger-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/logger-inl.h new file mode 100644 index 0000000..5218fe4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/logger-inl.h @@ -0,0 +1,198 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include +#include + +#include + +namespace spdlog { + +// public methods +SPDLOG_INLINE logger::logger(const logger &other) + : name_(other.name_), + sinks_(other.sinks_), + level_(other.level_.load(std::memory_order_relaxed)), + flush_level_(other.flush_level_.load(std::memory_order_relaxed)), + custom_err_handler_(other.custom_err_handler_), + tracer_(other.tracer_) {} + +SPDLOG_INLINE logger::logger(logger &&other) SPDLOG_NOEXCEPT + : name_(std::move(other.name_)), + sinks_(std::move(other.sinks_)), + level_(other.level_.load(std::memory_order_relaxed)), + flush_level_(other.flush_level_.load(std::memory_order_relaxed)), + custom_err_handler_(std::move(other.custom_err_handler_)), + tracer_(std::move(other.tracer_)) + +{} + +SPDLOG_INLINE logger &logger::operator=(logger other) SPDLOG_NOEXCEPT { + this->swap(other); + return *this; +} + +SPDLOG_INLINE void logger::swap(spdlog::logger &other) SPDLOG_NOEXCEPT { + name_.swap(other.name_); + sinks_.swap(other.sinks_); + + // swap level_ + auto other_level = other.level_.load(); + auto my_level = level_.exchange(other_level); + other.level_.store(my_level); + + // swap flush level_ + other_level = other.flush_level_.load(); + my_level = flush_level_.exchange(other_level); + other.flush_level_.store(my_level); + + custom_err_handler_.swap(other.custom_err_handler_); + std::swap(tracer_, other.tracer_); +} + +SPDLOG_INLINE void swap(logger &a, logger &b) { a.swap(b); } + +SPDLOG_INLINE void logger::set_level(level::level_enum log_level) { level_.store(log_level); } + +SPDLOG_INLINE level::level_enum logger::level() const { + return static_cast(level_.load(std::memory_order_relaxed)); +} + +SPDLOG_INLINE const std::string &logger::name() const { return name_; } + +// set formatting for the sinks in this logger. +// each sink will get a separate instance of the formatter object. +SPDLOG_INLINE void logger::set_formatter(std::unique_ptr f) { + for (auto it = sinks_.begin(); it != sinks_.end(); ++it) { + if (std::next(it) == sinks_.end()) { + // last element - we can be move it. + (*it)->set_formatter(std::move(f)); + break; // to prevent clang-tidy warning + } else { + (*it)->set_formatter(f->clone()); + } + } +} + +SPDLOG_INLINE void logger::set_pattern(std::string pattern, pattern_time_type time_type) { + auto new_formatter = details::make_unique(std::move(pattern), time_type); + set_formatter(std::move(new_formatter)); +} + +// create new backtrace sink and move to it all our child sinks +SPDLOG_INLINE void logger::enable_backtrace(size_t n_messages) { tracer_.enable(n_messages); } + +// restore orig sinks and level and delete the backtrace sink +SPDLOG_INLINE void logger::disable_backtrace() { tracer_.disable(); } + +SPDLOG_INLINE void logger::dump_backtrace() { dump_backtrace_(); } + +// flush functions +SPDLOG_INLINE void logger::flush() { flush_(); } + +SPDLOG_INLINE void logger::flush_on(level::level_enum log_level) { flush_level_.store(log_level); } + +SPDLOG_INLINE level::level_enum logger::flush_level() const { + return static_cast(flush_level_.load(std::memory_order_relaxed)); +} + +// sinks +SPDLOG_INLINE const std::vector &logger::sinks() const { return sinks_; } + +SPDLOG_INLINE std::vector &logger::sinks() { return sinks_; } + +// error handler +SPDLOG_INLINE void logger::set_error_handler(err_handler handler) { + custom_err_handler_ = std::move(handler); +} + +// create new logger with same sinks and configuration. +SPDLOG_INLINE std::shared_ptr logger::clone(std::string logger_name) { + auto cloned = std::make_shared(*this); + cloned->name_ = std::move(logger_name); + return cloned; +} + +// protected methods +SPDLOG_INLINE void logger::log_it_(const spdlog::details::log_msg &log_msg, + bool log_enabled, + bool traceback_enabled) { + if (log_enabled) { + sink_it_(log_msg); + } + if (traceback_enabled) { + tracer_.push_back(log_msg); + } +} + +SPDLOG_INLINE void logger::sink_it_(const details::log_msg &msg) { + for (auto &sink : sinks_) { + if (sink->should_log(msg.level)) { + SPDLOG_TRY { sink->log(msg); } + SPDLOG_LOGGER_CATCH(msg.source) + } + } + + if (should_flush_(msg)) { + flush_(); + } +} + +SPDLOG_INLINE void logger::flush_() { + for (auto &sink : sinks_) { + SPDLOG_TRY { sink->flush(); } + SPDLOG_LOGGER_CATCH(source_loc()) + } +} + +SPDLOG_INLINE void logger::dump_backtrace_() { + using details::log_msg; + if (tracer_.enabled() && !tracer_.empty()) { + sink_it_( + log_msg{name(), level::info, "****************** Backtrace Start ******************"}); + tracer_.foreach_pop([this](const log_msg &msg) { this->sink_it_(msg); }); + sink_it_( + log_msg{name(), level::info, "****************** Backtrace End ********************"}); + } +} + +SPDLOG_INLINE bool logger::should_flush_(const details::log_msg &msg) { + auto flush_level = flush_level_.load(std::memory_order_relaxed); + return (msg.level >= flush_level) && (msg.level != level::off); +} + +SPDLOG_INLINE void logger::err_handler_(const std::string &msg) { + if (custom_err_handler_) { + custom_err_handler_(msg); + } else { + using std::chrono::system_clock; + static std::mutex mutex; + static std::chrono::system_clock::time_point last_report_time; + static size_t err_counter = 0; + std::lock_guard lk{mutex}; + auto now = system_clock::now(); + err_counter++; + if (now - last_report_time < std::chrono::seconds(1)) { + return; + } + last_report_time = now; + auto tm_time = details::os::localtime(system_clock::to_time_t(now)); + char date_buf[64]; + std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); +#if defined(USING_R) && defined(R_R_H) // if in R environment + REprintf("[*** LOG ERROR #%04zu ***] [%s] [%s] %s\n", err_counter, date_buf, name().c_str(), + msg.c_str()); +#else + std::fprintf(stderr, "[*** LOG ERROR #%04zu ***] [%s] [%s] %s\n", err_counter, date_buf, + name().c_str(), msg.c_str()); +#endif + } +} +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/logger.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/logger.h new file mode 100644 index 0000000..f49bdc0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/logger.h @@ -0,0 +1,379 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Thread safe logger (except for set_error_handler()) +// Has name, log level, vector of std::shared sink pointers and formatter +// Upon each log write the logger: +// 1. Checks if its log level is enough to log the message and if yes: +// 2. Call the underlying sinks to do the job. +// 3. Each sink use its own private copy of a formatter to format the message +// and send to its destination. +// +// The use of private formatter per sink provides the opportunity to cache some +// formatted data, and support for different format per sink. + +#include +#include +#include + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + #ifndef _WIN32 + #error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows + #endif + #include +#endif + +#include + +#ifndef SPDLOG_NO_EXCEPTIONS + #define SPDLOG_LOGGER_CATCH(location) \ + catch (const std::exception &ex) { \ + if (location.filename) { \ + err_handler_(fmt_lib::format(SPDLOG_FMT_STRING("{} [{}({})]"), ex.what(), \ + location.filename, location.line)); \ + } else { \ + err_handler_(ex.what()); \ + } \ + } \ + catch (...) { \ + err_handler_("Rethrowing unknown exception in logger"); \ + throw; \ + } +#else + #define SPDLOG_LOGGER_CATCH(location) +#endif + +namespace spdlog { + +class SPDLOG_API logger { +public: + // Empty logger + explicit logger(std::string name) + : name_(std::move(name)), + sinks_() {} + + // Logger with range on sinks + template + logger(std::string name, It begin, It end) + : name_(std::move(name)), + sinks_(begin, end) {} + + // Logger with single sink + logger(std::string name, sink_ptr single_sink) + : logger(std::move(name), {std::move(single_sink)}) {} + + // Logger with sinks init list + logger(std::string name, sinks_init_list sinks) + : logger(std::move(name), sinks.begin(), sinks.end()) {} + + virtual ~logger() = default; + + logger(const logger &other); + logger(logger &&other) SPDLOG_NOEXCEPT; + logger &operator=(logger other) SPDLOG_NOEXCEPT; + void swap(spdlog::logger &other) SPDLOG_NOEXCEPT; + + template + void log(source_loc loc, level::level_enum lvl, format_string_t fmt, Args &&...args) { + log_(loc, lvl, details::to_string_view(fmt), std::forward(args)...); + } + + template + void log(level::level_enum lvl, format_string_t fmt, Args &&...args) { + log(source_loc{}, lvl, fmt, std::forward(args)...); + } + + template + void log(level::level_enum lvl, const T &msg) { + log(source_loc{}, lvl, msg); + } + + // T cannot be statically converted to format string (including string_view/wstring_view) + template ::value, + int>::type = 0> + void log(source_loc loc, level::level_enum lvl, const T &msg) { + log(loc, lvl, "{}", msg); + } + + void log(log_clock::time_point log_time, + source_loc loc, + level::level_enum lvl, + string_view_t msg) { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) { + return; + } + + details::log_msg log_msg(log_time, loc, name_, lvl, msg); + log_it_(log_msg, log_enabled, traceback_enabled); + } + + void log(source_loc loc, level::level_enum lvl, string_view_t msg) { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) { + return; + } + + details::log_msg log_msg(loc, name_, lvl, msg); + log_it_(log_msg, log_enabled, traceback_enabled); + } + + void log(level::level_enum lvl, string_view_t msg) { log(source_loc{}, lvl, msg); } + + template + void trace(format_string_t fmt, Args &&...args) { + log(level::trace, fmt, std::forward(args)...); + } + + template + void debug(format_string_t fmt, Args &&...args) { + log(level::debug, fmt, std::forward(args)...); + } + + template + void info(format_string_t fmt, Args &&...args) { + log(level::info, fmt, std::forward(args)...); + } + + template + void warn(format_string_t fmt, Args &&...args) { + log(level::warn, fmt, std::forward(args)...); + } + + template + void error(format_string_t fmt, Args &&...args) { + log(level::err, fmt, std::forward(args)...); + } + + template + void critical(format_string_t fmt, Args &&...args) { + log(level::critical, fmt, std::forward(args)...); + } + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + template + void log(source_loc loc, level::level_enum lvl, wformat_string_t fmt, Args &&...args) { + log_(loc, lvl, details::to_string_view(fmt), std::forward(args)...); + } + + template + void log(level::level_enum lvl, wformat_string_t fmt, Args &&...args) { + log(source_loc{}, lvl, fmt, std::forward(args)...); + } + + void log(log_clock::time_point log_time, + source_loc loc, + level::level_enum lvl, + wstring_view_t msg) { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) { + return; + } + + memory_buf_t buf; + details::os::wstr_to_utf8buf(wstring_view_t(msg.data(), msg.size()), buf); + details::log_msg log_msg(log_time, loc, name_, lvl, string_view_t(buf.data(), buf.size())); + log_it_(log_msg, log_enabled, traceback_enabled); + } + + void log(source_loc loc, level::level_enum lvl, wstring_view_t msg) { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) { + return; + } + + memory_buf_t buf; + details::os::wstr_to_utf8buf(wstring_view_t(msg.data(), msg.size()), buf); + details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); + log_it_(log_msg, log_enabled, traceback_enabled); + } + + void log(level::level_enum lvl, wstring_view_t msg) { log(source_loc{}, lvl, msg); } + + template + void trace(wformat_string_t fmt, Args &&...args) { + log(level::trace, fmt, std::forward(args)...); + } + + template + void debug(wformat_string_t fmt, Args &&...args) { + log(level::debug, fmt, std::forward(args)...); + } + + template + void info(wformat_string_t fmt, Args &&...args) { + log(level::info, fmt, std::forward(args)...); + } + + template + void warn(wformat_string_t fmt, Args &&...args) { + log(level::warn, fmt, std::forward(args)...); + } + + template + void error(wformat_string_t fmt, Args &&...args) { + log(level::err, fmt, std::forward(args)...); + } + + template + void critical(wformat_string_t fmt, Args &&...args) { + log(level::critical, fmt, std::forward(args)...); + } +#endif + + template + void trace(const T &msg) { + log(level::trace, msg); + } + + template + void debug(const T &msg) { + log(level::debug, msg); + } + + template + void info(const T &msg) { + log(level::info, msg); + } + + template + void warn(const T &msg) { + log(level::warn, msg); + } + + template + void error(const T &msg) { + log(level::err, msg); + } + + template + void critical(const T &msg) { + log(level::critical, msg); + } + + // return true logging is enabled for the given level. + bool should_log(level::level_enum msg_level) const { + return msg_level >= level_.load(std::memory_order_relaxed); + } + + // return true if backtrace logging is enabled. + bool should_backtrace() const { return tracer_.enabled(); } + + void set_level(level::level_enum log_level); + + level::level_enum level() const; + + const std::string &name() const; + + // set formatting for the sinks in this logger. + // each sink will get a separate instance of the formatter object. + void set_formatter(std::unique_ptr f); + + // set formatting for the sinks in this logger. + // equivalent to + // set_formatter(make_unique(pattern, time_type)) + // Note: each sink will get a new instance of a formatter object, replacing the old one. + void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local); + + // backtrace support. + // efficiently store all debug/trace messages in a circular buffer until needed for debugging. + void enable_backtrace(size_t n_messages); + void disable_backtrace(); + void dump_backtrace(); + + // flush functions + void flush(); + void flush_on(level::level_enum log_level); + level::level_enum flush_level() const; + + // sinks + const std::vector &sinks() const; + + std::vector &sinks(); + + // error handler + void set_error_handler(err_handler); + + // create new logger with same sinks and configuration. + virtual std::shared_ptr clone(std::string logger_name); + +protected: + std::string name_; + std::vector sinks_; + spdlog::level_t level_{level::info}; + spdlog::level_t flush_level_{level::off}; + err_handler custom_err_handler_{nullptr}; + details::backtracer tracer_; + + // common implementation for after templated public api has been resolved + template + void log_(source_loc loc, level::level_enum lvl, string_view_t fmt, Args &&...args) { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) { + return; + } + SPDLOG_TRY { + memory_buf_t buf; +#ifdef SPDLOG_USE_STD_FORMAT + fmt_lib::vformat_to(std::back_inserter(buf), fmt, fmt_lib::make_format_args(args...)); +#else + fmt::vformat_to(fmt::appender(buf), fmt, fmt::make_format_args(args...)); +#endif + + details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); + log_it_(log_msg, log_enabled, traceback_enabled); + } + SPDLOG_LOGGER_CATCH(loc) + } + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + template + void log_(source_loc loc, level::level_enum lvl, wstring_view_t fmt, Args &&...args) { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) { + return; + } + SPDLOG_TRY { + // format to wmemory_buffer and convert to utf8 + wmemory_buf_t wbuf; + fmt_lib::vformat_to(std::back_inserter(wbuf), fmt, + fmt_lib::make_format_args(args...)); + + memory_buf_t buf; + details::os::wstr_to_utf8buf(wstring_view_t(wbuf.data(), wbuf.size()), buf); + details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); + log_it_(log_msg, log_enabled, traceback_enabled); + } + SPDLOG_LOGGER_CATCH(loc) + } +#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT + + // log the given message (if the given log level is high enough), + // and save backtrace (if backtrace is enabled). + void log_it_(const details::log_msg &log_msg, bool log_enabled, bool traceback_enabled); + virtual void sink_it_(const details::log_msg &msg); + virtual void flush_(); + void dump_backtrace_(); + bool should_flush_(const details::log_msg &msg); + + // handle errors during logging. + // default handler prints the error to stderr at max rate of 1 message/sec. + void err_handler_(const std::string &msg); +}; + +void swap(logger &a, logger &b); + +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "logger-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/mdc.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/mdc.h new file mode 100644 index 0000000..80b6f25 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/mdc.h @@ -0,0 +1,50 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#if defined(SPDLOG_NO_TLS) + #error "This header requires thread local storage support, but SPDLOG_NO_TLS is defined." +#endif + +#include +#include + +#include + +// MDC is a simple map of key->string values stored in thread local storage whose content will be printed by the loggers. +// Note: Not supported in async mode (thread local storage - so the async thread pool have different copy). +// +// Usage example: +// spdlog::mdc::put("mdc_key_1", "mdc_value_1"); +// spdlog::info("Hello, {}", "World!"); // => [2024-04-26 02:08:05.040] [info] [mdc_key_1:mdc_value_1] Hello, World! + +namespace spdlog { +class SPDLOG_API mdc { +public: + using mdc_map_t = std::map; + + static void put(const std::string &key, const std::string &value) { + get_context()[key] = value; + } + + static std::string get(const std::string &key) { + auto &context = get_context(); + auto it = context.find(key); + if (it != context.end()) { + return it->second; + } + return ""; + } + + static void remove(const std::string &key) { get_context().erase(key); } + + static void clear() { get_context().clear(); } + + static mdc_map_t &get_context() { + static thread_local mdc_map_t context; + return context; + } +}; + +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/pattern_formatter-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/pattern_formatter-inl.h new file mode 100644 index 0000000..b53d805 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/pattern_formatter-inl.h @@ -0,0 +1,1338 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include +#include + +#ifndef SPDLOG_NO_TLS + #include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spdlog { +namespace details { + +/////////////////////////////////////////////////////////////////////// +// name & level pattern appender +/////////////////////////////////////////////////////////////////////// + +class scoped_padder { +public: + scoped_padder(size_t wrapped_size, const padding_info &padinfo, memory_buf_t &dest) + : padinfo_(padinfo), + dest_(dest) { + remaining_pad_ = static_cast(padinfo.width_) - static_cast(wrapped_size); + if (remaining_pad_ <= 0) { + return; + } + + if (padinfo_.side_ == padding_info::pad_side::left) { + pad_it(remaining_pad_); + remaining_pad_ = 0; + } else if (padinfo_.side_ == padding_info::pad_side::center) { + auto half_pad = remaining_pad_ / 2; + auto reminder = remaining_pad_ & 1; + pad_it(half_pad); + remaining_pad_ = half_pad + reminder; // for the right side + } + } + + template + static unsigned int count_digits(T n) { + return fmt_helper::count_digits(n); + } + + ~scoped_padder() { + if (remaining_pad_ >= 0) { + pad_it(remaining_pad_); + } else if (padinfo_.truncate_) { + long new_size = static_cast(dest_.size()) + remaining_pad_; + dest_.resize(static_cast(new_size)); + } + } + +private: + void pad_it(long count) { + fmt_helper::append_string_view(string_view_t(spaces_.data(), static_cast(count)), + dest_); + } + + const padding_info &padinfo_; + memory_buf_t &dest_; + long remaining_pad_; + string_view_t spaces_{" ", 64}; +}; + +struct null_scoped_padder { + null_scoped_padder(size_t /*wrapped_size*/, + const padding_info & /*padinfo*/, + memory_buf_t & /*dest*/) {} + + template + static unsigned int count_digits(T /* number */) { + return 0; + } +}; + +template +class name_formatter final : public flag_formatter { +public: + explicit name_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + ScopedPadder p(msg.logger_name.size(), padinfo_, dest); + fmt_helper::append_string_view(msg.logger_name, dest); + } +}; + +// log level appender +template +class level_formatter final : public flag_formatter { +public: + explicit level_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + const string_view_t &level_name = level::to_string_view(msg.level); + ScopedPadder p(level_name.size(), padinfo_, dest); + fmt_helper::append_string_view(level_name, dest); + } +}; + +// short log level appender +template +class short_level_formatter final : public flag_formatter { +public: + explicit short_level_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + string_view_t level_name{level::to_short_c_str(msg.level)}; + ScopedPadder p(level_name.size(), padinfo_, dest); + fmt_helper::append_string_view(level_name, dest); + } +}; + +/////////////////////////////////////////////////////////////////////// +// Date time pattern appenders +/////////////////////////////////////////////////////////////////////// + +static const char *ampm(const tm &t) { return t.tm_hour >= 12 ? "PM" : "AM"; } + +static int to12h(const tm &t) { return t.tm_hour > 12 ? t.tm_hour - 12 : t.tm_hour; } + +// Abbreviated weekday name +static std::array days{{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}}; + +template +class a_formatter final : public flag_formatter { +public: + explicit a_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + string_view_t field_value{days[static_cast(tm_time.tm_wday)]}; + ScopedPadder p(field_value.size(), padinfo_, dest); + fmt_helper::append_string_view(field_value, dest); + } +}; + +// Full weekday name +static std::array full_days{ + {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}}; + +template +class A_formatter : public flag_formatter { +public: + explicit A_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + string_view_t field_value{full_days[static_cast(tm_time.tm_wday)]}; + ScopedPadder p(field_value.size(), padinfo_, dest); + fmt_helper::append_string_view(field_value, dest); + } +}; + +// Abbreviated month +static const std::array months{ + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}}; + +template +class b_formatter final : public flag_formatter { +public: + explicit b_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + string_view_t field_value{months[static_cast(tm_time.tm_mon)]}; + ScopedPadder p(field_value.size(), padinfo_, dest); + fmt_helper::append_string_view(field_value, dest); + } +}; + +// Full month name +static const std::array full_months{{"January", "February", "March", "April", + "May", "June", "July", "August", "September", + "October", "November", "December"}}; + +template +class B_formatter final : public flag_formatter { +public: + explicit B_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + string_view_t field_value{full_months[static_cast(tm_time.tm_mon)]}; + ScopedPadder p(field_value.size(), padinfo_, dest); + fmt_helper::append_string_view(field_value, dest); + } +}; + +// Date and time representation (Thu Aug 23 15:35:46 2014) +template +class c_formatter final : public flag_formatter { +public: + explicit c_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 24; + ScopedPadder p(field_size, padinfo_, dest); + + fmt_helper::append_string_view(days[static_cast(tm_time.tm_wday)], dest); + dest.push_back(' '); + fmt_helper::append_string_view(months[static_cast(tm_time.tm_mon)], dest); + dest.push_back(' '); + fmt_helper::append_int(tm_time.tm_mday, dest); + dest.push_back(' '); + // time + + fmt_helper::pad2(tm_time.tm_hour, dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_min, dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_sec, dest); + dest.push_back(' '); + fmt_helper::append_int(tm_time.tm_year + 1900, dest); + } +}; + +// year - 2 digit +template +class C_formatter final : public flag_formatter { +public: + explicit C_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_year % 100, dest); + } +}; + +// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01 +template +class D_formatter final : public flag_formatter { +public: + explicit D_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 10; + ScopedPadder p(field_size, padinfo_, dest); + + fmt_helper::pad2(tm_time.tm_mon + 1, dest); + dest.push_back('/'); + fmt_helper::pad2(tm_time.tm_mday, dest); + dest.push_back('/'); + fmt_helper::pad2(tm_time.tm_year % 100, dest); + } +}; + +// year - 4 digit +template +class Y_formatter final : public flag_formatter { +public: + explicit Y_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 4; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::append_int(tm_time.tm_year + 1900, dest); + } +}; + +// month 1-12 +template +class m_formatter final : public flag_formatter { +public: + explicit m_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_mon + 1, dest); + } +}; + +// day of month 1-31 +template +class d_formatter final : public flag_formatter { +public: + explicit d_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_mday, dest); + } +}; + +// hours in 24 format 0-23 +template +class H_formatter final : public flag_formatter { +public: + explicit H_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_hour, dest); + } +}; + +// hours in 12 format 1-12 +template +class I_formatter final : public flag_formatter { +public: + explicit I_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(to12h(tm_time), dest); + } +}; + +// minutes 0-59 +template +class M_formatter final : public flag_formatter { +public: + explicit M_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_min, dest); + } +}; + +// seconds 0-59 +template +class S_formatter final : public flag_formatter { +public: + explicit S_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_sec, dest); + } +}; + +// milliseconds +template +class e_formatter final : public flag_formatter { +public: + explicit e_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + auto millis = fmt_helper::time_fraction(msg.time); + const size_t field_size = 3; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad3(static_cast(millis.count()), dest); + } +}; + +// microseconds +template +class f_formatter final : public flag_formatter { +public: + explicit f_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + auto micros = fmt_helper::time_fraction(msg.time); + + const size_t field_size = 6; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad6(static_cast(micros.count()), dest); + } +}; + +// nanoseconds +template +class F_formatter final : public flag_formatter { +public: + explicit F_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + auto ns = fmt_helper::time_fraction(msg.time); + const size_t field_size = 9; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad9(static_cast(ns.count()), dest); + } +}; + +// seconds since epoch +template +class E_formatter final : public flag_formatter { +public: + explicit E_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + const size_t field_size = 10; + ScopedPadder p(field_size, padinfo_, dest); + auto duration = msg.time.time_since_epoch(); + auto seconds = std::chrono::duration_cast(duration).count(); + fmt_helper::append_int(seconds, dest); + } +}; + +// AM/PM +template +class p_formatter final : public flag_formatter { +public: + explicit p_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 2; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::append_string_view(ampm(tm_time), dest); + } +}; + +// 12 hour clock 02:55:02 pm +template +class r_formatter final : public flag_formatter { +public: + explicit r_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 11; + ScopedPadder p(field_size, padinfo_, dest); + + fmt_helper::pad2(to12h(tm_time), dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_min, dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_sec, dest); + dest.push_back(' '); + fmt_helper::append_string_view(ampm(tm_time), dest); + } +}; + +// 24-hour HH:MM time, equivalent to %H:%M +template +class R_formatter final : public flag_formatter { +public: + explicit R_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 5; + ScopedPadder p(field_size, padinfo_, dest); + + fmt_helper::pad2(tm_time.tm_hour, dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_min, dest); + } +}; + +// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S +template +class T_formatter final : public flag_formatter { +public: + explicit T_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 8; + ScopedPadder p(field_size, padinfo_, dest); + + fmt_helper::pad2(tm_time.tm_hour, dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_min, dest); + dest.push_back(':'); + fmt_helper::pad2(tm_time.tm_sec, dest); + } +}; + +// ISO 8601 offset from UTC in timezone (+-HH:MM) +template +class z_formatter final : public flag_formatter { +public: + explicit z_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + z_formatter() = default; + z_formatter(const z_formatter &) = delete; + z_formatter &operator=(const z_formatter &) = delete; + + void format(const details::log_msg &msg, const std::tm &tm_time, memory_buf_t &dest) override { + const size_t field_size = 6; + ScopedPadder p(field_size, padinfo_, dest); + + auto total_minutes = get_cached_offset(msg, tm_time); + bool is_negative = total_minutes < 0; + if (is_negative) { + total_minutes = -total_minutes; + dest.push_back('-'); + } else { + dest.push_back('+'); + } + + fmt_helper::pad2(total_minutes / 60, dest); // hours + dest.push_back(':'); + fmt_helper::pad2(total_minutes % 60, dest); // minutes + } + +private: + log_clock::time_point last_update_{std::chrono::seconds(0)}; + int offset_minutes_{0}; + + int get_cached_offset(const log_msg &msg, const std::tm &tm_time) { + // refresh every 10 seconds + if (msg.time - last_update_ >= std::chrono::seconds(10)) { + offset_minutes_ = os::utc_minutes_offset(tm_time); + last_update_ = msg.time; + } + return offset_minutes_; + } +}; + +// Thread id +template +class t_formatter final : public flag_formatter { +public: + explicit t_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + const auto field_size = ScopedPadder::count_digits(msg.thread_id); + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::append_int(msg.thread_id, dest); + } +}; + +// Current pid +template +class pid_formatter final : public flag_formatter { +public: + explicit pid_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &, memory_buf_t &dest) override { + const auto pid = static_cast(details::os::pid()); + auto field_size = ScopedPadder::count_digits(pid); + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::append_int(pid, dest); + } +}; + +template +class v_formatter final : public flag_formatter { +public: + explicit v_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + ScopedPadder p(msg.payload.size(), padinfo_, dest); + fmt_helper::append_string_view(msg.payload, dest); + } +}; + +class ch_formatter final : public flag_formatter { +public: + explicit ch_formatter(char ch) + : ch_(ch) {} + + void format(const details::log_msg &, const std::tm &, memory_buf_t &dest) override { + dest.push_back(ch_); + } + +private: + char ch_; +}; + +// aggregate user chars to display as is +class aggregate_formatter final : public flag_formatter { +public: + aggregate_formatter() = default; + + void add_ch(char ch) { str_ += ch; } + void format(const details::log_msg &, const std::tm &, memory_buf_t &dest) override { + fmt_helper::append_string_view(str_, dest); + } + +private: + std::string str_; +}; + +// mark the color range. expect it to be in the form of "%^colored text%$" +class color_start_formatter final : public flag_formatter { +public: + explicit color_start_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + msg.color_range_start = dest.size(); + } +}; + +class color_stop_formatter final : public flag_formatter { +public: + explicit color_stop_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + msg.color_range_end = dest.size(); + } +}; + +// print source location +template +class source_location_formatter final : public flag_formatter { +public: + explicit source_location_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); + return; + } + + size_t text_size; + if (padinfo_.enabled()) { + // calc text size for padding based on "filename:line" + text_size = std::char_traits::length(msg.source.filename) + + ScopedPadder::count_digits(msg.source.line) + 1; + } else { + text_size = 0; + } + + ScopedPadder p(text_size, padinfo_, dest); + fmt_helper::append_string_view(msg.source.filename, dest); + dest.push_back(':'); + fmt_helper::append_int(msg.source.line, dest); + } +}; + +// print source filename +template +class source_filename_formatter final : public flag_formatter { +public: + explicit source_filename_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); + return; + } + size_t text_size = + padinfo_.enabled() ? std::char_traits::length(msg.source.filename) : 0; + ScopedPadder p(text_size, padinfo_, dest); + fmt_helper::append_string_view(msg.source.filename, dest); + } +}; + +template +class short_filename_formatter final : public flag_formatter { +public: + explicit short_filename_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable : 4127) // consider using 'if constexpr' instead +#endif // _MSC_VER + static const char *basename(const char *filename) { + // if the size is 2 (1 character + null terminator) we can use the more efficient strrchr + // the branch will be elided by optimizations + if (sizeof(os::folder_seps) == 2) { + const char *rv = std::strrchr(filename, os::folder_seps[0]); + return rv != nullptr ? rv + 1 : filename; + } else { + const std::reverse_iterator begin(filename + std::strlen(filename)); + const std::reverse_iterator end(filename); + + const auto it = std::find_first_of(begin, end, std::begin(os::folder_seps), + std::end(os::folder_seps) - 1); + return it != end ? it.base() : filename; + } + } +#ifdef _MSC_VER + #pragma warning(pop) +#endif // _MSC_VER + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); + return; + } + auto filename = basename(msg.source.filename); + size_t text_size = padinfo_.enabled() ? std::char_traits::length(filename) : 0; + ScopedPadder p(text_size, padinfo_, dest); + fmt_helper::append_string_view(filename, dest); + } +}; + +template +class source_linenum_formatter final : public flag_formatter { +public: + explicit source_linenum_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); + return; + } + + auto field_size = ScopedPadder::count_digits(msg.source.line); + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::append_int(msg.source.line, dest); + } +}; + +// print source funcname +template +class source_funcname_formatter final : public flag_formatter { +public: + explicit source_funcname_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); + return; + } + size_t text_size = + padinfo_.enabled() ? std::char_traits::length(msg.source.funcname) : 0; + ScopedPadder p(text_size, padinfo_, dest); + fmt_helper::append_string_view(msg.source.funcname, dest); + } +}; + +// print elapsed time since last message +template +class elapsed_formatter final : public flag_formatter { +public: + using DurationUnits = Units; + + explicit elapsed_formatter(padding_info padinfo) + : flag_formatter(padinfo), + last_message_time_(log_clock::now()) {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { + auto delta = (std::max)(msg.time - last_message_time_, log_clock::duration::zero()); + auto delta_units = std::chrono::duration_cast(delta); + last_message_time_ = msg.time; + auto delta_count = static_cast(delta_units.count()); + auto n_digits = static_cast(ScopedPadder::count_digits(delta_count)); + ScopedPadder p(n_digits, padinfo_, dest); + fmt_helper::append_int(delta_count, dest); + } + +private: + log_clock::time_point last_message_time_; +}; + +// Class for formatting Mapped Diagnostic Context (MDC) in log messages. +// Example: [logger-name] [info] [mdc_key_1:mdc_value_1 mdc_key_2:mdc_value_2] some message +#ifndef SPDLOG_NO_TLS +template +class mdc_formatter : public flag_formatter { +public: + explicit mdc_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &, const std::tm &, memory_buf_t &dest) override { + auto &mdc_map = mdc::get_context(); + if (mdc_map.empty()) { + ScopedPadder p(0, padinfo_, dest); + return; + } else { + format_mdc(mdc_map, dest); + } + } + + void format_mdc(const mdc::mdc_map_t &mdc_map, memory_buf_t &dest) { + auto last_element = --mdc_map.end(); + for (auto it = mdc_map.begin(); it != mdc_map.end(); ++it) { + auto &pair = *it; + const auto &key = pair.first; + const auto &value = pair.second; + size_t content_size = key.size() + value.size() + 1; // 1 for ':' + + if (it != last_element) { + content_size++; // 1 for ' ' + } + + ScopedPadder p(content_size, padinfo_, dest); + fmt_helper::append_string_view(key, dest); + fmt_helper::append_string_view(":", dest); + fmt_helper::append_string_view(value, dest); + if (it != last_element) { + fmt_helper::append_string_view(" ", dest); + } + } + } +}; +#endif + +// Full info formatter +// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] [%s:%#] %v +class full_formatter final : public flag_formatter { +public: + explicit full_formatter(padding_info padinfo) + : flag_formatter(padinfo) {} + + void format(const details::log_msg &msg, const std::tm &tm_time, memory_buf_t &dest) override { + using std::chrono::duration_cast; + using std::chrono::milliseconds; + using std::chrono::seconds; + + // cache the date/time part for the next second. + auto duration = msg.time.time_since_epoch(); + auto secs = duration_cast(duration); + + if (cache_timestamp_ != secs || cached_datetime_.size() == 0) { + cached_datetime_.clear(); + cached_datetime_.push_back('['); + fmt_helper::append_int(tm_time.tm_year + 1900, cached_datetime_); + cached_datetime_.push_back('-'); + + fmt_helper::pad2(tm_time.tm_mon + 1, cached_datetime_); + cached_datetime_.push_back('-'); + + fmt_helper::pad2(tm_time.tm_mday, cached_datetime_); + cached_datetime_.push_back(' '); + + fmt_helper::pad2(tm_time.tm_hour, cached_datetime_); + cached_datetime_.push_back(':'); + + fmt_helper::pad2(tm_time.tm_min, cached_datetime_); + cached_datetime_.push_back(':'); + + fmt_helper::pad2(tm_time.tm_sec, cached_datetime_); + cached_datetime_.push_back('.'); + + cache_timestamp_ = secs; + } + dest.append(cached_datetime_.begin(), cached_datetime_.end()); + + auto millis = fmt_helper::time_fraction(msg.time); + fmt_helper::pad3(static_cast(millis.count()), dest); + dest.push_back(']'); + dest.push_back(' '); + + // append logger name if exists + if (msg.logger_name.size() > 0) { + dest.push_back('['); + fmt_helper::append_string_view(msg.logger_name, dest); + dest.push_back(']'); + dest.push_back(' '); + } + + dest.push_back('['); + // wrap the level name with color + msg.color_range_start = dest.size(); + // fmt_helper::append_string_view(level::to_c_str(msg.level), dest); + fmt_helper::append_string_view(level::to_string_view(msg.level), dest); + msg.color_range_end = dest.size(); + dest.push_back(']'); + dest.push_back(' '); + + // add source location if present + if (!msg.source.empty()) { + dest.push_back('['); + const char *filename = + details::short_filename_formatter::basename( + msg.source.filename); + fmt_helper::append_string_view(filename, dest); + dest.push_back(':'); + fmt_helper::append_int(msg.source.line, dest); + dest.push_back(']'); + dest.push_back(' '); + } + +#ifndef SPDLOG_NO_TLS + // add mdc if present + auto &mdc_map = mdc::get_context(); + if (!mdc_map.empty()) { + dest.push_back('['); + mdc_formatter_.format_mdc(mdc_map, dest); + dest.push_back(']'); + dest.push_back(' '); + } +#endif + // fmt_helper::append_string_view(msg.msg(), dest); + fmt_helper::append_string_view(msg.payload, dest); + } + +private: + std::chrono::seconds cache_timestamp_{0}; + memory_buf_t cached_datetime_; + +#ifndef SPDLOG_NO_TLS + mdc_formatter mdc_formatter_{padding_info{}}; +#endif + +}; + +} // namespace details + +SPDLOG_INLINE pattern_formatter::pattern_formatter(std::string pattern, + pattern_time_type time_type, + std::string eol, + custom_flags custom_user_flags) + : pattern_(std::move(pattern)), + eol_(std::move(eol)), + pattern_time_type_(time_type), + need_localtime_(false), + last_log_secs_(0), + custom_handlers_(std::move(custom_user_flags)) { + std::memset(&cached_tm_, 0, sizeof(cached_tm_)); + compile_pattern_(pattern_); +} + +// use by default full formatter for if pattern is not given +SPDLOG_INLINE pattern_formatter::pattern_formatter(pattern_time_type time_type, std::string eol) + : pattern_("%+"), + eol_(std::move(eol)), + pattern_time_type_(time_type), + need_localtime_(true), + last_log_secs_(0) { + std::memset(&cached_tm_, 0, sizeof(cached_tm_)); + formatters_.push_back(details::make_unique(details::padding_info{})); +} + +SPDLOG_INLINE std::unique_ptr pattern_formatter::clone() const { + custom_flags cloned_custom_formatters; + for (auto &it : custom_handlers_) { + cloned_custom_formatters[it.first] = it.second->clone(); + } + auto cloned = details::make_unique(pattern_, pattern_time_type_, eol_, + std::move(cloned_custom_formatters)); + cloned->need_localtime(need_localtime_); +#if defined(__GNUC__) && __GNUC__ < 5 + return std::move(cloned); +#else + return cloned; +#endif +} + +SPDLOG_INLINE void pattern_formatter::format(const details::log_msg &msg, memory_buf_t &dest) { + if (need_localtime_) { + const auto secs = + std::chrono::duration_cast(msg.time.time_since_epoch()); + if (secs != last_log_secs_) { + cached_tm_ = get_time_(msg); + last_log_secs_ = secs; + } + } + + for (auto &f : formatters_) { + f->format(msg, cached_tm_, dest); + } + // write eol + details::fmt_helper::append_string_view(eol_, dest); +} + +SPDLOG_INLINE void pattern_formatter::set_pattern(std::string pattern) { + pattern_ = std::move(pattern); + need_localtime_ = false; + compile_pattern_(pattern_); +} + +SPDLOG_INLINE void pattern_formatter::need_localtime(bool need) { need_localtime_ = need; } + +SPDLOG_INLINE std::tm pattern_formatter::get_time_(const details::log_msg &msg) { + if (pattern_time_type_ == pattern_time_type::local) { + return details::os::localtime(log_clock::to_time_t(msg.time)); + } + return details::os::gmtime(log_clock::to_time_t(msg.time)); +} + +template +SPDLOG_INLINE void pattern_formatter::handle_flag_(char flag, details::padding_info padding) { + // process custom flags + auto it = custom_handlers_.find(flag); + if (it != custom_handlers_.end()) { + auto custom_handler = it->second->clone(); + custom_handler->set_padding_info(padding); + formatters_.push_back(std::move(custom_handler)); + return; + } + + // process built-in flags + switch (flag) { + case ('+'): // default formatter + formatters_.push_back(details::make_unique(padding)); + need_localtime_ = true; + break; + + case 'n': // logger name + formatters_.push_back(details::make_unique>(padding)); + break; + + case 'l': // level + formatters_.push_back(details::make_unique>(padding)); + break; + + case 'L': // short level + formatters_.push_back( + details::make_unique>(padding)); + break; + + case ('t'): // thread id + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('v'): // the message text + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('a'): // weekday + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('A'): // short weekday + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('b'): + case ('h'): // month + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('B'): // short month + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('c'): // datetime + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('C'): // year 2 digits + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('Y'): // year 4 digits + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('D'): + case ('x'): // datetime MM/DD/YY + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('m'): // month 1-12 + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('d'): // day of month 1-31 + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('H'): // hours 24 + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('I'): // hours 12 + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('M'): // minutes + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('S'): // seconds + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('e'): // milliseconds + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('f'): // microseconds + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('F'): // nanoseconds + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('E'): // seconds since epoch + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('p'): // am/pm + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('r'): // 12 hour clock 02:55:02 pm + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('R'): // 24-hour HH:MM time + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('T'): + case ('X'): // ISO 8601 time format (HH:MM:SS) + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('z'): // timezone + formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; + break; + + case ('P'): // pid + formatters_.push_back(details::make_unique>(padding)); + break; + + case ('^'): // color range start + formatters_.push_back(details::make_unique(padding)); + break; + + case ('$'): // color range end + formatters_.push_back(details::make_unique(padding)); + break; + + case ('@'): // source location (filename:filenumber) + formatters_.push_back( + details::make_unique>(padding)); + break; + + case ('s'): // short source filename - without directory name + formatters_.push_back( + details::make_unique>(padding)); + break; + + case ('g'): // full source filename + formatters_.push_back( + details::make_unique>(padding)); + break; + + case ('#'): // source line number + formatters_.push_back( + details::make_unique>(padding)); + break; + + case ('!'): // source funcname + formatters_.push_back( + details::make_unique>(padding)); + break; + + case ('%'): // % char + formatters_.push_back(details::make_unique('%')); + break; + + case ('u'): // elapsed time since last log message in nanos + formatters_.push_back( + details::make_unique>( + padding)); + break; + + case ('i'): // elapsed time since last log message in micros + formatters_.push_back( + details::make_unique>( + padding)); + break; + + case ('o'): // elapsed time since last log message in millis + formatters_.push_back( + details::make_unique>( + padding)); + break; + + case ('O'): // elapsed time since last log message in seconds + formatters_.push_back( + details::make_unique>( + padding)); + break; + +#ifndef SPDLOG_NO_TLS // mdc formatter requires TLS support + case ('&'): + formatters_.push_back(details::make_unique>(padding)); + break; +#endif + + default: // Unknown flag appears as is + auto unknown_flag = details::make_unique(); + + if (!padding.truncate_) { + unknown_flag->add_ch('%'); + unknown_flag->add_ch(flag); + formatters_.push_back((std::move(unknown_flag))); + } + // fix issue #1617 (prev char was '!' and should have been treated as funcname flag + // instead of truncating flag) spdlog::set_pattern("[%10!] %v") => "[ main] some + // message" spdlog::set_pattern("[%3!!] %v") => "[mai] some message" + else { + padding.truncate_ = false; + formatters_.push_back( + details::make_unique>(padding)); + unknown_flag->add_ch(flag); + formatters_.push_back((std::move(unknown_flag))); + } + + break; + } +} + +// Extract given pad spec (e.g. %8X, %=8X, %-8!X, %8!X, %=8!X, %-8!X, %+8!X) +// Advance the given it pass the end of the padding spec found (if any) +// Return padding. +SPDLOG_INLINE details::padding_info pattern_formatter::handle_padspec_( + std::string::const_iterator &it, std::string::const_iterator end) { + using details::padding_info; + using details::scoped_padder; + const size_t max_width = 64; + if (it == end) { + return padding_info{}; + } + + padding_info::pad_side side; + switch (*it) { + case '-': + side = padding_info::pad_side::right; + ++it; + break; + case '=': + side = padding_info::pad_side::center; + ++it; + break; + default: + side = details::padding_info::pad_side::left; + break; + } + + if (it == end || !std::isdigit(static_cast(*it))) { + return padding_info{}; // no padding if no digit found here + } + + auto width = static_cast(*it) - '0'; + for (++it; it != end && std::isdigit(static_cast(*it)); ++it) { + auto digit = static_cast(*it) - '0'; + width = width * 10 + digit; + } + + // search for the optional truncate marker '!' + bool truncate; + if (it != end && *it == '!') { + truncate = true; + ++it; + } else { + truncate = false; + } + return details::padding_info{std::min(width, max_width), side, truncate}; +} + +SPDLOG_INLINE void pattern_formatter::compile_pattern_(const std::string &pattern) { + auto end = pattern.end(); + std::unique_ptr user_chars; + formatters_.clear(); + for (auto it = pattern.begin(); it != end; ++it) { + if (*it == '%') { + if (user_chars) // append user chars found so far + { + formatters_.push_back(std::move(user_chars)); + } + + auto padding = handle_padspec_(++it, end); + + if (it != end) { + if (padding.enabled()) { + handle_flag_(*it, padding); + } else { + handle_flag_(*it, padding); + } + } else { + break; + } + } else // chars not following the % sign should be displayed as is + { + if (!user_chars) { + user_chars = details::make_unique(); + } + user_chars->add_ch(*it); + } + } + if (user_chars) // append raw chars found so far + { + formatters_.push_back(std::move(user_chars)); + } +} +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/pattern_formatter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/pattern_formatter.h new file mode 100644 index 0000000..ececd67 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/pattern_formatter.h @@ -0,0 +1,118 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace spdlog { +namespace details { + +// padding information. +struct padding_info { + enum class pad_side { left, right, center }; + + padding_info() = default; + padding_info(size_t width, padding_info::pad_side side, bool truncate) + : width_(width), + side_(side), + truncate_(truncate), + enabled_(true) {} + + bool enabled() const { return enabled_; } + size_t width_ = 0; + pad_side side_ = pad_side::left; + bool truncate_ = false; + bool enabled_ = false; +}; + +class SPDLOG_API flag_formatter { +public: + explicit flag_formatter(padding_info padinfo) + : padinfo_(padinfo) {} + flag_formatter() = default; + virtual ~flag_formatter() = default; + virtual void format(const details::log_msg &msg, + const std::tm &tm_time, + memory_buf_t &dest) = 0; + +protected: + padding_info padinfo_; +}; + +} // namespace details + +class SPDLOG_API custom_flag_formatter : public details::flag_formatter { +public: + virtual std::unique_ptr clone() const = 0; + + void set_padding_info(const details::padding_info &padding) { + flag_formatter::padinfo_ = padding; + } +}; + +class SPDLOG_API pattern_formatter final : public formatter { +public: + using custom_flags = std::unordered_map>; + + explicit pattern_formatter(std::string pattern, + pattern_time_type time_type = pattern_time_type::local, + std::string eol = spdlog::details::os::default_eol, + custom_flags custom_user_flags = custom_flags()); + + // use default pattern is not given + explicit pattern_formatter(pattern_time_type time_type = pattern_time_type::local, + std::string eol = spdlog::details::os::default_eol); + + pattern_formatter(const pattern_formatter &other) = delete; + pattern_formatter &operator=(const pattern_formatter &other) = delete; + + std::unique_ptr clone() const override; + void format(const details::log_msg &msg, memory_buf_t &dest) override; + + template + pattern_formatter &add_flag(char flag, Args &&...args) { + custom_handlers_[flag] = details::make_unique(std::forward(args)...); + return *this; + } + void set_pattern(std::string pattern); + void need_localtime(bool need = true); + +private: + std::string pattern_; + std::string eol_; + pattern_time_type pattern_time_type_; + bool need_localtime_; + std::tm cached_tm_; + std::chrono::seconds last_log_secs_; + std::vector> formatters_; + custom_flags custom_handlers_; + + std::tm get_time_(const details::log_msg &msg); + template + void handle_flag_(char flag, details::padding_info padding); + + // Extract given pad spec (e.g. %8X) + // Advance the given it pass the end of the padding spec found (if any) + // Return padding. + static details::padding_info handle_padspec_(std::string::const_iterator &it, + std::string::const_iterator end); + + void compile_pattern_(const std::string &pattern); +}; +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "pattern_formatter-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/android_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/android_sink.h new file mode 100644 index 0000000..4435a56 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/android_sink.h @@ -0,0 +1,137 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifdef __ANDROID__ + + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + + #if !defined(SPDLOG_ANDROID_RETRIES) + #define SPDLOG_ANDROID_RETRIES 2 + #endif + +namespace spdlog { +namespace sinks { + +/* + * Android sink + * (logging using __android_log_write or __android_log_buf_write depending on the specified + * BufferID) + */ +template +class android_sink final : public base_sink { +public: + explicit android_sink(std::string tag = "spdlog", bool use_raw_msg = false) + : tag_(std::move(tag)), + use_raw_msg_(use_raw_msg) {} + +protected: + void sink_it_(const details::log_msg &msg) override { + const android_LogPriority priority = convert_to_android_(msg.level); + memory_buf_t formatted; + if (use_raw_msg_) { + details::fmt_helper::append_string_view(msg.payload, formatted); + } else { + base_sink::formatter_->format(msg, formatted); + } + formatted.push_back('\0'); + const char *msg_output = formatted.data(); + + // See system/core/liblog/logger_write.c for explanation of return value + int ret = android_log(priority, tag_.c_str(), msg_output); + if (ret == -EPERM) { + return; // !__android_log_is_loggable + } + int retry_count = 0; + while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES)) { + details::os::sleep_for_millis(5); + ret = android_log(priority, tag_.c_str(), msg_output); + retry_count++; + } + + if (ret < 0) { + throw_spdlog_ex("logging to Android failed", ret); + } + } + + void flush_() override {} + +private: + // There might be liblog versions used, that do not support __android_log_buf_write. So we only + // compile and link against + // __android_log_buf_write, if user explicitly provides a non-default log buffer. Otherwise, + // when using the default log buffer, always log via __android_log_write. + template + typename std::enable_if(log_id::LOG_ID_MAIN), int>::type android_log( + int prio, const char *tag, const char *text) { + return __android_log_write(prio, tag, text); + } + + template + typename std::enable_if(log_id::LOG_ID_MAIN), int>::type android_log( + int prio, const char *tag, const char *text) { + return __android_log_buf_write(ID, prio, tag, text); + } + + static android_LogPriority convert_to_android_(spdlog::level::level_enum level) { + switch (level) { + case spdlog::level::trace: + return ANDROID_LOG_VERBOSE; + case spdlog::level::debug: + return ANDROID_LOG_DEBUG; + case spdlog::level::info: + return ANDROID_LOG_INFO; + case spdlog::level::warn: + return ANDROID_LOG_WARN; + case spdlog::level::err: + return ANDROID_LOG_ERROR; + case spdlog::level::critical: + return ANDROID_LOG_FATAL; + default: + return ANDROID_LOG_DEFAULT; + } + } + + std::string tag_; + bool use_raw_msg_; +}; + +using android_sink_mt = android_sink; +using android_sink_st = android_sink; + +template +using android_sink_buf_mt = android_sink; +template +using android_sink_buf_st = android_sink; + +} // namespace sinks + +// Create and register android syslog logger + +template +inline std::shared_ptr android_logger_mt(const std::string &logger_name, + const std::string &tag = "spdlog") { + return Factory::template create(logger_name, tag); +} + +template +inline std::shared_ptr android_logger_st(const std::string &logger_name, + const std::string &tag = "spdlog") { + return Factory::template create(logger_name, tag); +} + +} // namespace spdlog + +#endif // __ANDROID__ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ansicolor_sink-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ansicolor_sink-inl.h new file mode 100644 index 0000000..2194f67 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ansicolor_sink-inl.h @@ -0,0 +1,135 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +namespace spdlog { +namespace sinks { + +template +SPDLOG_INLINE ansicolor_sink::ansicolor_sink(FILE *target_file, color_mode mode) + : target_file_(target_file), + mutex_(ConsoleMutex::mutex()), + formatter_(details::make_unique()) + +{ + set_color_mode(mode); + colors_.at(level::trace) = to_string_(white); + colors_.at(level::debug) = to_string_(cyan); + colors_.at(level::info) = to_string_(green); + colors_.at(level::warn) = to_string_(yellow_bold); + colors_.at(level::err) = to_string_(red_bold); + colors_.at(level::critical) = to_string_(bold_on_red); + colors_.at(level::off) = to_string_(reset); +} + +template +SPDLOG_INLINE void ansicolor_sink::set_color(level::level_enum color_level, + string_view_t color) { + std::lock_guard lock(mutex_); + colors_.at(static_cast(color_level)) = to_string_(color); +} + +template +SPDLOG_INLINE void ansicolor_sink::log(const details::log_msg &msg) { + // Wrap the originally formatted message in color codes. + // If color is not supported in the terminal, log as is instead. + std::lock_guard lock(mutex_); + msg.color_range_start = 0; + msg.color_range_end = 0; + memory_buf_t formatted; + formatter_->format(msg, formatted); + if (should_do_colors_ && msg.color_range_end > msg.color_range_start) { + // before color range + print_range_(formatted, 0, msg.color_range_start); + // in color range + print_ccode_(colors_.at(static_cast(msg.level))); + print_range_(formatted, msg.color_range_start, msg.color_range_end); + print_ccode_(reset); + // after color range + print_range_(formatted, msg.color_range_end, formatted.size()); + } else // no color + { + print_range_(formatted, 0, formatted.size()); + } + fflush(target_file_); +} + +template +SPDLOG_INLINE void ansicolor_sink::flush() { + std::lock_guard lock(mutex_); + fflush(target_file_); +} + +template +SPDLOG_INLINE void ansicolor_sink::set_pattern(const std::string &pattern) { + std::lock_guard lock(mutex_); + formatter_ = std::unique_ptr(new pattern_formatter(pattern)); +} + +template +SPDLOG_INLINE void ansicolor_sink::set_formatter( + std::unique_ptr sink_formatter) { + std::lock_guard lock(mutex_); + formatter_ = std::move(sink_formatter); +} + +template +SPDLOG_INLINE bool ansicolor_sink::should_color() { + return should_do_colors_; +} + +template +SPDLOG_INLINE void ansicolor_sink::set_color_mode(color_mode mode) { + switch (mode) { + case color_mode::always: + should_do_colors_ = true; + return; + case color_mode::automatic: + should_do_colors_ = + details::os::in_terminal(target_file_) && details::os::is_color_terminal(); + return; + case color_mode::never: + should_do_colors_ = false; + return; + default: + should_do_colors_ = false; + } +} + +template +SPDLOG_INLINE void ansicolor_sink::print_ccode_(const string_view_t &color_code) { + fwrite(color_code.data(), sizeof(char), color_code.size(), target_file_); +} + +template +SPDLOG_INLINE void ansicolor_sink::print_range_(const memory_buf_t &formatted, + size_t start, + size_t end) { + fwrite(formatted.data() + start, sizeof(char), end - start, target_file_); +} + +template +SPDLOG_INLINE std::string ansicolor_sink::to_string_(const string_view_t &sv) { + return std::string(sv.data(), sv.size()); +} + +// ansicolor_stdout_sink +template +SPDLOG_INLINE ansicolor_stdout_sink::ansicolor_stdout_sink(color_mode mode) + : ansicolor_sink(stdout, mode) {} + +// ansicolor_stderr_sink +template +SPDLOG_INLINE ansicolor_stderr_sink::ansicolor_stderr_sink(color_mode mode) + : ansicolor_sink(stderr, mode) {} + +} // namespace sinks +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ansicolor_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ansicolor_sink.h new file mode 100644 index 0000000..d0dadd7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ansicolor_sink.h @@ -0,0 +1,115 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace spdlog { +namespace sinks { + +/** + * This sink prefixes the output with an ANSI escape sequence color code + * depending on the severity + * of the message. + * If no color terminal detected, omit the escape codes. + */ + +template +class ansicolor_sink : public sink { +public: + using mutex_t = typename ConsoleMutex::mutex_t; + ansicolor_sink(FILE *target_file, color_mode mode); + ~ansicolor_sink() override = default; + + ansicolor_sink(const ansicolor_sink &other) = delete; + ansicolor_sink(ansicolor_sink &&other) = delete; + + ansicolor_sink &operator=(const ansicolor_sink &other) = delete; + ansicolor_sink &operator=(ansicolor_sink &&other) = delete; + + void set_color(level::level_enum color_level, string_view_t color); + void set_color_mode(color_mode mode); + bool should_color(); + + void log(const details::log_msg &msg) override; + void flush() override; + void set_pattern(const std::string &pattern) final override; + void set_formatter(std::unique_ptr sink_formatter) override; + + // Formatting codes + const string_view_t reset = "\033[m"; + const string_view_t bold = "\033[1m"; + const string_view_t dark = "\033[2m"; + const string_view_t underline = "\033[4m"; + const string_view_t blink = "\033[5m"; + const string_view_t reverse = "\033[7m"; + const string_view_t concealed = "\033[8m"; + const string_view_t clear_line = "\033[K"; + + // Foreground colors + const string_view_t black = "\033[30m"; + const string_view_t red = "\033[31m"; + const string_view_t green = "\033[32m"; + const string_view_t yellow = "\033[33m"; + const string_view_t blue = "\033[34m"; + const string_view_t magenta = "\033[35m"; + const string_view_t cyan = "\033[36m"; + const string_view_t white = "\033[37m"; + + /// Background colors + const string_view_t on_black = "\033[40m"; + const string_view_t on_red = "\033[41m"; + const string_view_t on_green = "\033[42m"; + const string_view_t on_yellow = "\033[43m"; + const string_view_t on_blue = "\033[44m"; + const string_view_t on_magenta = "\033[45m"; + const string_view_t on_cyan = "\033[46m"; + const string_view_t on_white = "\033[47m"; + + /// Bold colors + const string_view_t yellow_bold = "\033[33m\033[1m"; + const string_view_t red_bold = "\033[31m\033[1m"; + const string_view_t bold_on_red = "\033[1m\033[41m"; + +private: + FILE *target_file_; + mutex_t &mutex_; + bool should_do_colors_; + std::unique_ptr formatter_; + std::array colors_; + void print_ccode_(const string_view_t &color_code); + void print_range_(const memory_buf_t &formatted, size_t start, size_t end); + static std::string to_string_(const string_view_t &sv); +}; + +template +class ansicolor_stdout_sink : public ansicolor_sink { +public: + explicit ansicolor_stdout_sink(color_mode mode = color_mode::automatic); +}; + +template +class ansicolor_stderr_sink : public ansicolor_sink { +public: + explicit ansicolor_stderr_sink(color_mode mode = color_mode::automatic); +}; + +using ansicolor_stdout_sink_mt = ansicolor_stdout_sink; +using ansicolor_stdout_sink_st = ansicolor_stdout_sink; + +using ansicolor_stderr_sink_mt = ansicolor_stderr_sink; +using ansicolor_stderr_sink_st = ansicolor_stderr_sink; + +} // namespace sinks +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "ansicolor_sink-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/base_sink-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/base_sink-inl.h new file mode 100644 index 0000000..ada161b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/base_sink-inl.h @@ -0,0 +1,59 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +#include +#include + +template +SPDLOG_INLINE spdlog::sinks::base_sink::base_sink() + : formatter_{details::make_unique()} {} + +template +SPDLOG_INLINE spdlog::sinks::base_sink::base_sink( + std::unique_ptr formatter) + : formatter_{std::move(formatter)} {} + +template +void SPDLOG_INLINE spdlog::sinks::base_sink::log(const details::log_msg &msg) { + std::lock_guard lock(mutex_); + sink_it_(msg); +} + +template +void SPDLOG_INLINE spdlog::sinks::base_sink::flush() { + std::lock_guard lock(mutex_); + flush_(); +} + +template +void SPDLOG_INLINE spdlog::sinks::base_sink::set_pattern(const std::string &pattern) { + std::lock_guard lock(mutex_); + set_pattern_(pattern); +} + +template +void SPDLOG_INLINE +spdlog::sinks::base_sink::set_formatter(std::unique_ptr sink_formatter) { + std::lock_guard lock(mutex_); + set_formatter_(std::move(sink_formatter)); +} + +template +void SPDLOG_INLINE spdlog::sinks::base_sink::set_pattern_(const std::string &pattern) { + set_formatter_(details::make_unique(pattern)); +} + +template +void SPDLOG_INLINE +spdlog::sinks::base_sink::set_formatter_(std::unique_ptr sink_formatter) { + formatter_ = std::move(sink_formatter); +} diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/base_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/base_sink.h new file mode 100644 index 0000000..1b4bb06 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/base_sink.h @@ -0,0 +1,51 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once +// +// base sink templated over a mutex (either dummy or real) +// concrete implementation should override the sink_it_() and flush_() methods. +// locking is taken care of in this class - no locking needed by the +// implementers.. +// + +#include +#include +#include + +namespace spdlog { +namespace sinks { +template +class SPDLOG_API base_sink : public sink { +public: + base_sink(); + explicit base_sink(std::unique_ptr formatter); + ~base_sink() override = default; + + base_sink(const base_sink &) = delete; + base_sink(base_sink &&) = delete; + + base_sink &operator=(const base_sink &) = delete; + base_sink &operator=(base_sink &&) = delete; + + void log(const details::log_msg &msg) final override; + void flush() final override; + void set_pattern(const std::string &pattern) final override; + void set_formatter(std::unique_ptr sink_formatter) final override; + +protected: + // sink formatter + std::unique_ptr formatter_; + Mutex mutex_; + + virtual void sink_it_(const details::log_msg &msg) = 0; + virtual void flush_() = 0; + virtual void set_pattern_(const std::string &pattern); + virtual void set_formatter_(std::unique_ptr sink_formatter); +}; +} // namespace sinks +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "base_sink-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/basic_file_sink-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/basic_file_sink-inl.h new file mode 100644 index 0000000..f7c1abf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/basic_file_sink-inl.h @@ -0,0 +1,42 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +namespace spdlog { +namespace sinks { + +template +SPDLOG_INLINE basic_file_sink::basic_file_sink(const filename_t &filename, + bool truncate, + const file_event_handlers &event_handlers) + : file_helper_{event_handlers} { + file_helper_.open(filename, truncate); +} + +template +SPDLOG_INLINE const filename_t &basic_file_sink::filename() const { + return file_helper_.filename(); +} + +template +SPDLOG_INLINE void basic_file_sink::sink_it_(const details::log_msg &msg) { + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + file_helper_.write(formatted); +} + +template +SPDLOG_INLINE void basic_file_sink::flush_() { + file_helper_.flush(); +} + +} // namespace sinks +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/basic_file_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/basic_file_sink.h new file mode 100644 index 0000000..699caa1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/basic_file_sink.h @@ -0,0 +1,65 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace spdlog { +namespace sinks { +/* + * Trivial file sink with single file as target + */ +template +class basic_file_sink final : public base_sink { +public: + explicit basic_file_sink(const filename_t &filename, + bool truncate = false, + const file_event_handlers &event_handlers = {}); + const filename_t &filename() const; + +protected: + void sink_it_(const details::log_msg &msg) override; + void flush_() override; + +private: + details::file_helper file_helper_; +}; + +using basic_file_sink_mt = basic_file_sink; +using basic_file_sink_st = basic_file_sink; + +} // namespace sinks + +// +// factory functions +// +template +inline std::shared_ptr basic_logger_mt(const std::string &logger_name, + const filename_t &filename, + bool truncate = false, + const file_event_handlers &event_handlers = {}) { + return Factory::template create(logger_name, filename, truncate, + event_handlers); +} + +template +inline std::shared_ptr basic_logger_st(const std::string &logger_name, + const filename_t &filename, + bool truncate = false, + const file_event_handlers &event_handlers = {}) { + return Factory::template create(logger_name, filename, truncate, + event_handlers); +} + +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "basic_file_sink-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/callback_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/callback_sink.h new file mode 100644 index 0000000..5f8b6bc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/callback_sink.h @@ -0,0 +1,56 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include + +#include +#include + +namespace spdlog { + +// callbacks type +typedef std::function custom_log_callback; + +namespace sinks { +/* + * Trivial callback sink, gets a callback function and calls it on each log + */ +template +class callback_sink final : public base_sink { +public: + explicit callback_sink(const custom_log_callback &callback) + : callback_{callback} {} + +protected: + void sink_it_(const details::log_msg &msg) override { callback_(msg); } + void flush_() override{} + +private: + custom_log_callback callback_; +}; + +using callback_sink_mt = callback_sink; +using callback_sink_st = callback_sink; + +} // namespace sinks + +// +// factory functions +// +template +inline std::shared_ptr callback_logger_mt(const std::string &logger_name, + const custom_log_callback &callback) { + return Factory::template create(logger_name, callback); +} + +template +inline std::shared_ptr callback_logger_st(const std::string &logger_name, + const custom_log_callback &callback) { + return Factory::template create(logger_name, callback); +} + +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/daily_file_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/daily_file_sink.h new file mode 100644 index 0000000..884145f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/daily_file_sink.h @@ -0,0 +1,255 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace spdlog { +namespace sinks { + +/* + * Generator of daily log file names in format basename.YYYY-MM-DD.ext + */ +struct daily_filename_calculator { + // Create filename for the form basename.YYYY-MM-DD + static filename_t calc_filename(const filename_t &filename, const tm &now_tm) { + filename_t basename, ext; + std::tie(basename, ext) = details::file_helper::split_by_extension(filename); + return fmt_lib::format(SPDLOG_FMT_STRING(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}")), + basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, + ext); + } +}; + +/* + * Generator of daily log file names with strftime format. + * Usages: + * auto sink = + * std::make_shared("myapp-%Y-%m-%d:%H:%M:%S.log", hour, + * minute);" auto logger = spdlog::daily_logger_format_mt("loggername, "myapp-%Y-%m-%d:%X.log", + * hour, minute)" + * + */ +struct daily_filename_format_calculator { + static filename_t calc_filename(const filename_t &file_path, const tm &now_tm) { +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) + std::wstringstream stream; +#else + std::stringstream stream; +#endif + stream << std::put_time(&now_tm, file_path.c_str()); + return stream.str(); + } +}; + +/* + * Rotating file sink based on date. + * If truncate != false , the created file will be truncated. + * If max_files > 0, retain only the last max_files and delete previous. + * If max_files > 0, retain only the last max_files and delete previous. + * Note that old log files from previous executions will not be deleted by this class, + * rotation and deletion is only applied while the program is running. + */ +template +class daily_file_sink final : public base_sink { +public: + // create daily file sink which rotates on given time + daily_file_sink(filename_t base_filename, + int rotation_hour, + int rotation_minute, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) + : base_filename_(std::move(base_filename)), + rotation_h_(rotation_hour), + rotation_m_(rotation_minute), + file_helper_{event_handlers}, + truncate_(truncate), + max_files_(max_files), + filenames_q_() { + if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || + rotation_minute > 59) { + throw_spdlog_ex("daily_file_sink: Invalid rotation time in ctor"); + } + + auto now = log_clock::now(); + auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now)); + file_helper_.open(filename, truncate_); + rotation_tp_ = next_rotation_tp_(); + + if (max_files_ > 0) { + init_filenames_q_(); + } + } + + filename_t filename() { + std::lock_guard lock(base_sink::mutex_); + return file_helper_.filename(); + } + +protected: + void sink_it_(const details::log_msg &msg) override { + auto time = msg.time; + bool should_rotate = time >= rotation_tp_; + if (should_rotate) { + auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(time)); + file_helper_.open(filename, truncate_); + rotation_tp_ = next_rotation_tp_(); + } + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + file_helper_.write(formatted); + + // Do the cleaning only at the end because it might throw on failure. + if (should_rotate && max_files_ > 0) { + delete_old_(); + } + } + + void flush_() override { file_helper_.flush(); } + +private: + void init_filenames_q_() { + using details::os::path_exists; + + filenames_q_ = details::circular_q(static_cast(max_files_)); + std::vector filenames; + auto now = log_clock::now(); + while (filenames.size() < max_files_) { + auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now)); + if (!path_exists(filename)) { + break; + } + filenames.emplace_back(filename); + now -= std::chrono::hours(24); + } + for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter) { + filenames_q_.push_back(std::move(*iter)); + } + } + + tm now_tm(log_clock::time_point tp) { + time_t tnow = log_clock::to_time_t(tp); + return spdlog::details::os::localtime(tnow); + } + + log_clock::time_point next_rotation_tp_() { + auto now = log_clock::now(); + tm date = now_tm(now); + date.tm_hour = rotation_h_; + date.tm_min = rotation_m_; + date.tm_sec = 0; + auto rotation_time = log_clock::from_time_t(std::mktime(&date)); + if (rotation_time > now) { + return rotation_time; + } + return {rotation_time + std::chrono::hours(24)}; + } + + // Delete the file N rotations ago. + // Throw spdlog_ex on failure to delete the old file. + void delete_old_() { + using details::os::filename_to_str; + using details::os::remove_if_exists; + + filename_t current_file = file_helper_.filename(); + if (filenames_q_.full()) { + auto old_filename = std::move(filenames_q_.front()); + filenames_q_.pop_front(); + bool ok = remove_if_exists(old_filename) == 0; + if (!ok) { + filenames_q_.push_back(std::move(current_file)); + throw_spdlog_ex("Failed removing daily file " + filename_to_str(old_filename), + errno); + } + } + filenames_q_.push_back(std::move(current_file)); + } + + filename_t base_filename_; + int rotation_h_; + int rotation_m_; + log_clock::time_point rotation_tp_; + details::file_helper file_helper_; + bool truncate_; + uint16_t max_files_; + details::circular_q filenames_q_; +}; + +using daily_file_sink_mt = daily_file_sink; +using daily_file_sink_st = daily_file_sink; +using daily_file_format_sink_mt = daily_file_sink; +using daily_file_format_sink_st = + daily_file_sink; + +} // namespace sinks + +// +// factory functions +// +template +inline std::shared_ptr daily_logger_mt(const std::string &logger_name, + const filename_t &filename, + int hour = 0, + int minute = 0, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) { + return Factory::template create(logger_name, filename, hour, minute, + truncate, max_files, event_handlers); +} + +template +inline std::shared_ptr daily_logger_format_mt( + const std::string &logger_name, + const filename_t &filename, + int hour = 0, + int minute = 0, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) { + return Factory::template create( + logger_name, filename, hour, minute, truncate, max_files, event_handlers); +} + +template +inline std::shared_ptr daily_logger_st(const std::string &logger_name, + const filename_t &filename, + int hour = 0, + int minute = 0, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) { + return Factory::template create(logger_name, filename, hour, minute, + truncate, max_files, event_handlers); +} + +template +inline std::shared_ptr daily_logger_format_st( + const std::string &logger_name, + const filename_t &filename, + int hour = 0, + int minute = 0, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) { + return Factory::template create( + logger_name, filename, hour, minute, truncate, max_files, event_handlers); +} +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/dist_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/dist_sink.h new file mode 100644 index 0000000..69c4971 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/dist_sink.h @@ -0,0 +1,81 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include "base_sink.h" +#include +#include +#include + +#include +#include +#include +#include + +// Distribution sink (mux). Stores a vector of sinks which get called when log +// is called + +namespace spdlog { +namespace sinks { + +template +class dist_sink : public base_sink { +public: + dist_sink() = default; + explicit dist_sink(std::vector> sinks) + : sinks_(sinks) {} + + dist_sink(const dist_sink &) = delete; + dist_sink &operator=(const dist_sink &) = delete; + + void add_sink(std::shared_ptr sub_sink) { + std::lock_guard lock(base_sink::mutex_); + sinks_.push_back(sub_sink); + } + + void remove_sink(std::shared_ptr sub_sink) { + std::lock_guard lock(base_sink::mutex_); + sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sub_sink), sinks_.end()); + } + + void set_sinks(std::vector> sinks) { + std::lock_guard lock(base_sink::mutex_); + sinks_ = std::move(sinks); + } + + std::vector> &sinks() { return sinks_; } + +protected: + void sink_it_(const details::log_msg &msg) override { + for (auto &sub_sink : sinks_) { + if (sub_sink->should_log(msg.level)) { + sub_sink->log(msg); + } + } + } + + void flush_() override { + for (auto &sub_sink : sinks_) { + sub_sink->flush(); + } + } + + void set_pattern_(const std::string &pattern) override { + set_formatter_(details::make_unique(pattern)); + } + + void set_formatter_(std::unique_ptr sink_formatter) override { + base_sink::formatter_ = std::move(sink_formatter); + for (auto &sub_sink : sinks_) { + sub_sink->set_formatter(base_sink::formatter_->clone()); + } + } + std::vector> sinks_; +}; + +using dist_sink_mt = dist_sink; +using dist_sink_st = dist_sink; + +} // namespace sinks +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/dup_filter_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/dup_filter_sink.h new file mode 100644 index 0000000..1498142 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/dup_filter_sink.h @@ -0,0 +1,92 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include "dist_sink.h" +#include +#include + +#include +#include +#include +#include + +// Duplicate message removal sink. +// Skip the message if previous one is identical and less than "max_skip_duration" have passed +// +// Example: +// +// #include +// +// int main() { +// auto dup_filter = std::make_shared(std::chrono::seconds(5), +// level::info); dup_filter->add_sink(std::make_shared()); +// spdlog::logger l("logger", dup_filter); +// l.info("Hello"); +// l.info("Hello"); +// l.info("Hello"); +// l.info("Different Hello"); +// } +// +// Will produce: +// [2019-06-25 17:50:56.511] [logger] [info] Hello +// [2019-06-25 17:50:56.512] [logger] [info] Skipped 3 duplicate messages.. +// [2019-06-25 17:50:56.512] [logger] [info] Different Hello + +namespace spdlog { +namespace sinks { +template +class dup_filter_sink : public dist_sink { +public: + template + explicit dup_filter_sink(std::chrono::duration max_skip_duration, + level::level_enum notification_level = level::info) + : max_skip_duration_{max_skip_duration}, + log_level_{notification_level} {} + +protected: + std::chrono::microseconds max_skip_duration_; + log_clock::time_point last_msg_time_; + std::string last_msg_payload_; + size_t skip_counter_ = 0; + level::level_enum log_level_; + + void sink_it_(const details::log_msg &msg) override { + bool filtered = filter_(msg); + if (!filtered) { + skip_counter_ += 1; + return; + } + + // log the "skipped.." message + if (skip_counter_ > 0) { + char buf[64]; + auto msg_size = ::snprintf(buf, sizeof(buf), "Skipped %u duplicate messages..", + static_cast(skip_counter_)); + if (msg_size > 0 && static_cast(msg_size) < sizeof(buf)) { + details::log_msg skipped_msg{msg.source, msg.logger_name, log_level_, + string_view_t{buf, static_cast(msg_size)}}; + dist_sink::sink_it_(skipped_msg); + } + } + + // log current message + dist_sink::sink_it_(msg); + last_msg_time_ = msg.time; + skip_counter_ = 0; + last_msg_payload_.assign(msg.payload.data(), msg.payload.data() + msg.payload.size()); + } + + // return whether the log msg should be displayed (true) or skipped (false) + bool filter_(const details::log_msg &msg) { + auto filter_duration = msg.time - last_msg_time_; + return (filter_duration > max_skip_duration_) || (msg.payload != last_msg_payload_); + } +}; + +using dup_filter_sink_mt = dup_filter_sink; +using dup_filter_sink_st = dup_filter_sink; + +} // namespace sinks +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/hourly_file_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/hourly_file_sink.h new file mode 100644 index 0000000..3e61872 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/hourly_file_sink.h @@ -0,0 +1,193 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace spdlog { +namespace sinks { + +/* + * Generator of Hourly log file names in format basename.YYYY-MM-DD-HH.ext + */ +struct hourly_filename_calculator { + // Create filename for the form basename.YYYY-MM-DD-H + static filename_t calc_filename(const filename_t &filename, const tm &now_tm) { + filename_t basename, ext; + std::tie(basename, ext) = details::file_helper::split_by_extension(filename); + return fmt_lib::format(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}{}"), basename, + now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, + now_tm.tm_hour, ext); + } +}; + +/* + * Rotating file sink based on time. + * If truncate != false , the created file will be truncated. + * If max_files > 0, retain only the last max_files and delete previous. + * Note that old log files from previous executions will not be deleted by this class, + * rotation and deletion is only applied while the program is running. + */ +template +class hourly_file_sink final : public base_sink { +public: + // create hourly file sink which rotates on given time + hourly_file_sink(filename_t base_filename, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) + : base_filename_(std::move(base_filename)), + file_helper_{event_handlers}, + truncate_(truncate), + max_files_(max_files), + filenames_q_() { + auto now = log_clock::now(); + auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now)); + file_helper_.open(filename, truncate_); + remove_init_file_ = file_helper_.size() == 0; + rotation_tp_ = next_rotation_tp_(); + + if (max_files_ > 0) { + init_filenames_q_(); + } + } + + filename_t filename() { + std::lock_guard lock(base_sink::mutex_); + return file_helper_.filename(); + } + +protected: + void sink_it_(const details::log_msg &msg) override { + auto time = msg.time; + bool should_rotate = time >= rotation_tp_; + if (should_rotate) { + if (remove_init_file_) { + file_helper_.close(); + details::os::remove(file_helper_.filename()); + } + auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(time)); + file_helper_.open(filename, truncate_); + rotation_tp_ = next_rotation_tp_(); + } + remove_init_file_ = false; + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + file_helper_.write(formatted); + + // Do the cleaning only at the end because it might throw on failure. + if (should_rotate && max_files_ > 0) { + delete_old_(); + } + } + + void flush_() override { file_helper_.flush(); } + +private: + void init_filenames_q_() { + using details::os::path_exists; + + filenames_q_ = details::circular_q(static_cast(max_files_)); + std::vector filenames; + auto now = log_clock::now(); + while (filenames.size() < max_files_) { + auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now)); + if (!path_exists(filename)) { + break; + } + filenames.emplace_back(filename); + now -= std::chrono::hours(1); + } + for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter) { + filenames_q_.push_back(std::move(*iter)); + } + } + + tm now_tm(log_clock::time_point tp) { + time_t tnow = log_clock::to_time_t(tp); + return spdlog::details::os::localtime(tnow); + } + + log_clock::time_point next_rotation_tp_() { + auto now = log_clock::now(); + tm date = now_tm(now); + date.tm_min = 0; + date.tm_sec = 0; + auto rotation_time = log_clock::from_time_t(std::mktime(&date)); + if (rotation_time > now) { + return rotation_time; + } + return {rotation_time + std::chrono::hours(1)}; + } + + // Delete the file N rotations ago. + // Throw spdlog_ex on failure to delete the old file. + void delete_old_() { + using details::os::filename_to_str; + using details::os::remove_if_exists; + + filename_t current_file = file_helper_.filename(); + if (filenames_q_.full()) { + auto old_filename = std::move(filenames_q_.front()); + filenames_q_.pop_front(); + bool ok = remove_if_exists(old_filename) == 0; + if (!ok) { + filenames_q_.push_back(std::move(current_file)); + SPDLOG_THROW(spdlog_ex( + "Failed removing hourly file " + filename_to_str(old_filename), errno)); + } + } + filenames_q_.push_back(std::move(current_file)); + } + + filename_t base_filename_; + log_clock::time_point rotation_tp_; + details::file_helper file_helper_; + bool truncate_; + uint16_t max_files_; + details::circular_q filenames_q_; + bool remove_init_file_; +}; + +using hourly_file_sink_mt = hourly_file_sink; +using hourly_file_sink_st = hourly_file_sink; + +} // namespace sinks + +// +// factory functions +// +template +inline std::shared_ptr hourly_logger_mt(const std::string &logger_name, + const filename_t &filename, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) { + return Factory::template create(logger_name, filename, truncate, + max_files, event_handlers); +} + +template +inline std::shared_ptr hourly_logger_st(const std::string &logger_name, + const filename_t &filename, + bool truncate = false, + uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) { + return Factory::template create(logger_name, filename, truncate, + max_files, event_handlers); +} +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/kafka_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/kafka_sink.h new file mode 100644 index 0000000..91e9878 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/kafka_sink.h @@ -0,0 +1,119 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// +// Custom sink for kafka +// Building and using requires librdkafka library. +// For building librdkafka library check the url below +// https://github.com/confluentinc/librdkafka +// + +#include "spdlog/async.h" +#include "spdlog/details/log_msg.h" +#include "spdlog/details/null_mutex.h" +#include "spdlog/details/synchronous_factory.h" +#include "spdlog/sinks/base_sink.h" +#include +#include + +// kafka header +#include + +namespace spdlog { +namespace sinks { + +struct kafka_sink_config { + std::string server_addr; + std::string produce_topic; + int32_t flush_timeout_ms = 1000; + + kafka_sink_config(std::string addr, std::string topic, int flush_timeout_ms = 1000) + : server_addr{std::move(addr)}, + produce_topic{std::move(topic)}, + flush_timeout_ms(flush_timeout_ms) {} +}; + +template +class kafka_sink : public base_sink { +public: + kafka_sink(kafka_sink_config config) + : config_{std::move(config)} { + try { + std::string errstr; + conf_.reset(RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL)); + RdKafka::Conf::ConfResult confRes = + conf_->set("bootstrap.servers", config_.server_addr, errstr); + if (confRes != RdKafka::Conf::CONF_OK) { + throw_spdlog_ex( + fmt_lib::format("conf set bootstrap.servers failed err:{}", errstr)); + } + + tconf_.reset(RdKafka::Conf::create(RdKafka::Conf::CONF_TOPIC)); + if (tconf_ == nullptr) { + throw_spdlog_ex(fmt_lib::format("create topic config failed")); + } + + producer_.reset(RdKafka::Producer::create(conf_.get(), errstr)); + if (producer_ == nullptr) { + throw_spdlog_ex(fmt_lib::format("create producer failed err:{}", errstr)); + } + topic_.reset(RdKafka::Topic::create(producer_.get(), config_.produce_topic, + tconf_.get(), errstr)); + if (topic_ == nullptr) { + throw_spdlog_ex(fmt_lib::format("create topic failed err:{}", errstr)); + } + } catch (const std::exception &e) { + throw_spdlog_ex(fmt_lib::format("error create kafka instance: {}", e.what())); + } + } + + ~kafka_sink() { producer_->flush(config_.flush_timeout_ms); } + +protected: + void sink_it_(const details::log_msg &msg) override { + producer_->produce(topic_.get(), 0, RdKafka::Producer::RK_MSG_COPY, + (void *)msg.payload.data(), msg.payload.size(), NULL, NULL); + } + + void flush_() override { producer_->flush(config_.flush_timeout_ms); } + +private: + kafka_sink_config config_; + std::unique_ptr producer_ = nullptr; + std::unique_ptr conf_ = nullptr; + std::unique_ptr tconf_ = nullptr; + std::unique_ptr topic_ = nullptr; +}; + +using kafka_sink_mt = kafka_sink; +using kafka_sink_st = kafka_sink; + +} // namespace sinks + +template +inline std::shared_ptr kafka_logger_mt(const std::string &logger_name, + spdlog::sinks::kafka_sink_config config) { + return Factory::template create(logger_name, config); +} + +template +inline std::shared_ptr kafka_logger_st(const std::string &logger_name, + spdlog::sinks::kafka_sink_config config) { + return Factory::template create(logger_name, config); +} + +template +inline std::shared_ptr kafka_logger_async_mt( + std::string logger_name, spdlog::sinks::kafka_sink_config config) { + return Factory::template create(logger_name, config); +} + +template +inline std::shared_ptr kafka_logger_async_st( + std::string logger_name, spdlog::sinks::kafka_sink_config config) { + return Factory::template create(logger_name, config); +} + +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/mongo_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/mongo_sink.h new file mode 100644 index 0000000..c5b38ab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/mongo_sink.h @@ -0,0 +1,108 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// +// Custom sink for mongodb +// Building and using requires mongocxx library. +// For building mongocxx library check the url below +// http://mongocxx.org/mongocxx-v3/installation/ +// + +#include "spdlog/common.h" +#include "spdlog/details/log_msg.h" +#include "spdlog/sinks/base_sink.h" +#include + +#include +#include +#include + +#include +#include +#include + +namespace spdlog { +namespace sinks { +template +class mongo_sink : public base_sink { +public: + mongo_sink(const std::string &db_name, + const std::string &collection_name, + const std::string &uri = "mongodb://localhost:27017") try + : mongo_sink(std::make_shared(), db_name, collection_name, uri) { + } catch (const std::exception &e) { + throw_spdlog_ex(fmt_lib::format("Error opening database: {}", e.what())); + } + + mongo_sink(std::shared_ptr instance, + const std::string &db_name, + const std::string &collection_name, + const std::string &uri = "mongodb://localhost:27017") + : instance_(std::move(instance)), + db_name_(db_name), + coll_name_(collection_name) { + try { + client_ = spdlog::details::make_unique(mongocxx::uri{uri}); + } catch (const std::exception &e) { + throw_spdlog_ex(fmt_lib::format("Error opening database: {}", e.what())); + } + } + + ~mongo_sink() { flush_(); } + +protected: + void sink_it_(const details::log_msg &msg) override { + using bsoncxx::builder::stream::document; + using bsoncxx::builder::stream::finalize; + + if (client_ != nullptr) { + auto doc = document{} << "timestamp" << bsoncxx::types::b_date(msg.time) << "level" + << level::to_string_view(msg.level).data() << "level_num" + << msg.level << "message" + << std::string(msg.payload.begin(), msg.payload.end()) + << "logger_name" + << std::string(msg.logger_name.begin(), msg.logger_name.end()) + << "thread_id" << static_cast(msg.thread_id) << finalize; + client_->database(db_name_).collection(coll_name_).insert_one(doc.view()); + } + } + + void flush_() override {} + +private: + std::shared_ptr instance_; + std::string db_name_; + std::string coll_name_; + std::unique_ptr client_ = nullptr; +}; + +#include "spdlog/details/null_mutex.h" +#include +using mongo_sink_mt = mongo_sink; +using mongo_sink_st = mongo_sink; + +} // namespace sinks + +template +inline std::shared_ptr mongo_logger_mt( + const std::string &logger_name, + const std::string &db_name, + const std::string &collection_name, + const std::string &uri = "mongodb://localhost:27017") { + return Factory::template create(logger_name, db_name, collection_name, + uri); +} + +template +inline std::shared_ptr mongo_logger_st( + const std::string &logger_name, + const std::string &db_name, + const std::string &collection_name, + const std::string &uri = "mongodb://localhost:27017") { + return Factory::template create(logger_name, db_name, collection_name, + uri); +} + +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/msvc_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/msvc_sink.h new file mode 100644 index 0000000..c28d6eb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/msvc_sink.h @@ -0,0 +1,68 @@ +// Copyright(c) 2016 Alexander Dalshov & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#if defined(_WIN32) + + #include + #if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) + #include + #endif + #include + + #include + #include + + // Avoid including windows.h (https://stackoverflow.com/a/30741042) + #if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +extern "C" __declspec(dllimport) void __stdcall OutputDebugStringW(const wchar_t *lpOutputString); + #else +extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char *lpOutputString); + #endif +extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + +namespace spdlog { +namespace sinks { +/* + * MSVC sink (logging using OutputDebugStringA) + */ +template +class msvc_sink : public base_sink { +public: + msvc_sink() = default; + msvc_sink(bool check_debugger_present) + : check_debugger_present_{check_debugger_present} {} + +protected: + void sink_it_(const details::log_msg &msg) override { + if (check_debugger_present_ && !IsDebuggerPresent()) { + return; + } + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + formatted.push_back('\0'); // add a null terminator for OutputDebugString + #if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) + wmemory_buf_t wformatted; + details::os::utf8_to_wstrbuf(string_view_t(formatted.data(), formatted.size()), wformatted); + OutputDebugStringW(wformatted.data()); + #else + OutputDebugStringA(formatted.data()); + #endif + } + + void flush_() override {} + + bool check_debugger_present_ = true; +}; + +using msvc_sink_mt = msvc_sink; +using msvc_sink_st = msvc_sink; + +using windebug_sink_mt = msvc_sink_mt; +using windebug_sink_st = msvc_sink_st; + +} // namespace sinks +} // namespace spdlog + +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/null_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/null_sink.h new file mode 100644 index 0000000..c51247f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/null_sink.h @@ -0,0 +1,41 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include + +#include + +namespace spdlog { +namespace sinks { + +template +class null_sink : public base_sink { +protected: + void sink_it_(const details::log_msg &) override {} + void flush_() override {} +}; + +using null_sink_mt = null_sink; +using null_sink_st = null_sink; + +} // namespace sinks + +template +inline std::shared_ptr null_logger_mt(const std::string &logger_name) { + auto null_logger = Factory::template create(logger_name); + null_logger->set_level(level::off); + return null_logger; +} + +template +inline std::shared_ptr null_logger_st(const std::string &logger_name) { + auto null_logger = Factory::template create(logger_name); + null_logger->set_level(level::off); + return null_logger; +} + +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ostream_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ostream_sink.h new file mode 100644 index 0000000..6af9dd0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ostream_sink.h @@ -0,0 +1,43 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +#include +#include + +namespace spdlog { +namespace sinks { +template +class ostream_sink final : public base_sink { +public: + explicit ostream_sink(std::ostream &os, bool force_flush = false) + : ostream_(os), + force_flush_(force_flush) {} + ostream_sink(const ostream_sink &) = delete; + ostream_sink &operator=(const ostream_sink &) = delete; + +protected: + void sink_it_(const details::log_msg &msg) override { + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + ostream_.write(formatted.data(), static_cast(formatted.size())); + if (force_flush_) { + ostream_.flush(); + } + } + + void flush_() override { ostream_.flush(); } + + std::ostream &ostream_; + bool force_flush_; +}; + +using ostream_sink_mt = ostream_sink; +using ostream_sink_st = ostream_sink; + +} // namespace sinks +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/qt_sinks.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/qt_sinks.h new file mode 100644 index 0000000..d319e84 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/qt_sinks.h @@ -0,0 +1,304 @@ +// Copyright(c) 2015-present, Gabi Melman, mguludag and spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// +// Custom sink for QPlainTextEdit or QTextEdit and its children (QTextBrowser... +// etc) Building and using requires Qt library. +// +// Warning: the qt_sink won't be notified if the target widget is destroyed. +// If the widget's lifetime can be shorter than the logger's one, you should provide some permanent +// QObject, and then use a standard signal/slot. +// + +#include "spdlog/common.h" +#include "spdlog/details/log_msg.h" +#include "spdlog/details/synchronous_factory.h" +#include "spdlog/sinks/base_sink.h" +#include + +#include +#include + +// +// qt_sink class +// +namespace spdlog { +namespace sinks { +template +class qt_sink : public base_sink { +public: + qt_sink(QObject *qt_object, std::string meta_method) + : qt_object_(qt_object), + meta_method_(std::move(meta_method)) { + if (!qt_object_) { + throw_spdlog_ex("qt_sink: qt_object is null"); + } + } + + ~qt_sink() { flush_(); } + +protected: + void sink_it_(const details::log_msg &msg) override { + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + const string_view_t str = string_view_t(formatted.data(), formatted.size()); + QMetaObject::invokeMethod( + qt_object_, meta_method_.c_str(), Qt::AutoConnection, + Q_ARG(QString, QString::fromUtf8(str.data(), static_cast(str.size())).trimmed())); + } + + void flush_() override {} + +private: + QObject *qt_object_ = nullptr; + std::string meta_method_; +}; + +// Qt color sink to QTextEdit. +// Color location is determined by the sink log pattern like in the rest of spdlog sinks. +// Colors can be modified if needed using sink->set_color(level, qtTextCharFormat). +// max_lines is the maximum number of lines that the sink will hold before removing the oldest +// lines. By default, only ascii (latin1) is supported by this sink. Set is_utf8 to true if utf8 +// support is needed. +template +class qt_color_sink : public base_sink { +public: + qt_color_sink(QTextEdit *qt_text_edit, + int max_lines, + bool dark_colors = false, + bool is_utf8 = false) + : qt_text_edit_(qt_text_edit), + max_lines_(max_lines), + is_utf8_(is_utf8) { + if (!qt_text_edit_) { + throw_spdlog_ex("qt_color_text_sink: text_edit is null"); + } + + default_color_ = qt_text_edit_->currentCharFormat(); + // set colors + QTextCharFormat format; + // trace + format.setForeground(dark_colors ? Qt::darkGray : Qt::gray); + colors_.at(level::trace) = format; + // debug + format.setForeground(dark_colors ? Qt::darkCyan : Qt::cyan); + colors_.at(level::debug) = format; + // info + format.setForeground(dark_colors ? Qt::darkGreen : Qt::green); + colors_.at(level::info) = format; + // warn + format.setForeground(dark_colors ? Qt::darkYellow : Qt::yellow); + colors_.at(level::warn) = format; + // err + format.setForeground(Qt::red); + colors_.at(level::err) = format; + // critical + format.setForeground(Qt::white); + format.setBackground(Qt::red); + colors_.at(level::critical) = format; + } + + ~qt_color_sink() { flush_(); } + + void set_default_color(QTextCharFormat format) { + // std::lock_guard lock(base_sink::mutex_); + default_color_ = format; + } + + void set_level_color(level::level_enum color_level, QTextCharFormat format) { + // std::lock_guard lock(base_sink::mutex_); + colors_.at(static_cast(color_level)) = format; + } + + QTextCharFormat &get_level_color(level::level_enum color_level) { + std::lock_guard lock(base_sink::mutex_); + return colors_.at(static_cast(color_level)); + } + + QTextCharFormat &get_default_color() { + std::lock_guard lock(base_sink::mutex_); + return default_color_; + } + +protected: + struct invoke_params { + invoke_params(int max_lines, + QTextEdit *q_text_edit, + QString payload, + QTextCharFormat default_color, + QTextCharFormat level_color, + int color_range_start, + int color_range_end) + : max_lines(max_lines), + q_text_edit(q_text_edit), + payload(std::move(payload)), + default_color(default_color), + level_color(level_color), + color_range_start(color_range_start), + color_range_end(color_range_end) {} + int max_lines; + QTextEdit *q_text_edit; + QString payload; + QTextCharFormat default_color; + QTextCharFormat level_color; + int color_range_start; + int color_range_end; + }; + + void sink_it_(const details::log_msg &msg) override { + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + + const string_view_t str = string_view_t(formatted.data(), formatted.size()); + // apply the color to the color range in the formatted message. + QString payload; + int color_range_start = static_cast(msg.color_range_start); + int color_range_end = static_cast(msg.color_range_end); + if (is_utf8_) { + payload = QString::fromUtf8(str.data(), static_cast(str.size())); + // convert color ranges from byte index to character index. + if (msg.color_range_start < msg.color_range_end) { + color_range_start = QString::fromUtf8(str.data(), msg.color_range_start).size(); + color_range_end = QString::fromUtf8(str.data(), msg.color_range_end).size(); + } + } else { + payload = QString::fromLatin1(str.data(), static_cast(str.size())); + } + + invoke_params params{max_lines_, // max lines + qt_text_edit_, // text edit to append to + std::move(payload), // text to append + default_color_, // default color + colors_.at(msg.level), // color to apply + color_range_start, // color range start + color_range_end}; // color range end + + QMetaObject::invokeMethod( + qt_text_edit_, [params]() { invoke_method_(params); }, Qt::AutoConnection); + } + + void flush_() override {} + + // Add colored text to the text edit widget. This method is invoked in the GUI thread. + // It is a static method to ensure that it is handled correctly even if the sink is destroyed + // prematurely before it is invoked. + + static void invoke_method_(invoke_params params) { + auto *document = params.q_text_edit->document(); + QTextCursor cursor(document); + + // remove first blocks if number of blocks exceeds max_lines + while (document->blockCount() > params.max_lines) { + cursor.select(QTextCursor::BlockUnderCursor); + cursor.removeSelectedText(); + cursor.deleteChar(); // delete the newline after the block + } + + cursor.movePosition(QTextCursor::End); + cursor.setCharFormat(params.default_color); + + // if color range not specified or not not valid, just append the text with default color + if (params.color_range_end <= params.color_range_start) { + cursor.insertText(params.payload); + return; + } + + // insert the text before the color range + cursor.insertText(params.payload.left(params.color_range_start)); + + // insert the colorized text + cursor.setCharFormat(params.level_color); + cursor.insertText(params.payload.mid(params.color_range_start, + params.color_range_end - params.color_range_start)); + + // insert the text after the color range with default format + cursor.setCharFormat(params.default_color); + cursor.insertText(params.payload.mid(params.color_range_end)); + } + + QTextEdit *qt_text_edit_; + int max_lines_; + bool is_utf8_; + QTextCharFormat default_color_; + std::array colors_; +}; + +#include "spdlog/details/null_mutex.h" +#include + +using qt_sink_mt = qt_sink; +using qt_sink_st = qt_sink; +using qt_color_sink_mt = qt_color_sink; +using qt_color_sink_st = qt_color_sink; +} // namespace sinks + +// +// Factory functions +// + +// log to QTextEdit +template +inline std::shared_ptr qt_logger_mt(const std::string &logger_name, + QTextEdit *qt_object, + const std::string &meta_method = "append") { + return Factory::template create(logger_name, qt_object, meta_method); +} + +template +inline std::shared_ptr qt_logger_st(const std::string &logger_name, + QTextEdit *qt_object, + const std::string &meta_method = "append") { + return Factory::template create(logger_name, qt_object, meta_method); +} + +// log to QPlainTextEdit +template +inline std::shared_ptr qt_logger_mt(const std::string &logger_name, + QPlainTextEdit *qt_object, + const std::string &meta_method = "appendPlainText") { + return Factory::template create(logger_name, qt_object, meta_method); +} + +template +inline std::shared_ptr qt_logger_st(const std::string &logger_name, + QPlainTextEdit *qt_object, + const std::string &meta_method = "appendPlainText") { + return Factory::template create(logger_name, qt_object, meta_method); +} +// log to QObject +template +inline std::shared_ptr qt_logger_mt(const std::string &logger_name, + QObject *qt_object, + const std::string &meta_method) { + return Factory::template create(logger_name, qt_object, meta_method); +} + +template +inline std::shared_ptr qt_logger_st(const std::string &logger_name, + QObject *qt_object, + const std::string &meta_method) { + return Factory::template create(logger_name, qt_object, meta_method); +} + +// log to QTextEdit with colorized output +template +inline std::shared_ptr qt_color_logger_mt(const std::string &logger_name, + QTextEdit *qt_text_edit, + int max_lines, + bool is_utf8 = false) { + return Factory::template create(logger_name, qt_text_edit, max_lines, + false, is_utf8); +} + +template +inline std::shared_ptr qt_color_logger_st(const std::string &logger_name, + QTextEdit *qt_text_edit, + int max_lines, + bool is_utf8 = false) { + return Factory::template create(logger_name, qt_text_edit, max_lines, + false, is_utf8); +} + +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ringbuffer_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ringbuffer_sink.h new file mode 100644 index 0000000..6156c6a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ringbuffer_sink.h @@ -0,0 +1,67 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include "spdlog/details/circular_q.h" +#include "spdlog/details/log_msg_buffer.h" +#include "spdlog/details/null_mutex.h" +#include "spdlog/sinks/base_sink.h" + +#include +#include +#include + +namespace spdlog { +namespace sinks { +/* + * Ring buffer sink + */ +template +class ringbuffer_sink final : public base_sink { +public: + explicit ringbuffer_sink(size_t n_items) + : q_{n_items} {} + + std::vector last_raw(size_t lim = 0) { + std::lock_guard lock(base_sink::mutex_); + auto items_available = q_.size(); + auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available; + std::vector ret; + ret.reserve(n_items); + for (size_t i = (items_available - n_items); i < items_available; i++) { + ret.push_back(q_.at(i)); + } + return ret; + } + + std::vector last_formatted(size_t lim = 0) { + std::lock_guard lock(base_sink::mutex_); + auto items_available = q_.size(); + auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available; + std::vector ret; + ret.reserve(n_items); + for (size_t i = (items_available - n_items); i < items_available; i++) { + memory_buf_t formatted; + base_sink::formatter_->format(q_.at(i), formatted); + ret.push_back(SPDLOG_BUF_TO_STRING(formatted)); + } + return ret; + } + +protected: + void sink_it_(const details::log_msg &msg) override { + q_.push_back(details::log_msg_buffer{msg}); + } + void flush_() override {} + +private: + details::circular_q q_; +}; + +using ringbuffer_sink_mt = ringbuffer_sink; +using ringbuffer_sink_st = ringbuffer_sink; + +} // namespace sinks + +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/rotating_file_sink-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/rotating_file_sink-inl.h new file mode 100644 index 0000000..bf9351e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/rotating_file_sink-inl.h @@ -0,0 +1,144 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace spdlog { +namespace sinks { + +template +SPDLOG_INLINE rotating_file_sink::rotating_file_sink( + filename_t base_filename, + std::size_t max_size, + std::size_t max_files, + bool rotate_on_open, + const file_event_handlers &event_handlers) + : base_filename_(std::move(base_filename)), + max_size_(max_size), + max_files_(max_files), + file_helper_{event_handlers} { + if (max_size == 0) { + throw_spdlog_ex("rotating sink constructor: max_size arg cannot be zero"); + } + + if (max_files > 200000) { + throw_spdlog_ex("rotating sink constructor: max_files arg cannot exceed 200000"); + } + file_helper_.open(calc_filename(base_filename_, 0)); + current_size_ = file_helper_.size(); // expensive. called only once + if (rotate_on_open && current_size_ > 0) { + rotate_(); + current_size_ = 0; + } +} + +// calc filename according to index and file extension if exists. +// e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt". +template +SPDLOG_INLINE filename_t rotating_file_sink::calc_filename(const filename_t &filename, + std::size_t index) { + if (index == 0u) { + return filename; + } + + filename_t basename, ext; + std::tie(basename, ext) = details::file_helper::split_by_extension(filename); + return fmt_lib::format(SPDLOG_FMT_STRING(SPDLOG_FILENAME_T("{}.{}{}")), basename, index, ext); +} + +template +SPDLOG_INLINE filename_t rotating_file_sink::filename() { + std::lock_guard lock(base_sink::mutex_); + return file_helper_.filename(); +} + +template +SPDLOG_INLINE void rotating_file_sink::sink_it_(const details::log_msg &msg) { + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + auto new_size = current_size_ + formatted.size(); + + // rotate if the new estimated file size exceeds max size. + // rotate only if the real size > 0 to better deal with full disk (see issue #2261). + // we only check the real size when new_size > max_size_ because it is relatively expensive. + if (new_size > max_size_) { + file_helper_.flush(); + if (file_helper_.size() > 0) { + rotate_(); + new_size = formatted.size(); + } + } + file_helper_.write(formatted); + current_size_ = new_size; +} + +template +SPDLOG_INLINE void rotating_file_sink::flush_() { + file_helper_.flush(); +} + +// Rotate files: +// log.txt -> log.1.txt +// log.1.txt -> log.2.txt +// log.2.txt -> log.3.txt +// log.3.txt -> delete +template +SPDLOG_INLINE void rotating_file_sink::rotate_() { + using details::os::filename_to_str; + using details::os::path_exists; + + file_helper_.close(); + for (auto i = max_files_; i > 0; --i) { + filename_t src = calc_filename(base_filename_, i - 1); + if (!path_exists(src)) { + continue; + } + filename_t target = calc_filename(base_filename_, i); + + if (!rename_file_(src, target)) { + // if failed try again after a small delay. + // this is a workaround to a windows issue, where very high rotation + // rates can cause the rename to fail with permission denied (because of antivirus?). + details::os::sleep_for_millis(100); + if (!rename_file_(src, target)) { + file_helper_.reopen( + true); // truncate the log file anyway to prevent it to grow beyond its limit! + current_size_ = 0; + throw_spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + + " to " + filename_to_str(target), + errno); + } + } + } + file_helper_.reopen(true); +} + +// delete the target if exists, and rename the src file to target +// return true on success, false otherwise. +template +SPDLOG_INLINE bool rotating_file_sink::rename_file_(const filename_t &src_filename, + const filename_t &target_filename) { + // try to delete the target file in case it already exists. + (void)details::os::remove(target_filename); + return details::os::rename(src_filename, target_filename) == 0; +} + +} // namespace sinks +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/rotating_file_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/rotating_file_sink.h new file mode 100644 index 0000000..cd43d34 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/rotating_file_sink.h @@ -0,0 +1,89 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace spdlog { +namespace sinks { + +// +// Rotating file sink based on size +// +template +class rotating_file_sink final : public base_sink { +public: + rotating_file_sink(filename_t base_filename, + std::size_t max_size, + std::size_t max_files, + bool rotate_on_open = false, + const file_event_handlers &event_handlers = {}); + static filename_t calc_filename(const filename_t &filename, std::size_t index); + filename_t filename(); + +protected: + void sink_it_(const details::log_msg &msg) override; + void flush_() override; + +private: + // Rotate files: + // log.txt -> log.1.txt + // log.1.txt -> log.2.txt + // log.2.txt -> log.3.txt + // log.3.txt -> delete + void rotate_(); + + // delete the target if exists, and rename the src file to target + // return true on success, false otherwise. + bool rename_file_(const filename_t &src_filename, const filename_t &target_filename); + + filename_t base_filename_; + std::size_t max_size_; + std::size_t max_files_; + std::size_t current_size_; + details::file_helper file_helper_; +}; + +using rotating_file_sink_mt = rotating_file_sink; +using rotating_file_sink_st = rotating_file_sink; + +} // namespace sinks + +// +// factory functions +// + +template +inline std::shared_ptr rotating_logger_mt(const std::string &logger_name, + const filename_t &filename, + size_t max_file_size, + size_t max_files, + bool rotate_on_open = false, + const file_event_handlers &event_handlers = {}) { + return Factory::template create( + logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); +} + +template +inline std::shared_ptr rotating_logger_st(const std::string &logger_name, + const filename_t &filename, + size_t max_file_size, + size_t max_files, + bool rotate_on_open = false, + const file_event_handlers &event_handlers = {}) { + return Factory::template create( + logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); +} +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "rotating_file_sink-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/sink-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/sink-inl.h new file mode 100644 index 0000000..e4b2714 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/sink-inl.h @@ -0,0 +1,22 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include + +SPDLOG_INLINE bool spdlog::sinks::sink::should_log(spdlog::level::level_enum msg_level) const { + return msg_level >= level_.load(std::memory_order_relaxed); +} + +SPDLOG_INLINE void spdlog::sinks::sink::set_level(level::level_enum log_level) { + level_.store(log_level, std::memory_order_relaxed); +} + +SPDLOG_INLINE spdlog::level::level_enum spdlog::sinks::sink::level() const { + return static_cast(level_.load(std::memory_order_relaxed)); +} diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/sink.h new file mode 100644 index 0000000..5850685 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/sink.h @@ -0,0 +1,34 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +namespace spdlog { + +namespace sinks { +class SPDLOG_API sink { +public: + virtual ~sink() = default; + virtual void log(const details::log_msg &msg) = 0; + virtual void flush() = 0; + virtual void set_pattern(const std::string &pattern) = 0; + virtual void set_formatter(std::unique_ptr sink_formatter) = 0; + + void set_level(level::level_enum log_level); + level::level_enum level() const; + bool should_log(level::level_enum msg_level) const; + +protected: + // sink log level - default is all + level_t level_{level::trace}; +}; + +} // namespace sinks +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "sink-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_color_sinks-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_color_sinks-inl.h new file mode 100644 index 0000000..166e386 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_color_sinks-inl.h @@ -0,0 +1,38 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +namespace spdlog { + +template +SPDLOG_INLINE std::shared_ptr stdout_color_mt(const std::string &logger_name, + color_mode mode) { + return Factory::template create(logger_name, mode); +} + +template +SPDLOG_INLINE std::shared_ptr stdout_color_st(const std::string &logger_name, + color_mode mode) { + return Factory::template create(logger_name, mode); +} + +template +SPDLOG_INLINE std::shared_ptr stderr_color_mt(const std::string &logger_name, + color_mode mode) { + return Factory::template create(logger_name, mode); +} + +template +SPDLOG_INLINE std::shared_ptr stderr_color_st(const std::string &logger_name, + color_mode mode) { + return Factory::template create(logger_name, mode); +} +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_color_sinks.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_color_sinks.h new file mode 100644 index 0000000..72991fe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_color_sinks.h @@ -0,0 +1,49 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifdef _WIN32 + #include +#else + #include +#endif + +#include + +namespace spdlog { +namespace sinks { +#ifdef _WIN32 +using stdout_color_sink_mt = wincolor_stdout_sink_mt; +using stdout_color_sink_st = wincolor_stdout_sink_st; +using stderr_color_sink_mt = wincolor_stderr_sink_mt; +using stderr_color_sink_st = wincolor_stderr_sink_st; +#else +using stdout_color_sink_mt = ansicolor_stdout_sink_mt; +using stdout_color_sink_st = ansicolor_stdout_sink_st; +using stderr_color_sink_mt = ansicolor_stderr_sink_mt; +using stderr_color_sink_st = ansicolor_stderr_sink_st; +#endif +} // namespace sinks + +template +std::shared_ptr stdout_color_mt(const std::string &logger_name, + color_mode mode = color_mode::automatic); + +template +std::shared_ptr stdout_color_st(const std::string &logger_name, + color_mode mode = color_mode::automatic); + +template +std::shared_ptr stderr_color_mt(const std::string &logger_name, + color_mode mode = color_mode::automatic); + +template +std::shared_ptr stderr_color_st(const std::string &logger_name, + color_mode mode = color_mode::automatic); + +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "stdout_color_sinks-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_sinks-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_sinks-inl.h new file mode 100644 index 0000000..f98244d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_sinks-inl.h @@ -0,0 +1,126 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include +#include + +#ifdef _WIN32 + // under windows using fwrite to non-binary stream results in \r\r\n (see issue #1675) + // so instead we use ::FileWrite + #include + + #ifndef _USING_V110_SDK71_ // fileapi.h doesn't exist in winxp + #include // WriteFile (..) + #endif + + #include // _get_osfhandle(..) + #include // _fileno(..) +#endif // WIN32 + +namespace spdlog { + +namespace sinks { + +template +SPDLOG_INLINE stdout_sink_base::stdout_sink_base(FILE *file) + : mutex_(ConsoleMutex::mutex()), + file_(file), + formatter_(details::make_unique()) { +#ifdef _WIN32 + // get windows handle from the FILE* object + + handle_ = reinterpret_cast(::_get_osfhandle(::_fileno(file_))); + + // don't throw to support cases where no console is attached, + // and let the log method to do nothing if (handle_ == INVALID_HANDLE_VALUE). + // throw only if non stdout/stderr target is requested (probably regular file and not console). + if (handle_ == INVALID_HANDLE_VALUE && file != stdout && file != stderr) { + throw_spdlog_ex("spdlog::stdout_sink_base: _get_osfhandle() failed", errno); + } +#endif // WIN32 +} + +template +SPDLOG_INLINE void stdout_sink_base::log(const details::log_msg &msg) { +#ifdef _WIN32 + if (handle_ == INVALID_HANDLE_VALUE) { + return; + } + std::lock_guard lock(mutex_); + memory_buf_t formatted; + formatter_->format(msg, formatted); + auto size = static_cast(formatted.size()); + DWORD bytes_written = 0; + bool ok = ::WriteFile(handle_, formatted.data(), size, &bytes_written, nullptr) != 0; + if (!ok) { + throw_spdlog_ex("stdout_sink_base: WriteFile() failed. GetLastError(): " + + std::to_string(::GetLastError())); + } +#else + std::lock_guard lock(mutex_); + memory_buf_t formatted; + formatter_->format(msg, formatted); + ::fwrite(formatted.data(), sizeof(char), formatted.size(), file_); +#endif // WIN32 + ::fflush(file_); // flush every line to terminal +} + +template +SPDLOG_INLINE void stdout_sink_base::flush() { + std::lock_guard lock(mutex_); + fflush(file_); +} + +template +SPDLOG_INLINE void stdout_sink_base::set_pattern(const std::string &pattern) { + std::lock_guard lock(mutex_); + formatter_ = std::unique_ptr(new pattern_formatter(pattern)); +} + +template +SPDLOG_INLINE void stdout_sink_base::set_formatter( + std::unique_ptr sink_formatter) { + std::lock_guard lock(mutex_); + formatter_ = std::move(sink_formatter); +} + +// stdout sink +template +SPDLOG_INLINE stdout_sink::stdout_sink() + : stdout_sink_base(stdout) {} + +// stderr sink +template +SPDLOG_INLINE stderr_sink::stderr_sink() + : stdout_sink_base(stderr) {} + +} // namespace sinks + +// factory methods +template +SPDLOG_INLINE std::shared_ptr stdout_logger_mt(const std::string &logger_name) { + return Factory::template create(logger_name); +} + +template +SPDLOG_INLINE std::shared_ptr stdout_logger_st(const std::string &logger_name) { + return Factory::template create(logger_name); +} + +template +SPDLOG_INLINE std::shared_ptr stderr_logger_mt(const std::string &logger_name) { + return Factory::template create(logger_name); +} + +template +SPDLOG_INLINE std::shared_ptr stderr_logger_st(const std::string &logger_name) { + return Factory::template create(logger_name); +} +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_sinks.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_sinks.h new file mode 100644 index 0000000..6ef0996 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_sinks.h @@ -0,0 +1,84 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include + +#ifdef _WIN32 + #include +#endif + +namespace spdlog { + +namespace sinks { + +template +class stdout_sink_base : public sink { +public: + using mutex_t = typename ConsoleMutex::mutex_t; + explicit stdout_sink_base(FILE *file); + ~stdout_sink_base() override = default; + + stdout_sink_base(const stdout_sink_base &other) = delete; + stdout_sink_base(stdout_sink_base &&other) = delete; + + stdout_sink_base &operator=(const stdout_sink_base &other) = delete; + stdout_sink_base &operator=(stdout_sink_base &&other) = delete; + + void log(const details::log_msg &msg) override; + void flush() override; + void set_pattern(const std::string &pattern) override; + + void set_formatter(std::unique_ptr sink_formatter) override; + +protected: + mutex_t &mutex_; + FILE *file_; + std::unique_ptr formatter_; +#ifdef _WIN32 + HANDLE handle_; +#endif // WIN32 +}; + +template +class stdout_sink : public stdout_sink_base { +public: + stdout_sink(); +}; + +template +class stderr_sink : public stdout_sink_base { +public: + stderr_sink(); +}; + +using stdout_sink_mt = stdout_sink; +using stdout_sink_st = stdout_sink; + +using stderr_sink_mt = stderr_sink; +using stderr_sink_st = stderr_sink; + +} // namespace sinks + +// factory methods +template +std::shared_ptr stdout_logger_mt(const std::string &logger_name); + +template +std::shared_ptr stdout_logger_st(const std::string &logger_name); + +template +std::shared_ptr stderr_logger_mt(const std::string &logger_name); + +template +std::shared_ptr stderr_logger_st(const std::string &logger_name); + +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "stdout_sinks-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/syslog_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/syslog_sink.h new file mode 100644 index 0000000..913d41b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/syslog_sink.h @@ -0,0 +1,104 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace spdlog { +namespace sinks { +/** + * Sink that write to syslog using the `syscall()` library call. + */ +template +class syslog_sink : public base_sink { +public: + syslog_sink(std::string ident, int syslog_option, int syslog_facility, bool enable_formatting) + : enable_formatting_{enable_formatting}, + syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG, + /* spdlog::level::debug */ LOG_DEBUG, + /* spdlog::level::info */ LOG_INFO, + /* spdlog::level::warn */ LOG_WARNING, + /* spdlog::level::err */ LOG_ERR, + /* spdlog::level::critical */ LOG_CRIT, + /* spdlog::level::off */ LOG_INFO}}, + ident_{std::move(ident)} { + // set ident to be program name if empty + ::openlog(ident_.empty() ? nullptr : ident_.c_str(), syslog_option, syslog_facility); + } + + ~syslog_sink() override { ::closelog(); } + + syslog_sink(const syslog_sink &) = delete; + syslog_sink &operator=(const syslog_sink &) = delete; + +protected: + void sink_it_(const details::log_msg &msg) override { + string_view_t payload; + memory_buf_t formatted; + if (enable_formatting_) { + base_sink::formatter_->format(msg, formatted); + payload = string_view_t(formatted.data(), formatted.size()); + } else { + payload = msg.payload; + } + + size_t length = payload.size(); + // limit to max int + if (length > static_cast(std::numeric_limits::max())) { + length = static_cast(std::numeric_limits::max()); + } + + ::syslog(syslog_prio_from_level(msg), "%.*s", static_cast(length), payload.data()); + } + + void flush_() override {} + bool enable_formatting_ = false; + + // + // Simply maps spdlog's log level to syslog priority level. + // + virtual int syslog_prio_from_level(const details::log_msg &msg) const { + return syslog_levels_.at(static_cast(msg.level)); + } + + using levels_array = std::array; + levels_array syslog_levels_; + +private: + // must store the ident because the man says openlog might use the pointer as + // is and not a string copy + const std::string ident_; +}; + +using syslog_sink_mt = syslog_sink; +using syslog_sink_st = syslog_sink; +} // namespace sinks + +// Create and register a syslog logger +template +inline std::shared_ptr syslog_logger_mt(const std::string &logger_name, + const std::string &syslog_ident = "", + int syslog_option = 0, + int syslog_facility = LOG_USER, + bool enable_formatting = false) { + return Factory::template create(logger_name, syslog_ident, syslog_option, + syslog_facility, enable_formatting); +} + +template +inline std::shared_ptr syslog_logger_st(const std::string &logger_name, + const std::string &syslog_ident = "", + int syslog_option = 0, + int syslog_facility = LOG_USER, + bool enable_formatting = false) { + return Factory::template create(logger_name, syslog_ident, syslog_option, + syslog_facility, enable_formatting); +} +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/systemd_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/systemd_sink.h new file mode 100644 index 0000000..d2cd55f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/systemd_sink.h @@ -0,0 +1,121 @@ +// Copyright(c) 2019 ZVYAGIN.Alexander@gmail.com +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include + +#include +#ifndef SD_JOURNAL_SUPPRESS_LOCATION + #define SD_JOURNAL_SUPPRESS_LOCATION +#endif +#include + +namespace spdlog { +namespace sinks { + +/** + * Sink that write to systemd journal using the `sd_journal_send()` library call. + */ +template +class systemd_sink : public base_sink { +public: + systemd_sink(std::string ident = "", bool enable_formatting = false) + : ident_{std::move(ident)}, + enable_formatting_{enable_formatting}, + syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG, + /* spdlog::level::debug */ LOG_DEBUG, + /* spdlog::level::info */ LOG_INFO, + /* spdlog::level::warn */ LOG_WARNING, + /* spdlog::level::err */ LOG_ERR, + /* spdlog::level::critical */ LOG_CRIT, + /* spdlog::level::off */ LOG_INFO}} {} + + ~systemd_sink() override {} + + systemd_sink(const systemd_sink &) = delete; + systemd_sink &operator=(const systemd_sink &) = delete; + +protected: + const std::string ident_; + bool enable_formatting_ = false; + using levels_array = std::array; + levels_array syslog_levels_; + + void sink_it_(const details::log_msg &msg) override { + int err; + string_view_t payload; + memory_buf_t formatted; + if (enable_formatting_) { + base_sink::formatter_->format(msg, formatted); + payload = string_view_t(formatted.data(), formatted.size()); + } else { + payload = msg.payload; + } + + size_t length = payload.size(); + // limit to max int + if (length > static_cast(std::numeric_limits::max())) { + length = static_cast(std::numeric_limits::max()); + } + + const string_view_t syslog_identifier = ident_.empty() ? msg.logger_name : ident_; + + // Do not send source location if not available + if (msg.source.empty()) { + // Note: function call inside '()' to avoid macro expansion + err = (sd_journal_send)("MESSAGE=%.*s", static_cast(length), payload.data(), + "PRIORITY=%d", syslog_level(msg.level), +#ifndef SPDLOG_NO_THREAD_ID + "TID=%zu", msg.thread_id, +#endif + "SYSLOG_IDENTIFIER=%.*s", + static_cast(syslog_identifier.size()), + syslog_identifier.data(), nullptr); + } else { + err = (sd_journal_send)("MESSAGE=%.*s", static_cast(length), payload.data(), + "PRIORITY=%d", syslog_level(msg.level), +#ifndef SPDLOG_NO_THREAD_ID + "TID=%zu", msg.thread_id, +#endif + "SYSLOG_IDENTIFIER=%.*s", + static_cast(syslog_identifier.size()), + syslog_identifier.data(), "CODE_FILE=%s", msg.source.filename, + "CODE_LINE=%d", msg.source.line, "CODE_FUNC=%s", + msg.source.funcname, nullptr); + } + + if (err) { + throw_spdlog_ex("Failed writing to systemd", errno); + } + } + + int syslog_level(level::level_enum l) { + return syslog_levels_.at(static_cast(l)); + } + + void flush_() override {} +}; + +using systemd_sink_mt = systemd_sink; +using systemd_sink_st = systemd_sink; +} // namespace sinks + +// Create and register a syslog logger +template +inline std::shared_ptr systemd_logger_mt(const std::string &logger_name, + const std::string &ident = "", + bool enable_formatting = false) { + return Factory::template create(logger_name, ident, enable_formatting); +} + +template +inline std::shared_ptr systemd_logger_st(const std::string &logger_name, + const std::string &ident = "", + bool enable_formatting = false) { + return Factory::template create(logger_name, ident, enable_formatting); +} +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/tcp_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/tcp_sink.h new file mode 100644 index 0000000..2534964 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/tcp_sink.h @@ -0,0 +1,75 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#ifdef _WIN32 + #include +#else + #include +#endif + +#include +#include +#include +#include + +#pragma once + +// Simple tcp client sink +// Connects to remote address and send the formatted log. +// Will attempt to reconnect if connection drops. +// If more complicated behaviour is needed (i.e get responses), you can inherit it and override the +// sink_it_ method. + +namespace spdlog { +namespace sinks { + +struct tcp_sink_config { + std::string server_host; + int server_port; + bool lazy_connect = false; // if true connect on first log call instead of on construction + + tcp_sink_config(std::string host, int port) + : server_host{std::move(host)}, + server_port{port} {} +}; + +template +class tcp_sink : public spdlog::sinks::base_sink { +public: + // connect to tcp host/port or throw if failed + // host can be hostname or ip address + + explicit tcp_sink(tcp_sink_config sink_config) + : config_{std::move(sink_config)} { + if (!config_.lazy_connect) { + this->client_.connect(config_.server_host, config_.server_port); + } + } + + ~tcp_sink() override = default; + +protected: + void sink_it_(const spdlog::details::log_msg &msg) override { + spdlog::memory_buf_t formatted; + spdlog::sinks::base_sink::formatter_->format(msg, formatted); + if (!client_.is_connected()) { + client_.connect(config_.server_host, config_.server_port); + } + client_.send(formatted.data(), formatted.size()); + } + + void flush_() override {} + tcp_sink_config config_; + details::tcp_client client_; +}; + +using tcp_sink_mt = tcp_sink; +using tcp_sink_st = tcp_sink; + +} // namespace sinks +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/udp_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/udp_sink.h new file mode 100644 index 0000000..4bff0fd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/udp_sink.h @@ -0,0 +1,69 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#ifdef _WIN32 + #include +#else + #include +#endif + +#include +#include +#include +#include + +// Simple udp client sink +// Sends formatted log via udp + +namespace spdlog { +namespace sinks { + +struct udp_sink_config { + std::string server_host; + uint16_t server_port; + + udp_sink_config(std::string host, uint16_t port) + : server_host{std::move(host)}, + server_port{port} {} +}; + +template +class udp_sink : public spdlog::sinks::base_sink { +public: + // host can be hostname or ip address + explicit udp_sink(udp_sink_config sink_config) + : client_{sink_config.server_host, sink_config.server_port} {} + + ~udp_sink() override = default; + +protected: + void sink_it_(const spdlog::details::log_msg &msg) override { + spdlog::memory_buf_t formatted; + spdlog::sinks::base_sink::formatter_->format(msg, formatted); + client_.send(formatted.data(), formatted.size()); + } + + void flush_() override {} + details::udp_client client_; +}; + +using udp_sink_mt = udp_sink; +using udp_sink_st = udp_sink; + +} // namespace sinks + +// +// factory functions +// +template +inline std::shared_ptr udp_logger_mt(const std::string &logger_name, + sinks::udp_sink_config skin_config) { + return Factory::template create(logger_name, skin_config); +} + +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/win_eventlog_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/win_eventlog_sink.h new file mode 100644 index 0000000..2c9b582 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/win_eventlog_sink.h @@ -0,0 +1,260 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +// Writing to Windows Event Log requires the registry entries below to be present, with the +// following modifications: +// 1. should be replaced with your log name (e.g. your application name) +// 2. should be replaced with the specific source name and the key should be +// duplicated for +// each source used in the application +// +// Since typically modifications of this kind require elevation, it's better to do it as a part of +// setup procedure. The snippet below uses mscoree.dll as the message file as it exists on most of +// the Windows systems anyway and happens to contain the needed resource. +// +// You can also specify a custom message file if needed. +// Please refer to Event Log functions descriptions in MSDN for more details on custom message +// files. + +/*--------------------------------------------------------------------------------------- + +Windows Registry Editor Version 5.00 + +[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\] + +[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\\] +"TypesSupported"=dword:00000007 +"EventMessageFile"=hex(2):25,00,73,00,79,00,73,00,74,00,65,00,6d,00,72,00,6f,\ + 00,6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,\ + 5c,00,6d,00,73,00,63,00,6f,00,72,00,65,00,65,00,2e,00,64,00,6c,00,6c,00,00,\ + 00 + +-----------------------------------------------------------------------------------------*/ + +#pragma once + +#include +#include + +#include +#include + +#include +#include +#include + +namespace spdlog { +namespace sinks { + +namespace win_eventlog { + +namespace internal { + +struct local_alloc_t { + HLOCAL hlocal_; + + SPDLOG_CONSTEXPR local_alloc_t() SPDLOG_NOEXCEPT : hlocal_(nullptr) {} + + local_alloc_t(local_alloc_t const &) = delete; + local_alloc_t &operator=(local_alloc_t const &) = delete; + + ~local_alloc_t() SPDLOG_NOEXCEPT { + if (hlocal_) { + LocalFree(hlocal_); + } + } +}; + +/** Windows error */ +struct win32_error : public spdlog_ex { + /** Formats an error report line: "user-message: error-code (system message)" */ + static std::string format(std::string const &user_message, DWORD error_code = GetLastError()) { + std::string system_message; + + local_alloc_t format_message_result{}; + auto format_message_succeeded = + ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&format_message_result.hlocal_, 0, nullptr); + + if (format_message_succeeded && format_message_result.hlocal_) { + system_message = fmt_lib::format(" ({})", (LPSTR)format_message_result.hlocal_); + } + + return fmt_lib::format("{}: {}{}", user_message, error_code, system_message); + } + + explicit win32_error(std::string const &func_name, DWORD error = GetLastError()) + : spdlog_ex(format(func_name, error)) {} +}; + +/** Wrapper for security identifiers (SID) on Windows */ +struct sid_t { + std::vector buffer_; + +public: + sid_t() {} + + /** creates a wrapped SID copy */ + static sid_t duplicate_sid(PSID psid) { + if (!::IsValidSid(psid)) { + throw_spdlog_ex("sid_t::sid_t(): invalid SID received"); + } + + auto const sid_length{::GetLengthSid(psid)}; + + sid_t result; + result.buffer_.resize(sid_length); + if (!::CopySid(sid_length, (PSID)result.as_sid(), psid)) { + SPDLOG_THROW(win32_error("CopySid")); + } + + return result; + } + + /** Retrieves pointer to the internal buffer contents as SID* */ + SID *as_sid() const { return buffer_.empty() ? nullptr : (SID *)buffer_.data(); } + + /** Get SID for the current user */ + static sid_t get_current_user_sid() { + /* create and init RAII holder for process token */ + struct process_token_t { + HANDLE token_handle_ = INVALID_HANDLE_VALUE; + explicit process_token_t(HANDLE process) { + if (!::OpenProcessToken(process, TOKEN_QUERY, &token_handle_)) { + SPDLOG_THROW(win32_error("OpenProcessToken")); + } + } + + ~process_token_t() { ::CloseHandle(token_handle_); } + + } current_process_token( + ::GetCurrentProcess()); // GetCurrentProcess returns pseudohandle, no leak here! + + // Get the required size, this is expected to fail with ERROR_INSUFFICIENT_BUFFER and return + // the token size + DWORD tusize = 0; + if (::GetTokenInformation(current_process_token.token_handle_, TokenUser, NULL, 0, + &tusize)) { + SPDLOG_THROW(win32_error("GetTokenInformation should fail")); + } + + // get user token + std::vector buffer(static_cast(tusize)); + if (!::GetTokenInformation(current_process_token.token_handle_, TokenUser, + (LPVOID)buffer.data(), tusize, &tusize)) { + SPDLOG_THROW(win32_error("GetTokenInformation")); + } + + // create a wrapper of the SID data as stored in the user token + return sid_t::duplicate_sid(((TOKEN_USER *)buffer.data())->User.Sid); + } +}; + +struct eventlog { + static WORD get_event_type(details::log_msg const &msg) { + switch (msg.level) { + case level::trace: + case level::debug: + return EVENTLOG_SUCCESS; + + case level::info: + return EVENTLOG_INFORMATION_TYPE; + + case level::warn: + return EVENTLOG_WARNING_TYPE; + + case level::err: + case level::critical: + case level::off: + return EVENTLOG_ERROR_TYPE; + + default: + return EVENTLOG_INFORMATION_TYPE; + } + } + + static WORD get_event_category(details::log_msg const &msg) { return (WORD)msg.level; } +}; + +} // namespace internal + +/* + * Windows Event Log sink + */ +template +class win_eventlog_sink : public base_sink { +private: + HANDLE hEventLog_{NULL}; + internal::sid_t current_user_sid_; + std::string source_; + DWORD event_id_; + + HANDLE event_log_handle() { + if (!hEventLog_) { + hEventLog_ = ::RegisterEventSourceA(nullptr, source_.c_str()); + if (!hEventLog_ || hEventLog_ == (HANDLE)ERROR_ACCESS_DENIED) { + SPDLOG_THROW(internal::win32_error("RegisterEventSource")); + } + } + + return hEventLog_; + } + +protected: + void sink_it_(const details::log_msg &msg) override { + using namespace internal; + + bool succeeded; + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + formatted.push_back('\0'); + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + wmemory_buf_t buf; + details::os::utf8_to_wstrbuf(string_view_t(formatted.data(), formatted.size()), buf); + + LPCWSTR lp_wstr = buf.data(); + succeeded = static_cast(::ReportEventW( + event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), + event_id_, current_user_sid_.as_sid(), 1, 0, &lp_wstr, nullptr)); +#else + LPCSTR lp_str = formatted.data(); + succeeded = static_cast(::ReportEventA( + event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), + event_id_, current_user_sid_.as_sid(), 1, 0, &lp_str, nullptr)); +#endif + + if (!succeeded) { + SPDLOG_THROW(win32_error("ReportEvent")); + } + } + + void flush_() override {} + +public: + win_eventlog_sink(std::string const &source, + DWORD event_id = 1000 /* according to mscoree.dll */) + : source_(source), + event_id_(event_id) { + try { + current_user_sid_ = internal::sid_t::get_current_user_sid(); + } catch (...) { + // get_current_user_sid() is unlikely to fail and if it does, we can still proceed + // without current_user_sid but in the event log the record will have no user name + } + } + + ~win_eventlog_sink() { + if (hEventLog_) DeregisterEventSource(hEventLog_); + } +}; + +} // namespace win_eventlog + +using win_eventlog_sink_mt = win_eventlog::win_eventlog_sink; +using win_eventlog_sink_st = win_eventlog::win_eventlog_sink; + +} // namespace sinks +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/wincolor_sink-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/wincolor_sink-inl.h new file mode 100644 index 0000000..696db56 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/wincolor_sink-inl.h @@ -0,0 +1,172 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +#include +#include + +namespace spdlog { +namespace sinks { +template +SPDLOG_INLINE wincolor_sink::wincolor_sink(void *out_handle, color_mode mode) + : out_handle_(out_handle), + mutex_(ConsoleMutex::mutex()), + formatter_(details::make_unique()) { + set_color_mode_impl(mode); + // set level colors + colors_[level::trace] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; // white + colors_[level::debug] = FOREGROUND_GREEN | FOREGROUND_BLUE; // cyan + colors_[level::info] = FOREGROUND_GREEN; // green + colors_[level::warn] = + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; // intense yellow + colors_[level::err] = FOREGROUND_RED | FOREGROUND_INTENSITY; // intense red + colors_[level::critical] = BACKGROUND_RED | FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE | + FOREGROUND_INTENSITY; // intense white on red background + colors_[level::off] = 0; +} + +template +SPDLOG_INLINE wincolor_sink::~wincolor_sink() { + this->flush(); +} + +// change the color for the given level +template +void SPDLOG_INLINE wincolor_sink::set_color(level::level_enum level, + std::uint16_t color) { + std::lock_guard lock(mutex_); + colors_[static_cast(level)] = color; +} + +template +void SPDLOG_INLINE wincolor_sink::log(const details::log_msg &msg) { + if (out_handle_ == nullptr || out_handle_ == INVALID_HANDLE_VALUE) { + return; + } + + std::lock_guard lock(mutex_); + msg.color_range_start = 0; + msg.color_range_end = 0; + memory_buf_t formatted; + formatter_->format(msg, formatted); + if (should_do_colors_ && msg.color_range_end > msg.color_range_start) { + // before color range + print_range_(formatted, 0, msg.color_range_start); + // in color range + auto orig_attribs = + static_cast(set_foreground_color_(colors_[static_cast(msg.level)])); + print_range_(formatted, msg.color_range_start, msg.color_range_end); + // reset to orig colors + ::SetConsoleTextAttribute(static_cast(out_handle_), orig_attribs); + print_range_(formatted, msg.color_range_end, formatted.size()); + } else // print without colors if color range is invalid (or color is disabled) + { + write_to_file_(formatted); + } +} + +template +void SPDLOG_INLINE wincolor_sink::flush() { + // windows console always flushed? +} + +template +void SPDLOG_INLINE wincolor_sink::set_pattern(const std::string &pattern) { + std::lock_guard lock(mutex_); + formatter_ = std::unique_ptr(new pattern_formatter(pattern)); +} + +template +void SPDLOG_INLINE +wincolor_sink::set_formatter(std::unique_ptr sink_formatter) { + std::lock_guard lock(mutex_); + formatter_ = std::move(sink_formatter); +} + +template +void SPDLOG_INLINE wincolor_sink::set_color_mode(color_mode mode) { + std::lock_guard lock(mutex_); + set_color_mode_impl(mode); +} + +template +void SPDLOG_INLINE wincolor_sink::set_color_mode_impl(color_mode mode) { + if (mode == color_mode::automatic) { + // should do colors only if out_handle_ points to actual console. + DWORD console_mode; + bool in_console = ::GetConsoleMode(static_cast(out_handle_), &console_mode) != 0; + should_do_colors_ = in_console; + } else { + should_do_colors_ = mode == color_mode::always ? true : false; + } +} + +// set foreground color and return the orig console attributes (for resetting later) +template +std::uint16_t SPDLOG_INLINE +wincolor_sink::set_foreground_color_(std::uint16_t attribs) { + CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info; + if (!::GetConsoleScreenBufferInfo(static_cast(out_handle_), &orig_buffer_info)) { + // just return white if failed getting console info + return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + } + + // change only the foreground bits (lowest 4 bits) + auto new_attribs = static_cast(attribs) | (orig_buffer_info.wAttributes & 0xfff0); + auto ignored = + ::SetConsoleTextAttribute(static_cast(out_handle_), static_cast(new_attribs)); + (void)(ignored); + return static_cast(orig_buffer_info.wAttributes); // return orig attribs +} + +// print a range of formatted message to console +template +void SPDLOG_INLINE wincolor_sink::print_range_(const memory_buf_t &formatted, + size_t start, + size_t end) { + if (end > start) { +#if defined(SPDLOG_UTF8_TO_WCHAR_CONSOLE) + wmemory_buf_t wformatted; + details::os::utf8_to_wstrbuf(string_view_t(formatted.data() + start, end - start), + wformatted); + auto size = static_cast(wformatted.size()); + auto ignored = ::WriteConsoleW(static_cast(out_handle_), wformatted.data(), size, + nullptr, nullptr); +#else + auto size = static_cast(end - start); + auto ignored = ::WriteConsoleA(static_cast(out_handle_), formatted.data() + start, + size, nullptr, nullptr); +#endif + (void)(ignored); + } +} + +template +void SPDLOG_INLINE wincolor_sink::write_to_file_(const memory_buf_t &formatted) { + auto size = static_cast(formatted.size()); + DWORD bytes_written = 0; + auto ignored = ::WriteFile(static_cast(out_handle_), formatted.data(), size, + &bytes_written, nullptr); + (void)(ignored); +} + +// wincolor_stdout_sink +template +SPDLOG_INLINE wincolor_stdout_sink::wincolor_stdout_sink(color_mode mode) + : wincolor_sink(::GetStdHandle(STD_OUTPUT_HANDLE), mode) {} + +// wincolor_stderr_sink +template +SPDLOG_INLINE wincolor_stderr_sink::wincolor_stderr_sink(color_mode mode) + : wincolor_sink(::GetStdHandle(STD_ERROR_HANDLE), mode) {} +} // namespace sinks +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/wincolor_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/wincolor_sink.h new file mode 100644 index 0000000..8ba594c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/wincolor_sink.h @@ -0,0 +1,82 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace spdlog { +namespace sinks { +/* + * Windows color console sink. Uses WriteConsoleA to write to the console with + * colors + */ +template +class wincolor_sink : public sink { +public: + wincolor_sink(void *out_handle, color_mode mode); + ~wincolor_sink() override; + + wincolor_sink(const wincolor_sink &other) = delete; + wincolor_sink &operator=(const wincolor_sink &other) = delete; + + // change the color for the given level + void set_color(level::level_enum level, std::uint16_t color); + void log(const details::log_msg &msg) final override; + void flush() final override; + void set_pattern(const std::string &pattern) override final; + void set_formatter(std::unique_ptr sink_formatter) override final; + void set_color_mode(color_mode mode); + +protected: + using mutex_t = typename ConsoleMutex::mutex_t; + void *out_handle_; + mutex_t &mutex_; + bool should_do_colors_; + std::unique_ptr formatter_; + std::array colors_; + + // set foreground color and return the orig console attributes (for resetting later) + std::uint16_t set_foreground_color_(std::uint16_t attribs); + + // print a range of formatted message to console + void print_range_(const memory_buf_t &formatted, size_t start, size_t end); + + // in case we are redirected to file (not in console mode) + void write_to_file_(const memory_buf_t &formatted); + + void set_color_mode_impl(color_mode mode); +}; + +template +class wincolor_stdout_sink : public wincolor_sink { +public: + explicit wincolor_stdout_sink(color_mode mode = color_mode::automatic); +}; + +template +class wincolor_stderr_sink : public wincolor_sink { +public: + explicit wincolor_stderr_sink(color_mode mode = color_mode::automatic); +}; + +using wincolor_stdout_sink_mt = wincolor_stdout_sink; +using wincolor_stdout_sink_st = wincolor_stdout_sink; + +using wincolor_stderr_sink_mt = wincolor_stderr_sink; +using wincolor_stderr_sink_st = wincolor_stderr_sink; +} // namespace sinks +} // namespace spdlog + +#ifdef SPDLOG_HEADER_ONLY + #include "wincolor_sink-inl.h" +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/spdlog-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/spdlog-inl.h new file mode 100644 index 0000000..97c3622 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/spdlog-inl.h @@ -0,0 +1,92 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#ifndef SPDLOG_HEADER_ONLY + #include +#endif + +#include +#include + +namespace spdlog { + +SPDLOG_INLINE void initialize_logger(std::shared_ptr logger) { + details::registry::instance().initialize_logger(std::move(logger)); +} + +SPDLOG_INLINE std::shared_ptr get(const std::string &name) { + return details::registry::instance().get(name); +} + +SPDLOG_INLINE void set_formatter(std::unique_ptr formatter) { + details::registry::instance().set_formatter(std::move(formatter)); +} + +SPDLOG_INLINE void set_pattern(std::string pattern, pattern_time_type time_type) { + set_formatter( + std::unique_ptr(new pattern_formatter(std::move(pattern), time_type))); +} + +SPDLOG_INLINE void enable_backtrace(size_t n_messages) { + details::registry::instance().enable_backtrace(n_messages); +} + +SPDLOG_INLINE void disable_backtrace() { details::registry::instance().disable_backtrace(); } + +SPDLOG_INLINE void dump_backtrace() { default_logger_raw()->dump_backtrace(); } + +SPDLOG_INLINE level::level_enum get_level() { return default_logger_raw()->level(); } + +SPDLOG_INLINE bool should_log(level::level_enum log_level) { + return default_logger_raw()->should_log(log_level); +} + +SPDLOG_INLINE void set_level(level::level_enum log_level) { + details::registry::instance().set_level(log_level); +} + +SPDLOG_INLINE void flush_on(level::level_enum log_level) { + details::registry::instance().flush_on(log_level); +} + +SPDLOG_INLINE void set_error_handler(void (*handler)(const std::string &msg)) { + details::registry::instance().set_error_handler(handler); +} + +SPDLOG_INLINE void register_logger(std::shared_ptr logger) { + details::registry::instance().register_logger(std::move(logger)); +} + +SPDLOG_INLINE void apply_all(const std::function)> &fun) { + details::registry::instance().apply_all(fun); +} + +SPDLOG_INLINE void drop(const std::string &name) { details::registry::instance().drop(name); } + +SPDLOG_INLINE void drop_all() { details::registry::instance().drop_all(); } + +SPDLOG_INLINE void shutdown() { details::registry::instance().shutdown(); } + +SPDLOG_INLINE void set_automatic_registration(bool automatic_registration) { + details::registry::instance().set_automatic_registration(automatic_registration); +} + +SPDLOG_INLINE std::shared_ptr default_logger() { + return details::registry::instance().default_logger(); +} + +SPDLOG_INLINE spdlog::logger *default_logger_raw() { + return details::registry::instance().get_default_raw(); +} + +SPDLOG_INLINE void set_default_logger(std::shared_ptr default_logger) { + details::registry::instance().set_default_logger(std::move(default_logger)); +} + +SPDLOG_INLINE void apply_logger_env_levels(std::shared_ptr logger) { + details::registry::instance().apply_logger_env_levels(std::move(logger)); +} + +} // namespace spdlog diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/spdlog.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/spdlog.h new file mode 100644 index 0000000..a8afbce --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/spdlog.h @@ -0,0 +1,352 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +// spdlog main header file. +// see example.cpp for usage example + +#ifndef SPDLOG_H +#define SPDLOG_H + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace spdlog { + +using default_factory = synchronous_factory; + +// Create and register a logger with a templated sink type +// The logger's level, formatter and flush level will be set according the +// global settings. +// +// Example: +// spdlog::create("logger_name", "dailylog_filename", 11, 59); +template +inline std::shared_ptr create(std::string logger_name, SinkArgs &&...sink_args) { + return default_factory::create(std::move(logger_name), + std::forward(sink_args)...); +} + +// Initialize and register a logger, +// formatter and flush level will be set according the global settings. +// +// Useful for initializing manually created loggers with the global settings. +// +// Example: +// auto mylogger = std::make_shared("mylogger", ...); +// spdlog::initialize_logger(mylogger); +SPDLOG_API void initialize_logger(std::shared_ptr logger); + +// Return an existing logger or nullptr if a logger with such name doesn't +// exist. +// example: spdlog::get("my_logger")->info("hello {}", "world"); +SPDLOG_API std::shared_ptr get(const std::string &name); + +// Set global formatter. Each sink in each logger will get a clone of this object +SPDLOG_API void set_formatter(std::unique_ptr formatter); + +// Set global format string. +// example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v"); +SPDLOG_API void set_pattern(std::string pattern, + pattern_time_type time_type = pattern_time_type::local); + +// enable global backtrace support +SPDLOG_API void enable_backtrace(size_t n_messages); + +// disable global backtrace support +SPDLOG_API void disable_backtrace(); + +// call dump backtrace on default logger +SPDLOG_API void dump_backtrace(); + +// Get global logging level +SPDLOG_API level::level_enum get_level(); + +// Set global logging level +SPDLOG_API void set_level(level::level_enum log_level); + +// Determine whether the default logger should log messages with a certain level +SPDLOG_API bool should_log(level::level_enum lvl); + +// Set global flush level +SPDLOG_API void flush_on(level::level_enum log_level); + +// Start/Restart a periodic flusher thread +// Warning: Use only if all your loggers are thread safe! +template +inline void flush_every(std::chrono::duration interval) { + details::registry::instance().flush_every(interval); +} + +// Set global error handler +SPDLOG_API void set_error_handler(void (*handler)(const std::string &msg)); + +// Register the given logger with the given name +SPDLOG_API void register_logger(std::shared_ptr logger); + +// Apply a user defined function on all registered loggers +// Example: +// spdlog::apply_all([&](std::shared_ptr l) {l->flush();}); +SPDLOG_API void apply_all(const std::function)> &fun); + +// Drop the reference to the given logger +SPDLOG_API void drop(const std::string &name); + +// Drop all references from the registry +SPDLOG_API void drop_all(); + +// stop any running threads started by spdlog and clean registry loggers +SPDLOG_API void shutdown(); + +// Automatic registration of loggers when using spdlog::create() or spdlog::create_async +SPDLOG_API void set_automatic_registration(bool automatic_registration); + +// API for using default logger (stdout_color_mt), +// e.g: spdlog::info("Message {}", 1); +// +// The default logger object can be accessed using the spdlog::default_logger(): +// For example, to add another sink to it: +// spdlog::default_logger()->sinks().push_back(some_sink); +// +// The default logger can replaced using spdlog::set_default_logger(new_logger). +// For example, to replace it with a file logger. +// +// IMPORTANT: +// The default API is thread safe (for _mt loggers), but: +// set_default_logger() *should not* be used concurrently with the default API. +// e.g do not call set_default_logger() from one thread while calling spdlog::info() from another. + +SPDLOG_API std::shared_ptr default_logger(); + +SPDLOG_API spdlog::logger *default_logger_raw(); + +SPDLOG_API void set_default_logger(std::shared_ptr default_logger); + +// Initialize logger level based on environment configs. +// +// Useful for applying SPDLOG_LEVEL to manually created loggers. +// +// Example: +// auto mylogger = std::make_shared("mylogger", ...); +// spdlog::apply_logger_env_levels(mylogger); +SPDLOG_API void apply_logger_env_levels(std::shared_ptr logger); + +template +inline void log(source_loc source, + level::level_enum lvl, + format_string_t fmt, + Args &&...args) { + default_logger_raw()->log(source, lvl, fmt, std::forward(args)...); +} + +template +inline void log(level::level_enum lvl, format_string_t fmt, Args &&...args) { + default_logger_raw()->log(source_loc{}, lvl, fmt, std::forward(args)...); +} + +template +inline void trace(format_string_t fmt, Args &&...args) { + default_logger_raw()->trace(fmt, std::forward(args)...); +} + +template +inline void debug(format_string_t fmt, Args &&...args) { + default_logger_raw()->debug(fmt, std::forward(args)...); +} + +template +inline void info(format_string_t fmt, Args &&...args) { + default_logger_raw()->info(fmt, std::forward(args)...); +} + +template +inline void warn(format_string_t fmt, Args &&...args) { + default_logger_raw()->warn(fmt, std::forward(args)...); +} + +template +inline void error(format_string_t fmt, Args &&...args) { + default_logger_raw()->error(fmt, std::forward(args)...); +} + +template +inline void critical(format_string_t fmt, Args &&...args) { + default_logger_raw()->critical(fmt, std::forward(args)...); +} + +template +inline void log(source_loc source, level::level_enum lvl, const T &msg) { + default_logger_raw()->log(source, lvl, msg); +} + +template +inline void log(level::level_enum lvl, const T &msg) { + default_logger_raw()->log(lvl, msg); +} + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT +template +inline void log(source_loc source, + level::level_enum lvl, + wformat_string_t fmt, + Args &&...args) { + default_logger_raw()->log(source, lvl, fmt, std::forward(args)...); +} + +template +inline void log(level::level_enum lvl, wformat_string_t fmt, Args &&...args) { + default_logger_raw()->log(source_loc{}, lvl, fmt, std::forward(args)...); +} + +template +inline void trace(wformat_string_t fmt, Args &&...args) { + default_logger_raw()->trace(fmt, std::forward(args)...); +} + +template +inline void debug(wformat_string_t fmt, Args &&...args) { + default_logger_raw()->debug(fmt, std::forward(args)...); +} + +template +inline void info(wformat_string_t fmt, Args &&...args) { + default_logger_raw()->info(fmt, std::forward(args)...); +} + +template +inline void warn(wformat_string_t fmt, Args &&...args) { + default_logger_raw()->warn(fmt, std::forward(args)...); +} + +template +inline void error(wformat_string_t fmt, Args &&...args) { + default_logger_raw()->error(fmt, std::forward(args)...); +} + +template +inline void critical(wformat_string_t fmt, Args &&...args) { + default_logger_raw()->critical(fmt, std::forward(args)...); +} +#endif + +template +inline void trace(const T &msg) { + default_logger_raw()->trace(msg); +} + +template +inline void debug(const T &msg) { + default_logger_raw()->debug(msg); +} + +template +inline void info(const T &msg) { + default_logger_raw()->info(msg); +} + +template +inline void warn(const T &msg) { + default_logger_raw()->warn(msg); +} + +template +inline void error(const T &msg) { + default_logger_raw()->error(msg); +} + +template +inline void critical(const T &msg) { + default_logger_raw()->critical(msg); +} + +} // namespace spdlog + +// +// enable/disable log calls at compile time according to global level. +// +// define SPDLOG_ACTIVE_LEVEL to one of those (before including spdlog.h): +// SPDLOG_LEVEL_TRACE, +// SPDLOG_LEVEL_DEBUG, +// SPDLOG_LEVEL_INFO, +// SPDLOG_LEVEL_WARN, +// SPDLOG_LEVEL_ERROR, +// SPDLOG_LEVEL_CRITICAL, +// SPDLOG_LEVEL_OFF +// + +#ifndef SPDLOG_NO_SOURCE_LOC + #define SPDLOG_LOGGER_CALL(logger, level, ...) \ + (logger)->log(spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}, level, __VA_ARGS__) +#else + #define SPDLOG_LOGGER_CALL(logger, level, ...) \ + (logger)->log(spdlog::source_loc{}, level, __VA_ARGS__) +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE + #define SPDLOG_LOGGER_TRACE(logger, ...) \ + SPDLOG_LOGGER_CALL(logger, spdlog::level::trace, __VA_ARGS__) + #define SPDLOG_TRACE(...) SPDLOG_LOGGER_TRACE(spdlog::default_logger_raw(), __VA_ARGS__) +#else + #define SPDLOG_LOGGER_TRACE(logger, ...) (void)0 + #define SPDLOG_TRACE(...) (void)0 +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_DEBUG + #define SPDLOG_LOGGER_DEBUG(logger, ...) \ + SPDLOG_LOGGER_CALL(logger, spdlog::level::debug, __VA_ARGS__) + #define SPDLOG_DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__) +#else + #define SPDLOG_LOGGER_DEBUG(logger, ...) (void)0 + #define SPDLOG_DEBUG(...) (void)0 +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_INFO + #define SPDLOG_LOGGER_INFO(logger, ...) \ + SPDLOG_LOGGER_CALL(logger, spdlog::level::info, __VA_ARGS__) + #define SPDLOG_INFO(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__) +#else + #define SPDLOG_LOGGER_INFO(logger, ...) (void)0 + #define SPDLOG_INFO(...) (void)0 +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_WARN + #define SPDLOG_LOGGER_WARN(logger, ...) \ + SPDLOG_LOGGER_CALL(logger, spdlog::level::warn, __VA_ARGS__) + #define SPDLOG_WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__) +#else + #define SPDLOG_LOGGER_WARN(logger, ...) (void)0 + #define SPDLOG_WARN(...) (void)0 +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_ERROR + #define SPDLOG_LOGGER_ERROR(logger, ...) \ + SPDLOG_LOGGER_CALL(logger, spdlog::level::err, __VA_ARGS__) + #define SPDLOG_ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__) +#else + #define SPDLOG_LOGGER_ERROR(logger, ...) (void)0 + #define SPDLOG_ERROR(...) (void)0 +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_CRITICAL + #define SPDLOG_LOGGER_CRITICAL(logger, ...) \ + SPDLOG_LOGGER_CALL(logger, spdlog::level::critical, __VA_ARGS__) + #define SPDLOG_CRITICAL(...) SPDLOG_LOGGER_CRITICAL(spdlog::default_logger_raw(), __VA_ARGS__) +#else + #define SPDLOG_LOGGER_CRITICAL(logger, ...) (void)0 + #define SPDLOG_CRITICAL(...) (void)0 +#endif + +#ifdef SPDLOG_HEADER_ONLY + #include "spdlog-inl.h" +#endif + +#endif // SPDLOG_H diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/stopwatch.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/stopwatch.h new file mode 100644 index 0000000..54ab3d3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/stopwatch.h @@ -0,0 +1,66 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include + +// Stopwatch support for spdlog (using std::chrono::steady_clock). +// Displays elapsed seconds since construction as double. +// +// Usage: +// +// spdlog::stopwatch sw; +// ... +// spdlog::debug("Elapsed: {} seconds", sw); => "Elapsed 0.005116733 seconds" +// spdlog::info("Elapsed: {:.6} seconds", sw); => "Elapsed 0.005163 seconds" +// +// +// If other units are needed (e.g. millis instead of double), include "fmt/chrono.h" and use +// "duration_cast<..>(sw.elapsed())": +// +// #include +//.. +// using std::chrono::duration_cast; +// using std::chrono::milliseconds; +// spdlog::info("Elapsed {}", duration_cast(sw.elapsed())); => "Elapsed 5ms" + +namespace spdlog { +class stopwatch { + using clock = std::chrono::steady_clock; + std::chrono::time_point start_tp_; + +public: + stopwatch() + : start_tp_{clock::now()} {} + + std::chrono::duration elapsed() const { + return std::chrono::duration(clock::now() - start_tp_); + } + + std::chrono::milliseconds elapsed_ms() const { + return std::chrono::duration_cast(clock::now() - start_tp_); + } + + void reset() { start_tp_ = clock::now(); } +}; +} // namespace spdlog + +// Support for fmt formatting (e.g. "{:012.9}" or just "{}") +namespace +#ifdef SPDLOG_USE_STD_FORMAT + std +#else + fmt +#endif +{ + +template <> +struct formatter : formatter { + template + auto format(const spdlog::stopwatch &sw, FormatContext &ctx) const -> decltype(ctx.out()) { + return formatter::format(sw.elapsed().count(), ctx); + } +}; +} // namespace std diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/tweakme.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/tweakme.h new file mode 100644 index 0000000..801c739 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/tweakme.h @@ -0,0 +1,143 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +/////////////////////////////////////////////////////////////////////////////// +// +// Edit this file to squeeze more performance, and to customize supported +// features +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Under Linux, the much faster CLOCK_REALTIME_COARSE clock can be used. +// This clock is less accurate - can be off by dozens of millis - depending on +// the kernel HZ. +// Uncomment to use it instead of the regular clock. +// +// #define SPDLOG_CLOCK_COARSE +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment if source location logging is not needed. +// This will prevent spdlog from using __FILE__, __LINE__ and SPDLOG_FUNCTION +// +// #define SPDLOG_NO_SOURCE_LOC +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment if thread id logging is not needed (i.e. no %t in the log pattern). +// This will prevent spdlog from querying the thread id on each log call. +// +// WARNING: If the log pattern contains thread id (i.e, %t) while this flag is +// on, zero will be logged as thread id. +// +// #define SPDLOG_NO_THREAD_ID +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to prevent spdlog from using thread local storage. +// +// WARNING: if your program forks, UNCOMMENT this flag to prevent undefined +// thread ids in the children logs. +// +// #define SPDLOG_NO_TLS +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to avoid spdlog's usage of atomic log levels +// Use only if your code never modifies a logger's log levels concurrently by +// different threads. +// +// #define SPDLOG_NO_ATOMIC_LEVELS +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to enable usage of wchar_t for file names on Windows. +// +// #define SPDLOG_WCHAR_FILENAMES +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to override default eol ("\n" or "\r\n" under Linux/Windows) +// +// #define SPDLOG_EOL ";-)\n" +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to override default folder separators ("/" or "\\/" under +// Linux/Windows). Each character in the string is treated as a different +// separator. +// +// #define SPDLOG_FOLDER_SEPS "\\" +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to use your own copy of the fmt library instead of spdlog's copy. +// In this case spdlog will try to include so set your -I flag +// accordingly. +// +#ifndef SPDLOG_FMT_EXTERNAL +#define SPDLOG_FMT_EXTERNAL +#endif +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to use C++20 std::format instead of fmt. +// +// #define SPDLOG_USE_STD_FORMAT +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to enable wchar_t support (convert to utf8) +// +// #define SPDLOG_WCHAR_TO_UTF8_SUPPORT +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to prevent child processes from inheriting log file descriptors +// +// #define SPDLOG_PREVENT_CHILD_FD +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to customize level names (e.g. "MY TRACE") +// +// #define SPDLOG_LEVEL_NAMES { "MY TRACE", "MY DEBUG", "MY INFO", "MY WARNING", "MY ERROR", "MY +// CRITICAL", "OFF" } +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to customize short level names (e.g. "MT") +// These can be longer than one character. +// +// #define SPDLOG_SHORT_LEVEL_NAMES { "T", "D", "I", "W", "E", "C", "O" } +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to disable default logger creation. +// This might save some (very) small initialization time if no default logger is needed. +// +// #define SPDLOG_DISABLE_DEFAULT_LOGGER +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment and set to compile time level with zero cost (default is INFO). +// Macros like SPDLOG_DEBUG(..), SPDLOG_INFO(..) will expand to empty statements if not enabled +// +// #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment (and change if desired) macro to use for function names. +// This is compiler dependent. +// __PRETTY_FUNCTION__ might be nicer in clang/gcc, and __FUNCTION__ in msvc. +// Defaults to __FUNCTION__ (should work on all compilers) if not defined. +// +// #ifdef __PRETTY_FUNCTION__ +// # define SPDLOG_FUNCTION __PRETTY_FUNCTION__ +// #else +// # define SPDLOG_FUNCTION __FUNCTION__ +// #endif +/////////////////////////////////////////////////////////////////////////////// diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/version.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/version.h new file mode 100644 index 0000000..7c5e129 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/version.h @@ -0,0 +1,11 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#define SPDLOG_VER_MAJOR 1 +#define SPDLOG_VER_MINOR 15 +#define SPDLOG_VER_PATCH 0 + +#define SPDLOG_TO_VERSION(major, minor, patch) (major * 10000 + minor * 100 + patch) +#define SPDLOG_VERSION SPDLOG_TO_VERSION(SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH) diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_c_lexer.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_c_lexer.h new file mode 100644 index 0000000..fd42f1c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_c_lexer.h @@ -0,0 +1,941 @@ +// stb_c_lexer.h - v0.12 - public domain Sean Barrett 2013 +// lexer for making little C-like languages with recursive-descent parsers +// +// This file provides both the interface and the implementation. +// To instantiate the implementation, +// #define STB_C_LEXER_IMPLEMENTATION +// in *ONE* source file, before #including this file. +// +// The default configuration is fairly close to a C lexer, although +// suffixes on integer constants are not handled (you can override this). +// +// History: +// 0.12 fix compilation bug for NUL support; better support separate inclusion +// 0.11 fix clang static analysis warning +// 0.10 fix warnings +// 0.09 hex floats, no-stdlib fixes +// 0.08 fix bad pointer comparison +// 0.07 fix mishandling of hexadecimal constants parsed by strtol +// 0.06 fix missing next character after ending quote mark (Andreas Fredriksson) +// 0.05 refixed get_location because github version had lost the fix +// 0.04 fix octal parsing bug +// 0.03 added STB_C_LEX_DISCARD_PREPROCESSOR option +// refactor API to simplify (only one struct instead of two) +// change literal enum names to have 'lit' at the end +// 0.02 first public release +// +// Status: +// - haven't tested compiling as C++ +// - haven't tested the float parsing path +// - haven't tested the non-default-config paths (e.g. non-stdlib) +// - only tested default-config paths by eyeballing output of self-parse +// +// - haven't implemented multiline strings +// - haven't implemented octal/hex character constants +// - haven't implemented support for unicode CLEX_char +// - need to expand error reporting so you don't just get "CLEX_parse_error" +// +// Contributors: +// Arpad Goretity (bugfix) +// Alan Hickman (hex floats) +// github:mundusnine (bugfix) +// +// LICENSE +// +// See end of file for license information. + +#ifdef STB_C_LEXER_IMPLEMENTATION +#ifndef STB_C_LEXER_DEFINITIONS +// to change the default parsing rules, copy the following lines +// into your C/C++ file *before* including this, and then replace +// the Y's with N's for the ones you don't want. This needs to be +// set to the same values for every place in your program where +// stb_c_lexer.h is included. +// --BEGIN-- + +#if defined(Y) || defined(N) +#error "Can only use stb_c_lexer in contexts where the preprocessor symbols 'Y' and 'N' are not defined" +#endif + +#define STB_C_LEX_C_DECIMAL_INTS Y // "0|[1-9][0-9]*" CLEX_intlit +#define STB_C_LEX_C_HEX_INTS Y // "0x[0-9a-fA-F]+" CLEX_intlit +#define STB_C_LEX_C_OCTAL_INTS Y // "[0-7]+" CLEX_intlit +#define STB_C_LEX_C_DECIMAL_FLOATS Y // "[0-9]*(.[0-9]*([eE][-+]?[0-9]+)?) CLEX_floatlit +#define STB_C_LEX_C99_HEX_FLOATS N // "0x{hex}+(.{hex}*)?[pP][-+]?{hex}+ CLEX_floatlit +#define STB_C_LEX_C_IDENTIFIERS Y // "[_a-zA-Z][_a-zA-Z0-9]*" CLEX_id +#define STB_C_LEX_C_DQ_STRINGS Y // double-quote-delimited strings with escapes CLEX_dqstring +#define STB_C_LEX_C_SQ_STRINGS N // single-quote-delimited strings with escapes CLEX_ssstring +#define STB_C_LEX_C_CHARS Y // single-quote-delimited character with escape CLEX_charlits +#define STB_C_LEX_C_COMMENTS Y // "/* comment */" +#define STB_C_LEX_CPP_COMMENTS Y // "// comment to end of line\n" +#define STB_C_LEX_C_COMPARISONS Y // "==" CLEX_eq "!=" CLEX_noteq "<=" CLEX_lesseq ">=" CLEX_greatereq +#define STB_C_LEX_C_LOGICAL Y // "&&" CLEX_andand "||" CLEX_oror +#define STB_C_LEX_C_SHIFTS Y // "<<" CLEX_shl ">>" CLEX_shr +#define STB_C_LEX_C_INCREMENTS Y // "++" CLEX_plusplus "--" CLEX_minusminus +#define STB_C_LEX_C_ARROW Y // "->" CLEX_arrow +#define STB_C_LEX_EQUAL_ARROW N // "=>" CLEX_eqarrow +#define STB_C_LEX_C_BITWISEEQ Y // "&=" CLEX_andeq "|=" CLEX_oreq "^=" CLEX_xoreq +#define STB_C_LEX_C_ARITHEQ Y // "+=" CLEX_pluseq "-=" CLEX_minuseq + // "*=" CLEX_muleq "/=" CLEX_diveq "%=" CLEX_modeq + // if both STB_C_LEX_SHIFTS & STB_C_LEX_ARITHEQ: + // "<<=" CLEX_shleq ">>=" CLEX_shreq + +#define STB_C_LEX_PARSE_SUFFIXES N // letters after numbers are parsed as part of those numbers, and must be in suffix list below +#define STB_C_LEX_DECIMAL_SUFFIXES "" // decimal integer suffixes e.g. "uUlL" -- these are returned as-is in string storage +#define STB_C_LEX_HEX_SUFFIXES "" // e.g. "uUlL" +#define STB_C_LEX_OCTAL_SUFFIXES "" // e.g. "uUlL" +#define STB_C_LEX_FLOAT_SUFFIXES "" // + +#define STB_C_LEX_0_IS_EOF N // if Y, ends parsing at '\0'; if N, returns '\0' as token +#define STB_C_LEX_INTEGERS_AS_DOUBLES N // parses integers as doubles so they can be larger than 'int', but only if STB_C_LEX_STDLIB==N +#define STB_C_LEX_MULTILINE_DSTRINGS N // allow newlines in double-quoted strings +#define STB_C_LEX_MULTILINE_SSTRINGS N // allow newlines in single-quoted strings +#define STB_C_LEX_USE_STDLIB Y // use strtod,strtol for parsing #s; otherwise inaccurate hack +#define STB_C_LEX_DOLLAR_IDENTIFIER Y // allow $ as an identifier character +#define STB_C_LEX_FLOAT_NO_DECIMAL Y // allow floats that have no decimal point if they have an exponent + +#define STB_C_LEX_DEFINE_ALL_TOKEN_NAMES N // if Y, all CLEX_ token names are defined, even if never returned + // leaving it as N should help you catch config bugs + +#define STB_C_LEX_DISCARD_PREPROCESSOR Y // discard C-preprocessor directives (e.g. after prepocess + // still have #line, #pragma, etc) + +//#define STB_C_LEX_ISWHITE(str) ... // return length in bytes of whitespace characters if first char is whitespace + +#define STB_C_LEXER_DEFINITIONS // This line prevents the header file from replacing your definitions +// --END-- +#endif +#endif + +#ifndef INCLUDE_STB_C_LEXER_H +#define INCLUDE_STB_C_LEXER_H + +typedef struct +{ + // lexer variables + char *input_stream; + char *eof; + char *parse_point; + char *string_storage; + int string_storage_len; + + // lexer parse location for error messages + char *where_firstchar; + char *where_lastchar; + + // lexer token variables + long token; + double real_number; + long int_number; + char *string; + int string_len; +} stb_lexer; + +typedef struct +{ + int line_number; + int line_offset; +} stb_lex_location; + +#ifdef __cplusplus +extern "C" { +#endif + +extern void stb_c_lexer_init(stb_lexer *lexer, const char *input_stream, const char *input_stream_end, char *string_store, int store_length); +// this function initialize the 'lexer' structure +// Input: +// - input_stream points to the file to parse, loaded into memory +// - input_stream_end points to the end of the file, or NULL if you use 0-for-EOF +// - string_store is storage the lexer can use for storing parsed strings and identifiers +// - store_length is the length of that storage + +extern int stb_c_lexer_get_token(stb_lexer *lexer); +// this function returns non-zero if a token is parsed, or 0 if at EOF +// Output: +// - lexer->token is the token ID, which is unicode code point for a single-char token, < 0 for a multichar or eof or error +// - lexer->real_number is a double constant value for CLEX_floatlit, or CLEX_intlit if STB_C_LEX_INTEGERS_AS_DOUBLES +// - lexer->int_number is an integer constant for CLEX_intlit if !STB_C_LEX_INTEGERS_AS_DOUBLES, or character for CLEX_charlit +// - lexer->string is a 0-terminated string for CLEX_dqstring or CLEX_sqstring or CLEX_identifier +// - lexer->string_len is the byte length of lexer->string + +extern void stb_c_lexer_get_location(const stb_lexer *lexer, const char *where, stb_lex_location *loc); +// this inefficient function returns the line number and character offset of a +// given location in the file as returned by stb_lex_token. Because it's inefficient, +// you should only call it for errors, not for every token. +// For error messages of invalid tokens, you typically want the location of the start +// of the token (which caused the token to be invalid). For bugs involving legit +// tokens, you can report the first or the range. +// Output: +// - loc->line_number is the line number in the file, counting from 1, of the location +// - loc->line_offset is the char-offset in the line, counting from 0, of the location + + +#ifdef __cplusplus +} +#endif + +enum +{ + CLEX_eof = 256, + CLEX_parse_error, + CLEX_intlit , + CLEX_floatlit , + CLEX_id , + CLEX_dqstring , + CLEX_sqstring , + CLEX_charlit , + CLEX_eq , + CLEX_noteq , + CLEX_lesseq , + CLEX_greatereq , + CLEX_andand , + CLEX_oror , + CLEX_shl , + CLEX_shr , + CLEX_plusplus , + CLEX_minusminus , + CLEX_pluseq , + CLEX_minuseq , + CLEX_muleq , + CLEX_diveq , + CLEX_modeq , + CLEX_andeq , + CLEX_oreq , + CLEX_xoreq , + CLEX_arrow , + CLEX_eqarrow , + CLEX_shleq, CLEX_shreq, + + CLEX_first_unused_token + +}; +#endif // INCLUDE_STB_C_LEXER_H + +#ifdef STB_C_LEXER_IMPLEMENTATION + +// Hacky definitions so we can easily #if on them +#define Y(x) 1 +#define N(x) 0 + +#if STB_C_LEX_INTEGERS_AS_DOUBLES(x) +typedef double stb__clex_int; +#define intfield real_number +#define STB__clex_int_as_double +#else +typedef long stb__clex_int; +#define intfield int_number +#endif + +// Convert these config options to simple conditional #defines so we can more +// easily test them once we've change the meaning of Y/N + +#if STB_C_LEX_PARSE_SUFFIXES(x) +#define STB__clex_parse_suffixes +#endif + +#if STB_C_LEX_C99_HEX_FLOATS(x) +#define STB__clex_hex_floats +#endif + +#if STB_C_LEX_C_HEX_INTS(x) +#define STB__clex_hex_ints +#endif + +#if STB_C_LEX_C_DECIMAL_INTS(x) +#define STB__clex_decimal_ints +#endif + +#if STB_C_LEX_C_OCTAL_INTS(x) +#define STB__clex_octal_ints +#endif + +#if STB_C_LEX_C_DECIMAL_FLOATS(x) +#define STB__clex_decimal_floats +#endif + +#if STB_C_LEX_DISCARD_PREPROCESSOR(x) +#define STB__clex_discard_preprocessor +#endif + +#if STB_C_LEX_USE_STDLIB(x) && (!defined(STB__clex_hex_floats) || __STDC_VERSION__ >= 199901L) +#define STB__CLEX_use_stdlib +#include +#endif + +// Now for the rest of the file we'll use the basic definition where +// where Y expands to its contents and N expands to nothing +#undef Y +#define Y(a) a +#undef N +#define N(a) + +// API function +void stb_c_lexer_init(stb_lexer *lexer, const char *input_stream, const char *input_stream_end, char *string_store, int store_length) +{ + lexer->input_stream = (char *) input_stream; + lexer->eof = (char *) input_stream_end; + lexer->parse_point = (char *) input_stream; + lexer->string_storage = string_store; + lexer->string_storage_len = store_length; +} + +// API function +void stb_c_lexer_get_location(const stb_lexer *lexer, const char *where, stb_lex_location *loc) +{ + char *p = lexer->input_stream; + int line_number = 1; + int char_offset = 0; + while (*p && p < where) { + if (*p == '\n' || *p == '\r') { + p += (p[0]+p[1] == '\r'+'\n' ? 2 : 1); // skip newline + line_number += 1; + char_offset = 0; + } else { + ++p; + ++char_offset; + } + } + loc->line_number = line_number; + loc->line_offset = char_offset; +} + +// main helper function for returning a parsed token +static int stb__clex_token(stb_lexer *lexer, int token, char *start, char *end) +{ + lexer->token = token; + lexer->where_firstchar = start; + lexer->where_lastchar = end; + lexer->parse_point = end+1; + return 1; +} + +// helper function for returning eof +static int stb__clex_eof(stb_lexer *lexer) +{ + lexer->token = CLEX_eof; + return 0; +} + +static int stb__clex_iswhite(int x) +{ + return x == ' ' || x == '\t' || x == '\r' || x == '\n' || x == '\f'; +} + +static const char *stb__strchr(const char *str, int ch) +{ + for (; *str; ++str) + if (*str == ch) + return str; + return 0; +} + +// parse suffixes at the end of a number +static int stb__clex_parse_suffixes(stb_lexer *lexer, long tokenid, char *start, char *cur, const char *suffixes) +{ + #ifdef STB__clex_parse_suffixes + lexer->string = lexer->string_storage; + lexer->string_len = 0; + + while ((*cur >= 'a' && *cur <= 'z') || (*cur >= 'A' && *cur <= 'Z')) { + if (stb__strchr(suffixes, *cur) == 0) + return stb__clex_token(lexer, CLEX_parse_error, start, cur); + if (lexer->string_len+1 >= lexer->string_storage_len) + return stb__clex_token(lexer, CLEX_parse_error, start, cur); + lexer->string[lexer->string_len++] = *cur++; + } + #else + suffixes = suffixes; // attempt to suppress warnings + #endif + return stb__clex_token(lexer, tokenid, start, cur-1); +} + +#ifndef STB__CLEX_use_stdlib +static double stb__clex_pow(double base, unsigned int exponent) +{ + double value=1; + for ( ; exponent; exponent >>= 1) { + if (exponent & 1) + value *= base; + base *= base; + } + return value; +} + +static double stb__clex_parse_float(char *p, char **q) +{ + char *s = p; + double value=0; + int base=10; + int exponent=0; + +#ifdef STB__clex_hex_floats + if (*p == '0') { + if (p[1] == 'x' || p[1] == 'X') { + base=16; + p += 2; + } + } +#endif + + for (;;) { + if (*p >= '0' && *p <= '9') + value = value*base + (*p++ - '0'); +#ifdef STB__clex_hex_floats + else if (base == 16 && *p >= 'a' && *p <= 'f') + value = value*base + 10 + (*p++ - 'a'); + else if (base == 16 && *p >= 'A' && *p <= 'F') + value = value*base + 10 + (*p++ - 'A'); +#endif + else + break; + } + + if (*p == '.') { + double pow, addend = 0; + ++p; + for (pow=1; ; pow*=base) { + if (*p >= '0' && *p <= '9') + addend = addend*base + (*p++ - '0'); +#ifdef STB__clex_hex_floats + else if (base == 16 && *p >= 'a' && *p <= 'f') + addend = addend*base + 10 + (*p++ - 'a'); + else if (base == 16 && *p >= 'A' && *p <= 'F') + addend = addend*base + 10 + (*p++ - 'A'); +#endif + else + break; + } + value += addend / pow; + } +#ifdef STB__clex_hex_floats + if (base == 16) { + // exponent required for hex float literal + if (*p != 'p' && *p != 'P') { + *q = s; + return 0; + } + exponent = 1; + } else +#endif + exponent = (*p == 'e' || *p == 'E'); + + if (exponent) { + int sign = p[1] == '-'; + unsigned int exponent=0; + double power=1; + ++p; + if (*p == '-' || *p == '+') + ++p; + while (*p >= '0' && *p <= '9') + exponent = exponent*10 + (*p++ - '0'); + +#ifdef STB__clex_hex_floats + if (base == 16) + power = stb__clex_pow(2, exponent); + else +#endif + power = stb__clex_pow(10, exponent); + if (sign) + value /= power; + else + value *= power; + } + *q = p; + return value; +} +#endif + +static int stb__clex_parse_char(char *p, char **q) +{ + if (*p == '\\') { + *q = p+2; // tentatively guess we'll parse two characters + switch(p[1]) { + case '\\': return '\\'; + case '\'': return '\''; + case '"': return '"'; + case 't': return '\t'; + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case '0': return '\0'; // @TODO ocatal constants + case 'x': case 'X': return -1; // @TODO hex constants + case 'u': return -1; // @TODO unicode constants + } + } + *q = p+1; + return (unsigned char) *p; +} + +static int stb__clex_parse_string(stb_lexer *lexer, char *p, int type) +{ + char *start = p; + char delim = *p++; // grab the " or ' for later matching + char *out = lexer->string_storage; + char *outend = lexer->string_storage + lexer->string_storage_len; + while (*p != delim) { + int n; + if (*p == '\\') { + char *q; + n = stb__clex_parse_char(p, &q); + if (n < 0) + return stb__clex_token(lexer, CLEX_parse_error, start, q); + p = q; + } else { + // @OPTIMIZE: could speed this up by looping-while-not-backslash + n = (unsigned char) *p++; + } + if (out+1 > outend) + return stb__clex_token(lexer, CLEX_parse_error, start, p); + // @TODO expand unicode escapes to UTF8 + *out++ = (char) n; + } + *out = 0; + lexer->string = lexer->string_storage; + lexer->string_len = (int) (out - lexer->string_storage); + return stb__clex_token(lexer, type, start, p); +} + +int stb_c_lexer_get_token(stb_lexer *lexer) +{ + char *p = lexer->parse_point; + + // skip whitespace and comments + for (;;) { + #ifdef STB_C_LEX_ISWHITE + while (p != lexer->stream_end) { + int n; + n = STB_C_LEX_ISWHITE(p); + if (n == 0) break; + if (lexer->eof && lexer->eof - lexer->parse_point < n) + return stb__clex_token(tok, CLEX_parse_error, p,lexer->eof-1); + p += n; + } + #else + while (p != lexer->eof && stb__clex_iswhite(*p)) + ++p; + #endif + + STB_C_LEX_CPP_COMMENTS( + if (p != lexer->eof && p[0] == '/' && p[1] == '/') { + while (p != lexer->eof && *p != '\r' && *p != '\n') + ++p; + continue; + } + ) + + STB_C_LEX_C_COMMENTS( + if (p != lexer->eof && p[0] == '/' && p[1] == '*') { + char *start = p; + p += 2; + while (p != lexer->eof && (p[0] != '*' || p[1] != '/')) + ++p; + if (p == lexer->eof) + return stb__clex_token(lexer, CLEX_parse_error, start, p-1); + p += 2; + continue; + } + ) + + #ifdef STB__clex_discard_preprocessor + // @TODO this discards everything after a '#', regardless + // of where in the line the # is, rather than requiring it + // be at the start. (because this parser doesn't otherwise + // check for line breaks!) + if (p != lexer->eof && p[0] == '#') { + while (p != lexer->eof && *p != '\r' && *p != '\n') + ++p; + continue; + } + #endif + + break; + } + + if (p == lexer->eof) + return stb__clex_eof(lexer); + + switch (*p) { + default: + if ( (*p >= 'a' && *p <= 'z') + || (*p >= 'A' && *p <= 'Z') + || *p == '_' || (unsigned char) *p >= 128 // >= 128 is UTF8 char + STB_C_LEX_DOLLAR_IDENTIFIER( || *p == '$' ) ) + { + int n = 0; + lexer->string = lexer->string_storage; + do { + if (n+1 >= lexer->string_storage_len) + return stb__clex_token(lexer, CLEX_parse_error, p, p+n); + lexer->string[n] = p[n]; + ++n; + } while ( + (p[n] >= 'a' && p[n] <= 'z') + || (p[n] >= 'A' && p[n] <= 'Z') + || (p[n] >= '0' && p[n] <= '9') // allow digits in middle of identifier + || p[n] == '_' || (unsigned char) p[n] >= 128 + STB_C_LEX_DOLLAR_IDENTIFIER( || p[n] == '$' ) + ); + lexer->string[n] = 0; + lexer->string_len = n; + return stb__clex_token(lexer, CLEX_id, p, p+n-1); + } + + // check for EOF + STB_C_LEX_0_IS_EOF( + if (*p == 0) + return stb__clex_eof(lexer); + ) + + single_char: + // not an identifier, return the character as itself + return stb__clex_token(lexer, *p, p, p); + + case '+': + if (p+1 != lexer->eof) { + STB_C_LEX_C_INCREMENTS(if (p[1] == '+') return stb__clex_token(lexer, CLEX_plusplus, p,p+1);) + STB_C_LEX_C_ARITHEQ( if (p[1] == '=') return stb__clex_token(lexer, CLEX_pluseq , p,p+1);) + } + goto single_char; + case '-': + if (p+1 != lexer->eof) { + STB_C_LEX_C_INCREMENTS(if (p[1] == '-') return stb__clex_token(lexer, CLEX_minusminus, p,p+1);) + STB_C_LEX_C_ARITHEQ( if (p[1] == '=') return stb__clex_token(lexer, CLEX_minuseq , p,p+1);) + STB_C_LEX_C_ARROW( if (p[1] == '>') return stb__clex_token(lexer, CLEX_arrow , p,p+1);) + } + goto single_char; + case '&': + if (p+1 != lexer->eof) { + STB_C_LEX_C_LOGICAL( if (p[1] == '&') return stb__clex_token(lexer, CLEX_andand, p,p+1);) + STB_C_LEX_C_BITWISEEQ(if (p[1] == '=') return stb__clex_token(lexer, CLEX_andeq , p,p+1);) + } + goto single_char; + case '|': + if (p+1 != lexer->eof) { + STB_C_LEX_C_LOGICAL( if (p[1] == '|') return stb__clex_token(lexer, CLEX_oror, p,p+1);) + STB_C_LEX_C_BITWISEEQ(if (p[1] == '=') return stb__clex_token(lexer, CLEX_oreq, p,p+1);) + } + goto single_char; + case '=': + if (p+1 != lexer->eof) { + STB_C_LEX_C_COMPARISONS(if (p[1] == '=') return stb__clex_token(lexer, CLEX_eq, p,p+1);) + STB_C_LEX_EQUAL_ARROW( if (p[1] == '>') return stb__clex_token(lexer, CLEX_eqarrow, p,p+1);) + } + goto single_char; + case '!': + STB_C_LEX_C_COMPARISONS(if (p+1 != lexer->eof && p[1] == '=') return stb__clex_token(lexer, CLEX_noteq, p,p+1);) + goto single_char; + case '^': + STB_C_LEX_C_BITWISEEQ(if (p+1 != lexer->eof && p[1] == '=') return stb__clex_token(lexer, CLEX_xoreq, p,p+1)); + goto single_char; + case '%': + STB_C_LEX_C_ARITHEQ(if (p+1 != lexer->eof && p[1] == '=') return stb__clex_token(lexer, CLEX_modeq, p,p+1)); + goto single_char; + case '*': + STB_C_LEX_C_ARITHEQ(if (p+1 != lexer->eof && p[1] == '=') return stb__clex_token(lexer, CLEX_muleq, p,p+1)); + goto single_char; + case '/': + STB_C_LEX_C_ARITHEQ(if (p+1 != lexer->eof && p[1] == '=') return stb__clex_token(lexer, CLEX_diveq, p,p+1)); + goto single_char; + case '<': + if (p+1 != lexer->eof) { + STB_C_LEX_C_COMPARISONS(if (p[1] == '=') return stb__clex_token(lexer, CLEX_lesseq, p,p+1);) + STB_C_LEX_C_SHIFTS( if (p[1] == '<') { + STB_C_LEX_C_ARITHEQ(if (p+2 != lexer->eof && p[2] == '=') + return stb__clex_token(lexer, CLEX_shleq, p,p+2);) + return stb__clex_token(lexer, CLEX_shl, p,p+1); + } + ) + } + goto single_char; + case '>': + if (p+1 != lexer->eof) { + STB_C_LEX_C_COMPARISONS(if (p[1] == '=') return stb__clex_token(lexer, CLEX_greatereq, p,p+1);) + STB_C_LEX_C_SHIFTS( if (p[1] == '>') { + STB_C_LEX_C_ARITHEQ(if (p+2 != lexer->eof && p[2] == '=') + return stb__clex_token(lexer, CLEX_shreq, p,p+2);) + return stb__clex_token(lexer, CLEX_shr, p,p+1); + } + ) + } + goto single_char; + + case '"': + STB_C_LEX_C_DQ_STRINGS(return stb__clex_parse_string(lexer, p, CLEX_dqstring);) + goto single_char; + case '\'': + STB_C_LEX_C_SQ_STRINGS(return stb__clex_parse_string(lexer, p, CLEX_sqstring);) + STB_C_LEX_C_CHARS( + { + char *start = p; + lexer->int_number = stb__clex_parse_char(p+1, &p); + if (lexer->int_number < 0) + return stb__clex_token(lexer, CLEX_parse_error, start,start); + if (p == lexer->eof || *p != '\'') + return stb__clex_token(lexer, CLEX_parse_error, start,p); + return stb__clex_token(lexer, CLEX_charlit, start, p+1); + }) + goto single_char; + + case '0': + #if defined(STB__clex_hex_ints) || defined(STB__clex_hex_floats) + if (p+1 != lexer->eof) { + if (p[1] == 'x' || p[1] == 'X') { + char *q; + + #ifdef STB__clex_hex_floats + for (q=p+2; + q != lexer->eof && ((*q >= '0' && *q <= '9') || (*q >= 'a' && *q <= 'f') || (*q >= 'A' && *q <= 'F')); + ++q); + if (q != lexer->eof) { + if (*q == '.' STB_C_LEX_FLOAT_NO_DECIMAL(|| *q == 'p' || *q == 'P')) { + #ifdef STB__CLEX_use_stdlib + lexer->real_number = strtod((char *) p, (char**) &q); + #else + lexer->real_number = stb__clex_parse_float(p, &q); + #endif + + if (p == q) + return stb__clex_token(lexer, CLEX_parse_error, p,q); + return stb__clex_parse_suffixes(lexer, CLEX_floatlit, p,q, STB_C_LEX_FLOAT_SUFFIXES); + + } + } + #endif // STB__CLEX_hex_floats + + #ifdef STB__clex_hex_ints + #ifdef STB__CLEX_use_stdlib + lexer->int_number = strtol((char *) p, (char **) &q, 16); + #else + { + stb__clex_int n=0; + for (q=p+2; q != lexer->eof; ++q) { + if (*q >= '0' && *q <= '9') + n = n*16 + (*q - '0'); + else if (*q >= 'a' && *q <= 'f') + n = n*16 + (*q - 'a') + 10; + else if (*q >= 'A' && *q <= 'F') + n = n*16 + (*q - 'A') + 10; + else + break; + } + lexer->int_number = n; + } + #endif + if (q == p+2) + return stb__clex_token(lexer, CLEX_parse_error, p-2,p-1); + return stb__clex_parse_suffixes(lexer, CLEX_intlit, p,q, STB_C_LEX_HEX_SUFFIXES); + #endif + } + } + #endif // defined(STB__clex_hex_ints) || defined(STB__clex_hex_floats) + // can't test for octal because we might parse '0.0' as float or as '0' '.' '0', + // so have to do float first + + /* FALL THROUGH */ + case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + + #ifdef STB__clex_decimal_floats + { + char *q = p; + while (q != lexer->eof && (*q >= '0' && *q <= '9')) + ++q; + if (q != lexer->eof) { + if (*q == '.' STB_C_LEX_FLOAT_NO_DECIMAL(|| *q == 'e' || *q == 'E')) { + #ifdef STB__CLEX_use_stdlib + lexer->real_number = strtod((char *) p, (char**) &q); + #else + lexer->real_number = stb__clex_parse_float(p, &q); + #endif + + return stb__clex_parse_suffixes(lexer, CLEX_floatlit, p,q, STB_C_LEX_FLOAT_SUFFIXES); + + } + } + } + #endif // STB__clex_decimal_floats + + #ifdef STB__clex_octal_ints + if (p[0] == '0') { + char *q = p; + #ifdef STB__CLEX_use_stdlib + lexer->int_number = strtol((char *) p, (char **) &q, 8); + #else + stb__clex_int n=0; + while (q != lexer->eof) { + if (*q >= '0' && *q <= '7') + n = n*8 + (*q - '0'); + else + break; + ++q; + } + if (q != lexer->eof && (*q == '8' || *q=='9')) + return stb__clex_token(lexer, CLEX_parse_error, p, q); + lexer->int_number = n; + #endif + return stb__clex_parse_suffixes(lexer, CLEX_intlit, p,q, STB_C_LEX_OCTAL_SUFFIXES); + } + #endif // STB__clex_octal_ints + + #ifdef STB__clex_decimal_ints + { + char *q = p; + #ifdef STB__CLEX_use_stdlib + lexer->int_number = strtol((char *) p, (char **) &q, 10); + #else + stb__clex_int n=0; + while (q != lexer->eof) { + if (*q >= '0' && *q <= '9') + n = n*10 + (*q - '0'); + else + break; + ++q; + } + lexer->int_number = n; + #endif + return stb__clex_parse_suffixes(lexer, CLEX_intlit, p,q, STB_C_LEX_OCTAL_SUFFIXES); + } + #endif // STB__clex_decimal_ints + goto single_char; + } +} +#endif // STB_C_LEXER_IMPLEMENTATION + +#ifdef STB_C_LEXER_SELF_TEST +#define _CRT_SECURE_NO_WARNINGS +#include +#include + +static void print_token(stb_lexer *lexer) +{ + switch (lexer->token) { + case CLEX_id : printf("_%s", lexer->string); break; + case CLEX_eq : printf("=="); break; + case CLEX_noteq : printf("!="); break; + case CLEX_lesseq : printf("<="); break; + case CLEX_greatereq : printf(">="); break; + case CLEX_andand : printf("&&"); break; + case CLEX_oror : printf("||"); break; + case CLEX_shl : printf("<<"); break; + case CLEX_shr : printf(">>"); break; + case CLEX_plusplus : printf("++"); break; + case CLEX_minusminus: printf("--"); break; + case CLEX_arrow : printf("->"); break; + case CLEX_andeq : printf("&="); break; + case CLEX_oreq : printf("|="); break; + case CLEX_xoreq : printf("^="); break; + case CLEX_pluseq : printf("+="); break; + case CLEX_minuseq : printf("-="); break; + case CLEX_muleq : printf("*="); break; + case CLEX_diveq : printf("/="); break; + case CLEX_modeq : printf("%%="); break; + case CLEX_shleq : printf("<<="); break; + case CLEX_shreq : printf(">>="); break; + case CLEX_eqarrow : printf("=>"); break; + case CLEX_dqstring : printf("\"%s\"", lexer->string); break; + case CLEX_sqstring : printf("'\"%s\"'", lexer->string); break; + case CLEX_charlit : printf("'%s'", lexer->string); break; + #if defined(STB__clex_int_as_double) && !defined(STB__CLEX_use_stdlib) + case CLEX_intlit : printf("#%g", lexer->real_number); break; + #else + case CLEX_intlit : printf("#%ld", lexer->int_number); break; + #endif + case CLEX_floatlit : printf("%g", lexer->real_number); break; + default: + if (lexer->token >= 0 && lexer->token < 256) + printf("%c", (int) lexer->token); + else { + printf("<<>>\n", lexer->token); + } + break; + } +} + +/* Force a test +of parsing +multiline comments */ + +/*/ comment /*/ +/**/ extern /**/ + +void dummy(void) +{ + double some_floats[] = { + 1.0501, -10.4e12, 5E+10, +#if 0 // not supported in C++ or C-pre-99, so don't try to compile it, but let our parser test it + 0x1.0p+24, 0xff.FP-8, 0x1p-23, +#endif + 4. + }; + (void) sizeof(some_floats); + (void) some_floats[1]; + + printf("test %d",1); // https://github.com/nothings/stb/issues/13 +} + +int main(int argc, char **argv) +{ + FILE *f = fopen("stb_c_lexer.h","rb"); + char *text = (char *) malloc(1 << 20); + int len = f ? (int) fread(text, 1, 1<<20, f) : -1; + stb_lexer lex; + if (len < 0) { + fprintf(stderr, "Error opening file\n"); + free(text); + fclose(f); + return 1; + } + fclose(f); + + stb_c_lexer_init(&lex, text, text+len, (char *) malloc(0x10000), 0x10000); + while (stb_c_lexer_get_token(&lex)) { + if (lex.token == CLEX_parse_error) { + printf("\n<<>>\n"); + break; + } + print_token(&lex); + printf(" "); + } + return 0; +} +#endif +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_connected_components.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_connected_components.h new file mode 100644 index 0000000..f762f65 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_connected_components.h @@ -0,0 +1,1049 @@ +// stb_connected_components - v0.96 - public domain connected components on grids +// http://github.com/nothings/stb +// +// Finds connected components on 2D grids for testing reachability between +// two points, with fast updates when changing reachability (e.g. on one machine +// it was typically 0.2ms w/ 1024x1024 grid). Each grid square must be "open" or +// "closed" (traversable or untraversable), and grid squares are only connected +// to their orthogonal neighbors, not diagonally. +// +// In one source file, create the implementation by doing something like this: +// +// #define STBCC_GRID_COUNT_X_LOG2 10 +// #define STBCC_GRID_COUNT_Y_LOG2 10 +// #define STB_CONNECTED_COMPONENTS_IMPLEMENTATION +// #include "stb_connected_components.h" +// +// The above creates an implementation that can run on maps up to 1024x1024. +// Map sizes must be a multiple of (1<<(LOG2/2)) on each axis (e.g. 32 if LOG2=10, +// 16 if LOG2=8, etc.) (You can just pad your map with untraversable space.) +// +// MEMORY USAGE +// +// Uses about 6-7 bytes per grid square (e.g. 7MB for a 1024x1024 grid). +// Uses a single worst-case allocation which you pass in. +// +// PERFORMANCE +// +// On a core i7-2700K at 3.5 Ghz, for a particular 1024x1024 map (map_03.png): +// +// Creating map : 44.85 ms +// Making one square traversable: 0.27 ms (average over 29,448 calls) +// Making one square untraversable: 0.23 ms (average over 30,123 calls) +// Reachability query: 0.00001 ms (average over 4,000,000 calls) +// +// On non-degenerate maps update time is O(N^0.5), but on degenerate maps like +// checkerboards or 50% random, update time is O(N^0.75) (~2ms on above machine). +// +// CHANGELOG +// +// 0.96 (2019-03-04) Fix warnings +// 0.95 (2016-10-16) Bugfix if multiple clumps in one cluster connect to same clump in another +// 0.94 (2016-04-17) Bugfix & optimize worst case (checkerboard & random) +// 0.93 (2016-04-16) Reduce memory by 10x for 1Kx1K map; small speedup +// 0.92 (2016-04-16) Compute sqrt(N) cluster size by default +// 0.91 (2016-04-15) Initial release +// +// TODO: +// - better API documentation +// - more comments +// - try re-integrating naive algorithm & compare performance +// - more optimized batching (current approach still recomputes local clumps many times) +// - function for setting a grid of squares at once (just use batching) +// +// LICENSE +// +// See end of file for license information. +// +// ALGORITHM +// +// The NxN grid map is split into sqrt(N) x sqrt(N) blocks called +// "clusters". Each cluster independently computes a set of connected +// components within that cluster (ignoring all connectivity out of +// that cluster) using a union-find disjoint set forest. This produces a bunch +// of locally connected components called "clumps". Each clump is (a) connected +// within its cluster, (b) does not directly connect to any other clumps in the +// cluster (though it may connect to them by paths that lead outside the cluster, +// but those are ignored at this step), and (c) maintains an adjacency list of +// all clumps in adjacent clusters that it _is_ connected to. Then a second +// union-find disjoint set forest is used to compute connected clumps +// globally, across the whole map. Reachability is then computed by +// finding which clump each input point belongs to, and checking whether +// those clumps are in the same "global" connected component. +// +// The above data structure can be updated efficiently; on a change +// of a single grid square on the map, only one cluster changes its +// purely-local state, so only one cluster needs its clumps fully +// recomputed. Clumps in adjacent clusters need their adjacency lists +// updated: first to remove all references to the old clumps in the +// rebuilt cluster, then to add new references to the new clumps. Both +// of these operations can use the existing "find which clump each input +// point belongs to" query to compute that adjacency information rapidly. + +#ifndef INCLUDE_STB_CONNECTED_COMPONENTS_H +#define INCLUDE_STB_CONNECTED_COMPONENTS_H + +#include + +typedef struct st_stbcc_grid stbcc_grid; + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////////////////////////////////////////////// +// +// initialization +// + +// you allocate the grid data structure to this size (note that it will be very big!!!) +extern size_t stbcc_grid_sizeof(void); + +// initialize the grid, value of map[] is 0 = traversable, non-0 is solid +extern void stbcc_init_grid(stbcc_grid *g, unsigned char *map, int w, int h); + + +////////////////////////////////////////////////////////////////////////////////////////// +// +// main functionality +// + +// update a grid square state, 0 = traversable, non-0 is solid +// i can add a batch-update if it's needed +extern void stbcc_update_grid(stbcc_grid *g, int x, int y, int solid); + +// query if two grid squares are reachable from each other +extern int stbcc_query_grid_node_connection(stbcc_grid *g, int x1, int y1, int x2, int y2); + + +////////////////////////////////////////////////////////////////////////////////////////// +// +// bonus functions +// + +// wrap multiple stbcc_update_grid calls in these function to compute +// multiple updates more efficiently; cannot make queries inside batch +extern void stbcc_update_batch_begin(stbcc_grid *g); +extern void stbcc_update_batch_end(stbcc_grid *g); + +// query the grid data structure for whether a given square is open or not +extern int stbcc_query_grid_open(stbcc_grid *g, int x, int y); + +// get a unique id for the connected component this is in; it's not necessarily +// small, you'll need a hash table or something to remap it (or just use +extern unsigned int stbcc_get_unique_id(stbcc_grid *g, int x, int y); +#define STBCC_NULL_UNIQUE_ID 0xffffffff // returned for closed map squares + +#ifdef __cplusplus +} +#endif + +#endif // INCLUDE_STB_CONNECTED_COMPONENTS_H + +#ifdef STB_CONNECTED_COMPONENTS_IMPLEMENTATION + +#include +#include // memset + +#if !defined(STBCC_GRID_COUNT_X_LOG2) || !defined(STBCC_GRID_COUNT_Y_LOG2) + #error "You must define STBCC_GRID_COUNT_X_LOG2 and STBCC_GRID_COUNT_Y_LOG2 to define the max grid supported." +#endif + +#define STBCC__GRID_COUNT_X (1 << STBCC_GRID_COUNT_X_LOG2) +#define STBCC__GRID_COUNT_Y (1 << STBCC_GRID_COUNT_Y_LOG2) + +#define STBCC__MAP_STRIDE (1 << (STBCC_GRID_COUNT_X_LOG2-3)) + +#ifndef STBCC_CLUSTER_SIZE_X_LOG2 + #define STBCC_CLUSTER_SIZE_X_LOG2 (STBCC_GRID_COUNT_X_LOG2/2) // log2(sqrt(2^N)) = 1/2 * log2(2^N)) = 1/2 * N + #if STBCC_CLUSTER_SIZE_X_LOG2 > 6 + #undef STBCC_CLUSTER_SIZE_X_LOG2 + #define STBCC_CLUSTER_SIZE_X_LOG2 6 + #endif +#endif + +#ifndef STBCC_CLUSTER_SIZE_Y_LOG2 + #define STBCC_CLUSTER_SIZE_Y_LOG2 (STBCC_GRID_COUNT_Y_LOG2/2) + #if STBCC_CLUSTER_SIZE_Y_LOG2 > 6 + #undef STBCC_CLUSTER_SIZE_Y_LOG2 + #define STBCC_CLUSTER_SIZE_Y_LOG2 6 + #endif +#endif + +#define STBCC__CLUSTER_SIZE_X (1 << STBCC_CLUSTER_SIZE_X_LOG2) +#define STBCC__CLUSTER_SIZE_Y (1 << STBCC_CLUSTER_SIZE_Y_LOG2) + +#define STBCC__CLUSTER_COUNT_X_LOG2 (STBCC_GRID_COUNT_X_LOG2 - STBCC_CLUSTER_SIZE_X_LOG2) +#define STBCC__CLUSTER_COUNT_Y_LOG2 (STBCC_GRID_COUNT_Y_LOG2 - STBCC_CLUSTER_SIZE_Y_LOG2) + +#define STBCC__CLUSTER_COUNT_X (1 << STBCC__CLUSTER_COUNT_X_LOG2) +#define STBCC__CLUSTER_COUNT_Y (1 << STBCC__CLUSTER_COUNT_Y_LOG2) + +#if STBCC__CLUSTER_SIZE_X >= STBCC__GRID_COUNT_X || STBCC__CLUSTER_SIZE_Y >= STBCC__GRID_COUNT_Y + #error "STBCC_CLUSTER_SIZE_X/Y_LOG2 must be smaller than STBCC_GRID_COUNT_X/Y_LOG2" +#endif + +// worst case # of clumps per cluster +#define STBCC__MAX_CLUMPS_PER_CLUSTER_LOG2 (STBCC_CLUSTER_SIZE_X_LOG2 + STBCC_CLUSTER_SIZE_Y_LOG2-1) +#define STBCC__MAX_CLUMPS_PER_CLUSTER (1 << STBCC__MAX_CLUMPS_PER_CLUSTER_LOG2) +#define STBCC__MAX_CLUMPS (STBCC__MAX_CLUMPS_PER_CLUSTER * STBCC__CLUSTER_COUNT_X * STBCC__CLUSTER_COUNT_Y) +#define STBCC__NULL_CLUMPID STBCC__MAX_CLUMPS_PER_CLUSTER + +#define STBCC__CLUSTER_X_FOR_COORD_X(x) ((x) >> STBCC_CLUSTER_SIZE_X_LOG2) +#define STBCC__CLUSTER_Y_FOR_COORD_Y(y) ((y) >> STBCC_CLUSTER_SIZE_Y_LOG2) + +#define STBCC__MAP_BYTE_MASK(x,y) (1 << ((x) & 7)) +#define STBCC__MAP_BYTE(g,x,y) ((g)->map[y][(x) >> 3]) +#define STBCC__MAP_OPEN(g,x,y) (STBCC__MAP_BYTE(g,x,y) & STBCC__MAP_BYTE_MASK(x,y)) + +typedef unsigned short stbcc__clumpid; +typedef unsigned char stbcc__verify_max_clumps[STBCC__MAX_CLUMPS_PER_CLUSTER < (1 << (8*sizeof(stbcc__clumpid))) ? 1 : -1]; + +#define STBCC__MAX_EXITS_PER_CLUSTER (STBCC__CLUSTER_SIZE_X + STBCC__CLUSTER_SIZE_Y) // 64 for 32x32 +#define STBCC__MAX_EXITS_PER_CLUMP (STBCC__CLUSTER_SIZE_X + STBCC__CLUSTER_SIZE_Y) // 64 for 32x32 +#define STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER (STBCC__MAX_EXITS_PER_CLUMP) + +// 2^19 * 2^6 => 2^25 exits => 2^26 => 64MB for 1024x1024 + +// Logic for above on 4x4 grid: +// +// Many clumps: One clump: +// + + + + +// +X.X. +XX.X+ +// .X.X+ .XXX +// +X.X. XXX. +// .X.X+ +X.XX+ +// + + + + +// +// 8 exits either way + +typedef unsigned char stbcc__verify_max_exits[STBCC__MAX_EXITS_PER_CLUMP <= 256]; + +typedef struct +{ + unsigned short clump_index:12; + signed short cluster_dx:2; + signed short cluster_dy:2; +} stbcc__relative_clumpid; + +typedef union +{ + struct { + unsigned int clump_index:12; + unsigned int cluster_x:10; + unsigned int cluster_y:10; + } f; + unsigned int c; +} stbcc__global_clumpid; + +// rebuilt cluster 3,4 + +// what changes in cluster 2,4 + +typedef struct +{ + stbcc__global_clumpid global_label; // 4 + unsigned char num_adjacent; // 1 + unsigned char max_adjacent; // 1 + unsigned char adjacent_clump_list_index; // 1 + unsigned char reserved; +} stbcc__clump; // 8 + +#define STBCC__CLUSTER_ADJACENCY_COUNT (STBCC__MAX_EXITS_PER_CLUSTER*2) +typedef struct +{ + short num_clumps; + unsigned char num_edge_clumps; + unsigned char rebuild_adjacency; + stbcc__clump clump[STBCC__MAX_CLUMPS_PER_CLUSTER]; // 8 * 2^9 = 4KB + stbcc__relative_clumpid adjacency_storage[STBCC__CLUSTER_ADJACENCY_COUNT]; // 256 bytes +} stbcc__cluster; + +struct st_stbcc_grid +{ + int w,h,cw,ch; + int in_batched_update; + //unsigned char cluster_dirty[STBCC__CLUSTER_COUNT_Y][STBCC__CLUSTER_COUNT_X]; // could bitpack, but: 1K x 1K => 1KB + unsigned char map[STBCC__GRID_COUNT_Y][STBCC__MAP_STRIDE]; // 1K x 1K => 1K x 128 => 128KB + stbcc__clumpid clump_for_node[STBCC__GRID_COUNT_Y][STBCC__GRID_COUNT_X]; // 1K x 1K x 2 = 2MB + stbcc__cluster cluster[STBCC__CLUSTER_COUNT_Y][STBCC__CLUSTER_COUNT_X]; // 1K x 4.5KB = 4.5MB +}; + +int stbcc_query_grid_node_connection(stbcc_grid *g, int x1, int y1, int x2, int y2) +{ + stbcc__global_clumpid label1, label2; + stbcc__clumpid c1 = g->clump_for_node[y1][x1]; + stbcc__clumpid c2 = g->clump_for_node[y2][x2]; + int cx1 = STBCC__CLUSTER_X_FOR_COORD_X(x1); + int cy1 = STBCC__CLUSTER_Y_FOR_COORD_Y(y1); + int cx2 = STBCC__CLUSTER_X_FOR_COORD_X(x2); + int cy2 = STBCC__CLUSTER_Y_FOR_COORD_Y(y2); + assert(!g->in_batched_update); + if (c1 == STBCC__NULL_CLUMPID || c2 == STBCC__NULL_CLUMPID) + return 0; + label1 = g->cluster[cy1][cx1].clump[c1].global_label; + label2 = g->cluster[cy2][cx2].clump[c2].global_label; + if (label1.c == label2.c) + return 1; + return 0; +} + +int stbcc_query_grid_open(stbcc_grid *g, int x, int y) +{ + return STBCC__MAP_OPEN(g, x, y) != 0; +} + +unsigned int stbcc_get_unique_id(stbcc_grid *g, int x, int y) +{ + stbcc__clumpid c = g->clump_for_node[y][x]; + int cx = STBCC__CLUSTER_X_FOR_COORD_X(x); + int cy = STBCC__CLUSTER_Y_FOR_COORD_Y(y); + assert(!g->in_batched_update); + if (c == STBCC__NULL_CLUMPID) return STBCC_NULL_UNIQUE_ID; + return g->cluster[cy][cx].clump[c].global_label.c; +} + +typedef struct +{ + unsigned char x,y; +} stbcc__tinypoint; + +typedef struct +{ + stbcc__tinypoint parent[STBCC__CLUSTER_SIZE_Y][STBCC__CLUSTER_SIZE_X]; // 32x32 => 2KB + stbcc__clumpid label[STBCC__CLUSTER_SIZE_Y][STBCC__CLUSTER_SIZE_X]; +} stbcc__cluster_build_info; + +static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy); +static void stbcc__remove_connections_to_adjacent_cluster(stbcc_grid *g, int cx, int cy, int dx, int dy); +static void stbcc__add_connections_to_adjacent_cluster(stbcc_grid *g, int cx, int cy, int dx, int dy); + +static stbcc__global_clumpid stbcc__clump_find(stbcc_grid *g, stbcc__global_clumpid n) +{ + stbcc__global_clumpid q; + stbcc__clump *c = &g->cluster[n.f.cluster_y][n.f.cluster_x].clump[n.f.clump_index]; + + if (c->global_label.c == n.c) + return n; + + q = stbcc__clump_find(g, c->global_label); + c->global_label = q; + return q; +} + +typedef struct +{ + unsigned int cluster_x; + unsigned int cluster_y; + unsigned int clump_index; +} stbcc__unpacked_clumpid; + +static void stbcc__clump_union(stbcc_grid *g, stbcc__unpacked_clumpid m, int x, int y, int idx) +{ + stbcc__clump *mc = &g->cluster[m.cluster_y][m.cluster_x].clump[m.clump_index]; + stbcc__clump *nc = &g->cluster[y][x].clump[idx]; + stbcc__global_clumpid mp = stbcc__clump_find(g, mc->global_label); + stbcc__global_clumpid np = stbcc__clump_find(g, nc->global_label); + + if (mp.c == np.c) + return; + + g->cluster[mp.f.cluster_y][mp.f.cluster_x].clump[mp.f.clump_index].global_label = np; +} + +static void stbcc__build_connected_components_for_clumps(stbcc_grid *g) +{ + int i,j,k,h; + + for (j=0; j < STBCC__CLUSTER_COUNT_Y; ++j) { + for (i=0; i < STBCC__CLUSTER_COUNT_X; ++i) { + stbcc__cluster *cluster = &g->cluster[j][i]; + for (k=0; k < (int) cluster->num_edge_clumps; ++k) { + stbcc__global_clumpid m; + m.f.clump_index = k; + m.f.cluster_x = i; + m.f.cluster_y = j; + assert((int) m.f.clump_index == k && (int) m.f.cluster_x == i && (int) m.f.cluster_y == j); + cluster->clump[k].global_label = m; + } + } + } + + for (j=0; j < STBCC__CLUSTER_COUNT_Y; ++j) { + for (i=0; i < STBCC__CLUSTER_COUNT_X; ++i) { + stbcc__cluster *cluster = &g->cluster[j][i]; + for (k=0; k < (int) cluster->num_edge_clumps; ++k) { + stbcc__clump *clump = &cluster->clump[k]; + stbcc__unpacked_clumpid m; + stbcc__relative_clumpid *adj; + m.clump_index = k; + m.cluster_x = i; + m.cluster_y = j; + adj = &cluster->adjacency_storage[clump->adjacent_clump_list_index]; + for (h=0; h < clump->num_adjacent; ++h) { + unsigned int clump_index = adj[h].clump_index; + unsigned int x = adj[h].cluster_dx + i; + unsigned int y = adj[h].cluster_dy + j; + stbcc__clump_union(g, m, x, y, clump_index); + } + } + } + } + + for (j=0; j < STBCC__CLUSTER_COUNT_Y; ++j) { + for (i=0; i < STBCC__CLUSTER_COUNT_X; ++i) { + stbcc__cluster *cluster = &g->cluster[j][i]; + for (k=0; k < (int) cluster->num_edge_clumps; ++k) { + stbcc__global_clumpid m; + m.f.clump_index = k; + m.f.cluster_x = i; + m.f.cluster_y = j; + stbcc__clump_find(g, m); + } + } + } +} + +static void stbcc__build_all_connections_for_cluster(stbcc_grid *g, int cx, int cy) +{ + // in this particular case, we are fully non-incremental. that means we + // can discover the correct sizes for the arrays, but requires we build + // the data into temporary data structures, or just count the sizes, so + // for simplicity we do the latter + stbcc__cluster *cluster = &g->cluster[cy][cx]; + unsigned char connected[STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER][STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER/8]; // 64 x 8 => 1KB + unsigned char num_adj[STBCC__MAX_CLUMPS_PER_CLUSTER] = { 0 }; + int x = cx * STBCC__CLUSTER_SIZE_X; + int y = cy * STBCC__CLUSTER_SIZE_Y; + int step_x, step_y=0, i, j, k, n, m, dx, dy, total; + int extra; + + g->cluster[cy][cx].rebuild_adjacency = 0; + + total = 0; + for (m=0; m < 4; ++m) { + switch (m) { + case 0: + dx = 1, dy = 0; + step_x = 0, step_y = 1; + i = STBCC__CLUSTER_SIZE_X-1; + j = 0; + n = STBCC__CLUSTER_SIZE_Y; + break; + case 1: + dx = -1, dy = 0; + i = 0; + j = 0; + step_x = 0; + step_y = 1; + n = STBCC__CLUSTER_SIZE_Y; + break; + case 2: + dy = -1, dx = 0; + i = 0; + j = 0; + step_x = 1; + step_y = 0; + n = STBCC__CLUSTER_SIZE_X; + break; + case 3: + dy = 1, dx = 0; + i = 0; + j = STBCC__CLUSTER_SIZE_Y-1; + step_x = 1; + step_y = 0; + n = STBCC__CLUSTER_SIZE_X; + break; + } + + if (cx+dx < 0 || cx+dx >= g->cw || cy+dy < 0 || cy+dy >= g->ch) + continue; + + memset(connected, 0, sizeof(connected)); + for (k=0; k < n; ++k) { + if (STBCC__MAP_OPEN(g, x+i, y+j) && STBCC__MAP_OPEN(g, x+i+dx, y+j+dy)) { + stbcc__clumpid src = g->clump_for_node[y+j][x+i]; + stbcc__clumpid dest = g->clump_for_node[y+j+dy][x+i+dx]; + if (0 == (connected[src][dest>>3] & (1 << (dest & 7)))) { + connected[src][dest>>3] |= 1 << (dest & 7); + ++num_adj[src]; + ++total; + } + } + i += step_x; + j += step_y; + } + } + + assert(total <= STBCC__CLUSTER_ADJACENCY_COUNT); + + // decide how to apportion unused adjacency slots; only clumps that lie + // on the edges of the cluster need adjacency slots, so divide them up + // evenly between those clumps + + // we want: + // extra = (STBCC__CLUSTER_ADJACENCY_COUNT - total) / cluster->num_edge_clumps; + // but we efficiently approximate this without a divide, because + // ignoring edge-vs-non-edge with 'num_adj[i]*2' was faster than + // 'num_adj[i]+extra' with the divide + if (total + (cluster->num_edge_clumps<<2) <= STBCC__CLUSTER_ADJACENCY_COUNT) + extra = 4; + else if (total + (cluster->num_edge_clumps<<1) <= STBCC__CLUSTER_ADJACENCY_COUNT) + extra = 2; + else if (total + (cluster->num_edge_clumps<<0) <= STBCC__CLUSTER_ADJACENCY_COUNT) + extra = 1; + else + extra = 0; + + total = 0; + for (i=0; i < (int) cluster->num_edge_clumps; ++i) { + int alloc = num_adj[i]+extra; + if (alloc > STBCC__MAX_EXITS_PER_CLUSTER) + alloc = STBCC__MAX_EXITS_PER_CLUSTER; + assert(total < 256); // must fit in byte + cluster->clump[i].adjacent_clump_list_index = (unsigned char) total; + cluster->clump[i].max_adjacent = alloc; + cluster->clump[i].num_adjacent = 0; + total += alloc; + } + assert(total <= STBCC__CLUSTER_ADJACENCY_COUNT); + + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, -1, 0); + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 1, 0); + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0,-1); + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0, 1); + // make sure all of the above succeeded. + assert(g->cluster[cy][cx].rebuild_adjacency == 0); +} + +static void stbcc__add_connections_to_adjacent_cluster_with_rebuild(stbcc_grid *g, int cx, int cy, int dx, int dy) +{ + if (cx >= 0 && cx < g->cw && cy >= 0 && cy < g->ch) { + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, dx, dy); + if (g->cluster[cy][cx].rebuild_adjacency) + stbcc__build_all_connections_for_cluster(g, cx, cy); + } +} + +void stbcc_update_grid(stbcc_grid *g, int x, int y, int solid) +{ + int cx,cy; + + if (!solid) { + if (STBCC__MAP_OPEN(g,x,y)) + return; + } else { + if (!STBCC__MAP_OPEN(g,x,y)) + return; + } + + cx = STBCC__CLUSTER_X_FOR_COORD_X(x); + cy = STBCC__CLUSTER_Y_FOR_COORD_Y(y); + + stbcc__remove_connections_to_adjacent_cluster(g, cx-1, cy, 1, 0); + stbcc__remove_connections_to_adjacent_cluster(g, cx+1, cy, -1, 0); + stbcc__remove_connections_to_adjacent_cluster(g, cx, cy-1, 0, 1); + stbcc__remove_connections_to_adjacent_cluster(g, cx, cy+1, 0,-1); + + if (!solid) + STBCC__MAP_BYTE(g,x,y) |= STBCC__MAP_BYTE_MASK(x,y); + else + STBCC__MAP_BYTE(g,x,y) &= ~STBCC__MAP_BYTE_MASK(x,y); + + stbcc__build_clumps_for_cluster(g, cx, cy); + stbcc__build_all_connections_for_cluster(g, cx, cy); + + stbcc__add_connections_to_adjacent_cluster_with_rebuild(g, cx-1, cy, 1, 0); + stbcc__add_connections_to_adjacent_cluster_with_rebuild(g, cx+1, cy, -1, 0); + stbcc__add_connections_to_adjacent_cluster_with_rebuild(g, cx, cy-1, 0, 1); + stbcc__add_connections_to_adjacent_cluster_with_rebuild(g, cx, cy+1, 0,-1); + + if (!g->in_batched_update) + stbcc__build_connected_components_for_clumps(g); + #if 0 + else + g->cluster_dirty[cy][cx] = 1; + #endif +} + +void stbcc_update_batch_begin(stbcc_grid *g) +{ + assert(!g->in_batched_update); + g->in_batched_update = 1; +} + +void stbcc_update_batch_end(stbcc_grid *g) +{ + assert(g->in_batched_update); + g->in_batched_update = 0; + stbcc__build_connected_components_for_clumps(g); // @OPTIMIZE: only do this if update was non-empty +} + +size_t stbcc_grid_sizeof(void) +{ + return sizeof(stbcc_grid); +} + +void stbcc_init_grid(stbcc_grid *g, unsigned char *map, int w, int h) +{ + int i,j,k; + assert(w % STBCC__CLUSTER_SIZE_X == 0); + assert(h % STBCC__CLUSTER_SIZE_Y == 0); + assert(w % 8 == 0); + + g->w = w; + g->h = h; + g->cw = w >> STBCC_CLUSTER_SIZE_X_LOG2; + g->ch = h >> STBCC_CLUSTER_SIZE_Y_LOG2; + g->in_batched_update = 0; + + #if 0 + for (j=0; j < STBCC__CLUSTER_COUNT_Y; ++j) + for (i=0; i < STBCC__CLUSTER_COUNT_X; ++i) + g->cluster_dirty[j][i] = 0; + #endif + + for (j=0; j < h; ++j) { + for (i=0; i < w; i += 8) { + unsigned char c = 0; + for (k=0; k < 8; ++k) + if (map[j*w + (i+k)] == 0) + c |= (1 << k); + g->map[j][i>>3] = c; + } + } + + for (j=0; j < g->ch; ++j) + for (i=0; i < g->cw; ++i) + stbcc__build_clumps_for_cluster(g, i, j); + + for (j=0; j < g->ch; ++j) + for (i=0; i < g->cw; ++i) + stbcc__build_all_connections_for_cluster(g, i, j); + + stbcc__build_connected_components_for_clumps(g); + + for (j=0; j < g->h; ++j) + for (i=0; i < g->w; ++i) + assert(g->clump_for_node[j][i] <= STBCC__NULL_CLUMPID); +} + + +static void stbcc__add_clump_connection(stbcc_grid *g, int x1, int y1, int x2, int y2) +{ + stbcc__cluster *cluster; + stbcc__clump *clump; + + int cx1 = STBCC__CLUSTER_X_FOR_COORD_X(x1); + int cy1 = STBCC__CLUSTER_Y_FOR_COORD_Y(y1); + int cx2 = STBCC__CLUSTER_X_FOR_COORD_X(x2); + int cy2 = STBCC__CLUSTER_Y_FOR_COORD_Y(y2); + + stbcc__clumpid c1 = g->clump_for_node[y1][x1]; + stbcc__clumpid c2 = g->clump_for_node[y2][x2]; + + stbcc__relative_clumpid rc; + + assert(cx1 != cx2 || cy1 != cy2); + assert(abs(cx1-cx2) + abs(cy1-cy2) == 1); + + // add connection to c2 in c1 + + rc.clump_index = c2; + rc.cluster_dx = x2-x1; + rc.cluster_dy = y2-y1; + + cluster = &g->cluster[cy1][cx1]; + clump = &cluster->clump[c1]; + assert(clump->num_adjacent <= clump->max_adjacent); + if (clump->num_adjacent == clump->max_adjacent) + g->cluster[cy1][cx1].rebuild_adjacency = 1; + else { + stbcc__relative_clumpid *adj = &cluster->adjacency_storage[clump->adjacent_clump_list_index]; + assert(clump->num_adjacent < STBCC__MAX_EXITS_PER_CLUMP); + assert(clump->adjacent_clump_list_index + clump->num_adjacent <= STBCC__CLUSTER_ADJACENCY_COUNT); + adj[clump->num_adjacent++] = rc; + } +} + +static void stbcc__remove_clump_connection(stbcc_grid *g, int x1, int y1, int x2, int y2) +{ + stbcc__cluster *cluster; + stbcc__clump *clump; + stbcc__relative_clumpid *adj; + int i; + + int cx1 = STBCC__CLUSTER_X_FOR_COORD_X(x1); + int cy1 = STBCC__CLUSTER_Y_FOR_COORD_Y(y1); + int cx2 = STBCC__CLUSTER_X_FOR_COORD_X(x2); + int cy2 = STBCC__CLUSTER_Y_FOR_COORD_Y(y2); + + stbcc__clumpid c1 = g->clump_for_node[y1][x1]; + stbcc__clumpid c2 = g->clump_for_node[y2][x2]; + + stbcc__relative_clumpid rc; + + assert(cx1 != cx2 || cy1 != cy2); + assert(abs(cx1-cx2) + abs(cy1-cy2) == 1); + + // add connection to c2 in c1 + + rc.clump_index = c2; + rc.cluster_dx = x2-x1; + rc.cluster_dy = y2-y1; + + cluster = &g->cluster[cy1][cx1]; + clump = &cluster->clump[c1]; + adj = &cluster->adjacency_storage[clump->adjacent_clump_list_index]; + + for (i=0; i < clump->num_adjacent; ++i) + if (rc.clump_index == adj[i].clump_index && + rc.cluster_dx == adj[i].cluster_dx && + rc.cluster_dy == adj[i].cluster_dy) + break; + + if (i < clump->num_adjacent) + adj[i] = adj[--clump->num_adjacent]; + else + assert(0); +} + +static void stbcc__add_connections_to_adjacent_cluster(stbcc_grid *g, int cx, int cy, int dx, int dy) +{ + unsigned char connected[STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER][STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER/8] = { { 0 } }; + int x = cx * STBCC__CLUSTER_SIZE_X; + int y = cy * STBCC__CLUSTER_SIZE_Y; + int step_x, step_y=0, i, j, k, n; + + if (cx < 0 || cx >= g->cw || cy < 0 || cy >= g->ch) + return; + + if (cx+dx < 0 || cx+dx >= g->cw || cy+dy < 0 || cy+dy >= g->ch) + return; + + if (g->cluster[cy][cx].rebuild_adjacency) + return; + + assert(abs(dx) + abs(dy) == 1); + + if (dx == 1) { + i = STBCC__CLUSTER_SIZE_X-1; + j = 0; + step_x = 0; + step_y = 1; + n = STBCC__CLUSTER_SIZE_Y; + } else if (dx == -1) { + i = 0; + j = 0; + step_x = 0; + step_y = 1; + n = STBCC__CLUSTER_SIZE_Y; + } else if (dy == -1) { + i = 0; + j = 0; + step_x = 1; + step_y = 0; + n = STBCC__CLUSTER_SIZE_X; + } else if (dy == 1) { + i = 0; + j = STBCC__CLUSTER_SIZE_Y-1; + step_x = 1; + step_y = 0; + n = STBCC__CLUSTER_SIZE_X; + } else { + assert(0); + return; + } + + for (k=0; k < n; ++k) { + if (STBCC__MAP_OPEN(g, x+i, y+j) && STBCC__MAP_OPEN(g, x+i+dx, y+j+dy)) { + stbcc__clumpid src = g->clump_for_node[y+j][x+i]; + stbcc__clumpid dest = g->clump_for_node[y+j+dy][x+i+dx]; + if (0 == (connected[src][dest>>3] & (1 << (dest & 7)))) { + assert((dest>>3) < sizeof(connected)); + connected[src][dest>>3] |= 1 << (dest & 7); + stbcc__add_clump_connection(g, x+i, y+j, x+i+dx, y+j+dy); + if (g->cluster[cy][cx].rebuild_adjacency) + break; + } + } + i += step_x; + j += step_y; + } +} + +static void stbcc__remove_connections_to_adjacent_cluster(stbcc_grid *g, int cx, int cy, int dx, int dy) +{ + unsigned char disconnected[STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER][STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER/8] = { { 0 } }; + int x = cx * STBCC__CLUSTER_SIZE_X; + int y = cy * STBCC__CLUSTER_SIZE_Y; + int step_x, step_y=0, i, j, k, n; + + if (cx < 0 || cx >= g->cw || cy < 0 || cy >= g->ch) + return; + + if (cx+dx < 0 || cx+dx >= g->cw || cy+dy < 0 || cy+dy >= g->ch) + return; + + assert(abs(dx) + abs(dy) == 1); + + if (dx == 1) { + i = STBCC__CLUSTER_SIZE_X-1; + j = 0; + step_x = 0; + step_y = 1; + n = STBCC__CLUSTER_SIZE_Y; + } else if (dx == -1) { + i = 0; + j = 0; + step_x = 0; + step_y = 1; + n = STBCC__CLUSTER_SIZE_Y; + } else if (dy == -1) { + i = 0; + j = 0; + step_x = 1; + step_y = 0; + n = STBCC__CLUSTER_SIZE_X; + } else if (dy == 1) { + i = 0; + j = STBCC__CLUSTER_SIZE_Y-1; + step_x = 1; + step_y = 0; + n = STBCC__CLUSTER_SIZE_X; + } else { + assert(0); + return; + } + + for (k=0; k < n; ++k) { + if (STBCC__MAP_OPEN(g, x+i, y+j) && STBCC__MAP_OPEN(g, x+i+dx, y+j+dy)) { + stbcc__clumpid src = g->clump_for_node[y+j][x+i]; + stbcc__clumpid dest = g->clump_for_node[y+j+dy][x+i+dx]; + if (0 == (disconnected[src][dest>>3] & (1 << (dest & 7)))) { + disconnected[src][dest>>3] |= 1 << (dest & 7); + stbcc__remove_clump_connection(g, x+i, y+j, x+i+dx, y+j+dy); + } + } + i += step_x; + j += step_y; + } +} + +static stbcc__tinypoint stbcc__incluster_find(stbcc__cluster_build_info *cbi, int x, int y) +{ + stbcc__tinypoint p,q; + p = cbi->parent[y][x]; + if (p.x == x && p.y == y) + return p; + q = stbcc__incluster_find(cbi, p.x, p.y); + cbi->parent[y][x] = q; + return q; +} + +static void stbcc__incluster_union(stbcc__cluster_build_info *cbi, int x1, int y1, int x2, int y2) +{ + stbcc__tinypoint p = stbcc__incluster_find(cbi, x1,y1); + stbcc__tinypoint q = stbcc__incluster_find(cbi, x2,y2); + + if (p.x == q.x && p.y == q.y) + return; + + cbi->parent[p.y][p.x] = q; +} + +static void stbcc__switch_root(stbcc__cluster_build_info *cbi, int x, int y, stbcc__tinypoint p) +{ + cbi->parent[p.y][p.x].x = x; + cbi->parent[p.y][p.x].y = y; + cbi->parent[y][x].x = x; + cbi->parent[y][x].y = y; +} + +static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) +{ + stbcc__cluster *c; + stbcc__cluster_build_info cbi; + int label=0; + int i,j; + int x = cx * STBCC__CLUSTER_SIZE_X; + int y = cy * STBCC__CLUSTER_SIZE_Y; + + // set initial disjoint set forest state + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) { + for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) { + cbi.parent[j][i].x = i; + cbi.parent[j][i].y = j; + } + } + + // join all sets that are connected + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) { + // check down only if not on bottom row + if (j < STBCC__CLUSTER_SIZE_Y-1) + for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) + if (STBCC__MAP_OPEN(g,x+i,y+j) && STBCC__MAP_OPEN(g,x+i ,y+j+1)) + stbcc__incluster_union(&cbi, i,j, i,j+1); + // check right for everything but rightmost column + for (i=0; i < STBCC__CLUSTER_SIZE_X-1; ++i) + if (STBCC__MAP_OPEN(g,x+i,y+j) && STBCC__MAP_OPEN(g,x+i+1,y+j )) + stbcc__incluster_union(&cbi, i,j, i+1,j); + } + + // label all non-empty clumps along edges so that all edge clumps are first + // in list; this means in degenerate case we can skip traversing non-edge clumps. + // because in the first pass we only label leaders, we swap the leader to the + // edge first + + // first put solid labels on all the edges; these will get overwritten if they're open + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) + cbi.label[j][0] = cbi.label[j][STBCC__CLUSTER_SIZE_X-1] = STBCC__NULL_CLUMPID; + for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) + cbi.label[0][i] = cbi.label[STBCC__CLUSTER_SIZE_Y-1][i] = STBCC__NULL_CLUMPID; + + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) { + i = 0; + if (STBCC__MAP_OPEN(g, x+i, y+j)) { + stbcc__tinypoint p = stbcc__incluster_find(&cbi, i,j); + if (p.x == i && p.y == j) + // if this is the leader, give it a label + cbi.label[j][i] = label++; + else if (!(p.x == 0 || p.x == STBCC__CLUSTER_SIZE_X-1 || p.y == 0 || p.y == STBCC__CLUSTER_SIZE_Y-1)) { + // if leader is in interior, promote this edge node to leader and label + stbcc__switch_root(&cbi, i, j, p); + cbi.label[j][i] = label++; + } + // else if leader is on edge, do nothing (it'll get labelled when we reach it) + } + i = STBCC__CLUSTER_SIZE_X-1; + if (STBCC__MAP_OPEN(g, x+i, y+j)) { + stbcc__tinypoint p = stbcc__incluster_find(&cbi, i,j); + if (p.x == i && p.y == j) + cbi.label[j][i] = label++; + else if (!(p.x == 0 || p.x == STBCC__CLUSTER_SIZE_X-1 || p.y == 0 || p.y == STBCC__CLUSTER_SIZE_Y-1)) { + stbcc__switch_root(&cbi, i, j, p); + cbi.label[j][i] = label++; + } + } + } + + for (i=1; i < STBCC__CLUSTER_SIZE_Y-1; ++i) { + j = 0; + if (STBCC__MAP_OPEN(g, x+i, y+j)) { + stbcc__tinypoint p = stbcc__incluster_find(&cbi, i,j); + if (p.x == i && p.y == j) + cbi.label[j][i] = label++; + else if (!(p.x == 0 || p.x == STBCC__CLUSTER_SIZE_X-1 || p.y == 0 || p.y == STBCC__CLUSTER_SIZE_Y-1)) { + stbcc__switch_root(&cbi, i, j, p); + cbi.label[j][i] = label++; + } + } + j = STBCC__CLUSTER_SIZE_Y-1; + if (STBCC__MAP_OPEN(g, x+i, y+j)) { + stbcc__tinypoint p = stbcc__incluster_find(&cbi, i,j); + if (p.x == i && p.y == j) + cbi.label[j][i] = label++; + else if (!(p.x == 0 || p.x == STBCC__CLUSTER_SIZE_X-1 || p.y == 0 || p.y == STBCC__CLUSTER_SIZE_Y-1)) { + stbcc__switch_root(&cbi, i, j, p); + cbi.label[j][i] = label++; + } + } + } + + c = &g->cluster[cy][cx]; + c->num_edge_clumps = label; + + // label any internal clusters + for (j=1; j < STBCC__CLUSTER_SIZE_Y-1; ++j) { + for (i=1; i < STBCC__CLUSTER_SIZE_X-1; ++i) { + stbcc__tinypoint p = cbi.parent[j][i]; + if (p.x == i && p.y == j) { + if (STBCC__MAP_OPEN(g,x+i,y+j)) + cbi.label[j][i] = label++; + else + cbi.label[j][i] = STBCC__NULL_CLUMPID; + } + } + } + + // label all other nodes + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) { + for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) { + stbcc__tinypoint p = stbcc__incluster_find(&cbi, i,j); + if (p.x != i || p.y != j) { + if (STBCC__MAP_OPEN(g,x+i,y+j)) + cbi.label[j][i] = cbi.label[p.y][p.x]; + } + if (STBCC__MAP_OPEN(g,x+i,y+j)) + assert(cbi.label[j][i] != STBCC__NULL_CLUMPID); + } + } + + c->num_clumps = label; + + for (i=0; i < label; ++i) { + c->clump[i].num_adjacent = 0; + c->clump[i].max_adjacent = 0; + } + + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) + for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) { + g->clump_for_node[y+j][x+i] = cbi.label[j][i]; // @OPTIMIZE: remove cbi.label entirely + assert(g->clump_for_node[y+j][x+i] <= STBCC__NULL_CLUMPID); + } + + // set the global label for all interior clumps since they can't have connections, + // so we don't have to do this on the global pass (brings from O(N) to O(N^0.75)) + for (i=(int) c->num_edge_clumps; i < (int) c->num_clumps; ++i) { + stbcc__global_clumpid gc; + gc.f.cluster_x = cx; + gc.f.cluster_y = cy; + gc.f.clump_index = i; + c->clump[i].global_label = gc; + } + + c->rebuild_adjacency = 1; // flag that it has no valid adjacency data +} + +#endif // STB_CONNECTED_COMPONENTS_IMPLEMENTATION +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_divide.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_divide.h new file mode 100644 index 0000000..6a51e3f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_divide.h @@ -0,0 +1,433 @@ +// stb_divide.h - v0.94 - public domain - Sean Barrett, Feb 2010 +// Three kinds of divide/modulus of signed integers. +// +// HISTORY +// +// v0.94 Fix integer overflow issues +// v0.93 2020-02-02 Write useful exit() value from main() +// v0.92 2019-02-25 Fix warning +// v0.91 2010-02-27 Fix euclidean division by INT_MIN for non-truncating C +// Check result with 64-bit math to catch such cases +// v0.90 2010-02-24 First public release +// +// USAGE +// +// In *ONE* source file, put: +// +// #define STB_DIVIDE_IMPLEMENTATION +// // #define C_INTEGER_DIVISION_TRUNCATES // see Note 1 +// // #define C_INTEGER_DIVISION_FLOORS // see Note 2 +// #include "stb_divide.h" +// +// Other source files should just include stb_divide.h +// +// Note 1: On platforms/compilers that you know signed C division +// truncates, you can #define C_INTEGER_DIVISION_TRUNCATES. +// +// Note 2: On platforms/compilers that you know signed C division +// floors (rounds to negative infinity), you can #define +// C_INTEGER_DIVISION_FLOORS. +// +// You can #define STB_DIVIDE_TEST in which case the implementation +// will generate a main() and compiling the result will create a +// program that tests the implementation. Run it with no arguments +// and any output indicates an error; run it with any argument and +// it will also print the test results. Define STB_DIVIDE_TEST_64 +// to a 64-bit integer type to avoid overflows in the result-checking +// which give false negatives. +// +// ABOUT +// +// This file provides three different consistent divide/mod pairs +// implemented on top of arbitrary C/C++ division, including correct +// handling of overflow of intermediate calculations: +// +// trunc: a/b truncates to 0, a%b has same sign as a +// floor: a/b truncates to -inf, a%b has same sign as b +// eucl: a/b truncates to sign(b)*inf, a%b is non-negative +// +// Not necessarily optimal; I tried to keep it generally efficient, +// but there may be better ways. +// +// Briefly, for those who are not familiar with the problem, we note +// the reason these divides exist and are interesting: +// +// 'trunc' is easy to implement in hardware (strip the signs, +// compute, reapply the signs), thus is commonly defined +// by many languages (including C99) +// +// 'floor' is simple to define and better behaved than trunc; +// for example it divides integers into fixed-size buckets +// without an extra-wide bucket at 0, and for a fixed +// divisor N there are only |N| possible moduli. +// +// 'eucl' guarantees fixed-sized buckets *and* a non-negative +// modulus and defines division to be whatever is needed +// to achieve that result. +// +// See "The Euclidean definition of the functions div and mod" +// by Raymond Boute (1992), or "Division and Modulus for Computer +// Scientists" by Daan Leijen (2001) +// +// We assume of the built-in C division: +// (a) modulus is the remainder for the corresponding division +// (b) a/b truncates if a and b are the same sign +// +// Property (a) requires (a/b)*b + (a%b)==a, and is required by C. +// Property (b) seems to be true of all hardware but is *not* satisfied +// by the euclidean division operator we define, so it's possibly not +// always true. If any such platform turns up, we can add more cases. +// (Possibly only stb_div_trunc currently relies on property (b).) +// +// LICENSE +// +// See end of file for license information. + + +#ifndef INCLUDE_STB_DIVIDE_H +#define INCLUDE_STB_DIVIDE_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern int stb_div_trunc(int value_to_be_divided, int value_to_divide_by); +extern int stb_div_floor(int value_to_be_divided, int value_to_divide_by); +extern int stb_div_eucl (int value_to_be_divided, int value_to_divide_by); +extern int stb_mod_trunc(int value_to_be_divided, int value_to_divide_by); +extern int stb_mod_floor(int value_to_be_divided, int value_to_divide_by); +extern int stb_mod_eucl (int value_to_be_divided, int value_to_divide_by); + +#ifdef __cplusplus +} +#endif + +#ifdef STB_DIVIDE_IMPLEMENTATION + +#if defined(__STDC_VERSION) && __STDC_VERSION__ >= 19901 + #ifndef C_INTEGER_DIVISION_TRUNCATES + #define C_INTEGER_DIVISION_TRUNCATES + #endif +#endif + +#ifndef INT_MIN +#include // if you have no limits.h, #define INT_MIN yourself +#endif + +// the following macros are designed to allow testing +// other platforms by simulating them +#ifndef STB_DIVIDE_TEST_FLOOR + #define stb__div(a,b) ((a)/(b)) + #define stb__mod(a,b) ((a)%(b)) +#else + // implement floor-style divide on trunc platform + #ifndef C_INTEGER_DIVISION_TRUNCATES + #error "floor test requires truncating division" + #endif + #undef C_INTEGER_DIVISION_TRUNCATES + int stb__div(int v1, int v2) + { + int q = v1/v2, r = v1%v2; + if ((r > 0 && v2 < 0) || (r < 0 && v2 > 0)) + return q-1; + else + return q; + } + + int stb__mod(int v1, int v2) + { + int r = v1%v2; + if ((r > 0 && v2 < 0) || (r < 0 && v2 > 0)) + return r+v2; + else + return r; + } +#endif + +int stb_div_trunc(int v1, int v2) +{ + #ifdef C_INTEGER_DIVISION_TRUNCATES + return v1/v2; + #else + if (v1 >= 0 && v2 <= 0) + return -stb__div(-v1,v2); // both negative to avoid overflow + if (v1 <= 0 && v2 >= 0) + if (v1 != INT_MIN) + return -stb__div(v1,-v2); // both negative to avoid overflow + else + return -stb__div(v1+v2,-v2)-1; // push v1 away from wrap point + else + return v1/v2; // same sign, so expect truncation + #endif +} + +int stb_div_floor(int v1, int v2) +{ + #ifdef C_INTEGER_DIVISION_FLOORS + return v1/v2; + #else + if (v1 >= 0 && v2 < 0) { + if (v2 + 1 >= INT_MIN + v1) // check if increasing v1's magnitude overflows + return -stb__div((v2+1)-v1,v2); // nope, so just compute it + else + return -stb__div(-v1,v2) + ((-v1)%v2 ? -1 : 0); + } + if (v1 < 0 && v2 >= 0) { + if (v1 != INT_MIN) { + if (v1 + 1 >= INT_MIN + v2) // check if increasing v1's magnitude overflows + return -stb__div((v1+1)-v2,-v2); // nope, so just compute it + else + return -stb__div(-v1,v2) + (stb__mod(v1,-v2) ? -1 : 0); + } else // it must be possible to compute -(v1+v2) without overflowing + return -stb__div(-(v1+v2),v2) + (stb__mod(-(v1+v2),v2) ? -2 : -1); + } else + return v1/v2; // same sign, so expect truncation + #endif +} + +int stb_div_eucl(int v1, int v2) +{ + int q,r; + #ifdef C_INTEGER_DIVISION_TRUNCATES + q = v1/v2; + r = v1%v2; + #else + // handle every quadrant separately, since we can't rely on q and r flor + if (v1 >= 0) + if (v2 >= 0) + return stb__div(v1,v2); + else if (v2 != INT_MIN) + q = -stb__div(v1,-v2), r = stb__mod(v1,-v2); + else + q = 0, r = v1; + else if (v1 != INT_MIN) + if (v2 >= 0) + q = -stb__div(-v1,v2), r = -stb__mod(-v1,v2); + else if (v2 != INT_MIN) + q = stb__div(-v1,-v2), r = -stb__mod(-v1,-v2); + else // if v2 is INT_MIN, then we can't use -v2, but we can't divide by v2 + q = 1, r = v1-q*v2; + else // if v1 is INT_MIN, we have to move away from overflow place + if (v2 >= 0) + q = -stb__div(-(v1+v2),v2)-1, r = -stb__mod(-(v1+v2),v2); + else if (v2 != INT_MIN) + q = stb__div(-(v1-v2),-v2)+1, r = -stb__mod(-(v1-v2),-v2); + else // for INT_MIN / INT_MIN, we need to be extra-careful to avoid overflow + q = 1, r = 0; + #endif + if (r >= 0) + return q; + else + return q + (v2 > 0 ? -1 : 1); +} + +int stb_mod_trunc(int v1, int v2) +{ + #ifdef C_INTEGER_DIVISION_TRUNCATES + return v1%v2; + #else + if (v1 >= 0) { // modulus result should always be positive + int r = stb__mod(v1,v2); + if (r >= 0) + return r; + else + return r - (v2 < 0 ? v2 : -v2); + } else { // modulus result should always be negative + int r = stb__mod(v1,v2); + if (r <= 0) + return r; + else + return r + (v2 < 0 ? v2 : -v2); + } + #endif +} + +int stb_mod_floor(int v1, int v2) +{ + #ifdef C_INTEGER_DIVISION_FLOORS + return v1%v2; + #else + if (v2 >= 0) { // result should always be positive + int r = stb__mod(v1,v2); + if (r >= 0) + return r; + else + return r + v2; + } else { // result should always be negative + int r = stb__mod(v1,v2); + if (r <= 0) + return r; + else + return r + v2; + } + #endif +} + +int stb_mod_eucl(int v1, int v2) +{ + int r = stb__mod(v1,v2); + + if (r >= 0) + return r; + else + return r - (v2 < 0 ? v2 : -v2); // negative abs() [to avoid overflow] +} + +#ifdef STB_DIVIDE_TEST +#include +#include +#include + +int show=0; +int err=0; + +void stbdiv_check(int q, int r, int a, int b, char *type, int dir) +{ + if ((dir > 0 && r < 0) || (dir < 0 && r > 0)) { + fprintf(stderr, "FAILED: %s(%d,%d) remainder %d in wrong direction\n", type,a,b,r); + err++; + } else + if (b != INT_MIN) // can't compute abs(), but if b==INT_MIN all remainders are valid + if (r <= -abs(b) || r >= abs(b)) { + fprintf(stderr, "FAILED: %s(%d,%d) remainder %d out of range\n", type,a,b,r); + err++; + } + #ifdef STB_DIVIDE_TEST_64 + { + STB_DIVIDE_TEST_64 q64 = q, r64=r, a64=a, b64=b; + if (q64*b64+r64 != a64) { + fprintf(stderr, "FAILED: %s(%d,%d) remainder %d doesn't match quotient %d\n", type,a,b,r,q); + err++; + } + } + #else + if (q*b+r != a) { + fprintf(stderr, "FAILED: %s(%d,%d) remainder %d doesn't match quotient %d\n", type,a,b,r,q); + err++; + } + #endif +} + +void test(int a, int b) +{ + int q,r; + if (show) printf("(%+11d,%+d) | ", a,b); + q = stb_div_trunc(a,b), r = stb_mod_trunc(a,b); + if (show) printf("(%+11d,%+2d) ", q,r); stbdiv_check(q,r,a,b, "trunc",a); + q = stb_div_floor(a,b), r = stb_mod_floor(a,b); + if (show) printf("(%+11d,%+2d) ", q,r); stbdiv_check(q,r,a,b, "floor",b); + q = stb_div_eucl (a,b), r = stb_mod_eucl (a,b); + if (show) printf("(%+11d,%+2d)\n", q,r); stbdiv_check(q,r,a,b, "euclidean",1); +} + +void testh(int a, int b) +{ + int q,r; + if (show) printf("(%08x,%08x) |\n", a,b); + q = stb_div_trunc(a,b), r = stb_mod_trunc(a,b); stbdiv_check(q,r,a,b, "trunc",a); + if (show) printf(" (%08x,%08x)", q,r); + q = stb_div_floor(a,b), r = stb_mod_floor(a,b); stbdiv_check(q,r,a,b, "floor",b); + if (show) printf(" (%08x,%08x)", q,r); + q = stb_div_eucl (a,b), r = stb_mod_eucl (a,b); stbdiv_check(q,r,a,b, "euclidean",1); + if (show) printf(" (%08x,%08x)\n ", q,r); +} + +int main(int argc, char **argv) +{ + if (argc > 1) show=1; + + test(8,3); + test(8,-3); + test(-8,3); + test(-8,-3); + test(1,2); + test(1,-2); + test(-1,2); + test(-1,-2); + test(8,4); + test(8,-4); + test(-8,4); + test(-8,-4); + + test(INT_MAX,1); + test(INT_MIN,1); + test(INT_MIN+1,1); + test(INT_MAX,-1); + //test(INT_MIN,-1); // this traps in MSVC, so we leave it untested + test(INT_MIN+1,-1); + test(INT_MIN,-2); + test(INT_MIN+1,2); + test(INT_MIN+1,-2); + test(INT_MAX,2); + test(INT_MAX,-2); + test(INT_MIN+1,2); + test(INT_MIN+1,-2); + test(INT_MIN,2); + test(INT_MIN,-2); + test(INT_MIN,7); + test(INT_MIN,-7); + test(INT_MIN+1,4); + test(INT_MIN+1,-4); + + testh(-7, INT_MIN); + testh(-1, INT_MIN); + testh(1, INT_MIN); + testh(7, INT_MIN); + + testh(INT_MAX-1, INT_MIN); + testh(INT_MAX, INT_MIN); + testh(INT_MIN, INT_MIN); + testh(INT_MIN+1, INT_MIN); + + testh(INT_MAX-1, INT_MAX); + testh(INT_MAX , INT_MAX); + testh(INT_MIN , INT_MAX); + testh(INT_MIN+1, INT_MAX); + + return err > 0 ? 1 : 0; +} +#endif // STB_DIVIDE_TEST +#endif // STB_DIVIDE_IMPLEMENTATION +#endif // INCLUDE_STB_DIVIDE_H + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_ds.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_ds.h new file mode 100644 index 0000000..e84c82d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_ds.h @@ -0,0 +1,1895 @@ +/* stb_ds.h - v0.67 - public domain data structures - Sean Barrett 2019 + + This is a single-header-file library that provides easy-to-use + dynamic arrays and hash tables for C (also works in C++). + + For a gentle introduction: + http://nothings.org/stb_ds + + To use this library, do this in *one* C or C++ file: + #define STB_DS_IMPLEMENTATION + #include "stb_ds.h" + +TABLE OF CONTENTS + + Table of Contents + Compile-time options + License + Documentation + Notes + Notes - Dynamic arrays + Notes - Hash maps + Credits + +COMPILE-TIME OPTIONS + + #define STBDS_NO_SHORT_NAMES + + This flag needs to be set globally. + + By default stb_ds exposes shorter function names that are not qualified + with the "stbds_" prefix. If these names conflict with the names in your + code, define this flag. + + #define STBDS_SIPHASH_2_4 + + This flag only needs to be set in the file containing #define STB_DS_IMPLEMENTATION. + + By default stb_ds.h hashes using a weaker variant of SipHash and a custom hash for + 4- and 8-byte keys. On 64-bit platforms, you can define the above flag to force + stb_ds.h to use specification-compliant SipHash-2-4 for all keys. Doing so makes + hash table insertion about 20% slower on 4- and 8-byte keys, 5% slower on + 64-byte keys, and 10% slower on 256-byte keys on my test computer. + + #define STBDS_REALLOC(context,ptr,size) better_realloc + #define STBDS_FREE(context,ptr) better_free + + These defines only need to be set in the file containing #define STB_DS_IMPLEMENTATION. + + By default stb_ds uses stdlib realloc() and free() for memory management. You can + substitute your own functions instead by defining these symbols. You must either + define both, or neither. Note that at the moment, 'context' will always be NULL. + @TODO add an array/hash initialization function that takes a memory context pointer. + + #define STBDS_UNIT_TESTS + + Defines a function stbds_unit_tests() that checks the functioning of the data structures. + + Note that on older versions of gcc (e.g. 5.x.x) you may need to build with '-std=c++0x' + (or equivalentally '-std=c++11') when using anonymous structures as seen on the web + page or in STBDS_UNIT_TESTS. + +LICENSE + + Placed in the public domain and also MIT licensed. + See end of file for detailed license information. + +DOCUMENTATION + + Dynamic Arrays + + Non-function interface: + + Declare an empty dynamic array of type T + T* foo = NULL; + + Access the i'th item of a dynamic array 'foo' of type T, T* foo: + foo[i] + + Functions (actually macros) + + arrfree: + void arrfree(T*); + Frees the array. + + arrlen: + ptrdiff_t arrlen(T*); + Returns the number of elements in the array. + + arrlenu: + size_t arrlenu(T*); + Returns the number of elements in the array as an unsigned type. + + arrpop: + T arrpop(T* a) + Removes the final element of the array and returns it. + + arrput: + T arrput(T* a, T b); + Appends the item b to the end of array a. Returns b. + + arrins: + T arrins(T* a, int p, T b); + Inserts the item b into the middle of array a, into a[p], + moving the rest of the array over. Returns b. + + arrinsn: + void arrinsn(T* a, int p, int n); + Inserts n uninitialized items into array a starting at a[p], + moving the rest of the array over. + + arraddnptr: + T* arraddnptr(T* a, int n) + Appends n uninitialized items onto array at the end. + Returns a pointer to the first uninitialized item added. + + arraddnindex: + size_t arraddnindex(T* a, int n) + Appends n uninitialized items onto array at the end. + Returns the index of the first uninitialized item added. + + arrdel: + void arrdel(T* a, int p); + Deletes the element at a[p], moving the rest of the array over. + + arrdeln: + void arrdeln(T* a, int p, int n); + Deletes n elements starting at a[p], moving the rest of the array over. + + arrdelswap: + void arrdelswap(T* a, int p); + Deletes the element at a[p], replacing it with the element from + the end of the array. O(1) performance. + + arrsetlen: + void arrsetlen(T* a, int n); + Changes the length of the array to n. Allocates uninitialized + slots at the end if necessary. + + arrsetcap: + size_t arrsetcap(T* a, int n); + Sets the length of allocated storage to at least n. It will not + change the length of the array. + + arrcap: + size_t arrcap(T* a); + Returns the number of total elements the array can contain without + needing to be reallocated. + + Hash maps & String hash maps + + Given T is a structure type: struct { TK key; TV value; }. Note that some + functions do not require TV value and can have other fields. For string + hash maps, TK must be 'char *'. + + Special interface: + + stbds_rand_seed: + void stbds_rand_seed(size_t seed); + For security against adversarially chosen data, you should seed the + library with a strong random number. Or at least seed it with time(). + + stbds_hash_string: + size_t stbds_hash_string(char *str, size_t seed); + Returns a hash value for a string. + + stbds_hash_bytes: + size_t stbds_hash_bytes(void *p, size_t len, size_t seed); + These functions hash an arbitrary number of bytes. The function + uses a custom hash for 4- and 8-byte data, and a weakened version + of SipHash for everything else. On 64-bit platforms you can get + specification-compliant SipHash-2-4 on all data by defining + STBDS_SIPHASH_2_4, at a significant cost in speed. + + Non-function interface: + + Declare an empty hash map of type T + T* foo = NULL; + + Access the i'th entry in a hash table T* foo: + foo[i] + + Function interface (actually macros): + + hmfree + shfree + void hmfree(T*); + void shfree(T*); + Frees the hashmap and sets the pointer to NULL. + + hmlen + shlen + ptrdiff_t hmlen(T*) + ptrdiff_t shlen(T*) + Returns the number of elements in the hashmap. + + hmlenu + shlenu + size_t hmlenu(T*) + size_t shlenu(T*) + Returns the number of elements in the hashmap. + + hmgeti + shgeti + hmgeti_ts + ptrdiff_t hmgeti(T*, TK key) + ptrdiff_t shgeti(T*, char* key) + ptrdiff_t hmgeti_ts(T*, TK key, ptrdiff_t tempvar) + Returns the index in the hashmap which has the key 'key', or -1 + if the key is not present. + + hmget + hmget_ts + shget + TV hmget(T*, TK key) + TV shget(T*, char* key) + TV hmget_ts(T*, TK key, ptrdiff_t tempvar) + Returns the value corresponding to 'key' in the hashmap. + The structure must have a 'value' field + + hmgets + shgets + T hmgets(T*, TK key) + T shgets(T*, char* key) + Returns the structure corresponding to 'key' in the hashmap. + + hmgetp + shgetp + hmgetp_ts + hmgetp_null + shgetp_null + T* hmgetp(T*, TK key) + T* shgetp(T*, char* key) + T* hmgetp_ts(T*, TK key, ptrdiff_t tempvar) + T* hmgetp_null(T*, TK key) + T* shgetp_null(T*, char *key) + Returns a pointer to the structure corresponding to 'key' in + the hashmap. Functions ending in "_null" return NULL if the key + is not present in the hashmap; the others return a pointer to a + structure holding the default value (but not the searched-for key). + + hmdefault + shdefault + TV hmdefault(T*, TV value) + TV shdefault(T*, TV value) + Sets the default value for the hashmap, the value which will be + returned by hmget/shget if the key is not present. + + hmdefaults + shdefaults + TV hmdefaults(T*, T item) + TV shdefaults(T*, T item) + Sets the default struct for the hashmap, the contents which will be + returned by hmgets/shgets if the key is not present. + + hmput + shput + TV hmput(T*, TK key, TV value) + TV shput(T*, char* key, TV value) + Inserts a pair into the hashmap. If the key is already + present in the hashmap, updates its value. + + hmputs + shputs + T hmputs(T*, T item) + T shputs(T*, T item) + Inserts a struct with T.key into the hashmap. If the struct is already + present in the hashmap, updates it. + + hmdel + shdel + int hmdel(T*, TK key) + int shdel(T*, char* key) + If 'key' is in the hashmap, deletes its entry and returns 1. + Otherwise returns 0. + + Function interface (actually macros) for strings only: + + sh_new_strdup + void sh_new_strdup(T*); + Overwrites the existing pointer with a newly allocated + string hashmap which will automatically allocate and free + each string key using realloc/free + + sh_new_arena + void sh_new_arena(T*); + Overwrites the existing pointer with a newly allocated + string hashmap which will automatically allocate each string + key to a string arena. Every string key ever used by this + hash table remains in the arena until the arena is freed. + Additionally, any key which is deleted and reinserted will + be allocated multiple times in the string arena. + +NOTES + + * These data structures are realloc'd when they grow, and the macro + "functions" write to the provided pointer. This means: (a) the pointer + must be an lvalue, and (b) the pointer to the data structure is not + stable, and you must maintain it the same as you would a realloc'd + pointer. For example, if you pass a pointer to a dynamic array to a + function which updates it, the function must return back the new + pointer to the caller. This is the price of trying to do this in C. + + * The following are the only functions that are thread-safe on a single data + structure, i.e. can be run in multiple threads simultaneously on the same + data structure + hmlen shlen + hmlenu shlenu + hmget_ts shget_ts + hmgeti_ts shgeti_ts + hmgets_ts shgets_ts + + * You iterate over the contents of a dynamic array and a hashmap in exactly + the same way, using arrlen/hmlen/shlen: + + for (i=0; i < arrlen(foo); ++i) + ... foo[i] ... + + * All operations except arrins/arrdel are O(1) amortized, but individual + operations can be slow, so these data structures may not be suitable + for real time use. Dynamic arrays double in capacity as needed, so + elements are copied an average of once. Hash tables double/halve + their size as needed, with appropriate hysteresis to maintain O(1) + performance. + +NOTES - DYNAMIC ARRAY + + * If you know how long a dynamic array is going to be in advance, you can avoid + extra memory allocations by using arrsetlen to allocate it to that length in + advance and use foo[n] while filling it out, or arrsetcap to allocate the memory + for that length and use arrput/arrpush as normal. + + * Unlike some other versions of the dynamic array, this version should + be safe to use with strict-aliasing optimizations. + +NOTES - HASH MAP + + * For compilers other than GCC and clang (e.g. Visual Studio), for hmput/hmget/hmdel + and variants, the key must be an lvalue (so the macro can take the address of it). + Extensions are used that eliminate this requirement if you're using C99 and later + in GCC or clang, or if you're using C++ in GCC. But note that this can make your + code less portable. + + * To test for presence of a key in a hashmap, just do 'hmgeti(foo,key) >= 0'. + + * The iteration order of your data in the hashmap is determined solely by the + order of insertions and deletions. In particular, if you never delete, new + keys are always added at the end of the array. This will be consistent + across all platforms and versions of the library. However, you should not + attempt to serialize the internal hash table, as the hash is not consistent + between different platforms, and may change with future versions of the library. + + * Use sh_new_arena() for string hashmaps that you never delete from. Initialize + with NULL if you're managing the memory for your strings, or your strings are + never freed (at least until the hashmap is freed). Otherwise, use sh_new_strdup(). + @TODO: make an arena variant that garbage collects the strings with a trivial + copy collector into a new arena whenever the table shrinks / rebuilds. Since + current arena recommendation is to only use arena if it never deletes, then + this can just replace current arena implementation. + + * If adversarial input is a serious concern and you're on a 64-bit platform, + enable STBDS_SIPHASH_2_4 (see the 'Compile-time options' section), and pass + a strong random number to stbds_rand_seed. + + * The default value for the hash table is stored in foo[-1], so if you + use code like 'hmget(T,k)->value = 5' you can accidentally overwrite + the value stored by hmdefault if 'k' is not present. + +CREDITS + + Sean Barrett -- library, idea for dynamic array API/implementation + Per Vognsen -- idea for hash table API/implementation + Rafael Sachetto -- arrpop() + github:HeroicKatora -- arraddn() reworking + + Bugfixes: + Andy Durdin + Shane Liesegang + Vinh Truong + Andreas Molzer + github:hashitaku + github:srdjanstipic + Macoy Madson + Andreas Vennstrom + Tobias Mansfield-Williams +*/ + +#ifdef STBDS_UNIT_TESTS +#define _CRT_SECURE_NO_WARNINGS +#endif + +#ifndef INCLUDE_STB_DS_H +#define INCLUDE_STB_DS_H + +#include +#include + +#ifndef STBDS_NO_SHORT_NAMES +#define arrlen stbds_arrlen +#define arrlenu stbds_arrlenu +#define arrput stbds_arrput +#define arrpush stbds_arrput +#define arrpop stbds_arrpop +#define arrfree stbds_arrfree +#define arraddn stbds_arraddn // deprecated, use one of the following instead: +#define arraddnptr stbds_arraddnptr +#define arraddnindex stbds_arraddnindex +#define arrsetlen stbds_arrsetlen +#define arrlast stbds_arrlast +#define arrins stbds_arrins +#define arrinsn stbds_arrinsn +#define arrdel stbds_arrdel +#define arrdeln stbds_arrdeln +#define arrdelswap stbds_arrdelswap +#define arrcap stbds_arrcap +#define arrsetcap stbds_arrsetcap + +#define hmput stbds_hmput +#define hmputs stbds_hmputs +#define hmget stbds_hmget +#define hmget_ts stbds_hmget_ts +#define hmgets stbds_hmgets +#define hmgetp stbds_hmgetp +#define hmgetp_ts stbds_hmgetp_ts +#define hmgetp_null stbds_hmgetp_null +#define hmgeti stbds_hmgeti +#define hmgeti_ts stbds_hmgeti_ts +#define hmdel stbds_hmdel +#define hmlen stbds_hmlen +#define hmlenu stbds_hmlenu +#define hmfree stbds_hmfree +#define hmdefault stbds_hmdefault +#define hmdefaults stbds_hmdefaults + +#define shput stbds_shput +#define shputi stbds_shputi +#define shputs stbds_shputs +#define shget stbds_shget +#define shgeti stbds_shgeti +#define shgets stbds_shgets +#define shgetp stbds_shgetp +#define shgetp_null stbds_shgetp_null +#define shdel stbds_shdel +#define shlen stbds_shlen +#define shlenu stbds_shlenu +#define shfree stbds_shfree +#define shdefault stbds_shdefault +#define shdefaults stbds_shdefaults +#define sh_new_arena stbds_sh_new_arena +#define sh_new_strdup stbds_sh_new_strdup + +#define stralloc stbds_stralloc +#define strreset stbds_strreset +#endif + +#if defined(STBDS_REALLOC) && !defined(STBDS_FREE) || !defined(STBDS_REALLOC) && defined(STBDS_FREE) +#error "You must define both STBDS_REALLOC and STBDS_FREE, or neither." +#endif +#if !defined(STBDS_REALLOC) && !defined(STBDS_FREE) +#include +#define STBDS_REALLOC(c,p,s) realloc(p,s) +#define STBDS_FREE(c,p) free(p) +#endif + +#ifdef _MSC_VER +#define STBDS_NOTUSED(v) (void)(v) +#else +#define STBDS_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// for security against attackers, seed the library with a random number, at least time() but stronger is better +extern void stbds_rand_seed(size_t seed); + +// these are the hash functions used internally if you want to test them or use them for other purposes +extern size_t stbds_hash_bytes(void *p, size_t len, size_t seed); +extern size_t stbds_hash_string(char *str, size_t seed); + +// this is a simple string arena allocator, initialize with e.g. 'stbds_string_arena my_arena={0}'. +typedef struct stbds_string_arena stbds_string_arena; +extern char * stbds_stralloc(stbds_string_arena *a, char *str); +extern void stbds_strreset(stbds_string_arena *a); + +// have to #define STBDS_UNIT_TESTS to call this +extern void stbds_unit_tests(void); + +/////////////// +// +// Everything below here is implementation details +// + +extern void * stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap); +extern void stbds_arrfreef(void *a); +extern void stbds_hmfree_func(void *p, size_t elemsize); +extern void * stbds_hmget_key(void *a, size_t elemsize, void *key, size_t keysize, int mode); +extern void * stbds_hmget_key_ts(void *a, size_t elemsize, void *key, size_t keysize, ptrdiff_t *temp, int mode); +extern void * stbds_hmput_default(void *a, size_t elemsize); +extern void * stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int mode); +extern void * stbds_hmdel_key(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode); +extern void * stbds_shmode_func(size_t elemsize, int mode); + +#ifdef __cplusplus +} +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define STBDS_HAS_TYPEOF +#ifdef __cplusplus +//#define STBDS_HAS_LITERAL_ARRAY // this is currently broken for clang +#endif +#endif + +#if !defined(__cplusplus) +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define STBDS_HAS_LITERAL_ARRAY +#endif +#endif + +// this macro takes the address of the argument, but on gcc/clang can accept rvalues +#if defined(STBDS_HAS_LITERAL_ARRAY) && defined(STBDS_HAS_TYPEOF) + #if __clang__ + #define STBDS_ADDRESSOF(typevar, value) ((__typeof__(typevar)[1]){value}) // literal array decays to pointer to value + #else + #define STBDS_ADDRESSOF(typevar, value) ((typeof(typevar)[1]){value}) // literal array decays to pointer to value + #endif +#else +#define STBDS_ADDRESSOF(typevar, value) &(value) +#endif + +#define STBDS_OFFSETOF(var,field) ((char *) &(var)->field - (char *) (var)) + +#define stbds_header(t) ((stbds_array_header *) (t) - 1) +#define stbds_temp(t) stbds_header(t)->temp +#define stbds_temp_key(t) (*(char **) stbds_header(t)->hash_table) + +#define stbds_arrsetcap(a,n) (stbds_arrgrow(a,0,n)) +#define stbds_arrsetlen(a,n) ((stbds_arrcap(a) < (size_t) (n) ? stbds_arrsetcap((a),(size_t)(n)),0 : 0), (a) ? stbds_header(a)->length = (size_t) (n) : 0) +#define stbds_arrcap(a) ((a) ? stbds_header(a)->capacity : 0) +#define stbds_arrlen(a) ((a) ? (ptrdiff_t) stbds_header(a)->length : 0) +#define stbds_arrlenu(a) ((a) ? stbds_header(a)->length : 0) +#define stbds_arrput(a,v) (stbds_arrmaybegrow(a,1), (a)[stbds_header(a)->length++] = (v)) +#define stbds_arrpush stbds_arrput // synonym +#define stbds_arrpop(a) (stbds_header(a)->length--, (a)[stbds_header(a)->length]) +#define stbds_arraddn(a,n) ((void)(stbds_arraddnindex(a, n))) // deprecated, use one of the following instead: +#define stbds_arraddnptr(a,n) (stbds_arrmaybegrow(a,n), (n) ? (stbds_header(a)->length += (n), &(a)[stbds_header(a)->length-(n)]) : (a)) +#define stbds_arraddnindex(a,n)(stbds_arrmaybegrow(a,n), (n) ? (stbds_header(a)->length += (n), stbds_header(a)->length-(n)) : stbds_arrlen(a)) +#define stbds_arraddnoff stbds_arraddnindex +#define stbds_arrlast(a) ((a)[stbds_header(a)->length-1]) +#define stbds_arrfree(a) ((void) ((a) ? STBDS_FREE(NULL,stbds_header(a)) : (void)0), (a)=NULL) +#define stbds_arrdel(a,i) stbds_arrdeln(a,i,1) +#define stbds_arrdeln(a,i,n) (memmove(&(a)[i], &(a)[(i)+(n)], sizeof *(a) * (stbds_header(a)->length-(n)-(i))), stbds_header(a)->length -= (n)) +#define stbds_arrdelswap(a,i) ((a)[i] = stbds_arrlast(a), stbds_header(a)->length -= 1) +#define stbds_arrinsn(a,i,n) (stbds_arraddn((a),(n)), memmove(&(a)[(i)+(n)], &(a)[i], sizeof *(a) * (stbds_header(a)->length-(n)-(i)))) +#define stbds_arrins(a,i,v) (stbds_arrinsn((a),(i),1), (a)[i]=(v)) + +#define stbds_arrmaybegrow(a,n) ((!(a) || stbds_header(a)->length + (n) > stbds_header(a)->capacity) \ + ? (stbds_arrgrow(a,n,0),0) : 0) + +#define stbds_arrgrow(a,b,c) ((a) = stbds_arrgrowf_wrapper((a), sizeof *(a), (b), (c))) + +#define stbds_hmput(t, k, v) \ + ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, 0), \ + (t)[stbds_temp((t)-1)].key = (k), \ + (t)[stbds_temp((t)-1)].value = (v)) + +#define stbds_hmputs(t, s) \ + ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), &(s).key, sizeof (s).key, STBDS_HM_BINARY), \ + (t)[stbds_temp((t)-1)] = (s)) + +#define stbds_hmgeti(t,k) \ + ((t) = stbds_hmget_key_wrapper((t), sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, STBDS_HM_BINARY), \ + stbds_temp((t)-1)) + +#define stbds_hmgeti_ts(t,k,temp) \ + ((t) = stbds_hmget_key_ts_wrapper((t), sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, &(temp), STBDS_HM_BINARY), \ + (temp)) + +#define stbds_hmgetp(t, k) \ + ((void) stbds_hmgeti(t,k), &(t)[stbds_temp((t)-1)]) + +#define stbds_hmgetp_ts(t, k, temp) \ + ((void) stbds_hmgeti_ts(t,k,temp), &(t)[temp]) + +#define stbds_hmdel(t,k) \ + (((t) = stbds_hmdel_key_wrapper((t),sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, STBDS_OFFSETOF((t),key), STBDS_HM_BINARY)),(t)?stbds_temp((t)-1):0) + +#define stbds_hmdefault(t, v) \ + ((t) = stbds_hmput_default_wrapper((t), sizeof *(t)), (t)[-1].value = (v)) + +#define stbds_hmdefaults(t, s) \ + ((t) = stbds_hmput_default_wrapper((t), sizeof *(t)), (t)[-1] = (s)) + +#define stbds_hmfree(p) \ + ((void) ((p) != NULL ? stbds_hmfree_func((p)-1,sizeof*(p)),0 : 0),(p)=NULL) + +#define stbds_hmgets(t, k) (*stbds_hmgetp(t,k)) +#define stbds_hmget(t, k) (stbds_hmgetp(t,k)->value) +#define stbds_hmget_ts(t, k, temp) (stbds_hmgetp_ts(t,k,temp)->value) +#define stbds_hmlen(t) ((t) ? (ptrdiff_t) stbds_header((t)-1)->length-1 : 0) +#define stbds_hmlenu(t) ((t) ? stbds_header((t)-1)->length-1 : 0) +#define stbds_hmgetp_null(t,k) (stbds_hmgeti(t,k) == -1 ? NULL : &(t)[stbds_temp((t)-1)]) + +#define stbds_shput(t, k, v) \ + ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_HM_STRING), \ + (t)[stbds_temp((t)-1)].value = (v)) + +#define stbds_shputi(t, k, v) \ + ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_HM_STRING), \ + (t)[stbds_temp((t)-1)].value = (v), stbds_temp((t)-1)) + +#define stbds_shputs(t, s) \ + ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (s).key, sizeof (s).key, STBDS_HM_STRING), \ + (t)[stbds_temp((t)-1)] = (s), \ + (t)[stbds_temp((t)-1)].key = stbds_temp_key((t)-1)) // above line overwrites whole structure, so must rewrite key here if it was allocated internally + +#define stbds_pshput(t, p) \ + ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (p)->key, sizeof (p)->key, STBDS_HM_PTR_TO_STRING), \ + (t)[stbds_temp((t)-1)] = (p)) + +#define stbds_shgeti(t,k) \ + ((t) = stbds_hmget_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_HM_STRING), \ + stbds_temp((t)-1)) + +#define stbds_pshgeti(t,k) \ + ((t) = stbds_hmget_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (*(t))->key, STBDS_HM_PTR_TO_STRING), \ + stbds_temp((t)-1)) + +#define stbds_shgetp(t, k) \ + ((void) stbds_shgeti(t,k), &(t)[stbds_temp((t)-1)]) + +#define stbds_pshget(t, k) \ + ((void) stbds_pshgeti(t,k), (t)[stbds_temp((t)-1)]) + +#define stbds_shdel(t,k) \ + (((t) = stbds_hmdel_key_wrapper((t),sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_OFFSETOF((t),key), STBDS_HM_STRING)),(t)?stbds_temp((t)-1):0) +#define stbds_pshdel(t,k) \ + (((t) = stbds_hmdel_key_wrapper((t),sizeof *(t), (void*) (k), sizeof (*(t))->key, STBDS_OFFSETOF(*(t),key), STBDS_HM_PTR_TO_STRING)),(t)?stbds_temp((t)-1):0) + +#define stbds_sh_new_arena(t) \ + ((t) = stbds_shmode_func_wrapper(t, sizeof *(t), STBDS_SH_ARENA)) +#define stbds_sh_new_strdup(t) \ + ((t) = stbds_shmode_func_wrapper(t, sizeof *(t), STBDS_SH_STRDUP)) + +#define stbds_shdefault(t, v) stbds_hmdefault(t,v) +#define stbds_shdefaults(t, s) stbds_hmdefaults(t,s) + +#define stbds_shfree stbds_hmfree +#define stbds_shlenu stbds_hmlenu + +#define stbds_shgets(t, k) (*stbds_shgetp(t,k)) +#define stbds_shget(t, k) (stbds_shgetp(t,k)->value) +#define stbds_shgetp_null(t,k) (stbds_shgeti(t,k) == -1 ? NULL : &(t)[stbds_temp((t)-1)]) +#define stbds_shlen stbds_hmlen + +typedef struct +{ + size_t length; + size_t capacity; + void * hash_table; + ptrdiff_t temp; +} stbds_array_header; + +typedef struct stbds_string_block +{ + struct stbds_string_block *next; + char storage[8]; +} stbds_string_block; + +struct stbds_string_arena +{ + stbds_string_block *storage; + size_t remaining; + unsigned char block; + unsigned char mode; // this isn't used by the string arena itself +}; + +#define STBDS_HM_BINARY 0 +#define STBDS_HM_STRING 1 + +enum +{ + STBDS_SH_NONE, + STBDS_SH_DEFAULT, + STBDS_SH_STRDUP, + STBDS_SH_ARENA +}; + +#ifdef __cplusplus +// in C we use implicit assignment from these void*-returning functions to T*. +// in C++ these templates make the same code work +template static T * stbds_arrgrowf_wrapper(T *a, size_t elemsize, size_t addlen, size_t min_cap) { + return (T*)stbds_arrgrowf((void *)a, elemsize, addlen, min_cap); +} +template static T * stbds_hmget_key_wrapper(T *a, size_t elemsize, void *key, size_t keysize, int mode) { + return (T*)stbds_hmget_key((void*)a, elemsize, key, keysize, mode); +} +template static T * stbds_hmget_key_ts_wrapper(T *a, size_t elemsize, void *key, size_t keysize, ptrdiff_t *temp, int mode) { + return (T*)stbds_hmget_key_ts((void*)a, elemsize, key, keysize, temp, mode); +} +template static T * stbds_hmput_default_wrapper(T *a, size_t elemsize) { + return (T*)stbds_hmput_default((void *)a, elemsize); +} +template static T * stbds_hmput_key_wrapper(T *a, size_t elemsize, void *key, size_t keysize, int mode) { + return (T*)stbds_hmput_key((void*)a, elemsize, key, keysize, mode); +} +template static T * stbds_hmdel_key_wrapper(T *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode){ + return (T*)stbds_hmdel_key((void*)a, elemsize, key, keysize, keyoffset, mode); +} +template static T * stbds_shmode_func_wrapper(T *, size_t elemsize, int mode) { + return (T*)stbds_shmode_func(elemsize, mode); +} +#else +#define stbds_arrgrowf_wrapper stbds_arrgrowf +#define stbds_hmget_key_wrapper stbds_hmget_key +#define stbds_hmget_key_ts_wrapper stbds_hmget_key_ts +#define stbds_hmput_default_wrapper stbds_hmput_default +#define stbds_hmput_key_wrapper stbds_hmput_key +#define stbds_hmdel_key_wrapper stbds_hmdel_key +#define stbds_shmode_func_wrapper(t,e,m) stbds_shmode_func(e,m) +#endif + +#endif // INCLUDE_STB_DS_H + + +////////////////////////////////////////////////////////////////////////////// +// +// IMPLEMENTATION +// + +#ifdef STB_DS_IMPLEMENTATION +#include +#include + +#ifndef STBDS_ASSERT +#define STBDS_ASSERT_WAS_UNDEFINED +#define STBDS_ASSERT(x) ((void) 0) +#endif + +#ifdef STBDS_STATISTICS +#define STBDS_STATS(x) x +size_t stbds_array_grow; +size_t stbds_hash_grow; +size_t stbds_hash_shrink; +size_t stbds_hash_rebuild; +size_t stbds_hash_probes; +size_t stbds_hash_alloc; +size_t stbds_rehash_probes; +size_t stbds_rehash_items; +#else +#define STBDS_STATS(x) +#endif + +// +// stbds_arr implementation +// + +//int *prev_allocs[65536]; +//int num_prev; + +void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap) +{ + stbds_array_header temp={0}; // force debugging + void *b; + size_t min_len = stbds_arrlen(a) + addlen; + (void) sizeof(temp); + + // compute the minimum capacity needed + if (min_len > min_cap) + min_cap = min_len; + + if (min_cap <= stbds_arrcap(a)) + return a; + + // increase needed capacity to guarantee O(1) amortized + if (min_cap < 2 * stbds_arrcap(a)) + min_cap = 2 * stbds_arrcap(a); + else if (min_cap < 4) + min_cap = 4; + + //if (num_prev < 65536) if (a) prev_allocs[num_prev++] = (int *) ((char *) a+1); + //if (num_prev == 2201) + // num_prev = num_prev; + b = STBDS_REALLOC(NULL, (a) ? stbds_header(a) : 0, elemsize * min_cap + sizeof(stbds_array_header)); + //if (num_prev < 65536) prev_allocs[num_prev++] = (int *) (char *) b; + b = (char *) b + sizeof(stbds_array_header); + if (a == NULL) { + stbds_header(b)->length = 0; + stbds_header(b)->hash_table = 0; + stbds_header(b)->temp = 0; + } else { + STBDS_STATS(++stbds_array_grow); + } + stbds_header(b)->capacity = min_cap; + + return b; +} + +void stbds_arrfreef(void *a) +{ + STBDS_FREE(NULL, stbds_header(a)); +} + +// +// stbds_hm hash table implementation +// + +#ifdef STBDS_INTERNAL_SMALL_BUCKET +#define STBDS_BUCKET_LENGTH 4 +#else +#define STBDS_BUCKET_LENGTH 8 +#endif + +#define STBDS_BUCKET_SHIFT (STBDS_BUCKET_LENGTH == 8 ? 3 : 2) +#define STBDS_BUCKET_MASK (STBDS_BUCKET_LENGTH-1) +#define STBDS_CACHE_LINE_SIZE 64 + +#define STBDS_ALIGN_FWD(n,a) (((n) + (a) - 1) & ~((a)-1)) + +typedef struct +{ + size_t hash [STBDS_BUCKET_LENGTH]; + ptrdiff_t index[STBDS_BUCKET_LENGTH]; +} stbds_hash_bucket; // in 32-bit, this is one 64-byte cache line; in 64-bit, each array is one 64-byte cache line + +typedef struct +{ + char * temp_key; // this MUST be the first field of the hash table + size_t slot_count; + size_t used_count; + size_t used_count_threshold; + size_t used_count_shrink_threshold; + size_t tombstone_count; + size_t tombstone_count_threshold; + size_t seed; + size_t slot_count_log2; + stbds_string_arena string; + stbds_hash_bucket *storage; // not a separate allocation, just 64-byte aligned storage after this struct +} stbds_hash_index; + +#define STBDS_INDEX_EMPTY -1 +#define STBDS_INDEX_DELETED -2 +#define STBDS_INDEX_IN_USE(x) ((x) >= 0) + +#define STBDS_HASH_EMPTY 0 +#define STBDS_HASH_DELETED 1 + +static size_t stbds_hash_seed=0x31415926; + +void stbds_rand_seed(size_t seed) +{ + stbds_hash_seed = seed; +} + +#define stbds_load_32_or_64(var, temp, v32, v64_hi, v64_lo) \ + temp = v64_lo ^ v32, temp <<= 16, temp <<= 16, temp >>= 16, temp >>= 16, /* discard if 32-bit */ \ + var = v64_hi, var <<= 16, var <<= 16, /* discard if 32-bit */ \ + var ^= temp ^ v32 + +#define STBDS_SIZE_T_BITS ((sizeof (size_t)) * 8) + +static size_t stbds_probe_position(size_t hash, size_t slot_count, size_t slot_log2) +{ + size_t pos; + STBDS_NOTUSED(slot_log2); + pos = hash & (slot_count-1); + #ifdef STBDS_INTERNAL_BUCKET_START + pos &= ~STBDS_BUCKET_MASK; + #endif + return pos; +} + +static size_t stbds_log2(size_t slot_count) +{ + size_t n=0; + while (slot_count > 1) { + slot_count >>= 1; + ++n; + } + return n; +} + +static stbds_hash_index *stbds_make_hash_index(size_t slot_count, stbds_hash_index *ot) +{ + stbds_hash_index *t; + t = (stbds_hash_index *) STBDS_REALLOC(NULL,0,(slot_count >> STBDS_BUCKET_SHIFT) * sizeof(stbds_hash_bucket) + sizeof(stbds_hash_index) + STBDS_CACHE_LINE_SIZE-1); + t->storage = (stbds_hash_bucket *) STBDS_ALIGN_FWD((size_t) (t+1), STBDS_CACHE_LINE_SIZE); + t->slot_count = slot_count; + t->slot_count_log2 = stbds_log2(slot_count); + t->tombstone_count = 0; + t->used_count = 0; + + #if 0 // A1 + t->used_count_threshold = slot_count*12/16; // if 12/16th of table is occupied, grow + t->tombstone_count_threshold = slot_count* 2/16; // if tombstones are 2/16th of table, rebuild + t->used_count_shrink_threshold = slot_count* 4/16; // if table is only 4/16th full, shrink + #elif 1 // A2 + //t->used_count_threshold = slot_count*12/16; // if 12/16th of table is occupied, grow + //t->tombstone_count_threshold = slot_count* 3/16; // if tombstones are 3/16th of table, rebuild + //t->used_count_shrink_threshold = slot_count* 4/16; // if table is only 4/16th full, shrink + + // compute without overflowing + t->used_count_threshold = slot_count - (slot_count>>2); + t->tombstone_count_threshold = (slot_count>>3) + (slot_count>>4); + t->used_count_shrink_threshold = slot_count >> 2; + + #elif 0 // B1 + t->used_count_threshold = slot_count*13/16; // if 13/16th of table is occupied, grow + t->tombstone_count_threshold = slot_count* 2/16; // if tombstones are 2/16th of table, rebuild + t->used_count_shrink_threshold = slot_count* 5/16; // if table is only 5/16th full, shrink + #else // C1 + t->used_count_threshold = slot_count*14/16; // if 14/16th of table is occupied, grow + t->tombstone_count_threshold = slot_count* 2/16; // if tombstones are 2/16th of table, rebuild + t->used_count_shrink_threshold = slot_count* 6/16; // if table is only 6/16th full, shrink + #endif + // Following statistics were measured on a Core i7-6700 @ 4.00Ghz, compiled with clang 7.0.1 -O2 + // Note that the larger tables have high variance as they were run fewer times + // A1 A2 B1 C1 + // 0.10ms : 0.10ms : 0.10ms : 0.11ms : 2,000 inserts creating 2K table + // 0.96ms : 0.95ms : 0.97ms : 1.04ms : 20,000 inserts creating 20K table + // 14.48ms : 14.46ms : 10.63ms : 11.00ms : 200,000 inserts creating 200K table + // 195.74ms : 196.35ms : 203.69ms : 214.92ms : 2,000,000 inserts creating 2M table + // 2193.88ms : 2209.22ms : 2285.54ms : 2437.17ms : 20,000,000 inserts creating 20M table + // 65.27ms : 53.77ms : 65.33ms : 65.47ms : 500,000 inserts & deletes in 2K table + // 72.78ms : 62.45ms : 71.95ms : 72.85ms : 500,000 inserts & deletes in 20K table + // 89.47ms : 77.72ms : 96.49ms : 96.75ms : 500,000 inserts & deletes in 200K table + // 97.58ms : 98.14ms : 97.18ms : 97.53ms : 500,000 inserts & deletes in 2M table + // 118.61ms : 119.62ms : 120.16ms : 118.86ms : 500,000 inserts & deletes in 20M table + // 192.11ms : 194.39ms : 196.38ms : 195.73ms : 500,000 inserts & deletes in 200M table + + if (slot_count <= STBDS_BUCKET_LENGTH) + t->used_count_shrink_threshold = 0; + // to avoid infinite loop, we need to guarantee that at least one slot is empty and will terminate probes + STBDS_ASSERT(t->used_count_threshold + t->tombstone_count_threshold < t->slot_count); + STBDS_STATS(++stbds_hash_alloc); + if (ot) { + t->string = ot->string; + // reuse old seed so we can reuse old hashes so below "copy out old data" doesn't do any hashing + t->seed = ot->seed; + } else { + size_t a,b,temp; + memset(&t->string, 0, sizeof(t->string)); + t->seed = stbds_hash_seed; + // LCG + // in 32-bit, a = 2147001325 b = 715136305 + // in 64-bit, a = 2862933555777941757 b = 3037000493 + stbds_load_32_or_64(a,temp, 2147001325, 0x27bb2ee6, 0x87b0b0fd); + stbds_load_32_or_64(b,temp, 715136305, 0, 0xb504f32d); + stbds_hash_seed = stbds_hash_seed * a + b; + } + + { + size_t i,j; + for (i=0; i < slot_count >> STBDS_BUCKET_SHIFT; ++i) { + stbds_hash_bucket *b = &t->storage[i]; + for (j=0; j < STBDS_BUCKET_LENGTH; ++j) + b->hash[j] = STBDS_HASH_EMPTY; + for (j=0; j < STBDS_BUCKET_LENGTH; ++j) + b->index[j] = STBDS_INDEX_EMPTY; + } + } + + // copy out the old data, if any + if (ot) { + size_t i,j; + t->used_count = ot->used_count; + for (i=0; i < ot->slot_count >> STBDS_BUCKET_SHIFT; ++i) { + stbds_hash_bucket *ob = &ot->storage[i]; + for (j=0; j < STBDS_BUCKET_LENGTH; ++j) { + if (STBDS_INDEX_IN_USE(ob->index[j])) { + size_t hash = ob->hash[j]; + size_t pos = stbds_probe_position(hash, t->slot_count, t->slot_count_log2); + size_t step = STBDS_BUCKET_LENGTH; + STBDS_STATS(++stbds_rehash_items); + for (;;) { + size_t limit,z; + stbds_hash_bucket *bucket; + bucket = &t->storage[pos >> STBDS_BUCKET_SHIFT]; + STBDS_STATS(++stbds_rehash_probes); + + for (z=pos & STBDS_BUCKET_MASK; z < STBDS_BUCKET_LENGTH; ++z) { + if (bucket->hash[z] == 0) { + bucket->hash[z] = hash; + bucket->index[z] = ob->index[j]; + goto done; + } + } + + limit = pos & STBDS_BUCKET_MASK; + for (z = 0; z < limit; ++z) { + if (bucket->hash[z] == 0) { + bucket->hash[z] = hash; + bucket->index[z] = ob->index[j]; + goto done; + } + } + + pos += step; // quadratic probing + step += STBDS_BUCKET_LENGTH; + pos &= (t->slot_count-1); + } + } + done: + ; + } + } + } + + return t; +} + +#define STBDS_ROTATE_LEFT(val, n) (((val) << (n)) | ((val) >> (STBDS_SIZE_T_BITS - (n)))) +#define STBDS_ROTATE_RIGHT(val, n) (((val) >> (n)) | ((val) << (STBDS_SIZE_T_BITS - (n)))) + +size_t stbds_hash_string(char *str, size_t seed) +{ + size_t hash = seed; + while (*str) + hash = STBDS_ROTATE_LEFT(hash, 9) + (unsigned char) *str++; + + // Thomas Wang 64-to-32 bit mix function, hopefully also works in 32 bits + hash ^= seed; + hash = (~hash) + (hash << 18); + hash ^= hash ^ STBDS_ROTATE_RIGHT(hash,31); + hash = hash * 21; + hash ^= hash ^ STBDS_ROTATE_RIGHT(hash,11); + hash += (hash << 6); + hash ^= STBDS_ROTATE_RIGHT(hash,22); + return hash+seed; +} + +#ifdef STBDS_SIPHASH_2_4 +#define STBDS_SIPHASH_C_ROUNDS 2 +#define STBDS_SIPHASH_D_ROUNDS 4 +typedef int STBDS_SIPHASH_2_4_can_only_be_used_in_64_bit_builds[sizeof(size_t) == 8 ? 1 : -1]; +#endif + +#ifndef STBDS_SIPHASH_C_ROUNDS +#define STBDS_SIPHASH_C_ROUNDS 1 +#endif +#ifndef STBDS_SIPHASH_D_ROUNDS +#define STBDS_SIPHASH_D_ROUNDS 1 +#endif + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) // conditional expression is constant, for do..while(0) and sizeof()== +#endif + +static size_t stbds_siphash_bytes(void *p, size_t len, size_t seed) +{ + unsigned char *d = (unsigned char *) p; + size_t i,j; + size_t v0,v1,v2,v3, data; + + // hash that works on 32- or 64-bit registers without knowing which we have + // (computes different results on 32-bit and 64-bit platform) + // derived from siphash, but on 32-bit platforms very different as it uses 4 32-bit state not 4 64-bit + v0 = ((((size_t) 0x736f6d65 << 16) << 16) + 0x70736575) ^ seed; + v1 = ((((size_t) 0x646f7261 << 16) << 16) + 0x6e646f6d) ^ ~seed; + v2 = ((((size_t) 0x6c796765 << 16) << 16) + 0x6e657261) ^ seed; + v3 = ((((size_t) 0x74656462 << 16) << 16) + 0x79746573) ^ ~seed; + + #ifdef STBDS_TEST_SIPHASH_2_4 + // hardcoded with key material in the siphash test vectors + v0 ^= 0x0706050403020100ull ^ seed; + v1 ^= 0x0f0e0d0c0b0a0908ull ^ ~seed; + v2 ^= 0x0706050403020100ull ^ seed; + v3 ^= 0x0f0e0d0c0b0a0908ull ^ ~seed; + #endif + + #define STBDS_SIPROUND() \ + do { \ + v0 += v1; v1 = STBDS_ROTATE_LEFT(v1, 13); v1 ^= v0; v0 = STBDS_ROTATE_LEFT(v0,STBDS_SIZE_T_BITS/2); \ + v2 += v3; v3 = STBDS_ROTATE_LEFT(v3, 16); v3 ^= v2; \ + v2 += v1; v1 = STBDS_ROTATE_LEFT(v1, 17); v1 ^= v2; v2 = STBDS_ROTATE_LEFT(v2,STBDS_SIZE_T_BITS/2); \ + v0 += v3; v3 = STBDS_ROTATE_LEFT(v3, 21); v3 ^= v0; \ + } while (0) + + for (i=0; i+sizeof(size_t) <= len; i += sizeof(size_t), d += sizeof(size_t)) { + data = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24); + data |= (size_t) (d[4] | (d[5] << 8) | (d[6] << 16) | (d[7] << 24)) << 16 << 16; // discarded if size_t == 4 + + v3 ^= data; + for (j=0; j < STBDS_SIPHASH_C_ROUNDS; ++j) + STBDS_SIPROUND(); + v0 ^= data; + } + data = len << (STBDS_SIZE_T_BITS-8); + switch (len - i) { + case 7: data |= ((size_t) d[6] << 24) << 24; // fall through + case 6: data |= ((size_t) d[5] << 20) << 20; // fall through + case 5: data |= ((size_t) d[4] << 16) << 16; // fall through + case 4: data |= (d[3] << 24); // fall through + case 3: data |= (d[2] << 16); // fall through + case 2: data |= (d[1] << 8); // fall through + case 1: data |= d[0]; // fall through + case 0: break; + } + v3 ^= data; + for (j=0; j < STBDS_SIPHASH_C_ROUNDS; ++j) + STBDS_SIPROUND(); + v0 ^= data; + v2 ^= 0xff; + for (j=0; j < STBDS_SIPHASH_D_ROUNDS; ++j) + STBDS_SIPROUND(); + +#ifdef STBDS_SIPHASH_2_4 + return v0^v1^v2^v3; +#else + return v1^v2^v3; // slightly stronger since v0^v3 in above cancels out final round operation? I tweeted at the authors of SipHash about this but they didn't reply +#endif +} + +size_t stbds_hash_bytes(void *p, size_t len, size_t seed) +{ +#ifdef STBDS_SIPHASH_2_4 + return stbds_siphash_bytes(p,len,seed); +#else + unsigned char *d = (unsigned char *) p; + + if (len == 4) { + unsigned int hash = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24); + #if 0 + // HASH32-A Bob Jenkin's hash function w/o large constants + hash ^= seed; + hash -= (hash<<6); + hash ^= (hash>>17); + hash -= (hash<<9); + hash ^= seed; + hash ^= (hash<<4); + hash -= (hash<<3); + hash ^= (hash<<10); + hash ^= (hash>>15); + #elif 1 + // HASH32-BB Bob Jenkin's presumably-accidental version of Thomas Wang hash with rotates turned into shifts. + // Note that converting these back to rotates makes it run a lot slower, presumably due to collisions, so I'm + // not really sure what's going on. + hash ^= seed; + hash = (hash ^ 61) ^ (hash >> 16); + hash = hash + (hash << 3); + hash = hash ^ (hash >> 4); + hash = hash * 0x27d4eb2d; + hash ^= seed; + hash = hash ^ (hash >> 15); + #else // HASH32-C - Murmur3 + hash ^= seed; + hash *= 0xcc9e2d51; + hash = (hash << 17) | (hash >> 15); + hash *= 0x1b873593; + hash ^= seed; + hash = (hash << 19) | (hash >> 13); + hash = hash*5 + 0xe6546b64; + hash ^= hash >> 16; + hash *= 0x85ebca6b; + hash ^= seed; + hash ^= hash >> 13; + hash *= 0xc2b2ae35; + hash ^= hash >> 16; + #endif + // Following statistics were measured on a Core i7-6700 @ 4.00Ghz, compiled with clang 7.0.1 -O2 + // Note that the larger tables have high variance as they were run fewer times + // HASH32-A // HASH32-BB // HASH32-C + // 0.10ms // 0.10ms // 0.10ms : 2,000 inserts creating 2K table + // 0.96ms // 0.95ms // 0.99ms : 20,000 inserts creating 20K table + // 14.69ms // 14.43ms // 14.97ms : 200,000 inserts creating 200K table + // 199.99ms // 195.36ms // 202.05ms : 2,000,000 inserts creating 2M table + // 2234.84ms // 2187.74ms // 2240.38ms : 20,000,000 inserts creating 20M table + // 55.68ms // 53.72ms // 57.31ms : 500,000 inserts & deletes in 2K table + // 63.43ms // 61.99ms // 65.73ms : 500,000 inserts & deletes in 20K table + // 80.04ms // 77.96ms // 81.83ms : 500,000 inserts & deletes in 200K table + // 100.42ms // 97.40ms // 102.39ms : 500,000 inserts & deletes in 2M table + // 119.71ms // 120.59ms // 121.63ms : 500,000 inserts & deletes in 20M table + // 185.28ms // 195.15ms // 187.74ms : 500,000 inserts & deletes in 200M table + // 15.58ms // 14.79ms // 15.52ms : 200,000 inserts creating 200K table with varying key spacing + + return (((size_t) hash << 16 << 16) | hash) ^ seed; + } else if (len == 8 && sizeof(size_t) == 8) { + size_t hash = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24); + hash |= (size_t) (d[4] | (d[5] << 8) | (d[6] << 16) | (d[7] << 24)) << 16 << 16; // avoid warning if size_t == 4 + hash ^= seed; + hash = (~hash) + (hash << 21); + hash ^= STBDS_ROTATE_RIGHT(hash,24); + hash *= 265; + hash ^= STBDS_ROTATE_RIGHT(hash,14); + hash ^= seed; + hash *= 21; + hash ^= STBDS_ROTATE_RIGHT(hash,28); + hash += (hash << 31); + hash = (~hash) + (hash << 18); + return hash; + } else { + return stbds_siphash_bytes(p,len,seed); + } +#endif +} +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + +static int stbds_is_key_equal(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode, size_t i) +{ + if (mode >= STBDS_HM_STRING) + return 0==strcmp((char *) key, * (char **) ((char *) a + elemsize*i + keyoffset)); + else + return 0==memcmp(key, (char *) a + elemsize*i + keyoffset, keysize); +} + +#define STBDS_HASH_TO_ARR(x,elemsize) ((char*) (x) - (elemsize)) +#define STBDS_ARR_TO_HASH(x,elemsize) ((char*) (x) + (elemsize)) + +#define stbds_hash_table(a) ((stbds_hash_index *) stbds_header(a)->hash_table) + +void stbds_hmfree_func(void *a, size_t elemsize) +{ + if (a == NULL) return; + if (stbds_hash_table(a) != NULL) { + if (stbds_hash_table(a)->string.mode == STBDS_SH_STRDUP) { + size_t i; + // skip 0th element, which is default + for (i=1; i < stbds_header(a)->length; ++i) + STBDS_FREE(NULL, *(char**) ((char *) a + elemsize*i)); + } + stbds_strreset(&stbds_hash_table(a)->string); + } + STBDS_FREE(NULL, stbds_header(a)->hash_table); + STBDS_FREE(NULL, stbds_header(a)); +} + +static ptrdiff_t stbds_hm_find_slot(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode) +{ + void *raw_a = STBDS_HASH_TO_ARR(a,elemsize); + stbds_hash_index *table = stbds_hash_table(raw_a); + size_t hash = mode >= STBDS_HM_STRING ? stbds_hash_string((char*)key,table->seed) : stbds_hash_bytes(key, keysize,table->seed); + size_t step = STBDS_BUCKET_LENGTH; + size_t limit,i; + size_t pos; + stbds_hash_bucket *bucket; + + if (hash < 2) hash += 2; // stored hash values are forbidden from being 0, so we can detect empty slots + + pos = stbds_probe_position(hash, table->slot_count, table->slot_count_log2); + + for (;;) { + STBDS_STATS(++stbds_hash_probes); + bucket = &table->storage[pos >> STBDS_BUCKET_SHIFT]; + + // start searching from pos to end of bucket, this should help performance on small hash tables that fit in cache + for (i=pos & STBDS_BUCKET_MASK; i < STBDS_BUCKET_LENGTH; ++i) { + if (bucket->hash[i] == hash) { + if (stbds_is_key_equal(a, elemsize, key, keysize, keyoffset, mode, bucket->index[i])) { + return (pos & ~STBDS_BUCKET_MASK)+i; + } + } else if (bucket->hash[i] == STBDS_HASH_EMPTY) { + return -1; + } + } + + // search from beginning of bucket to pos + limit = pos & STBDS_BUCKET_MASK; + for (i = 0; i < limit; ++i) { + if (bucket->hash[i] == hash) { + if (stbds_is_key_equal(a, elemsize, key, keysize, keyoffset, mode, bucket->index[i])) { + return (pos & ~STBDS_BUCKET_MASK)+i; + } + } else if (bucket->hash[i] == STBDS_HASH_EMPTY) { + return -1; + } + } + + // quadratic probing + pos += step; + step += STBDS_BUCKET_LENGTH; + pos &= (table->slot_count-1); + } + /* NOTREACHED */ +} + +void * stbds_hmget_key_ts(void *a, size_t elemsize, void *key, size_t keysize, ptrdiff_t *temp, int mode) +{ + size_t keyoffset = 0; + if (a == NULL) { + // make it non-empty so we can return a temp + a = stbds_arrgrowf(0, elemsize, 0, 1); + stbds_header(a)->length += 1; + memset(a, 0, elemsize); + *temp = STBDS_INDEX_EMPTY; + // adjust a to point after the default element + return STBDS_ARR_TO_HASH(a,elemsize); + } else { + stbds_hash_index *table; + void *raw_a = STBDS_HASH_TO_ARR(a,elemsize); + // adjust a to point to the default element + table = (stbds_hash_index *) stbds_header(raw_a)->hash_table; + if (table == 0) { + *temp = -1; + } else { + ptrdiff_t slot = stbds_hm_find_slot(a, elemsize, key, keysize, keyoffset, mode); + if (slot < 0) { + *temp = STBDS_INDEX_EMPTY; + } else { + stbds_hash_bucket *b = &table->storage[slot >> STBDS_BUCKET_SHIFT]; + *temp = b->index[slot & STBDS_BUCKET_MASK]; + } + } + return a; + } +} + +void * stbds_hmget_key(void *a, size_t elemsize, void *key, size_t keysize, int mode) +{ + ptrdiff_t temp; + void *p = stbds_hmget_key_ts(a, elemsize, key, keysize, &temp, mode); + stbds_temp(STBDS_HASH_TO_ARR(p,elemsize)) = temp; + return p; +} + +void * stbds_hmput_default(void *a, size_t elemsize) +{ + // three cases: + // a is NULL <- allocate + // a has a hash table but no entries, because of shmode <- grow + // a has entries <- do nothing + if (a == NULL || stbds_header(STBDS_HASH_TO_ARR(a,elemsize))->length == 0) { + a = stbds_arrgrowf(a ? STBDS_HASH_TO_ARR(a,elemsize) : NULL, elemsize, 0, 1); + stbds_header(a)->length += 1; + memset(a, 0, elemsize); + a=STBDS_ARR_TO_HASH(a,elemsize); + } + return a; +} + +static char *stbds_strdup(char *str); + +void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int mode) +{ + size_t keyoffset=0; + void *raw_a; + stbds_hash_index *table; + + if (a == NULL) { + a = stbds_arrgrowf(0, elemsize, 0, 1); + memset(a, 0, elemsize); + stbds_header(a)->length += 1; + // adjust a to point AFTER the default element + a = STBDS_ARR_TO_HASH(a,elemsize); + } + + // adjust a to point to the default element + raw_a = a; + a = STBDS_HASH_TO_ARR(a,elemsize); + + table = (stbds_hash_index *) stbds_header(a)->hash_table; + + if (table == NULL || table->used_count >= table->used_count_threshold) { + stbds_hash_index *nt; + size_t slot_count; + + slot_count = (table == NULL) ? STBDS_BUCKET_LENGTH : table->slot_count*2; + nt = stbds_make_hash_index(slot_count, table); + if (table) + STBDS_FREE(NULL, table); + else + nt->string.mode = mode >= STBDS_HM_STRING ? STBDS_SH_DEFAULT : 0; + stbds_header(a)->hash_table = table = nt; + STBDS_STATS(++stbds_hash_grow); + } + + // we iterate hash table explicitly because we want to track if we saw a tombstone + { + size_t hash = mode >= STBDS_HM_STRING ? stbds_hash_string((char*)key,table->seed) : stbds_hash_bytes(key, keysize,table->seed); + size_t step = STBDS_BUCKET_LENGTH; + size_t pos; + ptrdiff_t tombstone = -1; + stbds_hash_bucket *bucket; + + // stored hash values are forbidden from being 0, so we can detect empty slots to early out quickly + if (hash < 2) hash += 2; + + pos = stbds_probe_position(hash, table->slot_count, table->slot_count_log2); + + for (;;) { + size_t limit, i; + STBDS_STATS(++stbds_hash_probes); + bucket = &table->storage[pos >> STBDS_BUCKET_SHIFT]; + + // start searching from pos to end of bucket + for (i=pos & STBDS_BUCKET_MASK; i < STBDS_BUCKET_LENGTH; ++i) { + if (bucket->hash[i] == hash) { + if (stbds_is_key_equal(raw_a, elemsize, key, keysize, keyoffset, mode, bucket->index[i])) { + stbds_temp(a) = bucket->index[i]; + if (mode >= STBDS_HM_STRING) + stbds_temp_key(a) = * (char **) ((char *) raw_a + elemsize*bucket->index[i] + keyoffset); + return STBDS_ARR_TO_HASH(a,elemsize); + } + } else if (bucket->hash[i] == 0) { + pos = (pos & ~STBDS_BUCKET_MASK) + i; + goto found_empty_slot; + } else if (tombstone < 0) { + if (bucket->index[i] == STBDS_INDEX_DELETED) + tombstone = (ptrdiff_t) ((pos & ~STBDS_BUCKET_MASK) + i); + } + } + + // search from beginning of bucket to pos + limit = pos & STBDS_BUCKET_MASK; + for (i = 0; i < limit; ++i) { + if (bucket->hash[i] == hash) { + if (stbds_is_key_equal(raw_a, elemsize, key, keysize, keyoffset, mode, bucket->index[i])) { + stbds_temp(a) = bucket->index[i]; + return STBDS_ARR_TO_HASH(a,elemsize); + } + } else if (bucket->hash[i] == 0) { + pos = (pos & ~STBDS_BUCKET_MASK) + i; + goto found_empty_slot; + } else if (tombstone < 0) { + if (bucket->index[i] == STBDS_INDEX_DELETED) + tombstone = (ptrdiff_t) ((pos & ~STBDS_BUCKET_MASK) + i); + } + } + + // quadratic probing + pos += step; + step += STBDS_BUCKET_LENGTH; + pos &= (table->slot_count-1); + } + found_empty_slot: + if (tombstone >= 0) { + pos = tombstone; + --table->tombstone_count; + } + ++table->used_count; + + { + ptrdiff_t i = (ptrdiff_t) stbds_arrlen(a); + // we want to do stbds_arraddn(1), but we can't use the macros since we don't have something of the right type + if ((size_t) i+1 > stbds_arrcap(a)) + *(void **) &a = stbds_arrgrowf(a, elemsize, 1, 0); + raw_a = STBDS_ARR_TO_HASH(a,elemsize); + + STBDS_ASSERT((size_t) i+1 <= stbds_arrcap(a)); + stbds_header(a)->length = i+1; + bucket = &table->storage[pos >> STBDS_BUCKET_SHIFT]; + bucket->hash[pos & STBDS_BUCKET_MASK] = hash; + bucket->index[pos & STBDS_BUCKET_MASK] = i-1; + stbds_temp(a) = i-1; + + switch (table->string.mode) { + case STBDS_SH_STRDUP: stbds_temp_key(a) = *(char **) ((char *) a + elemsize*i) = stbds_strdup((char*) key); break; + case STBDS_SH_ARENA: stbds_temp_key(a) = *(char **) ((char *) a + elemsize*i) = stbds_stralloc(&table->string, (char*)key); break; + case STBDS_SH_DEFAULT: stbds_temp_key(a) = *(char **) ((char *) a + elemsize*i) = (char *) key; break; + default: memcpy((char *) a + elemsize*i, key, keysize); break; + } + } + return STBDS_ARR_TO_HASH(a,elemsize); + } +} + +void * stbds_shmode_func(size_t elemsize, int mode) +{ + void *a = stbds_arrgrowf(0, elemsize, 0, 1); + stbds_hash_index *h; + memset(a, 0, elemsize); + stbds_header(a)->length = 1; + stbds_header(a)->hash_table = h = (stbds_hash_index *) stbds_make_hash_index(STBDS_BUCKET_LENGTH, NULL); + h->string.mode = (unsigned char) mode; + return STBDS_ARR_TO_HASH(a,elemsize); +} + +void * stbds_hmdel_key(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode) +{ + if (a == NULL) { + return 0; + } else { + stbds_hash_index *table; + void *raw_a = STBDS_HASH_TO_ARR(a,elemsize); + table = (stbds_hash_index *) stbds_header(raw_a)->hash_table; + stbds_temp(raw_a) = 0; + if (table == 0) { + return a; + } else { + ptrdiff_t slot; + slot = stbds_hm_find_slot(a, elemsize, key, keysize, keyoffset, mode); + if (slot < 0) + return a; + else { + stbds_hash_bucket *b = &table->storage[slot >> STBDS_BUCKET_SHIFT]; + int i = slot & STBDS_BUCKET_MASK; + ptrdiff_t old_index = b->index[i]; + ptrdiff_t final_index = (ptrdiff_t) stbds_arrlen(raw_a)-1-1; // minus one for the raw_a vs a, and minus one for 'last' + STBDS_ASSERT(slot < (ptrdiff_t) table->slot_count); + --table->used_count; + ++table->tombstone_count; + stbds_temp(raw_a) = 1; + STBDS_ASSERT(table->used_count >= 0); + //STBDS_ASSERT(table->tombstone_count < table->slot_count/4); + b->hash[i] = STBDS_HASH_DELETED; + b->index[i] = STBDS_INDEX_DELETED; + + if (mode == STBDS_HM_STRING && table->string.mode == STBDS_SH_STRDUP) + STBDS_FREE(NULL, *(char**) ((char *) a+elemsize*old_index)); + + // if indices are the same, memcpy is a no-op, but back-pointer-fixup will fail, so skip + if (old_index != final_index) { + // swap delete + memmove((char*) a + elemsize*old_index, (char*) a + elemsize*final_index, elemsize); + + // now find the slot for the last element + if (mode == STBDS_HM_STRING) + slot = stbds_hm_find_slot(a, elemsize, *(char**) ((char *) a+elemsize*old_index + keyoffset), keysize, keyoffset, mode); + else + slot = stbds_hm_find_slot(a, elemsize, (char* ) a+elemsize*old_index + keyoffset, keysize, keyoffset, mode); + STBDS_ASSERT(slot >= 0); + b = &table->storage[slot >> STBDS_BUCKET_SHIFT]; + i = slot & STBDS_BUCKET_MASK; + STBDS_ASSERT(b->index[i] == final_index); + b->index[i] = old_index; + } + stbds_header(raw_a)->length -= 1; + + if (table->used_count < table->used_count_shrink_threshold && table->slot_count > STBDS_BUCKET_LENGTH) { + stbds_header(raw_a)->hash_table = stbds_make_hash_index(table->slot_count>>1, table); + STBDS_FREE(NULL, table); + STBDS_STATS(++stbds_hash_shrink); + } else if (table->tombstone_count > table->tombstone_count_threshold) { + stbds_header(raw_a)->hash_table = stbds_make_hash_index(table->slot_count , table); + STBDS_FREE(NULL, table); + STBDS_STATS(++stbds_hash_rebuild); + } + + return a; + } + } + } + /* NOTREACHED */ +} + +static char *stbds_strdup(char *str) +{ + // to keep replaceable allocator simple, we don't want to use strdup. + // rolling our own also avoids problem of strdup vs _strdup + size_t len = strlen(str)+1; + char *p = (char*) STBDS_REALLOC(NULL, 0, len); + memmove(p, str, len); + return p; +} + +#ifndef STBDS_STRING_ARENA_BLOCKSIZE_MIN +#define STBDS_STRING_ARENA_BLOCKSIZE_MIN 512u +#endif +#ifndef STBDS_STRING_ARENA_BLOCKSIZE_MAX +#define STBDS_STRING_ARENA_BLOCKSIZE_MAX (1u<<20) +#endif + +char *stbds_stralloc(stbds_string_arena *a, char *str) +{ + char *p; + size_t len = strlen(str)+1; + if (len > a->remaining) { + // compute the next blocksize + size_t blocksize = a->block; + + // size is 512, 512, 1024, 1024, 2048, 2048, 4096, 4096, etc., so that + // there are log(SIZE) allocations to free when we destroy the table + blocksize = (size_t) (STBDS_STRING_ARENA_BLOCKSIZE_MIN) << (blocksize>>1); + + // if size is under 1M, advance to next blocktype + if (blocksize < (size_t)(STBDS_STRING_ARENA_BLOCKSIZE_MAX)) + ++a->block; + + if (len > blocksize) { + // if string is larger than blocksize, then just allocate the full size. + // note that we still advance string_block so block size will continue + // increasing, so e.g. if somebody only calls this with 1000-long strings, + // eventually the arena will start doubling and handling those as well + stbds_string_block *sb = (stbds_string_block *) STBDS_REALLOC(NULL, 0, sizeof(*sb)-8 + len); + memmove(sb->storage, str, len); + if (a->storage) { + // insert it after the first element, so that we don't waste the space there + sb->next = a->storage->next; + a->storage->next = sb; + } else { + sb->next = 0; + a->storage = sb; + a->remaining = 0; // this is redundant, but good for clarity + } + return sb->storage; + } else { + stbds_string_block *sb = (stbds_string_block *) STBDS_REALLOC(NULL, 0, sizeof(*sb)-8 + blocksize); + sb->next = a->storage; + a->storage = sb; + a->remaining = blocksize; + } + } + + STBDS_ASSERT(len <= a->remaining); + p = a->storage->storage + a->remaining - len; + a->remaining -= len; + memmove(p, str, len); + return p; +} + +void stbds_strreset(stbds_string_arena *a) +{ + stbds_string_block *x,*y; + x = a->storage; + while (x) { + y = x->next; + STBDS_FREE(NULL, x); + x = y; + } + memset(a, 0, sizeof(*a)); +} + +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// UNIT TESTS +// + +#ifdef STBDS_UNIT_TESTS +#include +#ifdef STBDS_ASSERT_WAS_UNDEFINED +#undef STBDS_ASSERT +#endif +#ifndef STBDS_ASSERT +#define STBDS_ASSERT assert +#include +#endif + +typedef struct { int key,b,c,d; } stbds_struct; +typedef struct { int key[2],b,c,d; } stbds_struct2; + +static char buffer[256]; +char *strkey(int n) +{ +#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__) + sprintf_s(buffer, sizeof(buffer), "test_%d", n); +#else + sprintf(buffer, "test_%d", n); +#endif + return buffer; +} + +void stbds_unit_tests(void) +{ +#if defined(_MSC_VER) && _MSC_VER <= 1200 && defined(__cplusplus) + // VC6 C++ doesn't like the template<> trick on unnamed structures, so do nothing! + STBDS_ASSERT(0); +#else + const int testsize = 100000; + const int testsize2 = testsize/20; + int *arr=NULL; + struct { int key; int value; } *intmap = NULL; + struct { char *key; int value; } *strmap = NULL, s; + struct { stbds_struct key; int value; } *map = NULL; + stbds_struct *map2 = NULL; + stbds_struct2 *map3 = NULL; + stbds_string_arena sa = { 0 }; + int key3[2] = { 1,2 }; + ptrdiff_t temp; + + int i,j; + + STBDS_ASSERT(arrlen(arr)==0); + for (i=0; i < 20000; i += 50) { + for (j=0; j < i; ++j) + arrpush(arr,j); + arrfree(arr); + } + + for (i=0; i < 4; ++i) { + arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4); + arrdel(arr,i); + arrfree(arr); + arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4); + arrdelswap(arr,i); + arrfree(arr); + } + + for (i=0; i < 5; ++i) { + arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4); + stbds_arrins(arr,i,5); + STBDS_ASSERT(arr[i] == 5); + if (i < 4) + STBDS_ASSERT(arr[4] == 4); + arrfree(arr); + } + + i = 1; + STBDS_ASSERT(hmgeti(intmap,i) == -1); + hmdefault(intmap, -2); + STBDS_ASSERT(hmgeti(intmap, i) == -1); + STBDS_ASSERT(hmget (intmap, i) == -2); + for (i=0; i < testsize; i+=2) + hmput(intmap, i, i*5); + for (i=0; i < testsize; i+=1) { + if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 ); + else STBDS_ASSERT(hmget(intmap, i) == i*5); + if (i & 1) STBDS_ASSERT(hmget_ts(intmap, i, temp) == -2 ); + else STBDS_ASSERT(hmget_ts(intmap, i, temp) == i*5); + } + for (i=0; i < testsize; i+=2) + hmput(intmap, i, i*3); + for (i=0; i < testsize; i+=1) + if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 ); + else STBDS_ASSERT(hmget(intmap, i) == i*3); + for (i=2; i < testsize; i+=4) + hmdel(intmap, i); // delete half the entries + for (i=0; i < testsize; i+=1) + if (i & 3) STBDS_ASSERT(hmget(intmap, i) == -2 ); + else STBDS_ASSERT(hmget(intmap, i) == i*3); + for (i=0; i < testsize; i+=1) + hmdel(intmap, i); // delete the rest of the entries + for (i=0; i < testsize; i+=1) + STBDS_ASSERT(hmget(intmap, i) == -2 ); + hmfree(intmap); + for (i=0; i < testsize; i+=2) + hmput(intmap, i, i*3); + hmfree(intmap); + + #if defined(__clang__) || defined(__GNUC__) + #ifndef __cplusplus + intmap = NULL; + hmput(intmap, 15, 7); + hmput(intmap, 11, 3); + hmput(intmap, 9, 5); + STBDS_ASSERT(hmget(intmap, 9) == 5); + STBDS_ASSERT(hmget(intmap, 11) == 3); + STBDS_ASSERT(hmget(intmap, 15) == 7); + #endif + #endif + + for (i=0; i < testsize; ++i) + stralloc(&sa, strkey(i)); + strreset(&sa); + + { + s.key = "a", s.value = 1; + shputs(strmap, s); + STBDS_ASSERT(*strmap[0].key == 'a'); + STBDS_ASSERT(strmap[0].key == s.key); + STBDS_ASSERT(strmap[0].value == s.value); + shfree(strmap); + } + + { + s.key = "a", s.value = 1; + sh_new_strdup(strmap); + shputs(strmap, s); + STBDS_ASSERT(*strmap[0].key == 'a'); + STBDS_ASSERT(strmap[0].key != s.key); + STBDS_ASSERT(strmap[0].value == s.value); + shfree(strmap); + } + + { + s.key = "a", s.value = 1; + sh_new_arena(strmap); + shputs(strmap, s); + STBDS_ASSERT(*strmap[0].key == 'a'); + STBDS_ASSERT(strmap[0].key != s.key); + STBDS_ASSERT(strmap[0].value == s.value); + shfree(strmap); + } + + for (j=0; j < 2; ++j) { + STBDS_ASSERT(shgeti(strmap,"foo") == -1); + if (j == 0) + sh_new_strdup(strmap); + else + sh_new_arena(strmap); + STBDS_ASSERT(shgeti(strmap,"foo") == -1); + shdefault(strmap, -2); + STBDS_ASSERT(shgeti(strmap,"foo") == -1); + for (i=0; i < testsize; i+=2) + shput(strmap, strkey(i), i*3); + for (i=0; i < testsize; i+=1) + if (i & 1) STBDS_ASSERT(shget(strmap, strkey(i)) == -2 ); + else STBDS_ASSERT(shget(strmap, strkey(i)) == i*3); + for (i=2; i < testsize; i+=4) + shdel(strmap, strkey(i)); // delete half the entries + for (i=0; i < testsize; i+=1) + if (i & 3) STBDS_ASSERT(shget(strmap, strkey(i)) == -2 ); + else STBDS_ASSERT(shget(strmap, strkey(i)) == i*3); + for (i=0; i < testsize; i+=1) + shdel(strmap, strkey(i)); // delete the rest of the entries + for (i=0; i < testsize; i+=1) + STBDS_ASSERT(shget(strmap, strkey(i)) == -2 ); + shfree(strmap); + } + + { + struct { char *key; char value; } *hash = NULL; + char name[4] = "jen"; + shput(hash, "bob" , 'h'); + shput(hash, "sally" , 'e'); + shput(hash, "fred" , 'l'); + shput(hash, "jen" , 'x'); + shput(hash, "doug" , 'o'); + + shput(hash, name , 'l'); + shfree(hash); + } + + for (i=0; i < testsize; i += 2) { + stbds_struct s = { i,i*2,i*3,i*4 }; + hmput(map, s, i*5); + } + + for (i=0; i < testsize; i += 1) { + stbds_struct s = { i,i*2,i*3 ,i*4 }; + stbds_struct t = { i,i*2,i*3+1,i*4 }; + if (i & 1) STBDS_ASSERT(hmget(map, s) == 0); + else STBDS_ASSERT(hmget(map, s) == i*5); + if (i & 1) STBDS_ASSERT(hmget_ts(map, s, temp) == 0); + else STBDS_ASSERT(hmget_ts(map, s, temp) == i*5); + //STBDS_ASSERT(hmget(map, t.key) == 0); + } + + for (i=0; i < testsize; i += 2) { + stbds_struct s = { i,i*2,i*3,i*4 }; + hmputs(map2, s); + } + hmfree(map); + + for (i=0; i < testsize; i += 1) { + stbds_struct s = { i,i*2,i*3,i*4 }; + stbds_struct t = { i,i*2,i*3+1,i*4 }; + if (i & 1) STBDS_ASSERT(hmgets(map2, s.key).d == 0); + else STBDS_ASSERT(hmgets(map2, s.key).d == i*4); + //STBDS_ASSERT(hmgetp(map2, t.key) == 0); + } + hmfree(map2); + + for (i=0; i < testsize; i += 2) { + stbds_struct2 s = { { i,i*2 }, i*3,i*4, i*5 }; + hmputs(map3, s); + } + for (i=0; i < testsize; i += 1) { + stbds_struct2 s = { { i,i*2}, i*3, i*4, i*5 }; + stbds_struct2 t = { { i,i*2}, i*3+1, i*4, i*5 }; + if (i & 1) STBDS_ASSERT(hmgets(map3, s.key).d == 0); + else STBDS_ASSERT(hmgets(map3, s.key).d == i*5); + //STBDS_ASSERT(hmgetp(map3, t.key) == 0); + } +#endif +} +#endif + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2019 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_dxt.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_dxt.h new file mode 100644 index 0000000..6150a87 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_dxt.h @@ -0,0 +1,719 @@ +// stb_dxt.h - v1.12 - DXT1/DXT5 compressor - public domain +// original by fabian "ryg" giesen - ported to C by stb +// use '#define STB_DXT_IMPLEMENTATION' before including to create the implementation +// +// USAGE: +// call stb_compress_dxt_block() for every block (you must pad) +// source should be a 4x4 block of RGBA data in row-major order; +// Alpha channel is not stored if you specify alpha=0 (but you +// must supply some constant alpha in the alpha channel). +// You can turn on dithering and "high quality" using mode. +// +// version history: +// v1.12 - (ryg) fix bug in single-color table generator +// v1.11 - (ryg) avoid racy global init, better single-color tables, remove dither +// v1.10 - (i.c) various small quality improvements +// v1.09 - (stb) update documentation re: surprising alpha channel requirement +// v1.08 - (stb) fix bug in dxt-with-alpha block +// v1.07 - (stb) bc4; allow not using libc; add STB_DXT_STATIC +// v1.06 - (stb) fix to known-broken 1.05 +// v1.05 - (stb) support bc5/3dc (Arvids Kokins), use extern "C" in C++ (Pavel Krajcevski) +// v1.04 - (ryg) default to no rounding bias for lerped colors (as per S3TC/DX10 spec); +// single color match fix (allow for inexact color interpolation); +// optimal DXT5 index finder; "high quality" mode that runs multiple refinement steps. +// v1.03 - (stb) endianness support +// v1.02 - (stb) fix alpha encoding bug +// v1.01 - (stb) fix bug converting to RGB that messed up quality, thanks ryg & cbloom +// v1.00 - (stb) first release +// +// contributors: +// Rich Geldreich (more accurate index selection) +// Kevin Schmidt (#defines for "freestanding" compilation) +// github:ppiastucki (BC4 support) +// Ignacio Castano - improve DXT endpoint quantization +// Alan Hickman - static table initialization +// +// LICENSE +// +// See end of file for license information. + +#ifndef STB_INCLUDE_STB_DXT_H +#define STB_INCLUDE_STB_DXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_DXT_STATIC +#define STBDDEF static +#else +#define STBDDEF extern +#endif + +// compression mode (bitflags) +#define STB_DXT_NORMAL 0 +#define STB_DXT_DITHER 1 // use dithering. was always dubious, now deprecated. does nothing! +#define STB_DXT_HIGHQUAL 2 // high quality mode, does two refinement steps instead of 1. ~30-40% slower. + +STBDDEF void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src_rgba_four_bytes_per_pixel, int alpha, int mode); +STBDDEF void stb_compress_bc4_block(unsigned char *dest, const unsigned char *src_r_one_byte_per_pixel); +STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src_rg_two_byte_per_pixel); + +#define STB_COMPRESS_DXT_BLOCK + +#ifdef __cplusplus +} +#endif +#endif // STB_INCLUDE_STB_DXT_H + +#ifdef STB_DXT_IMPLEMENTATION + +// configuration options for DXT encoder. set them in the project/makefile or just define +// them at the top. + +// STB_DXT_USE_ROUNDING_BIAS +// use a rounding bias during color interpolation. this is closer to what "ideal" +// interpolation would do but doesn't match the S3TC/DX10 spec. old versions (pre-1.03) +// implicitly had this turned on. +// +// in case you're targeting a specific type of hardware (e.g. console programmers): +// NVidia and Intel GPUs (as of 2010) as well as DX9 ref use DXT decoders that are closer +// to STB_DXT_USE_ROUNDING_BIAS. AMD/ATI, S3 and DX10 ref are closer to rounding with no bias. +// you also see "(a*5 + b*3) / 8" on some old GPU designs. +// #define STB_DXT_USE_ROUNDING_BIAS + +#include + +#if !defined(STBD_FABS) +#include +#endif + +#ifndef STBD_FABS +#define STBD_FABS(x) fabs(x) +#endif + +static const unsigned char stb__OMatch5[256][2] = { + { 0, 0 }, { 0, 0 }, { 0, 1 }, { 0, 1 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 1 }, + { 1, 1 }, { 1, 1 }, { 1, 2 }, { 0, 4 }, { 2, 1 }, { 2, 1 }, { 2, 1 }, { 2, 2 }, + { 2, 2 }, { 2, 2 }, { 2, 3 }, { 1, 5 }, { 3, 2 }, { 3, 2 }, { 4, 0 }, { 3, 3 }, + { 3, 3 }, { 3, 3 }, { 3, 4 }, { 3, 4 }, { 3, 4 }, { 3, 5 }, { 4, 3 }, { 4, 3 }, + { 5, 2 }, { 4, 4 }, { 4, 4 }, { 4, 5 }, { 4, 5 }, { 5, 4 }, { 5, 4 }, { 5, 4 }, + { 6, 3 }, { 5, 5 }, { 5, 5 }, { 5, 6 }, { 4, 8 }, { 6, 5 }, { 6, 5 }, { 6, 5 }, + { 6, 6 }, { 6, 6 }, { 6, 6 }, { 6, 7 }, { 5, 9 }, { 7, 6 }, { 7, 6 }, { 8, 4 }, + { 7, 7 }, { 7, 7 }, { 7, 7 }, { 7, 8 }, { 7, 8 }, { 7, 8 }, { 7, 9 }, { 8, 7 }, + { 8, 7 }, { 9, 6 }, { 8, 8 }, { 8, 8 }, { 8, 9 }, { 8, 9 }, { 9, 8 }, { 9, 8 }, + { 9, 8 }, { 10, 7 }, { 9, 9 }, { 9, 9 }, { 9, 10 }, { 8, 12 }, { 10, 9 }, { 10, 9 }, + { 10, 9 }, { 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 11 }, { 9, 13 }, { 11, 10 }, { 11, 10 }, + { 12, 8 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 11, 12 }, { 11, 12 }, { 11, 12 }, { 11, 13 }, + { 12, 11 }, { 12, 11 }, { 13, 10 }, { 12, 12 }, { 12, 12 }, { 12, 13 }, { 12, 13 }, { 13, 12 }, + { 13, 12 }, { 13, 12 }, { 14, 11 }, { 13, 13 }, { 13, 13 }, { 13, 14 }, { 12, 16 }, { 14, 13 }, + { 14, 13 }, { 14, 13 }, { 14, 14 }, { 14, 14 }, { 14, 14 }, { 14, 15 }, { 13, 17 }, { 15, 14 }, + { 15, 14 }, { 16, 12 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 16 }, { 15, 16 }, { 15, 16 }, + { 15, 17 }, { 16, 15 }, { 16, 15 }, { 17, 14 }, { 16, 16 }, { 16, 16 }, { 16, 17 }, { 16, 17 }, + { 17, 16 }, { 17, 16 }, { 17, 16 }, { 18, 15 }, { 17, 17 }, { 17, 17 }, { 17, 18 }, { 16, 20 }, + { 18, 17 }, { 18, 17 }, { 18, 17 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, { 18, 19 }, { 17, 21 }, + { 19, 18 }, { 19, 18 }, { 20, 16 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, { 19, 20 }, { 19, 20 }, + { 19, 20 }, { 19, 21 }, { 20, 19 }, { 20, 19 }, { 21, 18 }, { 20, 20 }, { 20, 20 }, { 20, 21 }, + { 20, 21 }, { 21, 20 }, { 21, 20 }, { 21, 20 }, { 22, 19 }, { 21, 21 }, { 21, 21 }, { 21, 22 }, + { 20, 24 }, { 22, 21 }, { 22, 21 }, { 22, 21 }, { 22, 22 }, { 22, 22 }, { 22, 22 }, { 22, 23 }, + { 21, 25 }, { 23, 22 }, { 23, 22 }, { 24, 20 }, { 23, 23 }, { 23, 23 }, { 23, 23 }, { 23, 24 }, + { 23, 24 }, { 23, 24 }, { 23, 25 }, { 24, 23 }, { 24, 23 }, { 25, 22 }, { 24, 24 }, { 24, 24 }, + { 24, 25 }, { 24, 25 }, { 25, 24 }, { 25, 24 }, { 25, 24 }, { 26, 23 }, { 25, 25 }, { 25, 25 }, + { 25, 26 }, { 24, 28 }, { 26, 25 }, { 26, 25 }, { 26, 25 }, { 26, 26 }, { 26, 26 }, { 26, 26 }, + { 26, 27 }, { 25, 29 }, { 27, 26 }, { 27, 26 }, { 28, 24 }, { 27, 27 }, { 27, 27 }, { 27, 27 }, + { 27, 28 }, { 27, 28 }, { 27, 28 }, { 27, 29 }, { 28, 27 }, { 28, 27 }, { 29, 26 }, { 28, 28 }, + { 28, 28 }, { 28, 29 }, { 28, 29 }, { 29, 28 }, { 29, 28 }, { 29, 28 }, { 30, 27 }, { 29, 29 }, + { 29, 29 }, { 29, 30 }, { 29, 30 }, { 30, 29 }, { 30, 29 }, { 30, 29 }, { 30, 30 }, { 30, 30 }, + { 30, 30 }, { 30, 31 }, { 30, 31 }, { 31, 30 }, { 31, 30 }, { 31, 30 }, { 31, 31 }, { 31, 31 }, +}; +static const unsigned char stb__OMatch6[256][2] = { + { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 }, { 1, 1 }, { 1, 2 }, { 2, 1 }, { 2, 2 }, + { 2, 2 }, { 2, 3 }, { 3, 2 }, { 3, 3 }, { 3, 3 }, { 3, 4 }, { 4, 3 }, { 4, 4 }, + { 4, 4 }, { 4, 5 }, { 5, 4 }, { 5, 5 }, { 5, 5 }, { 5, 6 }, { 6, 5 }, { 6, 6 }, + { 6, 6 }, { 6, 7 }, { 7, 6 }, { 7, 7 }, { 7, 7 }, { 7, 8 }, { 8, 7 }, { 8, 8 }, + { 8, 8 }, { 8, 9 }, { 9, 8 }, { 9, 9 }, { 9, 9 }, { 9, 10 }, { 10, 9 }, { 10, 10 }, + { 10, 10 }, { 10, 11 }, { 11, 10 }, { 8, 16 }, { 11, 11 }, { 11, 12 }, { 12, 11 }, { 9, 17 }, + { 12, 12 }, { 12, 13 }, { 13, 12 }, { 11, 16 }, { 13, 13 }, { 13, 14 }, { 14, 13 }, { 12, 17 }, + { 14, 14 }, { 14, 15 }, { 15, 14 }, { 14, 16 }, { 15, 15 }, { 15, 16 }, { 16, 14 }, { 16, 15 }, + { 17, 14 }, { 16, 16 }, { 16, 17 }, { 17, 16 }, { 18, 15 }, { 17, 17 }, { 17, 18 }, { 18, 17 }, + { 20, 14 }, { 18, 18 }, { 18, 19 }, { 19, 18 }, { 21, 15 }, { 19, 19 }, { 19, 20 }, { 20, 19 }, + { 20, 20 }, { 20, 20 }, { 20, 21 }, { 21, 20 }, { 21, 21 }, { 21, 21 }, { 21, 22 }, { 22, 21 }, + { 22, 22 }, { 22, 22 }, { 22, 23 }, { 23, 22 }, { 23, 23 }, { 23, 23 }, { 23, 24 }, { 24, 23 }, + { 24, 24 }, { 24, 24 }, { 24, 25 }, { 25, 24 }, { 25, 25 }, { 25, 25 }, { 25, 26 }, { 26, 25 }, + { 26, 26 }, { 26, 26 }, { 26, 27 }, { 27, 26 }, { 24, 32 }, { 27, 27 }, { 27, 28 }, { 28, 27 }, + { 25, 33 }, { 28, 28 }, { 28, 29 }, { 29, 28 }, { 27, 32 }, { 29, 29 }, { 29, 30 }, { 30, 29 }, + { 28, 33 }, { 30, 30 }, { 30, 31 }, { 31, 30 }, { 30, 32 }, { 31, 31 }, { 31, 32 }, { 32, 30 }, + { 32, 31 }, { 33, 30 }, { 32, 32 }, { 32, 33 }, { 33, 32 }, { 34, 31 }, { 33, 33 }, { 33, 34 }, + { 34, 33 }, { 36, 30 }, { 34, 34 }, { 34, 35 }, { 35, 34 }, { 37, 31 }, { 35, 35 }, { 35, 36 }, + { 36, 35 }, { 36, 36 }, { 36, 36 }, { 36, 37 }, { 37, 36 }, { 37, 37 }, { 37, 37 }, { 37, 38 }, + { 38, 37 }, { 38, 38 }, { 38, 38 }, { 38, 39 }, { 39, 38 }, { 39, 39 }, { 39, 39 }, { 39, 40 }, + { 40, 39 }, { 40, 40 }, { 40, 40 }, { 40, 41 }, { 41, 40 }, { 41, 41 }, { 41, 41 }, { 41, 42 }, + { 42, 41 }, { 42, 42 }, { 42, 42 }, { 42, 43 }, { 43, 42 }, { 40, 48 }, { 43, 43 }, { 43, 44 }, + { 44, 43 }, { 41, 49 }, { 44, 44 }, { 44, 45 }, { 45, 44 }, { 43, 48 }, { 45, 45 }, { 45, 46 }, + { 46, 45 }, { 44, 49 }, { 46, 46 }, { 46, 47 }, { 47, 46 }, { 46, 48 }, { 47, 47 }, { 47, 48 }, + { 48, 46 }, { 48, 47 }, { 49, 46 }, { 48, 48 }, { 48, 49 }, { 49, 48 }, { 50, 47 }, { 49, 49 }, + { 49, 50 }, { 50, 49 }, { 52, 46 }, { 50, 50 }, { 50, 51 }, { 51, 50 }, { 53, 47 }, { 51, 51 }, + { 51, 52 }, { 52, 51 }, { 52, 52 }, { 52, 52 }, { 52, 53 }, { 53, 52 }, { 53, 53 }, { 53, 53 }, + { 53, 54 }, { 54, 53 }, { 54, 54 }, { 54, 54 }, { 54, 55 }, { 55, 54 }, { 55, 55 }, { 55, 55 }, + { 55, 56 }, { 56, 55 }, { 56, 56 }, { 56, 56 }, { 56, 57 }, { 57, 56 }, { 57, 57 }, { 57, 57 }, + { 57, 58 }, { 58, 57 }, { 58, 58 }, { 58, 58 }, { 58, 59 }, { 59, 58 }, { 59, 59 }, { 59, 59 }, + { 59, 60 }, { 60, 59 }, { 60, 60 }, { 60, 60 }, { 60, 61 }, { 61, 60 }, { 61, 61 }, { 61, 61 }, + { 61, 62 }, { 62, 61 }, { 62, 62 }, { 62, 62 }, { 62, 63 }, { 63, 62 }, { 63, 63 }, { 63, 63 }, +}; + +static int stb__Mul8Bit(int a, int b) +{ + int t = a*b + 128; + return (t + (t >> 8)) >> 8; +} + +static void stb__From16Bit(unsigned char *out, unsigned short v) +{ + int rv = (v & 0xf800) >> 11; + int gv = (v & 0x07e0) >> 5; + int bv = (v & 0x001f) >> 0; + + // expand to 8 bits via bit replication + out[0] = (rv * 33) >> 2; + out[1] = (gv * 65) >> 4; + out[2] = (bv * 33) >> 2; + out[3] = 0; +} + +static unsigned short stb__As16Bit(int r, int g, int b) +{ + return (unsigned short)((stb__Mul8Bit(r,31) << 11) + (stb__Mul8Bit(g,63) << 5) + stb__Mul8Bit(b,31)); +} + +// linear interpolation at 1/3 point between a and b, using desired rounding type +static int stb__Lerp13(int a, int b) +{ +#ifdef STB_DXT_USE_ROUNDING_BIAS + // with rounding bias + return a + stb__Mul8Bit(b-a, 0x55); +#else + // without rounding bias + // replace "/ 3" by "* 0xaaab) >> 17" if your compiler sucks or you really need every ounce of speed. + return (2*a + b) / 3; +#endif +} + +// lerp RGB color +static void stb__Lerp13RGB(unsigned char *out, unsigned char *p1, unsigned char *p2) +{ + out[0] = (unsigned char)stb__Lerp13(p1[0], p2[0]); + out[1] = (unsigned char)stb__Lerp13(p1[1], p2[1]); + out[2] = (unsigned char)stb__Lerp13(p1[2], p2[2]); +} + +/****************************************************************************/ + +static void stb__EvalColors(unsigned char *color,unsigned short c0,unsigned short c1) +{ + stb__From16Bit(color+ 0, c0); + stb__From16Bit(color+ 4, c1); + stb__Lerp13RGB(color+ 8, color+0, color+4); + stb__Lerp13RGB(color+12, color+4, color+0); +} + +// The color matching function +static unsigned int stb__MatchColorsBlock(unsigned char *block, unsigned char *color) +{ + unsigned int mask = 0; + int dirr = color[0*4+0] - color[1*4+0]; + int dirg = color[0*4+1] - color[1*4+1]; + int dirb = color[0*4+2] - color[1*4+2]; + int dots[16]; + int stops[4]; + int i; + int c0Point, halfPoint, c3Point; + + for(i=0;i<16;i++) + dots[i] = block[i*4+0]*dirr + block[i*4+1]*dirg + block[i*4+2]*dirb; + + for(i=0;i<4;i++) + stops[i] = color[i*4+0]*dirr + color[i*4+1]*dirg + color[i*4+2]*dirb; + + // think of the colors as arranged on a line; project point onto that line, then choose + // next color out of available ones. we compute the crossover points for "best color in top + // half"/"best in bottom half" and then the same inside that subinterval. + // + // relying on this 1d approximation isn't always optimal in terms of euclidean distance, + // but it's very close and a lot faster. + // http://cbloomrants.blogspot.com/2008/12/12-08-08-dxtc-summary.html + + c0Point = (stops[1] + stops[3]); + halfPoint = (stops[3] + stops[2]); + c3Point = (stops[2] + stops[0]); + + for (i=15;i>=0;i--) { + int dot = dots[i]*2; + mask <<= 2; + + if(dot < halfPoint) + mask |= (dot < c0Point) ? 1 : 3; + else + mask |= (dot < c3Point) ? 2 : 0; + } + + return mask; +} + +// The color optimization function. (Clever code, part 1) +static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16) +{ + int mind,maxd; + unsigned char *minp, *maxp; + double magn; + int v_r,v_g,v_b; + static const int nIterPower = 4; + float covf[6],vfr,vfg,vfb; + + // determine color distribution + int cov[6]; + int mu[3],min[3],max[3]; + int ch,i,iter; + + for(ch=0;ch<3;ch++) + { + const unsigned char *bp = ((const unsigned char *) block) + ch; + int muv,minv,maxv; + + muv = minv = maxv = bp[0]; + for(i=4;i<64;i+=4) + { + muv += bp[i]; + if (bp[i] < minv) minv = bp[i]; + else if (bp[i] > maxv) maxv = bp[i]; + } + + mu[ch] = (muv + 8) >> 4; + min[ch] = minv; + max[ch] = maxv; + } + + // determine covariance matrix + for (i=0;i<6;i++) + cov[i] = 0; + + for (i=0;i<16;i++) + { + int r = block[i*4+0] - mu[0]; + int g = block[i*4+1] - mu[1]; + int b = block[i*4+2] - mu[2]; + + cov[0] += r*r; + cov[1] += r*g; + cov[2] += r*b; + cov[3] += g*g; + cov[4] += g*b; + cov[5] += b*b; + } + + // convert covariance matrix to float, find principal axis via power iter + for(i=0;i<6;i++) + covf[i] = cov[i] / 255.0f; + + vfr = (float) (max[0] - min[0]); + vfg = (float) (max[1] - min[1]); + vfb = (float) (max[2] - min[2]); + + for(iter=0;iter magn) magn = STBD_FABS(vfg); + if (STBD_FABS(vfb) > magn) magn = STBD_FABS(vfb); + + if(magn < 4.0f) { // too small, default to luminance + v_r = 299; // JPEG YCbCr luma coefs, scaled by 1000. + v_g = 587; + v_b = 114; + } else { + magn = 512.0 / magn; + v_r = (int) (vfr * magn); + v_g = (int) (vfg * magn); + v_b = (int) (vfb * magn); + } + + minp = maxp = block; + mind = maxd = block[0]*v_r + block[1]*v_g + block[2]*v_b; + // Pick colors at extreme points + for(i=1;i<16;i++) + { + int dot = block[i*4+0]*v_r + block[i*4+1]*v_g + block[i*4+2]*v_b; + + if (dot < mind) { + mind = dot; + minp = block+i*4; + } + + if (dot > maxd) { + maxd = dot; + maxp = block+i*4; + } + } + + *pmax16 = stb__As16Bit(maxp[0],maxp[1],maxp[2]); + *pmin16 = stb__As16Bit(minp[0],minp[1],minp[2]); +} + +static const float stb__midpoints5[32] = { + 0.015686f, 0.047059f, 0.078431f, 0.111765f, 0.145098f, 0.176471f, 0.207843f, 0.241176f, 0.274510f, 0.305882f, 0.337255f, 0.370588f, 0.403922f, 0.435294f, 0.466667f, 0.5f, + 0.533333f, 0.564706f, 0.596078f, 0.629412f, 0.662745f, 0.694118f, 0.725490f, 0.758824f, 0.792157f, 0.823529f, 0.854902f, 0.888235f, 0.921569f, 0.952941f, 0.984314f, 1.0f +}; + +static const float stb__midpoints6[64] = { + 0.007843f, 0.023529f, 0.039216f, 0.054902f, 0.070588f, 0.086275f, 0.101961f, 0.117647f, 0.133333f, 0.149020f, 0.164706f, 0.180392f, 0.196078f, 0.211765f, 0.227451f, 0.245098f, + 0.262745f, 0.278431f, 0.294118f, 0.309804f, 0.325490f, 0.341176f, 0.356863f, 0.372549f, 0.388235f, 0.403922f, 0.419608f, 0.435294f, 0.450980f, 0.466667f, 0.482353f, 0.500000f, + 0.517647f, 0.533333f, 0.549020f, 0.564706f, 0.580392f, 0.596078f, 0.611765f, 0.627451f, 0.643137f, 0.658824f, 0.674510f, 0.690196f, 0.705882f, 0.721569f, 0.737255f, 0.754902f, + 0.772549f, 0.788235f, 0.803922f, 0.819608f, 0.835294f, 0.850980f, 0.866667f, 0.882353f, 0.898039f, 0.913725f, 0.929412f, 0.945098f, 0.960784f, 0.976471f, 0.992157f, 1.0f +}; + +static unsigned short stb__Quantize5(float x) +{ + unsigned short q; + x = x < 0 ? 0 : x > 1 ? 1 : x; // saturate + q = (unsigned short)(x * 31); + q += (x > stb__midpoints5[q]); + return q; +} + +static unsigned short stb__Quantize6(float x) +{ + unsigned short q; + x = x < 0 ? 0 : x > 1 ? 1 : x; // saturate + q = (unsigned short)(x * 63); + q += (x > stb__midpoints6[q]); + return q; +} + +// The refinement function. (Clever code, part 2) +// Tries to optimize colors to suit block contents better. +// (By solving a least squares system via normal equations+Cramer's rule) +static int stb__RefineBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16, unsigned int mask) +{ + static const int w1Tab[4] = { 3,0,2,1 }; + static const int prods[4] = { 0x090000,0x000900,0x040102,0x010402 }; + // ^some magic to save a lot of multiplies in the accumulating loop... + // (precomputed products of weights for least squares system, accumulated inside one 32-bit register) + + float f; + unsigned short oldMin, oldMax, min16, max16; + int i, akku = 0, xx,xy,yy; + int At1_r,At1_g,At1_b; + int At2_r,At2_g,At2_b; + unsigned int cm = mask; + + oldMin = *pmin16; + oldMax = *pmax16; + + if((mask ^ (mask<<2)) < 4) // all pixels have the same index? + { + // yes, linear system would be singular; solve using optimal + // single-color match on average color + int r = 8, g = 8, b = 8; + for (i=0;i<16;++i) { + r += block[i*4+0]; + g += block[i*4+1]; + b += block[i*4+2]; + } + + r >>= 4; g >>= 4; b >>= 4; + + max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0]; + min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1]; + } else { + At1_r = At1_g = At1_b = 0; + At2_r = At2_g = At2_b = 0; + for (i=0;i<16;++i,cm>>=2) { + int step = cm&3; + int w1 = w1Tab[step]; + int r = block[i*4+0]; + int g = block[i*4+1]; + int b = block[i*4+2]; + + akku += prods[step]; + At1_r += w1*r; + At1_g += w1*g; + At1_b += w1*b; + At2_r += r; + At2_g += g; + At2_b += b; + } + + At2_r = 3*At2_r - At1_r; + At2_g = 3*At2_g - At1_g; + At2_b = 3*At2_b - At1_b; + + // extract solutions and decide solvability + xx = akku >> 16; + yy = (akku >> 8) & 0xff; + xy = (akku >> 0) & 0xff; + + f = 3.0f / 255.0f / (xx*yy - xy*xy); + + max16 = stb__Quantize5((At1_r*yy - At2_r * xy) * f) << 11; + max16 |= stb__Quantize6((At1_g*yy - At2_g * xy) * f) << 5; + max16 |= stb__Quantize5((At1_b*yy - At2_b * xy) * f) << 0; + + min16 = stb__Quantize5((At2_r*xx - At1_r * xy) * f) << 11; + min16 |= stb__Quantize6((At2_g*xx - At1_g * xy) * f) << 5; + min16 |= stb__Quantize5((At2_b*xx - At1_b * xy) * f) << 0; + } + + *pmin16 = min16; + *pmax16 = max16; + return oldMin != min16 || oldMax != max16; +} + +// Color block compression +static void stb__CompressColorBlock(unsigned char *dest, unsigned char *block, int mode) +{ + unsigned int mask; + int i; + int refinecount; + unsigned short max16, min16; + unsigned char color[4*4]; + + refinecount = (mode & STB_DXT_HIGHQUAL) ? 2 : 1; + + // check if block is constant + for (i=1;i<16;i++) + if (((unsigned int *) block)[i] != ((unsigned int *) block)[0]) + break; + + if(i == 16) { // constant color + int r = block[0], g = block[1], b = block[2]; + mask = 0xaaaaaaaa; + max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0]; + min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1]; + } else { + // first step: PCA+map along principal axis + stb__OptimizeColorsBlock(block,&max16,&min16); + if (max16 != min16) { + stb__EvalColors(color,max16,min16); + mask = stb__MatchColorsBlock(block,color); + } else + mask = 0; + + // third step: refine (multiple times if requested) + for (i=0;i> 8); + dest[2] = (unsigned char) (min16); + dest[3] = (unsigned char) (min16 >> 8); + dest[4] = (unsigned char) (mask); + dest[5] = (unsigned char) (mask >> 8); + dest[6] = (unsigned char) (mask >> 16); + dest[7] = (unsigned char) (mask >> 24); +} + +// Alpha block compression (this is easy for a change) +static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src, int stride) +{ + int i,dist,bias,dist4,dist2,bits,mask; + + // find min/max color + int mn,mx; + mn = mx = src[0]; + + for (i=1;i<16;i++) + { + if (src[i*stride] < mn) mn = src[i*stride]; + else if (src[i*stride] > mx) mx = src[i*stride]; + } + + // encode them + dest[0] = (unsigned char)mx; + dest[1] = (unsigned char)mn; + dest += 2; + + // determine bias and emit color indices + // given the choice of mx/mn, these indices are optimal: + // http://fgiesen.wordpress.com/2009/12/15/dxt5-alpha-block-index-determination/ + dist = mx-mn; + dist4 = dist*4; + dist2 = dist*2; + bias = (dist < 8) ? (dist - 1) : (dist/2 + 2); + bias -= mn * 7; + bits = 0,mask=0; + + for (i=0;i<16;i++) { + int a = src[i*stride]*7 + bias; + int ind,t; + + // select index. this is a "linear scale" lerp factor between 0 (val=min) and 7 (val=max). + t = (a >= dist4) ? -1 : 0; ind = t & 4; a -= dist4 & t; + t = (a >= dist2) ? -1 : 0; ind += t & 2; a -= dist2 & t; + ind += (a >= dist); + + // turn linear scale into DXT index (0/1 are extremal pts) + ind = -ind & 7; + ind ^= (2 > ind); + + // write index + mask |= ind << bits; + if((bits += 3) >= 8) { + *dest++ = (unsigned char)mask; + mask >>= 8; + bits -= 8; + } + } +} + +void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode) +{ + unsigned char data[16][4]; + if (alpha) { + int i; + stb__CompressAlphaBlock(dest,(unsigned char*) src+3, 4); + dest += 8; + // make a new copy of the data in which alpha is opaque, + // because code uses a fast test for color constancy + memcpy(data, src, 4*16); + for (i=0; i < 16; ++i) + data[i][3] = 255; + src = &data[0][0]; + } + + stb__CompressColorBlock(dest,(unsigned char*) src,mode); +} + +void stb_compress_bc4_block(unsigned char *dest, const unsigned char *src) +{ + stb__CompressAlphaBlock(dest,(unsigned char*) src, 1); +} + +void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src) +{ + stb__CompressAlphaBlock(dest,(unsigned char*) src,2); + stb__CompressAlphaBlock(dest + 8,(unsigned char*) src+1,2); +} +#endif // STB_DXT_IMPLEMENTATION + +// Compile with STB_DXT_IMPLEMENTATION and STB_DXT_GENERATE_TABLES +// defined to generate the tables above. +#ifdef STB_DXT_GENERATE_TABLES +#include + +int main() +{ + int i, j; + const char *omatch_names[] = { "stb__OMatch5", "stb__OMatch6" }; + int dequant_mults[2] = { 33*4, 65 }; // .4 fixed-point dequant multipliers + + // optimal endpoint tables + for (i = 0; i < 2; ++i) { + int dequant = dequant_mults[i]; + int size = i ? 64 : 32; + printf("static const unsigned char %s[256][2] = {\n", omatch_names[i]); + for (int j = 0; j < 256; ++j) { + int mn, mx; + int best_mn = 0, best_mx = 0; + int best_err = 256 * 100; + for (mn=0;mn> 4; + int maxe = (mx * dequant) >> 4; + int err = abs(stb__Lerp13(maxe, mine) - j) * 100; + + // DX10 spec says that interpolation must be within 3% of "correct" result, + // add this as error term. Normally we'd expect a random distribution of + // +-1.5% error, but nowhere in the spec does it say that the error has to be + // unbiased - better safe than sorry. + err += abs(maxe - mine) * 3; + + if(err < best_err) { + best_mn = mn; + best_mx = mx; + best_err = err; + } + } + } + if ((j % 8) == 0) printf(" "); // 2 spaces, third is done below + printf(" { %2d, %2d },", best_mx, best_mn); + if ((j % 8) == 7) printf("\n"); + } + printf("};\n"); + } + + return 0; +} +#endif + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_easy_font.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_easy_font.h new file mode 100644 index 0000000..b663258 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_easy_font.h @@ -0,0 +1,305 @@ +// stb_easy_font.h - v1.1 - bitmap font for 3D rendering - public domain +// Sean Barrett, Feb 2015 +// +// Easy-to-deploy, +// reasonably compact, +// extremely inefficient performance-wise, +// crappy-looking, +// ASCII-only, +// bitmap font for use in 3D APIs. +// +// Intended for when you just want to get some text displaying +// in a 3D app as quickly as possible. +// +// Doesn't use any textures, instead builds characters out of quads. +// +// DOCUMENTATION: +// +// int stb_easy_font_width(char *text) +// int stb_easy_font_height(char *text) +// +// Takes a string and returns the horizontal size and the +// vertical size (which can vary if 'text' has newlines). +// +// int stb_easy_font_print(float x, float y, +// char *text, unsigned char color[4], +// void *vertex_buffer, int vbuf_size) +// +// Takes a string (which can contain '\n') and fills out a +// vertex buffer with renderable data to draw the string. +// Output data assumes increasing x is rightwards, increasing y +// is downwards. +// +// The vertex data is divided into quads, i.e. there are four +// vertices in the vertex buffer for each quad. +// +// The vertices are stored in an interleaved format: +// +// x:float +// y:float +// z:float +// color:uint8[4] +// +// You can ignore z and color if you get them from elsewhere +// This format was chosen in the hopes it would make it +// easier for you to reuse existing vertex-buffer-drawing code. +// +// If you pass in NULL for color, it becomes 255,255,255,255. +// +// Returns the number of quads. +// +// If the buffer isn't large enough, it will truncate. +// Expect it to use an average of ~270 bytes per character. +// +// If your API doesn't draw quads, build a reusable index +// list that allows you to render quads as indexed triangles. +// +// void stb_easy_font_spacing(float spacing) +// +// Use positive values to expand the space between characters, +// and small negative values (no smaller than -1.5) to contract +// the space between characters. +// +// E.g. spacing = 1 adds one "pixel" of spacing between the +// characters. spacing = -1 is reasonable but feels a bit too +// compact to me; -0.5 is a reasonable compromise as long as +// you're scaling the font up. +// +// LICENSE +// +// See end of file for license information. +// +// VERSION HISTORY +// +// (2020-02-02) 1.1 make everything static so can compile it in more than one src file +// (2017-01-15) 1.0 space character takes same space as numbers; fix bad spacing of 'f' +// (2016-01-22) 0.7 width() supports multiline text; add height() +// (2015-09-13) 0.6 #include ; updated license +// (2015-02-01) 0.5 First release +// +// CONTRIBUTORS +// +// github:vassvik -- bug report +// github:podsvirov -- fix multiple definition errors + +#if 0 +// SAMPLE CODE: +// +// Here's sample code for old OpenGL; it's a lot more complicated +// to make work on modern APIs, and that's your problem. +// +void print_string(float x, float y, char *text, float r, float g, float b) +{ + static char buffer[99999]; // ~500 chars + int num_quads; + + num_quads = stb_easy_font_print(x, y, text, NULL, buffer, sizeof(buffer)); + + glColor3f(r,g,b); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 16, buffer); + glDrawArrays(GL_QUADS, 0, num_quads*4); + glDisableClientState(GL_VERTEX_ARRAY); +} +#endif + +#ifndef INCLUDE_STB_EASY_FONT_H +#define INCLUDE_STB_EASY_FONT_H + +#include +#include + +static struct stb_easy_font_info_struct { + unsigned char advance; + unsigned char h_seg; + unsigned char v_seg; +} stb_easy_font_charinfo[96] = { + { 6, 0, 0 }, { 3, 0, 0 }, { 5, 1, 1 }, { 7, 1, 4 }, + { 7, 3, 7 }, { 7, 6, 12 }, { 7, 8, 19 }, { 4, 16, 21 }, + { 4, 17, 22 }, { 4, 19, 23 }, { 23, 21, 24 }, { 23, 22, 31 }, + { 20, 23, 34 }, { 22, 23, 36 }, { 19, 24, 36 }, { 21, 25, 36 }, + { 6, 25, 39 }, { 6, 27, 43 }, { 6, 28, 45 }, { 6, 30, 49 }, + { 6, 33, 53 }, { 6, 34, 57 }, { 6, 40, 58 }, { 6, 46, 59 }, + { 6, 47, 62 }, { 6, 55, 64 }, { 19, 57, 68 }, { 20, 59, 68 }, + { 21, 61, 69 }, { 22, 66, 69 }, { 21, 68, 69 }, { 7, 73, 69 }, + { 9, 75, 74 }, { 6, 78, 81 }, { 6, 80, 85 }, { 6, 83, 90 }, + { 6, 85, 91 }, { 6, 87, 95 }, { 6, 90, 96 }, { 7, 92, 97 }, + { 6, 96,102 }, { 5, 97,106 }, { 6, 99,107 }, { 6,100,110 }, + { 6,100,115 }, { 7,101,116 }, { 6,101,121 }, { 6,101,125 }, + { 6,102,129 }, { 7,103,133 }, { 6,104,140 }, { 6,105,145 }, + { 7,107,149 }, { 6,108,151 }, { 7,109,155 }, { 7,109,160 }, + { 7,109,165 }, { 7,118,167 }, { 6,118,172 }, { 4,120,176 }, + { 6,122,177 }, { 4,122,181 }, { 23,124,182 }, { 22,129,182 }, + { 4,130,182 }, { 22,131,183 }, { 6,133,187 }, { 22,135,191 }, + { 6,137,192 }, { 22,139,196 }, { 6,144,197 }, { 22,147,198 }, + { 6,150,202 }, { 19,151,206 }, { 21,152,207 }, { 6,155,209 }, + { 3,160,210 }, { 23,160,211 }, { 22,164,216 }, { 22,165,220 }, + { 22,167,224 }, { 22,169,228 }, { 21,171,232 }, { 21,173,233 }, + { 5,178,233 }, { 22,179,234 }, { 23,180,238 }, { 23,180,243 }, + { 23,180,248 }, { 22,189,248 }, { 22,191,252 }, { 5,196,252 }, + { 3,203,252 }, { 5,203,253 }, { 22,210,253 }, { 0,214,253 }, +}; + +static unsigned char stb_easy_font_hseg[214] = { + 97,37,69,84,28,51,2,18,10,49,98,41,65,25,81,105,33,9,97,1,97,37,37,36, + 81,10,98,107,3,100,3,99,58,51,4,99,58,8,73,81,10,50,98,8,73,81,4,10,50, + 98,8,25,33,65,81,10,50,17,65,97,25,33,25,49,9,65,20,68,1,65,25,49,41, + 11,105,13,101,76,10,50,10,50,98,11,99,10,98,11,50,99,11,50,11,99,8,57, + 58,3,99,99,107,10,10,11,10,99,11,5,100,41,65,57,41,65,9,17,81,97,3,107, + 9,97,1,97,33,25,9,25,41,100,41,26,82,42,98,27,83,42,98,26,51,82,8,41, + 35,8,10,26,82,114,42,1,114,8,9,73,57,81,41,97,18,8,8,25,26,26,82,26,82, + 26,82,41,25,33,82,26,49,73,35,90,17,81,41,65,57,41,65,25,81,90,114,20, + 84,73,57,41,49,25,33,65,81,9,97,1,97,25,33,65,81,57,33,25,41,25, +}; + +static unsigned char stb_easy_font_vseg[253] = { + 4,2,8,10,15,8,15,33,8,15,8,73,82,73,57,41,82,10,82,18,66,10,21,29,1,65, + 27,8,27,9,65,8,10,50,97,74,66,42,10,21,57,41,29,25,14,81,73,57,26,8,8, + 26,66,3,8,8,15,19,21,90,58,26,18,66,18,105,89,28,74,17,8,73,57,26,21, + 8,42,41,42,8,28,22,8,8,30,7,8,8,26,66,21,7,8,8,29,7,7,21,8,8,8,59,7,8, + 8,15,29,8,8,14,7,57,43,10,82,7,7,25,42,25,15,7,25,41,15,21,105,105,29, + 7,57,57,26,21,105,73,97,89,28,97,7,57,58,26,82,18,57,57,74,8,30,6,8,8, + 14,3,58,90,58,11,7,74,43,74,15,2,82,2,42,75,42,10,67,57,41,10,7,2,42, + 74,106,15,2,35,8,8,29,7,8,8,59,35,51,8,8,15,35,30,35,8,8,30,7,8,8,60, + 36,8,45,7,7,36,8,43,8,44,21,8,8,44,35,8,8,43,23,8,8,43,35,8,8,31,21,15, + 20,8,8,28,18,58,89,58,26,21,89,73,89,29,20,8,8,30,7, +}; + +typedef struct +{ + unsigned char c[4]; +} stb_easy_font_color; + +static int stb_easy_font_draw_segs(float x, float y, unsigned char *segs, int num_segs, int vertical, stb_easy_font_color c, char *vbuf, int vbuf_size, int offset) +{ + int i,j; + for (i=0; i < num_segs; ++i) { + int len = segs[i] & 7; + x += (float) ((segs[i] >> 3) & 1); + if (len && offset+64 <= vbuf_size) { + float y0 = y + (float) (segs[i]>>4); + for (j=0; j < 4; ++j) { + * (float *) (vbuf+offset+0) = x + (j==1 || j==2 ? (vertical ? 1 : len) : 0); + * (float *) (vbuf+offset+4) = y0 + ( j >= 2 ? (vertical ? len : 1) : 0); + * (float *) (vbuf+offset+8) = 0.f; + * (stb_easy_font_color *) (vbuf+offset+12) = c; + offset += 16; + } + } + } + return offset; +} + +static float stb_easy_font_spacing_val = 0; +static void stb_easy_font_spacing(float spacing) +{ + stb_easy_font_spacing_val = spacing; +} + +static int stb_easy_font_print(float x, float y, char *text, unsigned char color[4], void *vertex_buffer, int vbuf_size) +{ + char *vbuf = (char *) vertex_buffer; + float start_x = x; + int offset = 0; + + stb_easy_font_color c = { 255,255,255,255 }; // use structure copying to avoid needing depending on memcpy() + if (color) { c.c[0] = color[0]; c.c[1] = color[1]; c.c[2] = color[2]; c.c[3] = color[3]; } + + while (*text && offset < vbuf_size) { + if (*text == '\n') { + y += 12; + x = start_x; + } else { + unsigned char advance = stb_easy_font_charinfo[*text-32].advance; + float y_ch = advance & 16 ? y+1 : y; + int h_seg, v_seg, num_h, num_v; + h_seg = stb_easy_font_charinfo[*text-32 ].h_seg; + v_seg = stb_easy_font_charinfo[*text-32 ].v_seg; + num_h = stb_easy_font_charinfo[*text-32+1].h_seg - h_seg; + num_v = stb_easy_font_charinfo[*text-32+1].v_seg - v_seg; + offset = stb_easy_font_draw_segs(x, y_ch, &stb_easy_font_hseg[h_seg], num_h, 0, c, vbuf, vbuf_size, offset); + offset = stb_easy_font_draw_segs(x, y_ch, &stb_easy_font_vseg[v_seg], num_v, 1, c, vbuf, vbuf_size, offset); + x += advance & 15; + x += stb_easy_font_spacing_val; + } + ++text; + } + return (unsigned) offset/64; +} + +static int stb_easy_font_width(char *text) +{ + float len = 0; + float max_len = 0; + while (*text) { + if (*text == '\n') { + if (len > max_len) max_len = len; + len = 0; + } else { + len += stb_easy_font_charinfo[*text-32].advance & 15; + len += stb_easy_font_spacing_val; + } + ++text; + } + if (len > max_len) max_len = len; + return (int) ceil(max_len); +} + +static int stb_easy_font_height(char *text) +{ + float y = 0; + int nonempty_line=0; + while (*text) { + if (*text == '\n') { + y += 12; + nonempty_line = 0; + } else { + nonempty_line = 1; + } + ++text; + } + return (int) ceil(y + (nonempty_line ? 12 : 0)); +} +#endif + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_herringbone_wang_tile.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_herringbone_wang_tile.h new file mode 100644 index 0000000..5517941 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_herringbone_wang_tile.h @@ -0,0 +1,1221 @@ +/* stbhw - v0.7 - http://nothings.org/gamedev/herringbone + Herringbone Wang Tile Generator - Sean Barrett 2014 - public domain + +== LICENSE ============================== + +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. + +== WHAT IT IS =========================== + + This library is an SDK for Herringbone Wang Tile generation: + + http://nothings.org/gamedev/herringbone + + The core design is that you use this library offline to generate a + "template" of the tiles you'll create. You then edit those tiles, then + load the created tile image file back into this library and use it at + runtime to generate "maps". + + You cannot load arbitrary tile image files with this library; it is + only designed to load image files made from the template it created. + It stores a binary description of the tile sizes & constraints in a + few pixels, and uses those to recover the rules, rather than trying + to parse the tiles themselves. + + You *can* use this library to generate from arbitrary tile sets, but + only by loading the tile set and specifying the constraints explicitly + yourself. + +== COMPILING ============================ + + 1. #define STB_HERRINGBONE_WANG_TILE_IMPLEMENTATION before including this + header file in *one* source file to create the implementation + in that source file. + + 2. optionally #define STB_HBWANG_RAND() to be a random number + generator. if you don't define it, it will use rand(), + and you need to seed srand() yourself. + + 3. optionally #define STB_HBWANG_ASSERT(x), otherwise + it will use assert() + + 4. optionally #define STB_HBWANG_STATIC to force all symbols to be + static instead of public, so they are only accesible + in the source file that creates the implementation + + 5. optionally #define STB_HBWANG_NO_REPITITION_REDUCTION to disable + the code that tries to reduce having the same tile appear + adjacent to itself in wang-corner-tile mode (e.g. imagine + if you were doing something where 90% of things should be + the same grass tile, you need to disable this system) + + 6. optionally define STB_HBWANG_MAX_X and STB_HBWANG_MAX_Y + to be the max dimensions of the generated map in multiples + of the wang tile's short side's length (e.g. if you + have 20x10 wang tiles, so short_side_len=10, and you + have MAX_X is 17, then the largest map you can generate + is 170 pixels wide). The defaults are 100x100. This + is used to define static arrays which affect memory + usage. + +== USING ================================ + + To use the map generator, you need a tileset. You can download + some sample tilesets from http://nothings.org/gamedev/herringbone + + Then see the "sample application" below. + + You can also use this file to generate templates for + tilesets which you then hand-edit to create the data. + + +== MEMORY MANAGEMENT ==================== + + The tileset loader allocates memory with malloc(). The map + generator does no memory allocation, so e.g. you can load + tilesets at startup and never free them and never do any + further allocation. + + +== SAMPLE APPLICATION =================== + +#include +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" // http://nothings.org/stb_image.c + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" // http://nothings.org/stb/stb_image_write.h + +#define STB_HBWANG_IMPLEMENTATION +#include "stb_hbwang.h" + +int main(int argc, char **argv) +{ + unsigned char *data; + int xs,ys, w,h; + stbhw_tileset ts; + + if (argc != 4) { + fprintf(stderr, "Usage: mapgen {tile-file} {xsize} {ysize}\n" + "generates file named 'test_map.png'\n"); + exit(1); + } + data = stbi_load(argv[1], &w, &h, NULL, 3); + xs = atoi(argv[2]); + ys = atoi(argv[3]); + if (data == NULL) { + fprintf(stderr, "Error opening or parsing '%s' as an image file\n", argv[1]); + exit(1); + } + if (xs < 1 || xs > 1000) { + fprintf(stderr, "xsize invalid or out of range\n"); + exit(1); + } + if (ys < 1 || ys > 1000) { + fprintf(stderr, "ysize invalid or out of range\n"); + exit(1); + } + + stbhw_build_tileset_from_image(&ts, data, w*3, w, h); + free(data); + + // allocate a buffer to create the final image to + data = malloc(3 * xs * ys); + + srand(time(NULL)); + stbhw_generate_image(&ts, NULL, data, xs*3, xs, ys); + + stbi_write_png("test_map.png", xs, ys, 3, data, xs*3); + + stbhw_free_tileset(&ts); + free(data); + + return 0; +} + +== VERSION HISTORY =================== + + 0.7 2019-03-04 - fix warnings + 0.6 2014-08-17 - fix broken map-maker + 0.5 2014-07-07 - initial release + +*/ + +////////////////////////////////////////////////////////////////////////////// +// // +// HEADER FILE SECTION // +// // + +#ifndef INCLUDE_STB_HWANG_H +#define INCLUDE_STB_HWANG_H + +#ifdef STB_HBWANG_STATIC +#define STBHW_EXTERN static +#else +#ifdef __cplusplus +#define STBHW_EXTERN extern "C" +#else +#define STBHW_EXTERN extern +#endif +#endif + +typedef struct stbhw_tileset stbhw_tileset; + +// returns description of last error produced by any function (not thread-safe) +STBHW_EXTERN const char *stbhw_get_last_error(void); + +// build a tileset from an image that conforms to a template created by this +// library. (you allocate storage for stbhw_tileset and function fills it out; +// memory for individual tiles are malloc()ed). +// returns non-zero on success, 0 on error +STBHW_EXTERN int stbhw_build_tileset_from_image(stbhw_tileset *ts, + unsigned char *pixels, int stride_in_bytes, int w, int h); + +// free a tileset built by stbhw_build_tileset_from_image +STBHW_EXTERN void stbhw_free_tileset(stbhw_tileset *ts); + +// generate a map that is w * h pixels (3-bytes each) +// returns non-zero on success, 0 on error +// not thread-safe (uses a global data structure to avoid memory management) +// weighting should be NULL, as non-NULL weighting is currently untested +STBHW_EXTERN int stbhw_generate_image(stbhw_tileset *ts, int **weighting, + unsigned char *pixels, int stride_in_bytes, int w, int h); + +////////////////////////////////////// +// +// TILESET DATA STRUCTURE +// +// if you use the image-to-tileset system from this file, you +// don't need to worry about these data structures. but if you +// want to build/load a tileset yourself, you'll need to fill +// these out. + +typedef struct +{ + // the edge or vertex constraints, according to diagram below + signed char a,b,c,d,e,f; + + // The herringbone wang tile data; it is a bitmap which is either + // w=2*short_sidelen,h=short_sidelen, or w=short_sidelen,h=2*short_sidelen. + // it is always RGB, stored row-major, with no padding between rows. + // (allocate stbhw_tile structure to be large enough for the pixel data) + unsigned char pixels[1]; +} stbhw_tile; + +struct stbhw_tileset +{ + int is_corner; + int num_color[6]; // number of colors for each of 6 edge types or 4 corner types + int short_side_len; + stbhw_tile **h_tiles; + stbhw_tile **v_tiles; + int num_h_tiles, max_h_tiles; + int num_v_tiles, max_v_tiles; +}; + +/////////////// TEMPLATE GENERATOR ////////////////////////// + +// when requesting a template, you fill out this data +typedef struct +{ + int is_corner; // using corner colors or edge colors? + int short_side_len; // rectangles is 2n x n, n = short_side_len + int num_color[6]; // see below diagram for meaning of the index to this; + // 6 values if edge (!is_corner), 4 values if is_corner + // legal numbers: 1..8 if edge, 1..4 if is_corner + int num_vary_x; // additional number of variations along x axis in the template + int num_vary_y; // additional number of variations along y axis in the template + int corner_type_color_template[4][4]; + // if corner_type_color_template[s][t] is non-zero, then any + // corner of type s generated as color t will get a little + // corner sample markup in the template image data + +} stbhw_config; + +// computes the size needed for the template image +STBHW_EXTERN void stbhw_get_template_size(stbhw_config *c, int *w, int *h); + +// generates a template image, assuming data is 3*w*h bytes long, RGB format +STBHW_EXTERN int stbhw_make_template(stbhw_config *c, unsigned char *data, int w, int h, int stride_in_bytes); + +#endif//INCLUDE_STB_HWANG_H + + +// TILE CONSTRAINT TYPES +// +// there are 4 "types" of corners and 6 types of edges. +// you can configure the tileset to have different numbers +// of colors for each type of color or edge. +// +// corner types: +// +// 0---*---1---*---2---*---3 +// | | | +// * * * +// | | | +// 1---*---2---*---3 0---*---1---*---2 +// | | | +// * * * +// | | | +// 0---*---1---*---2---*---3 +// +// +// edge types: +// +// *---2---*---3---* *---0---* +// | | | | +// 1 4 5 1 +// | | | | +// *---0---*---2---* * * +// | | +// 4 5 +// | | +// *---3---* +// +// TILE CONSTRAINTS +// +// each corner/edge has a color; this shows the name +// of the variable containing the color +// +// corner constraints: +// +// a---*---d +// | | +// * * +// | | +// a---*---b---*---c b e +// | | | | +// * * * * +// | | | | +// d---*---e---*---f c---*---f +// +// +// edge constraints: +// +// *---a---*---b---* *---a---* +// | | | | +// c d b c +// | | | | +// *---e---*---f---* * * +// | | +// d e +// | | +// *---f---* +// + + +////////////////////////////////////////////////////////////////////////////// +// // +// IMPLEMENTATION SECTION // +// // + +#ifdef STB_HERRINGBONE_WANG_TILE_IMPLEMENTATION + + +#include // memcpy +#include // malloc + +#ifndef STB_HBWANG_RAND +#include +#define STB_HBWANG_RAND() (rand() >> 4) +#endif + +#ifndef STB_HBWANG_ASSERT +#include +#define STB_HBWANG_ASSERT(x) assert(x) +#endif + +// map size +#ifndef STB_HBWANG_MAX_X +#define STB_HBWANG_MAX_X 100 +#endif + +#ifndef STB_HBWANG_MAX_Y +#define STB_HBWANG_MAX_Y 100 +#endif + +// global variables for color assignments +// @MEMORY change these to just store last two/three rows +// and keep them on the stack +static signed char c_color[STB_HBWANG_MAX_Y+6][STB_HBWANG_MAX_X+6]; +static signed char v_color[STB_HBWANG_MAX_Y+6][STB_HBWANG_MAX_X+5]; +static signed char h_color[STB_HBWANG_MAX_Y+5][STB_HBWANG_MAX_X+6]; + +static const char *stbhw_error; +STBHW_EXTERN const char *stbhw_get_last_error(void) +{ + const char *temp = stbhw_error; + stbhw_error = 0; + return temp; +} + + + + +///////////////////////////////////////////////////////////// +// +// SHARED TEMPLATE-DESCRIPTION CODE +// +// Used by both template generator and tileset parser; by +// using the same code, they are locked in sync and we don't +// need to try to do more sophisticated parsing of edge color +// markup or something. + +typedef void stbhw__process_rect(struct stbhw__process *p, int xpos, int ypos, + int a, int b, int c, int d, int e, int f); + +typedef struct stbhw__process +{ + stbhw_tileset *ts; + stbhw_config *c; + stbhw__process_rect *process_h_rect; + stbhw__process_rect *process_v_rect; + unsigned char *data; + int stride,w,h; +} stbhw__process; + +static void stbhw__process_h_row(stbhw__process *p, + int xpos, int ypos, + int a0, int a1, + int b0, int b1, + int c0, int c1, + int d0, int d1, + int e0, int e1, + int f0, int f1, + int variants) +{ + int a,b,c,d,e,f,v; + + for (v=0; v < variants; ++v) + for (f=f0; f <= f1; ++f) + for (e=e0; e <= e1; ++e) + for (d=d0; d <= d1; ++d) + for (c=c0; c <= c1; ++c) + for (b=b0; b <= b1; ++b) + for (a=a0; a <= a1; ++a) { + p->process_h_rect(p, xpos, ypos, a,b,c,d,e,f); + xpos += 2*p->c->short_side_len + 3; + } +} + +static void stbhw__process_v_row(stbhw__process *p, + int xpos, int ypos, + int a0, int a1, + int b0, int b1, + int c0, int c1, + int d0, int d1, + int e0, int e1, + int f0, int f1, + int variants) +{ + int a,b,c,d,e,f,v; + + for (v=0; v < variants; ++v) + for (f=f0; f <= f1; ++f) + for (e=e0; e <= e1; ++e) + for (d=d0; d <= d1; ++d) + for (c=c0; c <= c1; ++c) + for (b=b0; b <= b1; ++b) + for (a=a0; a <= a1; ++a) { + p->process_v_rect(p, xpos, ypos, a,b,c,d,e,f); + xpos += p->c->short_side_len+3; + } +} + +static void stbhw__get_template_info(stbhw_config *c, int *w, int *h, int *h_count, int *v_count) +{ + int size_x,size_y; + int horz_count,vert_count; + + if (c->is_corner) { + int horz_w = c->num_color[1] * c->num_color[2] * c->num_color[3] * c->num_vary_x; + int horz_h = c->num_color[0] * c->num_color[1] * c->num_color[2] * c->num_vary_y; + + int vert_w = c->num_color[0] * c->num_color[3] * c->num_color[2] * c->num_vary_y; + int vert_h = c->num_color[1] * c->num_color[0] * c->num_color[3] * c->num_vary_x; + + int horz_x = horz_w * (2*c->short_side_len + 3); + int horz_y = horz_h * ( c->short_side_len + 3); + + int vert_x = vert_w * ( c->short_side_len + 3); + int vert_y = vert_h * (2*c->short_side_len + 3); + + horz_count = horz_w * horz_h; + vert_count = vert_w * vert_h; + + size_x = horz_x > vert_x ? horz_x : vert_x; + size_y = 2 + horz_y + 2 + vert_y; + } else { + int horz_w = c->num_color[0] * c->num_color[1] * c->num_color[2] * c->num_vary_x; + int horz_h = c->num_color[3] * c->num_color[4] * c->num_color[2] * c->num_vary_y; + + int vert_w = c->num_color[0] * c->num_color[5] * c->num_color[1] * c->num_vary_y; + int vert_h = c->num_color[3] * c->num_color[4] * c->num_color[5] * c->num_vary_x; + + int horz_x = horz_w * (2*c->short_side_len + 3); + int horz_y = horz_h * ( c->short_side_len + 3); + + int vert_x = vert_w * ( c->short_side_len + 3); + int vert_y = vert_h * (2*c->short_side_len + 3); + + horz_count = horz_w * horz_h; + vert_count = vert_w * vert_h; + + size_x = horz_x > vert_x ? horz_x : vert_x; + size_y = 2 + horz_y + 2 + vert_y; + } + if (w) *w = size_x; + if (h) *h = size_y; + if (h_count) *h_count = horz_count; + if (v_count) *v_count = vert_count; +} + +STBHW_EXTERN void stbhw_get_template_size(stbhw_config *c, int *w, int *h) +{ + stbhw__get_template_info(c, w, h, NULL, NULL); +} + +static int stbhw__process_template(stbhw__process *p) +{ + int i,j,k,q, ypos; + int size_x, size_y; + stbhw_config *c = p->c; + + stbhw__get_template_info(c, &size_x, &size_y, NULL, NULL); + + if (p->w < size_x || p->h < size_y) { + stbhw_error = "image too small for configuration"; + return 0; + } + + if (c->is_corner) { + ypos = 2; + for (k=0; k < c->num_color[2]; ++k) { + for (j=0; j < c->num_color[1]; ++j) { + for (i=0; i < c->num_color[0]; ++i) { + for (q=0; q < c->num_vary_y; ++q) { + stbhw__process_h_row(p, 0,ypos, + 0,c->num_color[1]-1, 0,c->num_color[2]-1, 0,c->num_color[3]-1, + i,i, j,j, k,k, + c->num_vary_x); + ypos += c->short_side_len + 3; + } + } + } + } + ypos += 2; + for (k=0; k < c->num_color[3]; ++k) { + for (j=0; j < c->num_color[0]; ++j) { + for (i=0; i < c->num_color[1]; ++i) { + for (q=0; q < c->num_vary_x; ++q) { + stbhw__process_v_row(p, 0,ypos, + 0,c->num_color[0]-1, 0,c->num_color[3]-1, 0,c->num_color[2]-1, + i,i, j,j, k,k, + c->num_vary_y); + ypos += (c->short_side_len*2) + 3; + } + } + } + } + assert(ypos == size_y); + } else { + ypos = 2; + for (k=0; k < c->num_color[3]; ++k) { + for (j=0; j < c->num_color[4]; ++j) { + for (i=0; i < c->num_color[2]; ++i) { + for (q=0; q < c->num_vary_y; ++q) { + stbhw__process_h_row(p, 0,ypos, + 0,c->num_color[2]-1, k,k, + 0,c->num_color[1]-1, j,j, + 0,c->num_color[0]-1, i,i, + c->num_vary_x); + ypos += c->short_side_len + 3; + } + } + } + } + ypos += 2; + for (k=0; k < c->num_color[3]; ++k) { + for (j=0; j < c->num_color[4]; ++j) { + for (i=0; i < c->num_color[5]; ++i) { + for (q=0; q < c->num_vary_x; ++q) { + stbhw__process_v_row(p, 0,ypos, + 0,c->num_color[0]-1, i,i, + 0,c->num_color[1]-1, j,j, + 0,c->num_color[5]-1, k,k, + c->num_vary_y); + ypos += (c->short_side_len*2) + 3; + } + } + } + } + assert(ypos == size_y); + } + return 1; +} + + +///////////////////////////////////////////////////////////// +// +// MAP GENERATOR +// + +static void stbhw__draw_pixel(unsigned char *output, int stride, int x, int y, unsigned char c[3]) +{ + memcpy(output + y*stride + x*3, c, 3); +} + +static void stbhw__draw_h_tile(unsigned char *output, int stride, int xmax, int ymax, int x, int y, stbhw_tile *h, int sz) +{ + int i,j; + for (j=0; j < sz; ++j) + if (y+j >= 0 && y+j < ymax) + for (i=0; i < sz*2; ++i) + if (x+i >= 0 && x+i < xmax) + stbhw__draw_pixel(output,stride, x+i,y+j, &h->pixels[(j*sz*2 + i)*3]); +} + +static void stbhw__draw_v_tile(unsigned char *output, int stride, int xmax, int ymax, int x, int y, stbhw_tile *h, int sz) +{ + int i,j; + for (j=0; j < sz*2; ++j) + if (y+j >= 0 && y+j < ymax) + for (i=0; i < sz; ++i) + if (x+i >= 0 && x+i < xmax) + stbhw__draw_pixel(output,stride, x+i,y+j, &h->pixels[(j*sz + i)*3]); +} + + +// randomly choose a tile that fits constraints for a given spot, and update the constraints +static stbhw_tile * stbhw__choose_tile(stbhw_tile **list, int numlist, + signed char *a, signed char *b, signed char *c, + signed char *d, signed char *e, signed char *f, + int **weighting) +{ + int i,n,m = 1<<30,pass; + for (pass=0; pass < 2; ++pass) { + n=0; + // pass #1: + // count number of variants that match this partial set of constraints + // pass #2: + // stop on randomly selected match + for (i=0; i < numlist; ++i) { + stbhw_tile *h = list[i]; + if ((*a < 0 || *a == h->a) && + (*b < 0 || *b == h->b) && + (*c < 0 || *c == h->c) && + (*d < 0 || *d == h->d) && + (*e < 0 || *e == h->e) && + (*f < 0 || *f == h->f)) { + if (weighting) + n += weighting[0][i]; + else + n += 1; + if (n > m) { + // use list[i] + // update constraints to reflect what we placed + *a = h->a; + *b = h->b; + *c = h->c; + *d = h->d; + *e = h->e; + *f = h->f; + return h; + } + } + } + if (n == 0) { + stbhw_error = "couldn't find tile matching constraints"; + return NULL; + } + m = STB_HBWANG_RAND() % n; + } + STB_HBWANG_ASSERT(0); + return NULL; +} + +static int stbhw__match(int x, int y) +{ + return c_color[y][x] == c_color[y+1][x+1]; +} + +static int stbhw__weighted(int num_options, int *weights) +{ + int k, total, choice; + total = 0; + for (k=0; k < num_options; ++k) + total += weights[k]; + choice = STB_HBWANG_RAND() % total; + total = 0; + for (k=0; k < num_options; ++k) { + total += weights[k]; + if (choice < total) + break; + } + STB_HBWANG_ASSERT(k < num_options); + return k; +} + +static int stbhw__change_color(int old_color, int num_options, int *weights) +{ + if (weights) { + int k, total, choice; + total = 0; + for (k=0; k < num_options; ++k) + if (k != old_color) + total += weights[k]; + choice = STB_HBWANG_RAND() % total; + total = 0; + for (k=0; k < num_options; ++k) { + if (k != old_color) { + total += weights[k]; + if (choice < total) + break; + } + } + STB_HBWANG_ASSERT(k < num_options); + return k; + } else { + int offset = 1+STB_HBWANG_RAND() % (num_options-1); + return (old_color+offset) % num_options; + } +} + + + +// generate a map that is w * h pixels (3-bytes each) +// returns 1 on success, 0 on error +STBHW_EXTERN int stbhw_generate_image(stbhw_tileset *ts, int **weighting, unsigned char *output, int stride, int w, int h) +{ + int sidelen = ts->short_side_len; + int xmax = (w / sidelen) + 6; + int ymax = (h / sidelen) + 6; + if (xmax > STB_HBWANG_MAX_X+6 || ymax > STB_HBWANG_MAX_Y+6) { + stbhw_error = "increase STB_HBWANG_MAX_X/Y"; + return 0; + } + + if (ts->is_corner) { + int i,j, ypos; + int *cc = ts->num_color; + + for (j=0; j < ymax; ++j) { + for (i=0; i < xmax; ++i) { + int p = (i-j+1)&3; // corner type + if (weighting==NULL || weighting[p]==0 || cc[p] == 1) + c_color[j][i] = STB_HBWANG_RAND() % cc[p]; + else + c_color[j][i] = stbhw__weighted(cc[p], weighting[p]); + } + } + #ifndef STB_HBWANG_NO_REPITITION_REDUCTION + // now go back through and make sure we don't have adjancent 3x2 vertices that are identical, + // to avoid really obvious repetition (which happens easily with extreme weights) + for (j=0; j < ymax-3; ++j) { + for (i=0; i < xmax-3; ++i) { + //int p = (i-j+1) & 3; // corner type // unused, not sure what the intent was so commenting it out + STB_HBWANG_ASSERT(i+3 < STB_HBWANG_MAX_X+6); + STB_HBWANG_ASSERT(j+3 < STB_HBWANG_MAX_Y+6); + if (stbhw__match(i,j) && stbhw__match(i,j+1) && stbhw__match(i,j+2) + && stbhw__match(i+1,j) && stbhw__match(i+1,j+1) && stbhw__match(i+1,j+2)) { + int p = ((i+1)-(j+1)+1) & 3; + if (cc[p] > 1) + c_color[j+1][i+1] = stbhw__change_color(c_color[j+1][i+1], cc[p], weighting ? weighting[p] : NULL); + } + if (stbhw__match(i,j) && stbhw__match(i+1,j) && stbhw__match(i+2,j) + && stbhw__match(i,j+1) && stbhw__match(i+1,j+1) && stbhw__match(i+2,j+1)) { + int p = ((i+2)-(j+1)+1) & 3; + if (cc[p] > 1) + c_color[j+1][i+2] = stbhw__change_color(c_color[j+1][i+2], cc[p], weighting ? weighting[p] : NULL); + } + } + } + #endif + + ypos = -1 * sidelen; + for (j = -1; ypos < h; ++j) { + // a general herringbone row consists of: + // horizontal left block, the bottom of a previous vertical, the top of a new vertical + int phase = (j & 3); + // displace horizontally according to pattern + if (phase == 0) { + i = 0; + } else { + i = phase-4; + } + for (;; i += 4) { + int xpos = i * sidelen; + if (xpos >= w) + break; + // horizontal left-block + if (xpos + sidelen*2 >= 0 && ypos >= 0) { + stbhw_tile *t = stbhw__choose_tile( + ts->h_tiles, ts->num_h_tiles, + &c_color[j+2][i+2], &c_color[j+2][i+3], &c_color[j+2][i+4], + &c_color[j+3][i+2], &c_color[j+3][i+3], &c_color[j+3][i+4], + weighting + ); + if (t == NULL) + return 0; + stbhw__draw_h_tile(output,stride,w,h, xpos, ypos, t, sidelen); + } + xpos += sidelen * 2; + // now we're at the end of a previous vertical one + xpos += sidelen; + // now we're at the start of a new vertical one + if (xpos < w) { + stbhw_tile *t = stbhw__choose_tile( + ts->v_tiles, ts->num_v_tiles, + &c_color[j+2][i+5], &c_color[j+3][i+5], &c_color[j+4][i+5], + &c_color[j+2][i+6], &c_color[j+3][i+6], &c_color[j+4][i+6], + weighting + ); + if (t == NULL) + return 0; + stbhw__draw_v_tile(output,stride,w,h, xpos, ypos, t, sidelen); + } + } + ypos += sidelen; + } + } else { + // @TODO edge-color repetition reduction + int i,j, ypos; + memset(v_color, -1, sizeof(v_color)); + memset(h_color, -1, sizeof(h_color)); + + ypos = -1 * sidelen; + for (j = -1; ypos= w) + break; + // horizontal left-block + if (xpos + sidelen*2 >= 0 && ypos >= 0) { + stbhw_tile *t = stbhw__choose_tile( + ts->h_tiles, ts->num_h_tiles, + &h_color[j+2][i+2], &h_color[j+2][i+3], + &v_color[j+2][i+2], &v_color[j+2][i+4], + &h_color[j+3][i+2], &h_color[j+3][i+3], + weighting + ); + if (t == NULL) return 0; + stbhw__draw_h_tile(output,stride,w,h, xpos, ypos, t, sidelen); + } + xpos += sidelen * 2; + // now we're at the end of a previous vertical one + xpos += sidelen; + // now we're at the start of a new vertical one + if (xpos < w) { + stbhw_tile *t = stbhw__choose_tile( + ts->v_tiles, ts->num_v_tiles, + &h_color[j+2][i+5], + &v_color[j+2][i+5], &v_color[j+2][i+6], + &v_color[j+3][i+5], &v_color[j+3][i+6], + &h_color[j+4][i+5], + weighting + ); + if (t == NULL) return 0; + stbhw__draw_v_tile(output,stride,w,h, xpos, ypos, t, sidelen); + } + } + ypos += sidelen; + } + } + return 1; +} + +static void stbhw__parse_h_rect(stbhw__process *p, int xpos, int ypos, + int a, int b, int c, int d, int e, int f) +{ + int len = p->c->short_side_len; + stbhw_tile *h = (stbhw_tile *) malloc(sizeof(*h)-1 + 3 * (len*2) * len); + int i,j; + ++xpos; + ++ypos; + h->a = a, h->b = b, h->c = c, h->d = d, h->e = e, h->f = f; + for (j=0; j < len; ++j) + for (i=0; i < len*2; ++i) + memcpy(h->pixels + j*(3*len*2) + i*3, p->data+(ypos+j)*p->stride+(xpos+i)*3, 3); + STB_HBWANG_ASSERT(p->ts->num_h_tiles < p->ts->max_h_tiles); + p->ts->h_tiles[p->ts->num_h_tiles++] = h; +} + +static void stbhw__parse_v_rect(stbhw__process *p, int xpos, int ypos, + int a, int b, int c, int d, int e, int f) +{ + int len = p->c->short_side_len; + stbhw_tile *h = (stbhw_tile *) malloc(sizeof(*h)-1 + 3 * (len*2) * len); + int i,j; + ++xpos; + ++ypos; + h->a = a, h->b = b, h->c = c, h->d = d, h->e = e, h->f = f; + for (j=0; j < len*2; ++j) + for (i=0; i < len; ++i) + memcpy(h->pixels + j*(3*len) + i*3, p->data+(ypos+j)*p->stride+(xpos+i)*3, 3); + STB_HBWANG_ASSERT(p->ts->num_v_tiles < p->ts->max_v_tiles); + p->ts->v_tiles[p->ts->num_v_tiles++] = h; +} + +STBHW_EXTERN int stbhw_build_tileset_from_image(stbhw_tileset *ts, unsigned char *data, int stride, int w, int h) +{ + int i, h_count, v_count; + unsigned char header[9]; + stbhw_config c = { 0 }; + stbhw__process p = { 0 }; + + // extract binary header + + // remove encoding that makes it more visually obvious it encodes actual data + for (i=0; i < 9; ++i) + header[i] = data[w*3 - 1 - i] ^ (i*55); + + // extract header info + if (header[7] == 0xc0) { + // corner-type + c.is_corner = 1; + for (i=0; i < 4; ++i) + c.num_color[i] = header[i]; + c.num_vary_x = header[4]; + c.num_vary_y = header[5]; + c.short_side_len = header[6]; + } else { + c.is_corner = 0; + // edge-type + for (i=0; i < 6; ++i) + c.num_color[i] = header[i]; + c.num_vary_x = header[6]; + c.num_vary_y = header[7]; + c.short_side_len = header[8]; + } + + if (c.num_vary_x < 0 || c.num_vary_x > 64 || c.num_vary_y < 0 || c.num_vary_y > 64) + return 0; + if (c.short_side_len == 0) + return 0; + if (c.num_color[0] > 32 || c.num_color[1] > 32 || c.num_color[2] > 32 || c.num_color[3] > 32) + return 0; + + stbhw__get_template_info(&c, NULL, NULL, &h_count, &v_count); + + ts->is_corner = c.is_corner; + ts->short_side_len = c.short_side_len; + memcpy(ts->num_color, c.num_color, sizeof(ts->num_color)); + + ts->max_h_tiles = h_count; + ts->max_v_tiles = v_count; + + ts->num_h_tiles = ts->num_v_tiles = 0; + + ts->h_tiles = (stbhw_tile **) malloc(sizeof(*ts->h_tiles) * h_count); + ts->v_tiles = (stbhw_tile **) malloc(sizeof(*ts->v_tiles) * v_count); + + p.ts = ts; + p.data = data; + p.stride = stride; + p.process_h_rect = stbhw__parse_h_rect; + p.process_v_rect = stbhw__parse_v_rect; + p.w = w; + p.h = h; + p.c = &c; + + // load all the tiles out of the image + return stbhw__process_template(&p); +} + +STBHW_EXTERN void stbhw_free_tileset(stbhw_tileset *ts) +{ + int i; + for (i=0; i < ts->num_h_tiles; ++i) + free(ts->h_tiles[i]); + for (i=0; i < ts->num_v_tiles; ++i) + free(ts->v_tiles[i]); + free(ts->h_tiles); + free(ts->v_tiles); + ts->h_tiles = NULL; + ts->v_tiles = NULL; + ts->num_h_tiles = ts->max_h_tiles = 0; + ts->num_v_tiles = ts->max_v_tiles = 0; +} + +////////////////////////////////////////////////////////////////////////////// +// +// GENERATOR +// +// + + +// shared code + +static void stbhw__set_pixel(unsigned char *data, int stride, int xpos, int ypos, unsigned char color[3]) +{ + memcpy(data + ypos*stride + xpos*3, color, 3); +} + +static void stbhw__stbhw__set_pixel_whiten(unsigned char *data, int stride, int xpos, int ypos, unsigned char color[3]) +{ + unsigned char c2[3]; + int i; + for (i=0; i < 3; ++i) + c2[i] = (color[i]*2 + 255)/3; + memcpy(data + ypos*stride + xpos*3, c2, 3); +} + + +static unsigned char stbhw__black[3] = { 0,0,0 }; + +// each edge set gets its own unique color variants +// used http://phrogz.net/css/distinct-colors.html to generate this set, +// but it's not very good and needs to be revised + +static unsigned char stbhw__color[7][8][3] = +{ + { {255,51,51} , {143,143,29}, {0,199,199}, {159,119,199}, {0,149,199} , {143, 0,143}, {255,128,0}, {64,255,0}, }, + { {235,255,30 }, {255,0,255}, {199,139,119}, {29,143, 57}, {143,0,71} , { 0,143,143}, {0,99,199}, {143,71,0}, }, + { {0,149,199} , {143, 0,143}, {255,128,0}, {64,255,0}, {255,191,0} , {51,255,153}, {0,0,143}, {199,119,159},}, + { {143,0,71} , { 0,143,143}, {0,99,199}, {143,71,0}, {255,190,153}, { 0,255,255}, {128,0,255}, {255,51,102},}, + { {255,191,0} , {51,255,153}, {0,0,143}, {199,119,159}, {255,51,51} , {143,143,29}, {0,199,199}, {159,119,199},}, + { {255,190,153}, { 0,255,255}, {128,0,255}, {255,51,102}, {235,255,30 }, {255,0,255}, {199,139,119}, {29,143, 57}, }, + + { {40,40,40 }, { 90,90,90 }, { 150,150,150 }, { 200,200,200 }, + { 255,90,90 }, { 160,160,80}, { 50,150,150 }, { 200,50,200 } }, +}; + +static void stbhw__draw_hline(unsigned char *data, int stride, int xpos, int ypos, int color, int len, int slot) +{ + int i; + int j = len * 6 / 16; + int k = len * 10 / 16; + for (i=0; i < len; ++i) + stbhw__set_pixel(data, stride, xpos+i, ypos, stbhw__black); + if (k-j < 2) { + j = len/2 - 1; + k = j+2; + if (len & 1) + ++k; + } + for (i=j; i < k; ++i) + stbhw__stbhw__set_pixel_whiten(data, stride, xpos+i, ypos, stbhw__color[slot][color]); +} + +static void stbhw__draw_vline(unsigned char *data, int stride, int xpos, int ypos, int color, int len, int slot) +{ + int i; + int j = len * 6 / 16; + int k = len * 10 / 16; + for (i=0; i < len; ++i) + stbhw__set_pixel(data, stride, xpos, ypos+i, stbhw__black); + if (k-j < 2) { + j = len/2 - 1; + k = j+2; + if (len & 1) + ++k; + } + for (i=j; i < k; ++i) + stbhw__stbhw__set_pixel_whiten(data, stride, xpos, ypos+i, stbhw__color[slot][color]); +} + +// 0--*--1--*--2--*--3 +// | | | +// * * * +// | | | +// 1--*--2--*--3 0--*--1--*--2 +// | | | +// * * * +// | | | +// 0--*--1--*--2--*--3 +// +// variables while enumerating (no correspondence between corners +// of the types is implied by these variables) +// +// a-----b-----c a-----d +// | | | | +// | | | | +// | | | | +// d-----e-----f b e +// | | +// | | +// | | +// c-----f +// + +unsigned char stbhw__corner_colors[4][4][3] = +{ + { { 255,0,0 }, { 200,200,200 }, { 100,100,200 }, { 255,200,150 }, }, + { { 0,0,255 }, { 255,255,0 }, { 100,200,100 }, { 150,255,200 }, }, + { { 255,0,255 }, { 80,80,80 }, { 200,100,100 }, { 200,150,255 }, }, + { { 0,255,255 }, { 0,255,0 }, { 200,120,200 }, { 255,200,200 }, }, +}; + +int stbhw__corner_colors_to_edge_color[4][4] = +{ + // 0 1 2 3 + { 0, 1, 4, 9, }, // 0 + { 2, 3, 5, 10, }, // 1 + { 6, 7, 8, 11, }, // 2 + { 12, 13, 14, 15, }, // 3 +}; + +#define stbhw__c2e stbhw__corner_colors_to_edge_color + +static void stbhw__draw_clipped_corner(unsigned char *data, int stride, int xpos, int ypos, int w, int h, int x, int y) +{ + static unsigned char template_color[3] = { 167,204,204 }; + int i,j; + for (j = -2; j <= 1; ++j) { + for (i = -2; i <= 1; ++i) { + if ((i == -2 || i == 1) && (j == -2 || j == 1)) + continue; + else { + if (x+i < 1 || x+i > w) continue; + if (y+j < 1 || y+j > h) continue; + stbhw__set_pixel(data, stride, xpos+x+i, ypos+y+j, template_color); + + } + } + } +} + +static void stbhw__edge_process_h_rect(stbhw__process *p, int xpos, int ypos, + int a, int b, int c, int d, int e, int f) +{ + int len = p->c->short_side_len; + stbhw__draw_hline(p->data, p->stride, xpos+1 , ypos , a, len, 2); + stbhw__draw_hline(p->data, p->stride, xpos+ len+1 , ypos , b, len, 3); + stbhw__draw_vline(p->data, p->stride, xpos , ypos+1 , c, len, 1); + stbhw__draw_vline(p->data, p->stride, xpos+2*len+1 , ypos+1 , d, len, 4); + stbhw__draw_hline(p->data, p->stride, xpos+1 , ypos + len+1, e, len, 0); + stbhw__draw_hline(p->data, p->stride, xpos + len+1 , ypos + len+1, f, len, 2); +} + +static void stbhw__edge_process_v_rect(stbhw__process *p, int xpos, int ypos, + int a, int b, int c, int d, int e, int f) +{ + int len = p->c->short_side_len; + stbhw__draw_hline(p->data, p->stride, xpos+1 , ypos , a, len, 0); + stbhw__draw_vline(p->data, p->stride, xpos , ypos+1 , b, len, 5); + stbhw__draw_vline(p->data, p->stride, xpos + len+1, ypos+1 , c, len, 1); + stbhw__draw_vline(p->data, p->stride, xpos , ypos + len+1, d, len, 4); + stbhw__draw_vline(p->data, p->stride, xpos + len+1, ypos + len+1, e, len, 5); + stbhw__draw_hline(p->data, p->stride, xpos+1 , ypos + 2*len+1, f, len, 3); +} + +static void stbhw__corner_process_h_rect(stbhw__process *p, int xpos, int ypos, + int a, int b, int c, int d, int e, int f) +{ + int len = p->c->short_side_len; + + stbhw__draw_hline(p->data, p->stride, xpos+1 , ypos , stbhw__c2e[a][b], len, 2); + stbhw__draw_hline(p->data, p->stride, xpos+ len+1 , ypos , stbhw__c2e[b][c], len, 3); + stbhw__draw_vline(p->data, p->stride, xpos , ypos+1 , stbhw__c2e[a][d], len, 1); + stbhw__draw_vline(p->data, p->stride, xpos+2*len+1 , ypos+1 , stbhw__c2e[c][f], len, 4); + stbhw__draw_hline(p->data, p->stride, xpos+1 , ypos + len+1, stbhw__c2e[d][e], len, 0); + stbhw__draw_hline(p->data, p->stride, xpos + len+1 , ypos + len+1, stbhw__c2e[e][f], len, 2); + + if (p->c->corner_type_color_template[1][a]) stbhw__draw_clipped_corner(p->data,p->stride, xpos,ypos, len*2,len, 1,1); + if (p->c->corner_type_color_template[2][b]) stbhw__draw_clipped_corner(p->data,p->stride, xpos,ypos, len*2,len, len+1,1); + if (p->c->corner_type_color_template[3][c]) stbhw__draw_clipped_corner(p->data,p->stride, xpos,ypos, len*2,len, len*2+1,1); + + if (p->c->corner_type_color_template[0][d]) stbhw__draw_clipped_corner(p->data,p->stride, xpos,ypos, len*2,len, 1,len+1); + if (p->c->corner_type_color_template[1][e]) stbhw__draw_clipped_corner(p->data,p->stride, xpos,ypos, len*2,len, len+1,len+1); + if (p->c->corner_type_color_template[2][f]) stbhw__draw_clipped_corner(p->data,p->stride, xpos,ypos, len*2,len, len*2+1,len+1); + + stbhw__set_pixel(p->data, p->stride, xpos , ypos, stbhw__corner_colors[1][a]); + stbhw__set_pixel(p->data, p->stride, xpos+len , ypos, stbhw__corner_colors[2][b]); + stbhw__set_pixel(p->data, p->stride, xpos+2*len+1, ypos, stbhw__corner_colors[3][c]); + stbhw__set_pixel(p->data, p->stride, xpos , ypos+len+1, stbhw__corner_colors[0][d]); + stbhw__set_pixel(p->data, p->stride, xpos+len , ypos+len+1, stbhw__corner_colors[1][e]); + stbhw__set_pixel(p->data, p->stride, xpos+2*len+1, ypos+len+1, stbhw__corner_colors[2][f]); +} + +static void stbhw__corner_process_v_rect(stbhw__process *p, int xpos, int ypos, + int a, int b, int c, int d, int e, int f) +{ + int len = p->c->short_side_len; + + stbhw__draw_hline(p->data, p->stride, xpos+1 , ypos , stbhw__c2e[a][d], len, 0); + stbhw__draw_vline(p->data, p->stride, xpos , ypos+1 , stbhw__c2e[a][b], len, 5); + stbhw__draw_vline(p->data, p->stride, xpos + len+1, ypos+1 , stbhw__c2e[d][e], len, 1); + stbhw__draw_vline(p->data, p->stride, xpos , ypos + len+1, stbhw__c2e[b][c], len, 4); + stbhw__draw_vline(p->data, p->stride, xpos + len+1, ypos + len+1, stbhw__c2e[e][f], len, 5); + stbhw__draw_hline(p->data, p->stride, xpos+1 , ypos + 2*len+1, stbhw__c2e[c][f], len, 3); + + if (p->c->corner_type_color_template[0][a]) stbhw__draw_clipped_corner(p->data,p->stride, xpos,ypos, len,len*2, 1,1); + if (p->c->corner_type_color_template[3][b]) stbhw__draw_clipped_corner(p->data,p->stride, xpos,ypos, len,len*2, 1,len+1); + if (p->c->corner_type_color_template[2][c]) stbhw__draw_clipped_corner(p->data,p->stride, xpos,ypos, len,len*2, 1,len*2+1); + + if (p->c->corner_type_color_template[1][d]) stbhw__draw_clipped_corner(p->data,p->stride, xpos,ypos, len,len*2, len+1,1); + if (p->c->corner_type_color_template[0][e]) stbhw__draw_clipped_corner(p->data,p->stride, xpos,ypos, len,len*2, len+1,len+1); + if (p->c->corner_type_color_template[3][f]) stbhw__draw_clipped_corner(p->data,p->stride, xpos,ypos, len,len*2, len+1,len*2+1); + + stbhw__set_pixel(p->data, p->stride, xpos , ypos , stbhw__corner_colors[0][a]); + stbhw__set_pixel(p->data, p->stride, xpos , ypos+len , stbhw__corner_colors[3][b]); + stbhw__set_pixel(p->data, p->stride, xpos , ypos+2*len+1, stbhw__corner_colors[2][c]); + stbhw__set_pixel(p->data, p->stride, xpos+len+1, ypos , stbhw__corner_colors[1][d]); + stbhw__set_pixel(p->data, p->stride, xpos+len+1, ypos+len , stbhw__corner_colors[0][e]); + stbhw__set_pixel(p->data, p->stride, xpos+len+1, ypos+2*len+1, stbhw__corner_colors[3][f]); +} + +// generates a template image, assuming data is 3*w*h bytes long, RGB format +STBHW_EXTERN int stbhw_make_template(stbhw_config *c, unsigned char *data, int w, int h, int stride_in_bytes) +{ + stbhw__process p; + int i; + + p.data = data; + p.w = w; + p.h = h; + p.stride = stride_in_bytes; + p.ts = 0; + p.c = c; + + if (c->is_corner) { + p.process_h_rect = stbhw__corner_process_h_rect; + p.process_v_rect = stbhw__corner_process_v_rect; + } else { + p.process_h_rect = stbhw__edge_process_h_rect; + p.process_v_rect = stbhw__edge_process_v_rect; + } + + for (i=0; i < p.h; ++i) + memset(p.data + i*p.stride, 255, 3*p.w); + + if (!stbhw__process_template(&p)) + return 0; + + if (c->is_corner) { + // write out binary information in first line of image + for (i=0; i < 4; ++i) + data[w*3-1-i] = c->num_color[i]; + data[w*3-1-i] = c->num_vary_x; + data[w*3-2-i] = c->num_vary_y; + data[w*3-3-i] = c->short_side_len; + data[w*3-4-i] = 0xc0; + } else { + for (i=0; i < 6; ++i) + data[w*3-1-i] = c->num_color[i]; + data[w*3-1-i] = c->num_vary_x; + data[w*3-2-i] = c->num_vary_y; + data[w*3-3-i] = c->short_side_len; + } + + // make it more obvious it encodes actual data + for (i=0; i < 9; ++i) + p.data[p.w*3 - 1 - i] ^= i*55; + + return 1; +} +#endif // STB_HBWANG_IMPLEMENTATION diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_hexwave.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_hexwave.h new file mode 100644 index 0000000..480ab1b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_hexwave.h @@ -0,0 +1,680 @@ +// stb_hexwave - v0.5 - public domain, initial release 2021-04-01 +// +// A flexible anti-aliased (bandlimited) digital audio oscillator. +// +// This library generates waveforms of a variety of shapes made of +// line segments. It does not do envelopes, LFO effects, etc.; it +// merely tries to solve the problem of generating an artifact-free +// morphable digital waveform with a variety of spectra, and leaves +// it to the user to rescale the waveform and mix multiple voices, etc. +// +// Compiling: +// +// In one C/C++ file that #includes this file, do +// +// #define STB_HEXWAVE_IMPLEMENTATION +// #include "stb_hexwave.h" +// +// Optionally, #define STB_HEXWAVE_STATIC before including +// the header to cause the definitions to be private to the +// implementation file (i.e. to be "static" instead of "extern"). +// +// Notes: +// +// Optionally performs memory allocation during initialization, +// never allocates otherwise. +// +// License: +// +// See end of file for license information. +// +// Usage: +// +// Initialization: +// +// hexwave_init(32,16,NULL); // read "header section" for alternatives +// +// Create oscillator: +// +// HexWave *osc = malloc(sizeof(*osc)); // or "new HexWave", or declare globally or on stack +// hexwave_create(osc, reflect_flag, peak_time, half_height, zero_wait); +// see "Waveform shapes" below for the meaning of these parameters +// +// Generate audio: +// +// hexwave_generate_samples(output, number_of_samples, osc, oscillator_freq) +// where: +// output is a buffer where the library will store floating point audio samples +// number_of_samples is the number of audio samples to generate +// osc is a pointer to a Hexwave +// oscillator_freq is the frequency of the oscillator divided by the sample rate +// +// The output samples will continue from where the samples generated by the +// previous hexwave_generate_samples() on this oscillator ended. +// +// Change oscillator waveform: +// +// hexwave_change(osc, reflect_flag, peak_time, half_height, zero_wait); +// can call in between calls to hexwave_generate_samples +// +// Waveform shapes: +// +// All waveforms generated by hexwave are constructed from six line segments +// characterized by 3 parameters. +// +// See demonstration: https://www.youtube.com/watch?v=hsUCrAsDN-M +// +// reflect=0 reflect=1 +// +// 0-----P---1 0-----P---1 peak_time = P +// . 1 . 1 +// /\_ : /\_ : +// / \_ : / \_ : +// / \.H / \.H half_height = H +// / | : / | : +// _____/ |_:___ _____/ | : _____ +// . : \ | . | : / +// . : \ | . | : / +// . : \ _/ . \_: / +// . : \ _/ . :_ / +// . -1 \/ . -1 \/ +// 0 - Z - - - - 1 0 - Z - - - - 1 zero_wait = Z +// +// Classic waveforms: +// peak half zero +// reflect time height wait +// Sawtooth 1 0 0 0 +// Square 1 0 1 0 +// Triangle 1 0.5 0 0 +// +// Some waveforms can be produced in multiple ways, which is useful when morphing +// into other waveforms, and there are a few more notable shapes: +// +// peak half zero +// reflect time height wait +// Sawtooth 1 1 any 0 +// Sawtooth (8va) 1 0 -1 0 +// Triangle 1 0.5 0 0 +// Square 1 0 1 0 +// Square 0 0 1 0 +// Triangle 0 0.5 0 0 +// Triangle 0 0 -1 0 +// AlternatingSaw 0 0 0 0 +// AlternatingSaw 0 1 any 0 +// Stairs 0 0 1 0.5 +// +// The "Sawtooth (8va)" waveform is identical to a sawtooth wave with 2x the +// frequency, but when morphed with other values, it becomes an overtone of +// the base frequency. +// +// Morphing waveforms: +// +// Sweeping peak_time morphs the waveform while producing various spectra. +// Sweeping half_height effectively crossfades between two waveforms; useful, but less exciting. +// Sweeping zero_wait produces a similar effect no matter the reset of the waveform, +// a sort of high-pass/PWM effect where the wave becomes silent at zero_wait=1. +// +// You can trivially morph between any two waveforms from the above table +// which only differ in one column. +// +// Crossfade between classic waveforms: +// peak half zero +// Start End reflect time height wait +// ----- --- ------- ---- ------ ---- +// Triangle Square 0 0 -1..1 0 +// Saw Square 1 0 0..1 0 +// Triangle Saw 1 0.5 0..2 0 +// +// The last morph uses uses half-height values larger than 1, which means it will +// be louder and the output should be scaled down by half to compensate, or better +// by dynamically tracking the morph: volume_scale = 1 - half_height/4 +// +// Non-crossfade morph between classic waveforms, most require changing +// two parameters at the same time: +// peak half zero +// Start End reflect time height wait +// ----- --- ------- ---- ------ ---- +// Square Triangle any 0..0.5 1..0 0 +// Square Saw 1 0..1 1..any 0 +// Triangle Saw 1 0.5..1 0..-1 0 +// +// Other noteworthy morphs between simple shapes: +// peak half zero +// Start Halfway End reflect time height wait +// ----- --------- --- ------- ---- ------ ---- +// Saw (8va,neg) Saw (pos) 1 0..1 -1 0 +// Saw (neg) Saw (pos) 1 0..1 0 0 +// Triangle AlternatingSaw 0 0..1 -1 0 +// AlternatingSaw Triangle AlternatingSaw 0 0..1 0 0 +// Square AlternatingSaw 0 0..1 1 0 +// Triangle Triangle AlternatingSaw 0 0..1 -1..1 0 +// Square AlternatingSaw 0 0..1 1..0 0 +// Saw (8va) Triangle Saw 1 0..1 -1..1 0 +// Saw (neg) Saw (pos) 1 0..1 0..1 0 +// AlternatingSaw AlternatingSaw 0 0..1 0..any 0 +// +// The last entry is noteworthy because the morph from the halfway point to either +// endpoint sounds very different. For example, an LFO sweeping back and forth over +// the whole range will morph between the middle timbre and the AlternatingSaw +// timbre in two different ways, alternating. +// +// Entries with "any" for half_height are whole families of morphs, as you can pick +// any value you want as the endpoint for half_height. +// +// You can always morph between any two waveforms with the same value of 'reflect' +// by just sweeping the parameters simultaneously. There will never be artifacts +// and the result will always be useful, if not necessarily what you want. +// +// You can vary the sound of two-parameter morphs by ramping them differently, +// e.g. if the morph goes from t=0..1, then square-to-triangle looks like: +// peak_time = lerp(t, 0, 0.5) +// half_height = lerp(t, 1, 0 ) +// but you can also do things like: +// peak_time = lerp(smoothstep(t), 0, 0.5) +// half_height = cos(PI/2 * t) +// +// How it works: +// +// hexwave use BLEP to bandlimit discontinuities and BLAMP +// to bandlimit C1 discontinuities. This is not polyBLEP +// (polynomial BLEP), it is table-driven BLEP. It is +// also not minBLEP (minimum-phase BLEP), as that complicates +// things for little benefit once BLAMP is involved. +// +// The previous oscillator frequency is remembered, and when +// the frequency changes, a BLAMP is generated to remove the +// C1 discontinuity, which reduces artifacts for sweeps/LFO. +// +// Changes to an oscillator timbre using hexwave_change() actually +// wait until the oscillator finishes its current cycle. All +// waveforms with non-zero "zero_wait" settings pass through 0 +// and have 0-slope at the start of a cycle, which means changing +// the settings is artifact free at that time. (If zero_wait is 0, +// the code still treats it as passing through 0 with 0-slope; it'll +// apply the necessary fixups to make it artifact free as if it does +// transition to 0 with 0-slope vs. the waveform at the end of +// the cycle, then adds the fixups for a non-0 and non-0 slope +// at the start of the cycle, which cancels out if zero_wait is 0, +// and still does the right thing if zero_wait is 0 when the +// settings are updated.) +// +// BLEP/BLAMP normally requires overlapping buffers, but this +// is hidden from the user by generating the waveform to a +// temporary buffer and saving the overlap regions internally +// between calls. (It is slightly more complicated; see code.) +// +// By design all shapes have 0 DC offset; this is one reason +// hexwave uses zero_wait instead of standard PWM. +// +// The internals of hexwave could support any arbitrary shape +// made of line segments, but I chose not to expose this +// generality in favor of a simple, easy-to-use API. + +#ifndef STB_INCLUDE_STB_HEXWAVE_H +#define STB_INCLUDE_STB_HEXWAVE_H + +#ifndef STB_HEXWAVE_MAX_BLEP_LENGTH +#define STB_HEXWAVE_MAX_BLEP_LENGTH 64 // good enough for anybody +#endif + +#ifdef STB_HEXWAVE_STATIC +#define STB_HEXWAVE_DEF static +#else +#define STB_HEXWAVE_DEF extern +#endif + +typedef struct HexWave HexWave; + +STB_HEXWAVE_DEF void hexwave_init(int width, int oversample, float *user_buffer); +// width: size of BLEP, from 4..64, larger is slower & more memory but less aliasing +// oversample: 2+, number of subsample positions, larger uses more memory but less noise +// user_buffer: optional, if provided the library will perform no allocations. +// 16*width*(oversample+1) bytes, must stay allocated as long as library is used +// technically it only needs: 8*( width * (oversample + 1)) +// + 8*((width * oversample) + 1) bytes +// +// width can be larger than 64 if you define STB_HEXWAVE_MAX_BLEP_LENGTH to a larger value + +STB_HEXWAVE_DEF void hexwave_shutdown(float *user_buffer); +// user_buffer: pass in same parameter as passed to hexwave_init + +STB_HEXWAVE_DEF void hexwave_create(HexWave *hex, int reflect, float peak_time, float half_height, float zero_wait); +// see docs above for description +// +// reflect is tested as 0 or non-zero +// peak_time is clamped to 0..1 +// half_height is not clamped +// zero_wait is clamped to 0..1 + +STB_HEXWAVE_DEF void hexwave_change(HexWave *hex, int reflect, float peak_time, float half_height, float zero_wait); +// see docs + +STB_HEXWAVE_DEF void hexwave_generate_samples(float *output, int num_samples, HexWave *hex, float freq); +// output: buffer where the library will store generated floating point audio samples +// number_of_samples: the number of audio samples to generate +// osc: pointer to a Hexwave initialized with 'hexwave_create' +// oscillator_freq: frequency of the oscillator divided by the sample rate + +// private: +typedef struct +{ + int reflect; + float peak_time; + float zero_wait; + float half_height; +} HexWaveParameters; + +struct HexWave +{ + float t, prev_dt; + HexWaveParameters current, pending; + int have_pending; + float buffer[STB_HEXWAVE_MAX_BLEP_LENGTH]; +}; +#endif + +#ifdef STB_HEXWAVE_IMPLEMENTATION + +#ifndef STB_HEXWAVE_NO_ALLOCATION +#include // malloc,free +#endif + +#include // memset,memcpy,memmove +#include // sin,cos,fabs + +#define hexwave_clamp(v,a,b) ((v) < (a) ? (a) : (v) > (b) ? (b) : (v)) + +STB_HEXWAVE_DEF void hexwave_change(HexWave *hex, int reflect, float peak_time, float half_height, float zero_wait) +{ + hex->pending.reflect = reflect; + hex->pending.peak_time = hexwave_clamp(peak_time,0,1); + hex->pending.half_height = half_height; + hex->pending.zero_wait = hexwave_clamp(zero_wait,0,1); + // put a barrier here to allow changing from a different thread than the generator + hex->have_pending = 1; +} + +STB_HEXWAVE_DEF void hexwave_create(HexWave *hex, int reflect, float peak_time, float half_height, float zero_wait) +{ + memset(hex, 0, sizeof(*hex)); + hexwave_change(hex, reflect, peak_time, half_height, zero_wait); + hex->current = hex->pending; + hex->have_pending = 0; + hex->t = 0; + hex->prev_dt = 0; +} + +static struct +{ + int width; // width of fixup in samples + int oversample; // number of oversampled versions (there's actually one more to allow lerpign) + float *blep; + float *blamp; +} hexblep; + +static void hex_add_oversampled_bleplike(float *output, float time_since_transition, float scale, float *data) +{ + float *d1,*d2; + float lerpweight; + int i, bw = hexblep.width; + + int slot = (int) (time_since_transition * hexblep.oversample); + if (slot >= hexblep.oversample) + slot = hexblep.oversample-1; // clamp in case the floats overshoot + + d1 = &data[ slot *bw]; + d2 = &data[(slot+1)*bw]; + + lerpweight = time_since_transition * hexblep.oversample - slot; + for (i=0; i < bw; ++i) + output[i] += scale * (d1[i] + (d2[i]-d1[i])*lerpweight); +} + +static void hex_blep (float *output, float time_since_transition, float scale) +{ + hex_add_oversampled_bleplike(output, time_since_transition, scale, hexblep.blep); +} + +static void hex_blamp(float *output, float time_since_transition, float scale) +{ + hex_add_oversampled_bleplike(output, time_since_transition, scale, hexblep.blamp); +} + +typedef struct +{ + float t,v,s; // time, value, slope +} hexvert; + +// each half of the waveform needs 4 vertices to represent 3 line +// segments, plus 1 more for wraparound +static void hexwave_generate_linesegs(hexvert vert[9], HexWave *hex, float dt) +{ + int j; + float min_len = dt / 256.0f; + + vert[0].t = 0; + vert[0].v = 0; + vert[1].t = hex->current.zero_wait*0.5f; + vert[1].v = 0; + vert[2].t = 0.5f*hex->current.peak_time + vert[1].t*(1-hex->current.peak_time); + vert[2].v = 1; + vert[3].t = 0.5f; + vert[3].v = hex->current.half_height; + + if (hex->current.reflect) { + for (j=4; j <= 7; ++j) { + vert[j].t = 1 - vert[7-j].t; + vert[j].v = - vert[7-j].v; + } + } else { + for (j=4; j <= 7; ++j) { + vert[j].t = 0.5f + vert[j-4].t; + vert[j].v = - vert[j-4].v; + } + } + vert[8].t = 1; + vert[8].v = 0; + + for (j=0; j < 8; ++j) { + if (vert[j+1].t <= vert[j].t + min_len) { + // if change takes place over less than a fraction of a sample treat as discontinuity + // + // otherwise the slope computation can blow up to arbitrarily large and we + // try to generate a huge BLAMP and the result is wrong. + // + // why does this happen if the math is right? i believe if done perfectly, + // the two BLAMPs on either side of the slope would cancel out, but our + // BLAMPs have only limited sub-sample precision and limited integration + // accuracy. or maybe it's just the math blowing up w/ floating point precision + // limits as we try to make x * (1/x) cancel out + // + // min_len verified artifact-free even near nyquist with only oversample=4 + vert[j+1].t = vert[j].t; + } + } + + if (vert[8].t != 1.0f) { + // if the above fixup moved the endpoint away from 1.0, move it back, + // along with any other vertices that got moved to the same time + float t = vert[8].t; + for (j=5; j <= 8; ++j) + if (vert[j].t == t) + vert[j].t = 1.0f; + } + + // compute the exact slopes from the final fixed-up positions + for (j=0; j < 8; ++j) + if (vert[j+1].t == vert[j].t) + vert[j].s = 0; + else + vert[j].s = (vert[j+1].v - vert[j].v) / (vert[j+1].t - vert[j].t); + + // wraparound at end + vert[8].t = 1; + vert[8].v = vert[0].v; + vert[8].s = vert[0].s; +} + +STB_HEXWAVE_DEF void hexwave_generate_samples(float *output, int num_samples, HexWave *hex, float freq) +{ + hexvert vert[9]; + int pass,i,j; + float t = hex->t; + float temp_output[2*STB_HEXWAVE_MAX_BLEP_LENGTH]; + int buffered_length = sizeof(float)*hexblep.width; + float dt = (float) fabs(freq); + float recip_dt = (dt == 0.0f) ? 0.0f : 1.0f / dt; + + int halfw = hexblep.width/2; + // all sample times are biased by halfw to leave room for BLEP/BLAMP to go back in time + + if (num_samples <= 0) + return; + + // convert parameters to times and slopes + hexwave_generate_linesegs(vert, hex, dt); + + if (hex->prev_dt != dt) { + // if frequency changes, add a fixup at the derivative discontinuity starting at now + float slope; + for (j=1; j < 6; ++j) + if (t < vert[j].t) + break; + slope = vert[j].s; + if (slope != 0) + hex_blamp(output, 0, (dt - hex->prev_dt)*slope); + hex->prev_dt = dt; + } + + // copy the buffered data from last call and clear the rest of the output array + memset(output, 0, sizeof(float)*num_samples); + memset(temp_output, 0, 2*hexblep.width*sizeof(float)); + + if (num_samples >= hexblep.width) { + memcpy(output, hex->buffer, buffered_length); + } else { + // if the output is shorter than hexblep.width, we do all synthesis to temp_output + memcpy(temp_output, hex->buffer, buffered_length); + } + + for (pass=0; pass < 2; ++pass) { + int i0,i1; + float *out; + + // we want to simulate having one buffer that is num_output + hexblep.width + // samples long, without putting that requirement on the user, and without + // allocating a temp buffer that's as long as the whole thing. so we use two + // overlapping buffers, one the user's buffer and one a fixed-length temp + // buffer. + + if (pass == 0) { + if (num_samples < hexblep.width) + continue; + // run as far as we can without overwriting the end of the user's buffer + out = output; + i0 = 0; + i1 = num_samples - hexblep.width; + } else { + // generate the rest into a temp buffer + out = temp_output; + i0 = 0; + if (num_samples >= hexblep.width) + i1 = hexblep.width; + else + i1 = num_samples; + } + + // determine current segment + for (j=0; j < 8; ++j) + if (t < vert[j+1].t) + break; + + i = i0; + for(;;) { + while (t < vert[j+1].t) { + if (i == i1) + goto done; + out[i+halfw] += vert[j].v + vert[j].s*(t - vert[j].t); + t += dt; + ++i; + } + // transition from lineseg starting at j to lineseg starting at j+1 + + if (vert[j].t == vert[j+1].t) + hex_blep(out+i, recip_dt*(t-vert[j+1].t), (vert[j+1].v - vert[j].v)); + hex_blamp(out+i, recip_dt*(t-vert[j+1].t), dt*(vert[j+1].s - vert[j].s)); + ++j; + + if (j == 8) { + // change to different waveform if there's a change pending + j = 0; + t -= 1.0; // t was >= 1.f if j==8 + if (hex->have_pending) { + float prev_s0 = vert[j].s; + float prev_v0 = vert[j].v; + hex->current = hex->pending; + hex->have_pending = 0; + hexwave_generate_linesegs(vert, hex, dt); + // the following never occurs with this oscillator, but it makes + // the code work in more general cases + if (vert[j].v != prev_v0) + hex_blep (out+i, recip_dt*t, (vert[j].v - prev_v0)); + if (vert[j].s != prev_s0) + hex_blamp(out+i, recip_dt*t, dt*(vert[j].s - prev_s0)); + } + } + } + done: + ; + } + + // at this point, we've written output[] and temp_output[] + if (num_samples >= hexblep.width) { + // the first half of temp[] overlaps the end of output, the second half will be the new start overlap + for (i=0; i < hexblep.width; ++i) + output[num_samples-hexblep.width + i] += temp_output[i]; + memcpy(hex->buffer, temp_output+hexblep.width, buffered_length); + } else { + for (i=0; i < num_samples; ++i) + output[i] = temp_output[i]; + memcpy(hex->buffer, temp_output+num_samples, buffered_length); + } + + hex->t = t; +} + +STB_HEXWAVE_DEF void hexwave_shutdown(float *user_buffer) +{ + #ifndef STB_HEXWAVE_NO_ALLOCATION + if (user_buffer != 0) { + free(hexblep.blep); + free(hexblep.blamp); + } + #endif +} + +// buffer should be NULL or must be 4*(width*(oversample+1)*2 + +STB_HEXWAVE_DEF void hexwave_init(int width, int oversample, float *user_buffer) +{ + int halfwidth = width/2; + int half = halfwidth*oversample; + int blep_buffer_count = width*(oversample+1); + int n = 2*half+1; +#ifdef STB_HEXWAVE_NO_ALLOCATION + float *buffers = user_buffer; +#else + float *buffers = user_buffer ? user_buffer : (float *) malloc(sizeof(float) * n * 2); +#endif + float *step = buffers+0*n; + float *ramp = buffers+1*n; + float *blep_buffer, *blamp_buffer; + double integrate_impulse=0, integrate_step=0; + int i,j; + + if (width > STB_HEXWAVE_MAX_BLEP_LENGTH) + width = STB_HEXWAVE_MAX_BLEP_LENGTH; + + if (user_buffer == 0) { + #ifndef STB_HEXWAVE_NO_ALLOCATION + blep_buffer = (float *) malloc(sizeof(float)*blep_buffer_count); + blamp_buffer = (float *) malloc(sizeof(float)*blep_buffer_count); + #endif + } else { + blep_buffer = ramp+n; + blamp_buffer = blep_buffer + blep_buffer_count; + } + + // compute BLEP and BLAMP by integerating windowed sinc + for (i=0; i < n; ++i) { + for (j=0; j < 16; ++j) { + float sinc_t = 3.141592f* (i-half) / oversample; + float sinc = (i==half) ? 1.0f : (float) sin(sinc_t) / (sinc_t); + float wt = 2.0f*3.1415926f * i / (n-1); + float window = (float) (0.355768 - 0.487396*cos(wt) + 0.144232*cos(2*wt) - 0.012604*cos(3*wt)); // Nuttall + double value = window * sinc; + integrate_impulse += value/16; + integrate_step += integrate_impulse/16; + } + step[i] = (float) integrate_impulse; + ramp[i] = (float) integrate_step; + } + + // renormalize + for (i=0; i < n; ++i) { + step[i] = step[i] * (float) (1.0 / step[n-1]); // step needs to reach to 1.0 + ramp[i] = ramp[i] * (float) (halfwidth / ramp[n-1]); // ramp needs to become a slope of 1.0 after oversampling + } + + // deinterleave to allow efficient interpolation e.g. w/SIMD + for (j=0; j <= oversample; ++j) { + for (i=0; i < width; ++i) { + blep_buffer [j*width+i] = step[j+i*oversample]; + blamp_buffer[j*width+i] = ramp[j+i*oversample]; + } + } + + // subtract out the naive waveform; note we can't do this to the raw data + // above, because we want the discontinuity to be in a different locations + // for j=0 and j=oversample (which exists to provide something to interpolate against) + for (j=0; j <= oversample; ++j) { + // subtract step + for (i=halfwidth; i < width; ++i) + blep_buffer [j*width+i] -= 1.0f; + // subtract ramp + for (i=halfwidth; i < width; ++i) + blamp_buffer[j*width+i] -= (j+i*oversample-half)*(1.0f/oversample); + } + + hexblep.blep = blep_buffer; + hexblep.blamp = blamp_buffer; + hexblep.width = width; + hexblep.oversample = oversample; + + #ifndef STB_HEXWAVE_NO_ALLOCATION + if (user_buffer == 0) + free(buffers); + #endif +} +#endif // STB_HEXWAVE_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_image.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_image.h new file mode 100644 index 0000000..9eedabe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_image.h @@ -0,0 +1,7988 @@ +/* stb_image - v2.30 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8/16-bit-per-channel + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.30 (2024-05-31) avoid erroneous gcc warning + 2.29 (2023-05-xx) optimizations + 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff + 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes + 2.26 (2020-07-13) many minor fixes + 2.25 (2020-02-02) fix warnings + 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically + 2.23 (2019-08-11) fix clang static analysis warning + 2.22 (2019-03-04) gif fixes, fix warnings + 2.21 (2019-02-25) fix typo in comment + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) + Arseny Kapoulkine Simon Breuss (16-bit PNM) + John-Mark Allen + Carmelo J Fdez-Aguera + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski + Phil Jordan Dave Moore Roy Eltham + Hayaki Saito Nathan Reed Won Chun + Luke Graham Johan Duparc Nick Verigakis the Horde3D community + Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Eugene Golushkov Laurent Gomila Cort Stratton github:snagar + Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex + Cass Everitt Ryamond Barbiero github:grim210 + Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw + Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus + Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo + Julian Raschke Gregory Mullen Christian Floisand github:darealshinji + Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 + Brad Weinberger Matvey Cherevko github:mosra + Luca Sas Alexander Veselov Zack Middleton [reserved] + Ryan C. Gordon [reserved] [reserved] + DO NOT ADD YOUR NAME HERE + + Jacko Dirks + + To add your name to the credits, pick a random blank space in the middle and fill it. + 80% of merge conflicts on stb PRs are due to people adding their name at the end + of the credits. +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data); +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// To query the width, height and component count of an image without having to +// decode the full file, you can use the stbi_info family of functions: +// +// int x,y,n,ok; +// ok = stbi_info(filename, &x, &y, &n); +// // returns ok=1 and sets x, y, n if image is a supported format, +// // 0 otherwise. +// +// Note that stb_image pervasively uses ints in its public API for sizes, +// including sizes of memory buffers. This is now part of the API and thus +// hard to change without causing breakage. As a result, the various image +// loaders all have certain limits on image size; these differ somewhat +// by format but generally boil down to either just under 2GB or just under +// 1GB. When the decoded image would be larger than this, stb_image decoding +// will fail. +// +// Additionally, stb_image will reject image files that have any of their +// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, +// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, +// the only way to have an image with such dimensions load correctly +// is for it to have a rather extreme aspect ratio. Either way, the +// assumption here is that such larger images are likely to be malformed +// or malicious. If you do need to load an image with individual dimensions +// larger than that, and it still fits in the overall size limit, you can +// #define STBI_MAX_DIMENSIONS on your own to be something larger. +// +// =========================================================================== +// +// UNICODE: +// +// If compiling for Windows and you wish to use Unicode filenames, compile +// with +// #define STBI_WINDOWS_UTF8 +// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert +// Windows wchar_t filenames to utf8. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy-to-use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// provide more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small source code footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image supports loading HDR images in general, and currently the Radiance +// .HDR file format specifically. You can still load any file through the existing +// interface; if you attempt to load an HDR file, it will be automatically remapped +// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// We optionally support converting iPhone-formatted PNGs (which store +// premultiplied BGRA) back to RGB, even though they're internally encoded +// differently. To enable this conversion, call +// stbi_convert_iphone_png_to_rgb(1). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// +// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater +// than that size (in either width or height) without further processing. +// This is to let programs in the wild set an upper bound to prevent +// denial-of-service attacks on untrusted data, as one could generate a +// valid image of gigantic dimensions and force stb_image to allocate a +// huge block of memory and spend disproportionate time decoding it. By +// default this is set to (1 << 24), which is 16777216, but that's still +// very big. + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +#include +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STBIDEF +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + +#ifdef STBI_WINDOWS_UTF8 +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif + +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// on most compilers (and ALL modern mainstream compilers) this is threadsafe +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// as above, but only applies to images loaded on the thread that calls the function +// this function is only available if your compiler supports thread-local variables; +// calling it will fail to link if your compiler doesn't +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert); +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + +#ifdef __cplusplus +#define STBI_EXTERN extern "C" +#else +#define STBI_EXTERN extern +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + +#ifndef STBI_NO_THREAD_LOCALS + #if defined(__cplusplus) && __cplusplus >= 201103L + #define STBI_THREAD_LOCAL thread_local + #elif defined(__GNUC__) && __GNUC__ < 5 + #define STBI_THREAD_LOCAL __thread + #elif defined(_MSC_VER) + #define STBI_THREAD_LOCAL __declspec(thread) + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) + #define STBI_THREAD_LOCAL _Thread_local + #endif + + #ifndef STBI_THREAD_LOCAL + #if defined(__GNUC__) + #define STBI_THREAD_LOCAL __thread + #endif + #endif +#endif + +#if defined(_MSC_VER) || defined(__SYMBIAN32__) +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#endif + +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif + +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +#ifdef _MSC_VER +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name +#else +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +#ifndef STBI_MAX_DIMENSIONS +#define STBI_MAX_DIMENSIONS (1 << 24) +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + int callback_already_read; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + int ch; + fseek((FILE*) user, n, SEEK_CUR); + ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */ + if (ch != EOF) { + ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */ + } +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user) || ferror((FILE *) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__pnm_is16(stbi__context *s); +#endif + +static +#ifdef STBI_THREAD_LOCAL +STBI_THREAD_LOCAL +#endif +const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +#ifndef STBI_NO_FAILURE_STRINGS +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} +#endif + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} +#endif + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} +#endif + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow. +static int stbi__addints_valid(int a, int b) +{ + if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow + if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0. + return a <= INT_MAX - b; +} + +// returns 1 if the product of two ints fits in a signed short, 0 on overflow. +static int stbi__mul2shorts_valid(int a, int b) +{ + if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow + if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid + if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN + return a >= SHRT_MIN / b; +} + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load_global = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_global = flag_true_if_should_flip; +} + +#ifndef STBI_THREAD_LOCAL +#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global +#else +static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set; + +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_local = flag_true_if_should_flip; + stbi__vertically_flip_on_load_set = 1; +} + +#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \ + ? stbi__vertically_flip_on_load_local \ + : stbi__vertically_flip_on_load_global) +#endif // STBI_THREAD_LOCAL + +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + + // test the formats with a very explicit header first (at least a FOURCC + // or distinctive magic number first) + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #else + STBI_NOTUSED(bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif + + // then the formats that can end up attempting to load with just 1 or 2 + // bytes matching expectations; these are prone to false positives, so + // try them later + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +#ifndef STBI_NO_GIF +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} +#endif + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + + if (ri.bits_per_channel != 8) { + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + + if (ri.bits_per_channel != 16) { + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#ifndef STBI_NO_STDIO + +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); +#endif + +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) + return 0; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} +#endif + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) +// nothing +#else +static void stbi__skip(stbi__context *s, int n) +{ + if (n == 0) return; // already there! + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM) +// nothing +#else +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} +#endif + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} +#endif + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + z += (stbi__uint32)stbi__get16le(s) << 16; + return z; +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + } + if (n < comp) { + for (i=0; i < x*y; ++i) { + output[i*comp + n] = data[i*comp + n]/255.0f; + } + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) { + for (j=0; j < count[i]; ++j) { + h->size[k++] = (stbi_uc) (i+1); + if(k >= 257) return stbi__err("bad size list","Corrupt JPEG"); + } + } + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + if(c < 0 || c >= 256) // symbol id out of bounds! + return -1; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing + + sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & (sgn - 1)); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG"); + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + diff = t ? stbi__extend_receive(j, t) : 0; + + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG"); + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * (1 << j->succ_low)); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * (1 << shift)); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values! + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios + // and I've never seen a non-corrupted JPEG file actually use them + for (i=0; i < s->img_n; ++i) { + if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG"); + if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG"); + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) +{ + // some JPEGs have junk at end, skip over it but if we find what looks + // like a valid marker, resume there + while (!stbi__at_eof(j->s)) { + stbi_uc x = stbi__get8(j->s); + while (x == 0xff) { // might be a marker + if (stbi__at_eof(j->s)) return STBI__MARKER_none; + x = stbi__get8(j->s); + if (x != 0x00 && x != 0xff) { + // not a stuffed zero or lead-in to another marker, looks + // like an actual marker, return it + return x; + } + // stuffed zero has x=0 now which ends the loop, meaning we go + // back to regular scan loop. + // repeated 0xff keeps trying to read the next byte of the marker. + } + } + return STBI__MARKER_none; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + j->marker = stbi__skip_jpeg_junk_at_end(j); + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + m = stbi__get_marker(j); + if (STBI__RESTART(m)) + m = stbi__get_marker(j); + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + m = stbi__get_marker(j); + } else { + if (!stbi__process_marker(j, m)) return 1; + m = stbi__get_marker(j); + } + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + else + decode_n = z->s->img_n; + + // nothing to do if no components requested; check this now to avoid + // accessing uninitialized coutput[0] later + if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; } + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__errpuc("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) +#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[STBI__ZNSYMS]; + stbi__uint16 value[STBI__ZNSYMS]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + int hit_zeof_once; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static int stbi__zeof(stbi__zbuf *z) +{ + return (z->zbuffer >= z->zbuffer_end); +} + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + return stbi__zeof(z) ? 0 : *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + if (z->code_buffer >= (1U << z->num_bits)) { + z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */ + return; + } + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s >= 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere! + if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) { + if (stbi__zeof(a)) { + if (!a->hit_zeof_once) { + // This is the first time we hit eof, insert 16 extra padding btis + // to allow us to keep going; if we actually consume any of them + // though, that is invalid data. This is caught later. + a->hit_zeof_once = 1; + a->num_bits += 16; // add 16 implicit zero bits + } else { + // We already inserted our extra 16 padding bits and are again + // out, this stream is actually prematurely terminated. + return -1; + } + } else { + stbi__fill_bits(a); + } + } + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + unsigned int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (unsigned int) (z->zout - z->zout_start); + limit = old_limit = (unsigned) (z->zout_end - z->zout_start); + if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory"); + while (cur + n > limit) { + if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory"); + limit *= 2; + } + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + if (a->hit_zeof_once && a->num_bits < 16) { + // The first time we hit zeof, we inserted 16 extra zero bits into our bit + // buffer so the decoder can just do its speculative decoding. But if we + // actually consumed any of those bits (which is the case when num_bits < 16), + // the stream actually read past the end so it is malformed. + return stbi__err("unexpected end","Corrupt PNG"); + } + return 1; + } + if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (len > a->zout_end - zout) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) { + c = stbi__zreceive(a,3)+3; + } else if (c == 18) { + c = stbi__zreceive(a,7)+11; + } else { + return stbi__err("bad codelengths", "Corrupt PNG"); + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG"); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + a->hit_zeof_once = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filter used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub +}; + +static int stbi__paeth(int a, int b, int c) +{ + // This formulation looks very different from the reference in the PNG spec, but is + // actually equivalent and has favorable data dependencies and admits straightforward + // generation of branch-free code, which helps performance significantly. + int thresh = c*3 - (a + b); + int lo = a < b ? a : b; + int hi = a < b ? b : a; + int t0 = (hi <= thresh) ? lo : c; + int t1 = (thresh <= lo) ? hi : t0; + return t1; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// adds an extra all-255 alpha channel +// dest == src is legal +// img_n must be 1 or 3 +static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n) +{ + int i; + // must process data backwards since we allow dest==src + if (img_n == 1) { + for (i=x-1; i >= 0; --i) { + dest[i*2+1] = 255; + dest[i*2+0] = src[i]; + } + } else { + STBI_ASSERT(img_n == 3); + for (i=x-1; i >= 0; --i) { + dest[i*4+3] = 255; + dest[i*4+2] = src[i*3+2]; + dest[i*4+1] = src[i*3+1]; + dest[i*4+0] = src[i*3+0]; + } + } +} + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16 ? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + stbi_uc *filter_buf; + int all_ok = 1; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + // note: error exits here don't need to clean up a->out individually, + // stbi__do_png always does on error. + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG"); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + // Allocate two scan lines worth of filter workspace buffer. + filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0); + if (!filter_buf) return stbi__err("outofmem", "Out of memory"); + + // Filtering for low-bit-depth images + if (depth < 8) { + filter_bytes = 1; + width = img_width_bytes; + } + + for (j=0; j < y; ++j) { + // cur/prior filter buffers alternate + stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes; + stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes; + stbi_uc *dest = a->out + stride*j; + int nk = width * filter_bytes; + int filter = *raw++; + + // check filter type + if (filter > 4) { + all_ok = stbi__err("invalid filter","Corrupt PNG"); + break; + } + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // perform actual filtering + switch (filter) { + case STBI__F_none: + memcpy(cur, raw, nk); + break; + case STBI__F_sub: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); + break; + case STBI__F_up: + for (k = 0; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); + break; + case STBI__F_avg: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); + break; + case STBI__F_paeth: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0) + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes])); + break; + case STBI__F_avg_first: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); + break; + } + + raw += nk; + + // expand decoded bits in cur to dest, also adding an extra alpha channel if desired + if (depth < 8) { + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + stbi_uc *in = cur; + stbi_uc *out = dest; + stbi_uc inb = 0; + stbi__uint32 nsmp = x*img_n; + + // expand bits to bytes first + if (depth == 4) { + for (i=0; i < nsmp; ++i) { + if ((i & 1) == 0) inb = *in++; + *out++ = scale * (inb >> 4); + inb <<= 4; + } + } else if (depth == 2) { + for (i=0; i < nsmp; ++i) { + if ((i & 3) == 0) inb = *in++; + *out++ = scale * (inb >> 6); + inb <<= 2; + } + } else { + STBI_ASSERT(depth == 1); + for (i=0; i < nsmp; ++i) { + if ((i & 7) == 0) inb = *in++; + *out++ = scale * (inb >> 7); + inb <<= 1; + } + } + + // insert alpha=255 values if desired + if (img_n != out_n) + stbi__create_png_alpha_expand8(dest, dest, x, img_n); + } else if (depth == 8) { + if (img_n == out_n) + memcpy(dest, cur, x*img_n); + else + stbi__create_png_alpha_expand8(dest, cur, x, img_n); + } else if (depth == 16) { + // convert the image data from big-endian to platform-native + stbi__uint16 *dest16 = (stbi__uint16*)dest; + stbi__uint32 nsmp = x*img_n; + + if (img_n == out_n) { + for (i = 0; i < nsmp; ++i, ++dest16, cur += 2) + *dest16 = (cur[0] << 8) | cur[1]; + } else { + STBI_ASSERT(img_n+1 == out_n); + if (img_n == 1) { + for (i = 0; i < x; ++i, dest16 += 2, cur += 2) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = 0xffff; + } + } else { + STBI_ASSERT(img_n == 3); + for (i = 0; i < x; ++i, dest16 += 4, cur += 6) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = (cur[2] << 8) | cur[3]; + dest16[2] = (cur[4] << 8) | cur[5]; + dest16[3] = 0xffff; + } + } + } + } + } + + STBI_FREE(filter_buf); + if (!all_ok) return 0; + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + if (!final) return stbi__err("outofmem", "Out of memory"); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load_global = 0; +static int stbi__de_iphone_flag_global = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_global = flag_true_if_should_convert; +} + +#ifndef STBI_THREAD_LOCAL +#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global +#define stbi__de_iphone_flag stbi__de_iphone_flag_global +#else +static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; +static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; + +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; + stbi__unpremultiply_on_load_set = 1; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_local = flag_true_if_should_convert; + stbi__de_iphone_flag_set = 1; +} + +#define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \ + ? stbi__unpremultiply_on_load_local \ + : stbi__unpremultiply_on_load_global) +#define stbi__de_iphone_flag (stbi__de_iphone_flag_set \ + ? stbi__de_iphone_flag_local \ + : stbi__de_iphone_flag_global) +#endif // STBI_THREAD_LOCAL + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]={0}; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); + s->img_y = stbi__get32be(s); + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + } + // even with SCAN_header, have to scan to see if we have a tRNS + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. + if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } + if (z->depth == 16) { + for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning + tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n && k < 3; ++k) + tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { + // header scan definitely stops at first IDAT + if (pal_img_n) + s->img_n = pal_img_n; + return 1; + } + if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes"); + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth <= 8) + ri->bits_per_channel = 8; + else if (p->depth == 16) + ri->bits_per_channel = 16; + else + return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth"); + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) { n += 16; z >>= 16; } + if (z >= 0x00100) { n += 8; z >>= 8; } + if (z >= 0x00010) { n += 4; z >>= 4; } + if (z >= 0x00004) { n += 2; z >>= 2; } + if (z >= 0x00002) { n += 1;/* >>= 1;*/ } + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. +static int stbi__shiftsigned(unsigned int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; + int extra_read; +} stbi__bmp_data; + +static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) +{ + // BI_BITFIELDS specifies masks explicitly, don't override + if (compress == 3) + return 1; + + if (compress == 0) { + if (info->bpp == 16) { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } else if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + // otherwise, use defaults, which is all-0 + info->mr = info->mg = info->mb = info->ma = 0; + } + return 1; + } + return 0; // error +} + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + info->extra_read = 14; + + if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP"); + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes + if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + stbi__bmp_set_mask_defaults(info, compress); + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->extra_read += 12; + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + // V4/V5 header + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs + stbi__bmp_set_mask_defaults(info, compress); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - info.extra_read - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - info.extra_read - info.hsz) >> 2; + } + if (psize == 0) { + // accept some number of extra bytes after the header, but if the offset points either to before + // the header ends or implies a large amount of extra data, reject the file as malformed + int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original); + int header_limit = 1024; // max we actually read is below 256 bytes currently. + int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size. + if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) { + return stbi__errpuc("bad header", "Corrupt BMP"); + } + // we established that bytes_read_so_far is positive and sensible. + // the first half of this test rejects offsets that are either too small positives, or + // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn + // ensures the number computed in the second half of the test can't overflow. + if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { + return stbi__errpuc("bad offset", "Corrupt BMP"); + } else { + stbi__skip(s, info.offset - bytes_read_so_far); + } + } + + if (info.bpp == 24 && ma == 0xff000000) + s->img_n = 3; + else + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - info.extra_read - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i]; p1[i] = p2[i]; p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); + STBI_NOTUSED(tga_x_origin); // @TODO + STBI_NOTUSED(tga_y_origin); // @TODO + + if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + if (tga_palette_len == 0) { /* you have to have at least one entry! */ + STBI_FREE(tga_data); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + STBI_NOTUSED(tga_palette_start); + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + + if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + if (!result) return stbi__errpuc("outofmem", "Out of memory"); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!g) return stbi__err("outofmem", "Out of memory"); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + STBI_NOTUSED(req_comp); + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) + return stbi__errpuc("too large", "GIF image is too large"); + pcount = g->w * g->h; + g->out = (stbi_uc *) stbi__malloc(4 * pcount); + g->background = (stbi_uc *) stbi__malloc(4 * pcount); + g->history = (stbi_uc *) stbi__malloc(pcount); + if (!g->out || !g->background || !g->history) + return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "transparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to the color that was there the previous frame. + memset(g->out, 0x00, 4 * pcount); + memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) + memset(g->history, 0x00, pcount); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispose of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } + + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + // if the width of the specified rectangle is 0, that means + // we may not see *any* pixels or the image is malformed; + // to make sure this is caught, move the current y down to + // max_y (which is what out_gif_code checks). + if (w == 0) + g->cur_y = g->max_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (!o) return NULL; + + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) +{ + STBI_FREE(g->out); + STBI_FREE(g->history); + STBI_FREE(g->background); + + if (out) STBI_FREE(out); + if (delays && *delays) STBI_FREE(*delays); + return stbi__errpuc("outofmem", "Out of memory"); +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + int out_size = 0; + int delays_size = 0; + + STBI_NOTUSED(out_size); + STBI_NOTUSED(delays_size); + + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride ); + if (!tmp) + return stbi__load_gif_main_outofmem(&g, out, delays); + else { + out = (stbi_uc*) tmp; + out_size = layers * stride; + } + + if (delays) { + int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); + if (!new_delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + *delays = new_delays; + delays_size = layers * sizeof(int); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (!out) + return stbi__load_gif_main_outofmem(&g, out, delays); + out_size = layers * stride; + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + if (!*delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + delays_size = layers * sizeof(int); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + STBI_NOTUSED(ri); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } else if (g.out) { + // if there was an error and we allocated an image buffer, free it! + STBI_FREE(g.out); + } + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + if (p == NULL) { + stbi__rewind( s ); + return 0; + } + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) { + if (info.bpp == 24 && info.ma == 0xff000000) + *comp = 3; + else + *comp = info.ma ? 4 : 3; + } + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + STBI_NOTUSED(stbi__get32be(s)); + STBI_NOTUSED(stbi__get32be(s)); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); + if (ri->bits_per_channel == 0) + return 0; + + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + + if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) { + STBI_FREE(out); + return stbi__errpuc("bad PNM", "PNM file truncated"); + } + + if (req_comp && req_comp != s->img_n) { + if (ri->bits_per_channel == 16) { + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); + } else { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + } + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + if((value > 214748364) || (value == 214748364 && *c > '7')) + return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int"); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + if(*x == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + if (*y == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + if (maxv > 65535) + return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images"); + else if (maxv > 255) + return 16; + else + return 8; +} + +static int stbi__pnm_is16(stbi__context *s) +{ + if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) + return 1; + return 0; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_is16(s)) return 1; + #endif + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_image_resize2.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_image_resize2.h new file mode 100644 index 0000000..a5c959f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_image_resize2.h @@ -0,0 +1,10572 @@ +/* stb_image_resize2 - v2.10 - public domain image resizing + + by Jeff Roberts (v2) and Jorge L Rodriguez + http://github.com/nothings/stb + + Can be threaded with the extended API. SSE2, AVX, Neon and WASM SIMD support. Only + scaling and translation is supported, no rotations or shears. + + COMPILING & LINKING + In one C/C++ file that #includes this file, do this: + #define STB_IMAGE_RESIZE_IMPLEMENTATION + before the #include. That will create the implementation in that file. + + PORTING FROM VERSION 1 + + The API has changed. You can continue to use the old version of stb_image_resize.h, + which is available in the "deprecated/" directory. + + If you're using the old simple-to-use API, porting is straightforward. + (For more advanced APIs, read the documentation.) + + stbir_resize_uint8(): + - call `stbir_resize_uint8_linear`, cast channel count to `stbir_pixel_layout` + + stbir_resize_float(): + - call `stbir_resize_float_linear`, cast channel count to `stbir_pixel_layout` + + stbir_resize_uint8_srgb(): + - function name is unchanged + - cast channel count to `stbir_pixel_layout` + - above is sufficient unless your image has alpha and it's not RGBA/BGRA + - in that case, follow the below instructions for stbir_resize_uint8_srgb_edgemode + + stbir_resize_uint8_srgb_edgemode() + - switch to the "medium complexity" API + - stbir_resize(), very similar API but a few more parameters: + - pixel_layout: cast channel count to `stbir_pixel_layout` + - data_type: STBIR_TYPE_UINT8_SRGB + - edge: unchanged (STBIR_EDGE_WRAP, etc.) + - filter: STBIR_FILTER_DEFAULT + - which channel is alpha is specified in stbir_pixel_layout, see enum for details + + EASY API CALLS: + Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation, clamps to edge. + + stbir_resize_uint8_srgb( input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout_enum ) + + stbir_resize_uint8_linear( input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout_enum ) + + stbir_resize_float_linear( input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout_enum ) + + If you pass NULL or zero for the output_pixels, we will allocate the output buffer + for you and return it from the function (free with free() or STBIR_FREE). + As a special case, XX_stride_in_bytes of 0 means packed continuously in memory. + + API LEVELS + There are three levels of API - easy-to-use, medium-complexity and extended-complexity. + + See the "header file" section of the source for API documentation. + + ADDITIONAL DOCUMENTATION + + MEMORY ALLOCATION + By default, we use malloc and free for memory allocation. To override the + memory allocation, before the implementation #include, add a: + + #define STBIR_MALLOC(size,user_data) ... + #define STBIR_FREE(ptr,user_data) ... + + Each resize makes exactly one call to malloc/free (unless you use the + extended API where you can do one allocation for many resizes). Under + address sanitizer, we do separate allocations to find overread/writes. + + PERFORMANCE + This library was written with an emphasis on performance. When testing + stb_image_resize with RGBA, the fastest mode is STBIR_4CHANNEL with + STBIR_TYPE_UINT8 pixels and CLAMPed edges (which is what many other resize + libs do by default). Also, make sure SIMD is turned on of course (default + for 64-bit targets). Avoid WRAP edge mode if you want the fastest speed. + + This library also comes with profiling built-in. If you define STBIR_PROFILE, + you can use the advanced API and get low-level profiling information by + calling stbir_resize_extended_profile_info() or stbir_resize_split_profile_info() + after a resize. + + SIMD + Most of the routines have optimized SSE2, AVX, NEON and WASM versions. + + On Microsoft compilers, we automatically turn on SIMD for 64-bit x64 and + ARM; for 32-bit x86 and ARM, you select SIMD mode by defining STBIR_SSE2 or + STBIR_NEON. For AVX and AVX2, we auto-select it by detecting the /arch:AVX + or /arch:AVX2 switches. You can also always manually turn SSE2, AVX or AVX2 + support on by defining STBIR_SSE2, STBIR_AVX or STBIR_AVX2. + + On Linux, SSE2 and Neon is on by default for 64-bit x64 or ARM64. For 32-bit, + we select x86 SIMD mode by whether you have -msse2, -mavx or -mavx2 enabled + on the command line. For 32-bit ARM, you must pass -mfpu=neon-vfpv4 for both + clang and GCC, but GCC also requires an additional -mfp16-format=ieee to + automatically enable NEON. + + On x86 platforms, you can also define STBIR_FP16C to turn on FP16C instructions + for converting back and forth to half-floats. This is autoselected when we + are using AVX2. Clang and GCC also require the -mf16c switch. ARM always uses + the built-in half float hardware NEON instructions. + + You can also tell us to use multiply-add instructions with STBIR_USE_FMA. + Because x86 doesn't always have fma, we turn it off by default to maintain + determinism across all platforms. If you don't care about non-FMA determinism + and are willing to restrict yourself to more recent x86 CPUs (around the AVX + timeframe), then fma will give you around a 15% speedup. + + You can force off SIMD in all cases by defining STBIR_NO_SIMD. You can turn + off AVX or AVX2 specifically with STBIR_NO_AVX or STBIR_NO_AVX2. AVX is 10% + to 40% faster, and AVX2 is generally another 12%. + + ALPHA CHANNEL + Most of the resizing functions provide the ability to control how the alpha + channel of an image is processed. + + When alpha represents transparency, it is important that when combining + colors with filtering, the pixels should not be treated equally; they + should use a weighted average based on their alpha values. For example, + if a pixel is 1% opaque bright green and another pixel is 99% opaque + black and you average them, the average will be 50% opaque, but the + unweighted average and will be a middling green color, while the weighted + average will be nearly black. This means the unweighted version introduced + green energy that didn't exist in the source image. + + (If you want to know why this makes sense, you can work out the math for + the following: consider what happens if you alpha composite a source image + over a fixed color and then average the output, vs. if you average the + source image pixels and then composite that over the same fixed color. + Only the weighted average produces the same result as the ground truth + composite-then-average result.) + + Therefore, it is in general best to "alpha weight" the pixels when applying + filters to them. This essentially means multiplying the colors by the alpha + values before combining them, and then dividing by the alpha value at the + end. + + The computer graphics industry introduced a technique called "premultiplied + alpha" or "associated alpha" in which image colors are stored in image files + already multiplied by their alpha. This saves some math when compositing, + and also avoids the need to divide by the alpha at the end (which is quite + inefficient). However, while premultiplied alpha is common in the movie CGI + industry, it is not commonplace in other industries like videogames, and most + consumer file formats are generally expected to contain not-premultiplied + colors. For example, Photoshop saves PNG files "unpremultiplied", and web + browsers like Chrome and Firefox expect PNG images to be unpremultiplied. + + Note that there are three possibilities that might describe your image + and resize expectation: + + 1. images are not premultiplied, alpha weighting is desired + 2. images are not premultiplied, alpha weighting is not desired + 3. images are premultiplied + + Both case #2 and case #3 require the exact same math: no alpha weighting + should be applied or removed. Only case 1 requires extra math operations; + the other two cases can be handled identically. + + stb_image_resize expects case #1 by default, applying alpha weighting to + images, expecting the input images to be unpremultiplied. This is what the + COLOR+ALPHA buffer types tell the resizer to do. + + When you use the pixel layouts STBIR_RGBA, STBIR_BGRA, STBIR_ARGB, + STBIR_ABGR, STBIR_RX, or STBIR_XR you are telling us that the pixels are + non-premultiplied. In these cases, the resizer will alpha weight the colors + (effectively creating the premultiplied image), do the filtering, and then + convert back to non-premult on exit. + + When you use the pixel layouts STBIR_RGBA_PM, STBIR_RGBA_PM, STBIR_RGBA_PM, + STBIR_RGBA_PM, STBIR_RX_PM or STBIR_XR_PM, you are telling that the pixels + ARE premultiplied. In this case, the resizer doesn't have to do the + premultipling - it can filter directly on the input. This about twice as + fast as the non-premultiplied case, so it's the right option if your data is + already setup correctly. + + When you use the pixel layout STBIR_4CHANNEL or STBIR_2CHANNEL, you are + telling us that there is no channel that represents transparency; it may be + RGB and some unrelated fourth channel that has been stored in the alpha + channel, but it is actually not alpha. No special processing will be + performed. + + The difference between the generic 4 or 2 channel layouts, and the + specialized _PM versions is with the _PM versions you are telling us that + the data *is* alpha, just don't premultiply it. That's important when + using SRGB pixel formats, we need to know where the alpha is, because + it is converted linearly (rather than with the SRGB converters). + + Because alpha weighting produces the same effect as premultiplying, you + even have the option with non-premultiplied inputs to let the resizer + produce a premultiplied output. Because the intially computed alpha-weighted + output image is effectively premultiplied, this is actually more performant + than the normal path which un-premultiplies the output image as a final step. + + Finally, when converting both in and out of non-premulitplied space (for + example, when using STBIR_RGBA), we go to somewhat heroic measures to + ensure that areas with zero alpha value pixels get something reasonable + in the RGB values. If you don't care about the RGB values of zero alpha + pixels, you can call the stbir_set_non_pm_alpha_speed_over_quality() + function - this runs a premultiplied resize about 25% faster. That said, + when you really care about speed, using premultiplied pixels for both in + and out (STBIR_RGBA_PM, etc) much faster than both of these premultiplied + options. + + PIXEL LAYOUT CONVERSION + The resizer can convert from some pixel layouts to others. When using the + stbir_set_pixel_layouts(), you can, for example, specify STBIR_RGBA + on input, and STBIR_ARGB on output, and it will re-organize the channels + during the resize. Currently, you can only convert between two pixel + layouts with the same number of channels. + + DETERMINISM + We commit to being deterministic (from x64 to ARM to scalar to SIMD, etc). + This requires compiling with fast-math off (using at least /fp:precise). + Also, you must turn off fp-contracting (which turns mult+adds into fmas)! + We attempt to do this with pragmas, but with Clang, you usually want to add + -ffp-contract=off to the command line as well. + + For 32-bit x86, you must use SSE and SSE2 codegen for determinism. That is, + if the scalar x87 unit gets used at all, we immediately lose determinism. + On Microsoft Visual Studio 2008 and earlier, from what we can tell there is + no way to be deterministic in 32-bit x86 (some x87 always leaks in, even + with fp:strict). On 32-bit x86 GCC, determinism requires both -msse2 and + -fpmath=sse. + + Note that we will not be deterministic with float data containing NaNs - + the NaNs will propagate differently on different SIMD and platforms. + + If you turn on STBIR_USE_FMA, then we will be deterministic with other + fma targets, but we will differ from non-fma targets (this is unavoidable, + because a fma isn't simply an add with a mult - it also introduces a + rounding difference compared to non-fma instruction sequences. + + FLOAT PIXEL FORMAT RANGE + Any range of values can be used for the non-alpha float data that you pass + in (0 to 1, -1 to 1, whatever). However, if you are inputting float values + but *outputting* bytes or shorts, you must use a range of 0 to 1 so that we + scale back properly. The alpha channel must also be 0 to 1 for any format + that does premultiplication prior to resizing. + + Note also that with float output, using filters with negative lobes, the + output filtered values might go slightly out of range. You can define + STBIR_FLOAT_LOW_CLAMP and/or STBIR_FLOAT_HIGH_CLAMP to specify the range + to clamp to on output, if that's important. + + MAX/MIN SCALE FACTORS + The input pixel resolutions are in integers, and we do the internal pointer + resolution in size_t sized integers. However, the scale ratio from input + resolution to output resolution is calculated in float form. This means + the effective possible scale ratio is limited to 24 bits (or 16 million + to 1). As you get close to the size of the float resolution (again, 16 + million pixels wide or high), you might start seeing float inaccuracy + issues in general in the pipeline. If you have to do extreme resizes, + you can usually do this is multiple stages (using float intermediate + buffers). + + FLIPPED IMAGES + Stride is just the delta from one scanline to the next. This means you can + use a negative stride to handle inverted images (point to the final + scanline and use a negative stride). You can invert the input or output, + using negative strides. + + DEFAULT FILTERS + For functions which don't provide explicit control over what filters to + use, you can change the compile-time defaults with: + + #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something + #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something + + See stbir_filter in the header-file section for the list of filters. + + NEW FILTERS + A number of 1D filter kernels are supplied. For a list of supported + filters, see the stbir_filter enum. You can install your own filters by + using the stbir_set_filter_callbacks function. + + PROGRESS + For interactive use with slow resize operations, you can use the the + scanline callbacks in the extended API. It would have to be a *very* large + image resample to need progress though - we're very fast. + + CEIL and FLOOR + In scalar mode, the only functions we use from math.h are ceilf and floorf, + but if you have your own versions, you can define the STBIR_CEILF(v) and + STBIR_FLOORF(v) macros and we'll use them instead. In SIMD, we just use + our own versions. + + ASSERT + Define STBIR_ASSERT(boolval) to override assert() and not use assert.h + + FUTURE TODOS + * For polyphase integral filters, we just memcpy the coeffs to dupe + them, but we should indirect and use the same coeff memory. + * Add pixel layout conversions for sensible different channel counts + (maybe, 1->3/4, 3->4, 4->1, 3->1). + * For SIMD encode and decode scanline routines, do any pre-aligning + for bad input/output buffer alignments and pitch? + * For very wide scanlines, we should we do vertical strips to stay within + L2 cache. Maybe do chunks of 1K pixels at a time. There would be + some pixel reconversion, but probably dwarfed by things falling out + of cache. Probably also something possible with alternating between + scattering and gathering at high resize scales? + * Rewrite the coefficient generator to do many at once. + * AVX-512 vertical kernels - worried about downclocking here. + * Convert the reincludes to macros when we know they aren't changing. + * Experiment with pivoting the horizontal and always using the + vertical filters (which are faster, but perhaps not enough to overcome + the pivot cost and the extra memory touches). Need to buffer the whole + image so have to balance memory use. + * Most of our code is internally function pointers, should we compile + all the SIMD stuff always and dynamically dispatch? + + CONTRIBUTORS + Jeff Roberts: 2.0 implementation, optimizations, SIMD + Martins Mozeiko: NEON simd, WASM simd, clang and GCC whisperer + Fabian Giesen: half float and srgb converters + Sean Barrett: API design, optimizations + Jorge L Rodriguez: Original 1.0 implementation + Aras Pranckevicius: bugfixes + Nathan Reed: warning fixes for 1.0 + + REVISIONS + 2.10 (2024-07-27) fix the defines GCC and mingw for loop unroll control, + fix MSVC 32-bit arm half float routines. + 2.09 (2024-06-19) fix the defines for 32-bit ARM GCC builds (was selecting + hardware half floats). + 2.08 (2024-06-10) fix for RGB->BGR three channel flips and add SIMD (thanks + to Ryan Salsbury), fix for sub-rect resizes, use the + pragmas to control unrolling when they are available. + 2.07 (2024-05-24) fix for slow final split during threaded conversions of very + wide scanlines when downsampling (caused by extra input + converting), fix for wide scanline resamples with many + splits (int overflow), fix GCC warning. + 2.06 (2024-02-10) fix for identical width/height 3x or more down-scaling + undersampling a single row on rare resize ratios (about 1%). + 2.05 (2024-02-07) fix for 2 pixel to 1 pixel resizes with wrap (thanks Aras), + fix for output callback (thanks Julien Koenen). + 2.04 (2023-11-17) fix for rare AVX bug, shadowed symbol (thanks Nikola Smiljanic). + 2.03 (2023-11-01) ASAN and TSAN warnings fixed, minor tweaks. + 2.00 (2023-10-10) mostly new source: new api, optimizations, simd, vertical-first, etc + 2x-5x faster without simd, 4x-12x faster with simd, + in some cases, 20x to 40x faster esp resizing large to very small. + 0.96 (2019-03-04) fixed warnings + 0.95 (2017-07-23) fixed warnings + 0.94 (2017-03-18) fixed warnings + 0.93 (2017-03-03) fixed bug with certain combinations of heights + 0.92 (2017-01-02) fix integer overflow on large (>2GB) images + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions + 0.90 (2014-09-17) first released version + + LICENSE + See end of file for license information. +*/ + +#if !defined(STB_IMAGE_RESIZE_DO_HORIZONTALS) && !defined(STB_IMAGE_RESIZE_DO_VERTICALS) && !defined(STB_IMAGE_RESIZE_DO_CODERS) // for internal re-includes + +#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE2_H +#define STBIR_INCLUDE_STB_IMAGE_RESIZE2_H + +#include +#ifdef _MSC_VER +typedef unsigned char stbir_uint8; +typedef unsigned short stbir_uint16; +typedef unsigned int stbir_uint32; +typedef unsigned __int64 stbir_uint64; +#else +#include +typedef uint8_t stbir_uint8; +typedef uint16_t stbir_uint16; +typedef uint32_t stbir_uint32; +typedef uint64_t stbir_uint64; +#endif + +#ifdef _M_IX86_FP +#if ( _M_IX86_FP >= 1 ) +#ifndef STBIR_SSE +#define STBIR_SSE +#endif +#endif +#endif + +#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(_M_AMD64) || defined(__SSE2__) || defined(STBIR_SSE) || defined(STBIR_SSE2) + #ifndef STBIR_SSE2 + #define STBIR_SSE2 + #endif + #if defined(__AVX__) || defined(STBIR_AVX2) + #ifndef STBIR_AVX + #ifndef STBIR_NO_AVX + #define STBIR_AVX + #endif + #endif + #endif + #if defined(__AVX2__) || defined(STBIR_AVX2) + #ifndef STBIR_NO_AVX2 + #ifndef STBIR_AVX2 + #define STBIR_AVX2 + #endif + #if defined( _MSC_VER ) && !defined(__clang__) + #ifndef STBIR_FP16C // FP16C instructions are on all AVX2 cpus, so we can autoselect it here on microsoft - clang needs -m16c + #define STBIR_FP16C + #endif + #endif + #endif + #endif + #ifdef __F16C__ + #ifndef STBIR_FP16C // turn on FP16C instructions if the define is set (for clang and gcc) + #define STBIR_FP16C + #endif + #endif +#endif + +#if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || ((__ARM_NEON_FP & 4) != 0) || defined(__ARM_NEON__) +#ifndef STBIR_NEON +#define STBIR_NEON +#endif +#endif + +#if defined(_M_ARM) || defined(__arm__) +#ifdef STBIR_USE_FMA +#undef STBIR_USE_FMA // no FMA for 32-bit arm on MSVC +#endif +#endif + +#if defined(__wasm__) && defined(__wasm_simd128__) +#ifndef STBIR_WASM +#define STBIR_WASM +#endif +#endif + +#ifndef STBIRDEF +#ifdef STB_IMAGE_RESIZE_STATIC +#define STBIRDEF static +#else +#ifdef __cplusplus +#define STBIRDEF extern "C" +#else +#define STBIRDEF extern +#endif +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +//// start "header file" /////////////////////////////////////////////////// +// +// Easy-to-use API: +// +// * stride is the offset between successive rows of image data +// in memory, in bytes. specify 0 for packed continuously in memory +// * colorspace is linear or sRGB as specified by function name +// * Uses the default filters +// * Uses edge mode clamped +// * returned result is 1 for success or 0 in case of an error. + + +// stbir_pixel_layout specifies: +// number of channels +// order of channels +// whether color is premultiplied by alpha +// for back compatibility, you can cast the old channel count to an stbir_pixel_layout +typedef enum +{ + STBIR_1CHANNEL = 1, + STBIR_2CHANNEL = 2, + STBIR_RGB = 3, // 3-chan, with order specified (for channel flipping) + STBIR_BGR = 0, // 3-chan, with order specified (for channel flipping) + STBIR_4CHANNEL = 5, + + STBIR_RGBA = 4, // alpha formats, where alpha is NOT premultiplied into color channels + STBIR_BGRA = 6, + STBIR_ARGB = 7, + STBIR_ABGR = 8, + STBIR_RA = 9, + STBIR_AR = 10, + + STBIR_RGBA_PM = 11, // alpha formats, where alpha is premultiplied into color channels + STBIR_BGRA_PM = 12, + STBIR_ARGB_PM = 13, + STBIR_ABGR_PM = 14, + STBIR_RA_PM = 15, + STBIR_AR_PM = 16, + + STBIR_RGBA_NO_AW = 11, // alpha formats, where NO alpha weighting is applied at all! + STBIR_BGRA_NO_AW = 12, // these are just synonyms for the _PM flags (which also do + STBIR_ARGB_NO_AW = 13, // no alpha weighting). These names just make it more clear + STBIR_ABGR_NO_AW = 14, // for some folks). + STBIR_RA_NO_AW = 15, + STBIR_AR_NO_AW = 16, + +} stbir_pixel_layout; + +//=============================================================== +// Simple-complexity API +// +// If output_pixels is NULL (0), then we will allocate the buffer and return it to you. +//-------------------------------- + +STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_type ); + +STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_type ); + +STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_type ); +//=============================================================== + +//=============================================================== +// Medium-complexity API +// +// This extends the easy-to-use API as follows: +// +// * Can specify the datatype - U8, U8_SRGB, U16, FLOAT, HALF_FLOAT +// * Edge wrap can selected explicitly +// * Filter can be selected explicitly +//-------------------------------- + +typedef enum +{ + STBIR_EDGE_CLAMP = 0, + STBIR_EDGE_REFLECT = 1, + STBIR_EDGE_WRAP = 2, // this edge mode is slower and uses more memory + STBIR_EDGE_ZERO = 3, +} stbir_edge; + +typedef enum +{ + STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses + STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios + STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering + STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque + STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline + STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3 + STBIR_FILTER_POINT_SAMPLE = 6, // Simple point sampling + STBIR_FILTER_OTHER = 7, // User callback specified +} stbir_filter; + +typedef enum +{ + STBIR_TYPE_UINT8 = 0, + STBIR_TYPE_UINT8_SRGB = 1, + STBIR_TYPE_UINT8_SRGB_ALPHA = 2, // alpha channel, when present, should also be SRGB (this is very unusual) + STBIR_TYPE_UINT16 = 3, + STBIR_TYPE_FLOAT = 4, + STBIR_TYPE_HALF_FLOAT = 5 +} stbir_datatype; + +// medium api +STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout, stbir_datatype data_type, + stbir_edge edge, stbir_filter filter ); +//=============================================================== + + + +//=============================================================== +// Extended-complexity API +// +// This API exposes all resize functionality. +// +// * Separate filter types for each axis +// * Separate edge modes for each axis +// * Separate input and output data types +// * Can specify regions with subpixel correctness +// * Can specify alpha flags +// * Can specify a memory callback +// * Can specify a callback data type for pixel input and output +// * Can be threaded for a single resize +// * Can be used to resize many frames without recalculating the sampler info +// +// Use this API as follows: +// 1) Call the stbir_resize_init function on a local STBIR_RESIZE structure +// 2) Call any of the stbir_set functions +// 3) Optionally call stbir_build_samplers() if you are going to resample multiple times +// with the same input and output dimensions (like resizing video frames) +// 4) Resample by calling stbir_resize_extended(). +// 5) Call stbir_free_samplers() if you called stbir_build_samplers() +//-------------------------------- + + +// Types: + +// INPUT CALLBACK: this callback is used for input scanlines +typedef void const * stbir_input_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ); + +// OUTPUT CALLBACK: this callback is used for output scanlines +typedef void stbir_output_callback( void const * output_ptr, int num_pixels, int y, void * context ); + +// callbacks for user installed filters +typedef float stbir__kernel_callback( float x, float scale, void * user_data ); // centered at zero +typedef float stbir__support_callback( float scale, void * user_data ); + +// internal structure with precomputed scaling +typedef struct stbir__info stbir__info; + +typedef struct STBIR_RESIZE // use the stbir_resize_init and stbir_override functions to set these values for future compatibility +{ + void * user_data; + void const * input_pixels; + int input_w, input_h; + double input_s0, input_t0, input_s1, input_t1; + stbir_input_callback * input_cb; + void * output_pixels; + int output_w, output_h; + int output_subx, output_suby, output_subw, output_subh; + stbir_output_callback * output_cb; + int input_stride_in_bytes; + int output_stride_in_bytes; + int splits; + int fast_alpha; + int needs_rebuild; + int called_alloc; + stbir_pixel_layout input_pixel_layout_public; + stbir_pixel_layout output_pixel_layout_public; + stbir_datatype input_data_type; + stbir_datatype output_data_type; + stbir_filter horizontal_filter, vertical_filter; + stbir_edge horizontal_edge, vertical_edge; + stbir__kernel_callback * horizontal_filter_kernel; stbir__support_callback * horizontal_filter_support; + stbir__kernel_callback * vertical_filter_kernel; stbir__support_callback * vertical_filter_support; + stbir__info * samplers; +} STBIR_RESIZE; + +// extended complexity api + + +// First off, you must ALWAYS call stbir_resize_init on your resize structure before any of the other calls! +STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize, + const void *input_pixels, int input_w, int input_h, int input_stride_in_bytes, // stride can be zero + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, // stride can be zero + stbir_pixel_layout pixel_layout, stbir_datatype data_type ); + +//=============================================================== +// You can update these parameters any time after resize_init and there is no cost +//-------------------------------- + +STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_type, stbir_datatype output_type ); +STBIRDEF void stbir_set_pixel_callbacks( STBIR_RESIZE * resize, stbir_input_callback * input_cb, stbir_output_callback * output_cb ); // no callbacks by default +STBIRDEF void stbir_set_user_data( STBIR_RESIZE * resize, void * user_data ); // pass back STBIR_RESIZE* by default +STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_pixels, int input_stride_in_bytes, void * output_pixels, int output_stride_in_bytes ); + +//=============================================================== + + +//=============================================================== +// If you call any of these functions, you will trigger a sampler rebuild! +//-------------------------------- + +STBIRDEF int stbir_set_pixel_layouts( STBIR_RESIZE * resize, stbir_pixel_layout input_pixel_layout, stbir_pixel_layout output_pixel_layout ); // sets new buffer layouts +STBIRDEF int stbir_set_edgemodes( STBIR_RESIZE * resize, stbir_edge horizontal_edge, stbir_edge vertical_edge ); // CLAMP by default + +STBIRDEF int stbir_set_filters( STBIR_RESIZE * resize, stbir_filter horizontal_filter, stbir_filter vertical_filter ); // STBIR_DEFAULT_FILTER_UPSAMPLE/DOWNSAMPLE by default +STBIRDEF int stbir_set_filter_callbacks( STBIR_RESIZE * resize, stbir__kernel_callback * horizontal_filter, stbir__support_callback * horizontal_support, stbir__kernel_callback * vertical_filter, stbir__support_callback * vertical_support ); + +STBIRDEF int stbir_set_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ); // sets both sub-regions (full regions by default) +STBIRDEF int stbir_set_input_subrect( STBIR_RESIZE * resize, double s0, double t0, double s1, double t1 ); // sets input sub-region (full region by default) +STBIRDEF int stbir_set_output_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ); // sets output sub-region (full region by default) + +// when inputting AND outputting non-premultiplied alpha pixels, we use a slower but higher quality technique +// that fills the zero alpha pixel's RGB values with something plausible. If you don't care about areas of +// zero alpha, you can call this function to get about a 25% speed improvement for STBIR_RGBA to STBIR_RGBA +// types of resizes. +STBIRDEF int stbir_set_non_pm_alpha_speed_over_quality( STBIR_RESIZE * resize, int non_pma_alpha_speed_over_quality ); +//=============================================================== + + +//=============================================================== +// You can call build_samplers to prebuild all the internal data we need to resample. +// Then, if you call resize_extended many times with the same resize, you only pay the +// cost once. +// If you do call build_samplers, you MUST call free_samplers eventually. +//-------------------------------- + +// This builds the samplers and does one allocation +STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize ); + +// You MUST call this, if you call stbir_build_samplers or stbir_build_samplers_with_splits +STBIRDEF void stbir_free_samplers( STBIR_RESIZE * resize ); +//=============================================================== + + +// And this is the main function to perform the resize synchronously on one thread. +STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize ); + + +//=============================================================== +// Use these functions for multithreading. +// 1) You call stbir_build_samplers_with_splits first on the main thread +// 2) Then stbir_resize_with_split on each thread +// 3) stbir_free_samplers when done on the main thread +//-------------------------------- + +// This will build samplers for threading. +// You can pass in the number of threads you'd like to use (try_splits). +// It returns the number of splits (threads) that you can call it with. +/// It might be less if the image resize can't be split up that many ways. + +STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int try_splits ); + +// This function does a split of the resizing (you call this fuction for each +// split, on multiple threads). A split is a piece of the output resize pixel space. + +// Note that you MUST call stbir_build_samplers_with_splits before stbir_resize_extended_split! + +// Usually, you will always call stbir_resize_split with split_start as the thread_index +// and "1" for the split_count. +// But, if you have a weird situation where you MIGHT want 8 threads, but sometimes +// only 4 threads, you can use 0,2,4,6 for the split_start's and use "2" for the +// split_count each time to turn in into a 4 thread resize. (This is unusual). + +STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start, int split_count ); +//=============================================================== + + +//=============================================================== +// Pixel Callbacks info: +//-------------------------------- + +// The input callback is super flexible - it calls you with the input address +// (based on the stride and base pointer), it gives you an optional_output +// pointer that you can fill, or you can just return your own pointer into +// your own data. +// +// You can also do conversion from non-supported data types if necessary - in +// this case, you ignore the input_ptr and just use the x and y parameters to +// calculate your own input_ptr based on the size of each non-supported pixel. +// (Something like the third example below.) +// +// You can also install just an input or just an output callback by setting the +// callback that you don't want to zero. +// +// First example, progress: (getting a callback that you can monitor the progress): +// void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ) +// { +// percentage_done = y / input_height; +// return input_ptr; // use buffer from call +// } +// +// Next example, copying: (copy from some other buffer or stream): +// void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ) +// { +// CopyOrStreamData( optional_output, other_data_src, num_pixels * pixel_width_in_bytes ); +// return optional_output; // return the optional buffer that we filled +// } +// +// Third example, input another buffer without copying: (zero-copy from other buffer): +// void const * my_callback( void * optional_output, void const * input_ptr, int num_pixels, int x, int y, void * context ) +// { +// void * pixels = ( (char*) other_image_base ) + ( y * other_image_stride ) + ( x * other_pixel_width_in_bytes ); +// return pixels; // return pointer to your data without copying +// } +// +// +// The output callback is considerably simpler - it just calls you so that you can dump +// out each scanline. You could even directly copy out to disk if you have a simple format +// like TGA or BMP. You can also convert to other output types here if you want. +// +// Simple example: +// void const * my_output( void * output_ptr, int num_pixels, int y, void * context ) +// { +// percentage_done = y / output_height; +// fwrite( output_ptr, pixel_width_in_bytes, num_pixels, output_file ); +// } +//=============================================================== + + + + +//=============================================================== +// optional built-in profiling API +//-------------------------------- + +#ifdef STBIR_PROFILE + +typedef struct STBIR_PROFILE_INFO +{ + stbir_uint64 total_clocks; + + // how many clocks spent (of total_clocks) in the various resize routines, along with a string description + // there are "resize_count" number of zones + stbir_uint64 clocks[ 8 ]; + char const ** descriptions; + + // count of clocks and descriptions + stbir_uint32 count; +} STBIR_PROFILE_INFO; + +// use after calling stbir_resize_extended (or stbir_build_samplers or stbir_build_samplers_with_splits) +STBIRDEF void stbir_resize_build_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize ); + +// use after calling stbir_resize_extended +STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize ); + +// use after calling stbir_resize_extended_split +STBIRDEF void stbir_resize_split_profile_info( STBIR_PROFILE_INFO * out_info, STBIR_RESIZE const * resize, int split_start, int split_num ); + +//=============================================================== + +#endif + + +//// end header file ///////////////////////////////////////////////////// +#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE2_H + +#if defined(STB_IMAGE_RESIZE_IMPLEMENTATION) || defined(STB_IMAGE_RESIZE2_IMPLEMENTATION) + +#ifndef STBIR_ASSERT +#include +#define STBIR_ASSERT(x) assert(x) +#endif + +#ifndef STBIR_MALLOC +#include +#define STBIR_MALLOC(size,user_data) ((void)(user_data), malloc(size)) +#define STBIR_FREE(ptr,user_data) ((void)(user_data), free(ptr)) +// (we used the comma operator to evaluate user_data, to avoid "unused parameter" warnings) +#endif + +#ifdef _MSC_VER + +#define stbir__inline __forceinline + +#else + +#define stbir__inline __inline__ + +// Clang address sanitizer +#if defined(__has_feature) + #if __has_feature(address_sanitizer) || __has_feature(memory_sanitizer) + #ifndef STBIR__SEPARATE_ALLOCATIONS + #define STBIR__SEPARATE_ALLOCATIONS + #endif + #endif +#endif + +#endif + +// GCC and MSVC +#if defined(__SANITIZE_ADDRESS__) + #ifndef STBIR__SEPARATE_ALLOCATIONS + #define STBIR__SEPARATE_ALLOCATIONS + #endif +#endif + +// Always turn off automatic FMA use - use STBIR_USE_FMA if you want. +// Otherwise, this is a determinism disaster. +#ifndef STBIR_DONT_CHANGE_FP_CONTRACT // override in case you don't want this behavior +#if defined(_MSC_VER) && !defined(__clang__) +#if _MSC_VER > 1200 +#pragma fp_contract(off) +#endif +#elif defined(__GNUC__) && !defined(__clang__) +#pragma GCC optimize("fp-contract=off") +#else +#pragma STDC FP_CONTRACT OFF +#endif +#endif + +#ifdef _MSC_VER +#define STBIR__UNUSED(v) (void)(v) +#else +#define STBIR__UNUSED(v) (void)sizeof(v) +#endif + +#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0])) + + +#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE +#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM +#endif + +#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE +#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL +#endif + + +#ifndef STBIR__HEADER_FILENAME +#define STBIR__HEADER_FILENAME "stb_image_resize2.h" +#endif + +// the internal pixel layout enums are in a different order, so we can easily do range comparisons of types +// the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible +typedef enum +{ + STBIRI_1CHANNEL = 0, + STBIRI_2CHANNEL = 1, + STBIRI_RGB = 2, + STBIRI_BGR = 3, + STBIRI_4CHANNEL = 4, + + STBIRI_RGBA = 5, + STBIRI_BGRA = 6, + STBIRI_ARGB = 7, + STBIRI_ABGR = 8, + STBIRI_RA = 9, + STBIRI_AR = 10, + + STBIRI_RGBA_PM = 11, + STBIRI_BGRA_PM = 12, + STBIRI_ARGB_PM = 13, + STBIRI_ABGR_PM = 14, + STBIRI_RA_PM = 15, + STBIRI_AR_PM = 16, +} stbir_internal_pixel_layout; + +// define the public pixel layouts to not compile inside the implementation (to avoid accidental use) +#define STBIR_BGR bad_dont_use_in_implementation +#define STBIR_1CHANNEL STBIR_BGR +#define STBIR_2CHANNEL STBIR_BGR +#define STBIR_RGB STBIR_BGR +#define STBIR_RGBA STBIR_BGR +#define STBIR_4CHANNEL STBIR_BGR +#define STBIR_BGRA STBIR_BGR +#define STBIR_ARGB STBIR_BGR +#define STBIR_ABGR STBIR_BGR +#define STBIR_RA STBIR_BGR +#define STBIR_AR STBIR_BGR +#define STBIR_RGBA_PM STBIR_BGR +#define STBIR_BGRA_PM STBIR_BGR +#define STBIR_ARGB_PM STBIR_BGR +#define STBIR_ABGR_PM STBIR_BGR +#define STBIR_RA_PM STBIR_BGR +#define STBIR_AR_PM STBIR_BGR + +// must match stbir_datatype +static unsigned char stbir__type_size[] = { + 1,1,1,2,4,2 // STBIR_TYPE_UINT8,STBIR_TYPE_UINT8_SRGB,STBIR_TYPE_UINT8_SRGB_ALPHA,STBIR_TYPE_UINT16,STBIR_TYPE_FLOAT,STBIR_TYPE_HALF_FLOAT +}; + +// When gathering, the contributors are which source pixels contribute. +// When scattering, the contributors are which destination pixels are contributed to. +typedef struct +{ + int n0; // First contributing pixel + int n1; // Last contributing pixel +} stbir__contributors; + +typedef struct +{ + int lowest; // First sample index for whole filter + int highest; // Last sample index for whole filter + int widest; // widest single set of samples for an output +} stbir__filter_extent_info; + +typedef struct +{ + int n0; // First pixel of decode buffer to write to + int n1; // Last pixel of decode that will be written to + int pixel_offset_for_input; // Pixel offset into input_scanline +} stbir__span; + +typedef struct stbir__scale_info +{ + int input_full_size; + int output_sub_size; + float scale; + float inv_scale; + float pixel_shift; // starting shift in output pixel space (in pixels) + int scale_is_rational; + stbir_uint32 scale_numerator, scale_denominator; +} stbir__scale_info; + +typedef struct +{ + stbir__contributors * contributors; + float* coefficients; + stbir__contributors * gather_prescatter_contributors; + float * gather_prescatter_coefficients; + stbir__scale_info scale_info; + float support; + stbir_filter filter_enum; + stbir__kernel_callback * filter_kernel; + stbir__support_callback * filter_support; + stbir_edge edge; + int coefficient_width; + int filter_pixel_width; + int filter_pixel_margin; + int num_contributors; + int contributors_size; + int coefficients_size; + stbir__filter_extent_info extent_info; + int is_gather; // 0 = scatter, 1 = gather with scale >= 1, 2 = gather with scale < 1 + int gather_prescatter_num_contributors; + int gather_prescatter_coefficient_width; + int gather_prescatter_contributors_size; + int gather_prescatter_coefficients_size; +} stbir__sampler; + +typedef struct +{ + stbir__contributors conservative; + int edge_sizes[2]; // this can be less than filter_pixel_margin, if the filter and scaling falls off + stbir__span spans[2]; // can be two spans, if doing input subrect with clamp mode WRAP +} stbir__extents; + +typedef struct +{ +#ifdef STBIR_PROFILE + union + { + struct { stbir_uint64 total, looping, vertical, horizontal, decode, encode, alpha, unalpha; } named; + stbir_uint64 array[8]; + } profile; + stbir_uint64 * current_zone_excluded_ptr; +#endif + float* decode_buffer; + + int ring_buffer_first_scanline; + int ring_buffer_last_scanline; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer + int start_output_y, end_output_y; + int start_input_y, end_input_y; // used in scatter only + + #ifdef STBIR__SEPARATE_ALLOCATIONS + float** ring_buffers; // one pointer for each ring buffer + #else + float* ring_buffer; // one big buffer that we index into + #endif + + float* vertical_buffer; + + char no_cache_straddle[64]; +} stbir__per_split_info; + +typedef void stbir__decode_pixels_func( float * decode, int width_times_channels, void const * input ); +typedef void stbir__alpha_weight_func( float * decode_buffer, int width_times_channels ); +typedef void stbir__horizontal_gather_channels_func( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, + stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ); +typedef void stbir__alpha_unweight_func(float * encode_buffer, int width_times_channels ); +typedef void stbir__encode_pixels_func( void * output, int width_times_channels, float const * encode ); + +struct stbir__info +{ +#ifdef STBIR_PROFILE + union + { + struct { stbir_uint64 total, build, alloc, horizontal, vertical, cleanup, pivot; } named; + stbir_uint64 array[7]; + } profile; + stbir_uint64 * current_zone_excluded_ptr; +#endif + stbir__sampler horizontal; + stbir__sampler vertical; + + void const * input_data; + void * output_data; + + int input_stride_bytes; + int output_stride_bytes; + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. + + stbir_datatype input_type; + stbir_datatype output_type; + + stbir_input_callback * in_pixels_cb; + void * user_data; + stbir_output_callback * out_pixels_cb; + + stbir__extents scanline_extents; + + void * alloced_mem; + stbir__per_split_info * split_info; // by default 1, but there will be N of these allocated based on the thread init you did + + stbir__decode_pixels_func * decode_pixels; + stbir__alpha_weight_func * alpha_weight; + stbir__horizontal_gather_channels_func * horizontal_gather_channels; + stbir__alpha_unweight_func * alpha_unweight; + stbir__encode_pixels_func * encode_pixels; + + int alloc_ring_buffer_num_entries; // Number of entries in the ring buffer that will be allocated + int splits; // count of splits + + stbir_internal_pixel_layout input_pixel_layout_internal; + stbir_internal_pixel_layout output_pixel_layout_internal; + + int input_color_and_type; + int offset_x, offset_y; // offset within output_data + int vertical_first; + int channels; + int effective_channels; // same as channels, except on RGBA/ARGB (7), or XA/AX (3) + size_t alloced_total; +}; + + +#define stbir__max_uint8_as_float 255.0f +#define stbir__max_uint16_as_float 65535.0f +#define stbir__max_uint8_as_float_inverted (1.0f/255.0f) +#define stbir__max_uint16_as_float_inverted (1.0f/65535.0f) +#define stbir__small_float ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) + +// min/max friendly +#define STBIR_CLAMP(x, xmin, xmax) for(;;) { \ + if ( (x) < (xmin) ) (x) = (xmin); \ + if ( (x) > (xmax) ) (x) = (xmax); \ + break; \ +} + +static stbir__inline int stbir__min(int a, int b) +{ + return a < b ? a : b; +} + +static stbir__inline int stbir__max(int a, int b) +{ + return a > b ? a : b; +} + +static float stbir__srgb_uchar_to_linear_float[256] = { + 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f, + 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f, + 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f, + 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, + 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f, + 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, + 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f, + 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, + 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f, + 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f, + 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, + 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f, + 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, + 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f, + 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f, + 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f, + 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f, + 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f, + 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f, + 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, + 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f, + 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, + 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f, + 0.982251f, 0.991102f, 1.0f +}; + +typedef union +{ + unsigned int u; + float f; +} stbir__FP32; + +// From https://gist.github.com/rygorous/2203834 + +static const stbir_uint32 fp32_to_srgb8_tab4[104] = { + 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d, + 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a, + 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033, + 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067, + 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5, + 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2, + 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143, + 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af, + 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240, + 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300, + 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401, + 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, + 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, +}; + +static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in) +{ + static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps + static const stbir__FP32 minval = { (127-13) << 23 }; + stbir_uint32 tab,bias,scale,t; + stbir__FP32 f; + + // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + // The tests are carefully written so that NaNs map to 0, same as in the reference + // implementation. + if (!(in > minval.f)) // written this way to catch NaNs + return 0; + if (in > almostone.f) + return 255; + + // Do the table lookup and unpack bias, scale + f.f = in; + tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + // Grab next-highest mantissa bits and perform linear interpolation + t = (f.u >> 12) & 0xff; + return (unsigned char) ((bias + scale*t) >> 16); +} + +#ifndef STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT +#define STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT 32 // when downsampling and <= 32 scanlines of buffering, use gather. gather used down to 1/8th scaling for 25% win. +#endif + +#ifndef STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS +#define STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS 4 // when threading, what is the minimum number of scanlines for a split? +#endif + +// restrict pointers for the output pointers, other loop and unroll control +#if defined( _MSC_VER ) && !defined(__clang__) + #define STBIR_STREAMOUT_PTR( star ) star __restrict + #define STBIR_NO_UNROLL( ptr ) __assume(ptr) // this oddly keeps msvc from unrolling a loop + #if _MSC_VER >= 1900 + #define STBIR_NO_UNROLL_LOOP_START __pragma(loop( no_vector )) + #else + #define STBIR_NO_UNROLL_LOOP_START + #endif +#elif defined( __clang__ ) + #define STBIR_STREAMOUT_PTR( star ) star __restrict__ + #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr)) + #if ( __clang_major__ >= 4 ) || ( ( __clang_major__ >= 3 ) && ( __clang_minor__ >= 5 ) ) + #define STBIR_NO_UNROLL_LOOP_START _Pragma("clang loop unroll(disable)") _Pragma("clang loop vectorize(disable)") + #else + #define STBIR_NO_UNROLL_LOOP_START + #endif +#elif defined( __GNUC__ ) + #define STBIR_STREAMOUT_PTR( star ) star __restrict__ + #define STBIR_NO_UNROLL( ptr ) __asm__ (""::"r"(ptr)) + #if __GNUC__ >= 14 + #define STBIR_NO_UNROLL_LOOP_START _Pragma("GCC unroll 0") _Pragma("GCC novector") + #else + #define STBIR_NO_UNROLL_LOOP_START + #endif + #define STBIR_NO_UNROLL_LOOP_START_INF_FOR +#else + #define STBIR_STREAMOUT_PTR( star ) star + #define STBIR_NO_UNROLL( ptr ) + #define STBIR_NO_UNROLL_LOOP_START +#endif + +#ifndef STBIR_NO_UNROLL_LOOP_START_INF_FOR +#define STBIR_NO_UNROLL_LOOP_START_INF_FOR STBIR_NO_UNROLL_LOOP_START +#endif + +#ifdef STBIR_NO_SIMD // force simd off for whatever reason + +// force simd off overrides everything else, so clear it all + +#ifdef STBIR_SSE2 +#undef STBIR_SSE2 +#endif + +#ifdef STBIR_AVX +#undef STBIR_AVX +#endif + +#ifdef STBIR_NEON +#undef STBIR_NEON +#endif + +#ifdef STBIR_AVX2 +#undef STBIR_AVX2 +#endif + +#ifdef STBIR_FP16C +#undef STBIR_FP16C +#endif + +#ifdef STBIR_WASM +#undef STBIR_WASM +#endif + +#ifdef STBIR_SIMD +#undef STBIR_SIMD +#endif + +#else // STBIR_SIMD + +#ifdef STBIR_SSE2 + #include + + #define stbir__simdf __m128 + #define stbir__simdi __m128i + + #define stbir_simdi_castf( reg ) _mm_castps_si128(reg) + #define stbir_simdf_casti( reg ) _mm_castsi128_ps(reg) + + #define stbir__simdf_load( reg, ptr ) (reg) = _mm_loadu_ps( (float const*)(ptr) ) + #define stbir__simdi_load( reg, ptr ) (reg) = _mm_loadu_si128 ( (stbir__simdi const*)(ptr) ) + #define stbir__simdf_load1( out, ptr ) (out) = _mm_load_ss( (float const*)(ptr) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdi_load1( out, ptr ) (out) = _mm_castps_si128( _mm_load_ss( (float const*)(ptr) )) + #define stbir__simdf_load1z( out, ptr ) (out) = _mm_load_ss( (float const*)(ptr) ) // top values must be zero + #define stbir__simdf_frep4( fvar ) _mm_set_ps1( fvar ) + #define stbir__simdf_load1frep4( out, fvar ) (out) = _mm_set_ps1( fvar ) + #define stbir__simdf_load2( out, ptr ) (out) = _mm_castsi128_ps( _mm_loadl_epi64( (__m128i*)(ptr)) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdf_load2z( out, ptr ) (out) = _mm_castsi128_ps( _mm_loadl_epi64( (__m128i*)(ptr)) ) // top values must be zero + #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = _mm_castpd_ps(_mm_loadh_pd( _mm_castps_pd(reg), (double*)(ptr) )) + + #define stbir__simdf_zeroP() _mm_setzero_ps() + #define stbir__simdf_zero( reg ) (reg) = _mm_setzero_ps() + + #define stbir__simdf_store( ptr, reg ) _mm_storeu_ps( (float*)(ptr), reg ) + #define stbir__simdf_store1( ptr, reg ) _mm_store_ss( (float*)(ptr), reg ) + #define stbir__simdf_store2( ptr, reg ) _mm_storel_epi64( (__m128i*)(ptr), _mm_castps_si128(reg) ) + #define stbir__simdf_store2h( ptr, reg ) _mm_storeh_pd( (double*)(ptr), _mm_castps_pd(reg) ) + + #define stbir__simdi_store( ptr, reg ) _mm_storeu_si128( (__m128i*)(ptr), reg ) + #define stbir__simdi_store1( ptr, reg ) _mm_store_ss( (float*)(ptr), _mm_castsi128_ps(reg) ) + #define stbir__simdi_store2( ptr, reg ) _mm_storel_epi64( (__m128i*)(ptr), (reg) ) + + #define stbir__prefetch( ptr ) _mm_prefetch((char*)(ptr), _MM_HINT_T0 ) + + #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \ + { \ + stbir__simdi zero = _mm_setzero_si128(); \ + out2 = _mm_unpacklo_epi8( ireg, zero ); \ + out3 = _mm_unpackhi_epi8( ireg, zero ); \ + out0 = _mm_unpacklo_epi16( out2, zero ); \ + out1 = _mm_unpackhi_epi16( out2, zero ); \ + out2 = _mm_unpacklo_epi16( out3, zero ); \ + out3 = _mm_unpackhi_epi16( out3, zero ); \ + } + +#define stbir__simdi_expand_u8_to_1u32(out,ireg) \ + { \ + stbir__simdi zero = _mm_setzero_si128(); \ + out = _mm_unpacklo_epi8( ireg, zero ); \ + out = _mm_unpacklo_epi16( out, zero ); \ + } + + #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \ + { \ + stbir__simdi zero = _mm_setzero_si128(); \ + out0 = _mm_unpacklo_epi16( ireg, zero ); \ + out1 = _mm_unpackhi_epi16( ireg, zero ); \ + } + + #define stbir__simdf_convert_float_to_i32( i, f ) (i) = _mm_cvttps_epi32(f) + #define stbir__simdf_convert_float_to_int( f ) _mm_cvtt_ss2si(f) + #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)_mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(f,STBIR__CONSTF(STBIR_max_uint8_as_float)),_mm_setzero_ps())))) + #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)_mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(f,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())))) + + #define stbir__simdi_to_int( i ) _mm_cvtsi128_si32(i) + #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = _mm_cvtepi32_ps( ireg ) + #define stbir__simdf_add( out, reg0, reg1 ) (out) = _mm_add_ps( reg0, reg1 ) + #define stbir__simdf_mult( out, reg0, reg1 ) (out) = _mm_mul_ps( reg0, reg1 ) + #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = _mm_mul_ps( reg, _mm_loadu_ps( (float const*)(ptr) ) ) + #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = _mm_mul_ss( reg, _mm_load_ss( (float const*)(ptr) ) ) + #define stbir__simdf_add_mem( out, reg, ptr ) (out) = _mm_add_ps( reg, _mm_loadu_ps( (float const*)(ptr) ) ) + #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = _mm_add_ss( reg, _mm_load_ss( (float const*)(ptr) ) ) + + #ifdef STBIR_USE_FMA // not on by default to maintain bit identical simd to non-simd + #include + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = _mm_fmadd_ps( mul1, mul2, add ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = _mm_fmadd_ss( mul1, mul2, add ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = _mm_fmadd_ps( mul, _mm_loadu_ps( (float const*)(ptr) ), add ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = _mm_fmadd_ss( mul, _mm_load_ss( (float const*)(ptr) ), add ) + #else + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = _mm_add_ps( add, _mm_mul_ps( mul1, mul2 ) ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = _mm_add_ss( add, _mm_mul_ss( mul1, mul2 ) ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = _mm_add_ps( add, _mm_mul_ps( mul, _mm_loadu_ps( (float const*)(ptr) ) ) ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = _mm_add_ss( add, _mm_mul_ss( mul, _mm_load_ss( (float const*)(ptr) ) ) ) + #endif + + #define stbir__simdf_add1( out, reg0, reg1 ) (out) = _mm_add_ss( reg0, reg1 ) + #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = _mm_mul_ss( reg0, reg1 ) + + #define stbir__simdf_and( out, reg0, reg1 ) (out) = _mm_and_ps( reg0, reg1 ) + #define stbir__simdf_or( out, reg0, reg1 ) (out) = _mm_or_ps( reg0, reg1 ) + + #define stbir__simdf_min( out, reg0, reg1 ) (out) = _mm_min_ps( reg0, reg1 ) + #define stbir__simdf_max( out, reg0, reg1 ) (out) = _mm_max_ps( reg0, reg1 ) + #define stbir__simdf_min1( out, reg0, reg1 ) (out) = _mm_min_ss( reg0, reg1 ) + #define stbir__simdf_max1( out, reg0, reg1 ) (out) = _mm_max_ss( reg0, reg1 ) + + #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_shuffle_ps( reg1,reg0, (0<<0) + (1<<2) + (2<<4) + (3<<6) )), (3<<0) + (0<<2) + (1<<4) + (2<<6) ) ) + #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_shuffle_ps( reg1,reg0, (0<<0) + (1<<2) + (2<<4) + (3<<6) )), (2<<0) + (3<<2) + (0<<4) + (1<<6) ) ) + + static const stbir__simdf STBIR_zeroones = { 0.0f,1.0f,0.0f,1.0f }; + static const stbir__simdf STBIR_onezeros = { 1.0f,0.0f,1.0f,0.0f }; + #define stbir__simdf_aaa1( out, alp, ones ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_movehl_ps( ones, alp ) ), (1<<0) + (1<<2) + (1<<4) + (2<<6) ) ) + #define stbir__simdf_1aaa( out, alp, ones ) (out)=_mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( _mm_movelh_ps( ones, alp ) ), (0<<0) + (2<<2) + (2<<4) + (2<<6) ) ) + #define stbir__simdf_a1a1( out, alp, ones) (out) = _mm_or_ps( _mm_castsi128_ps( _mm_srli_epi64( _mm_castps_si128(alp), 32 ) ), STBIR_zeroones ) + #define stbir__simdf_1a1a( out, alp, ones) (out) = _mm_or_ps( _mm_castsi128_ps( _mm_slli_epi64( _mm_castps_si128(alp), 32 ) ), STBIR_onezeros ) + + #define stbir__simdf_swiz( reg, one, two, three, four ) _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( reg ), (one<<0) + (two<<2) + (three<<4) + (four<<6) ) ) + + #define stbir__simdi_and( out, reg0, reg1 ) (out) = _mm_and_si128( reg0, reg1 ) + #define stbir__simdi_or( out, reg0, reg1 ) (out) = _mm_or_si128( reg0, reg1 ) + #define stbir__simdi_16madd( out, reg0, reg1 ) (out) = _mm_madd_epi16( reg0, reg1 ) + + #define stbir__simdf_pack_to_8bytes(out,aa,bb) \ + { \ + stbir__simdf af,bf; \ + stbir__simdi a,b; \ + af = _mm_min_ps( aa, STBIR_max_uint8_as_float ); \ + bf = _mm_min_ps( bb, STBIR_max_uint8_as_float ); \ + af = _mm_max_ps( af, _mm_setzero_ps() ); \ + bf = _mm_max_ps( bf, _mm_setzero_ps() ); \ + a = _mm_cvttps_epi32( af ); \ + b = _mm_cvttps_epi32( bf ); \ + a = _mm_packs_epi32( a, b ); \ + out = _mm_packus_epi16( a, a ); \ + } + + #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \ + stbir__simdf_load( o0, (ptr) ); \ + stbir__simdf_load( o1, (ptr)+4 ); \ + stbir__simdf_load( o2, (ptr)+8 ); \ + stbir__simdf_load( o3, (ptr)+12 ); \ + { \ + __m128 tmp0, tmp1, tmp2, tmp3; \ + tmp0 = _mm_unpacklo_ps(o0, o1); \ + tmp2 = _mm_unpacklo_ps(o2, o3); \ + tmp1 = _mm_unpackhi_ps(o0, o1); \ + tmp3 = _mm_unpackhi_ps(o2, o3); \ + o0 = _mm_movelh_ps(tmp0, tmp2); \ + o1 = _mm_movehl_ps(tmp2, tmp0); \ + o2 = _mm_movelh_ps(tmp1, tmp3); \ + o3 = _mm_movehl_ps(tmp3, tmp1); \ + } + + #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \ + r0 = _mm_packs_epi32( r0, r1 ); \ + r2 = _mm_packs_epi32( r2, r3 ); \ + r1 = _mm_unpacklo_epi16( r0, r2 ); \ + r3 = _mm_unpackhi_epi16( r0, r2 ); \ + r0 = _mm_unpacklo_epi16( r1, r3 ); \ + r2 = _mm_unpackhi_epi16( r1, r3 ); \ + r0 = _mm_packus_epi16( r0, r2 ); \ + stbir__simdi_store( ptr, r0 ); \ + + #define stbir__simdi_32shr( out, reg, imm ) out = _mm_srli_epi32( reg, imm ) + + #if defined(_MSC_VER) && !defined(__clang__) + // msvc inits with 8 bytes + #define STBIR__CONST_32_TO_8( v ) (char)(unsigned char)((v)&255),(char)(unsigned char)(((v)>>8)&255),(char)(unsigned char)(((v)>>16)&255),(char)(unsigned char)(((v)>>24)&255) + #define STBIR__CONST_4_32i( v ) STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ), STBIR__CONST_32_TO_8( v ) + #define STBIR__CONST_4d_32i( v0, v1, v2, v3 ) STBIR__CONST_32_TO_8( v0 ), STBIR__CONST_32_TO_8( v1 ), STBIR__CONST_32_TO_8( v2 ), STBIR__CONST_32_TO_8( v3 ) + #else + // everything else inits with long long's + #define STBIR__CONST_4_32i( v ) (long long)((((stbir_uint64)(stbir_uint32)(v))<<32)|((stbir_uint64)(stbir_uint32)(v))),(long long)((((stbir_uint64)(stbir_uint32)(v))<<32)|((stbir_uint64)(stbir_uint32)(v))) + #define STBIR__CONST_4d_32i( v0, v1, v2, v3 ) (long long)((((stbir_uint64)(stbir_uint32)(v1))<<32)|((stbir_uint64)(stbir_uint32)(v0))),(long long)((((stbir_uint64)(stbir_uint32)(v3))<<32)|((stbir_uint64)(stbir_uint32)(v2))) + #endif + + #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = { x, x, x, x } + #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { STBIR__CONST_4_32i(x) } + #define STBIR__CONSTF(var) (var) + #define STBIR__CONSTI(var) (var) + + #if defined(STBIR_AVX) || defined(__SSE4_1__) + #include + #define stbir__simdf_pack_to_8words(out,reg0,reg1) out = _mm_packus_epi32(_mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg0,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())), _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg1,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps()))) + #else + STBIRDEF STBIR__SIMDI_CONST(stbir__s32_32768, 32768); + STBIRDEF STBIR__SIMDI_CONST(stbir__s16_32768, ((32768<<16)|32768)); + + #define stbir__simdf_pack_to_8words(out,reg0,reg1) \ + { \ + stbir__simdi tmp0,tmp1; \ + tmp0 = _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg0,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())); \ + tmp1 = _mm_cvttps_epi32(_mm_max_ps(_mm_min_ps(reg1,STBIR__CONSTF(STBIR_max_uint16_as_float)),_mm_setzero_ps())); \ + tmp0 = _mm_sub_epi32( tmp0, stbir__s32_32768 ); \ + tmp1 = _mm_sub_epi32( tmp1, stbir__s32_32768 ); \ + out = _mm_packs_epi32( tmp0, tmp1 ); \ + out = _mm_sub_epi16( out, stbir__s16_32768 ); \ + } + + #endif + + #define STBIR_SIMD + + // if we detect AVX, set the simd8 defines + #ifdef STBIR_AVX + #include + #define STBIR_SIMD8 + #define stbir__simdf8 __m256 + #define stbir__simdi8 __m256i + #define stbir__simdf8_load( out, ptr ) (out) = _mm256_loadu_ps( (float const *)(ptr) ) + #define stbir__simdi8_load( out, ptr ) (out) = _mm256_loadu_si256( (__m256i const *)(ptr) ) + #define stbir__simdf8_mult( out, a, b ) (out) = _mm256_mul_ps( (a), (b) ) + #define stbir__simdf8_store( ptr, out ) _mm256_storeu_ps( (float*)(ptr), out ) + #define stbir__simdi8_store( ptr, reg ) _mm256_storeu_si256( (__m256i*)(ptr), reg ) + #define stbir__simdf8_frep8( fval ) _mm256_set1_ps( fval ) + + #define stbir__simdf8_min( out, reg0, reg1 ) (out) = _mm256_min_ps( reg0, reg1 ) + #define stbir__simdf8_max( out, reg0, reg1 ) (out) = _mm256_max_ps( reg0, reg1 ) + + #define stbir__simdf8_add4halves( out, bot4, top8 ) (out) = _mm_add_ps( bot4, _mm256_extractf128_ps( top8, 1 ) ) + #define stbir__simdf8_mult_mem( out, reg, ptr ) (out) = _mm256_mul_ps( reg, _mm256_loadu_ps( (float const*)(ptr) ) ) + #define stbir__simdf8_add_mem( out, reg, ptr ) (out) = _mm256_add_ps( reg, _mm256_loadu_ps( (float const*)(ptr) ) ) + #define stbir__simdf8_add( out, a, b ) (out) = _mm256_add_ps( a, b ) + #define stbir__simdf8_load1b( out, ptr ) (out) = _mm256_broadcast_ss( ptr ) + #define stbir__simdf_load1rep4( out, ptr ) (out) = _mm_broadcast_ss( ptr ) // avx load instruction + + #define stbir__simdi8_convert_i32_to_float(out, ireg) (out) = _mm256_cvtepi32_ps( ireg ) + #define stbir__simdf8_convert_float_to_i32( i, f ) (i) = _mm256_cvttps_epi32(f) + + #define stbir__simdf8_bot4s( out, a, b ) (out) = _mm256_permute2f128_ps(a,b, (0<<0)+(2<<4) ) + #define stbir__simdf8_top4s( out, a, b ) (out) = _mm256_permute2f128_ps(a,b, (1<<0)+(3<<4) ) + + #define stbir__simdf8_gettop4( reg ) _mm256_extractf128_ps(reg,1) + + #ifdef STBIR_AVX2 + + #define stbir__simdi8_expand_u8_to_u32(out0,out1,ireg) \ + { \ + stbir__simdi8 a, zero =_mm256_setzero_si256();\ + a = _mm256_permute4x64_epi64( _mm256_unpacklo_epi8( _mm256_permute4x64_epi64(_mm256_castsi128_si256(ireg),(0<<0)+(2<<2)+(1<<4)+(3<<6)), zero ),(0<<0)+(2<<2)+(1<<4)+(3<<6)); \ + out0 = _mm256_unpacklo_epi16( a, zero ); \ + out1 = _mm256_unpackhi_epi16( a, zero ); \ + } + + #define stbir__simdf8_pack_to_16bytes(out,aa,bb) \ + { \ + stbir__simdi8 t; \ + stbir__simdf8 af,bf; \ + stbir__simdi8 a,b; \ + af = _mm256_min_ps( aa, STBIR_max_uint8_as_floatX ); \ + bf = _mm256_min_ps( bb, STBIR_max_uint8_as_floatX ); \ + af = _mm256_max_ps( af, _mm256_setzero_ps() ); \ + bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \ + a = _mm256_cvttps_epi32( af ); \ + b = _mm256_cvttps_epi32( bf ); \ + t = _mm256_permute4x64_epi64( _mm256_packs_epi32( a, b ), (0<<0)+(2<<2)+(1<<4)+(3<<6) ); \ + out = _mm256_castsi256_si128( _mm256_permute4x64_epi64( _mm256_packus_epi16( t, t ), (0<<0)+(2<<2)+(1<<4)+(3<<6) ) ); \ + } + + #define stbir__simdi8_expand_u16_to_u32(out,ireg) out = _mm256_unpacklo_epi16( _mm256_permute4x64_epi64(_mm256_castsi128_si256(ireg),(0<<0)+(2<<2)+(1<<4)+(3<<6)), _mm256_setzero_si256() ); + + #define stbir__simdf8_pack_to_16words(out,aa,bb) \ + { \ + stbir__simdf8 af,bf; \ + stbir__simdi8 a,b; \ + af = _mm256_min_ps( aa, STBIR_max_uint16_as_floatX ); \ + bf = _mm256_min_ps( bb, STBIR_max_uint16_as_floatX ); \ + af = _mm256_max_ps( af, _mm256_setzero_ps() ); \ + bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \ + a = _mm256_cvttps_epi32( af ); \ + b = _mm256_cvttps_epi32( bf ); \ + (out) = _mm256_permute4x64_epi64( _mm256_packus_epi32(a, b), (0<<0)+(2<<2)+(1<<4)+(3<<6) ); \ + } + + #else + + #define stbir__simdi8_expand_u8_to_u32(out0,out1,ireg) \ + { \ + stbir__simdi a,zero = _mm_setzero_si128(); \ + a = _mm_unpacklo_epi8( ireg, zero ); \ + out0 = _mm256_setr_m128i( _mm_unpacklo_epi16( a, zero ), _mm_unpackhi_epi16( a, zero ) ); \ + a = _mm_unpackhi_epi8( ireg, zero ); \ + out1 = _mm256_setr_m128i( _mm_unpacklo_epi16( a, zero ), _mm_unpackhi_epi16( a, zero ) ); \ + } + + #define stbir__simdf8_pack_to_16bytes(out,aa,bb) \ + { \ + stbir__simdi t; \ + stbir__simdf8 af,bf; \ + stbir__simdi8 a,b; \ + af = _mm256_min_ps( aa, STBIR_max_uint8_as_floatX ); \ + bf = _mm256_min_ps( bb, STBIR_max_uint8_as_floatX ); \ + af = _mm256_max_ps( af, _mm256_setzero_ps() ); \ + bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \ + a = _mm256_cvttps_epi32( af ); \ + b = _mm256_cvttps_epi32( bf ); \ + out = _mm_packs_epi32( _mm256_castsi256_si128(a), _mm256_extractf128_si256( a, 1 ) ); \ + out = _mm_packus_epi16( out, out ); \ + t = _mm_packs_epi32( _mm256_castsi256_si128(b), _mm256_extractf128_si256( b, 1 ) ); \ + t = _mm_packus_epi16( t, t ); \ + out = _mm_castps_si128( _mm_shuffle_ps( _mm_castsi128_ps(out), _mm_castsi128_ps(t), (0<<0)+(1<<2)+(0<<4)+(1<<6) ) ); \ + } + + #define stbir__simdi8_expand_u16_to_u32(out,ireg) \ + { \ + stbir__simdi a,b,zero = _mm_setzero_si128(); \ + a = _mm_unpacklo_epi16( ireg, zero ); \ + b = _mm_unpackhi_epi16( ireg, zero ); \ + out = _mm256_insertf128_si256( _mm256_castsi128_si256( a ), b, 1 ); \ + } + + #define stbir__simdf8_pack_to_16words(out,aa,bb) \ + { \ + stbir__simdi t0,t1; \ + stbir__simdf8 af,bf; \ + stbir__simdi8 a,b; \ + af = _mm256_min_ps( aa, STBIR_max_uint16_as_floatX ); \ + bf = _mm256_min_ps( bb, STBIR_max_uint16_as_floatX ); \ + af = _mm256_max_ps( af, _mm256_setzero_ps() ); \ + bf = _mm256_max_ps( bf, _mm256_setzero_ps() ); \ + a = _mm256_cvttps_epi32( af ); \ + b = _mm256_cvttps_epi32( bf ); \ + t0 = _mm_packus_epi32( _mm256_castsi256_si128(a), _mm256_extractf128_si256( a, 1 ) ); \ + t1 = _mm_packus_epi32( _mm256_castsi256_si128(b), _mm256_extractf128_si256( b, 1 ) ); \ + out = _mm256_setr_m128i( t0, t1 ); \ + } + + #endif + + static __m256i stbir_00001111 = { STBIR__CONST_4d_32i( 0, 0, 0, 0 ), STBIR__CONST_4d_32i( 1, 1, 1, 1 ) }; + #define stbir__simdf8_0123to00001111( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_00001111 ) + + static __m256i stbir_22223333 = { STBIR__CONST_4d_32i( 2, 2, 2, 2 ), STBIR__CONST_4d_32i( 3, 3, 3, 3 ) }; + #define stbir__simdf8_0123to22223333( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_22223333 ) + + #define stbir__simdf8_0123to2222( out, in ) (out) = stbir__simdf_swiz(_mm256_castps256_ps128(in), 2,2,2,2 ) + + #define stbir__simdf8_load4b( out, ptr ) (out) = _mm256_broadcast_ps( (__m128 const *)(ptr) ) + + static __m256i stbir_00112233 = { STBIR__CONST_4d_32i( 0, 0, 1, 1 ), STBIR__CONST_4d_32i( 2, 2, 3, 3 ) }; + #define stbir__simdf8_0123to00112233( out, in ) (out) = _mm256_permutevar_ps ( in, stbir_00112233 ) + #define stbir__simdf8_add4( out, a8, b ) (out) = _mm256_add_ps( a8, _mm256_castps128_ps256( b ) ) + + static __m256i stbir_load6 = { STBIR__CONST_4_32i( 0x80000000 ), STBIR__CONST_4d_32i( 0x80000000, 0x80000000, 0, 0 ) }; + #define stbir__simdf8_load6z( out, ptr ) (out) = _mm256_maskload_ps( ptr, stbir_load6 ) + + #define stbir__simdf8_0123to00000000( out, in ) (out) = _mm256_shuffle_ps ( in, in, (0<<0)+(0<<2)+(0<<4)+(0<<6) ) + #define stbir__simdf8_0123to11111111( out, in ) (out) = _mm256_shuffle_ps ( in, in, (1<<0)+(1<<2)+(1<<4)+(1<<6) ) + #define stbir__simdf8_0123to22222222( out, in ) (out) = _mm256_shuffle_ps ( in, in, (2<<0)+(2<<2)+(2<<4)+(2<<6) ) + #define stbir__simdf8_0123to33333333( out, in ) (out) = _mm256_shuffle_ps ( in, in, (3<<0)+(3<<2)+(3<<4)+(3<<6) ) + #define stbir__simdf8_0123to21032103( out, in ) (out) = _mm256_shuffle_ps ( in, in, (2<<0)+(1<<2)+(0<<4)+(3<<6) ) + #define stbir__simdf8_0123to32103210( out, in ) (out) = _mm256_shuffle_ps ( in, in, (3<<0)+(2<<2)+(1<<4)+(0<<6) ) + #define stbir__simdf8_0123to12301230( out, in ) (out) = _mm256_shuffle_ps ( in, in, (1<<0)+(2<<2)+(3<<4)+(0<<6) ) + #define stbir__simdf8_0123to10321032( out, in ) (out) = _mm256_shuffle_ps ( in, in, (1<<0)+(0<<2)+(3<<4)+(2<<6) ) + #define stbir__simdf8_0123to30123012( out, in ) (out) = _mm256_shuffle_ps ( in, in, (3<<0)+(0<<2)+(1<<4)+(2<<6) ) + + #define stbir__simdf8_0123to11331133( out, in ) (out) = _mm256_shuffle_ps ( in, in, (1<<0)+(1<<2)+(3<<4)+(3<<6) ) + #define stbir__simdf8_0123to00220022( out, in ) (out) = _mm256_shuffle_ps ( in, in, (0<<0)+(0<<2)+(2<<4)+(2<<6) ) + + #define stbir__simdf8_aaa1( out, alp, ones ) (out) = _mm256_blend_ps( alp, ones, (1<<0)+(1<<1)+(1<<2)+(0<<3)+(1<<4)+(1<<5)+(1<<6)+(0<<7)); (out)=_mm256_shuffle_ps( out,out, (3<<0) + (3<<2) + (3<<4) + (0<<6) ) + #define stbir__simdf8_1aaa( out, alp, ones ) (out) = _mm256_blend_ps( alp, ones, (0<<0)+(1<<1)+(1<<2)+(1<<3)+(0<<4)+(1<<5)+(1<<6)+(1<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (0<<4) + (0<<6) ) + #define stbir__simdf8_a1a1( out, alp, ones) (out) = _mm256_blend_ps( alp, ones, (1<<0)+(0<<1)+(1<<2)+(0<<3)+(1<<4)+(0<<5)+(1<<6)+(0<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (3<<4) + (2<<6) ) + #define stbir__simdf8_1a1a( out, alp, ones) (out) = _mm256_blend_ps( alp, ones, (0<<0)+(1<<1)+(0<<2)+(1<<3)+(0<<4)+(1<<5)+(0<<6)+(1<<7)); (out)=_mm256_shuffle_ps( out,out, (1<<0) + (0<<2) + (3<<4) + (2<<6) ) + + #define stbir__simdf8_zero( reg ) (reg) = _mm256_setzero_ps() + + #ifdef STBIR_USE_FMA // not on by default to maintain bit identical simd to non-simd + #define stbir__simdf8_madd( out, add, mul1, mul2 ) (out) = _mm256_fmadd_ps( mul1, mul2, add ) + #define stbir__simdf8_madd_mem( out, add, mul, ptr ) (out) = _mm256_fmadd_ps( mul, _mm256_loadu_ps( (float const*)(ptr) ), add ) + #define stbir__simdf8_madd_mem4( out, add, mul, ptr )(out) = _mm256_fmadd_ps( _mm256_setr_m128( mul, _mm_setzero_ps() ), _mm256_setr_m128( _mm_loadu_ps( (float const*)(ptr) ), _mm_setzero_ps() ), add ) + #else + #define stbir__simdf8_madd( out, add, mul1, mul2 ) (out) = _mm256_add_ps( add, _mm256_mul_ps( mul1, mul2 ) ) + #define stbir__simdf8_madd_mem( out, add, mul, ptr ) (out) = _mm256_add_ps( add, _mm256_mul_ps( mul, _mm256_loadu_ps( (float const*)(ptr) ) ) ) + #define stbir__simdf8_madd_mem4( out, add, mul, ptr ) (out) = _mm256_add_ps( add, _mm256_setr_m128( _mm_mul_ps( mul, _mm_loadu_ps( (float const*)(ptr) ) ), _mm_setzero_ps() ) ) + #endif + #define stbir__if_simdf8_cast_to_simdf4( val ) _mm256_castps256_ps128( val ) + + #endif + + #ifdef STBIR_FLOORF + #undef STBIR_FLOORF + #endif + #define STBIR_FLOORF stbir_simd_floorf + static stbir__inline float stbir_simd_floorf(float x) // martins floorf + { + #if defined(STBIR_AVX) || defined(__SSE4_1__) || defined(STBIR_SSE41) + __m128 t = _mm_set_ss(x); + return _mm_cvtss_f32( _mm_floor_ss(t, t) ); + #else + __m128 f = _mm_set_ss(x); + __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f)); + __m128 r = _mm_add_ss(t, _mm_and_ps(_mm_cmplt_ss(f, t), _mm_set_ss(-1.0f))); + return _mm_cvtss_f32(r); + #endif + } + + #ifdef STBIR_CEILF + #undef STBIR_CEILF + #endif + #define STBIR_CEILF stbir_simd_ceilf + static stbir__inline float stbir_simd_ceilf(float x) // martins ceilf + { + #if defined(STBIR_AVX) || defined(__SSE4_1__) || defined(STBIR_SSE41) + __m128 t = _mm_set_ss(x); + return _mm_cvtss_f32( _mm_ceil_ss(t, t) ); + #else + __m128 f = _mm_set_ss(x); + __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f)); + __m128 r = _mm_add_ss(t, _mm_and_ps(_mm_cmplt_ss(t, f), _mm_set_ss(1.0f))); + return _mm_cvtss_f32(r); + #endif + } + +#elif defined(STBIR_NEON) + + #include + + #define stbir__simdf float32x4_t + #define stbir__simdi uint32x4_t + + #define stbir_simdi_castf( reg ) vreinterpretq_u32_f32(reg) + #define stbir_simdf_casti( reg ) vreinterpretq_f32_u32(reg) + + #define stbir__simdf_load( reg, ptr ) (reg) = vld1q_f32( (float const*)(ptr) ) + #define stbir__simdi_load( reg, ptr ) (reg) = vld1q_u32( (uint32_t const*)(ptr) ) + #define stbir__simdf_load1( out, ptr ) (out) = vld1q_dup_f32( (float const*)(ptr) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdi_load1( out, ptr ) (out) = vld1q_dup_u32( (uint32_t const*)(ptr) ) + #define stbir__simdf_load1z( out, ptr ) (out) = vld1q_lane_f32( (float const*)(ptr), vdupq_n_f32(0), 0 ) // top values must be zero + #define stbir__simdf_frep4( fvar ) vdupq_n_f32( fvar ) + #define stbir__simdf_load1frep4( out, fvar ) (out) = vdupq_n_f32( fvar ) + #define stbir__simdf_load2( out, ptr ) (out) = vcombine_f32( vld1_f32( (float const*)(ptr) ), vcreate_f32(0) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdf_load2z( out, ptr ) (out) = vcombine_f32( vld1_f32( (float const*)(ptr) ), vcreate_f32(0) ) // top values must be zero + #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = vcombine_f32( vget_low_f32(reg), vld1_f32( (float const*)(ptr) ) ) + + #define stbir__simdf_zeroP() vdupq_n_f32(0) + #define stbir__simdf_zero( reg ) (reg) = vdupq_n_f32(0) + + #define stbir__simdf_store( ptr, reg ) vst1q_f32( (float*)(ptr), reg ) + #define stbir__simdf_store1( ptr, reg ) vst1q_lane_f32( (float*)(ptr), reg, 0) + #define stbir__simdf_store2( ptr, reg ) vst1_f32( (float*)(ptr), vget_low_f32(reg) ) + #define stbir__simdf_store2h( ptr, reg ) vst1_f32( (float*)(ptr), vget_high_f32(reg) ) + + #define stbir__simdi_store( ptr, reg ) vst1q_u32( (uint32_t*)(ptr), reg ) + #define stbir__simdi_store1( ptr, reg ) vst1q_lane_u32( (uint32_t*)(ptr), reg, 0 ) + #define stbir__simdi_store2( ptr, reg ) vst1_u32( (uint32_t*)(ptr), vget_low_u32(reg) ) + + #define stbir__prefetch( ptr ) + + #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \ + { \ + uint16x8_t l = vmovl_u8( vget_low_u8 ( vreinterpretq_u8_u32(ireg) ) ); \ + uint16x8_t h = vmovl_u8( vget_high_u8( vreinterpretq_u8_u32(ireg) ) ); \ + out0 = vmovl_u16( vget_low_u16 ( l ) ); \ + out1 = vmovl_u16( vget_high_u16( l ) ); \ + out2 = vmovl_u16( vget_low_u16 ( h ) ); \ + out3 = vmovl_u16( vget_high_u16( h ) ); \ + } + + #define stbir__simdi_expand_u8_to_1u32(out,ireg) \ + { \ + uint16x8_t tmp = vmovl_u8( vget_low_u8( vreinterpretq_u8_u32(ireg) ) ); \ + out = vmovl_u16( vget_low_u16( tmp ) ); \ + } + + #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \ + { \ + uint16x8_t tmp = vreinterpretq_u16_u32(ireg); \ + out0 = vmovl_u16( vget_low_u16 ( tmp ) ); \ + out1 = vmovl_u16( vget_high_u16( tmp ) ); \ + } + + #define stbir__simdf_convert_float_to_i32( i, f ) (i) = vreinterpretq_u32_s32( vcvtq_s32_f32(f) ) + #define stbir__simdf_convert_float_to_int( f ) vgetq_lane_s32(vcvtq_s32_f32(f), 0) + #define stbir__simdi_to_int( i ) (int)vgetq_lane_u32(i, 0) + #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)vgetq_lane_s32(vcvtq_s32_f32(vmaxq_f32(vminq_f32(f,STBIR__CONSTF(STBIR_max_uint8_as_float)),vdupq_n_f32(0))), 0)) + #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)vgetq_lane_s32(vcvtq_s32_f32(vmaxq_f32(vminq_f32(f,STBIR__CONSTF(STBIR_max_uint16_as_float)),vdupq_n_f32(0))), 0)) + #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = vcvtq_f32_s32( vreinterpretq_s32_u32(ireg) ) + #define stbir__simdf_add( out, reg0, reg1 ) (out) = vaddq_f32( reg0, reg1 ) + #define stbir__simdf_mult( out, reg0, reg1 ) (out) = vmulq_f32( reg0, reg1 ) + #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = vmulq_f32( reg, vld1q_f32( (float const*)(ptr) ) ) + #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = vmulq_f32( reg, vld1q_dup_f32( (float const*)(ptr) ) ) + #define stbir__simdf_add_mem( out, reg, ptr ) (out) = vaddq_f32( reg, vld1q_f32( (float const*)(ptr) ) ) + #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = vaddq_f32( reg, vld1q_dup_f32( (float const*)(ptr) ) ) + + #ifdef STBIR_USE_FMA // not on by default to maintain bit identical simd to non-simd (and also x64 no madd to arm madd) + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = vfmaq_f32( add, mul1, mul2 ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = vfmaq_f32( add, mul1, mul2 ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = vfmaq_f32( add, mul, vld1q_f32( (float const*)(ptr) ) ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = vfmaq_f32( add, mul, vld1q_dup_f32( (float const*)(ptr) ) ) + #else + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = vaddq_f32( add, vmulq_f32( mul1, mul2 ) ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = vaddq_f32( add, vmulq_f32( mul1, mul2 ) ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = vaddq_f32( add, vmulq_f32( mul, vld1q_f32( (float const*)(ptr) ) ) ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = vaddq_f32( add, vmulq_f32( mul, vld1q_dup_f32( (float const*)(ptr) ) ) ) + #endif + + #define stbir__simdf_add1( out, reg0, reg1 ) (out) = vaddq_f32( reg0, reg1 ) + #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = vmulq_f32( reg0, reg1 ) + + #define stbir__simdf_and( out, reg0, reg1 ) (out) = vreinterpretq_f32_u32( vandq_u32( vreinterpretq_u32_f32(reg0), vreinterpretq_u32_f32(reg1) ) ) + #define stbir__simdf_or( out, reg0, reg1 ) (out) = vreinterpretq_f32_u32( vorrq_u32( vreinterpretq_u32_f32(reg0), vreinterpretq_u32_f32(reg1) ) ) + + #define stbir__simdf_min( out, reg0, reg1 ) (out) = vminq_f32( reg0, reg1 ) + #define stbir__simdf_max( out, reg0, reg1 ) (out) = vmaxq_f32( reg0, reg1 ) + #define stbir__simdf_min1( out, reg0, reg1 ) (out) = vminq_f32( reg0, reg1 ) + #define stbir__simdf_max1( out, reg0, reg1 ) (out) = vmaxq_f32( reg0, reg1 ) + + #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out) = vextq_f32( reg0, reg1, 3 ) + #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out) = vextq_f32( reg0, reg1, 2 ) + + #define stbir__simdf_a1a1( out, alp, ones ) (out) = vzipq_f32(vuzpq_f32(alp, alp).val[1], ones).val[0] + #define stbir__simdf_1a1a( out, alp, ones ) (out) = vzipq_f32(ones, vuzpq_f32(alp, alp).val[0]).val[0] + + #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) + + #define stbir__simdf_aaa1( out, alp, ones ) (out) = vcopyq_laneq_f32(vdupq_n_f32(vgetq_lane_f32(alp, 3)), 3, ones, 3) + #define stbir__simdf_1aaa( out, alp, ones ) (out) = vcopyq_laneq_f32(vdupq_n_f32(vgetq_lane_f32(alp, 0)), 0, ones, 0) + + #if defined( _MSC_VER ) && !defined(__clang__) + #define stbir_make16(a,b,c,d) vcombine_u8( \ + vcreate_u8( (4*a+0) | ((4*a+1)<<8) | ((4*a+2)<<16) | ((4*a+3)<<24) | \ + ((stbir_uint64)(4*b+0)<<32) | ((stbir_uint64)(4*b+1)<<40) | ((stbir_uint64)(4*b+2)<<48) | ((stbir_uint64)(4*b+3)<<56)), \ + vcreate_u8( (4*c+0) | ((4*c+1)<<8) | ((4*c+2)<<16) | ((4*c+3)<<24) | \ + ((stbir_uint64)(4*d+0)<<32) | ((stbir_uint64)(4*d+1)<<40) | ((stbir_uint64)(4*d+2)<<48) | ((stbir_uint64)(4*d+3)<<56) ) ) + + static stbir__inline uint8x16x2_t stbir_make16x2(float32x4_t rega,float32x4_t regb) + { + uint8x16x2_t r = { vreinterpretq_u8_f32(rega), vreinterpretq_u8_f32(regb) }; + return r; + } + #else + #define stbir_make16(a,b,c,d) (uint8x16_t){4*a+0,4*a+1,4*a+2,4*a+3,4*b+0,4*b+1,4*b+2,4*b+3,4*c+0,4*c+1,4*c+2,4*c+3,4*d+0,4*d+1,4*d+2,4*d+3} + #define stbir_make16x2(a,b) (uint8x16x2_t){{vreinterpretq_u8_f32(a),vreinterpretq_u8_f32(b)}} + #endif + + #define stbir__simdf_swiz( reg, one, two, three, four ) vreinterpretq_f32_u8( vqtbl1q_u8( vreinterpretq_u8_f32(reg), stbir_make16(one, two, three, four) ) ) + #define stbir__simdf_swiz2( rega, regb, one, two, three, four ) vreinterpretq_f32_u8( vqtbl2q_u8( stbir_make16x2(rega,regb), stbir_make16(one, two, three, four) ) ) + + #define stbir__simdi_16madd( out, reg0, reg1 ) \ + { \ + int16x8_t r0 = vreinterpretq_s16_u32(reg0); \ + int16x8_t r1 = vreinterpretq_s16_u32(reg1); \ + int32x4_t tmp0 = vmull_s16( vget_low_s16(r0), vget_low_s16(r1) ); \ + int32x4_t tmp1 = vmull_s16( vget_high_s16(r0), vget_high_s16(r1) ); \ + (out) = vreinterpretq_u32_s32( vpaddq_s32(tmp0, tmp1) ); \ + } + + #else + + #define stbir__simdf_aaa1( out, alp, ones ) (out) = vsetq_lane_f32(1.0f, vdupq_n_f32(vgetq_lane_f32(alp, 3)), 3) + #define stbir__simdf_1aaa( out, alp, ones ) (out) = vsetq_lane_f32(1.0f, vdupq_n_f32(vgetq_lane_f32(alp, 0)), 0) + + #if defined( _MSC_VER ) && !defined(__clang__) + static stbir__inline uint8x8x2_t stbir_make8x2(float32x4_t reg) + { + uint8x8x2_t r = { { vget_low_u8(vreinterpretq_u8_f32(reg)), vget_high_u8(vreinterpretq_u8_f32(reg)) } }; + return r; + } + #define stbir_make8(a,b) vcreate_u8( \ + (4*a+0) | ((4*a+1)<<8) | ((4*a+2)<<16) | ((4*a+3)<<24) | \ + ((stbir_uint64)(4*b+0)<<32) | ((stbir_uint64)(4*b+1)<<40) | ((stbir_uint64)(4*b+2)<<48) | ((stbir_uint64)(4*b+3)<<56) ) + #else + #define stbir_make8x2(reg) (uint8x8x2_t){ { vget_low_u8(vreinterpretq_u8_f32(reg)), vget_high_u8(vreinterpretq_u8_f32(reg)) } } + #define stbir_make8(a,b) (uint8x8_t){4*a+0,4*a+1,4*a+2,4*a+3,4*b+0,4*b+1,4*b+2,4*b+3} + #endif + + #define stbir__simdf_swiz( reg, one, two, three, four ) vreinterpretq_f32_u8( vcombine_u8( \ + vtbl2_u8( stbir_make8x2( reg ), stbir_make8( one, two ) ), \ + vtbl2_u8( stbir_make8x2( reg ), stbir_make8( three, four ) ) ) ) + + #define stbir__simdi_16madd( out, reg0, reg1 ) \ + { \ + int16x8_t r0 = vreinterpretq_s16_u32(reg0); \ + int16x8_t r1 = vreinterpretq_s16_u32(reg1); \ + int32x4_t tmp0 = vmull_s16( vget_low_s16(r0), vget_low_s16(r1) ); \ + int32x4_t tmp1 = vmull_s16( vget_high_s16(r0), vget_high_s16(r1) ); \ + int32x2_t out0 = vpadd_s32( vget_low_s32(tmp0), vget_high_s32(tmp0) ); \ + int32x2_t out1 = vpadd_s32( vget_low_s32(tmp1), vget_high_s32(tmp1) ); \ + (out) = vreinterpretq_u32_s32( vcombine_s32(out0, out1) ); \ + } + + #endif + + #define stbir__simdi_and( out, reg0, reg1 ) (out) = vandq_u32( reg0, reg1 ) + #define stbir__simdi_or( out, reg0, reg1 ) (out) = vorrq_u32( reg0, reg1 ) + + #define stbir__simdf_pack_to_8bytes(out,aa,bb) \ + { \ + float32x4_t af = vmaxq_f32( vminq_f32(aa,STBIR__CONSTF(STBIR_max_uint8_as_float) ), vdupq_n_f32(0) ); \ + float32x4_t bf = vmaxq_f32( vminq_f32(bb,STBIR__CONSTF(STBIR_max_uint8_as_float) ), vdupq_n_f32(0) ); \ + int16x4_t ai = vqmovn_s32( vcvtq_s32_f32( af ) ); \ + int16x4_t bi = vqmovn_s32( vcvtq_s32_f32( bf ) ); \ + uint8x8_t out8 = vqmovun_s16( vcombine_s16(ai, bi) ); \ + out = vreinterpretq_u32_u8( vcombine_u8(out8, out8) ); \ + } + + #define stbir__simdf_pack_to_8words(out,aa,bb) \ + { \ + float32x4_t af = vmaxq_f32( vminq_f32(aa,STBIR__CONSTF(STBIR_max_uint16_as_float) ), vdupq_n_f32(0) ); \ + float32x4_t bf = vmaxq_f32( vminq_f32(bb,STBIR__CONSTF(STBIR_max_uint16_as_float) ), vdupq_n_f32(0) ); \ + int32x4_t ai = vcvtq_s32_f32( af ); \ + int32x4_t bi = vcvtq_s32_f32( bf ); \ + out = vreinterpretq_u32_u16( vcombine_u16(vqmovun_s32(ai), vqmovun_s32(bi)) ); \ + } + + #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \ + { \ + int16x4x2_t tmp0 = vzip_s16( vqmovn_s32(vreinterpretq_s32_u32(r0)), vqmovn_s32(vreinterpretq_s32_u32(r2)) ); \ + int16x4x2_t tmp1 = vzip_s16( vqmovn_s32(vreinterpretq_s32_u32(r1)), vqmovn_s32(vreinterpretq_s32_u32(r3)) ); \ + uint8x8x2_t out = \ + { { \ + vqmovun_s16( vcombine_s16(tmp0.val[0], tmp0.val[1]) ), \ + vqmovun_s16( vcombine_s16(tmp1.val[0], tmp1.val[1]) ), \ + } }; \ + vst2_u8(ptr, out); \ + } + + #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \ + { \ + float32x4x4_t tmp = vld4q_f32(ptr); \ + o0 = tmp.val[0]; \ + o1 = tmp.val[1]; \ + o2 = tmp.val[2]; \ + o3 = tmp.val[3]; \ + } + + #define stbir__simdi_32shr( out, reg, imm ) out = vshrq_n_u32( reg, imm ) + + #if defined( _MSC_VER ) && !defined(__clang__) + #define STBIR__SIMDF_CONST(var, x) __declspec(align(8)) float var[] = { x, x, x, x } + #define STBIR__SIMDI_CONST(var, x) __declspec(align(8)) uint32_t var[] = { x, x, x, x } + #define STBIR__CONSTF(var) (*(const float32x4_t*)var) + #define STBIR__CONSTI(var) (*(const uint32x4_t*)var) + #else + #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = { x, x, x, x } + #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { x, x, x, x } + #define STBIR__CONSTF(var) (var) + #define STBIR__CONSTI(var) (var) + #endif + + #ifdef STBIR_FLOORF + #undef STBIR_FLOORF + #endif + #define STBIR_FLOORF stbir_simd_floorf + static stbir__inline float stbir_simd_floorf(float x) + { + #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) + return vget_lane_f32( vrndm_f32( vdup_n_f32(x) ), 0); + #else + float32x2_t f = vdup_n_f32(x); + float32x2_t t = vcvt_f32_s32(vcvt_s32_f32(f)); + uint32x2_t a = vclt_f32(f, t); + uint32x2_t b = vreinterpret_u32_f32(vdup_n_f32(-1.0f)); + float32x2_t r = vadd_f32(t, vreinterpret_f32_u32(vand_u32(a, b))); + return vget_lane_f32(r, 0); + #endif + } + + #ifdef STBIR_CEILF + #undef STBIR_CEILF + #endif + #define STBIR_CEILF stbir_simd_ceilf + static stbir__inline float stbir_simd_ceilf(float x) + { + #if defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) + return vget_lane_f32( vrndp_f32( vdup_n_f32(x) ), 0); + #else + float32x2_t f = vdup_n_f32(x); + float32x2_t t = vcvt_f32_s32(vcvt_s32_f32(f)); + uint32x2_t a = vclt_f32(t, f); + uint32x2_t b = vreinterpret_u32_f32(vdup_n_f32(1.0f)); + float32x2_t r = vadd_f32(t, vreinterpret_f32_u32(vand_u32(a, b))); + return vget_lane_f32(r, 0); + #endif + } + + #define STBIR_SIMD + +#elif defined(STBIR_WASM) + + #include + + #define stbir__simdf v128_t + #define stbir__simdi v128_t + + #define stbir_simdi_castf( reg ) (reg) + #define stbir_simdf_casti( reg ) (reg) + + #define stbir__simdf_load( reg, ptr ) (reg) = wasm_v128_load( (void const*)(ptr) ) + #define stbir__simdi_load( reg, ptr ) (reg) = wasm_v128_load( (void const*)(ptr) ) + #define stbir__simdf_load1( out, ptr ) (out) = wasm_v128_load32_splat( (void const*)(ptr) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdi_load1( out, ptr ) (out) = wasm_v128_load32_splat( (void const*)(ptr) ) + #define stbir__simdf_load1z( out, ptr ) (out) = wasm_v128_load32_zero( (void const*)(ptr) ) // top values must be zero + #define stbir__simdf_frep4( fvar ) wasm_f32x4_splat( fvar ) + #define stbir__simdf_load1frep4( out, fvar ) (out) = wasm_f32x4_splat( fvar ) + #define stbir__simdf_load2( out, ptr ) (out) = wasm_v128_load64_splat( (void const*)(ptr) ) // top values can be random (not denormal or nan for perf) + #define stbir__simdf_load2z( out, ptr ) (out) = wasm_v128_load64_zero( (void const*)(ptr) ) // top values must be zero + #define stbir__simdf_load2hmerge( out, reg, ptr ) (out) = wasm_v128_load64_lane( (void const*)(ptr), reg, 1 ) + + #define stbir__simdf_zeroP() wasm_f32x4_const_splat(0) + #define stbir__simdf_zero( reg ) (reg) = wasm_f32x4_const_splat(0) + + #define stbir__simdf_store( ptr, reg ) wasm_v128_store( (void*)(ptr), reg ) + #define stbir__simdf_store1( ptr, reg ) wasm_v128_store32_lane( (void*)(ptr), reg, 0 ) + #define stbir__simdf_store2( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 0 ) + #define stbir__simdf_store2h( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 1 ) + + #define stbir__simdi_store( ptr, reg ) wasm_v128_store( (void*)(ptr), reg ) + #define stbir__simdi_store1( ptr, reg ) wasm_v128_store32_lane( (void*)(ptr), reg, 0 ) + #define stbir__simdi_store2( ptr, reg ) wasm_v128_store64_lane( (void*)(ptr), reg, 0 ) + + #define stbir__prefetch( ptr ) + + #define stbir__simdi_expand_u8_to_u32(out0,out1,out2,out3,ireg) \ + { \ + v128_t l = wasm_u16x8_extend_low_u8x16 ( ireg ); \ + v128_t h = wasm_u16x8_extend_high_u8x16( ireg ); \ + out0 = wasm_u32x4_extend_low_u16x8 ( l ); \ + out1 = wasm_u32x4_extend_high_u16x8( l ); \ + out2 = wasm_u32x4_extend_low_u16x8 ( h ); \ + out3 = wasm_u32x4_extend_high_u16x8( h ); \ + } + + #define stbir__simdi_expand_u8_to_1u32(out,ireg) \ + { \ + v128_t tmp = wasm_u16x8_extend_low_u8x16(ireg); \ + out = wasm_u32x4_extend_low_u16x8(tmp); \ + } + + #define stbir__simdi_expand_u16_to_u32(out0,out1,ireg) \ + { \ + out0 = wasm_u32x4_extend_low_u16x8 ( ireg ); \ + out1 = wasm_u32x4_extend_high_u16x8( ireg ); \ + } + + #define stbir__simdf_convert_float_to_i32( i, f ) (i) = wasm_i32x4_trunc_sat_f32x4(f) + #define stbir__simdf_convert_float_to_int( f ) wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(f), 0) + #define stbir__simdi_to_int( i ) wasm_i32x4_extract_lane(i, 0) + #define stbir__simdf_convert_float_to_uint8( f ) ((unsigned char)wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_max(wasm_f32x4_min(f,STBIR_max_uint8_as_float),wasm_f32x4_const_splat(0))), 0)) + #define stbir__simdf_convert_float_to_short( f ) ((unsigned short)wasm_i32x4_extract_lane(wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_max(wasm_f32x4_min(f,STBIR_max_uint16_as_float),wasm_f32x4_const_splat(0))), 0)) + #define stbir__simdi_convert_i32_to_float(out, ireg) (out) = wasm_f32x4_convert_i32x4(ireg) + #define stbir__simdf_add( out, reg0, reg1 ) (out) = wasm_f32x4_add( reg0, reg1 ) + #define stbir__simdf_mult( out, reg0, reg1 ) (out) = wasm_f32x4_mul( reg0, reg1 ) + #define stbir__simdf_mult_mem( out, reg, ptr ) (out) = wasm_f32x4_mul( reg, wasm_v128_load( (void const*)(ptr) ) ) + #define stbir__simdf_mult1_mem( out, reg, ptr ) (out) = wasm_f32x4_mul( reg, wasm_v128_load32_splat( (void const*)(ptr) ) ) + #define stbir__simdf_add_mem( out, reg, ptr ) (out) = wasm_f32x4_add( reg, wasm_v128_load( (void const*)(ptr) ) ) + #define stbir__simdf_add1_mem( out, reg, ptr ) (out) = wasm_f32x4_add( reg, wasm_v128_load32_splat( (void const*)(ptr) ) ) + + #define stbir__simdf_madd( out, add, mul1, mul2 ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul1, mul2 ) ) + #define stbir__simdf_madd1( out, add, mul1, mul2 ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul1, mul2 ) ) + #define stbir__simdf_madd_mem( out, add, mul, ptr ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul, wasm_v128_load( (void const*)(ptr) ) ) ) + #define stbir__simdf_madd1_mem( out, add, mul, ptr ) (out) = wasm_f32x4_add( add, wasm_f32x4_mul( mul, wasm_v128_load32_splat( (void const*)(ptr) ) ) ) + + #define stbir__simdf_add1( out, reg0, reg1 ) (out) = wasm_f32x4_add( reg0, reg1 ) + #define stbir__simdf_mult1( out, reg0, reg1 ) (out) = wasm_f32x4_mul( reg0, reg1 ) + + #define stbir__simdf_and( out, reg0, reg1 ) (out) = wasm_v128_and( reg0, reg1 ) + #define stbir__simdf_or( out, reg0, reg1 ) (out) = wasm_v128_or( reg0, reg1 ) + + #define stbir__simdf_min( out, reg0, reg1 ) (out) = wasm_f32x4_min( reg0, reg1 ) + #define stbir__simdf_max( out, reg0, reg1 ) (out) = wasm_f32x4_max( reg0, reg1 ) + #define stbir__simdf_min1( out, reg0, reg1 ) (out) = wasm_f32x4_min( reg0, reg1 ) + #define stbir__simdf_max1( out, reg0, reg1 ) (out) = wasm_f32x4_max( reg0, reg1 ) + + #define stbir__simdf_0123ABCDto3ABx( out, reg0, reg1 ) (out) = wasm_i32x4_shuffle( reg0, reg1, 3, 4, 5, -1 ) + #define stbir__simdf_0123ABCDto23Ax( out, reg0, reg1 ) (out) = wasm_i32x4_shuffle( reg0, reg1, 2, 3, 4, -1 ) + + #define stbir__simdf_aaa1(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 3, 3, 3, 4) + #define stbir__simdf_1aaa(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 4, 0, 0, 0) + #define stbir__simdf_a1a1(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 1, 4, 3, 4) + #define stbir__simdf_1a1a(out,alp,ones) (out) = wasm_i32x4_shuffle(alp, ones, 4, 0, 4, 2) + + #define stbir__simdf_swiz( reg, one, two, three, four ) wasm_i32x4_shuffle(reg, reg, one, two, three, four) + + #define stbir__simdi_and( out, reg0, reg1 ) (out) = wasm_v128_and( reg0, reg1 ) + #define stbir__simdi_or( out, reg0, reg1 ) (out) = wasm_v128_or( reg0, reg1 ) + #define stbir__simdi_16madd( out, reg0, reg1 ) (out) = wasm_i32x4_dot_i16x8( reg0, reg1 ) + + #define stbir__simdf_pack_to_8bytes(out,aa,bb) \ + { \ + v128_t af = wasm_f32x4_max( wasm_f32x4_min(aa, STBIR_max_uint8_as_float), wasm_f32x4_const_splat(0) ); \ + v128_t bf = wasm_f32x4_max( wasm_f32x4_min(bb, STBIR_max_uint8_as_float), wasm_f32x4_const_splat(0) ); \ + v128_t ai = wasm_i32x4_trunc_sat_f32x4( af ); \ + v128_t bi = wasm_i32x4_trunc_sat_f32x4( bf ); \ + v128_t out16 = wasm_i16x8_narrow_i32x4( ai, bi ); \ + out = wasm_u8x16_narrow_i16x8( out16, out16 ); \ + } + + #define stbir__simdf_pack_to_8words(out,aa,bb) \ + { \ + v128_t af = wasm_f32x4_max( wasm_f32x4_min(aa, STBIR_max_uint16_as_float), wasm_f32x4_const_splat(0)); \ + v128_t bf = wasm_f32x4_max( wasm_f32x4_min(bb, STBIR_max_uint16_as_float), wasm_f32x4_const_splat(0)); \ + v128_t ai = wasm_i32x4_trunc_sat_f32x4( af ); \ + v128_t bi = wasm_i32x4_trunc_sat_f32x4( bf ); \ + out = wasm_u16x8_narrow_i32x4( ai, bi ); \ + } + + #define stbir__interleave_pack_and_store_16_u8( ptr, r0, r1, r2, r3 ) \ + { \ + v128_t tmp0 = wasm_i16x8_narrow_i32x4(r0, r1); \ + v128_t tmp1 = wasm_i16x8_narrow_i32x4(r2, r3); \ + v128_t tmp = wasm_u8x16_narrow_i16x8(tmp0, tmp1); \ + tmp = wasm_i8x16_shuffle(tmp, tmp, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15); \ + wasm_v128_store( (void*)(ptr), tmp); \ + } + + #define stbir__simdf_load4_transposed( o0, o1, o2, o3, ptr ) \ + { \ + v128_t t0 = wasm_v128_load( ptr ); \ + v128_t t1 = wasm_v128_load( ptr+4 ); \ + v128_t t2 = wasm_v128_load( ptr+8 ); \ + v128_t t3 = wasm_v128_load( ptr+12 ); \ + v128_t s0 = wasm_i32x4_shuffle(t0, t1, 0, 4, 2, 6); \ + v128_t s1 = wasm_i32x4_shuffle(t0, t1, 1, 5, 3, 7); \ + v128_t s2 = wasm_i32x4_shuffle(t2, t3, 0, 4, 2, 6); \ + v128_t s3 = wasm_i32x4_shuffle(t2, t3, 1, 5, 3, 7); \ + o0 = wasm_i32x4_shuffle(s0, s2, 0, 1, 4, 5); \ + o1 = wasm_i32x4_shuffle(s1, s3, 0, 1, 4, 5); \ + o2 = wasm_i32x4_shuffle(s0, s2, 2, 3, 6, 7); \ + o3 = wasm_i32x4_shuffle(s1, s3, 2, 3, 6, 7); \ + } + + #define stbir__simdi_32shr( out, reg, imm ) out = wasm_u32x4_shr( reg, imm ) + + typedef float stbir__f32x4 __attribute__((__vector_size__(16), __aligned__(16))); + #define STBIR__SIMDF_CONST(var, x) stbir__simdf var = (v128_t)(stbir__f32x4){ x, x, x, x } + #define STBIR__SIMDI_CONST(var, x) stbir__simdi var = { x, x, x, x } + #define STBIR__CONSTF(var) (var) + #define STBIR__CONSTI(var) (var) + + #ifdef STBIR_FLOORF + #undef STBIR_FLOORF + #endif + #define STBIR_FLOORF stbir_simd_floorf + static stbir__inline float stbir_simd_floorf(float x) + { + return wasm_f32x4_extract_lane( wasm_f32x4_floor( wasm_f32x4_splat(x) ), 0); + } + + #ifdef STBIR_CEILF + #undef STBIR_CEILF + #endif + #define STBIR_CEILF stbir_simd_ceilf + static stbir__inline float stbir_simd_ceilf(float x) + { + return wasm_f32x4_extract_lane( wasm_f32x4_ceil( wasm_f32x4_splat(x) ), 0); + } + + #define STBIR_SIMD + +#endif // SSE2/NEON/WASM + +#endif // NO SIMD + +#ifdef STBIR_SIMD8 + #define stbir__simdfX stbir__simdf8 + #define stbir__simdiX stbir__simdi8 + #define stbir__simdfX_load stbir__simdf8_load + #define stbir__simdiX_load stbir__simdi8_load + #define stbir__simdfX_mult stbir__simdf8_mult + #define stbir__simdfX_add_mem stbir__simdf8_add_mem + #define stbir__simdfX_madd_mem stbir__simdf8_madd_mem + #define stbir__simdfX_store stbir__simdf8_store + #define stbir__simdiX_store stbir__simdi8_store + #define stbir__simdf_frepX stbir__simdf8_frep8 + #define stbir__simdfX_madd stbir__simdf8_madd + #define stbir__simdfX_min stbir__simdf8_min + #define stbir__simdfX_max stbir__simdf8_max + #define stbir__simdfX_aaa1 stbir__simdf8_aaa1 + #define stbir__simdfX_1aaa stbir__simdf8_1aaa + #define stbir__simdfX_a1a1 stbir__simdf8_a1a1 + #define stbir__simdfX_1a1a stbir__simdf8_1a1a + #define stbir__simdfX_convert_float_to_i32 stbir__simdf8_convert_float_to_i32 + #define stbir__simdfX_pack_to_words stbir__simdf8_pack_to_16words + #define stbir__simdfX_zero stbir__simdf8_zero + #define STBIR_onesX STBIR_ones8 + #define STBIR_max_uint8_as_floatX STBIR_max_uint8_as_float8 + #define STBIR_max_uint16_as_floatX STBIR_max_uint16_as_float8 + #define STBIR_simd_point5X STBIR_simd_point58 + #define stbir__simdfX_float_count 8 + #define stbir__simdfX_0123to1230 stbir__simdf8_0123to12301230 + #define stbir__simdfX_0123to2103 stbir__simdf8_0123to21032103 + static const stbir__simdf8 STBIR_max_uint16_as_float_inverted8 = { stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted,stbir__max_uint16_as_float_inverted }; + static const stbir__simdf8 STBIR_max_uint8_as_float_inverted8 = { stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted,stbir__max_uint8_as_float_inverted }; + static const stbir__simdf8 STBIR_ones8 = { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }; + static const stbir__simdf8 STBIR_simd_point58 = { 0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5 }; + static const stbir__simdf8 STBIR_max_uint8_as_float8 = { stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float, stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float,stbir__max_uint8_as_float }; + static const stbir__simdf8 STBIR_max_uint16_as_float8 = { stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float, stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float,stbir__max_uint16_as_float }; +#else + #define stbir__simdfX stbir__simdf + #define stbir__simdiX stbir__simdi + #define stbir__simdfX_load stbir__simdf_load + #define stbir__simdiX_load stbir__simdi_load + #define stbir__simdfX_mult stbir__simdf_mult + #define stbir__simdfX_add_mem stbir__simdf_add_mem + #define stbir__simdfX_madd_mem stbir__simdf_madd_mem + #define stbir__simdfX_store stbir__simdf_store + #define stbir__simdiX_store stbir__simdi_store + #define stbir__simdf_frepX stbir__simdf_frep4 + #define stbir__simdfX_madd stbir__simdf_madd + #define stbir__simdfX_min stbir__simdf_min + #define stbir__simdfX_max stbir__simdf_max + #define stbir__simdfX_aaa1 stbir__simdf_aaa1 + #define stbir__simdfX_1aaa stbir__simdf_1aaa + #define stbir__simdfX_a1a1 stbir__simdf_a1a1 + #define stbir__simdfX_1a1a stbir__simdf_1a1a + #define stbir__simdfX_convert_float_to_i32 stbir__simdf_convert_float_to_i32 + #define stbir__simdfX_pack_to_words stbir__simdf_pack_to_8words + #define stbir__simdfX_zero stbir__simdf_zero + #define STBIR_onesX STBIR__CONSTF(STBIR_ones) + #define STBIR_simd_point5X STBIR__CONSTF(STBIR_simd_point5) + #define STBIR_max_uint8_as_floatX STBIR__CONSTF(STBIR_max_uint8_as_float) + #define STBIR_max_uint16_as_floatX STBIR__CONSTF(STBIR_max_uint16_as_float) + #define stbir__simdfX_float_count 4 + #define stbir__if_simdf8_cast_to_simdf4( val ) ( val ) + #define stbir__simdfX_0123to1230 stbir__simdf_0123to1230 + #define stbir__simdfX_0123to2103 stbir__simdf_0123to2103 +#endif + + +#if defined(STBIR_NEON) && !defined(_M_ARM) && !defined(__arm__) + + #if defined( _MSC_VER ) && !defined(__clang__) + typedef __int16 stbir__FP16; + #else + typedef float16_t stbir__FP16; + #endif + +#else // no NEON, or 32-bit ARM for MSVC + + typedef union stbir__FP16 + { + unsigned short u; + } stbir__FP16; + +#endif + +#if (!defined(STBIR_NEON) && !defined(STBIR_FP16C)) || (defined(STBIR_NEON) && defined(_M_ARM)) || (defined(STBIR_NEON) && defined(__arm__)) + + // Fabian's half float routines, see: https://gist.github.com/rygorous/2156668 + + static stbir__inline float stbir__half_to_float( stbir__FP16 h ) + { + static const stbir__FP32 magic = { (254 - 15) << 23 }; + static const stbir__FP32 was_infnan = { (127 + 16) << 23 }; + stbir__FP32 o; + + o.u = (h.u & 0x7fff) << 13; // exponent/mantissa bits + o.f *= magic.f; // exponent adjust + if (o.f >= was_infnan.f) // make sure Inf/NaN survive + o.u |= 255 << 23; + o.u |= (h.u & 0x8000) << 16; // sign bit + return o.f; + } + + static stbir__inline stbir__FP16 stbir__float_to_half(float val) + { + stbir__FP32 f32infty = { 255 << 23 }; + stbir__FP32 f16max = { (127 + 16) << 23 }; + stbir__FP32 denorm_magic = { ((127 - 15) + (23 - 10) + 1) << 23 }; + unsigned int sign_mask = 0x80000000u; + stbir__FP16 o = { 0 }; + stbir__FP32 f; + unsigned int sign; + + f.f = val; + sign = f.u & sign_mask; + f.u ^= sign; + + if (f.u >= f16max.u) // result is Inf or NaN (all exponent bits set) + o.u = (f.u > f32infty.u) ? 0x7e00 : 0x7c00; // NaN->qNaN and Inf->Inf + else // (De)normalized number or zero + { + if (f.u < (113 << 23)) // resulting FP16 is subnormal or zero + { + // use a magic value to align our 10 mantissa bits at the bottom of + // the float. as long as FP addition is round-to-nearest-even this + // just works. + f.f += denorm_magic.f; + // and one integer subtract of the bias later, we have our final float! + o.u = (unsigned short) ( f.u - denorm_magic.u ); + } + else + { + unsigned int mant_odd = (f.u >> 13) & 1; // resulting mantissa is odd + // update exponent, rounding bias part 1 + f.u = f.u + ((15u - 127) << 23) + 0xfff; + // rounding bias part 2 + f.u += mant_odd; + // take the bits! + o.u = (unsigned short) ( f.u >> 13 ); + } + } + + o.u |= sign >> 16; + return o; + } + +#endif + + +#if defined(STBIR_FP16C) + + #include + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + _mm256_storeu_ps( (float*)output, _mm256_cvtph_ps( _mm_loadu_si128( (__m128i const* )input ) ) ); + } + + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + _mm_storeu_si128( (__m128i*)output, _mm256_cvtps_ph( _mm256_loadu_ps( input ), 0 ) ); + } + + static stbir__inline float stbir__half_to_float( stbir__FP16 h ) + { + return _mm_cvtss_f32( _mm_cvtph_ps( _mm_cvtsi32_si128( (int)h.u ) ) ); + } + + static stbir__inline stbir__FP16 stbir__float_to_half( float f ) + { + stbir__FP16 h; + h.u = (unsigned short) _mm_cvtsi128_si32( _mm_cvtps_ph( _mm_set_ss( f ), 0 ) ); + return h; + } + +#elif defined(STBIR_SSE2) + + // Fabian's half float routines, see: https://gist.github.com/rygorous/2156668 + stbir__inline static void stbir__half_to_float_SIMD(float * output, void const * input) + { + static const STBIR__SIMDI_CONST(mask_nosign, 0x7fff); + static const STBIR__SIMDI_CONST(smallest_normal, 0x0400); + static const STBIR__SIMDI_CONST(infinity, 0x7c00); + static const STBIR__SIMDI_CONST(expadjust_normal, (127 - 15) << 23); + static const STBIR__SIMDI_CONST(magic_denorm, 113 << 23); + + __m128i i = _mm_loadu_si128 ( (__m128i const*)(input) ); + __m128i h = _mm_unpacklo_epi16 ( i, _mm_setzero_si128() ); + __m128i mnosign = STBIR__CONSTI(mask_nosign); + __m128i eadjust = STBIR__CONSTI(expadjust_normal); + __m128i smallest = STBIR__CONSTI(smallest_normal); + __m128i infty = STBIR__CONSTI(infinity); + __m128i expmant = _mm_and_si128(mnosign, h); + __m128i justsign = _mm_xor_si128(h, expmant); + __m128i b_notinfnan = _mm_cmpgt_epi32(infty, expmant); + __m128i b_isdenorm = _mm_cmpgt_epi32(smallest, expmant); + __m128i shifted = _mm_slli_epi32(expmant, 13); + __m128i adj_infnan = _mm_andnot_si128(b_notinfnan, eadjust); + __m128i adjusted = _mm_add_epi32(eadjust, shifted); + __m128i den1 = _mm_add_epi32(shifted, STBIR__CONSTI(magic_denorm)); + __m128i adjusted2 = _mm_add_epi32(adjusted, adj_infnan); + __m128 den2 = _mm_sub_ps(_mm_castsi128_ps(den1), *(const __m128 *)&magic_denorm); + __m128 adjusted3 = _mm_and_ps(den2, _mm_castsi128_ps(b_isdenorm)); + __m128 adjusted4 = _mm_andnot_ps(_mm_castsi128_ps(b_isdenorm), _mm_castsi128_ps(adjusted2)); + __m128 adjusted5 = _mm_or_ps(adjusted3, adjusted4); + __m128i sign = _mm_slli_epi32(justsign, 16); + __m128 final = _mm_or_ps(adjusted5, _mm_castsi128_ps(sign)); + stbir__simdf_store( output + 0, final ); + + h = _mm_unpackhi_epi16 ( i, _mm_setzero_si128() ); + expmant = _mm_and_si128(mnosign, h); + justsign = _mm_xor_si128(h, expmant); + b_notinfnan = _mm_cmpgt_epi32(infty, expmant); + b_isdenorm = _mm_cmpgt_epi32(smallest, expmant); + shifted = _mm_slli_epi32(expmant, 13); + adj_infnan = _mm_andnot_si128(b_notinfnan, eadjust); + adjusted = _mm_add_epi32(eadjust, shifted); + den1 = _mm_add_epi32(shifted, STBIR__CONSTI(magic_denorm)); + adjusted2 = _mm_add_epi32(adjusted, adj_infnan); + den2 = _mm_sub_ps(_mm_castsi128_ps(den1), *(const __m128 *)&magic_denorm); + adjusted3 = _mm_and_ps(den2, _mm_castsi128_ps(b_isdenorm)); + adjusted4 = _mm_andnot_ps(_mm_castsi128_ps(b_isdenorm), _mm_castsi128_ps(adjusted2)); + adjusted5 = _mm_or_ps(adjusted3, adjusted4); + sign = _mm_slli_epi32(justsign, 16); + final = _mm_or_ps(adjusted5, _mm_castsi128_ps(sign)); + stbir__simdf_store( output + 4, final ); + + // ~38 SSE2 ops for 8 values + } + + // Fabian's round-to-nearest-even float to half + // ~48 SSE2 ops for 8 output + stbir__inline static void stbir__float_to_half_SIMD(void * output, float const * input) + { + static const STBIR__SIMDI_CONST(mask_sign, 0x80000000u); + static const STBIR__SIMDI_CONST(c_f16max, (127 + 16) << 23); // all FP32 values >=this round to +inf + static const STBIR__SIMDI_CONST(c_nanbit, 0x200); + static const STBIR__SIMDI_CONST(c_infty_as_fp16, 0x7c00); + static const STBIR__SIMDI_CONST(c_min_normal, (127 - 14) << 23); // smallest FP32 that yields a normalized FP16 + static const STBIR__SIMDI_CONST(c_subnorm_magic, ((127 - 15) + (23 - 10) + 1) << 23); + static const STBIR__SIMDI_CONST(c_normal_bias, 0xfff - ((127 - 15) << 23)); // adjust exponent and add mantissa rounding + + __m128 f = _mm_loadu_ps(input); + __m128 msign = _mm_castsi128_ps(STBIR__CONSTI(mask_sign)); + __m128 justsign = _mm_and_ps(msign, f); + __m128 absf = _mm_xor_ps(f, justsign); + __m128i absf_int = _mm_castps_si128(absf); // the cast is "free" (extra bypass latency, but no thruput hit) + __m128i f16max = STBIR__CONSTI(c_f16max); + __m128 b_isnan = _mm_cmpunord_ps(absf, absf); // is this a NaN? + __m128i b_isregular = _mm_cmpgt_epi32(f16max, absf_int); // (sub)normalized or special? + __m128i nanbit = _mm_and_si128(_mm_castps_si128(b_isnan), STBIR__CONSTI(c_nanbit)); + __m128i inf_or_nan = _mm_or_si128(nanbit, STBIR__CONSTI(c_infty_as_fp16)); // output for specials + + __m128i min_normal = STBIR__CONSTI(c_min_normal); + __m128i b_issub = _mm_cmpgt_epi32(min_normal, absf_int); + + // "result is subnormal" path + __m128 subnorm1 = _mm_add_ps(absf, _mm_castsi128_ps(STBIR__CONSTI(c_subnorm_magic))); // magic value to round output mantissa + __m128i subnorm2 = _mm_sub_epi32(_mm_castps_si128(subnorm1), STBIR__CONSTI(c_subnorm_magic)); // subtract out bias + + // "result is normal" path + __m128i mantoddbit = _mm_slli_epi32(absf_int, 31 - 13); // shift bit 13 (mantissa LSB) to sign + __m128i mantodd = _mm_srai_epi32(mantoddbit, 31); // -1 if FP16 mantissa odd, else 0 + + __m128i round1 = _mm_add_epi32(absf_int, STBIR__CONSTI(c_normal_bias)); + __m128i round2 = _mm_sub_epi32(round1, mantodd); // if mantissa LSB odd, bias towards rounding up (RTNE) + __m128i normal = _mm_srli_epi32(round2, 13); // rounded result + + // combine the two non-specials + __m128i nonspecial = _mm_or_si128(_mm_and_si128(subnorm2, b_issub), _mm_andnot_si128(b_issub, normal)); + + // merge in specials as well + __m128i joined = _mm_or_si128(_mm_and_si128(nonspecial, b_isregular), _mm_andnot_si128(b_isregular, inf_or_nan)); + + __m128i sign_shift = _mm_srai_epi32(_mm_castps_si128(justsign), 16); + __m128i final2, final= _mm_or_si128(joined, sign_shift); + + f = _mm_loadu_ps(input+4); + justsign = _mm_and_ps(msign, f); + absf = _mm_xor_ps(f, justsign); + absf_int = _mm_castps_si128(absf); // the cast is "free" (extra bypass latency, but no thruput hit) + b_isnan = _mm_cmpunord_ps(absf, absf); // is this a NaN? + b_isregular = _mm_cmpgt_epi32(f16max, absf_int); // (sub)normalized or special? + nanbit = _mm_and_si128(_mm_castps_si128(b_isnan), c_nanbit); + inf_or_nan = _mm_or_si128(nanbit, STBIR__CONSTI(c_infty_as_fp16)); // output for specials + + b_issub = _mm_cmpgt_epi32(min_normal, absf_int); + + // "result is subnormal" path + subnorm1 = _mm_add_ps(absf, _mm_castsi128_ps(STBIR__CONSTI(c_subnorm_magic))); // magic value to round output mantissa + subnorm2 = _mm_sub_epi32(_mm_castps_si128(subnorm1), STBIR__CONSTI(c_subnorm_magic)); // subtract out bias + + // "result is normal" path + mantoddbit = _mm_slli_epi32(absf_int, 31 - 13); // shift bit 13 (mantissa LSB) to sign + mantodd = _mm_srai_epi32(mantoddbit, 31); // -1 if FP16 mantissa odd, else 0 + + round1 = _mm_add_epi32(absf_int, STBIR__CONSTI(c_normal_bias)); + round2 = _mm_sub_epi32(round1, mantodd); // if mantissa LSB odd, bias towards rounding up (RTNE) + normal = _mm_srli_epi32(round2, 13); // rounded result + + // combine the two non-specials + nonspecial = _mm_or_si128(_mm_and_si128(subnorm2, b_issub), _mm_andnot_si128(b_issub, normal)); + + // merge in specials as well + joined = _mm_or_si128(_mm_and_si128(nonspecial, b_isregular), _mm_andnot_si128(b_isregular, inf_or_nan)); + + sign_shift = _mm_srai_epi32(_mm_castps_si128(justsign), 16); + final2 = _mm_or_si128(joined, sign_shift); + final = _mm_packs_epi32(final, final2); + stbir__simdi_store( output,final ); + } + +#elif defined(STBIR_NEON) && defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__) // 64-bit ARM on MSVC (not clang) + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + float16x4_t in0 = vld1_f16(input + 0); + float16x4_t in1 = vld1_f16(input + 4); + vst1q_f32(output + 0, vcvt_f32_f16(in0)); + vst1q_f32(output + 4, vcvt_f32_f16(in1)); + } + + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + float16x4_t out0 = vcvt_f16_f32(vld1q_f32(input + 0)); + float16x4_t out1 = vcvt_f16_f32(vld1q_f32(input + 4)); + vst1_f16(output+0, out0); + vst1_f16(output+4, out1); + } + + static stbir__inline float stbir__half_to_float( stbir__FP16 h ) + { + return vgetq_lane_f32(vcvt_f32_f16(vld1_dup_f16(&h)), 0); + } + + static stbir__inline stbir__FP16 stbir__float_to_half( float f ) + { + return vget_lane_f16(vcvt_f16_f32(vdupq_n_f32(f)), 0).n16_u16[0]; + } + +#elif defined(STBIR_NEON) && ( defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) ) // 64-bit ARM + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + float16x8_t in = vld1q_f16(input); + vst1q_f32(output + 0, vcvt_f32_f16(vget_low_f16(in))); + vst1q_f32(output + 4, vcvt_f32_f16(vget_high_f16(in))); + } + + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + float16x4_t out0 = vcvt_f16_f32(vld1q_f32(input + 0)); + float16x4_t out1 = vcvt_f16_f32(vld1q_f32(input + 4)); + vst1q_f16(output, vcombine_f16(out0, out1)); + } + + static stbir__inline float stbir__half_to_float( stbir__FP16 h ) + { + return vgetq_lane_f32(vcvt_f32_f16(vdup_n_f16(h)), 0); + } + + static stbir__inline stbir__FP16 stbir__float_to_half( float f ) + { + return vget_lane_f16(vcvt_f16_f32(vdupq_n_f32(f)), 0); + } + +#elif defined(STBIR_WASM) || (defined(STBIR_NEON) && (defined(_MSC_VER) || defined(_M_ARM) || defined(__arm__))) // WASM or 32-bit ARM on MSVC/clang + + static stbir__inline void stbir__half_to_float_SIMD(float * output, stbir__FP16 const * input) + { + for (int i=0; i<8; i++) + { + output[i] = stbir__half_to_float(input[i]); + } + } + static stbir__inline void stbir__float_to_half_SIMD(stbir__FP16 * output, float const * input) + { + for (int i=0; i<8; i++) + { + output[i] = stbir__float_to_half(input[i]); + } + } + +#endif + + +#ifdef STBIR_SIMD + +#define stbir__simdf_0123to3333( out, reg ) (out) = stbir__simdf_swiz( reg, 3,3,3,3 ) +#define stbir__simdf_0123to2222( out, reg ) (out) = stbir__simdf_swiz( reg, 2,2,2,2 ) +#define stbir__simdf_0123to1111( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,1,1 ) +#define stbir__simdf_0123to0000( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,0 ) +#define stbir__simdf_0123to0003( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,3 ) +#define stbir__simdf_0123to0001( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,0,1 ) +#define stbir__simdf_0123to1122( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,2,2 ) +#define stbir__simdf_0123to2333( out, reg ) (out) = stbir__simdf_swiz( reg, 2,3,3,3 ) +#define stbir__simdf_0123to0023( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,2,3 ) +#define stbir__simdf_0123to1230( out, reg ) (out) = stbir__simdf_swiz( reg, 1,2,3,0 ) +#define stbir__simdf_0123to2103( out, reg ) (out) = stbir__simdf_swiz( reg, 2,1,0,3 ) +#define stbir__simdf_0123to3210( out, reg ) (out) = stbir__simdf_swiz( reg, 3,2,1,0 ) +#define stbir__simdf_0123to2301( out, reg ) (out) = stbir__simdf_swiz( reg, 2,3,0,1 ) +#define stbir__simdf_0123to3012( out, reg ) (out) = stbir__simdf_swiz( reg, 3,0,1,2 ) +#define stbir__simdf_0123to0011( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,1,1 ) +#define stbir__simdf_0123to1100( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,0,0 ) +#define stbir__simdf_0123to2233( out, reg ) (out) = stbir__simdf_swiz( reg, 2,2,3,3 ) +#define stbir__simdf_0123to1133( out, reg ) (out) = stbir__simdf_swiz( reg, 1,1,3,3 ) +#define stbir__simdf_0123to0022( out, reg ) (out) = stbir__simdf_swiz( reg, 0,0,2,2 ) +#define stbir__simdf_0123to1032( out, reg ) (out) = stbir__simdf_swiz( reg, 1,0,3,2 ) + +typedef union stbir__simdi_u32 +{ + stbir_uint32 m128i_u32[4]; + int m128i_i32[4]; + stbir__simdi m128i_i128; +} stbir__simdi_u32; + +static const int STBIR_mask[9] = { 0,0,0,-1,-1,-1,0,0,0 }; + +static const STBIR__SIMDF_CONST(STBIR_max_uint8_as_float, stbir__max_uint8_as_float); +static const STBIR__SIMDF_CONST(STBIR_max_uint16_as_float, stbir__max_uint16_as_float); +static const STBIR__SIMDF_CONST(STBIR_max_uint8_as_float_inverted, stbir__max_uint8_as_float_inverted); +static const STBIR__SIMDF_CONST(STBIR_max_uint16_as_float_inverted, stbir__max_uint16_as_float_inverted); + +static const STBIR__SIMDF_CONST(STBIR_simd_point5, 0.5f); +static const STBIR__SIMDF_CONST(STBIR_ones, 1.0f); +static const STBIR__SIMDI_CONST(STBIR_almost_zero, (127 - 13) << 23); +static const STBIR__SIMDI_CONST(STBIR_almost_one, 0x3f7fffff); +static const STBIR__SIMDI_CONST(STBIR_mastissa_mask, 0xff); +static const STBIR__SIMDI_CONST(STBIR_topscale, 0x02000000); + +// Basically, in simd mode, we unroll the proper amount, and we don't want +// the non-simd remnant loops to be unroll because they only run a few times +// Adding this switch saves about 5K on clang which is Captain Unroll the 3rd. +#define STBIR_SIMD_STREAMOUT_PTR( star ) STBIR_STREAMOUT_PTR( star ) +#define STBIR_SIMD_NO_UNROLL(ptr) STBIR_NO_UNROLL(ptr) +#define STBIR_SIMD_NO_UNROLL_LOOP_START STBIR_NO_UNROLL_LOOP_START +#define STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR STBIR_NO_UNROLL_LOOP_START_INF_FOR + +#ifdef STBIR_MEMCPY +#undef STBIR_MEMCPY +#endif +#define STBIR_MEMCPY stbir_simd_memcpy + +// override normal use of memcpy with much simpler copy (faster and smaller with our sized copies) +static void stbir_simd_memcpy( void * dest, void const * src, size_t bytes ) +{ + char STBIR_SIMD_STREAMOUT_PTR (*) d = (char*) dest; + char STBIR_SIMD_STREAMOUT_PTR( * ) d_end = ((char*) dest) + bytes; + ptrdiff_t ofs_to_src = (char*)src - (char*)dest; + + // check overlaps + STBIR_ASSERT( ( ( d >= ( (char*)src) + bytes ) ) || ( ( d + bytes ) <= (char*)src ) ); + + if ( bytes < (16*stbir__simdfX_float_count) ) + { + if ( bytes < 16 ) + { + if ( bytes ) + { + STBIR_SIMD_NO_UNROLL_LOOP_START + do + { + STBIR_SIMD_NO_UNROLL(d); + d[ 0 ] = d[ ofs_to_src ]; + ++d; + } while ( d < d_end ); + } + } + else + { + stbir__simdf x; + // do one unaligned to get us aligned for the stream out below + stbir__simdf_load( x, ( d + ofs_to_src ) ); + stbir__simdf_store( d, x ); + d = (char*)( ( ( (size_t)d ) + 16 ) & ~15 ); + + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + STBIR_SIMD_NO_UNROLL(d); + + if ( d > ( d_end - 16 ) ) + { + if ( d == d_end ) + return; + d = d_end - 16; + } + + stbir__simdf_load( x, ( d + ofs_to_src ) ); + stbir__simdf_store( d, x ); + d += 16; + } + } + } + else + { + stbir__simdfX x0,x1,x2,x3; + + // do one unaligned to get us aligned for the stream out below + stbir__simdfX_load( x0, ( d + ofs_to_src ) + 0*stbir__simdfX_float_count ); + stbir__simdfX_load( x1, ( d + ofs_to_src ) + 4*stbir__simdfX_float_count ); + stbir__simdfX_load( x2, ( d + ofs_to_src ) + 8*stbir__simdfX_float_count ); + stbir__simdfX_load( x3, ( d + ofs_to_src ) + 12*stbir__simdfX_float_count ); + stbir__simdfX_store( d + 0*stbir__simdfX_float_count, x0 ); + stbir__simdfX_store( d + 4*stbir__simdfX_float_count, x1 ); + stbir__simdfX_store( d + 8*stbir__simdfX_float_count, x2 ); + stbir__simdfX_store( d + 12*stbir__simdfX_float_count, x3 ); + d = (char*)( ( ( (size_t)d ) + (16*stbir__simdfX_float_count) ) & ~((16*stbir__simdfX_float_count)-1) ); + + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + STBIR_SIMD_NO_UNROLL(d); + + if ( d > ( d_end - (16*stbir__simdfX_float_count) ) ) + { + if ( d == d_end ) + return; + d = d_end - (16*stbir__simdfX_float_count); + } + + stbir__simdfX_load( x0, ( d + ofs_to_src ) + 0*stbir__simdfX_float_count ); + stbir__simdfX_load( x1, ( d + ofs_to_src ) + 4*stbir__simdfX_float_count ); + stbir__simdfX_load( x2, ( d + ofs_to_src ) + 8*stbir__simdfX_float_count ); + stbir__simdfX_load( x3, ( d + ofs_to_src ) + 12*stbir__simdfX_float_count ); + stbir__simdfX_store( d + 0*stbir__simdfX_float_count, x0 ); + stbir__simdfX_store( d + 4*stbir__simdfX_float_count, x1 ); + stbir__simdfX_store( d + 8*stbir__simdfX_float_count, x2 ); + stbir__simdfX_store( d + 12*stbir__simdfX_float_count, x3 ); + d += (16*stbir__simdfX_float_count); + } + } +} + +// memcpy that is specically intentionally overlapping (src is smaller then dest, so can be +// a normal forward copy, bytes is divisible by 4 and bytes is greater than or equal to +// the diff between dest and src) +static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes ) +{ + char STBIR_SIMD_STREAMOUT_PTR (*) sd = (char*) src; + char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes; + ptrdiff_t ofs_to_dest = (char*)dest - (char*)src; + + if ( ofs_to_dest >= 16 ) // is the overlap more than 16 away? + { + char STBIR_SIMD_STREAMOUT_PTR( * ) s_end16 = ((char*) src) + (bytes&~15); + STBIR_SIMD_NO_UNROLL_LOOP_START + do + { + stbir__simdf x; + STBIR_SIMD_NO_UNROLL(sd); + stbir__simdf_load( x, sd ); + stbir__simdf_store( ( sd + ofs_to_dest ), x ); + sd += 16; + } while ( sd < s_end16 ); + + if ( sd == s_end ) + return; + } + + do + { + STBIR_SIMD_NO_UNROLL(sd); + *(int*)( sd + ofs_to_dest ) = *(int*) sd; + sd += 4; + } while ( sd < s_end ); +} + +#else // no SSE2 + +// when in scalar mode, we let unrolling happen, so this macro just does the __restrict +#define STBIR_SIMD_STREAMOUT_PTR( star ) STBIR_STREAMOUT_PTR( star ) +#define STBIR_SIMD_NO_UNROLL(ptr) +#define STBIR_SIMD_NO_UNROLL_LOOP_START +#define STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + +#endif // SSE2 + + +#ifdef STBIR_PROFILE + +#ifndef STBIR_PROFILE_FUNC + +#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined(STBIR_SSE) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ ) + +#ifdef _MSC_VER + + STBIRDEF stbir_uint64 __rdtsc(); + #define STBIR_PROFILE_FUNC() __rdtsc() + +#else // non msvc + + static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC() + { + stbir_uint32 lo, hi; + asm volatile ("rdtsc" : "=a" (lo), "=d" (hi) ); + return ( ( (stbir_uint64) hi ) << 32 ) | ( (stbir_uint64) lo ); + } + +#endif // msvc + +#elif defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__) + +#if defined( _MSC_VER ) && !defined(__clang__) + + #define STBIR_PROFILE_FUNC() _ReadStatusReg(ARM64_CNTVCT) + +#else + + static stbir__inline stbir_uint64 STBIR_PROFILE_FUNC() + { + stbir_uint64 tsc; + asm volatile("mrs %0, cntvct_el0" : "=r" (tsc)); + return tsc; + } + +#endif + +#else // x64, arm + +#error Unknown platform for profiling. + +#endif // x64, arm + +#endif // STBIR_PROFILE_FUNC + +#define STBIR_ONLY_PROFILE_GET_SPLIT_INFO ,stbir__per_split_info * split_info +#define STBIR_ONLY_PROFILE_SET_SPLIT_INFO ,split_info + +#define STBIR_ONLY_PROFILE_BUILD_GET_INFO ,stbir__info * profile_info +#define STBIR_ONLY_PROFILE_BUILD_SET_INFO ,profile_info + +// super light-weight micro profiler +#define STBIR_PROFILE_START_ll( info, wh ) { stbir_uint64 wh##thiszonetime = STBIR_PROFILE_FUNC(); stbir_uint64 * wh##save_parent_excluded_ptr = info->current_zone_excluded_ptr; stbir_uint64 wh##current_zone_excluded = 0; info->current_zone_excluded_ptr = &wh##current_zone_excluded; +#define STBIR_PROFILE_END_ll( info, wh ) wh##thiszonetime = STBIR_PROFILE_FUNC() - wh##thiszonetime; info->profile.named.wh += wh##thiszonetime - wh##current_zone_excluded; *wh##save_parent_excluded_ptr += wh##thiszonetime; info->current_zone_excluded_ptr = wh##save_parent_excluded_ptr; } +#define STBIR_PROFILE_FIRST_START_ll( info, wh ) { int i; info->current_zone_excluded_ptr = &info->profile.named.total; for(i=0;iprofile.array);i++) info->profile.array[i]=0; } STBIR_PROFILE_START_ll( info, wh ); +#define STBIR_PROFILE_CLEAR_EXTRAS_ll( info, num ) { int extra; for(extra=1;extra<(num);extra++) { int i; for(i=0;iprofile.array);i++) (info)[extra].profile.array[i]=0; } } + +// for thread data +#define STBIR_PROFILE_START( wh ) STBIR_PROFILE_START_ll( split_info, wh ) +#define STBIR_PROFILE_END( wh ) STBIR_PROFILE_END_ll( split_info, wh ) +#define STBIR_PROFILE_FIRST_START( wh ) STBIR_PROFILE_FIRST_START_ll( split_info, wh ) +#define STBIR_PROFILE_CLEAR_EXTRAS() STBIR_PROFILE_CLEAR_EXTRAS_ll( split_info, split_count ) + +// for build data +#define STBIR_PROFILE_BUILD_START( wh ) STBIR_PROFILE_START_ll( profile_info, wh ) +#define STBIR_PROFILE_BUILD_END( wh ) STBIR_PROFILE_END_ll( profile_info, wh ) +#define STBIR_PROFILE_BUILD_FIRST_START( wh ) STBIR_PROFILE_FIRST_START_ll( profile_info, wh ) +#define STBIR_PROFILE_BUILD_CLEAR( info ) { int i; for(i=0;iprofile.array);i++) info->profile.array[i]=0; } + +#else // no profile + +#define STBIR_ONLY_PROFILE_GET_SPLIT_INFO +#define STBIR_ONLY_PROFILE_SET_SPLIT_INFO + +#define STBIR_ONLY_PROFILE_BUILD_GET_INFO +#define STBIR_ONLY_PROFILE_BUILD_SET_INFO + +#define STBIR_PROFILE_START( wh ) +#define STBIR_PROFILE_END( wh ) +#define STBIR_PROFILE_FIRST_START( wh ) +#define STBIR_PROFILE_CLEAR_EXTRAS( ) + +#define STBIR_PROFILE_BUILD_START( wh ) +#define STBIR_PROFILE_BUILD_END( wh ) +#define STBIR_PROFILE_BUILD_FIRST_START( wh ) +#define STBIR_PROFILE_BUILD_CLEAR( info ) + +#endif // stbir_profile + +#ifndef STBIR_CEILF +#include +#if _MSC_VER <= 1200 // support VC6 for Sean +#define STBIR_CEILF(x) ((float)ceil((float)(x))) +#define STBIR_FLOORF(x) ((float)floor((float)(x))) +#else +#define STBIR_CEILF(x) ceilf(x) +#define STBIR_FLOORF(x) floorf(x) +#endif +#endif + +#ifndef STBIR_MEMCPY +// For memcpy +#include +#define STBIR_MEMCPY( dest, src, len ) memcpy( dest, src, len ) +#endif + +#ifndef STBIR_SIMD + +// memcpy that is specifically intentionally overlapping (src is smaller then dest, so can be +// a normal forward copy, bytes is divisible by 4 and bytes is greater than or equal to +// the diff between dest and src) +static void stbir_overlapping_memcpy( void * dest, void const * src, size_t bytes ) +{ + char STBIR_SIMD_STREAMOUT_PTR (*) sd = (char*) src; + char STBIR_SIMD_STREAMOUT_PTR( * ) s_end = ((char*) src) + bytes; + ptrdiff_t ofs_to_dest = (char*)dest - (char*)src; + + if ( ofs_to_dest >= 8 ) // is the overlap more than 8 away? + { + char STBIR_SIMD_STREAMOUT_PTR( * ) s_end8 = ((char*) src) + (bytes&~7); + STBIR_NO_UNROLL_LOOP_START + do + { + STBIR_NO_UNROLL(sd); + *(stbir_uint64*)( sd + ofs_to_dest ) = *(stbir_uint64*) sd; + sd += 8; + } while ( sd < s_end8 ); + + if ( sd == s_end ) + return; + } + + STBIR_NO_UNROLL_LOOP_START + do + { + STBIR_NO_UNROLL(sd); + *(int*)( sd + ofs_to_dest ) = *(int*) sd; + sd += 4; + } while ( sd < s_end ); +} + +#endif + +static float stbir__filter_trapezoid(float x, float scale, void * user_data) +{ + float halfscale = scale / 2; + float t = 0.5f + halfscale; + STBIR_ASSERT(scale <= 1); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x >= t) + return 0.0f; + else + { + float r = 0.5f - halfscale; + if (x <= r) + return 1.0f; + else + return (t - x) / scale; + } +} + +static float stbir__support_trapezoid(float scale, void * user_data) +{ + STBIR__UNUSED(user_data); + return 0.5f + scale / 2.0f; +} + +static float stbir__filter_triangle(float x, float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x <= 1.0f) + return 1.0f - x; + else + return 0.0f; +} + +static float stbir__filter_point(float x, float s, void * user_data) +{ + STBIR__UNUSED(x); + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + return 1.0f; +} + +static float stbir__filter_cubic(float x, float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x < 1.0f) + return (4.0f + x*x*(3.0f*x - 6.0f))/6.0f; + else if (x < 2.0f) + return (8.0f + x*(-12.0f + x*(6.0f - x)))/6.0f; + + return (0.0f); +} + +static float stbir__filter_catmullrom(float x, float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x < 1.0f) + return 1.0f - x*x*(2.5f - 1.5f*x); + else if (x < 2.0f) + return 2.0f - x*(4.0f + x*(0.5f*x - 2.5f)); + + return (0.0f); +} + +static float stbir__filter_mitchell(float x, float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + + if ( x < 0.0f ) x = -x; + + if (x < 1.0f) + return (16.0f + x*x*(21.0f * x - 36.0f))/18.0f; + else if (x < 2.0f) + return (32.0f + x*(-60.0f + x*(36.0f - 7.0f*x)))/18.0f; + + return (0.0f); +} + +static float stbir__support_zeropoint5(float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + return 0.5f; +} + +static float stbir__support_one(float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + return 1; +} + +static float stbir__support_two(float s, void * user_data) +{ + STBIR__UNUSED(s); + STBIR__UNUSED(user_data); + return 2; +} + +// This is the maximum number of input samples that can affect an output sample +// with the given filter from the output pixel's perspective +static int stbir__get_filter_pixel_width(stbir__support_callback * support, float scale, void * user_data) +{ + STBIR_ASSERT(support != 0); + + if ( scale >= ( 1.0f-stbir__small_float ) ) // upscale + return (int)STBIR_CEILF(support(1.0f/scale,user_data) * 2.0f); + else + return (int)STBIR_CEILF(support(scale,user_data) * 2.0f / scale); +} + +// this is how many coefficents per run of the filter (which is different +// from the filter_pixel_width depending on if we are scattering or gathering) +static int stbir__get_coefficient_width(stbir__sampler * samp, int is_gather, void * user_data) +{ + float scale = samp->scale_info.scale; + stbir__support_callback * support = samp->filter_support; + + switch( is_gather ) + { + case 1: + return (int)STBIR_CEILF(support(1.0f / scale, user_data) * 2.0f); + case 2: + return (int)STBIR_CEILF(support(scale, user_data) * 2.0f / scale); + case 0: + return (int)STBIR_CEILF(support(scale, user_data) * 2.0f); + default: + STBIR_ASSERT( (is_gather >= 0 ) && (is_gather <= 2 ) ); + return 0; + } +} + +static int stbir__get_contributors(stbir__sampler * samp, int is_gather) +{ + if (is_gather) + return samp->scale_info.output_sub_size; + else + return (samp->scale_info.input_full_size + samp->filter_pixel_margin * 2); +} + +static int stbir__edge_zero_full( int n, int max ) +{ + STBIR__UNUSED(n); + STBIR__UNUSED(max); + return 0; // NOTREACHED +} + +static int stbir__edge_clamp_full( int n, int max ) +{ + if (n < 0) + return 0; + + if (n >= max) + return max - 1; + + return n; // NOTREACHED +} + +static int stbir__edge_reflect_full( int n, int max ) +{ + if (n < 0) + { + if (n > -max) + return -n; + else + return max - 1; + } + + if (n >= max) + { + int max2 = max * 2; + if (n >= max2) + return 0; + else + return max2 - n - 1; + } + + return n; // NOTREACHED +} + +static int stbir__edge_wrap_full( int n, int max ) +{ + if (n >= 0) + return (n % max); + else + { + int m = (-n) % max; + + if (m != 0) + m = max - m; + + return (m); + } +} + +typedef int stbir__edge_wrap_func( int n, int max ); +static stbir__edge_wrap_func * stbir__edge_wrap_slow[] = +{ + stbir__edge_clamp_full, // STBIR_EDGE_CLAMP + stbir__edge_reflect_full, // STBIR_EDGE_REFLECT + stbir__edge_wrap_full, // STBIR_EDGE_WRAP + stbir__edge_zero_full, // STBIR_EDGE_ZERO +}; + +stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) +{ + // avoid per-pixel switch + if (n >= 0 && n < max) + return n; + return stbir__edge_wrap_slow[edge]( n, max ); +} + +#define STBIR__MERGE_RUNS_PIXEL_THRESHOLD 16 + +// get information on the extents of a sampler +static void stbir__get_extents( stbir__sampler * samp, stbir__extents * scanline_extents ) +{ + int j, stop; + int left_margin, right_margin; + int min_n = 0x7fffffff, max_n = -0x7fffffff; + int min_left = 0x7fffffff, max_left = -0x7fffffff; + int min_right = 0x7fffffff, max_right = -0x7fffffff; + stbir_edge edge = samp->edge; + stbir__contributors* contributors = samp->contributors; + int output_sub_size = samp->scale_info.output_sub_size; + int input_full_size = samp->scale_info.input_full_size; + int filter_pixel_margin = samp->filter_pixel_margin; + + STBIR_ASSERT( samp->is_gather ); + + stop = output_sub_size; + for (j = 0; j < stop; j++ ) + { + STBIR_ASSERT( contributors[j].n1 >= contributors[j].n0 ); + if ( contributors[j].n0 < min_n ) + { + min_n = contributors[j].n0; + stop = j + filter_pixel_margin; // if we find a new min, only scan another filter width + if ( stop > output_sub_size ) stop = output_sub_size; + } + } + + stop = 0; + for (j = output_sub_size - 1; j >= stop; j-- ) + { + STBIR_ASSERT( contributors[j].n1 >= contributors[j].n0 ); + if ( contributors[j].n1 > max_n ) + { + max_n = contributors[j].n1; + stop = j - filter_pixel_margin; // if we find a new max, only scan another filter width + if (stop<0) stop = 0; + } + } + + STBIR_ASSERT( scanline_extents->conservative.n0 <= min_n ); + STBIR_ASSERT( scanline_extents->conservative.n1 >= max_n ); + + // now calculate how much into the margins we really read + left_margin = 0; + if ( min_n < 0 ) + { + left_margin = -min_n; + min_n = 0; + } + + right_margin = 0; + if ( max_n >= input_full_size ) + { + right_margin = max_n - input_full_size + 1; + max_n = input_full_size - 1; + } + + // index 1 is margin pixel extents (how many pixels we hang over the edge) + scanline_extents->edge_sizes[0] = left_margin; + scanline_extents->edge_sizes[1] = right_margin; + + // index 2 is pixels read from the input + scanline_extents->spans[0].n0 = min_n; + scanline_extents->spans[0].n1 = max_n; + scanline_extents->spans[0].pixel_offset_for_input = min_n; + + // default to no other input range + scanline_extents->spans[1].n0 = 0; + scanline_extents->spans[1].n1 = -1; + scanline_extents->spans[1].pixel_offset_for_input = 0; + + // don't have to do edge calc for zero clamp + if ( edge == STBIR_EDGE_ZERO ) + return; + + // convert margin pixels to the pixels within the input (min and max) + for( j = -left_margin ; j < 0 ; j++ ) + { + int p = stbir__edge_wrap( edge, j, input_full_size ); + if ( p < min_left ) + min_left = p; + if ( p > max_left ) + max_left = p; + } + + for( j = input_full_size ; j < (input_full_size + right_margin) ; j++ ) + { + int p = stbir__edge_wrap( edge, j, input_full_size ); + if ( p < min_right ) + min_right = p; + if ( p > max_right ) + max_right = p; + } + + // merge the left margin pixel region if it connects within 4 pixels of main pixel region + if ( min_left != 0x7fffffff ) + { + if ( ( ( min_left <= min_n ) && ( ( max_left + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= min_n ) ) || + ( ( min_n <= min_left ) && ( ( max_n + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= max_left ) ) ) + { + scanline_extents->spans[0].n0 = min_n = stbir__min( min_n, min_left ); + scanline_extents->spans[0].n1 = max_n = stbir__max( max_n, max_left ); + scanline_extents->spans[0].pixel_offset_for_input = min_n; + left_margin = 0; + } + } + + // merge the right margin pixel region if it connects within 4 pixels of main pixel region + if ( min_right != 0x7fffffff ) + { + if ( ( ( min_right <= min_n ) && ( ( max_right + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= min_n ) ) || + ( ( min_n <= min_right ) && ( ( max_n + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= max_right ) ) ) + { + scanline_extents->spans[0].n0 = min_n = stbir__min( min_n, min_right ); + scanline_extents->spans[0].n1 = max_n = stbir__max( max_n, max_right ); + scanline_extents->spans[0].pixel_offset_for_input = min_n; + right_margin = 0; + } + } + + STBIR_ASSERT( scanline_extents->conservative.n0 <= min_n ); + STBIR_ASSERT( scanline_extents->conservative.n1 >= max_n ); + + // you get two ranges when you have the WRAP edge mode and you are doing just the a piece of the resize + // so you need to get a second run of pixels from the opposite side of the scanline (which you + // wouldn't need except for WRAP) + + + // if we can't merge the min_left range, add it as a second range + if ( ( left_margin ) && ( min_left != 0x7fffffff ) ) + { + stbir__span * newspan = scanline_extents->spans + 1; + STBIR_ASSERT( right_margin == 0 ); + if ( min_left < scanline_extents->spans[0].n0 ) + { + scanline_extents->spans[1].pixel_offset_for_input = scanline_extents->spans[0].n0; + scanline_extents->spans[1].n0 = scanline_extents->spans[0].n0; + scanline_extents->spans[1].n1 = scanline_extents->spans[0].n1; + --newspan; + } + newspan->pixel_offset_for_input = min_left; + newspan->n0 = -left_margin; + newspan->n1 = ( max_left - min_left ) - left_margin; + scanline_extents->edge_sizes[0] = 0; // don't need to copy the left margin, since we are directly decoding into the margin + return; + } + + // if we can't merge the min_left range, add it as a second range + if ( ( right_margin ) && ( min_right != 0x7fffffff ) ) + { + stbir__span * newspan = scanline_extents->spans + 1; + if ( min_right < scanline_extents->spans[0].n0 ) + { + scanline_extents->spans[1].pixel_offset_for_input = scanline_extents->spans[0].n0; + scanline_extents->spans[1].n0 = scanline_extents->spans[0].n0; + scanline_extents->spans[1].n1 = scanline_extents->spans[0].n1; + --newspan; + } + newspan->pixel_offset_for_input = min_right; + newspan->n0 = scanline_extents->spans[1].n1 + 1; + newspan->n1 = scanline_extents->spans[1].n1 + 1 + ( max_right - min_right ); + scanline_extents->edge_sizes[1] = 0; // don't need to copy the right margin, since we are directly decoding into the margin + return; + } +} + +static void stbir__calculate_in_pixel_range( int * first_pixel, int * last_pixel, float out_pixel_center, float out_filter_radius, float inv_scale, float out_shift, int input_size, stbir_edge edge ) +{ + int first, last; + float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; + float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; + + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) * inv_scale; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) * inv_scale; + + first = (int)(STBIR_FLOORF(in_pixel_influence_lowerbound + 0.5f)); + last = (int)(STBIR_FLOORF(in_pixel_influence_upperbound - 0.5f)); + + if ( edge == STBIR_EDGE_WRAP ) + { + if ( first < -input_size ) + first = -input_size; + if ( last >= (input_size*2)) + last = (input_size*2) - 1; + } + + *first_pixel = first; + *last_pixel = last; +} + +static void stbir__calculate_coefficients_for_gather_upsample( float out_filter_radius, stbir__kernel_callback * kernel, stbir__scale_info * scale_info, int num_contributors, stbir__contributors* contributors, float* coefficient_group, int coefficient_width, stbir_edge edge, void * user_data ) +{ + int n, end; + float inv_scale = scale_info->inv_scale; + float out_shift = scale_info->pixel_shift; + int input_size = scale_info->input_full_size; + int numerator = scale_info->scale_numerator; + int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < num_contributors ) ); + + // Looping through out pixels + end = num_contributors; if ( polyphase ) end = numerator; + for (n = 0; n < end; n++) + { + int i; + int last_non_zero; + float out_pixel_center = (float)n + 0.5f; + float in_center_of_out = (out_pixel_center + out_shift) * inv_scale; + + int in_first_pixel, in_last_pixel; + + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, out_pixel_center, out_filter_radius, inv_scale, out_shift, input_size, edge ); + + last_non_zero = -1; + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + { + float in_pixel_center = (float)(i + in_first_pixel) + 0.5f; + float coeff = kernel(in_center_of_out - in_pixel_center, inv_scale, user_data); + + // kill denormals + if ( ( ( coeff < stbir__small_float ) && ( coeff > -stbir__small_float ) ) ) + { + if ( i == 0 ) // if we're at the front, just eat zero contributors + { + STBIR_ASSERT ( ( in_last_pixel - in_first_pixel ) != 0 ); // there should be at least one contrib + ++in_first_pixel; + i--; + continue; + } + coeff = 0; // make sure is fully zero (should keep denormals away) + } + else + last_non_zero = i; + + coefficient_group[i] = coeff; + } + + in_last_pixel = last_non_zero+in_first_pixel; // kills trailing zeros + contributors->n0 = in_first_pixel; + contributors->n1 = in_last_pixel; + + STBIR_ASSERT(contributors->n1 >= contributors->n0); + + ++contributors; + coefficient_group += coefficient_width; + } +} + +static void stbir__insert_coeff( stbir__contributors * contribs, float * coeffs, int new_pixel, float new_coeff ) +{ + if ( new_pixel <= contribs->n1 ) // before the end + { + if ( new_pixel < contribs->n0 ) // before the front? + { + int j, o = contribs->n0 - new_pixel; + for ( j = contribs->n1 - contribs->n0 ; j <= 0 ; j-- ) + coeffs[ j + o ] = coeffs[ j ]; + for ( j = 1 ; j < o ; j-- ) + coeffs[ j ] = coeffs[ 0 ]; + coeffs[ 0 ] = new_coeff; + contribs->n0 = new_pixel; + } + else + { + coeffs[ new_pixel - contribs->n0 ] += new_coeff; + } + } + else + { + int j, e = new_pixel - contribs->n0; + for( j = ( contribs->n1 - contribs->n0 ) + 1 ; j < e ; j++ ) // clear in-betweens coeffs if there are any + coeffs[j] = 0; + + coeffs[ e ] = new_coeff; + contribs->n1 = new_pixel; + } +} + +static void stbir__calculate_out_pixel_range( int * first_pixel, int * last_pixel, float in_pixel_center, float in_pixels_radius, float scale, float out_shift, int out_size ) +{ + float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; + float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; + float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale - out_shift; + int out_first_pixel = (int)(STBIR_FLOORF(out_pixel_influence_lowerbound + 0.5f)); + int out_last_pixel = (int)(STBIR_FLOORF(out_pixel_influence_upperbound - 0.5f)); + + if ( out_first_pixel < 0 ) + out_first_pixel = 0; + if ( out_last_pixel >= out_size ) + out_last_pixel = out_size - 1; + *first_pixel = out_first_pixel; + *last_pixel = out_last_pixel; +} + +static void stbir__calculate_coefficients_for_gather_downsample( int start, int end, float in_pixels_radius, stbir__kernel_callback * kernel, stbir__scale_info * scale_info, int coefficient_width, int num_contributors, stbir__contributors * contributors, float * coefficient_group, void * user_data ) +{ + int in_pixel; + int i; + int first_out_inited = -1; + float scale = scale_info->scale; + float out_shift = scale_info->pixel_shift; + int out_size = scale_info->output_sub_size; + int numerator = scale_info->scale_numerator; + int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < out_size ) ); + + STBIR__UNUSED(num_contributors); + + // Loop through the input pixels + for (in_pixel = start; in_pixel < end; in_pixel++) + { + float in_pixel_center = (float)in_pixel + 0.5f; + float out_center_of_in = in_pixel_center * scale - out_shift; + int out_first_pixel, out_last_pixel; + + stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, in_pixel_center, in_pixels_radius, scale, out_shift, out_size ); + + if ( out_first_pixel > out_last_pixel ) + continue; + + // clamp or exit if we are using polyphase filtering, and the limit is up + if ( polyphase ) + { + // when polyphase, you only have to do coeffs up to the numerator count + if ( out_first_pixel == numerator ) + break; + + // don't do any extra work, clamp last pixel at numerator too + if ( out_last_pixel >= numerator ) + out_last_pixel = numerator - 1; + } + + for (i = 0; i <= out_last_pixel - out_first_pixel; i++) + { + float out_pixel_center = (float)(i + out_first_pixel) + 0.5f; + float x = out_pixel_center - out_center_of_in; + float coeff = kernel(x, scale, user_data) * scale; + + // kill the coeff if it's too small (avoid denormals) + if ( ( ( coeff < stbir__small_float ) && ( coeff > -stbir__small_float ) ) ) + coeff = 0.0f; + + { + int out = i + out_first_pixel; + float * coeffs = coefficient_group + out * coefficient_width; + stbir__contributors * contribs = contributors + out; + + // is this the first time this output pixel has been seen? Init it. + if ( out > first_out_inited ) + { + STBIR_ASSERT( out == ( first_out_inited + 1 ) ); // ensure we have only advanced one at time + first_out_inited = out; + contribs->n0 = in_pixel; + contribs->n1 = in_pixel; + coeffs[0] = coeff; + } + else + { + // insert on end (always in order) + if ( coeffs[0] == 0.0f ) // if the first coefficent is zero, then zap it for this coeffs + { + STBIR_ASSERT( ( in_pixel - contribs->n0 ) == 1 ); // ensure that when we zap, we're at the 2nd pos + contribs->n0 = in_pixel; + } + contribs->n1 = in_pixel; + STBIR_ASSERT( ( in_pixel - contribs->n0 ) < coefficient_width ); + coeffs[in_pixel - contribs->n0] = coeff; + } + } + } + } +} + +#ifdef STBIR_RENORMALIZE_IN_FLOAT +#define STBIR_RENORM_TYPE float +#else +#define STBIR_RENORM_TYPE double +#endif + +static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter_extent_info* filter_info, stbir__scale_info * scale_info, int num_contributors, stbir__contributors* contributors, float * coefficient_group, int coefficient_width ) +{ + int input_size = scale_info->input_full_size; + int input_last_n1 = input_size - 1; + int n, end; + int lowest = 0x7fffffff; + int highest = -0x7fffffff; + int widest = -1; + int numerator = scale_info->scale_numerator; + int denominator = scale_info->scale_denominator; + int polyphase = ( ( scale_info->scale_is_rational ) && ( numerator < num_contributors ) ); + float * coeffs; + stbir__contributors * contribs; + + // weight all the coeffs for each sample + coeffs = coefficient_group; + contribs = contributors; + end = num_contributors; if ( polyphase ) end = numerator; + for (n = 0; n < end; n++) + { + int i; + STBIR_RENORM_TYPE filter_scale, total_filter = 0; + int e; + + // add all contribs + e = contribs->n1 - contribs->n0; + for( i = 0 ; i <= e ; i++ ) + { + total_filter += (STBIR_RENORM_TYPE) coeffs[i]; + STBIR_ASSERT( ( coeffs[i] >= -2.0f ) && ( coeffs[i] <= 2.0f ) ); // check for wonky weights + } + + // rescale + if ( ( total_filter < stbir__small_float ) && ( total_filter > -stbir__small_float ) ) + { + // all coeffs are extremely small, just zero it + contribs->n1 = contribs->n0; + coeffs[0] = 0.0f; + } + else + { + // if the total isn't 1.0, rescale everything + if ( ( total_filter < (1.0f-stbir__small_float) ) || ( total_filter > (1.0f+stbir__small_float) ) ) + { + filter_scale = ((STBIR_RENORM_TYPE)1.0) / total_filter; + + // scale them all + for (i = 0; i <= e; i++) + coeffs[i] = (float) ( coeffs[i] * filter_scale ); + } + } + ++contribs; + coeffs += coefficient_width; + } + + // if we have a rational for the scale, we can exploit the polyphaseness to not calculate + // most of the coefficients, so we copy them here + if ( polyphase ) + { + stbir__contributors * prev_contribs = contributors; + stbir__contributors * cur_contribs = contributors + numerator; + + for( n = numerator ; n < num_contributors ; n++ ) + { + cur_contribs->n0 = prev_contribs->n0 + denominator; + cur_contribs->n1 = prev_contribs->n1 + denominator; + ++cur_contribs; + ++prev_contribs; + } + stbir_overlapping_memcpy( coefficient_group + numerator * coefficient_width, coefficient_group, ( num_contributors - numerator ) * coefficient_width * sizeof( coeffs[ 0 ] ) ); + } + + coeffs = coefficient_group; + contribs = contributors; + for (n = 0; n < num_contributors; n++) + { + int i; + + // in zero edge mode, just remove out of bounds contribs completely (since their weights are accounted for now) + if ( edge == STBIR_EDGE_ZERO ) + { + // shrink the right side if necessary + if ( contribs->n1 > input_last_n1 ) + contribs->n1 = input_last_n1; + + // shrink the left side + if ( contribs->n0 < 0 ) + { + int j, left, skips = 0; + + skips = -contribs->n0; + contribs->n0 = 0; + + // now move down the weights + left = contribs->n1 - contribs->n0 + 1; + if ( left > 0 ) + { + for( j = 0 ; j < left ; j++ ) + coeffs[ j ] = coeffs[ j + skips ]; + } + } + } + else if ( ( edge == STBIR_EDGE_CLAMP ) || ( edge == STBIR_EDGE_REFLECT ) ) + { + // for clamp and reflect, calculate the true inbounds position (based on edge type) and just add that to the existing weight + + // right hand side first + if ( contribs->n1 > input_last_n1 ) + { + int start = contribs->n0; + int endi = contribs->n1; + contribs->n1 = input_last_n1; + for( i = input_size; i <= endi; i++ ) + stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( i, input_size ), coeffs[i-start] ); + } + + // now check left hand edge + if ( contribs->n0 < 0 ) + { + int save_n0; + float save_n0_coeff; + float * c = coeffs - ( contribs->n0 + 1 ); + + // reinsert the coeffs with it reflected or clamped (insert accumulates, if the coeffs exist) + for( i = -1 ; i > contribs->n0 ; i-- ) + stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( i, input_size ), *c-- ); + save_n0 = contribs->n0; + save_n0_coeff = c[0]; // save it, since we didn't do the final one (i==n0), because there might be too many coeffs to hold (before we resize)! + + // now slide all the coeffs down (since we have accumulated them in the positive contribs) and reset the first contrib + contribs->n0 = 0; + for(i = 0 ; i <= contribs->n1 ; i++ ) + coeffs[i] = coeffs[i-save_n0]; + + // now that we have shrunk down the contribs, we insert the first one safely + stbir__insert_coeff( contribs, coeffs, stbir__edge_wrap_slow[edge]( save_n0, input_size ), save_n0_coeff ); + } + } + + if ( contribs->n0 <= contribs->n1 ) + { + int diff = contribs->n1 - contribs->n0 + 1; + while ( diff && ( coeffs[ diff-1 ] == 0.0f ) ) + --diff; + contribs->n1 = contribs->n0 + diff - 1; + + if ( contribs->n0 <= contribs->n1 ) + { + if ( contribs->n0 < lowest ) + lowest = contribs->n0; + if ( contribs->n1 > highest ) + highest = contribs->n1; + if ( diff > widest ) + widest = diff; + } + + // re-zero out unused coefficients (if any) + for( i = diff ; i < coefficient_width ; i++ ) + coeffs[i] = 0.0f; + } + + ++contribs; + coeffs += coefficient_width; + } + filter_info->lowest = lowest; + filter_info->highest = highest; + filter_info->widest = widest; +} + +#undef STBIR_RENORM_TYPE + +static int stbir__pack_coefficients( int num_contributors, stbir__contributors* contributors, float * coefficents, int coefficient_width, int widest, int row0, int row1 ) +{ + #define STBIR_MOVE_1( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint32*)(dest))[0] = ((stbir_uint32*)(src))[0]; } + #define STBIR_MOVE_2( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; } + #ifdef STBIR_SIMD + #define STBIR_MOVE_4( dest, src ) { stbir__simdf t; STBIR_NO_UNROLL(dest); stbir__simdf_load( t, src ); stbir__simdf_store( dest, t ); } + #else + #define STBIR_MOVE_4( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; ((stbir_uint64*)(dest))[1] = ((stbir_uint64*)(src))[1]; } + #endif + + int row_end = row1 + 1; + STBIR__UNUSED( row0 ); // only used in an assert + + if ( coefficient_width != widest ) + { + float * pc = coefficents; + float * coeffs = coefficents; + float * pc_end = coefficents + num_contributors * widest; + switch( widest ) + { + case 1: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_1( pc, coeffs ); + ++pc; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 2: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_2( pc, coeffs ); + pc += 2; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 3: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_2( pc, coeffs ); + STBIR_MOVE_1( pc+2, coeffs+2 ); + pc += 3; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 4: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + pc += 4; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 5: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_1( pc+4, coeffs+4 ); + pc += 5; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 6: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_2( pc+4, coeffs+4 ); + pc += 6; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 7: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_2( pc+4, coeffs+4 ); + STBIR_MOVE_1( pc+6, coeffs+6 ); + pc += 7; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 8: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + pc += 8; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 9: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + STBIR_MOVE_1( pc+8, coeffs+8 ); + pc += 9; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 10: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + STBIR_MOVE_2( pc+8, coeffs+8 ); + pc += 10; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 11: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + STBIR_MOVE_2( pc+8, coeffs+8 ); + STBIR_MOVE_1( pc+10, coeffs+10 ); + pc += 11; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + case 12: + STBIR_NO_UNROLL_LOOP_START + do { + STBIR_MOVE_4( pc, coeffs ); + STBIR_MOVE_4( pc+4, coeffs+4 ); + STBIR_MOVE_4( pc+8, coeffs+8 ); + pc += 12; + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + default: + STBIR_NO_UNROLL_LOOP_START + do { + float * copy_end = pc + widest - 4; + float * c = coeffs; + do { + STBIR_NO_UNROLL( pc ); + STBIR_MOVE_4( pc, c ); + pc += 4; + c += 4; + } while ( pc <= copy_end ); + copy_end += 4; + STBIR_NO_UNROLL_LOOP_START + while ( pc < copy_end ) + { + STBIR_MOVE_1( pc, c ); + ++pc; ++c; + } + coeffs += coefficient_width; + } while ( pc < pc_end ); + break; + } + } + + // some horizontal routines read one float off the end (which is then masked off), so put in a sentinal so we don't read an snan or denormal + coefficents[ widest * num_contributors ] = 8888.0f; + + // the minimum we might read for unrolled filters widths is 12. So, we need to + // make sure we never read outside the decode buffer, by possibly moving + // the sample area back into the scanline, and putting zeros weights first. + // we start on the right edge and check until we're well past the possible + // clip area (2*widest). + { + stbir__contributors * contribs = contributors + num_contributors - 1; + float * coeffs = coefficents + widest * ( num_contributors - 1 ); + + // go until no chance of clipping (this is usually less than 8 lops) + while ( ( contribs >= contributors ) && ( ( contribs->n0 + widest*2 ) >= row_end ) ) + { + // might we clip?? + if ( ( contribs->n0 + widest ) > row_end ) + { + int stop_range = widest; + + // if range is larger than 12, it will be handled by generic loops that can terminate on the exact length + // of this contrib n1, instead of a fixed widest amount - so calculate this + if ( widest > 12 ) + { + int mod; + + // how far will be read in the n_coeff loop (which depends on the widest count mod4); + mod = widest & 3; + stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod; + + // the n_coeff loops do a minimum amount of coeffs, so factor that in! + if ( stop_range < ( 8 + mod ) ) stop_range = 8 + mod; + } + + // now see if we still clip with the refined range + if ( ( contribs->n0 + stop_range ) > row_end ) + { + int new_n0 = row_end - stop_range; + int num = contribs->n1 - contribs->n0 + 1; + int backup = contribs->n0 - new_n0; + float * from_co = coeffs + num - 1; + float * to_co = from_co + backup; + + STBIR_ASSERT( ( new_n0 >= row0 ) && ( new_n0 < contribs->n0 ) ); + + // move the coeffs over + while( num ) + { + *to_co-- = *from_co--; + --num; + } + // zero new positions + while ( to_co >= coeffs ) + *to_co-- = 0; + // set new start point + contribs->n0 = new_n0; + if ( widest > 12 ) + { + int mod; + + // how far will be read in the n_coeff loop (which depends on the widest count mod4); + mod = widest & 3; + stop_range = ( ( ( contribs->n1 - contribs->n0 + 1 ) - mod + 3 ) & ~3 ) + mod; + + // the n_coeff loops do a minimum amount of coeffs, so factor that in! + if ( stop_range < ( 8 + mod ) ) stop_range = 8 + mod; + } + } + } + --contribs; + coeffs -= widest; + } + } + + return widest; + #undef STBIR_MOVE_1 + #undef STBIR_MOVE_2 + #undef STBIR_MOVE_4 +} + +static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * other_axis_for_pivot, void * user_data STBIR_ONLY_PROFILE_BUILD_GET_INFO ) +{ + int n; + float scale = samp->scale_info.scale; + stbir__kernel_callback * kernel = samp->filter_kernel; + stbir__support_callback * support = samp->filter_support; + float inv_scale = samp->scale_info.inv_scale; + int input_full_size = samp->scale_info.input_full_size; + int gather_num_contributors = samp->num_contributors; + stbir__contributors* gather_contributors = samp->contributors; + float * gather_coeffs = samp->coefficients; + int gather_coefficient_width = samp->coefficient_width; + + switch ( samp->is_gather ) + { + case 1: // gather upsample + { + float out_pixels_radius = support(inv_scale,user_data) * scale; + + stbir__calculate_coefficients_for_gather_upsample( out_pixels_radius, kernel, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width, samp->edge, user_data ); + + STBIR_PROFILE_BUILD_START( cleanup ); + stbir__cleanup_gathered_coefficients( samp->edge, &samp->extent_info, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width ); + STBIR_PROFILE_BUILD_END( cleanup ); + } + break; + + case 0: // scatter downsample (only on vertical) + case 2: // gather downsample + { + float in_pixels_radius = support(scale,user_data) * inv_scale; + int filter_pixel_margin = samp->filter_pixel_margin; + int input_end = input_full_size + filter_pixel_margin; + + // if this is a scatter, we do a downsample gather to get the coeffs, and then pivot after + if ( !samp->is_gather ) + { + // check if we are using the same gather downsample on the horizontal as this vertical, + // if so, then we don't have to generate them, we can just pivot from the horizontal. + if ( other_axis_for_pivot ) + { + gather_contributors = other_axis_for_pivot->contributors; + gather_coeffs = other_axis_for_pivot->coefficients; + gather_coefficient_width = other_axis_for_pivot->coefficient_width; + gather_num_contributors = other_axis_for_pivot->num_contributors; + samp->extent_info.lowest = other_axis_for_pivot->extent_info.lowest; + samp->extent_info.highest = other_axis_for_pivot->extent_info.highest; + samp->extent_info.widest = other_axis_for_pivot->extent_info.widest; + goto jump_right_to_pivot; + } + + gather_contributors = samp->gather_prescatter_contributors; + gather_coeffs = samp->gather_prescatter_coefficients; + gather_coefficient_width = samp->gather_prescatter_coefficient_width; + gather_num_contributors = samp->gather_prescatter_num_contributors; + } + + stbir__calculate_coefficients_for_gather_downsample( -filter_pixel_margin, input_end, in_pixels_radius, kernel, &samp->scale_info, gather_coefficient_width, gather_num_contributors, gather_contributors, gather_coeffs, user_data ); + + STBIR_PROFILE_BUILD_START( cleanup ); + stbir__cleanup_gathered_coefficients( samp->edge, &samp->extent_info, &samp->scale_info, gather_num_contributors, gather_contributors, gather_coeffs, gather_coefficient_width ); + STBIR_PROFILE_BUILD_END( cleanup ); + + if ( !samp->is_gather ) + { + // if this is a scatter (vertical only), then we need to pivot the coeffs + stbir__contributors * scatter_contributors; + int highest_set; + + jump_right_to_pivot: + + STBIR_PROFILE_BUILD_START( pivot ); + + highest_set = (-filter_pixel_margin) - 1; + for (n = 0; n < gather_num_contributors; n++) + { + int k; + int gn0 = gather_contributors->n0, gn1 = gather_contributors->n1; + int scatter_coefficient_width = samp->coefficient_width; + float * scatter_coeffs = samp->coefficients + ( gn0 + filter_pixel_margin ) * scatter_coefficient_width; + float * g_coeffs = gather_coeffs; + scatter_contributors = samp->contributors + ( gn0 + filter_pixel_margin ); + + for (k = gn0 ; k <= gn1 ; k++ ) + { + float gc = *g_coeffs++; + + // skip zero and denormals - must skip zeros to avoid adding coeffs beyond scatter_coefficient_width + // (which happens when pivoting from horizontal, which might have dummy zeros) + if ( ( ( gc >= stbir__small_float ) || ( gc <= -stbir__small_float ) ) ) + { + if ( ( k > highest_set ) || ( scatter_contributors->n0 > scatter_contributors->n1 ) ) + { + { + // if we are skipping over several contributors, we need to clear the skipped ones + stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1); + while ( clear_contributors < scatter_contributors ) + { + clear_contributors->n0 = 0; + clear_contributors->n1 = -1; + ++clear_contributors; + } + } + scatter_contributors->n0 = n; + scatter_contributors->n1 = n; + scatter_coeffs[0] = gc; + highest_set = k; + } + else + { + stbir__insert_coeff( scatter_contributors, scatter_coeffs, n, gc ); + } + STBIR_ASSERT( ( scatter_contributors->n1 - scatter_contributors->n0 + 1 ) <= scatter_coefficient_width ); + } + ++scatter_contributors; + scatter_coeffs += scatter_coefficient_width; + } + + ++gather_contributors; + gather_coeffs += gather_coefficient_width; + } + + // now clear any unset contribs + { + stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1); + stbir__contributors * end_contributors = samp->contributors + samp->num_contributors; + while ( clear_contributors < end_contributors ) + { + clear_contributors->n0 = 0; + clear_contributors->n1 = -1; + ++clear_contributors; + } + } + + STBIR_PROFILE_BUILD_END( pivot ); + } + } + break; + } +} + + +//======================================================================================================== +// scanline decoders and encoders + +#define stbir__coder_min_num 1 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + +#define stbir__decode_suffix BGRA +#define stbir__decode_swizzle +#define stbir__decode_order0 2 +#define stbir__decode_order1 1 +#define stbir__decode_order2 0 +#define stbir__decode_order3 3 +#define stbir__encode_order0 2 +#define stbir__encode_order1 1 +#define stbir__encode_order2 0 +#define stbir__encode_order3 3 +#define stbir__coder_min_num 4 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + +#define stbir__decode_suffix ARGB +#define stbir__decode_swizzle +#define stbir__decode_order0 1 +#define stbir__decode_order1 2 +#define stbir__decode_order2 3 +#define stbir__decode_order3 0 +#define stbir__encode_order0 3 +#define stbir__encode_order1 0 +#define stbir__encode_order2 1 +#define stbir__encode_order3 2 +#define stbir__coder_min_num 4 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + +#define stbir__decode_suffix ABGR +#define stbir__decode_swizzle +#define stbir__decode_order0 3 +#define stbir__decode_order1 2 +#define stbir__decode_order2 1 +#define stbir__decode_order3 0 +#define stbir__encode_order0 3 +#define stbir__encode_order1 2 +#define stbir__encode_order2 1 +#define stbir__encode_order3 0 +#define stbir__coder_min_num 4 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + +#define stbir__decode_suffix AR +#define stbir__decode_swizzle +#define stbir__decode_order0 1 +#define stbir__decode_order1 0 +#define stbir__decode_order2 3 +#define stbir__decode_order3 2 +#define stbir__encode_order0 1 +#define stbir__encode_order1 0 +#define stbir__encode_order2 3 +#define stbir__encode_order3 2 +#define stbir__coder_min_num 2 +#define STB_IMAGE_RESIZE_DO_CODERS +#include STBIR__HEADER_FILENAME + + +// fancy alpha means we expand to keep both premultipied and non-premultiplied color channels +static void stbir__fancy_alpha_weight_4ch( float * out_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) out = out_buffer; + float const * end_decode = out_buffer + ( width_times_channels / 4 ) * 7; // decode buffer aligned to end of out_buffer + float STBIR_STREAMOUT_PTR(*) decode = (float*)end_decode - width_times_channels; + + // fancy alpha is stored internally as R G B A Rpm Gpm Bpm + + #ifdef STBIR_SIMD + + #ifdef STBIR_SIMD8 + decode += 16; + STBIR_NO_UNROLL_LOOP_START + while ( decode <= end_decode ) + { + stbir__simdf8 d0,d1,a0,a1,p0,p1; + STBIR_NO_UNROLL(decode); + stbir__simdf8_load( d0, decode-16 ); + stbir__simdf8_load( d1, decode-16+8 ); + stbir__simdf8_0123to33333333( a0, d0 ); + stbir__simdf8_0123to33333333( a1, d1 ); + stbir__simdf8_mult( p0, a0, d0 ); + stbir__simdf8_mult( p1, a1, d1 ); + stbir__simdf8_bot4s( a0, d0, p0 ); + stbir__simdf8_bot4s( a1, d1, p1 ); + stbir__simdf8_top4s( d0, d0, p0 ); + stbir__simdf8_top4s( d1, d1, p1 ); + stbir__simdf8_store ( out, a0 ); + stbir__simdf8_store ( out+7, d0 ); + stbir__simdf8_store ( out+14, a1 ); + stbir__simdf8_store ( out+21, d1 ); + decode += 16; + out += 28; + } + decode -= 16; + #else + decode += 8; + STBIR_NO_UNROLL_LOOP_START + while ( decode <= end_decode ) + { + stbir__simdf d0,a0,d1,a1,p0,p1; + STBIR_NO_UNROLL(decode); + stbir__simdf_load( d0, decode-8 ); + stbir__simdf_load( d1, decode-8+4 ); + stbir__simdf_0123to3333( a0, d0 ); + stbir__simdf_0123to3333( a1, d1 ); + stbir__simdf_mult( p0, a0, d0 ); + stbir__simdf_mult( p1, a1, d1 ); + stbir__simdf_store ( out, d0 ); + stbir__simdf_store ( out+4, p0 ); + stbir__simdf_store ( out+7, d1 ); + stbir__simdf_store ( out+7+4, p1 ); + decode += 8; + out += 14; + } + decode -= 8; + #endif + + // might be one last odd pixel + #ifdef STBIR_SIMD8 + STBIR_NO_UNROLL_LOOP_START + while ( decode < end_decode ) + #else + if ( decode < end_decode ) + #endif + { + stbir__simdf d,a,p; + STBIR_NO_UNROLL(decode); + stbir__simdf_load( d, decode ); + stbir__simdf_0123to3333( a, d ); + stbir__simdf_mult( p, a, d ); + stbir__simdf_store ( out, d ); + stbir__simdf_store ( out+4, p ); + decode += 4; + out += 7; + } + + #else + + while( decode < end_decode ) + { + float r = decode[0], g = decode[1], b = decode[2], alpha = decode[3]; + out[0] = r; + out[1] = g; + out[2] = b; + out[3] = alpha; + out[4] = r * alpha; + out[5] = g * alpha; + out[6] = b * alpha; + out += 7; + decode += 4; + } + + #endif +} + +static void stbir__fancy_alpha_weight_2ch( float * out_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) out = out_buffer; + float const * end_decode = out_buffer + ( width_times_channels / 2 ) * 3; + float STBIR_STREAMOUT_PTR(*) decode = (float*)end_decode - width_times_channels; + + // for fancy alpha, turns into: [X A Xpm][X A Xpm],etc + + #ifdef STBIR_SIMD + + decode += 8; + if ( decode <= end_decode ) + { + STBIR_NO_UNROLL_LOOP_START + do { + #ifdef STBIR_SIMD8 + stbir__simdf8 d0,a0,p0; + STBIR_NO_UNROLL(decode); + stbir__simdf8_load( d0, decode-8 ); + stbir__simdf8_0123to11331133( p0, d0 ); + stbir__simdf8_0123to00220022( a0, d0 ); + stbir__simdf8_mult( p0, p0, a0 ); + + stbir__simdf_store2( out, stbir__if_simdf8_cast_to_simdf4( d0 ) ); + stbir__simdf_store( out+2, stbir__if_simdf8_cast_to_simdf4( p0 ) ); + stbir__simdf_store2h( out+3, stbir__if_simdf8_cast_to_simdf4( d0 ) ); + + stbir__simdf_store2( out+6, stbir__simdf8_gettop4( d0 ) ); + stbir__simdf_store( out+8, stbir__simdf8_gettop4( p0 ) ); + stbir__simdf_store2h( out+9, stbir__simdf8_gettop4( d0 ) ); + #else + stbir__simdf d0,a0,d1,a1,p0,p1; + STBIR_NO_UNROLL(decode); + stbir__simdf_load( d0, decode-8 ); + stbir__simdf_load( d1, decode-8+4 ); + stbir__simdf_0123to1133( p0, d0 ); + stbir__simdf_0123to1133( p1, d1 ); + stbir__simdf_0123to0022( a0, d0 ); + stbir__simdf_0123to0022( a1, d1 ); + stbir__simdf_mult( p0, p0, a0 ); + stbir__simdf_mult( p1, p1, a1 ); + + stbir__simdf_store2( out, d0 ); + stbir__simdf_store( out+2, p0 ); + stbir__simdf_store2h( out+3, d0 ); + + stbir__simdf_store2( out+6, d1 ); + stbir__simdf_store( out+8, p1 ); + stbir__simdf_store2h( out+9, d1 ); + #endif + decode += 8; + out += 12; + } while ( decode <= end_decode ); + } + decode -= 8; + #endif + + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode < end_decode ) + { + float x = decode[0], y = decode[1]; + STBIR_SIMD_NO_UNROLL(decode); + out[0] = x; + out[1] = y; + out[2] = x * y; + out += 3; + decode += 2; + } +} + +static void stbir__fancy_alpha_unweight_4ch( float * encode_buffer, int width_times_channels ) +{ + float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; + float STBIR_SIMD_STREAMOUT_PTR(*) input = encode_buffer; + float const * end_output = encode_buffer + width_times_channels; + + // fancy RGBA is stored internally as R G B A Rpm Gpm Bpm + + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float alpha = input[3]; +#ifdef STBIR_SIMD + stbir__simdf i,ia; + STBIR_SIMD_NO_UNROLL(encode); + if ( alpha < stbir__small_float ) + { + stbir__simdf_load( i, input ); + stbir__simdf_store( encode, i ); + } + else + { + stbir__simdf_load1frep4( ia, 1.0f / alpha ); + stbir__simdf_load( i, input+4 ); + stbir__simdf_mult( i, i, ia ); + stbir__simdf_store( encode, i ); + encode[3] = alpha; + } +#else + if ( alpha < stbir__small_float ) + { + encode[0] = input[0]; + encode[1] = input[1]; + encode[2] = input[2]; + } + else + { + float ialpha = 1.0f / alpha; + encode[0] = input[4] * ialpha; + encode[1] = input[5] * ialpha; + encode[2] = input[6] * ialpha; + } + encode[3] = alpha; +#endif + + input += 7; + encode += 4; + } while ( encode < end_output ); +} + +// format: [X A Xpm][X A Xpm] etc +static void stbir__fancy_alpha_unweight_2ch( float * encode_buffer, int width_times_channels ) +{ + float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; + float STBIR_SIMD_STREAMOUT_PTR(*) input = encode_buffer; + float const * end_output = encode_buffer + width_times_channels; + + do { + float alpha = input[1]; + encode[0] = input[0]; + if ( alpha >= stbir__small_float ) + encode[0] = input[2] / alpha; + encode[1] = alpha; + + input += 3; + encode += 2; + } while ( encode < end_output ); +} + +static void stbir__simple_alpha_weight_4ch( float * decode_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) decode = decode_buffer; + float const * end_decode = decode_buffer + width_times_channels; + + #ifdef STBIR_SIMD + { + decode += 2 * stbir__simdfX_float_count; + STBIR_NO_UNROLL_LOOP_START + while ( decode <= end_decode ) + { + stbir__simdfX d0,a0,d1,a1; + STBIR_NO_UNROLL(decode); + stbir__simdfX_load( d0, decode-2*stbir__simdfX_float_count ); + stbir__simdfX_load( d1, decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count ); + stbir__simdfX_aaa1( a0, d0, STBIR_onesX ); + stbir__simdfX_aaa1( a1, d1, STBIR_onesX ); + stbir__simdfX_mult( d0, d0, a0 ); + stbir__simdfX_mult( d1, d1, a1 ); + stbir__simdfX_store ( decode-2*stbir__simdfX_float_count, d0 ); + stbir__simdfX_store ( decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count, d1 ); + decode += 2 * stbir__simdfX_float_count; + } + decode -= 2 * stbir__simdfX_float_count; + + // few last pixels remnants + #ifdef STBIR_SIMD8 + STBIR_NO_UNROLL_LOOP_START + while ( decode < end_decode ) + #else + if ( decode < end_decode ) + #endif + { + stbir__simdf d,a; + stbir__simdf_load( d, decode ); + stbir__simdf_aaa1( a, d, STBIR__CONSTF(STBIR_ones) ); + stbir__simdf_mult( d, d, a ); + stbir__simdf_store ( decode, d ); + decode += 4; + } + } + + #else + + while( decode < end_decode ) + { + float alpha = decode[3]; + decode[0] *= alpha; + decode[1] *= alpha; + decode[2] *= alpha; + decode += 4; + } + + #endif +} + +static void stbir__simple_alpha_weight_2ch( float * decode_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) decode = decode_buffer; + float const * end_decode = decode_buffer + width_times_channels; + + #ifdef STBIR_SIMD + decode += 2 * stbir__simdfX_float_count; + STBIR_NO_UNROLL_LOOP_START + while ( decode <= end_decode ) + { + stbir__simdfX d0,a0,d1,a1; + STBIR_NO_UNROLL(decode); + stbir__simdfX_load( d0, decode-2*stbir__simdfX_float_count ); + stbir__simdfX_load( d1, decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count ); + stbir__simdfX_a1a1( a0, d0, STBIR_onesX ); + stbir__simdfX_a1a1( a1, d1, STBIR_onesX ); + stbir__simdfX_mult( d0, d0, a0 ); + stbir__simdfX_mult( d1, d1, a1 ); + stbir__simdfX_store ( decode-2*stbir__simdfX_float_count, d0 ); + stbir__simdfX_store ( decode-2*stbir__simdfX_float_count+stbir__simdfX_float_count, d1 ); + decode += 2 * stbir__simdfX_float_count; + } + decode -= 2 * stbir__simdfX_float_count; + #endif + + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode < end_decode ) + { + float alpha = decode[1]; + STBIR_SIMD_NO_UNROLL(decode); + decode[0] *= alpha; + decode += 2; + } +} + +static void stbir__simple_alpha_unweight_4ch( float * encode_buffer, int width_times_channels ) +{ + float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; + float const * end_output = encode_buffer + width_times_channels; + + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float alpha = encode[3]; + +#ifdef STBIR_SIMD + stbir__simdf i,ia; + STBIR_SIMD_NO_UNROLL(encode); + if ( alpha >= stbir__small_float ) + { + stbir__simdf_load1frep4( ia, 1.0f / alpha ); + stbir__simdf_load( i, encode ); + stbir__simdf_mult( i, i, ia ); + stbir__simdf_store( encode, i ); + encode[3] = alpha; + } +#else + if ( alpha >= stbir__small_float ) + { + float ialpha = 1.0f / alpha; + encode[0] *= ialpha; + encode[1] *= ialpha; + encode[2] *= ialpha; + } +#endif + encode += 4; + } while ( encode < end_output ); +} + +static void stbir__simple_alpha_unweight_2ch( float * encode_buffer, int width_times_channels ) +{ + float STBIR_SIMD_STREAMOUT_PTR(*) encode = encode_buffer; + float const * end_output = encode_buffer + width_times_channels; + + do { + float alpha = encode[1]; + if ( alpha >= stbir__small_float ) + encode[0] /= alpha; + encode += 2; + } while ( encode < end_output ); +} + + +// only used in RGB->BGR or BGR->RGB +static void stbir__simple_flip_3ch( float * decode_buffer, int width_times_channels ) +{ + float STBIR_STREAMOUT_PTR(*) decode = decode_buffer; + float const * end_decode = decode_buffer + width_times_channels; + +#ifdef STBIR_SIMD + #ifdef stbir__simdf_swiz2 // do we have two argument swizzles? + end_decode -= 12; + STBIR_NO_UNROLL_LOOP_START + while( decode <= end_decode ) + { + // on arm64 8 instructions, no overlapping stores + stbir__simdf a,b,c,na,nb; + STBIR_SIMD_NO_UNROLL(decode); + stbir__simdf_load( a, decode ); + stbir__simdf_load( b, decode+4 ); + stbir__simdf_load( c, decode+8 ); + + na = stbir__simdf_swiz2( a, b, 2, 1, 0, 5 ); + b = stbir__simdf_swiz2( a, b, 4, 3, 6, 7 ); + nb = stbir__simdf_swiz2( b, c, 0, 1, 4, 3 ); + c = stbir__simdf_swiz2( b, c, 2, 7, 6, 5 ); + + stbir__simdf_store( decode, na ); + stbir__simdf_store( decode+4, nb ); + stbir__simdf_store( decode+8, c ); + decode += 12; + } + end_decode += 12; + #else + end_decode -= 24; + STBIR_NO_UNROLL_LOOP_START + while( decode <= end_decode ) + { + // 26 instructions on x64 + stbir__simdf a,b,c,d,e,f,g; + float i21, i23; + STBIR_SIMD_NO_UNROLL(decode); + stbir__simdf_load( a, decode ); + stbir__simdf_load( b, decode+3 ); + stbir__simdf_load( c, decode+6 ); + stbir__simdf_load( d, decode+9 ); + stbir__simdf_load( e, decode+12 ); + stbir__simdf_load( f, decode+15 ); + stbir__simdf_load( g, decode+18 ); + + a = stbir__simdf_swiz( a, 2, 1, 0, 3 ); + b = stbir__simdf_swiz( b, 2, 1, 0, 3 ); + c = stbir__simdf_swiz( c, 2, 1, 0, 3 ); + d = stbir__simdf_swiz( d, 2, 1, 0, 3 ); + e = stbir__simdf_swiz( e, 2, 1, 0, 3 ); + f = stbir__simdf_swiz( f, 2, 1, 0, 3 ); + g = stbir__simdf_swiz( g, 2, 1, 0, 3 ); + + // stores overlap, need to be in order, + stbir__simdf_store( decode, a ); + i21 = decode[21]; + stbir__simdf_store( decode+3, b ); + i23 = decode[23]; + stbir__simdf_store( decode+6, c ); + stbir__simdf_store( decode+9, d ); + stbir__simdf_store( decode+12, e ); + stbir__simdf_store( decode+15, f ); + stbir__simdf_store( decode+18, g ); + decode[21] = i23; + decode[23] = i21; + decode += 24; + } + end_decode += 24; + #endif +#else + end_decode -= 12; + STBIR_NO_UNROLL_LOOP_START + while( decode <= end_decode ) + { + // 16 instructions + float t0,t1,t2,t3; + STBIR_NO_UNROLL(decode); + t0 = decode[0]; t1 = decode[3]; t2 = decode[6]; t3 = decode[9]; + decode[0] = decode[2]; decode[3] = decode[5]; decode[6] = decode[8]; decode[9] = decode[11]; + decode[2] = t0; decode[5] = t1; decode[8] = t2; decode[11] = t3; + decode += 12; + } + end_decode += 12; +#endif + + STBIR_NO_UNROLL_LOOP_START + while( decode < end_decode ) + { + float t = decode[0]; + STBIR_NO_UNROLL(decode); + decode[0] = decode[2]; + decode[2] = t; + decode += 3; + } +} + + + +static void stbir__decode_scanline(stbir__info const * stbir_info, int n, float * output_buffer STBIR_ONLY_PROFILE_GET_SPLIT_INFO ) +{ + int channels = stbir_info->channels; + int effective_channels = stbir_info->effective_channels; + int input_sample_in_bytes = stbir__type_size[stbir_info->input_type] * channels; + stbir_edge edge_horizontal = stbir_info->horizontal.edge; + stbir_edge edge_vertical = stbir_info->vertical.edge; + int row = stbir__edge_wrap(edge_vertical, n, stbir_info->vertical.scale_info.input_full_size); + const void* input_plane_data = ( (char *) stbir_info->input_data ) + (size_t)row * (size_t) stbir_info->input_stride_bytes; + stbir__span const * spans = stbir_info->scanline_extents.spans; + float* full_decode_buffer = output_buffer - stbir_info->scanline_extents.conservative.n0 * effective_channels; + + // if we are on edge_zero, and we get in here with an out of bounds n, then the calculate filters has failed + STBIR_ASSERT( !(edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->vertical.scale_info.input_full_size)) ); + + do + { + float * decode_buffer; + void const * input_data; + float * end_decode; + int width_times_channels; + int width; + + if ( spans->n1 < spans->n0 ) + break; + + width = spans->n1 + 1 - spans->n0; + decode_buffer = full_decode_buffer + spans->n0 * effective_channels; + end_decode = full_decode_buffer + ( spans->n1 + 1 ) * effective_channels; + width_times_channels = width * channels; + + // read directly out of input plane by default + input_data = ( (char*)input_plane_data ) + spans->pixel_offset_for_input * input_sample_in_bytes; + + // if we have an input callback, call it to get the input data + if ( stbir_info->in_pixels_cb ) + { + // call the callback with a temp buffer (that they can choose to use or not). the temp is just right aligned memory in the decode_buffer itself + input_data = stbir_info->in_pixels_cb( ( (char*) end_decode ) - ( width * input_sample_in_bytes ), input_plane_data, width, spans->pixel_offset_for_input, row, stbir_info->user_data ); + } + + STBIR_PROFILE_START( decode ); + // convert the pixels info the float decode_buffer, (we index from end_decode, so that when channelsdecode_pixels( (float*)end_decode - width_times_channels, width_times_channels, input_data ); + STBIR_PROFILE_END( decode ); + + if (stbir_info->alpha_weight) + { + STBIR_PROFILE_START( alpha ); + stbir_info->alpha_weight( decode_buffer, width_times_channels ); + STBIR_PROFILE_END( alpha ); + } + + ++spans; + } while ( spans <= ( &stbir_info->scanline_extents.spans[1] ) ); + + // handle the edge_wrap filter (all other types are handled back out at the calculate_filter stage) + // basically the idea here is that if we have the whole scanline in memory, we don't redecode the + // wrapped edge pixels, and instead just memcpy them from the scanline into the edge positions + if ( ( edge_horizontal == STBIR_EDGE_WRAP ) && ( stbir_info->scanline_extents.edge_sizes[0] | stbir_info->scanline_extents.edge_sizes[1] ) ) + { + // this code only runs if we're in edge_wrap, and we're doing the entire scanline + int e, start_x[2]; + int input_full_size = stbir_info->horizontal.scale_info.input_full_size; + + start_x[0] = -stbir_info->scanline_extents.edge_sizes[0]; // left edge start x + start_x[1] = input_full_size; // right edge + + for( e = 0; e < 2 ; e++ ) + { + // do each margin + int margin = stbir_info->scanline_extents.edge_sizes[e]; + if ( margin ) + { + int x = start_x[e]; + float * marg = full_decode_buffer + x * effective_channels; + float const * src = full_decode_buffer + stbir__edge_wrap(edge_horizontal, x, input_full_size) * effective_channels; + STBIR_MEMCPY( marg, src, margin * effective_channels * sizeof(float) ); + } + } + } +} + + +//================= +// Do 1 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc ); \ + stbir__simdf_mult1_mem( tot, c, decode ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot,c,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2z( c, hc ); \ + stbir__simdf_load2( d, decode ); \ + stbir__simdf_mult( tot, c, d ); \ + stbir__simdf_0123to1230( c, tot ); \ + stbir__simdf_add1( tot, tot, c ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot,c,t; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( c, hc ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + stbir__simdf_0123to1230( c, tot ); \ + stbir__simdf_0123to2301( t, tot ); \ + stbir__simdf_add1( tot, tot, c ); \ + stbir__simdf_add1( tot, tot, t ); + +#define stbir__store_output_tiny() \ + stbir__simdf_store1( output, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 1; + +#define stbir__4_coeff_start() \ + stbir__simdf tot,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( c, hc ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( c, hc + (ofs) ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+(ofs) ); + +#define stbir__1_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + stbir__simdf_load1z( c, hc + (ofs) ); \ + stbir__simdf_load1( d, decode + (ofs) ); \ + stbir__simdf_madd( tot, tot, d, c ); } + +#define stbir__2_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + stbir__simdf_load2z( c, hc+(ofs) ); \ + stbir__simdf_load2( d, decode+(ofs) ); \ + stbir__simdf_madd( tot, tot, d, c ); } + +#define stbir__3_coeff_setup() \ + stbir__simdf mask; \ + stbir__simdf_load( mask, STBIR_mask + 3 ); + +#define stbir__3_coeff_remnant( ofs ) \ + stbir__simdf_load( c, hc+(ofs) ); \ + stbir__simdf_and( c, c, mask ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+(ofs) ); + +#define stbir__store_output() \ + stbir__simdf_0123to2301( c, tot ); \ + stbir__simdf_add( tot, tot, c ); \ + stbir__simdf_0123to1230( c, tot ); \ + stbir__simdf_add1( tot, tot, c ); \ + stbir__simdf_store1( output, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 1; + +#else + +#define stbir__1_coeff_only() \ + float tot; \ + tot = decode[0]*hc[0]; + +#define stbir__2_coeff_only() \ + float tot; \ + tot = decode[0] * hc[0]; \ + tot += decode[1] * hc[1]; + +#define stbir__3_coeff_only() \ + float tot; \ + tot = decode[0] * hc[0]; \ + tot += decode[1] * hc[1]; \ + tot += decode[2] * hc[2]; + +#define stbir__store_output_tiny() \ + output[0] = tot; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 1; + +#define stbir__4_coeff_start() \ + float tot0,tot1,tot2,tot3; \ + tot0 = decode[0] * hc[0]; \ + tot1 = decode[1] * hc[1]; \ + tot2 = decode[2] * hc[2]; \ + tot3 = decode[3] * hc[3]; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; \ + tot1 += decode[1+(ofs)] * hc[1+(ofs)]; \ + tot2 += decode[2+(ofs)] * hc[2+(ofs)]; \ + tot3 += decode[3+(ofs)] * hc[3+(ofs)]; + +#define stbir__1_coeff_remnant( ofs ) \ + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; + +#define stbir__2_coeff_remnant( ofs ) \ + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; \ + tot1 += decode[1+(ofs)] * hc[1+(ofs)]; \ + +#define stbir__3_coeff_remnant( ofs ) \ + tot0 += decode[0+(ofs)] * hc[0+(ofs)]; \ + tot1 += decode[1+(ofs)] * hc[1+(ofs)]; \ + tot2 += decode[2+(ofs)] * hc[2+(ofs)]; + +#define stbir__store_output() \ + output[0] = (tot0+tot2)+(tot1+tot3); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 1; + +#endif + +#define STBIR__horizontal_channels 1 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + + +//================= +// Do 2 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot,c,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1z( c, hc ); \ + stbir__simdf_0123to0011( c, c ); \ + stbir__simdf_load2( d, decode ); \ + stbir__simdf_mult( tot, d, c ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( c, hc ); \ + stbir__simdf_0123to0011( c, c ); \ + stbir__simdf_mult_mem( tot, c, decode ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot,c,cs,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_load2z( d, decode+4 ); \ + stbir__simdf_madd( tot, tot, d, c ); + +#define stbir__store_output_tiny() \ + stbir__simdf_0123to2301( c, tot ); \ + stbir__simdf_add( tot, tot, c ); \ + stbir__simdf_store2( output, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; + +#ifdef STBIR_SIMD8 + +#define stbir__4_coeff_start() \ + stbir__simdf8 tot0,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc ); \ + stbir__simdf8_0123to00112233( c, cs ); \ + stbir__simdf8_mult_mem( tot0, c, decode ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00112233( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); + +#define stbir__1_coeff_remnant( ofs ) \ + { stbir__simdf t; \ + stbir__simdf_load1z( t, hc + (ofs) ); \ + stbir__simdf_0123to0011( t, t ); \ + stbir__simdf_mult_mem( t, t, decode+(ofs)*2 ); \ + stbir__simdf8_add4( tot0, tot0, t ); } + +#define stbir__2_coeff_remnant( ofs ) \ + { stbir__simdf t; \ + stbir__simdf_load2( t, hc + (ofs) ); \ + stbir__simdf_0123to0011( t, t ); \ + stbir__simdf_mult_mem( t, t, decode+(ofs)*2 ); \ + stbir__simdf8_add4( tot0, tot0, t ); } + +#define stbir__3_coeff_remnant( ofs ) \ + { stbir__simdf8 d; \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00112233( c, cs ); \ + stbir__simdf8_load6z( d, decode+(ofs)*2 ); \ + stbir__simdf8_madd( tot0, tot0, c, d ); } + +#define stbir__store_output() \ + { stbir__simdf t,d; \ + stbir__simdf8_add4halves( t, stbir__if_simdf8_cast_to_simdf4(tot0), tot0 ); \ + stbir__simdf_0123to2301( d, t ); \ + stbir__simdf_add( t, t, d ); \ + stbir__simdf_store2( output, t ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; } + +#else + +#define stbir__4_coeff_start() \ + stbir__simdf tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_0123to2233( c, cs ); \ + stbir__simdf_mult_mem( tot1, c, decode+4 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); \ + stbir__simdf_0123to2233( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*2+4 ); + +#define stbir__1_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + stbir__simdf_load1z( cs, hc + (ofs) ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_load2( d, decode + (ofs) * 2 ); \ + stbir__simdf_madd( tot0, tot0, d, c ); } + +#define stbir__2_coeff_remnant( ofs ) \ + stbir__simdf_load2( cs, hc + (ofs) ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); + +#define stbir__3_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0011( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*2 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_load2z( d, decode + (ofs) * 2 + 4 ); \ + stbir__simdf_madd( tot1, tot1, d, c ); } + +#define stbir__store_output() \ + stbir__simdf_add( tot0, tot0, tot1 ); \ + stbir__simdf_0123to2301( c, tot0 ); \ + stbir__simdf_add( tot0, tot0, c ); \ + stbir__simdf_store2( output, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; + +#endif + +#else + +#define stbir__1_coeff_only() \ + float tota,totb,c; \ + c = hc[0]; \ + tota = decode[0]*c; \ + totb = decode[1]*c; + +#define stbir__2_coeff_only() \ + float tota,totb,c; \ + c = hc[0]; \ + tota = decode[0]*c; \ + totb = decode[1]*c; \ + c = hc[1]; \ + tota += decode[2]*c; \ + totb += decode[3]*c; + +// this weird order of add matches the simd +#define stbir__3_coeff_only() \ + float tota,totb,c; \ + c = hc[0]; \ + tota = decode[0]*c; \ + totb = decode[1]*c; \ + c = hc[2]; \ + tota += decode[4]*c; \ + totb += decode[5]*c; \ + c = hc[1]; \ + tota += decode[2]*c; \ + totb += decode[3]*c; + +#define stbir__store_output_tiny() \ + output[0] = tota; \ + output[1] = totb; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; + +#define stbir__4_coeff_start() \ + float tota0,tota1,tota2,tota3,totb0,totb1,totb2,totb3,c; \ + c = hc[0]; \ + tota0 = decode[0]*c; \ + totb0 = decode[1]*c; \ + c = hc[1]; \ + tota1 = decode[2]*c; \ + totb1 = decode[3]*c; \ + c = hc[2]; \ + tota2 = decode[4]*c; \ + totb2 = decode[5]*c; \ + c = hc[3]; \ + tota3 = decode[6]*c; \ + totb3 = decode[7]*c; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*2]*c; \ + totb0 += decode[1+(ofs)*2]*c; \ + c = hc[1+(ofs)]; \ + tota1 += decode[2+(ofs)*2]*c; \ + totb1 += decode[3+(ofs)*2]*c; \ + c = hc[2+(ofs)]; \ + tota2 += decode[4+(ofs)*2]*c; \ + totb2 += decode[5+(ofs)*2]*c; \ + c = hc[3+(ofs)]; \ + tota3 += decode[6+(ofs)*2]*c; \ + totb3 += decode[7+(ofs)*2]*c; + +#define stbir__1_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*2] * c; \ + totb0 += decode[1+(ofs)*2] * c; + +#define stbir__2_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*2] * c; \ + totb0 += decode[1+(ofs)*2] * c; \ + c = hc[1+(ofs)]; \ + tota1 += decode[2+(ofs)*2] * c; \ + totb1 += decode[3+(ofs)*2] * c; + +#define stbir__3_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*2] * c; \ + totb0 += decode[1+(ofs)*2] * c; \ + c = hc[1+(ofs)]; \ + tota1 += decode[2+(ofs)*2] * c; \ + totb1 += decode[3+(ofs)*2] * c; \ + c = hc[2+(ofs)]; \ + tota2 += decode[4+(ofs)*2] * c; \ + totb2 += decode[5+(ofs)*2] * c; + +#define stbir__store_output() \ + output[0] = (tota0+tota2)+(tota1+tota3); \ + output[1] = (totb0+totb2)+(totb1+totb3); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 2; + +#endif + +#define STBIR__horizontal_channels 2 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + + +//================= +// Do 3 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot,c,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1z( c, hc ); \ + stbir__simdf_0123to0001( c, c ); \ + stbir__simdf_load( d, decode ); \ + stbir__simdf_mult( tot, d, c ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot,c,cs,d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_load( d, decode ); \ + stbir__simdf_mult( tot, d, c ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_load( d, decode+3 ); \ + stbir__simdf_madd( tot, tot, d, c ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot,c,d,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_load( d, decode ); \ + stbir__simdf_mult( tot, d, c ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_load( d, decode+3 ); \ + stbir__simdf_madd( tot, tot, d, c ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_load( d, decode+6 ); \ + stbir__simdf_madd( tot, tot, d, c ); + +#define stbir__store_output_tiny() \ + stbir__simdf_store2( output, tot ); \ + stbir__simdf_0123to2301( tot, tot ); \ + stbir__simdf_store1( output+2, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; + +#ifdef STBIR_SIMD8 + +// we're loading from the XXXYYY decode by -1 to get the XXXYYY into different halves of the AVX reg fyi +#define stbir__4_coeff_start() \ + stbir__simdf8 tot0,tot1,c,cs; stbir__simdf t; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_mult_mem( tot0, c, decode - 1 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_mult_mem( tot1, c, decode+6 - 1 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*3 + 6 - 1 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1rep4( t, hc + (ofs) ); \ + stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*3 - 1 ); + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) - 2 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); + + #define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*3 - 1 ); \ + stbir__simdf8_0123to2222( t, cs ); \ + stbir__simdf8_madd_mem4( tot1, tot1, t, decode+(ofs)*3 + 6 - 1 ); + +#define stbir__store_output() \ + stbir__simdf8_add( tot0, tot0, tot1 ); \ + stbir__simdf_0123to1230( t, stbir__if_simdf8_cast_to_simdf4( tot0 ) ); \ + stbir__simdf8_add4halves( t, t, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; \ + if ( output < output_end ) \ + { \ + stbir__simdf_store( output-3, t ); \ + continue; \ + } \ + { stbir__simdf tt; stbir__simdf_0123to2301( tt, t ); \ + stbir__simdf_store2( output-3, t ); \ + stbir__simdf_store1( output+2-3, tt ); } \ + break; + + +#else + +#define stbir__4_coeff_start() \ + stbir__simdf tot0,tot1,tot2,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0001( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_0123to1122( c, cs ); \ + stbir__simdf_mult_mem( tot1, c, decode+4 ); \ + stbir__simdf_0123to2333( c, cs ); \ + stbir__simdf_mult_mem( tot2, c, decode+8 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0001( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); \ + stbir__simdf_0123to1122( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*3+4 ); \ + stbir__simdf_0123to2333( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*3+8 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1z( c, hc + (ofs) ); \ + stbir__simdf_0123to0001( c, c ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); + +#define stbir__2_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2z( cs, hc + (ofs) ); \ + stbir__simdf_0123to0001( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); \ + stbir__simdf_0123to1122( c, cs ); \ + stbir__simdf_load2z( d, decode+(ofs)*3+4 ); \ + stbir__simdf_madd( tot1, tot1, c, d ); } + +#define stbir__3_coeff_remnant( ofs ) \ + { stbir__simdf d; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0001( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*3 ); \ + stbir__simdf_0123to1122( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*3+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_load1z( d, decode+(ofs)*3+8 ); \ + stbir__simdf_madd( tot2, tot2, c, d ); } + +#define stbir__store_output() \ + stbir__simdf_0123ABCDto3ABx( c, tot0, tot1 ); \ + stbir__simdf_0123ABCDto23Ax( cs, tot1, tot2 ); \ + stbir__simdf_0123to1230( tot2, tot2 ); \ + stbir__simdf_add( tot0, tot0, cs ); \ + stbir__simdf_add( c, c, tot2 ); \ + stbir__simdf_add( tot0, tot0, c ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; \ + if ( output < output_end ) \ + { \ + stbir__simdf_store( output-3, tot0 ); \ + continue; \ + } \ + stbir__simdf_0123to2301( tot1, tot0 ); \ + stbir__simdf_store2( output-3, tot0 ); \ + stbir__simdf_store1( output+2-3, tot1 ); \ + break; + +#endif + +#else + +#define stbir__1_coeff_only() \ + float tot0, tot1, tot2, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; + +#define stbir__2_coeff_only() \ + float tot0, tot1, tot2, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + c = hc[1]; \ + tot0 += decode[3]*c; \ + tot1 += decode[4]*c; \ + tot2 += decode[5]*c; + +#define stbir__3_coeff_only() \ + float tot0, tot1, tot2, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + c = hc[1]; \ + tot0 += decode[3]*c; \ + tot1 += decode[4]*c; \ + tot2 += decode[5]*c; \ + c = hc[2]; \ + tot0 += decode[6]*c; \ + tot1 += decode[7]*c; \ + tot2 += decode[8]*c; + +#define stbir__store_output_tiny() \ + output[0] = tot0; \ + output[1] = tot1; \ + output[2] = tot2; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; + +#define stbir__4_coeff_start() \ + float tota0,tota1,tota2,totb0,totb1,totb2,totc0,totc1,totc2,totd0,totd1,totd2,c; \ + c = hc[0]; \ + tota0 = decode[0]*c; \ + tota1 = decode[1]*c; \ + tota2 = decode[2]*c; \ + c = hc[1]; \ + totb0 = decode[3]*c; \ + totb1 = decode[4]*c; \ + totb2 = decode[5]*c; \ + c = hc[2]; \ + totc0 = decode[6]*c; \ + totc1 = decode[7]*c; \ + totc2 = decode[8]*c; \ + c = hc[3]; \ + totd0 = decode[9]*c; \ + totd1 = decode[10]*c; \ + totd2 = decode[11]*c; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*3]*c; \ + tota1 += decode[1+(ofs)*3]*c; \ + tota2 += decode[2+(ofs)*3]*c; \ + c = hc[1+(ofs)]; \ + totb0 += decode[3+(ofs)*3]*c; \ + totb1 += decode[4+(ofs)*3]*c; \ + totb2 += decode[5+(ofs)*3]*c; \ + c = hc[2+(ofs)]; \ + totc0 += decode[6+(ofs)*3]*c; \ + totc1 += decode[7+(ofs)*3]*c; \ + totc2 += decode[8+(ofs)*3]*c; \ + c = hc[3+(ofs)]; \ + totd0 += decode[9+(ofs)*3]*c; \ + totd1 += decode[10+(ofs)*3]*c; \ + totd2 += decode[11+(ofs)*3]*c; + +#define stbir__1_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*3]*c; \ + tota1 += decode[1+(ofs)*3]*c; \ + tota2 += decode[2+(ofs)*3]*c; + +#define stbir__2_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*3]*c; \ + tota1 += decode[1+(ofs)*3]*c; \ + tota2 += decode[2+(ofs)*3]*c; \ + c = hc[1+(ofs)]; \ + totb0 += decode[3+(ofs)*3]*c; \ + totb1 += decode[4+(ofs)*3]*c; \ + totb2 += decode[5+(ofs)*3]*c; \ + +#define stbir__3_coeff_remnant( ofs ) \ + c = hc[0+(ofs)]; \ + tota0 += decode[0+(ofs)*3]*c; \ + tota1 += decode[1+(ofs)*3]*c; \ + tota2 += decode[2+(ofs)*3]*c; \ + c = hc[1+(ofs)]; \ + totb0 += decode[3+(ofs)*3]*c; \ + totb1 += decode[4+(ofs)*3]*c; \ + totb2 += decode[5+(ofs)*3]*c; \ + c = hc[2+(ofs)]; \ + totc0 += decode[6+(ofs)*3]*c; \ + totc1 += decode[7+(ofs)*3]*c; \ + totc2 += decode[8+(ofs)*3]*c; + +#define stbir__store_output() \ + output[0] = (tota0+totc0)+(totb0+totd0); \ + output[1] = (tota1+totc1)+(totb1+totd1); \ + output[2] = (tota2+totc2)+(totb2+totd2); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 3; + +#endif + +#define STBIR__horizontal_channels 3 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + +//================= +// Do 4 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc ); \ + stbir__simdf_0123to0000( c, c ); \ + stbir__simdf_mult_mem( tot, c, decode ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+4 ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot, c, decode ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot, tot, c, decode+8 ); + +#define stbir__store_output_tiny() \ + stbir__simdf_store( output, tot ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#ifdef STBIR_SIMD8 + +#define stbir__4_coeff_start() \ + stbir__simdf8 tot0,c,cs; stbir__simdf t; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_mult_mem( tot0, c, decode ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+8 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1rep4( t, hc + (ofs) ); \ + stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4 ); + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) - 2 ); \ + stbir__simdf8_0123to22223333( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); + + #define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00001111( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf8_0123to2222( t, cs ); \ + stbir__simdf8_madd_mem4( tot0, tot0, t, decode+(ofs)*4+8 ); + +#define stbir__store_output() \ + stbir__simdf8_add4halves( t, stbir__if_simdf8_cast_to_simdf4(tot0), tot0 ); \ + stbir__simdf_store( output, t ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#else + +#define stbir__4_coeff_start() \ + stbir__simdf tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_mult_mem( tot1, c, decode+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+8 ); \ + stbir__simdf_0123to3333( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+12 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 ); \ + stbir__simdf_0123to3333( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+12 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, c ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 ); + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*4+4 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*4+8 ); + +#define stbir__store_output() \ + stbir__simdf_add( tot0, tot0, tot1 ); \ + stbir__simdf_store( output, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#endif + +#else + +#define stbir__1_coeff_only() \ + float p0,p1,p2,p3,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + p0 = decode[0] * c; \ + p1 = decode[1] * c; \ + p2 = decode[2] * c; \ + p3 = decode[3] * c; + +#define stbir__2_coeff_only() \ + float p0,p1,p2,p3,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + p0 = decode[0] * c; \ + p1 = decode[1] * c; \ + p2 = decode[2] * c; \ + p3 = decode[3] * c; \ + c = hc[1]; \ + p0 += decode[4] * c; \ + p1 += decode[5] * c; \ + p2 += decode[6] * c; \ + p3 += decode[7] * c; + +#define stbir__3_coeff_only() \ + float p0,p1,p2,p3,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + p0 = decode[0] * c; \ + p1 = decode[1] * c; \ + p2 = decode[2] * c; \ + p3 = decode[3] * c; \ + c = hc[1]; \ + p0 += decode[4] * c; \ + p1 += decode[5] * c; \ + p2 += decode[6] * c; \ + p3 += decode[7] * c; \ + c = hc[2]; \ + p0 += decode[8] * c; \ + p1 += decode[9] * c; \ + p2 += decode[10] * c; \ + p3 += decode[11] * c; + +#define stbir__store_output_tiny() \ + output[0] = p0; \ + output[1] = p1; \ + output[2] = p2; \ + output[3] = p3; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#define stbir__4_coeff_start() \ + float x0,x1,x2,x3,y0,y1,y2,y3,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + x0 = decode[0] * c; \ + x1 = decode[1] * c; \ + x2 = decode[2] * c; \ + x3 = decode[3] * c; \ + c = hc[1]; \ + y0 = decode[4] * c; \ + y1 = decode[5] * c; \ + y2 = decode[6] * c; \ + y3 = decode[7] * c; \ + c = hc[2]; \ + x0 += decode[8] * c; \ + x1 += decode[9] * c; \ + x2 += decode[10] * c; \ + x3 += decode[11] * c; \ + c = hc[3]; \ + y0 += decode[12] * c; \ + y1 += decode[13] * c; \ + y2 += decode[14] * c; \ + y3 += decode[15] * c; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*4] * c; \ + x1 += decode[1+(ofs)*4] * c; \ + x2 += decode[2+(ofs)*4] * c; \ + x3 += decode[3+(ofs)*4] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[4+(ofs)*4] * c; \ + y1 += decode[5+(ofs)*4] * c; \ + y2 += decode[6+(ofs)*4] * c; \ + y3 += decode[7+(ofs)*4] * c; \ + c = hc[2+(ofs)]; \ + x0 += decode[8+(ofs)*4] * c; \ + x1 += decode[9+(ofs)*4] * c; \ + x2 += decode[10+(ofs)*4] * c; \ + x3 += decode[11+(ofs)*4] * c; \ + c = hc[3+(ofs)]; \ + y0 += decode[12+(ofs)*4] * c; \ + y1 += decode[13+(ofs)*4] * c; \ + y2 += decode[14+(ofs)*4] * c; \ + y3 += decode[15+(ofs)*4] * c; + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*4] * c; \ + x1 += decode[1+(ofs)*4] * c; \ + x2 += decode[2+(ofs)*4] * c; \ + x3 += decode[3+(ofs)*4] * c; + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*4] * c; \ + x1 += decode[1+(ofs)*4] * c; \ + x2 += decode[2+(ofs)*4] * c; \ + x3 += decode[3+(ofs)*4] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[4+(ofs)*4] * c; \ + y1 += decode[5+(ofs)*4] * c; \ + y2 += decode[6+(ofs)*4] * c; \ + y3 += decode[7+(ofs)*4] * c; + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*4] * c; \ + x1 += decode[1+(ofs)*4] * c; \ + x2 += decode[2+(ofs)*4] * c; \ + x3 += decode[3+(ofs)*4] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[4+(ofs)*4] * c; \ + y1 += decode[5+(ofs)*4] * c; \ + y2 += decode[6+(ofs)*4] * c; \ + y3 += decode[7+(ofs)*4] * c; \ + c = hc[2+(ofs)]; \ + x0 += decode[8+(ofs)*4] * c; \ + x1 += decode[9+(ofs)*4] * c; \ + x2 += decode[10+(ofs)*4] * c; \ + x3 += decode[11+(ofs)*4] * c; + +#define stbir__store_output() \ + output[0] = x0 + y0; \ + output[1] = x1 + y1; \ + output[2] = x2 + y2; \ + output[3] = x3 + y3; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 4; + +#endif + +#define STBIR__horizontal_channels 4 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + + + +//================= +// Do 7 channel horizontal routines + +#ifdef STBIR_SIMD + +#define stbir__1_coeff_only() \ + stbir__simdf tot0,tot1,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc ); \ + stbir__simdf_0123to0000( c, c ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_mult_mem( tot1, c, decode+3 ); + +#define stbir__2_coeff_only() \ + stbir__simdf tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_mult_mem( tot1, c, decode+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c,decode+10 ); + +#define stbir__3_coeff_only() \ + stbir__simdf tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_mult_mem( tot1, c, decode+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+10 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+14 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+17 ); + +#define stbir__store_output_tiny() \ + stbir__simdf_store( output+3, tot1 ); \ + stbir__simdf_store( output, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; + +#ifdef STBIR_SIMD8 + +#define stbir__4_coeff_start() \ + stbir__simdf8 tot0,tot1,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc ); \ + stbir__simdf8_0123to00000000( c, cs ); \ + stbir__simdf8_mult_mem( tot0, c, decode ); \ + stbir__simdf8_0123to11111111( c, cs ); \ + stbir__simdf8_mult_mem( tot1, c, decode+7 ); \ + stbir__simdf8_0123to22222222( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+14 ); \ + stbir__simdf8_0123to33333333( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+21 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00000000( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf8_0123to11111111( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 ); \ + stbir__simdf8_0123to22222222( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \ + stbir__simdf8_0123to33333333( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+21 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load1b( c, hc + (ofs) ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load1b( c, hc + (ofs) ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf8_load1b( c, hc + (ofs)+1 ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 ); + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf8_load4b( cs, hc + (ofs) ); \ + stbir__simdf8_0123to00000000( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf8_0123to11111111( c, cs ); \ + stbir__simdf8_madd_mem( tot1, tot1, c, decode+(ofs)*7+7 ); \ + stbir__simdf8_0123to22222222( c, cs ); \ + stbir__simdf8_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); + +#define stbir__store_output() \ + stbir__simdf8_add( tot0, tot0, tot1 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; \ + if ( output < output_end ) \ + { \ + stbir__simdf8_store( output-7, tot0 ); \ + continue; \ + } \ + stbir__simdf_store( output-7+3, stbir__simdf_swiz(stbir__simdf8_gettop4(tot0),0,0,1,2) ); \ + stbir__simdf_store( output-7, stbir__if_simdf8_cast_to_simdf4(tot0) ); \ + break; + +#else + +#define stbir__4_coeff_start() \ + stbir__simdf tot0,tot1,tot2,tot3,c,cs; \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_mult_mem( tot0, c, decode ); \ + stbir__simdf_mult_mem( tot1, c, decode+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_mult_mem( tot2, c, decode+7 ); \ + stbir__simdf_mult_mem( tot3, c, decode+10 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+14 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+17 ); \ + stbir__simdf_0123to3333( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+21 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+24 ); + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 ); \ + stbir__simdf_0123to3333( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+21 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+24 ); + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load1( c, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, c ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load2( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 ); + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + stbir__simdf_load( cs, hc + (ofs) ); \ + stbir__simdf_0123to0000( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+3 ); \ + stbir__simdf_0123to1111( c, cs ); \ + stbir__simdf_madd_mem( tot2, tot2, c, decode+(ofs)*7+7 ); \ + stbir__simdf_madd_mem( tot3, tot3, c, decode+(ofs)*7+10 ); \ + stbir__simdf_0123to2222( c, cs ); \ + stbir__simdf_madd_mem( tot0, tot0, c, decode+(ofs)*7+14 ); \ + stbir__simdf_madd_mem( tot1, tot1, c, decode+(ofs)*7+17 ); + +#define stbir__store_output() \ + stbir__simdf_add( tot0, tot0, tot2 ); \ + stbir__simdf_add( tot1, tot1, tot3 ); \ + stbir__simdf_store( output+3, tot1 ); \ + stbir__simdf_store( output, tot0 ); \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; + +#endif + +#else + +#define stbir__1_coeff_only() \ + float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + tot3 = decode[3]*c; \ + tot4 = decode[4]*c; \ + tot5 = decode[5]*c; \ + tot6 = decode[6]*c; + +#define stbir__2_coeff_only() \ + float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + tot3 = decode[3]*c; \ + tot4 = decode[4]*c; \ + tot5 = decode[5]*c; \ + tot6 = decode[6]*c; \ + c = hc[1]; \ + tot0 += decode[7]*c; \ + tot1 += decode[8]*c; \ + tot2 += decode[9]*c; \ + tot3 += decode[10]*c; \ + tot4 += decode[11]*c; \ + tot5 += decode[12]*c; \ + tot6 += decode[13]*c; \ + +#define stbir__3_coeff_only() \ + float tot0, tot1, tot2, tot3, tot4, tot5, tot6, c; \ + c = hc[0]; \ + tot0 = decode[0]*c; \ + tot1 = decode[1]*c; \ + tot2 = decode[2]*c; \ + tot3 = decode[3]*c; \ + tot4 = decode[4]*c; \ + tot5 = decode[5]*c; \ + tot6 = decode[6]*c; \ + c = hc[1]; \ + tot0 += decode[7]*c; \ + tot1 += decode[8]*c; \ + tot2 += decode[9]*c; \ + tot3 += decode[10]*c; \ + tot4 += decode[11]*c; \ + tot5 += decode[12]*c; \ + tot6 += decode[13]*c; \ + c = hc[2]; \ + tot0 += decode[14]*c; \ + tot1 += decode[15]*c; \ + tot2 += decode[16]*c; \ + tot3 += decode[17]*c; \ + tot4 += decode[18]*c; \ + tot5 += decode[19]*c; \ + tot6 += decode[20]*c; \ + +#define stbir__store_output_tiny() \ + output[0] = tot0; \ + output[1] = tot1; \ + output[2] = tot2; \ + output[3] = tot3; \ + output[4] = tot4; \ + output[5] = tot5; \ + output[6] = tot6; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; + +#define stbir__4_coeff_start() \ + float x0,x1,x2,x3,x4,x5,x6,y0,y1,y2,y3,y4,y5,y6,c; \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0]; \ + x0 = decode[0] * c; \ + x1 = decode[1] * c; \ + x2 = decode[2] * c; \ + x3 = decode[3] * c; \ + x4 = decode[4] * c; \ + x5 = decode[5] * c; \ + x6 = decode[6] * c; \ + c = hc[1]; \ + y0 = decode[7] * c; \ + y1 = decode[8] * c; \ + y2 = decode[9] * c; \ + y3 = decode[10] * c; \ + y4 = decode[11] * c; \ + y5 = decode[12] * c; \ + y6 = decode[13] * c; \ + c = hc[2]; \ + x0 += decode[14] * c; \ + x1 += decode[15] * c; \ + x2 += decode[16] * c; \ + x3 += decode[17] * c; \ + x4 += decode[18] * c; \ + x5 += decode[19] * c; \ + x6 += decode[20] * c; \ + c = hc[3]; \ + y0 += decode[21] * c; \ + y1 += decode[22] * c; \ + y2 += decode[23] * c; \ + y3 += decode[24] * c; \ + y4 += decode[25] * c; \ + y5 += decode[26] * c; \ + y6 += decode[27] * c; + +#define stbir__4_coeff_continue_from_4( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*7] * c; \ + x1 += decode[1+(ofs)*7] * c; \ + x2 += decode[2+(ofs)*7] * c; \ + x3 += decode[3+(ofs)*7] * c; \ + x4 += decode[4+(ofs)*7] * c; \ + x5 += decode[5+(ofs)*7] * c; \ + x6 += decode[6+(ofs)*7] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[7+(ofs)*7] * c; \ + y1 += decode[8+(ofs)*7] * c; \ + y2 += decode[9+(ofs)*7] * c; \ + y3 += decode[10+(ofs)*7] * c; \ + y4 += decode[11+(ofs)*7] * c; \ + y5 += decode[12+(ofs)*7] * c; \ + y6 += decode[13+(ofs)*7] * c; \ + c = hc[2+(ofs)]; \ + x0 += decode[14+(ofs)*7] * c; \ + x1 += decode[15+(ofs)*7] * c; \ + x2 += decode[16+(ofs)*7] * c; \ + x3 += decode[17+(ofs)*7] * c; \ + x4 += decode[18+(ofs)*7] * c; \ + x5 += decode[19+(ofs)*7] * c; \ + x6 += decode[20+(ofs)*7] * c; \ + c = hc[3+(ofs)]; \ + y0 += decode[21+(ofs)*7] * c; \ + y1 += decode[22+(ofs)*7] * c; \ + y2 += decode[23+(ofs)*7] * c; \ + y3 += decode[24+(ofs)*7] * c; \ + y4 += decode[25+(ofs)*7] * c; \ + y5 += decode[26+(ofs)*7] * c; \ + y6 += decode[27+(ofs)*7] * c; + +#define stbir__1_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*7] * c; \ + x1 += decode[1+(ofs)*7] * c; \ + x2 += decode[2+(ofs)*7] * c; \ + x3 += decode[3+(ofs)*7] * c; \ + x4 += decode[4+(ofs)*7] * c; \ + x5 += decode[5+(ofs)*7] * c; \ + x6 += decode[6+(ofs)*7] * c; \ + +#define stbir__2_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*7] * c; \ + x1 += decode[1+(ofs)*7] * c; \ + x2 += decode[2+(ofs)*7] * c; \ + x3 += decode[3+(ofs)*7] * c; \ + x4 += decode[4+(ofs)*7] * c; \ + x5 += decode[5+(ofs)*7] * c; \ + x6 += decode[6+(ofs)*7] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[7+(ofs)*7] * c; \ + y1 += decode[8+(ofs)*7] * c; \ + y2 += decode[9+(ofs)*7] * c; \ + y3 += decode[10+(ofs)*7] * c; \ + y4 += decode[11+(ofs)*7] * c; \ + y5 += decode[12+(ofs)*7] * c; \ + y6 += decode[13+(ofs)*7] * c; \ + +#define stbir__3_coeff_remnant( ofs ) \ + STBIR_SIMD_NO_UNROLL(decode); \ + c = hc[0+(ofs)]; \ + x0 += decode[0+(ofs)*7] * c; \ + x1 += decode[1+(ofs)*7] * c; \ + x2 += decode[2+(ofs)*7] * c; \ + x3 += decode[3+(ofs)*7] * c; \ + x4 += decode[4+(ofs)*7] * c; \ + x5 += decode[5+(ofs)*7] * c; \ + x6 += decode[6+(ofs)*7] * c; \ + c = hc[1+(ofs)]; \ + y0 += decode[7+(ofs)*7] * c; \ + y1 += decode[8+(ofs)*7] * c; \ + y2 += decode[9+(ofs)*7] * c; \ + y3 += decode[10+(ofs)*7] * c; \ + y4 += decode[11+(ofs)*7] * c; \ + y5 += decode[12+(ofs)*7] * c; \ + y6 += decode[13+(ofs)*7] * c; \ + c = hc[2+(ofs)]; \ + x0 += decode[14+(ofs)*7] * c; \ + x1 += decode[15+(ofs)*7] * c; \ + x2 += decode[16+(ofs)*7] * c; \ + x3 += decode[17+(ofs)*7] * c; \ + x4 += decode[18+(ofs)*7] * c; \ + x5 += decode[19+(ofs)*7] * c; \ + x6 += decode[20+(ofs)*7] * c; \ + +#define stbir__store_output() \ + output[0] = x0 + y0; \ + output[1] = x1 + y1; \ + output[2] = x2 + y2; \ + output[3] = x3 + y3; \ + output[4] = x4 + y4; \ + output[5] = x5 + y5; \ + output[6] = x6 + y6; \ + horizontal_coefficients += coefficient_width; \ + ++horizontal_contributors; \ + output += 7; + +#endif + +#define STBIR__horizontal_channels 7 +#define STB_IMAGE_RESIZE_DO_HORIZONTALS +#include STBIR__HEADER_FILENAME + + +// include all of the vertical resamplers (both scatter and gather versions) + +#define STBIR__vertical_channels 1 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 1 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 2 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 2 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 3 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 3 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 4 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 4 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 5 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 5 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 6 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 6 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 7 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 7 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 8 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#include STBIR__HEADER_FILENAME + +#define STBIR__vertical_channels 8 +#define STB_IMAGE_RESIZE_DO_VERTICALS +#define STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#include STBIR__HEADER_FILENAME + +typedef void STBIR_VERTICAL_GATHERFUNC( float * output, float const * coeffs, float const ** inputs, float const * input0_end ); + +static STBIR_VERTICAL_GATHERFUNC * stbir__vertical_gathers[ 8 ] = +{ + stbir__vertical_gather_with_1_coeffs,stbir__vertical_gather_with_2_coeffs,stbir__vertical_gather_with_3_coeffs,stbir__vertical_gather_with_4_coeffs,stbir__vertical_gather_with_5_coeffs,stbir__vertical_gather_with_6_coeffs,stbir__vertical_gather_with_7_coeffs,stbir__vertical_gather_with_8_coeffs +}; + +static STBIR_VERTICAL_GATHERFUNC * stbir__vertical_gathers_continues[ 8 ] = +{ + stbir__vertical_gather_with_1_coeffs_cont,stbir__vertical_gather_with_2_coeffs_cont,stbir__vertical_gather_with_3_coeffs_cont,stbir__vertical_gather_with_4_coeffs_cont,stbir__vertical_gather_with_5_coeffs_cont,stbir__vertical_gather_with_6_coeffs_cont,stbir__vertical_gather_with_7_coeffs_cont,stbir__vertical_gather_with_8_coeffs_cont +}; + +typedef void STBIR_VERTICAL_SCATTERFUNC( float ** outputs, float const * coeffs, float const * input, float const * input_end ); + +static STBIR_VERTICAL_SCATTERFUNC * stbir__vertical_scatter_sets[ 8 ] = +{ + stbir__vertical_scatter_with_1_coeffs,stbir__vertical_scatter_with_2_coeffs,stbir__vertical_scatter_with_3_coeffs,stbir__vertical_scatter_with_4_coeffs,stbir__vertical_scatter_with_5_coeffs,stbir__vertical_scatter_with_6_coeffs,stbir__vertical_scatter_with_7_coeffs,stbir__vertical_scatter_with_8_coeffs +}; + +static STBIR_VERTICAL_SCATTERFUNC * stbir__vertical_scatter_blends[ 8 ] = +{ + stbir__vertical_scatter_with_1_coeffs_cont,stbir__vertical_scatter_with_2_coeffs_cont,stbir__vertical_scatter_with_3_coeffs_cont,stbir__vertical_scatter_with_4_coeffs_cont,stbir__vertical_scatter_with_5_coeffs_cont,stbir__vertical_scatter_with_6_coeffs_cont,stbir__vertical_scatter_with_7_coeffs_cont,stbir__vertical_scatter_with_8_coeffs_cont +}; + + +static void stbir__encode_scanline( stbir__info const * stbir_info, void *output_buffer_data, float * encode_buffer, int row STBIR_ONLY_PROFILE_GET_SPLIT_INFO ) +{ + int num_pixels = stbir_info->horizontal.scale_info.output_sub_size; + int channels = stbir_info->channels; + int width_times_channels = num_pixels * channels; + void * output_buffer; + + // un-alpha weight if we need to + if ( stbir_info->alpha_unweight ) + { + STBIR_PROFILE_START( unalpha ); + stbir_info->alpha_unweight( encode_buffer, width_times_channels ); + STBIR_PROFILE_END( unalpha ); + } + + // write directly into output by default + output_buffer = output_buffer_data; + + // if we have an output callback, we first convert the decode buffer in place (and then hand that to the callback) + if ( stbir_info->out_pixels_cb ) + output_buffer = encode_buffer; + + STBIR_PROFILE_START( encode ); + // convert into the output buffer + stbir_info->encode_pixels( output_buffer, width_times_channels, encode_buffer ); + STBIR_PROFILE_END( encode ); + + // if we have an output callback, call it to send the data + if ( stbir_info->out_pixels_cb ) + stbir_info->out_pixels_cb( output_buffer, num_pixels, row, stbir_info->user_data ); +} + + +// Get the ring buffer pointer for an index +static float* stbir__get_ring_buffer_entry(stbir__info const * stbir_info, stbir__per_split_info const * split_info, int index ) +{ + STBIR_ASSERT( index < stbir_info->ring_buffer_num_entries ); + + #ifdef STBIR__SEPARATE_ALLOCATIONS + return split_info->ring_buffers[ index ]; + #else + return (float*) ( ( (char*) split_info->ring_buffer ) + ( index * stbir_info->ring_buffer_length_bytes ) ); + #endif +} + +// Get the specified scan line from the ring buffer +static float* stbir__get_ring_buffer_scanline(stbir__info const * stbir_info, stbir__per_split_info const * split_info, int get_scanline) +{ + int ring_buffer_index = (split_info->ring_buffer_begin_index + (get_scanline - split_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + return stbir__get_ring_buffer_entry( stbir_info, split_info, ring_buffer_index ); +} + +static void stbir__resample_horizontal_gather(stbir__info const * stbir_info, float* output_buffer, float const * input_buffer STBIR_ONLY_PROFILE_GET_SPLIT_INFO ) +{ + float const * decode_buffer = input_buffer - ( stbir_info->scanline_extents.conservative.n0 * stbir_info->effective_channels ); + + STBIR_PROFILE_START( horizontal ); + if ( ( stbir_info->horizontal.filter_enum == STBIR_FILTER_POINT_SAMPLE ) && ( stbir_info->horizontal.scale_info.scale == 1.0f ) ) + STBIR_MEMCPY( output_buffer, input_buffer, stbir_info->horizontal.scale_info.output_sub_size * sizeof( float ) * stbir_info->effective_channels ); + else + stbir_info->horizontal_gather_channels( output_buffer, stbir_info->horizontal.scale_info.output_sub_size, decode_buffer, stbir_info->horizontal.contributors, stbir_info->horizontal.coefficients, stbir_info->horizontal.coefficient_width ); + STBIR_PROFILE_END( horizontal ); +} + +static void stbir__resample_vertical_gather(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n, int contrib_n0, int contrib_n1, float const * vertical_coefficients ) +{ + float* encode_buffer = split_info->vertical_buffer; + float* decode_buffer = split_info->decode_buffer; + int vertical_first = stbir_info->vertical_first; + int width = (vertical_first) ? ( stbir_info->scanline_extents.conservative.n1-stbir_info->scanline_extents.conservative.n0+1 ) : stbir_info->horizontal.scale_info.output_sub_size; + int width_times_channels = stbir_info->effective_channels * width; + + STBIR_ASSERT( stbir_info->vertical.is_gather ); + + // loop over the contributing scanlines and scale into the buffer + STBIR_PROFILE_START( vertical ); + { + int k = 0, total = contrib_n1 - contrib_n0 + 1; + STBIR_ASSERT( total > 0 ); + do { + float const * inputs[8]; + int i, cnt = total; if ( cnt > 8 ) cnt = 8; + for( i = 0 ; i < cnt ; i++ ) + inputs[ i ] = stbir__get_ring_buffer_scanline(stbir_info, split_info, k+i+contrib_n0 ); + + // call the N scanlines at a time function (up to 8 scanlines of blending at once) + ((k==0)?stbir__vertical_gathers:stbir__vertical_gathers_continues)[cnt-1]( (vertical_first) ? decode_buffer : encode_buffer, vertical_coefficients + k, inputs, inputs[0] + width_times_channels ); + k += cnt; + total -= cnt; + } while ( total ); + } + STBIR_PROFILE_END( vertical ); + + if ( vertical_first ) + { + // Now resample the gathered vertical data in the horizontal axis into the encode buffer + stbir__resample_horizontal_gather(stbir_info, encode_buffer, decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + } + + stbir__encode_scanline( stbir_info, ( (char *) stbir_info->output_data ) + ((size_t)n * (size_t)stbir_info->output_stride_bytes), + encode_buffer, n STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); +} + +static void stbir__decode_and_resample_for_vertical_gather_loop(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n) +{ + int ring_buffer_index; + float* ring_buffer; + + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline( stbir_info, n, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // update new end scanline + split_info->ring_buffer_last_scanline = n; + + // get ring buffer + ring_buffer_index = (split_info->ring_buffer_begin_index + (split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + ring_buffer = stbir__get_ring_buffer_entry(stbir_info, split_info, ring_buffer_index); + + // Now resample it into the ring buffer. + stbir__resample_horizontal_gather( stbir_info, ring_buffer, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. +} + +static void stbir__vertical_gather_loop( stbir__info const * stbir_info, stbir__per_split_info* split_info, int split_count ) +{ + int y, start_output_y, end_output_y; + stbir__contributors* vertical_contributors = stbir_info->vertical.contributors; + float const * vertical_coefficients = stbir_info->vertical.coefficients; + + STBIR_ASSERT( stbir_info->vertical.is_gather ); + + start_output_y = split_info->start_output_y; + end_output_y = split_info[split_count-1].end_output_y; + + vertical_contributors += start_output_y; + vertical_coefficients += start_output_y * stbir_info->vertical.coefficient_width; + + // initialize the ring buffer for gathering + split_info->ring_buffer_begin_index = 0; + split_info->ring_buffer_first_scanline = vertical_contributors->n0; + split_info->ring_buffer_last_scanline = split_info->ring_buffer_first_scanline - 1; // means "empty" + + for (y = start_output_y; y < end_output_y; y++) + { + int in_first_scanline, in_last_scanline; + + in_first_scanline = vertical_contributors->n0; + in_last_scanline = vertical_contributors->n1; + + // make sure the indexing hasn't broken + STBIR_ASSERT( in_first_scanline >= split_info->ring_buffer_first_scanline ); + + // Load in new scanlines + while (in_last_scanline > split_info->ring_buffer_last_scanline) + { + STBIR_ASSERT( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) <= stbir_info->ring_buffer_num_entries ); + + // make sure there was room in the ring buffer when we add new scanlines + if ( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) == stbir_info->ring_buffer_num_entries ) + { + split_info->ring_buffer_first_scanline++; + split_info->ring_buffer_begin_index++; + } + + if ( stbir_info->vertical_first ) + { + float * ring_buffer = stbir__get_ring_buffer_scanline( stbir_info, split_info, ++split_info->ring_buffer_last_scanline ); + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline( stbir_info, split_info->ring_buffer_last_scanline, ring_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + } + else + { + stbir__decode_and_resample_for_vertical_gather_loop(stbir_info, split_info, split_info->ring_buffer_last_scanline + 1); + } + } + + // Now all buffers should be ready to write a row of vertical sampling, so do it. + stbir__resample_vertical_gather(stbir_info, split_info, y, in_first_scanline, in_last_scanline, vertical_coefficients ); + + ++vertical_contributors; + vertical_coefficients += stbir_info->vertical.coefficient_width; + } +} + +#define STBIR__FLOAT_EMPTY_MARKER 3.0e+38F +#define STBIR__FLOAT_BUFFER_IS_EMPTY(ptr) ((ptr)[0]==STBIR__FLOAT_EMPTY_MARKER) + +static void stbir__encode_first_scanline_from_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info) +{ + // evict a scanline out into the output buffer + float* ring_buffer_entry = stbir__get_ring_buffer_entry(stbir_info, split_info, split_info->ring_buffer_begin_index ); + + // dump the scanline out + stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (size_t)split_info->ring_buffer_first_scanline * (size_t)stbir_info->output_stride_bytes ), ring_buffer_entry, split_info->ring_buffer_first_scanline STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // mark it as empty + ring_buffer_entry[ 0 ] = STBIR__FLOAT_EMPTY_MARKER; + + // advance the first scanline + split_info->ring_buffer_first_scanline++; + if ( ++split_info->ring_buffer_begin_index == stbir_info->ring_buffer_num_entries ) + split_info->ring_buffer_begin_index = 0; +} + +static void stbir__horizontal_resample_and_encode_first_scanline_from_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info) +{ + // evict a scanline out into the output buffer + + float* ring_buffer_entry = stbir__get_ring_buffer_entry(stbir_info, split_info, split_info->ring_buffer_begin_index ); + + // Now resample it into the buffer. + stbir__resample_horizontal_gather( stbir_info, split_info->vertical_buffer, ring_buffer_entry STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // dump the scanline out + stbir__encode_scanline( stbir_info, ( (char *)stbir_info->output_data ) + ( (size_t)split_info->ring_buffer_first_scanline * (size_t)stbir_info->output_stride_bytes ), split_info->vertical_buffer, split_info->ring_buffer_first_scanline STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // mark it as empty + ring_buffer_entry[ 0 ] = STBIR__FLOAT_EMPTY_MARKER; + + // advance the first scanline + split_info->ring_buffer_first_scanline++; + if ( ++split_info->ring_buffer_begin_index == stbir_info->ring_buffer_num_entries ) + split_info->ring_buffer_begin_index = 0; +} + +static void stbir__resample_vertical_scatter(stbir__info const * stbir_info, stbir__per_split_info* split_info, int n0, int n1, float const * vertical_coefficients, float const * vertical_buffer, float const * vertical_buffer_end ) +{ + STBIR_ASSERT( !stbir_info->vertical.is_gather ); + + STBIR_PROFILE_START( vertical ); + { + int k = 0, total = n1 - n0 + 1; + STBIR_ASSERT( total > 0 ); + do { + float * outputs[8]; + int i, n = total; if ( n > 8 ) n = 8; + for( i = 0 ; i < n ; i++ ) + { + outputs[ i ] = stbir__get_ring_buffer_scanline(stbir_info, split_info, k+i+n0 ); + if ( ( i ) && ( STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[i] ) != STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[0] ) ) ) // make sure runs are of the same type + { + n = i; + break; + } + } + // call the scatter to N scanlines at a time function (up to 8 scanlines of scattering at once) + ((STBIR__FLOAT_BUFFER_IS_EMPTY( outputs[0] ))?stbir__vertical_scatter_sets:stbir__vertical_scatter_blends)[n-1]( outputs, vertical_coefficients + k, vertical_buffer, vertical_buffer_end ); + k += n; + total -= n; + } while ( total ); + } + + STBIR_PROFILE_END( vertical ); +} + +typedef void stbir__handle_scanline_for_scatter_func(stbir__info const * stbir_info, stbir__per_split_info* split_info); + +static void stbir__vertical_scatter_loop( stbir__info const * stbir_info, stbir__per_split_info* split_info, int split_count ) +{ + int y, start_output_y, end_output_y, start_input_y, end_input_y; + stbir__contributors* vertical_contributors = stbir_info->vertical.contributors; + float const * vertical_coefficients = stbir_info->vertical.coefficients; + stbir__handle_scanline_for_scatter_func * handle_scanline_for_scatter; + void * scanline_scatter_buffer; + void * scanline_scatter_buffer_end; + int on_first_input_y, last_input_y; + + STBIR_ASSERT( !stbir_info->vertical.is_gather ); + + start_output_y = split_info->start_output_y; + end_output_y = split_info[split_count-1].end_output_y; // may do multiple split counts + + start_input_y = split_info->start_input_y; + end_input_y = split_info[split_count-1].end_input_y; + + // adjust for starting offset start_input_y + y = start_input_y + stbir_info->vertical.filter_pixel_margin; + vertical_contributors += y ; + vertical_coefficients += stbir_info->vertical.coefficient_width * y; + + if ( stbir_info->vertical_first ) + { + handle_scanline_for_scatter = stbir__horizontal_resample_and_encode_first_scanline_from_scatter; + scanline_scatter_buffer = split_info->decode_buffer; + scanline_scatter_buffer_end = ( (char*) scanline_scatter_buffer ) + sizeof( float ) * stbir_info->effective_channels * (stbir_info->scanline_extents.conservative.n1-stbir_info->scanline_extents.conservative.n0+1); + } + else + { + handle_scanline_for_scatter = stbir__encode_first_scanline_from_scatter; + scanline_scatter_buffer = split_info->vertical_buffer; + scanline_scatter_buffer_end = ( (char*) scanline_scatter_buffer ) + sizeof( float ) * stbir_info->effective_channels * stbir_info->horizontal.scale_info.output_sub_size; + } + + // initialize the ring buffer for scattering + split_info->ring_buffer_first_scanline = start_output_y; + split_info->ring_buffer_last_scanline = -1; + split_info->ring_buffer_begin_index = -1; + + // mark all the buffers as empty to start + for( y = 0 ; y < stbir_info->ring_buffer_num_entries ; y++ ) + stbir__get_ring_buffer_entry( stbir_info, split_info, y )[0] = STBIR__FLOAT_EMPTY_MARKER; // only used on scatter + + // do the loop in input space + on_first_input_y = 1; last_input_y = start_input_y; + for (y = start_input_y ; y < end_input_y; y++) + { + int out_first_scanline, out_last_scanline; + + out_first_scanline = vertical_contributors->n0; + out_last_scanline = vertical_contributors->n1; + + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if ( ( out_last_scanline >= out_first_scanline ) && ( ( ( out_first_scanline >= start_output_y ) && ( out_first_scanline < end_output_y ) ) || ( ( out_last_scanline >= start_output_y ) && ( out_last_scanline < end_output_y ) ) ) ) + { + float const * vc = vertical_coefficients; + + // keep track of the range actually seen for the next resize + last_input_y = y; + if ( ( on_first_input_y ) && ( y > start_input_y ) ) + split_info->start_input_y = y; + on_first_input_y = 0; + + // clip the region + if ( out_first_scanline < start_output_y ) + { + vc += start_output_y - out_first_scanline; + out_first_scanline = start_output_y; + } + + if ( out_last_scanline >= end_output_y ) + out_last_scanline = end_output_y - 1; + + // if very first scanline, init the index + if (split_info->ring_buffer_begin_index < 0) + split_info->ring_buffer_begin_index = out_first_scanline - start_output_y; + + STBIR_ASSERT( split_info->ring_buffer_begin_index <= out_first_scanline ); + + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline( stbir_info, y, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // When horizontal first, we resample horizontally into the vertical buffer before we scatter it out + if ( !stbir_info->vertical_first ) + stbir__resample_horizontal_gather( stbir_info, split_info->vertical_buffer, split_info->decode_buffer STBIR_ONLY_PROFILE_SET_SPLIT_INFO ); + + // Now it's sitting in the buffer ready to be distributed into the ring buffers. + + // evict from the ringbuffer, if we need are full + if ( ( ( split_info->ring_buffer_last_scanline - split_info->ring_buffer_first_scanline + 1 ) == stbir_info->ring_buffer_num_entries ) && + ( out_last_scanline > split_info->ring_buffer_last_scanline ) ) + handle_scanline_for_scatter( stbir_info, split_info ); + + // Now the horizontal buffer is ready to write to all ring buffer rows, so do it. + stbir__resample_vertical_scatter(stbir_info, split_info, out_first_scanline, out_last_scanline, vc, (float*)scanline_scatter_buffer, (float*)scanline_scatter_buffer_end ); + + // update the end of the buffer + if ( out_last_scanline > split_info->ring_buffer_last_scanline ) + split_info->ring_buffer_last_scanline = out_last_scanline; + } + ++vertical_contributors; + vertical_coefficients += stbir_info->vertical.coefficient_width; + } + + // now evict the scanlines that are left over in the ring buffer + while ( split_info->ring_buffer_first_scanline < end_output_y ) + handle_scanline_for_scatter(stbir_info, split_info); + + // update the end_input_y if we do multiple resizes with the same data + ++last_input_y; + for( y = 0 ; y < split_count; y++ ) + if ( split_info[y].end_input_y > last_input_y ) + split_info[y].end_input_y = last_input_y; +} + + +static stbir__kernel_callback * stbir__builtin_kernels[] = { 0, stbir__filter_trapezoid, stbir__filter_triangle, stbir__filter_cubic, stbir__filter_catmullrom, stbir__filter_mitchell, stbir__filter_point }; +static stbir__support_callback * stbir__builtin_supports[] = { 0, stbir__support_trapezoid, stbir__support_one, stbir__support_two, stbir__support_two, stbir__support_two, stbir__support_zeropoint5 }; + +static void stbir__set_sampler(stbir__sampler * samp, stbir_filter filter, stbir__kernel_callback * kernel, stbir__support_callback * support, stbir_edge edge, stbir__scale_info * scale_info, int always_gather, void * user_data ) +{ + // set filter + if (filter == 0) + { + filter = STBIR_DEFAULT_FILTER_DOWNSAMPLE; // default to downsample + if (scale_info->scale >= ( 1.0f - stbir__small_float ) ) + { + if ( (scale_info->scale <= ( 1.0f + stbir__small_float ) ) && ( STBIR_CEILF(scale_info->pixel_shift) == scale_info->pixel_shift ) ) + filter = STBIR_FILTER_POINT_SAMPLE; + else + filter = STBIR_DEFAULT_FILTER_UPSAMPLE; + } + } + samp->filter_enum = filter; + + STBIR_ASSERT(samp->filter_enum != 0); + STBIR_ASSERT((unsigned)samp->filter_enum < STBIR_FILTER_OTHER); + samp->filter_kernel = stbir__builtin_kernels[ filter ]; + samp->filter_support = stbir__builtin_supports[ filter ]; + + if ( kernel && support ) + { + samp->filter_kernel = kernel; + samp->filter_support = support; + samp->filter_enum = STBIR_FILTER_OTHER; + } + + samp->edge = edge; + samp->filter_pixel_width = stbir__get_filter_pixel_width (samp->filter_support, scale_info->scale, user_data ); + // Gather is always better, but in extreme downsamples, you have to most or all of the data in memory + // For horizontal, we always have all the pixels, so we always use gather here (always_gather==1). + // For vertical, we use gather if scaling up (which means we will have samp->filter_pixel_width + // scanlines in memory at once). + samp->is_gather = 0; + if ( scale_info->scale >= ( 1.0f - stbir__small_float ) ) + samp->is_gather = 1; + else if ( ( always_gather ) || ( samp->filter_pixel_width <= STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT ) ) + samp->is_gather = 2; + + // pre calculate stuff based on the above + samp->coefficient_width = stbir__get_coefficient_width(samp, samp->is_gather, user_data); + + // filter_pixel_width is the conservative size in pixels of input that affect an output pixel. + // In rare cases (only with 2 pix to 1 pix with the default filters), it's possible that the + // filter will extend before or after the scanline beyond just one extra entire copy of the + // scanline (we would hit the edge twice). We don't let you do that, so we clamp the total + // width to 3x the total of input pixel (once for the scanline, once for the left side + // overhang, and once for the right side). We only do this for edge mode, since the other + // modes can just re-edge clamp back in again. + if ( edge == STBIR_EDGE_WRAP ) + if ( samp->filter_pixel_width > ( scale_info->input_full_size * 3 ) ) + samp->filter_pixel_width = scale_info->input_full_size * 3; + + // This is how much to expand buffers to account for filters seeking outside + // the image boundaries. + samp->filter_pixel_margin = samp->filter_pixel_width / 2; + + // filter_pixel_margin is the amount that this filter can overhang on just one side of either + // end of the scanline (left or the right). Since we only allow you to overhang 1 scanline's + // worth of pixels, we clamp this one side of overhang to the input scanline size. Again, + // this clamping only happens in rare cases with the default filters (2 pix to 1 pix). + if ( edge == STBIR_EDGE_WRAP ) + if ( samp->filter_pixel_margin > scale_info->input_full_size ) + samp->filter_pixel_margin = scale_info->input_full_size; + + samp->num_contributors = stbir__get_contributors(samp, samp->is_gather); + + samp->contributors_size = samp->num_contributors * sizeof(stbir__contributors); + samp->coefficients_size = samp->num_contributors * samp->coefficient_width * sizeof(float) + sizeof(float); // extra sizeof(float) is padding + + samp->gather_prescatter_contributors = 0; + samp->gather_prescatter_coefficients = 0; + if ( samp->is_gather == 0 ) + { + samp->gather_prescatter_coefficient_width = samp->filter_pixel_width; + samp->gather_prescatter_num_contributors = stbir__get_contributors(samp, 2); + samp->gather_prescatter_contributors_size = samp->gather_prescatter_num_contributors * sizeof(stbir__contributors); + samp->gather_prescatter_coefficients_size = samp->gather_prescatter_num_contributors * samp->gather_prescatter_coefficient_width * sizeof(float); + } +} + +static void stbir__get_conservative_extents( stbir__sampler * samp, stbir__contributors * range, void * user_data ) +{ + float scale = samp->scale_info.scale; + float out_shift = samp->scale_info.pixel_shift; + stbir__support_callback * support = samp->filter_support; + int input_full_size = samp->scale_info.input_full_size; + stbir_edge edge = samp->edge; + float inv_scale = samp->scale_info.inv_scale; + + STBIR_ASSERT( samp->is_gather != 0 ); + + if ( samp->is_gather == 1 ) + { + int in_first_pixel, in_last_pixel; + float out_filter_radius = support(inv_scale, user_data) * scale; + + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, 0.5, out_filter_radius, inv_scale, out_shift, input_full_size, edge ); + range->n0 = in_first_pixel; + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, ( (float)(samp->scale_info.output_sub_size-1) ) + 0.5f, out_filter_radius, inv_scale, out_shift, input_full_size, edge ); + range->n1 = in_last_pixel; + } + else if ( samp->is_gather == 2 ) // downsample gather, refine + { + float in_pixels_radius = support(scale, user_data) * inv_scale; + int filter_pixel_margin = samp->filter_pixel_margin; + int output_sub_size = samp->scale_info.output_sub_size; + int input_end; + int n; + int in_first_pixel, in_last_pixel; + + // get a conservative area of the input range + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, 0, 0, inv_scale, out_shift, input_full_size, edge ); + range->n0 = in_first_pixel; + stbir__calculate_in_pixel_range( &in_first_pixel, &in_last_pixel, (float)output_sub_size, 0, inv_scale, out_shift, input_full_size, edge ); + range->n1 = in_last_pixel; + + // now go through the margin to the start of area to find bottom + n = range->n0 + 1; + input_end = -filter_pixel_margin; + while( n >= input_end ) + { + int out_first_pixel, out_last_pixel; + stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, ((float)n)+0.5f, in_pixels_radius, scale, out_shift, output_sub_size ); + if ( out_first_pixel > out_last_pixel ) + break; + + if ( ( out_first_pixel < output_sub_size ) || ( out_last_pixel >= 0 ) ) + range->n0 = n; + --n; + } + + // now go through the end of the area through the margin to find top + n = range->n1 - 1; + input_end = n + 1 + filter_pixel_margin; + while( n <= input_end ) + { + int out_first_pixel, out_last_pixel; + stbir__calculate_out_pixel_range( &out_first_pixel, &out_last_pixel, ((float)n)+0.5f, in_pixels_radius, scale, out_shift, output_sub_size ); + if ( out_first_pixel > out_last_pixel ) + break; + if ( ( out_first_pixel < output_sub_size ) || ( out_last_pixel >= 0 ) ) + range->n1 = n; + ++n; + } + } + + if ( samp->edge == STBIR_EDGE_WRAP ) + { + // if we are wrapping, and we are very close to the image size (so the edges might merge), just use the scanline up to the edge + if ( ( range->n0 > 0 ) && ( range->n1 >= input_full_size ) ) + { + int marg = range->n1 - input_full_size + 1; + if ( ( marg + STBIR__MERGE_RUNS_PIXEL_THRESHOLD ) >= range->n0 ) + range->n0 = 0; + } + if ( ( range->n0 < 0 ) && ( range->n1 < (input_full_size-1) ) ) + { + int marg = -range->n0; + if ( ( input_full_size - marg - STBIR__MERGE_RUNS_PIXEL_THRESHOLD - 1 ) <= range->n1 ) + range->n1 = input_full_size - 1; + } + } + else + { + // for non-edge-wrap modes, we never read over the edge, so clamp + if ( range->n0 < 0 ) + range->n0 = 0; + if ( range->n1 >= input_full_size ) + range->n1 = input_full_size - 1; + } +} + +static void stbir__get_split_info( stbir__per_split_info* split_info, int splits, int output_height, int vertical_pixel_margin, int input_full_height ) +{ + int i, cur; + int left = output_height; + + cur = 0; + for( i = 0 ; i < splits ; i++ ) + { + int each; + split_info[i].start_output_y = cur; + each = left / ( splits - i ); + split_info[i].end_output_y = cur + each; + cur += each; + left -= each; + + // scatter range (updated to minimum as you run it) + split_info[i].start_input_y = -vertical_pixel_margin; + split_info[i].end_input_y = input_full_height + vertical_pixel_margin; + } +} + +static void stbir__free_internal_mem( stbir__info *info ) +{ + #define STBIR__FREE_AND_CLEAR( ptr ) { if ( ptr ) { void * p = (ptr); (ptr) = 0; STBIR_FREE( p, info->user_data); } } + + if ( info ) + { + #ifndef STBIR__SEPARATE_ALLOCATIONS + STBIR__FREE_AND_CLEAR( info->alloced_mem ); + #else + int i,j; + + if ( ( info->vertical.gather_prescatter_contributors ) && ( (void*)info->vertical.gather_prescatter_contributors != (void*)info->split_info[0].decode_buffer ) ) + { + STBIR__FREE_AND_CLEAR( info->vertical.gather_prescatter_coefficients ); + STBIR__FREE_AND_CLEAR( info->vertical.gather_prescatter_contributors ); + } + for( i = 0 ; i < info->splits ; i++ ) + { + for( j = 0 ; j < info->alloc_ring_buffer_num_entries ; j++ ) + { + #ifdef STBIR_SIMD8 + if ( info->effective_channels == 3 ) + --info->split_info[i].ring_buffers[j]; // avx in 3 channel mode needs one float at the start of the buffer + #endif + STBIR__FREE_AND_CLEAR( info->split_info[i].ring_buffers[j] ); + } + + #ifdef STBIR_SIMD8 + if ( info->effective_channels == 3 ) + --info->split_info[i].decode_buffer; // avx in 3 channel mode needs one float at the start of the buffer + #endif + STBIR__FREE_AND_CLEAR( info->split_info[i].decode_buffer ); + STBIR__FREE_AND_CLEAR( info->split_info[i].ring_buffers ); + STBIR__FREE_AND_CLEAR( info->split_info[i].vertical_buffer ); + } + STBIR__FREE_AND_CLEAR( info->split_info ); + if ( info->vertical.coefficients != info->horizontal.coefficients ) + { + STBIR__FREE_AND_CLEAR( info->vertical.coefficients ); + STBIR__FREE_AND_CLEAR( info->vertical.contributors ); + } + STBIR__FREE_AND_CLEAR( info->horizontal.coefficients ); + STBIR__FREE_AND_CLEAR( info->horizontal.contributors ); + STBIR__FREE_AND_CLEAR( info->alloced_mem ); + STBIR__FREE_AND_CLEAR( info ); + #endif + } + + #undef STBIR__FREE_AND_CLEAR +} + +static int stbir__get_max_split( int splits, int height ) +{ + int i; + int max = 0; + + for( i = 0 ; i < splits ; i++ ) + { + int each = height / ( splits - i ); + if ( each > max ) + max = each; + height -= each; + } + return max; +} + +static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_n_coeffs_funcs[8] = +{ + 0, stbir__horizontal_gather_1_channels_with_n_coeffs_funcs, stbir__horizontal_gather_2_channels_with_n_coeffs_funcs, stbir__horizontal_gather_3_channels_with_n_coeffs_funcs, stbir__horizontal_gather_4_channels_with_n_coeffs_funcs, 0,0, stbir__horizontal_gather_7_channels_with_n_coeffs_funcs +}; + +static stbir__horizontal_gather_channels_func ** stbir__horizontal_gather_channels_funcs[8] = +{ + 0, stbir__horizontal_gather_1_channels_funcs, stbir__horizontal_gather_2_channels_funcs, stbir__horizontal_gather_3_channels_funcs, stbir__horizontal_gather_4_channels_funcs, 0,0, stbir__horizontal_gather_7_channels_funcs +}; + +// there are six resize classifications: 0 == vertical scatter, 1 == vertical gather < 1x scale, 2 == vertical gather 1x-2x scale, 4 == vertical gather < 3x scale, 4 == vertical gather > 3x scale, 5 == <=4 pixel height, 6 == <=4 pixel wide column +#define STBIR_RESIZE_CLASSIFICATIONS 8 + +static float stbir__compute_weights[5][STBIR_RESIZE_CLASSIFICATIONS][4]= // 5 = 0=1chan, 1=2chan, 2=3chan, 3=4chan, 4=7chan +{ + { + { 1.00000f, 1.00000f, 0.31250f, 1.00000f }, + { 0.56250f, 0.59375f, 0.00000f, 0.96875f }, + { 1.00000f, 0.06250f, 0.00000f, 1.00000f }, + { 0.00000f, 0.09375f, 1.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.03125f, 0.12500f, 1.00000f, 1.00000f }, + { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.00000f, 0.03125f }, + }, { + { 0.00000f, 0.84375f, 0.00000f, 0.03125f }, + { 0.09375f, 0.93750f, 0.00000f, 0.78125f }, + { 0.87500f, 0.21875f, 0.00000f, 0.96875f }, + { 0.09375f, 0.09375f, 1.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.03125f, 0.12500f, 1.00000f, 1.00000f }, + { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.00000f, 0.53125f }, + }, { + { 0.00000f, 0.53125f, 0.00000f, 0.03125f }, + { 0.06250f, 0.96875f, 0.00000f, 0.53125f }, + { 0.87500f, 0.18750f, 0.00000f, 0.93750f }, + { 0.00000f, 0.09375f, 1.00000f, 1.00000f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.03125f, 0.12500f, 1.00000f, 1.00000f }, + { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.00000f, 0.56250f }, + }, { + { 0.00000f, 0.50000f, 0.00000f, 0.71875f }, + { 0.06250f, 0.84375f, 0.00000f, 0.87500f }, + { 1.00000f, 0.50000f, 0.50000f, 0.96875f }, + { 1.00000f, 0.09375f, 0.31250f, 0.50000f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 1.00000f, 0.03125f, 0.03125f, 0.53125f }, + { 0.18750f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.03125f, 0.18750f }, + }, { + { 0.00000f, 0.59375f, 0.00000f, 0.96875f }, + { 0.06250f, 0.81250f, 0.06250f, 0.59375f }, + { 0.75000f, 0.43750f, 0.12500f, 0.96875f }, + { 0.87500f, 0.06250f, 0.18750f, 0.43750f }, + { 1.00000f, 1.00000f, 1.00000f, 1.00000f }, + { 0.15625f, 0.12500f, 1.00000f, 1.00000f }, + { 0.06250f, 0.12500f, 0.00000f, 1.00000f }, + { 0.00000f, 1.00000f, 0.03125f, 0.34375f }, + } +}; + +// structure that allow us to query and override info for training the costs +typedef struct STBIR__V_FIRST_INFO +{ + double v_cost, h_cost; + int control_v_first; // 0 = no control, 1 = force hori, 2 = force vert + int v_first; + int v_resize_classification; + int is_gather; +} STBIR__V_FIRST_INFO; + +#ifdef STBIR__V_FIRST_INFO_BUFFER +static STBIR__V_FIRST_INFO STBIR__V_FIRST_INFO_BUFFER = {0}; +#define STBIR__V_FIRST_INFO_POINTER &STBIR__V_FIRST_INFO_BUFFER +#else +#define STBIR__V_FIRST_INFO_POINTER 0 +#endif + +// Figure out whether to scale along the horizontal or vertical first. +// This only *super* important when you are scaling by a massively +// different amount in the vertical vs the horizontal (for example, if +// you are scaling by 2x in the width, and 0.5x in the height, then you +// want to do the vertical scale first, because it's around 3x faster +// in that order. +// +// In more normal circumstances, this makes a 20-40% differences, so +// it's good to get right, but not critical. The normal way that you +// decide which direction goes first is just figuring out which +// direction does more multiplies. But with modern CPUs with their +// fancy caches and SIMD and high IPC abilities, so there's just a lot +// more that goes into it. +// +// My handwavy sort of solution is to have an app that does a whole +// bunch of timing for both vertical and horizontal first modes, +// and then another app that can read lots of these timing files +// and try to search for the best weights to use. Dotimings.c +// is the app that does a bunch of timings, and vf_train.c is the +// app that solves for the best weights (and shows how well it +// does currently). + +static int stbir__should_do_vertical_first( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int horizontal_filter_pixel_width, float horizontal_scale, int horizontal_output_size, int vertical_filter_pixel_width, float vertical_scale, int vertical_output_size, int is_gather, STBIR__V_FIRST_INFO * info ) +{ + double v_cost, h_cost; + float * weights; + int vertical_first; + int v_classification; + + // categorize the resize into buckets + if ( ( vertical_output_size <= 4 ) || ( horizontal_output_size <= 4 ) ) + v_classification = ( vertical_output_size < horizontal_output_size ) ? 6 : 7; + else if ( vertical_scale <= 1.0f ) + v_classification = ( is_gather ) ? 1 : 0; + else if ( vertical_scale <= 2.0f) + v_classification = 2; + else if ( vertical_scale <= 3.0f) + v_classification = 3; + else if ( vertical_scale <= 4.0f) + v_classification = 5; + else + v_classification = 6; + + // use the right weights + weights = weights_table[ v_classification ]; + + // this is the costs when you don't take into account modern CPUs with high ipc and simd and caches - wish we had a better estimate + h_cost = (float)horizontal_filter_pixel_width * weights[0] + horizontal_scale * (float)vertical_filter_pixel_width * weights[1]; + v_cost = (float)vertical_filter_pixel_width * weights[2] + vertical_scale * (float)horizontal_filter_pixel_width * weights[3]; + + // use computation estimate to decide vertical first or not + vertical_first = ( v_cost <= h_cost ) ? 1 : 0; + + // save these, if requested + if ( info ) + { + info->h_cost = h_cost; + info->v_cost = v_cost; + info->v_resize_classification = v_classification; + info->v_first = vertical_first; + info->is_gather = is_gather; + } + + // and this allows us to override everything for testing (see dotiming.c) + if ( ( info ) && ( info->control_v_first ) ) + vertical_first = ( info->control_v_first == 2 ) ? 1 : 0; + + return vertical_first; +} + +// layout lookups - must match stbir_internal_pixel_layout +static unsigned char stbir__pixel_channels[] = { + 1,2,3,3,4, // 1ch, 2ch, rgb, bgr, 4ch + 4,4,4,4,2,2, // RGBA,BGRA,ARGB,ABGR,RA,AR + 4,4,4,4,2,2, // RGBA_PM,BGRA_PM,ARGB_PM,ABGR_PM,RA_PM,AR_PM +}; + +// the internal pixel layout enums are in a different order, so we can easily do range comparisons of types +// the public pixel layout is ordered in a way that if you cast num_channels (1-4) to the enum, you get something sensible +static stbir_internal_pixel_layout stbir__pixel_layout_convert_public_to_internal[] = { + STBIRI_BGR, STBIRI_1CHANNEL, STBIRI_2CHANNEL, STBIRI_RGB, STBIRI_RGBA, + STBIRI_4CHANNEL, STBIRI_BGRA, STBIRI_ARGB, STBIRI_ABGR, STBIRI_RA, STBIRI_AR, + STBIRI_RGBA_PM, STBIRI_BGRA_PM, STBIRI_ARGB_PM, STBIRI_ABGR_PM, STBIRI_RA_PM, STBIRI_AR_PM, +}; + +static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sampler * horizontal, stbir__sampler * vertical, stbir__contributors * conservative, stbir_pixel_layout input_pixel_layout_public, stbir_pixel_layout output_pixel_layout_public, int splits, int new_x, int new_y, int fast_alpha, void * user_data STBIR_ONLY_PROFILE_BUILD_GET_INFO ) +{ + static char stbir_channel_count_index[8]={ 9,0,1,2, 3,9,9,4 }; + + stbir__info * info = 0; + void * alloced = 0; + size_t alloced_total = 0; + int vertical_first; + int decode_buffer_size, ring_buffer_length_bytes, ring_buffer_size, vertical_buffer_size, alloc_ring_buffer_num_entries; + + int alpha_weighting_type = 0; // 0=none, 1=simple, 2=fancy + int conservative_split_output_size = stbir__get_max_split( splits, vertical->scale_info.output_sub_size ); + stbir_internal_pixel_layout input_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ input_pixel_layout_public ]; + stbir_internal_pixel_layout output_pixel_layout = stbir__pixel_layout_convert_public_to_internal[ output_pixel_layout_public ]; + int channels = stbir__pixel_channels[ input_pixel_layout ]; + int effective_channels = channels; + + // first figure out what type of alpha weighting to use (if any) + if ( ( horizontal->filter_enum != STBIR_FILTER_POINT_SAMPLE ) || ( vertical->filter_enum != STBIR_FILTER_POINT_SAMPLE ) ) // no alpha weighting on point sampling + { + if ( ( input_pixel_layout >= STBIRI_RGBA ) && ( input_pixel_layout <= STBIRI_AR ) && ( output_pixel_layout >= STBIRI_RGBA ) && ( output_pixel_layout <= STBIRI_AR ) ) + { + if ( fast_alpha ) + { + alpha_weighting_type = 4; + } + else + { + static int fancy_alpha_effective_cnts[6] = { 7, 7, 7, 7, 3, 3 }; + alpha_weighting_type = 2; + effective_channels = fancy_alpha_effective_cnts[ input_pixel_layout - STBIRI_RGBA ]; + } + } + else if ( ( input_pixel_layout >= STBIRI_RGBA_PM ) && ( input_pixel_layout <= STBIRI_AR_PM ) && ( output_pixel_layout >= STBIRI_RGBA ) && ( output_pixel_layout <= STBIRI_AR ) ) + { + // input premult, output non-premult + alpha_weighting_type = 3; + } + else if ( ( input_pixel_layout >= STBIRI_RGBA ) && ( input_pixel_layout <= STBIRI_AR ) && ( output_pixel_layout >= STBIRI_RGBA_PM ) && ( output_pixel_layout <= STBIRI_AR_PM ) ) + { + // input non-premult, output premult + alpha_weighting_type = 1; + } + } + + // channel in and out count must match currently + if ( channels != stbir__pixel_channels[ output_pixel_layout ] ) + return 0; + + // get vertical first + vertical_first = stbir__should_do_vertical_first( stbir__compute_weights[ (int)stbir_channel_count_index[ effective_channels ] ], horizontal->filter_pixel_width, horizontal->scale_info.scale, horizontal->scale_info.output_sub_size, vertical->filter_pixel_width, vertical->scale_info.scale, vertical->scale_info.output_sub_size, vertical->is_gather, STBIR__V_FIRST_INFO_POINTER ); + + // sometimes read one float off in some of the unrolled loops (with a weight of zero coeff, so it doesn't have an effect) + decode_buffer_size = ( conservative->n1 - conservative->n0 + 1 ) * effective_channels * sizeof(float) + sizeof(float); // extra float for padding + +#if defined( STBIR__SEPARATE_ALLOCATIONS ) && defined(STBIR_SIMD8) + if ( effective_channels == 3 ) + decode_buffer_size += sizeof(float); // avx in 3 channel mode needs one float at the start of the buffer (only with separate allocations) +#endif + + ring_buffer_length_bytes = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float); // extra float for padding + + // if we do vertical first, the ring buffer holds a whole decoded line + if ( vertical_first ) + ring_buffer_length_bytes = ( decode_buffer_size + 15 ) & ~15; + + if ( ( ring_buffer_length_bytes & 4095 ) == 0 ) ring_buffer_length_bytes += 64*3; // avoid 4k alias + + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + alloc_ring_buffer_num_entries = vertical->filter_pixel_width + 1; + + // we never need more ring buffer entries than the scanlines we're outputting when in scatter mode + if ( ( !vertical->is_gather ) && ( alloc_ring_buffer_num_entries > conservative_split_output_size ) ) + alloc_ring_buffer_num_entries = conservative_split_output_size; + + ring_buffer_size = alloc_ring_buffer_num_entries * ring_buffer_length_bytes; + + // The vertical buffer is used differently, depending on whether we are scattering + // the vertical scanlines, or gathering them. + // If scattering, it's used at the temp buffer to accumulate each output. + // If gathering, it's just the output buffer. + vertical_buffer_size = horizontal->scale_info.output_sub_size * effective_channels * sizeof(float) + sizeof(float); // extra float for padding + + // we make two passes through this loop, 1st to add everything up, 2nd to allocate and init + for(;;) + { + int i; + void * advance_mem = alloced; + int copy_horizontal = 0; + stbir__sampler * possibly_use_horizontal_for_pivot = 0; + +#ifdef STBIR__SEPARATE_ALLOCATIONS + #define STBIR__NEXT_PTR( ptr, size, ntype ) if ( alloced ) { void * p = STBIR_MALLOC( size, user_data); if ( p == 0 ) { stbir__free_internal_mem( info ); return 0; } (ptr) = (ntype*)p; } +#else + #define STBIR__NEXT_PTR( ptr, size, ntype ) advance_mem = (void*) ( ( ((size_t)advance_mem) + 15 ) & ~15 ); if ( alloced ) ptr = (ntype*)advance_mem; advance_mem = ((char*)advance_mem) + (size); +#endif + + STBIR__NEXT_PTR( info, sizeof( stbir__info ), stbir__info ); + + STBIR__NEXT_PTR( info->split_info, sizeof( stbir__per_split_info ) * splits, stbir__per_split_info ); + + if ( info ) + { + static stbir__alpha_weight_func * fancy_alpha_weights[6] = { stbir__fancy_alpha_weight_4ch, stbir__fancy_alpha_weight_4ch, stbir__fancy_alpha_weight_4ch, stbir__fancy_alpha_weight_4ch, stbir__fancy_alpha_weight_2ch, stbir__fancy_alpha_weight_2ch }; + static stbir__alpha_unweight_func * fancy_alpha_unweights[6] = { stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_4ch, stbir__fancy_alpha_unweight_2ch, stbir__fancy_alpha_unweight_2ch }; + static stbir__alpha_weight_func * simple_alpha_weights[6] = { stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_4ch, stbir__simple_alpha_weight_2ch, stbir__simple_alpha_weight_2ch }; + static stbir__alpha_unweight_func * simple_alpha_unweights[6] = { stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_4ch, stbir__simple_alpha_unweight_2ch, stbir__simple_alpha_unweight_2ch }; + + // initialize info fields + info->alloced_mem = alloced; + info->alloced_total = alloced_total; + + info->channels = channels; + info->effective_channels = effective_channels; + + info->offset_x = new_x; + info->offset_y = new_y; + info->alloc_ring_buffer_num_entries = alloc_ring_buffer_num_entries; + info->ring_buffer_num_entries = 0; + info->ring_buffer_length_bytes = ring_buffer_length_bytes; + info->splits = splits; + info->vertical_first = vertical_first; + + info->input_pixel_layout_internal = input_pixel_layout; + info->output_pixel_layout_internal = output_pixel_layout; + + // setup alpha weight functions + info->alpha_weight = 0; + info->alpha_unweight = 0; + + // handle alpha weighting functions and overrides + if ( alpha_weighting_type == 2 ) + { + // high quality alpha multiplying on the way in, dividing on the way out + info->alpha_weight = fancy_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; + info->alpha_unweight = fancy_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ]; + } + else if ( alpha_weighting_type == 4 ) + { + // fast alpha multiplying on the way in, dividing on the way out + info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; + info->alpha_unweight = simple_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ]; + } + else if ( alpha_weighting_type == 1 ) + { + // fast alpha on the way in, leave in premultiplied form on way out + info->alpha_weight = simple_alpha_weights[ input_pixel_layout - STBIRI_RGBA ]; + } + else if ( alpha_weighting_type == 3 ) + { + // incoming is premultiplied, fast alpha dividing on the way out - non-premultiplied output + info->alpha_unweight = simple_alpha_unweights[ output_pixel_layout - STBIRI_RGBA ]; + } + + // handle 3-chan color flipping, using the alpha weight path + if ( ( ( input_pixel_layout == STBIRI_RGB ) && ( output_pixel_layout == STBIRI_BGR ) ) || + ( ( input_pixel_layout == STBIRI_BGR ) && ( output_pixel_layout == STBIRI_RGB ) ) ) + { + // do the flipping on the smaller of the two ends + if ( horizontal->scale_info.scale < 1.0f ) + info->alpha_unweight = stbir__simple_flip_3ch; + else + info->alpha_weight = stbir__simple_flip_3ch; + } + + } + + // get all the per-split buffers + for( i = 0 ; i < splits ; i++ ) + { + STBIR__NEXT_PTR( info->split_info[i].decode_buffer, decode_buffer_size, float ); + +#ifdef STBIR__SEPARATE_ALLOCATIONS + + #ifdef STBIR_SIMD8 + if ( ( info ) && ( effective_channels == 3 ) ) + ++info->split_info[i].decode_buffer; // avx in 3 channel mode needs one float at the start of the buffer + #endif + + STBIR__NEXT_PTR( info->split_info[i].ring_buffers, alloc_ring_buffer_num_entries * sizeof(float*), float* ); + { + int j; + for( j = 0 ; j < alloc_ring_buffer_num_entries ; j++ ) + { + STBIR__NEXT_PTR( info->split_info[i].ring_buffers[j], ring_buffer_length_bytes, float ); + #ifdef STBIR_SIMD8 + if ( ( info ) && ( effective_channels == 3 ) ) + ++info->split_info[i].ring_buffers[j]; // avx in 3 channel mode needs one float at the start of the buffer + #endif + } + } +#else + STBIR__NEXT_PTR( info->split_info[i].ring_buffer, ring_buffer_size, float ); +#endif + STBIR__NEXT_PTR( info->split_info[i].vertical_buffer, vertical_buffer_size, float ); + } + + // alloc memory for to-be-pivoted coeffs (if necessary) + if ( vertical->is_gather == 0 ) + { + int both; + int temp_mem_amt; + + // when in vertical scatter mode, we first build the coefficients in gather mode, and then pivot after, + // that means we need two buffers, so we try to use the decode buffer and ring buffer for this. if that + // is too small, we just allocate extra memory to use as this temp. + + both = vertical->gather_prescatter_contributors_size + vertical->gather_prescatter_coefficients_size; + +#ifdef STBIR__SEPARATE_ALLOCATIONS + temp_mem_amt = decode_buffer_size; +#else + temp_mem_amt = ( decode_buffer_size + ring_buffer_size + vertical_buffer_size ) * splits; +#endif + if ( temp_mem_amt >= both ) + { + if ( info ) + { + vertical->gather_prescatter_contributors = (stbir__contributors*)info->split_info[0].decode_buffer; + vertical->gather_prescatter_coefficients = (float*) ( ( (char*)info->split_info[0].decode_buffer ) + vertical->gather_prescatter_contributors_size ); + } + } + else + { + // ring+decode memory is too small, so allocate temp memory + STBIR__NEXT_PTR( vertical->gather_prescatter_contributors, vertical->gather_prescatter_contributors_size, stbir__contributors ); + STBIR__NEXT_PTR( vertical->gather_prescatter_coefficients, vertical->gather_prescatter_coefficients_size, float ); + } + } + + STBIR__NEXT_PTR( horizontal->contributors, horizontal->contributors_size, stbir__contributors ); + STBIR__NEXT_PTR( horizontal->coefficients, horizontal->coefficients_size, float ); + + // are the two filters identical?? (happens a lot with mipmap generation) + if ( ( horizontal->filter_kernel == vertical->filter_kernel ) && ( horizontal->filter_support == vertical->filter_support ) && ( horizontal->edge == vertical->edge ) && ( horizontal->scale_info.output_sub_size == vertical->scale_info.output_sub_size ) ) + { + float diff_scale = horizontal->scale_info.scale - vertical->scale_info.scale; + float diff_shift = horizontal->scale_info.pixel_shift - vertical->scale_info.pixel_shift; + if ( diff_scale < 0.0f ) diff_scale = -diff_scale; + if ( diff_shift < 0.0f ) diff_shift = -diff_shift; + if ( ( diff_scale <= stbir__small_float ) && ( diff_shift <= stbir__small_float ) ) + { + if ( horizontal->is_gather == vertical->is_gather ) + { + copy_horizontal = 1; + goto no_vert_alloc; + } + // everything matches, but vertical is scatter, horizontal is gather, use horizontal coeffs for vertical pivot coeffs + possibly_use_horizontal_for_pivot = horizontal; + } + } + + STBIR__NEXT_PTR( vertical->contributors, vertical->contributors_size, stbir__contributors ); + STBIR__NEXT_PTR( vertical->coefficients, vertical->coefficients_size, float ); + + no_vert_alloc: + + if ( info ) + { + STBIR_PROFILE_BUILD_START( horizontal ); + + stbir__calculate_filters( horizontal, 0, user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO ); + + // setup the horizontal gather functions + // start with defaulting to the n_coeffs functions (specialized on channels and remnant leftover) + info->horizontal_gather_channels = stbir__horizontal_gather_n_coeffs_funcs[ effective_channels ][ horizontal->extent_info.widest & 3 ]; + // but if the number of coeffs <= 12, use another set of special cases. <=12 coeffs is any enlarging resize, or shrinking resize down to about 1/3 size + if ( horizontal->extent_info.widest <= 12 ) + info->horizontal_gather_channels = stbir__horizontal_gather_channels_funcs[ effective_channels ][ horizontal->extent_info.widest - 1 ]; + + info->scanline_extents.conservative.n0 = conservative->n0; + info->scanline_extents.conservative.n1 = conservative->n1; + + // get exact extents + stbir__get_extents( horizontal, &info->scanline_extents ); + + // pack the horizontal coeffs + horizontal->coefficient_width = stbir__pack_coefficients(horizontal->num_contributors, horizontal->contributors, horizontal->coefficients, horizontal->coefficient_width, horizontal->extent_info.widest, info->scanline_extents.conservative.n0, info->scanline_extents.conservative.n1 ); + + STBIR_MEMCPY( &info->horizontal, horizontal, sizeof( stbir__sampler ) ); + + STBIR_PROFILE_BUILD_END( horizontal ); + + if ( copy_horizontal ) + { + STBIR_MEMCPY( &info->vertical, horizontal, sizeof( stbir__sampler ) ); + } + else + { + STBIR_PROFILE_BUILD_START( vertical ); + + stbir__calculate_filters( vertical, possibly_use_horizontal_for_pivot, user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO ); + STBIR_MEMCPY( &info->vertical, vertical, sizeof( stbir__sampler ) ); + + STBIR_PROFILE_BUILD_END( vertical ); + } + + // setup the vertical split ranges + stbir__get_split_info( info->split_info, info->splits, info->vertical.scale_info.output_sub_size, info->vertical.filter_pixel_margin, info->vertical.scale_info.input_full_size ); + + // now we know precisely how many entries we need + info->ring_buffer_num_entries = info->vertical.extent_info.widest; + + // we never need more ring buffer entries than the scanlines we're outputting + if ( ( !info->vertical.is_gather ) && ( info->ring_buffer_num_entries > conservative_split_output_size ) ) + info->ring_buffer_num_entries = conservative_split_output_size; + STBIR_ASSERT( info->ring_buffer_num_entries <= info->alloc_ring_buffer_num_entries ); + + // a few of the horizontal gather functions read past the end of the decode (but mask it out), + // so put in normal values so no snans or denormals accidentally sneak in (also, in the ring + // buffer for vertical first) + for( i = 0 ; i < splits ; i++ ) + { + int t, ofs, start; + + ofs = decode_buffer_size / 4; + start = ofs - 4; + if ( start < 0 ) start = 0; + + for( t = start ; t < ofs; t++ ) + info->split_info[i].decode_buffer[ t ] = 9999.0f; + + if ( vertical_first ) + { + int j; + for( j = 0; j < info->ring_buffer_num_entries ; j++ ) + { + for( t = start ; t < ofs; t++ ) + stbir__get_ring_buffer_entry( info, info->split_info + i, j )[ t ] = 9999.0f; + } + } + } + } + + #undef STBIR__NEXT_PTR + + + // is this the first time through loop? + if ( info == 0 ) + { + alloced_total = ( 15 + (size_t)advance_mem ); + alloced = STBIR_MALLOC( alloced_total, user_data ); + if ( alloced == 0 ) + return 0; + } + else + return info; // success + } +} + +static int stbir__perform_resize( stbir__info const * info, int split_start, int split_count ) +{ + stbir__per_split_info * split_info = info->split_info + split_start; + + STBIR_PROFILE_CLEAR_EXTRAS(); + + STBIR_PROFILE_FIRST_START( looping ); + if (info->vertical.is_gather) + stbir__vertical_gather_loop( info, split_info, split_count ); + else + stbir__vertical_scatter_loop( info, split_info, split_count ); + STBIR_PROFILE_END( looping ); + + return 1; +} + +static void stbir__update_info_from_resize( stbir__info * info, STBIR_RESIZE * resize ) +{ + static stbir__decode_pixels_func * decode_simple[STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= + { + /* 1ch-4ch */ stbir__decode_uint8_srgb, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear, + }; + + static stbir__decode_pixels_func * decode_alphas[STBIRI_AR-STBIRI_RGBA+1][STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= + { + { /* RGBA */ stbir__decode_uint8_srgb4_linearalpha, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear }, + { /* BGRA */ stbir__decode_uint8_srgb4_linearalpha_BGRA, stbir__decode_uint8_srgb_BGRA, 0, stbir__decode_float_linear_BGRA, stbir__decode_half_float_linear_BGRA }, + { /* ARGB */ stbir__decode_uint8_srgb4_linearalpha_ARGB, stbir__decode_uint8_srgb_ARGB, 0, stbir__decode_float_linear_ARGB, stbir__decode_half_float_linear_ARGB }, + { /* ABGR */ stbir__decode_uint8_srgb4_linearalpha_ABGR, stbir__decode_uint8_srgb_ABGR, 0, stbir__decode_float_linear_ABGR, stbir__decode_half_float_linear_ABGR }, + { /* RA */ stbir__decode_uint8_srgb2_linearalpha, stbir__decode_uint8_srgb, 0, stbir__decode_float_linear, stbir__decode_half_float_linear }, + { /* AR */ stbir__decode_uint8_srgb2_linearalpha_AR, stbir__decode_uint8_srgb_AR, 0, stbir__decode_float_linear_AR, stbir__decode_half_float_linear_AR }, + }; + + static stbir__decode_pixels_func * decode_simple_scaled_or_not[2][2]= + { + { stbir__decode_uint8_linear_scaled, stbir__decode_uint8_linear }, { stbir__decode_uint16_linear_scaled, stbir__decode_uint16_linear }, + }; + + static stbir__decode_pixels_func * decode_alphas_scaled_or_not[STBIRI_AR-STBIRI_RGBA+1][2][2]= + { + { /* RGBA */ { stbir__decode_uint8_linear_scaled, stbir__decode_uint8_linear }, { stbir__decode_uint16_linear_scaled, stbir__decode_uint16_linear } }, + { /* BGRA */ { stbir__decode_uint8_linear_scaled_BGRA, stbir__decode_uint8_linear_BGRA }, { stbir__decode_uint16_linear_scaled_BGRA, stbir__decode_uint16_linear_BGRA } }, + { /* ARGB */ { stbir__decode_uint8_linear_scaled_ARGB, stbir__decode_uint8_linear_ARGB }, { stbir__decode_uint16_linear_scaled_ARGB, stbir__decode_uint16_linear_ARGB } }, + { /* ABGR */ { stbir__decode_uint8_linear_scaled_ABGR, stbir__decode_uint8_linear_ABGR }, { stbir__decode_uint16_linear_scaled_ABGR, stbir__decode_uint16_linear_ABGR } }, + { /* RA */ { stbir__decode_uint8_linear_scaled, stbir__decode_uint8_linear }, { stbir__decode_uint16_linear_scaled, stbir__decode_uint16_linear } }, + { /* AR */ { stbir__decode_uint8_linear_scaled_AR, stbir__decode_uint8_linear_AR }, { stbir__decode_uint16_linear_scaled_AR, stbir__decode_uint16_linear_AR } } + }; + + static stbir__encode_pixels_func * encode_simple[STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= + { + /* 1ch-4ch */ stbir__encode_uint8_srgb, stbir__encode_uint8_srgb, 0, stbir__encode_float_linear, stbir__encode_half_float_linear, + }; + + static stbir__encode_pixels_func * encode_alphas[STBIRI_AR-STBIRI_RGBA+1][STBIR_TYPE_HALF_FLOAT-STBIR_TYPE_UINT8_SRGB+1]= + { + { /* RGBA */ stbir__encode_uint8_srgb4_linearalpha, stbir__encode_uint8_srgb, 0, stbir__encode_float_linear, stbir__encode_half_float_linear }, + { /* BGRA */ stbir__encode_uint8_srgb4_linearalpha_BGRA, stbir__encode_uint8_srgb_BGRA, 0, stbir__encode_float_linear_BGRA, stbir__encode_half_float_linear_BGRA }, + { /* ARGB */ stbir__encode_uint8_srgb4_linearalpha_ARGB, stbir__encode_uint8_srgb_ARGB, 0, stbir__encode_float_linear_ARGB, stbir__encode_half_float_linear_ARGB }, + { /* ABGR */ stbir__encode_uint8_srgb4_linearalpha_ABGR, stbir__encode_uint8_srgb_ABGR, 0, stbir__encode_float_linear_ABGR, stbir__encode_half_float_linear_ABGR }, + { /* RA */ stbir__encode_uint8_srgb2_linearalpha, stbir__encode_uint8_srgb, 0, stbir__encode_float_linear, stbir__encode_half_float_linear }, + { /* AR */ stbir__encode_uint8_srgb2_linearalpha_AR, stbir__encode_uint8_srgb_AR, 0, stbir__encode_float_linear_AR, stbir__encode_half_float_linear_AR } + }; + + static stbir__encode_pixels_func * encode_simple_scaled_or_not[2][2]= + { + { stbir__encode_uint8_linear_scaled, stbir__encode_uint8_linear }, { stbir__encode_uint16_linear_scaled, stbir__encode_uint16_linear }, + }; + + static stbir__encode_pixels_func * encode_alphas_scaled_or_not[STBIRI_AR-STBIRI_RGBA+1][2][2]= + { + { /* RGBA */ { stbir__encode_uint8_linear_scaled, stbir__encode_uint8_linear }, { stbir__encode_uint16_linear_scaled, stbir__encode_uint16_linear } }, + { /* BGRA */ { stbir__encode_uint8_linear_scaled_BGRA, stbir__encode_uint8_linear_BGRA }, { stbir__encode_uint16_linear_scaled_BGRA, stbir__encode_uint16_linear_BGRA } }, + { /* ARGB */ { stbir__encode_uint8_linear_scaled_ARGB, stbir__encode_uint8_linear_ARGB }, { stbir__encode_uint16_linear_scaled_ARGB, stbir__encode_uint16_linear_ARGB } }, + { /* ABGR */ { stbir__encode_uint8_linear_scaled_ABGR, stbir__encode_uint8_linear_ABGR }, { stbir__encode_uint16_linear_scaled_ABGR, stbir__encode_uint16_linear_ABGR } }, + { /* RA */ { stbir__encode_uint8_linear_scaled, stbir__encode_uint8_linear }, { stbir__encode_uint16_linear_scaled, stbir__encode_uint16_linear } }, + { /* AR */ { stbir__encode_uint8_linear_scaled_AR, stbir__encode_uint8_linear_AR }, { stbir__encode_uint16_linear_scaled_AR, stbir__encode_uint16_linear_AR } } + }; + + stbir__decode_pixels_func * decode_pixels = 0; + stbir__encode_pixels_func * encode_pixels = 0; + stbir_datatype input_type, output_type; + + input_type = resize->input_data_type; + output_type = resize->output_data_type; + info->input_data = resize->input_pixels; + info->input_stride_bytes = resize->input_stride_in_bytes; + info->output_stride_bytes = resize->output_stride_in_bytes; + + // if we're completely point sampling, then we can turn off SRGB + if ( ( info->horizontal.filter_enum == STBIR_FILTER_POINT_SAMPLE ) && ( info->vertical.filter_enum == STBIR_FILTER_POINT_SAMPLE ) ) + { + if ( ( ( input_type == STBIR_TYPE_UINT8_SRGB ) || ( input_type == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) && + ( ( output_type == STBIR_TYPE_UINT8_SRGB ) || ( output_type == STBIR_TYPE_UINT8_SRGB_ALPHA ) ) ) + { + input_type = STBIR_TYPE_UINT8; + output_type = STBIR_TYPE_UINT8; + } + } + + // recalc the output and input strides + if ( info->input_stride_bytes == 0 ) + info->input_stride_bytes = info->channels * info->horizontal.scale_info.input_full_size * stbir__type_size[input_type]; + + if ( info->output_stride_bytes == 0 ) + info->output_stride_bytes = info->channels * info->horizontal.scale_info.output_sub_size * stbir__type_size[output_type]; + + // calc offset + info->output_data = ( (char*) resize->output_pixels ) + ( (size_t) info->offset_y * (size_t) resize->output_stride_in_bytes ) + ( info->offset_x * info->channels * stbir__type_size[output_type] ); + + info->in_pixels_cb = resize->input_cb; + info->user_data = resize->user_data; + info->out_pixels_cb = resize->output_cb; + + // setup the input format converters + if ( ( input_type == STBIR_TYPE_UINT8 ) || ( input_type == STBIR_TYPE_UINT16 ) ) + { + int non_scaled = 0; + + // check if we can run unscaled - 0-255.0/0-65535.0 instead of 0-1.0 (which is a tiny bit faster when doing linear 8->8 or 16->16) + if ( ( !info->alpha_weight ) && ( !info->alpha_unweight ) ) // don't short circuit when alpha weighting (get everything to 0-1.0 as usual) + if ( ( ( input_type == STBIR_TYPE_UINT8 ) && ( output_type == STBIR_TYPE_UINT8 ) ) || ( ( input_type == STBIR_TYPE_UINT16 ) && ( output_type == STBIR_TYPE_UINT16 ) ) ) + non_scaled = 1; + + if ( info->input_pixel_layout_internal <= STBIRI_4CHANNEL ) + decode_pixels = decode_simple_scaled_or_not[ input_type == STBIR_TYPE_UINT16 ][ non_scaled ]; + else + decode_pixels = decode_alphas_scaled_or_not[ ( info->input_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ input_type == STBIR_TYPE_UINT16 ][ non_scaled ]; + } + else + { + if ( info->input_pixel_layout_internal <= STBIRI_4CHANNEL ) + decode_pixels = decode_simple[ input_type - STBIR_TYPE_UINT8_SRGB ]; + else + decode_pixels = decode_alphas[ ( info->input_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ input_type - STBIR_TYPE_UINT8_SRGB ]; + } + + // setup the output format converters + if ( ( output_type == STBIR_TYPE_UINT8 ) || ( output_type == STBIR_TYPE_UINT16 ) ) + { + int non_scaled = 0; + + // check if we can run unscaled - 0-255.0/0-65535.0 instead of 0-1.0 (which is a tiny bit faster when doing linear 8->8 or 16->16) + if ( ( !info->alpha_weight ) && ( !info->alpha_unweight ) ) // don't short circuit when alpha weighting (get everything to 0-1.0 as usual) + if ( ( ( input_type == STBIR_TYPE_UINT8 ) && ( output_type == STBIR_TYPE_UINT8 ) ) || ( ( input_type == STBIR_TYPE_UINT16 ) && ( output_type == STBIR_TYPE_UINT16 ) ) ) + non_scaled = 1; + + if ( info->output_pixel_layout_internal <= STBIRI_4CHANNEL ) + encode_pixels = encode_simple_scaled_or_not[ output_type == STBIR_TYPE_UINT16 ][ non_scaled ]; + else + encode_pixels = encode_alphas_scaled_or_not[ ( info->output_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ output_type == STBIR_TYPE_UINT16 ][ non_scaled ]; + } + else + { + if ( info->output_pixel_layout_internal <= STBIRI_4CHANNEL ) + encode_pixels = encode_simple[ output_type - STBIR_TYPE_UINT8_SRGB ]; + else + encode_pixels = encode_alphas[ ( info->output_pixel_layout_internal - STBIRI_RGBA ) % ( STBIRI_AR-STBIRI_RGBA+1 ) ][ output_type - STBIR_TYPE_UINT8_SRGB ]; + } + + info->input_type = input_type; + info->output_type = output_type; + info->decode_pixels = decode_pixels; + info->encode_pixels = encode_pixels; +} + +static void stbir__clip( int * outx, int * outsubw, int outw, double * u0, double * u1 ) +{ + double per, adj; + int over; + + // do left/top edge + if ( *outx < 0 ) + { + per = ( (double)*outx ) / ( (double)*outsubw ); // is negative + adj = per * ( *u1 - *u0 ); + *u0 -= adj; // increases u0 + *outx = 0; + } + + // do right/bot edge + over = outw - ( *outx + *outsubw ); + if ( over < 0 ) + { + per = ( (double)over ) / ( (double)*outsubw ); // is negative + adj = per * ( *u1 - *u0 ); + *u1 += adj; // decrease u1 + *outsubw = outw - *outx; + } +} + +// converts a double to a rational that has less than one float bit of error (returns 0 if unable to do so) +static int stbir__double_to_rational(double f, stbir_uint32 limit, stbir_uint32 *numer, stbir_uint32 *denom, int limit_denom ) // limit_denom (1) or limit numer (0) +{ + double err; + stbir_uint64 top, bot; + stbir_uint64 numer_last = 0; + stbir_uint64 denom_last = 1; + stbir_uint64 numer_estimate = 1; + stbir_uint64 denom_estimate = 0; + + // scale to past float error range + top = (stbir_uint64)( f * (double)(1 << 25) ); + bot = 1 << 25; + + // keep refining, but usually stops in a few loops - usually 5 for bad cases + for(;;) + { + stbir_uint64 est, temp; + + // hit limit, break out and do best full range estimate + if ( ( ( limit_denom ) ? denom_estimate : numer_estimate ) >= limit ) + break; + + // is the current error less than 1 bit of a float? if so, we're done + if ( denom_estimate ) + { + err = ( (double)numer_estimate / (double)denom_estimate ) - f; + if ( err < 0.0 ) err = -err; + if ( err < ( 1.0 / (double)(1<<24) ) ) + { + // yup, found it + *numer = (stbir_uint32) numer_estimate; + *denom = (stbir_uint32) denom_estimate; + return 1; + } + } + + // no more refinement bits left? break out and do full range estimate + if ( bot == 0 ) + break; + + // gcd the estimate bits + est = top / bot; + temp = top % bot; + top = bot; + bot = temp; + + // move remainders + temp = est * denom_estimate + denom_last; + denom_last = denom_estimate; + denom_estimate = temp; + + // move remainders + temp = est * numer_estimate + numer_last; + numer_last = numer_estimate; + numer_estimate = temp; + } + + // we didn't fine anything good enough for float, use a full range estimate + if ( limit_denom ) + { + numer_estimate= (stbir_uint64)( f * (double)limit + 0.5 ); + denom_estimate = limit; + } + else + { + numer_estimate = limit; + denom_estimate = (stbir_uint64)( ( (double)limit / f ) + 0.5 ); + } + + *numer = (stbir_uint32) numer_estimate; + *denom = (stbir_uint32) denom_estimate; + + err = ( denom_estimate ) ? ( ( (double)(stbir_uint32)numer_estimate / (double)(stbir_uint32)denom_estimate ) - f ) : 1.0; + if ( err < 0.0 ) err = -err; + return ( err < ( 1.0 / (double)(1<<24) ) ) ? 1 : 0; +} + +static int stbir__calculate_region_transform( stbir__scale_info * scale_info, int output_full_range, int * output_offset, int output_sub_range, int input_full_range, double input_s0, double input_s1 ) +{ + double output_range, input_range, output_s, input_s, ratio, scale; + + input_s = input_s1 - input_s0; + + // null area + if ( ( output_full_range == 0 ) || ( input_full_range == 0 ) || + ( output_sub_range == 0 ) || ( input_s <= stbir__small_float ) ) + return 0; + + // are either of the ranges completely out of bounds? + if ( ( *output_offset >= output_full_range ) || ( ( *output_offset + output_sub_range ) <= 0 ) || ( input_s0 >= (1.0f-stbir__small_float) ) || ( input_s1 <= stbir__small_float ) ) + return 0; + + output_range = (double)output_full_range; + input_range = (double)input_full_range; + + output_s = ( (double)output_sub_range) / output_range; + + // figure out the scaling to use + ratio = output_s / input_s; + + // save scale before clipping + scale = ( output_range / input_range ) * ratio; + scale_info->scale = (float)scale; + scale_info->inv_scale = (float)( 1.0 / scale ); + + // clip output area to left/right output edges (and adjust input area) + stbir__clip( output_offset, &output_sub_range, output_full_range, &input_s0, &input_s1 ); + + // recalc input area + input_s = input_s1 - input_s0; + + // after clipping do we have zero input area? + if ( input_s <= stbir__small_float ) + return 0; + + // calculate and store the starting source offsets in output pixel space + scale_info->pixel_shift = (float) ( input_s0 * ratio * output_range ); + + scale_info->scale_is_rational = stbir__double_to_rational( scale, ( scale <= 1.0 ) ? output_full_range : input_full_range, &scale_info->scale_numerator, &scale_info->scale_denominator, ( scale >= 1.0 ) ); + + scale_info->input_full_size = input_full_range; + scale_info->output_sub_size = output_sub_range; + + return 1; +} + + +static void stbir__init_and_set_layout( STBIR_RESIZE * resize, stbir_pixel_layout pixel_layout, stbir_datatype data_type ) +{ + resize->input_cb = 0; + resize->output_cb = 0; + resize->user_data = resize; + resize->samplers = 0; + resize->called_alloc = 0; + resize->horizontal_filter = STBIR_FILTER_DEFAULT; + resize->horizontal_filter_kernel = 0; resize->horizontal_filter_support = 0; + resize->vertical_filter = STBIR_FILTER_DEFAULT; + resize->vertical_filter_kernel = 0; resize->vertical_filter_support = 0; + resize->horizontal_edge = STBIR_EDGE_CLAMP; + resize->vertical_edge = STBIR_EDGE_CLAMP; + resize->input_s0 = 0; resize->input_t0 = 0; resize->input_s1 = 1; resize->input_t1 = 1; + resize->output_subx = 0; resize->output_suby = 0; resize->output_subw = resize->output_w; resize->output_subh = resize->output_h; + resize->input_data_type = data_type; + resize->output_data_type = data_type; + resize->input_pixel_layout_public = pixel_layout; + resize->output_pixel_layout_public = pixel_layout; + resize->needs_rebuild = 1; +} + +STBIRDEF void stbir_resize_init( STBIR_RESIZE * resize, + const void *input_pixels, int input_w, int input_h, int input_stride_in_bytes, // stride can be zero + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, // stride can be zero + stbir_pixel_layout pixel_layout, stbir_datatype data_type ) +{ + resize->input_pixels = input_pixels; + resize->input_w = input_w; + resize->input_h = input_h; + resize->input_stride_in_bytes = input_stride_in_bytes; + resize->output_pixels = output_pixels; + resize->output_w = output_w; + resize->output_h = output_h; + resize->output_stride_in_bytes = output_stride_in_bytes; + resize->fast_alpha = 0; + + stbir__init_and_set_layout( resize, pixel_layout, data_type ); +} + +// You can update parameters any time after resize_init +STBIRDEF void stbir_set_datatypes( STBIR_RESIZE * resize, stbir_datatype input_type, stbir_datatype output_type ) // by default, datatype from resize_init +{ + resize->input_data_type = input_type; + resize->output_data_type = output_type; + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + stbir__update_info_from_resize( resize->samplers, resize ); +} + +STBIRDEF void stbir_set_pixel_callbacks( STBIR_RESIZE * resize, stbir_input_callback * input_cb, stbir_output_callback * output_cb ) // no callbacks by default +{ + resize->input_cb = input_cb; + resize->output_cb = output_cb; + + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + { + resize->samplers->in_pixels_cb = input_cb; + resize->samplers->out_pixels_cb = output_cb; + } +} + +STBIRDEF void stbir_set_user_data( STBIR_RESIZE * resize, void * user_data ) // pass back STBIR_RESIZE* by default +{ + resize->user_data = user_data; + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + resize->samplers->user_data = user_data; +} + +STBIRDEF void stbir_set_buffer_ptrs( STBIR_RESIZE * resize, const void * input_pixels, int input_stride_in_bytes, void * output_pixels, int output_stride_in_bytes ) +{ + resize->input_pixels = input_pixels; + resize->input_stride_in_bytes = input_stride_in_bytes; + resize->output_pixels = output_pixels; + resize->output_stride_in_bytes = output_stride_in_bytes; + if ( ( resize->samplers ) && ( !resize->needs_rebuild ) ) + stbir__update_info_from_resize( resize->samplers, resize ); +} + + +STBIRDEF int stbir_set_edgemodes( STBIR_RESIZE * resize, stbir_edge horizontal_edge, stbir_edge vertical_edge ) // CLAMP by default +{ + resize->horizontal_edge = horizontal_edge; + resize->vertical_edge = vertical_edge; + resize->needs_rebuild = 1; + return 1; +} + +STBIRDEF int stbir_set_filters( STBIR_RESIZE * resize, stbir_filter horizontal_filter, stbir_filter vertical_filter ) // STBIR_DEFAULT_FILTER_UPSAMPLE/DOWNSAMPLE by default +{ + resize->horizontal_filter = horizontal_filter; + resize->vertical_filter = vertical_filter; + resize->needs_rebuild = 1; + return 1; +} + +STBIRDEF int stbir_set_filter_callbacks( STBIR_RESIZE * resize, stbir__kernel_callback * horizontal_filter, stbir__support_callback * horizontal_support, stbir__kernel_callback * vertical_filter, stbir__support_callback * vertical_support ) +{ + resize->horizontal_filter_kernel = horizontal_filter; resize->horizontal_filter_support = horizontal_support; + resize->vertical_filter_kernel = vertical_filter; resize->vertical_filter_support = vertical_support; + resize->needs_rebuild = 1; + return 1; +} + +STBIRDEF int stbir_set_pixel_layouts( STBIR_RESIZE * resize, stbir_pixel_layout input_pixel_layout, stbir_pixel_layout output_pixel_layout ) // sets new pixel layouts +{ + resize->input_pixel_layout_public = input_pixel_layout; + resize->output_pixel_layout_public = output_pixel_layout; + resize->needs_rebuild = 1; + return 1; +} + + +STBIRDEF int stbir_set_non_pm_alpha_speed_over_quality( STBIR_RESIZE * resize, int non_pma_alpha_speed_over_quality ) // sets alpha speed +{ + resize->fast_alpha = non_pma_alpha_speed_over_quality; + resize->needs_rebuild = 1; + return 1; +} + +STBIRDEF int stbir_set_input_subrect( STBIR_RESIZE * resize, double s0, double t0, double s1, double t1 ) // sets input region (full region by default) +{ + resize->input_s0 = s0; + resize->input_t0 = t0; + resize->input_s1 = s1; + resize->input_t1 = t1; + resize->needs_rebuild = 1; + + // are we inbounds? + if ( ( s1 < stbir__small_float ) || ( (s1-s0) < stbir__small_float ) || + ( t1 < stbir__small_float ) || ( (t1-t0) < stbir__small_float ) || + ( s0 > (1.0f-stbir__small_float) ) || + ( t0 > (1.0f-stbir__small_float) ) ) + return 0; + + return 1; +} + +STBIRDEF int stbir_set_output_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ) // sets input region (full region by default) +{ + resize->output_subx = subx; + resize->output_suby = suby; + resize->output_subw = subw; + resize->output_subh = subh; + resize->needs_rebuild = 1; + + // are we inbounds? + if ( ( subx >= resize->output_w ) || ( ( subx + subw ) <= 0 ) || ( suby >= resize->output_h ) || ( ( suby + subh ) <= 0 ) || ( subw == 0 ) || ( subh == 0 ) ) + return 0; + + return 1; +} + +STBIRDEF int stbir_set_pixel_subrect( STBIR_RESIZE * resize, int subx, int suby, int subw, int subh ) // sets both regions (full regions by default) +{ + double s0, t0, s1, t1; + + s0 = ( (double)subx ) / ( (double)resize->output_w ); + t0 = ( (double)suby ) / ( (double)resize->output_h ); + s1 = ( (double)(subx+subw) ) / ( (double)resize->output_w ); + t1 = ( (double)(suby+subh) ) / ( (double)resize->output_h ); + + resize->input_s0 = s0; + resize->input_t0 = t0; + resize->input_s1 = s1; + resize->input_t1 = t1; + resize->output_subx = subx; + resize->output_suby = suby; + resize->output_subw = subw; + resize->output_subh = subh; + resize->needs_rebuild = 1; + + // are we inbounds? + if ( ( subx >= resize->output_w ) || ( ( subx + subw ) <= 0 ) || ( suby >= resize->output_h ) || ( ( suby + subh ) <= 0 ) || ( subw == 0 ) || ( subh == 0 ) ) + return 0; + + return 1; +} + +static int stbir__perform_build( STBIR_RESIZE * resize, int splits ) +{ + stbir__contributors conservative = { 0, 0 }; + stbir__sampler horizontal, vertical; + int new_output_subx, new_output_suby; + stbir__info * out_info; + #ifdef STBIR_PROFILE + stbir__info profile_infod; // used to contain building profile info before everything is allocated + stbir__info * profile_info = &profile_infod; + #endif + + // have we already built the samplers? + if ( resize->samplers ) + return 0; + + #define STBIR_RETURN_ERROR_AND_ASSERT( exp ) STBIR_ASSERT( !(exp) ); if (exp) return 0; + STBIR_RETURN_ERROR_AND_ASSERT( (unsigned)resize->horizontal_filter >= STBIR_FILTER_OTHER) + STBIR_RETURN_ERROR_AND_ASSERT( (unsigned)resize->vertical_filter >= STBIR_FILTER_OTHER) + #undef STBIR_RETURN_ERROR_AND_ASSERT + + if ( splits <= 0 ) + return 0; + + STBIR_PROFILE_BUILD_FIRST_START( build ); + + new_output_subx = resize->output_subx; + new_output_suby = resize->output_suby; + + // do horizontal clip and scale calcs + if ( !stbir__calculate_region_transform( &horizontal.scale_info, resize->output_w, &new_output_subx, resize->output_subw, resize->input_w, resize->input_s0, resize->input_s1 ) ) + return 0; + + // do vertical clip and scale calcs + if ( !stbir__calculate_region_transform( &vertical.scale_info, resize->output_h, &new_output_suby, resize->output_subh, resize->input_h, resize->input_t0, resize->input_t1 ) ) + return 0; + + // if nothing to do, just return + if ( ( horizontal.scale_info.output_sub_size == 0 ) || ( vertical.scale_info.output_sub_size == 0 ) ) + return 0; + + stbir__set_sampler(&horizontal, resize->horizontal_filter, resize->horizontal_filter_kernel, resize->horizontal_filter_support, resize->horizontal_edge, &horizontal.scale_info, 1, resize->user_data ); + stbir__get_conservative_extents( &horizontal, &conservative, resize->user_data ); + stbir__set_sampler(&vertical, resize->vertical_filter, resize->horizontal_filter_kernel, resize->vertical_filter_support, resize->vertical_edge, &vertical.scale_info, 0, resize->user_data ); + + if ( ( vertical.scale_info.output_sub_size / splits ) < STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS ) // each split should be a minimum of 4 scanlines (handwavey choice) + { + splits = vertical.scale_info.output_sub_size / STBIR_FORCE_MINIMUM_SCANLINES_FOR_SPLITS; + if ( splits == 0 ) splits = 1; + } + + STBIR_PROFILE_BUILD_START( alloc ); + out_info = stbir__alloc_internal_mem_and_build_samplers( &horizontal, &vertical, &conservative, resize->input_pixel_layout_public, resize->output_pixel_layout_public, splits, new_output_subx, new_output_suby, resize->fast_alpha, resize->user_data STBIR_ONLY_PROFILE_BUILD_SET_INFO ); + STBIR_PROFILE_BUILD_END( alloc ); + STBIR_PROFILE_BUILD_END( build ); + + if ( out_info ) + { + resize->splits = splits; + resize->samplers = out_info; + resize->needs_rebuild = 0; + #ifdef STBIR_PROFILE + STBIR_MEMCPY( &out_info->profile, &profile_infod.profile, sizeof( out_info->profile ) ); + #endif + + // update anything that can be changed without recalcing samplers + stbir__update_info_from_resize( out_info, resize ); + + return splits; + } + + return 0; +} + +void stbir_free_samplers( STBIR_RESIZE * resize ) +{ + if ( resize->samplers ) + { + stbir__free_internal_mem( resize->samplers ); + resize->samplers = 0; + resize->called_alloc = 0; + } +} + +STBIRDEF int stbir_build_samplers_with_splits( STBIR_RESIZE * resize, int splits ) +{ + if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) ) + { + if ( resize->samplers ) + stbir_free_samplers( resize ); + + resize->called_alloc = 1; + return stbir__perform_build( resize, splits ); + } + + STBIR_PROFILE_BUILD_CLEAR( resize->samplers ); + + return 1; +} + +STBIRDEF int stbir_build_samplers( STBIR_RESIZE * resize ) +{ + return stbir_build_samplers_with_splits( resize, 1 ); +} + +STBIRDEF int stbir_resize_extended( STBIR_RESIZE * resize ) +{ + int result; + + if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) ) + { + int alloc_state = resize->called_alloc; // remember allocated state + + if ( resize->samplers ) + { + stbir__free_internal_mem( resize->samplers ); + resize->samplers = 0; + } + + if ( !stbir_build_samplers( resize ) ) + return 0; + + resize->called_alloc = alloc_state; + + // if build_samplers succeeded (above), but there are no samplers set, then + // the area to stretch into was zero pixels, so don't do anything and return + // success + if ( resize->samplers == 0 ) + return 1; + } + else + { + // didn't build anything - clear it + STBIR_PROFILE_BUILD_CLEAR( resize->samplers ); + } + + // do resize + result = stbir__perform_resize( resize->samplers, 0, resize->splits ); + + // if we alloced, then free + if ( !resize->called_alloc ) + { + stbir_free_samplers( resize ); + resize->samplers = 0; + } + + return result; +} + +STBIRDEF int stbir_resize_extended_split( STBIR_RESIZE * resize, int split_start, int split_count ) +{ + STBIR_ASSERT( resize->samplers ); + + // if we're just doing the whole thing, call full + if ( ( split_start == -1 ) || ( ( split_start == 0 ) && ( split_count == resize->splits ) ) ) + return stbir_resize_extended( resize ); + + // you **must** build samplers first when using split resize + if ( ( resize->samplers == 0 ) || ( resize->needs_rebuild ) ) + return 0; + + if ( ( split_start >= resize->splits ) || ( split_start < 0 ) || ( ( split_start + split_count ) > resize->splits ) || ( split_count <= 0 ) ) + return 0; + + // do resize + return stbir__perform_resize( resize->samplers, split_start, split_count ); +} + +static int stbir__check_output_stuff( void ** ret_ptr, int * ret_pitch, void * output_pixels, int type_size, int output_w, int output_h, int output_stride_in_bytes, stbir_internal_pixel_layout pixel_layout ) +{ + size_t size; + int pitch; + void * ptr; + + pitch = output_w * type_size * stbir__pixel_channels[ pixel_layout ]; + if ( pitch == 0 ) + return 0; + + if ( output_stride_in_bytes == 0 ) + output_stride_in_bytes = pitch; + + if ( output_stride_in_bytes < pitch ) + return 0; + + size = (size_t)output_stride_in_bytes * (size_t)output_h; + if ( size == 0 ) + return 0; + + *ret_ptr = 0; + *ret_pitch = output_stride_in_bytes; + + if ( output_pixels == 0 ) + { + ptr = STBIR_MALLOC( size, 0 ); + if ( ptr == 0 ) + return 0; + + *ret_ptr = ptr; + *ret_pitch = pitch; + } + + return 1; +} + + +STBIRDEF unsigned char * stbir_resize_uint8_linear( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout ) +{ + STBIR_RESIZE resize; + unsigned char * optr; + int opitch; + + if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) + return 0; + + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, opitch, + pixel_layout, STBIR_TYPE_UINT8 ); + + if ( !stbir_resize_extended( &resize ) ) + { + if ( optr ) + STBIR_FREE( optr, 0 ); + return 0; + } + + return (optr) ? optr : output_pixels; +} + +STBIRDEF unsigned char * stbir_resize_uint8_srgb( const unsigned char *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout ) +{ + STBIR_RESIZE resize; + unsigned char * optr; + int opitch; + + if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( unsigned char ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) + return 0; + + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, opitch, + pixel_layout, STBIR_TYPE_UINT8_SRGB ); + + if ( !stbir_resize_extended( &resize ) ) + { + if ( optr ) + STBIR_FREE( optr, 0 ); + return 0; + } + + return (optr) ? optr : output_pixels; +} + + +STBIRDEF float * stbir_resize_float_linear( const float *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout ) +{ + STBIR_RESIZE resize; + float * optr; + int opitch; + + if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, sizeof( float ), output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) + return 0; + + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, opitch, + pixel_layout, STBIR_TYPE_FLOAT ); + + if ( !stbir_resize_extended( &resize ) ) + { + if ( optr ) + STBIR_FREE( optr, 0 ); + return 0; + } + + return (optr) ? optr : output_pixels; +} + + +STBIRDEF void * stbir_resize( const void *input_pixels , int input_w , int input_h, int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_pixel_layout pixel_layout, stbir_datatype data_type, + stbir_edge edge, stbir_filter filter ) +{ + STBIR_RESIZE resize; + float * optr; + int opitch; + + if ( !stbir__check_output_stuff( (void**)&optr, &opitch, output_pixels, stbir__type_size[data_type], output_w, output_h, output_stride_in_bytes, stbir__pixel_layout_convert_public_to_internal[ pixel_layout ] ) ) + return 0; + + stbir_resize_init( &resize, + input_pixels, input_w, input_h, input_stride_in_bytes, + (optr) ? optr : output_pixels, output_w, output_h, output_stride_in_bytes, + pixel_layout, data_type ); + + resize.horizontal_edge = edge; + resize.vertical_edge = edge; + resize.horizontal_filter = filter; + resize.vertical_filter = filter; + + if ( !stbir_resize_extended( &resize ) ) + { + if ( optr ) + STBIR_FREE( optr, 0 ); + return 0; + } + + return (optr) ? optr : output_pixels; +} + +#ifdef STBIR_PROFILE + +STBIRDEF void stbir_resize_build_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize ) +{ + static char const * bdescriptions[6] = { "Building", "Allocating", "Horizontal sampler", "Vertical sampler", "Coefficient cleanup", "Coefficient piovot" } ; + stbir__info* samp = resize->samplers; + int i; + + typedef int testa[ (STBIR__ARRAY_SIZE( bdescriptions ) == (STBIR__ARRAY_SIZE( samp->profile.array )-1) )?1:-1]; + typedef int testb[ (sizeof( samp->profile.array ) == (sizeof(samp->profile.named)) )?1:-1]; + typedef int testc[ (sizeof( info->clocks ) >= (sizeof(samp->profile.named)) )?1:-1]; + + for( i = 0 ; i < STBIR__ARRAY_SIZE( bdescriptions ) ; i++) + info->clocks[i] = samp->profile.array[i+1]; + + info->total_clocks = samp->profile.named.total; + info->descriptions = bdescriptions; + info->count = STBIR__ARRAY_SIZE( bdescriptions ); +} + +STBIRDEF void stbir_resize_split_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize, int split_start, int split_count ) +{ + static char const * descriptions[7] = { "Looping", "Vertical sampling", "Horizontal sampling", "Scanline input", "Scanline output", "Alpha weighting", "Alpha unweighting" }; + stbir__per_split_info * split_info; + int s, i; + + typedef int testa[ (STBIR__ARRAY_SIZE( descriptions ) == (STBIR__ARRAY_SIZE( split_info->profile.array )-1) )?1:-1]; + typedef int testb[ (sizeof( split_info->profile.array ) == (sizeof(split_info->profile.named)) )?1:-1]; + typedef int testc[ (sizeof( info->clocks ) >= (sizeof(split_info->profile.named)) )?1:-1]; + + if ( split_start == -1 ) + { + split_start = 0; + split_count = resize->samplers->splits; + } + + if ( ( split_start >= resize->splits ) || ( split_start < 0 ) || ( ( split_start + split_count ) > resize->splits ) || ( split_count <= 0 ) ) + { + info->total_clocks = 0; + info->descriptions = 0; + info->count = 0; + return; + } + + split_info = resize->samplers->split_info + split_start; + + // sum up the profile from all the splits + for( i = 0 ; i < STBIR__ARRAY_SIZE( descriptions ) ; i++ ) + { + stbir_uint64 sum = 0; + for( s = 0 ; s < split_count ; s++ ) + sum += split_info[s].profile.array[i+1]; + info->clocks[i] = sum; + } + + info->total_clocks = split_info->profile.named.total; + info->descriptions = descriptions; + info->count = STBIR__ARRAY_SIZE( descriptions ); +} + +STBIRDEF void stbir_resize_extended_profile_info( STBIR_PROFILE_INFO * info, STBIR_RESIZE const * resize ) +{ + stbir_resize_split_profile_info( info, resize, -1, 0 ); +} + +#endif // STBIR_PROFILE + +#undef STBIR_BGR +#undef STBIR_1CHANNEL +#undef STBIR_2CHANNEL +#undef STBIR_RGB +#undef STBIR_RGBA +#undef STBIR_4CHANNEL +#undef STBIR_BGRA +#undef STBIR_ARGB +#undef STBIR_ABGR +#undef STBIR_RA +#undef STBIR_AR +#undef STBIR_RGBA_PM +#undef STBIR_BGRA_PM +#undef STBIR_ARGB_PM +#undef STBIR_ABGR_PM +#undef STBIR_RA_PM +#undef STBIR_AR_PM + +#endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +#else // STB_IMAGE_RESIZE_HORIZONTALS&STB_IMAGE_RESIZE_DO_VERTICALS + +// we reinclude the header file to define all the horizontal functions +// specializing each function for the number of coeffs is 20-40% faster *OVERALL* + +// by including the header file again this way, we can still debug the functions + +#define STBIR_strs_join2( start, mid, end ) start##mid##end +#define STBIR_strs_join1( start, mid, end ) STBIR_strs_join2( start, mid, end ) + +#define STBIR_strs_join24( start, mid1, mid2, end ) start##mid1##mid2##end +#define STBIR_strs_join14( start, mid1, mid2, end ) STBIR_strs_join24( start, mid1, mid2, end ) + +#ifdef STB_IMAGE_RESIZE_DO_CODERS + +#ifdef stbir__decode_suffix +#define STBIR__CODER_NAME( name ) STBIR_strs_join1( name, _, stbir__decode_suffix ) +#else +#define STBIR__CODER_NAME( name ) name +#endif + +#ifdef stbir__decode_swizzle +#define stbir__decode_simdf8_flip(reg) STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( stbir__simdf8_0123to,stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3),stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3)(reg, reg) +#define stbir__decode_simdf4_flip(reg) STBIR_strs_join1( STBIR_strs_join1( stbir__simdf_0123to,stbir__decode_order0,stbir__decode_order1),stbir__decode_order2,stbir__decode_order3)(reg, reg) +#define stbir__encode_simdf8_unflip(reg) STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( STBIR_strs_join1( stbir__simdf8_0123to,stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3),stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3)(reg, reg) +#define stbir__encode_simdf4_unflip(reg) STBIR_strs_join1( STBIR_strs_join1( stbir__simdf_0123to,stbir__encode_order0,stbir__encode_order1),stbir__encode_order2,stbir__encode_order3)(reg, reg) +#else +#define stbir__decode_order0 0 +#define stbir__decode_order1 1 +#define stbir__decode_order2 2 +#define stbir__decode_order3 3 +#define stbir__encode_order0 0 +#define stbir__encode_order1 1 +#define stbir__encode_order2 2 +#define stbir__encode_order3 3 +#define stbir__decode_simdf8_flip(reg) +#define stbir__decode_simdf4_flip(reg) +#define stbir__encode_simdf8_unflip(reg) +#define stbir__encode_simdf4_unflip(reg) +#endif + +#ifdef STBIR_SIMD8 +#define stbir__encode_simdfX_unflip stbir__encode_simdf8_unflip +#else +#define stbir__encode_simdfX_unflip stbir__encode_simdf4_unflip +#endif + +static void STBIR__CODER_NAME( stbir__decode_uint8_linear_scaled )( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const*)inputp; + + #ifdef STBIR_SIMD + unsigned char const * end_input_m16 = input + width_times_channels - 16; + if ( width_times_channels >= 16 ) + { + decode_end -= 16; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + #ifdef STBIR_SIMD8 + stbir__simdi i; stbir__simdi8 o0,o1; + stbir__simdf8 of0, of1; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi8_expand_u8_to_u32( o0, o1, i ); + stbir__simdi8_convert_i32_to_float( of0, o0 ); + stbir__simdi8_convert_i32_to_float( of1, o1 ); + stbir__simdf8_mult( of0, of0, STBIR_max_uint8_as_float_inverted8); + stbir__simdf8_mult( of1, of1, STBIR_max_uint8_as_float_inverted8); + stbir__decode_simdf8_flip( of0 ); + stbir__decode_simdf8_flip( of1 ); + stbir__simdf8_store( decode + 0, of0 ); + stbir__simdf8_store( decode + 8, of1 ); + #else + stbir__simdi i, o0, o1, o2, o3; + stbir__simdf of0, of1, of2, of3; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi_expand_u8_to_u32( o0,o1,o2,o3,i); + stbir__simdi_convert_i32_to_float( of0, o0 ); + stbir__simdi_convert_i32_to_float( of1, o1 ); + stbir__simdi_convert_i32_to_float( of2, o2 ); + stbir__simdi_convert_i32_to_float( of3, o3 ); + stbir__simdf_mult( of0, of0, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) ); + stbir__simdf_mult( of1, of1, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) ); + stbir__simdf_mult( of2, of2, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) ); + stbir__simdf_mult( of3, of3, STBIR__CONSTF(STBIR_max_uint8_as_float_inverted) ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__decode_simdf4_flip( of2 ); + stbir__decode_simdf4_flip( of3 ); + stbir__simdf_store( decode + 0, of0 ); + stbir__simdf_store( decode + 4, of1 ); + stbir__simdf_store( decode + 8, of2 ); + stbir__simdf_store( decode + 12, of3 ); + #endif + decode += 16; + input += 16; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 16 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m16; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = ((float)(input[stbir__decode_order0])) * stbir__max_uint8_as_float_inverted; + decode[1-4] = ((float)(input[stbir__decode_order1])) * stbir__max_uint8_as_float_inverted; + decode[2-4] = ((float)(input[stbir__decode_order2])) * stbir__max_uint8_as_float_inverted; + decode[3-4] = ((float)(input[stbir__decode_order3])) * stbir__max_uint8_as_float_inverted; + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = ((float)(input[stbir__decode_order0])) * stbir__max_uint8_as_float_inverted; + #if stbir__coder_min_num >= 2 + decode[1] = ((float)(input[stbir__decode_order1])) * stbir__max_uint8_as_float_inverted; + #endif + #if stbir__coder_min_num >= 3 + decode[2] = ((float)(input[stbir__decode_order2])) * stbir__max_uint8_as_float_inverted; + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME( stbir__encode_uint8_linear_scaled )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char *) outputp; + unsigned char * end_output = ( (unsigned char *) output ) + width_times_channels; + + #ifdef STBIR_SIMD + if ( width_times_channels >= stbir__simdfX_float_count*2 ) + { + float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; + end_output -= stbir__simdfX_float_count*2; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdfX e0, e1; + stbir__simdi i; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_madd_mem( e0, STBIR_simd_point5X, STBIR_max_uint8_as_floatX, encode ); + stbir__simdfX_madd_mem( e1, STBIR_simd_point5X, STBIR_max_uint8_as_floatX, encode+stbir__simdfX_float_count ); + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + #ifdef STBIR_SIMD8 + stbir__simdf8_pack_to_16bytes( i, e0, e1 ); + stbir__simdi_store( output, i ); + #else + stbir__simdf_pack_to_8bytes( i, e0, e1 ); + stbir__simdi_store2( output, i ); + #endif + encode += stbir__simdfX_float_count*2; + output += stbir__simdfX_float_count*2; + if ( output <= end_output ) + continue; + if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + stbir__simdf e0; + stbir__simdi i0; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e0, encode ); + stbir__simdf_madd( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), e0 ); + stbir__encode_simdf4_unflip( e0 ); + stbir__simdf_pack_to_8bytes( i0, e0, e0 ); // only use first 4 + *(int*)(output-4) = stbir__simdi_to_int( i0 ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + stbir__simdf e0; + STBIR_NO_UNROLL(encode); + stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order0 ); output[0] = stbir__simdf_convert_float_to_uint8( e0 ); + #if stbir__coder_min_num >= 2 + stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order1 ); output[1] = stbir__simdf_convert_float_to_uint8( e0 ); + #endif + #if stbir__coder_min_num >= 3 + stbir__simdf_madd1_mem( e0, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint8_as_float), encode+stbir__encode_order2 ); output[2] = stbir__simdf_convert_float_to_uint8( e0 ); + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + float f; + f = encode[stbir__encode_order0] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[0-4] = (unsigned char)f; + f = encode[stbir__encode_order1] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[1-4] = (unsigned char)f; + f = encode[stbir__encode_order2] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[2-4] = (unsigned char)f; + f = encode[stbir__encode_order3] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[3-4] = (unsigned char)f; + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + float f; + STBIR_NO_UNROLL(encode); + f = encode[stbir__encode_order0] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[0] = (unsigned char)f; + #if stbir__coder_min_num >= 2 + f = encode[stbir__encode_order1] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[1] = (unsigned char)f; + #endif + #if stbir__coder_min_num >= 3 + f = encode[stbir__encode_order2] * stbir__max_uint8_as_float + 0.5f; STBIR_CLAMP(f, 0, 255); output[2] = (unsigned char)f; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_uint8_linear)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const*)inputp; + + #ifdef STBIR_SIMD + unsigned char const * end_input_m16 = input + width_times_channels - 16; + if ( width_times_channels >= 16 ) + { + decode_end -= 16; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + #ifdef STBIR_SIMD8 + stbir__simdi i; stbir__simdi8 o0,o1; + stbir__simdf8 of0, of1; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi8_expand_u8_to_u32( o0, o1, i ); + stbir__simdi8_convert_i32_to_float( of0, o0 ); + stbir__simdi8_convert_i32_to_float( of1, o1 ); + stbir__decode_simdf8_flip( of0 ); + stbir__decode_simdf8_flip( of1 ); + stbir__simdf8_store( decode + 0, of0 ); + stbir__simdf8_store( decode + 8, of1 ); + #else + stbir__simdi i, o0, o1, o2, o3; + stbir__simdf of0, of1, of2, of3; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi_expand_u8_to_u32( o0,o1,o2,o3,i); + stbir__simdi_convert_i32_to_float( of0, o0 ); + stbir__simdi_convert_i32_to_float( of1, o1 ); + stbir__simdi_convert_i32_to_float( of2, o2 ); + stbir__simdi_convert_i32_to_float( of3, o3 ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__decode_simdf4_flip( of2 ); + stbir__decode_simdf4_flip( of3 ); + stbir__simdf_store( decode + 0, of0 ); + stbir__simdf_store( decode + 4, of1 ); + stbir__simdf_store( decode + 8, of2 ); + stbir__simdf_store( decode + 12, of3 ); +#endif + decode += 16; + input += 16; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 16 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m16; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = ((float)(input[stbir__decode_order0])); + decode[1-4] = ((float)(input[stbir__decode_order1])); + decode[2-4] = ((float)(input[stbir__decode_order2])); + decode[3-4] = ((float)(input[stbir__decode_order3])); + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = ((float)(input[stbir__decode_order0])); + #if stbir__coder_min_num >= 2 + decode[1] = ((float)(input[stbir__decode_order1])); + #endif + #if stbir__coder_min_num >= 3 + decode[2] = ((float)(input[stbir__decode_order2])); + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME( stbir__encode_uint8_linear )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char *) outputp; + unsigned char * end_output = ( (unsigned char *) output ) + width_times_channels; + + #ifdef STBIR_SIMD + if ( width_times_channels >= stbir__simdfX_float_count*2 ) + { + float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; + end_output -= stbir__simdfX_float_count*2; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdfX e0, e1; + stbir__simdi i; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_add_mem( e0, STBIR_simd_point5X, encode ); + stbir__simdfX_add_mem( e1, STBIR_simd_point5X, encode+stbir__simdfX_float_count ); + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + #ifdef STBIR_SIMD8 + stbir__simdf8_pack_to_16bytes( i, e0, e1 ); + stbir__simdi_store( output, i ); + #else + stbir__simdf_pack_to_8bytes( i, e0, e1 ); + stbir__simdi_store2( output, i ); + #endif + encode += stbir__simdfX_float_count*2; + output += stbir__simdfX_float_count*2; + if ( output <= end_output ) + continue; + if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + stbir__simdf e0; + stbir__simdi i0; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e0, encode ); + stbir__simdf_add( e0, STBIR__CONSTF(STBIR_simd_point5), e0 ); + stbir__encode_simdf4_unflip( e0 ); + stbir__simdf_pack_to_8bytes( i0, e0, e0 ); // only use first 4 + *(int*)(output-4) = stbir__simdi_to_int( i0 ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + while( output <= end_output ) + { + float f; + f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 255); output[0-4] = (unsigned char)f; + f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 255); output[1-4] = (unsigned char)f; + f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 255); output[2-4] = (unsigned char)f; + f = encode[stbir__encode_order3] + 0.5f; STBIR_CLAMP(f, 0, 255); output[3-4] = (unsigned char)f; + output += 4; + encode += 4; + } + output -= 4; + #endif + + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + float f; + STBIR_NO_UNROLL(encode); + f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 255); output[0] = (unsigned char)f; + #if stbir__coder_min_num >= 2 + f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 255); output[1] = (unsigned char)f; + #endif + #if stbir__coder_min_num >= 3 + f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 255); output[2] = (unsigned char)f; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_uint8_srgb)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float const * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const *)inputp; + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + while( decode <= decode_end ) + { + decode[0-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order0 ] ]; + decode[1-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order1 ] ]; + decode[2-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order2 ] ]; + decode[3-4] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order3 ] ]; + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order0 ] ]; + #if stbir__coder_min_num >= 2 + decode[1] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order1 ] ]; + #endif + #if stbir__coder_min_num >= 3 + decode[2] = stbir__srgb_uchar_to_linear_float[ input[ stbir__decode_order2 ] ]; + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +#define stbir__min_max_shift20( i, f ) \ + stbir__simdf_max( f, f, stbir_simdf_casti(STBIR__CONSTI( STBIR_almost_zero )) ); \ + stbir__simdf_min( f, f, stbir_simdf_casti(STBIR__CONSTI( STBIR_almost_one )) ); \ + stbir__simdi_32shr( i, stbir_simdi_castf( f ), 20 ); + +#define stbir__scale_and_convert( i, f ) \ + stbir__simdf_madd( f, STBIR__CONSTF( STBIR_simd_point5 ), STBIR__CONSTF( STBIR_max_uint8_as_float ), f ); \ + stbir__simdf_max( f, f, stbir__simdf_zeroP() ); \ + stbir__simdf_min( f, f, STBIR__CONSTF( STBIR_max_uint8_as_float ) ); \ + stbir__simdf_convert_float_to_i32( i, f ); + +#define stbir__linear_to_srgb_finish( i, f ) \ +{ \ + stbir__simdi temp; \ + stbir__simdi_32shr( temp, stbir_simdi_castf( f ), 12 ) ; \ + stbir__simdi_and( temp, temp, STBIR__CONSTI(STBIR_mastissa_mask) ); \ + stbir__simdi_or( temp, temp, STBIR__CONSTI(STBIR_topscale) ); \ + stbir__simdi_16madd( i, i, temp ); \ + stbir__simdi_32shr( i, i, 16 ); \ +} + +#define stbir__simdi_table_lookup2( v0,v1, table ) \ +{ \ + stbir__simdi_u32 temp0,temp1; \ + temp0.m128i_i128 = v0; \ + temp1.m128i_i128 = v1; \ + temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \ + temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \ + v0 = temp0.m128i_i128; \ + v1 = temp1.m128i_i128; \ +} + +#define stbir__simdi_table_lookup3( v0,v1,v2, table ) \ +{ \ + stbir__simdi_u32 temp0,temp1,temp2; \ + temp0.m128i_i128 = v0; \ + temp1.m128i_i128 = v1; \ + temp2.m128i_i128 = v2; \ + temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \ + temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \ + temp2.m128i_u32[0] = table[temp2.m128i_i32[0]]; temp2.m128i_u32[1] = table[temp2.m128i_i32[1]]; temp2.m128i_u32[2] = table[temp2.m128i_i32[2]]; temp2.m128i_u32[3] = table[temp2.m128i_i32[3]]; \ + v0 = temp0.m128i_i128; \ + v1 = temp1.m128i_i128; \ + v2 = temp2.m128i_i128; \ +} + +#define stbir__simdi_table_lookup4( v0,v1,v2,v3, table ) \ +{ \ + stbir__simdi_u32 temp0,temp1,temp2,temp3; \ + temp0.m128i_i128 = v0; \ + temp1.m128i_i128 = v1; \ + temp2.m128i_i128 = v2; \ + temp3.m128i_i128 = v3; \ + temp0.m128i_u32[0] = table[temp0.m128i_i32[0]]; temp0.m128i_u32[1] = table[temp0.m128i_i32[1]]; temp0.m128i_u32[2] = table[temp0.m128i_i32[2]]; temp0.m128i_u32[3] = table[temp0.m128i_i32[3]]; \ + temp1.m128i_u32[0] = table[temp1.m128i_i32[0]]; temp1.m128i_u32[1] = table[temp1.m128i_i32[1]]; temp1.m128i_u32[2] = table[temp1.m128i_i32[2]]; temp1.m128i_u32[3] = table[temp1.m128i_i32[3]]; \ + temp2.m128i_u32[0] = table[temp2.m128i_i32[0]]; temp2.m128i_u32[1] = table[temp2.m128i_i32[1]]; temp2.m128i_u32[2] = table[temp2.m128i_i32[2]]; temp2.m128i_u32[3] = table[temp2.m128i_i32[3]]; \ + temp3.m128i_u32[0] = table[temp3.m128i_i32[0]]; temp3.m128i_u32[1] = table[temp3.m128i_i32[1]]; temp3.m128i_u32[2] = table[temp3.m128i_i32[2]]; temp3.m128i_u32[3] = table[temp3.m128i_i32[3]]; \ + v0 = temp0.m128i_i128; \ + v1 = temp1.m128i_i128; \ + v2 = temp2.m128i_i128; \ + v3 = temp3.m128i_i128; \ +} + +static void STBIR__CODER_NAME( stbir__encode_uint8_srgb )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp; + unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + + if ( width_times_channels >= 16 ) + { + float const * end_encode_m16 = encode + width_times_channels - 16; + end_output -= 16; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdf f0, f1, f2, f3; + stbir__simdi i0, i1, i2, i3; + STBIR_SIMD_NO_UNROLL(encode); + + stbir__simdf_load4_transposed( f0, f1, f2, f3, encode ); + + stbir__min_max_shift20( i0, f0 ); + stbir__min_max_shift20( i1, f1 ); + stbir__min_max_shift20( i2, f2 ); + stbir__min_max_shift20( i3, f3 ); + + stbir__simdi_table_lookup4( i0, i1, i2, i3, ( fp32_to_srgb8_tab4 - (127-13)*8 ) ); + + stbir__linear_to_srgb_finish( i0, f0 ); + stbir__linear_to_srgb_finish( i1, f1 ); + stbir__linear_to_srgb_finish( i2, f2 ); + stbir__linear_to_srgb_finish( i3, f3 ); + + stbir__interleave_pack_and_store_16_u8( output, STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) ); + + encode += 16; + output += 16; + if ( output <= end_output ) + continue; + if ( output == ( end_output + 16 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m16; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( output <= end_output ) + { + STBIR_SIMD_NO_UNROLL(encode); + + output[0-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order0] ); + output[1-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order1] ); + output[2-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order2] ); + output[3-4] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order3] ); + + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + STBIR_NO_UNROLL(encode); + output[0] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order0] ); + #if stbir__coder_min_num >= 2 + output[1] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order1] ); + #endif + #if stbir__coder_min_num >= 3 + output[2] = stbir__linear_to_srgb_uchar( encode[stbir__encode_order2] ); + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif +} + +#if ( stbir__coder_min_num == 4 ) || ( ( stbir__coder_min_num == 1 ) && ( !defined(stbir__decode_swizzle) ) ) + +static void STBIR__CODER_NAME(stbir__decode_uint8_srgb4_linearalpha)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float const * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const *)inputp; + do { + decode[0] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0] ]; + decode[1] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order1] ]; + decode[2] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order2] ]; + decode[3] = ( (float) input[stbir__decode_order3] ) * stbir__max_uint8_as_float_inverted; + input += 4; + decode += 4; + } while( decode < decode_end ); +} + + +static void STBIR__CODER_NAME( stbir__encode_uint8_srgb4_linearalpha )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp; + unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + + if ( width_times_channels >= 16 ) + { + float const * end_encode_m16 = encode + width_times_channels - 16; + end_output -= 16; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdf f0, f1, f2, f3; + stbir__simdi i0, i1, i2, i3; + + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdf_load4_transposed( f0, f1, f2, f3, encode ); + + stbir__min_max_shift20( i0, f0 ); + stbir__min_max_shift20( i1, f1 ); + stbir__min_max_shift20( i2, f2 ); + stbir__scale_and_convert( i3, f3 ); + + stbir__simdi_table_lookup3( i0, i1, i2, ( fp32_to_srgb8_tab4 - (127-13)*8 ) ); + + stbir__linear_to_srgb_finish( i0, f0 ); + stbir__linear_to_srgb_finish( i1, f1 ); + stbir__linear_to_srgb_finish( i2, f2 ); + + stbir__interleave_pack_and_store_16_u8( output, STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) ); + + output += 16; + encode += 16; + + if ( output <= end_output ) + continue; + if ( output == ( end_output + 16 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m16; + } + return; + } + #endif + + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float f; + STBIR_SIMD_NO_UNROLL(encode); + + output[stbir__decode_order0] = stbir__linear_to_srgb_uchar( encode[0] ); + output[stbir__decode_order1] = stbir__linear_to_srgb_uchar( encode[1] ); + output[stbir__decode_order2] = stbir__linear_to_srgb_uchar( encode[2] ); + + f = encode[3] * stbir__max_uint8_as_float + 0.5f; + STBIR_CLAMP(f, 0, 255); + output[stbir__decode_order3] = (unsigned char) f; + + output += 4; + encode += 4; + } while( output < end_output ); +} + +#endif + +#if ( stbir__coder_min_num == 2 ) || ( ( stbir__coder_min_num == 1 ) && ( !defined(stbir__decode_swizzle) ) ) + +static void STBIR__CODER_NAME(stbir__decode_uint8_srgb2_linearalpha)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float const * decode_end = (float*) decode + width_times_channels; + unsigned char const * input = (unsigned char const *)inputp; + decode += 4; + while( decode <= decode_end ) + { + decode[0-4] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0] ]; + decode[1-4] = ( (float) input[stbir__decode_order1] ) * stbir__max_uint8_as_float_inverted; + decode[2-4] = stbir__srgb_uchar_to_linear_float[ input[stbir__decode_order0+2] ]; + decode[3-4] = ( (float) input[stbir__decode_order1+2] ) * stbir__max_uint8_as_float_inverted; + input += 4; + decode += 4; + } + decode -= 4; + if( decode < decode_end ) + { + decode[0] = stbir__srgb_uchar_to_linear_float[ stbir__decode_order0 ]; + decode[1] = ( (float) input[stbir__decode_order1] ) * stbir__max_uint8_as_float_inverted; + } +} + +static void STBIR__CODER_NAME( stbir__encode_uint8_srgb2_linearalpha )( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned char STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned char*) outputp; + unsigned char * end_output = ( (unsigned char*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + + if ( width_times_channels >= 16 ) + { + float const * end_encode_m16 = encode + width_times_channels - 16; + end_output -= 16; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdf f0, f1, f2, f3; + stbir__simdi i0, i1, i2, i3; + + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdf_load4_transposed( f0, f1, f2, f3, encode ); + + stbir__min_max_shift20( i0, f0 ); + stbir__scale_and_convert( i1, f1 ); + stbir__min_max_shift20( i2, f2 ); + stbir__scale_and_convert( i3, f3 ); + + stbir__simdi_table_lookup2( i0, i2, ( fp32_to_srgb8_tab4 - (127-13)*8 ) ); + + stbir__linear_to_srgb_finish( i0, f0 ); + stbir__linear_to_srgb_finish( i2, f2 ); + + stbir__interleave_pack_and_store_16_u8( output, STBIR_strs_join1(i, ,stbir__encode_order0), STBIR_strs_join1(i, ,stbir__encode_order1), STBIR_strs_join1(i, ,stbir__encode_order2), STBIR_strs_join1(i, ,stbir__encode_order3) ); + + output += 16; + encode += 16; + if ( output <= end_output ) + continue; + if ( output == ( end_output + 16 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m16; + } + return; + } + #endif + + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float f; + STBIR_SIMD_NO_UNROLL(encode); + + output[stbir__decode_order0] = stbir__linear_to_srgb_uchar( encode[0] ); + + f = encode[1] * stbir__max_uint8_as_float + 0.5f; + STBIR_CLAMP(f, 0, 255); + output[stbir__decode_order1] = (unsigned char) f; + + output += 2; + encode += 2; + } while( output < end_output ); +} + +#endif + +static void STBIR__CODER_NAME(stbir__decode_uint16_linear_scaled)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + unsigned short const * input = (unsigned short const *)inputp; + + #ifdef STBIR_SIMD + unsigned short const * end_input_m8 = input + width_times_channels - 8; + if ( width_times_channels >= 8 ) + { + decode_end -= 8; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + #ifdef STBIR_SIMD8 + stbir__simdi i; stbir__simdi8 o; + stbir__simdf8 of; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi8_expand_u16_to_u32( o, i ); + stbir__simdi8_convert_i32_to_float( of, o ); + stbir__simdf8_mult( of, of, STBIR_max_uint16_as_float_inverted8); + stbir__decode_simdf8_flip( of ); + stbir__simdf8_store( decode + 0, of ); + #else + stbir__simdi i, o0, o1; + stbir__simdf of0, of1; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi_expand_u16_to_u32( o0,o1,i ); + stbir__simdi_convert_i32_to_float( of0, o0 ); + stbir__simdi_convert_i32_to_float( of1, o1 ); + stbir__simdf_mult( of0, of0, STBIR__CONSTF(STBIR_max_uint16_as_float_inverted) ); + stbir__simdf_mult( of1, of1, STBIR__CONSTF(STBIR_max_uint16_as_float_inverted)); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__simdf_store( decode + 0, of0 ); + stbir__simdf_store( decode + 4, of1 ); + #endif + decode += 8; + input += 8; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 8 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m8; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = ((float)(input[stbir__decode_order0])) * stbir__max_uint16_as_float_inverted; + decode[1-4] = ((float)(input[stbir__decode_order1])) * stbir__max_uint16_as_float_inverted; + decode[2-4] = ((float)(input[stbir__decode_order2])) * stbir__max_uint16_as_float_inverted; + decode[3-4] = ((float)(input[stbir__decode_order3])) * stbir__max_uint16_as_float_inverted; + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = ((float)(input[stbir__decode_order0])) * stbir__max_uint16_as_float_inverted; + #if stbir__coder_min_num >= 2 + decode[1] = ((float)(input[stbir__decode_order1])) * stbir__max_uint16_as_float_inverted; + #endif + #if stbir__coder_min_num >= 3 + decode[2] = ((float)(input[stbir__decode_order2])) * stbir__max_uint16_as_float_inverted; + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + + +static void STBIR__CODER_NAME(stbir__encode_uint16_linear_scaled)( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned short STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned short*) outputp; + unsigned short * end_output = ( (unsigned short*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + { + if ( width_times_channels >= stbir__simdfX_float_count*2 ) + { + float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; + end_output -= stbir__simdfX_float_count*2; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdfX e0, e1; + stbir__simdiX i; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_madd_mem( e0, STBIR_simd_point5X, STBIR_max_uint16_as_floatX, encode ); + stbir__simdfX_madd_mem( e1, STBIR_simd_point5X, STBIR_max_uint16_as_floatX, encode+stbir__simdfX_float_count ); + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + stbir__simdfX_pack_to_words( i, e0, e1 ); + stbir__simdiX_store( output, i ); + encode += stbir__simdfX_float_count*2; + output += stbir__simdfX_float_count*2; + if ( output <= end_output ) + continue; + if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + stbir__simdf e; + stbir__simdi i; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e, encode ); + stbir__simdf_madd( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), e ); + stbir__encode_simdf4_unflip( e ); + stbir__simdf_pack_to_8words( i, e, e ); // only use first 4 + stbir__simdi_store2( output-4, i ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + stbir__simdf e; + STBIR_NO_UNROLL(encode); + stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order0 ); output[0] = stbir__simdf_convert_float_to_short( e ); + #if stbir__coder_min_num >= 2 + stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order1 ); output[1] = stbir__simdf_convert_float_to_short( e ); + #endif + #if stbir__coder_min_num >= 3 + stbir__simdf_madd1_mem( e, STBIR__CONSTF(STBIR_simd_point5), STBIR__CONSTF(STBIR_max_uint16_as_float), encode+stbir__encode_order2 ); output[2] = stbir__simdf_convert_float_to_short( e ); + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + float f; + STBIR_SIMD_NO_UNROLL(encode); + f = encode[stbir__encode_order0] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0-4] = (unsigned short)f; + f = encode[stbir__encode_order1] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1-4] = (unsigned short)f; + f = encode[stbir__encode_order2] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2-4] = (unsigned short)f; + f = encode[stbir__encode_order3] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[3-4] = (unsigned short)f; + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + float f; + STBIR_NO_UNROLL(encode); + f = encode[stbir__encode_order0] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0] = (unsigned short)f; + #if stbir__coder_min_num >= 2 + f = encode[stbir__encode_order1] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1] = (unsigned short)f; + #endif + #if stbir__coder_min_num >= 3 + f = encode[stbir__encode_order2] * stbir__max_uint16_as_float + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2] = (unsigned short)f; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_uint16_linear)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + unsigned short const * input = (unsigned short const *)inputp; + + #ifdef STBIR_SIMD + unsigned short const * end_input_m8 = input + width_times_channels - 8; + if ( width_times_channels >= 8 ) + { + decode_end -= 8; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + #ifdef STBIR_SIMD8 + stbir__simdi i; stbir__simdi8 o; + stbir__simdf8 of; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi8_expand_u16_to_u32( o, i ); + stbir__simdi8_convert_i32_to_float( of, o ); + stbir__decode_simdf8_flip( of ); + stbir__simdf8_store( decode + 0, of ); + #else + stbir__simdi i, o0, o1; + stbir__simdf of0, of1; + STBIR_NO_UNROLL(decode); + stbir__simdi_load( i, input ); + stbir__simdi_expand_u16_to_u32( o0, o1, i ); + stbir__simdi_convert_i32_to_float( of0, o0 ); + stbir__simdi_convert_i32_to_float( of1, o1 ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__simdf_store( decode + 0, of0 ); + stbir__simdf_store( decode + 4, of1 ); + #endif + decode += 8; + input += 8; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 8 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m8; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = ((float)(input[stbir__decode_order0])); + decode[1-4] = ((float)(input[stbir__decode_order1])); + decode[2-4] = ((float)(input[stbir__decode_order2])); + decode[3-4] = ((float)(input[stbir__decode_order3])); + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = ((float)(input[stbir__decode_order0])); + #if stbir__coder_min_num >= 2 + decode[1] = ((float)(input[stbir__decode_order1])); + #endif + #if stbir__coder_min_num >= 3 + decode[2] = ((float)(input[stbir__decode_order2])); + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME(stbir__encode_uint16_linear)( void * outputp, int width_times_channels, float const * encode ) +{ + unsigned short STBIR_SIMD_STREAMOUT_PTR( * ) output = (unsigned short*) outputp; + unsigned short * end_output = ( (unsigned short*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + { + if ( width_times_channels >= stbir__simdfX_float_count*2 ) + { + float const * end_encode_m8 = encode + width_times_channels - stbir__simdfX_float_count*2; + end_output -= stbir__simdfX_float_count*2; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdfX e0, e1; + stbir__simdiX i; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_add_mem( e0, STBIR_simd_point5X, encode ); + stbir__simdfX_add_mem( e1, STBIR_simd_point5X, encode+stbir__simdfX_float_count ); + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + stbir__simdfX_pack_to_words( i, e0, e1 ); + stbir__simdiX_store( output, i ); + encode += stbir__simdfX_float_count*2; + output += stbir__simdfX_float_count*2; + if ( output <= end_output ) + continue; + if ( output == ( end_output + stbir__simdfX_float_count*2 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + stbir__simdf e; + stbir__simdi i; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e, encode ); + stbir__simdf_add( e, STBIR__CONSTF(STBIR_simd_point5), e ); + stbir__encode_simdf4_unflip( e ); + stbir__simdf_pack_to_8words( i, e, e ); // only use first 4 + stbir__simdi_store2( output-4, i ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + float f; + STBIR_SIMD_NO_UNROLL(encode); + f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0-4] = (unsigned short)f; + f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1-4] = (unsigned short)f; + f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2-4] = (unsigned short)f; + f = encode[stbir__encode_order3] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[3-4] = (unsigned short)f; + output += 4; + encode += 4; + } + output -= 4; + #endif + + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + float f; + STBIR_NO_UNROLL(encode); + f = encode[stbir__encode_order0] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[0] = (unsigned short)f; + #if stbir__coder_min_num >= 2 + f = encode[stbir__encode_order1] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[1] = (unsigned short)f; + #endif + #if stbir__coder_min_num >= 3 + f = encode[stbir__encode_order2] + 0.5f; STBIR_CLAMP(f, 0, 65535); output[2] = (unsigned short)f; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_half_float_linear)( float * decodep, int width_times_channels, void const * inputp ) +{ + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + stbir__FP16 const * input = (stbir__FP16 const *)inputp; + + #ifdef STBIR_SIMD + if ( width_times_channels >= 8 ) + { + stbir__FP16 const * end_input_m8 = input + width_times_channels - 8; + decode_end -= 8; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + STBIR_NO_UNROLL(decode); + + stbir__half_to_float_SIMD( decode, input ); + #ifdef stbir__decode_swizzle + #ifdef STBIR_SIMD8 + { + stbir__simdf8 of; + stbir__simdf8_load( of, decode ); + stbir__decode_simdf8_flip( of ); + stbir__simdf8_store( decode, of ); + } + #else + { + stbir__simdf of0,of1; + stbir__simdf_load( of0, decode ); + stbir__simdf_load( of1, decode+4 ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__simdf_store( decode, of0 ); + stbir__simdf_store( decode+4, of1 ); + } + #endif + #endif + decode += 8; + input += 8; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 8 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m8; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = stbir__half_to_float(input[stbir__decode_order0]); + decode[1-4] = stbir__half_to_float(input[stbir__decode_order1]); + decode[2-4] = stbir__half_to_float(input[stbir__decode_order2]); + decode[3-4] = stbir__half_to_float(input[stbir__decode_order3]); + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = stbir__half_to_float(input[stbir__decode_order0]); + #if stbir__coder_min_num >= 2 + decode[1] = stbir__half_to_float(input[stbir__decode_order1]); + #endif + #if stbir__coder_min_num >= 3 + decode[2] = stbir__half_to_float(input[stbir__decode_order2]); + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME( stbir__encode_half_float_linear )( void * outputp, int width_times_channels, float const * encode ) +{ + stbir__FP16 STBIR_SIMD_STREAMOUT_PTR( * ) output = (stbir__FP16*) outputp; + stbir__FP16 * end_output = ( (stbir__FP16*) output ) + width_times_channels; + + #ifdef STBIR_SIMD + if ( width_times_channels >= 8 ) + { + float const * end_encode_m8 = encode + width_times_channels - 8; + end_output -= 8; + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + STBIR_SIMD_NO_UNROLL(encode); + #ifdef stbir__decode_swizzle + #ifdef STBIR_SIMD8 + { + stbir__simdf8 of; + stbir__simdf8_load( of, encode ); + stbir__encode_simdf8_unflip( of ); + stbir__float_to_half_SIMD( output, (float*)&of ); + } + #else + { + stbir__simdf of[2]; + stbir__simdf_load( of[0], encode ); + stbir__simdf_load( of[1], encode+4 ); + stbir__encode_simdf4_unflip( of[0] ); + stbir__encode_simdf4_unflip( of[1] ); + stbir__float_to_half_SIMD( output, (float*)of ); + } + #endif + #else + stbir__float_to_half_SIMD( output, encode ); + #endif + encode += 8; + output += 8; + if ( output <= end_output ) + continue; + if ( output == ( end_output + 8 ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + STBIR_SIMD_NO_UNROLL(output); + output[0-4] = stbir__float_to_half(encode[stbir__encode_order0]); + output[1-4] = stbir__float_to_half(encode[stbir__encode_order1]); + output[2-4] = stbir__float_to_half(encode[stbir__encode_order2]); + output[3-4] = stbir__float_to_half(encode[stbir__encode_order3]); + output += 4; + encode += 4; + } + output -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + STBIR_NO_UNROLL(output); + output[0] = stbir__float_to_half(encode[stbir__encode_order0]); + #if stbir__coder_min_num >= 2 + output[1] = stbir__float_to_half(encode[stbir__encode_order1]); + #endif + #if stbir__coder_min_num >= 3 + output[2] = stbir__float_to_half(encode[stbir__encode_order2]); + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif +} + +static void STBIR__CODER_NAME(stbir__decode_float_linear)( float * decodep, int width_times_channels, void const * inputp ) +{ + #ifdef stbir__decode_swizzle + float STBIR_STREAMOUT_PTR( * ) decode = decodep; + float * decode_end = (float*) decode + width_times_channels; + float const * input = (float const *)inputp; + + #ifdef STBIR_SIMD + if ( width_times_channels >= 16 ) + { + float const * end_input_m16 = input + width_times_channels - 16; + decode_end -= 16; + STBIR_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + STBIR_NO_UNROLL(decode); + #ifdef stbir__decode_swizzle + #ifdef STBIR_SIMD8 + { + stbir__simdf8 of0,of1; + stbir__simdf8_load( of0, input ); + stbir__simdf8_load( of1, input+8 ); + stbir__decode_simdf8_flip( of0 ); + stbir__decode_simdf8_flip( of1 ); + stbir__simdf8_store( decode, of0 ); + stbir__simdf8_store( decode+8, of1 ); + } + #else + { + stbir__simdf of0,of1,of2,of3; + stbir__simdf_load( of0, input ); + stbir__simdf_load( of1, input+4 ); + stbir__simdf_load( of2, input+8 ); + stbir__simdf_load( of3, input+12 ); + stbir__decode_simdf4_flip( of0 ); + stbir__decode_simdf4_flip( of1 ); + stbir__decode_simdf4_flip( of2 ); + stbir__decode_simdf4_flip( of3 ); + stbir__simdf_store( decode, of0 ); + stbir__simdf_store( decode+4, of1 ); + stbir__simdf_store( decode+8, of2 ); + stbir__simdf_store( decode+12, of3 ); + } + #endif + #endif + decode += 16; + input += 16; + if ( decode <= decode_end ) + continue; + if ( decode == ( decode_end + 16 ) ) + break; + decode = decode_end; // backup and do last couple + input = end_input_m16; + } + return; + } + #endif + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + decode += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( decode <= decode_end ) + { + STBIR_SIMD_NO_UNROLL(decode); + decode[0-4] = input[stbir__decode_order0]; + decode[1-4] = input[stbir__decode_order1]; + decode[2-4] = input[stbir__decode_order2]; + decode[3-4] = input[stbir__decode_order3]; + decode += 4; + input += 4; + } + decode -= 4; + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( decode < decode_end ) + { + STBIR_NO_UNROLL(decode); + decode[0] = input[stbir__decode_order0]; + #if stbir__coder_min_num >= 2 + decode[1] = input[stbir__decode_order1]; + #endif + #if stbir__coder_min_num >= 3 + decode[2] = input[stbir__decode_order2]; + #endif + decode += stbir__coder_min_num; + input += stbir__coder_min_num; + } + #endif + + #else + + if ( (void*)decodep != inputp ) + STBIR_MEMCPY( decodep, inputp, width_times_channels * sizeof( float ) ); + + #endif +} + +static void STBIR__CODER_NAME( stbir__encode_float_linear )( void * outputp, int width_times_channels, float const * encode ) +{ + #if !defined( STBIR_FLOAT_HIGH_CLAMP ) && !defined(STBIR_FLOAT_LO_CLAMP) && !defined(stbir__decode_swizzle) + + if ( (void*)outputp != (void*) encode ) + STBIR_MEMCPY( outputp, encode, width_times_channels * sizeof( float ) ); + + #else + + float STBIR_SIMD_STREAMOUT_PTR( * ) output = (float*) outputp; + float * end_output = ( (float*) output ) + width_times_channels; + + #ifdef STBIR_FLOAT_HIGH_CLAMP + #define stbir_scalar_hi_clamp( v ) if ( v > STBIR_FLOAT_HIGH_CLAMP ) v = STBIR_FLOAT_HIGH_CLAMP; + #else + #define stbir_scalar_hi_clamp( v ) + #endif + #ifdef STBIR_FLOAT_LOW_CLAMP + #define stbir_scalar_lo_clamp( v ) if ( v < STBIR_FLOAT_LOW_CLAMP ) v = STBIR_FLOAT_LOW_CLAMP; + #else + #define stbir_scalar_lo_clamp( v ) + #endif + + #ifdef STBIR_SIMD + + #ifdef STBIR_FLOAT_HIGH_CLAMP + const stbir__simdfX high_clamp = stbir__simdf_frepX(STBIR_FLOAT_HIGH_CLAMP); + #endif + #ifdef STBIR_FLOAT_LOW_CLAMP + const stbir__simdfX low_clamp = stbir__simdf_frepX(STBIR_FLOAT_LOW_CLAMP); + #endif + + if ( width_times_channels >= ( stbir__simdfX_float_count * 2 ) ) + { + float const * end_encode_m8 = encode + width_times_channels - ( stbir__simdfX_float_count * 2 ); + end_output -= ( stbir__simdfX_float_count * 2 ); + STBIR_SIMD_NO_UNROLL_LOOP_START_INF_FOR + for(;;) + { + stbir__simdfX e0, e1; + STBIR_SIMD_NO_UNROLL(encode); + stbir__simdfX_load( e0, encode ); + stbir__simdfX_load( e1, encode+stbir__simdfX_float_count ); +#ifdef STBIR_FLOAT_HIGH_CLAMP + stbir__simdfX_min( e0, e0, high_clamp ); + stbir__simdfX_min( e1, e1, high_clamp ); +#endif +#ifdef STBIR_FLOAT_LOW_CLAMP + stbir__simdfX_max( e0, e0, low_clamp ); + stbir__simdfX_max( e1, e1, low_clamp ); +#endif + stbir__encode_simdfX_unflip( e0 ); + stbir__encode_simdfX_unflip( e1 ); + stbir__simdfX_store( output, e0 ); + stbir__simdfX_store( output+stbir__simdfX_float_count, e1 ); + encode += stbir__simdfX_float_count * 2; + output += stbir__simdfX_float_count * 2; + if ( output < end_output ) + continue; + if ( output == ( end_output + ( stbir__simdfX_float_count * 2 ) ) ) + break; + output = end_output; // backup and do last couple + encode = end_encode_m8; + } + return; + } + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + stbir__simdf e0; + STBIR_NO_UNROLL(encode); + stbir__simdf_load( e0, encode ); +#ifdef STBIR_FLOAT_HIGH_CLAMP + stbir__simdf_min( e0, e0, high_clamp ); +#endif +#ifdef STBIR_FLOAT_LOW_CLAMP + stbir__simdf_max( e0, e0, low_clamp ); +#endif + stbir__encode_simdf4_unflip( e0 ); + stbir__simdf_store( output-4, e0 ); + output += 4; + encode += 4; + } + output -= 4; + #endif + + #else + + // try to do blocks of 4 when you can + #if stbir__coder_min_num != 3 // doesn't divide cleanly by four + output += 4; + STBIR_SIMD_NO_UNROLL_LOOP_START + while( output <= end_output ) + { + float e; + STBIR_SIMD_NO_UNROLL(encode); + e = encode[ stbir__encode_order0 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[0-4] = e; + e = encode[ stbir__encode_order1 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[1-4] = e; + e = encode[ stbir__encode_order2 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[2-4] = e; + e = encode[ stbir__encode_order3 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[3-4] = e; + output += 4; + encode += 4; + } + output -= 4; + + #endif + + #endif + + // do the remnants + #if stbir__coder_min_num < 4 + STBIR_NO_UNROLL_LOOP_START + while( output < end_output ) + { + float e; + STBIR_NO_UNROLL(encode); + e = encode[ stbir__encode_order0 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[0] = e; + #if stbir__coder_min_num >= 2 + e = encode[ stbir__encode_order1 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[1] = e; + #endif + #if stbir__coder_min_num >= 3 + e = encode[ stbir__encode_order2 ]; stbir_scalar_hi_clamp( e ); stbir_scalar_lo_clamp( e ); output[2] = e; + #endif + output += stbir__coder_min_num; + encode += stbir__coder_min_num; + } + #endif + + #endif +} + +#undef stbir__decode_suffix +#undef stbir__decode_simdf8_flip +#undef stbir__decode_simdf4_flip +#undef stbir__decode_order0 +#undef stbir__decode_order1 +#undef stbir__decode_order2 +#undef stbir__decode_order3 +#undef stbir__encode_order0 +#undef stbir__encode_order1 +#undef stbir__encode_order2 +#undef stbir__encode_order3 +#undef stbir__encode_simdf8_unflip +#undef stbir__encode_simdf4_unflip +#undef stbir__encode_simdfX_unflip +#undef STBIR__CODER_NAME +#undef stbir__coder_min_num +#undef stbir__decode_swizzle +#undef stbir_scalar_hi_clamp +#undef stbir_scalar_lo_clamp +#undef STB_IMAGE_RESIZE_DO_CODERS + +#elif defined( STB_IMAGE_RESIZE_DO_VERTICALS) + +#ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#define STBIR_chans( start, end ) STBIR_strs_join14(start,STBIR__vertical_channels,end,_cont) +#else +#define STBIR_chans( start, end ) STBIR_strs_join1(start,STBIR__vertical_channels,end) +#endif + +#if STBIR__vertical_channels >= 1 +#define stbIF0( code ) code +#else +#define stbIF0( code ) +#endif +#if STBIR__vertical_channels >= 2 +#define stbIF1( code ) code +#else +#define stbIF1( code ) +#endif +#if STBIR__vertical_channels >= 3 +#define stbIF2( code ) code +#else +#define stbIF2( code ) +#endif +#if STBIR__vertical_channels >= 4 +#define stbIF3( code ) code +#else +#define stbIF3( code ) +#endif +#if STBIR__vertical_channels >= 5 +#define stbIF4( code ) code +#else +#define stbIF4( code ) +#endif +#if STBIR__vertical_channels >= 6 +#define stbIF5( code ) code +#else +#define stbIF5( code ) +#endif +#if STBIR__vertical_channels >= 7 +#define stbIF6( code ) code +#else +#define stbIF6( code ) +#endif +#if STBIR__vertical_channels >= 8 +#define stbIF7( code ) code +#else +#define stbIF7( code ) +#endif + +static void STBIR_chans( stbir__vertical_scatter_with_,_coeffs)( float ** outputs, float const * vertical_coefficients, float const * input, float const * input_end ) +{ + stbIF0( float STBIR_SIMD_STREAMOUT_PTR( * ) output0 = outputs[0]; float c0s = vertical_coefficients[0]; ) + stbIF1( float STBIR_SIMD_STREAMOUT_PTR( * ) output1 = outputs[1]; float c1s = vertical_coefficients[1]; ) + stbIF2( float STBIR_SIMD_STREAMOUT_PTR( * ) output2 = outputs[2]; float c2s = vertical_coefficients[2]; ) + stbIF3( float STBIR_SIMD_STREAMOUT_PTR( * ) output3 = outputs[3]; float c3s = vertical_coefficients[3]; ) + stbIF4( float STBIR_SIMD_STREAMOUT_PTR( * ) output4 = outputs[4]; float c4s = vertical_coefficients[4]; ) + stbIF5( float STBIR_SIMD_STREAMOUT_PTR( * ) output5 = outputs[5]; float c5s = vertical_coefficients[5]; ) + stbIF6( float STBIR_SIMD_STREAMOUT_PTR( * ) output6 = outputs[6]; float c6s = vertical_coefficients[6]; ) + stbIF7( float STBIR_SIMD_STREAMOUT_PTR( * ) output7 = outputs[7]; float c7s = vertical_coefficients[7]; ) + + #ifdef STBIR_SIMD + { + stbIF0(stbir__simdfX c0 = stbir__simdf_frepX( c0s ); ) + stbIF1(stbir__simdfX c1 = stbir__simdf_frepX( c1s ); ) + stbIF2(stbir__simdfX c2 = stbir__simdf_frepX( c2s ); ) + stbIF3(stbir__simdfX c3 = stbir__simdf_frepX( c3s ); ) + stbIF4(stbir__simdfX c4 = stbir__simdf_frepX( c4s ); ) + stbIF5(stbir__simdfX c5 = stbir__simdf_frepX( c5s ); ) + stbIF6(stbir__simdfX c6 = stbir__simdf_frepX( c6s ); ) + stbIF7(stbir__simdfX c7 = stbir__simdf_frepX( c7s ); ) + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( ( (char*)input_end - (char*) input ) >= (16*stbir__simdfX_float_count) ) + { + stbir__simdfX o0, o1, o2, o3, r0, r1, r2, r3; + STBIR_SIMD_NO_UNROLL(output0); + + stbir__simdfX_load( r0, input ); stbir__simdfX_load( r1, input+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input+(3*stbir__simdfX_float_count) ); + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( stbir__simdfX_load( o0, output0 ); stbir__simdfX_load( o1, output0+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output0+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output0+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c0 ); stbir__simdfX_madd( o1, o1, r1, c0 ); stbir__simdfX_madd( o2, o2, r2, c0 ); stbir__simdfX_madd( o3, o3, r3, c0 ); + stbir__simdfX_store( output0, o0 ); stbir__simdfX_store( output0+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output0+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output0+(3*stbir__simdfX_float_count), o3 ); ) + stbIF1( stbir__simdfX_load( o0, output1 ); stbir__simdfX_load( o1, output1+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output1+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output1+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c1 ); stbir__simdfX_madd( o1, o1, r1, c1 ); stbir__simdfX_madd( o2, o2, r2, c1 ); stbir__simdfX_madd( o3, o3, r3, c1 ); + stbir__simdfX_store( output1, o0 ); stbir__simdfX_store( output1+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output1+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output1+(3*stbir__simdfX_float_count), o3 ); ) + stbIF2( stbir__simdfX_load( o0, output2 ); stbir__simdfX_load( o1, output2+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output2+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output2+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c2 ); stbir__simdfX_madd( o1, o1, r1, c2 ); stbir__simdfX_madd( o2, o2, r2, c2 ); stbir__simdfX_madd( o3, o3, r3, c2 ); + stbir__simdfX_store( output2, o0 ); stbir__simdfX_store( output2+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output2+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output2+(3*stbir__simdfX_float_count), o3 ); ) + stbIF3( stbir__simdfX_load( o0, output3 ); stbir__simdfX_load( o1, output3+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output3+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output3+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c3 ); stbir__simdfX_madd( o1, o1, r1, c3 ); stbir__simdfX_madd( o2, o2, r2, c3 ); stbir__simdfX_madd( o3, o3, r3, c3 ); + stbir__simdfX_store( output3, o0 ); stbir__simdfX_store( output3+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output3+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output3+(3*stbir__simdfX_float_count), o3 ); ) + stbIF4( stbir__simdfX_load( o0, output4 ); stbir__simdfX_load( o1, output4+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output4+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output4+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c4 ); stbir__simdfX_madd( o1, o1, r1, c4 ); stbir__simdfX_madd( o2, o2, r2, c4 ); stbir__simdfX_madd( o3, o3, r3, c4 ); + stbir__simdfX_store( output4, o0 ); stbir__simdfX_store( output4+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output4+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output4+(3*stbir__simdfX_float_count), o3 ); ) + stbIF5( stbir__simdfX_load( o0, output5 ); stbir__simdfX_load( o1, output5+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output5+(2*stbir__simdfX_float_count)); stbir__simdfX_load( o3, output5+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c5 ); stbir__simdfX_madd( o1, o1, r1, c5 ); stbir__simdfX_madd( o2, o2, r2, c5 ); stbir__simdfX_madd( o3, o3, r3, c5 ); + stbir__simdfX_store( output5, o0 ); stbir__simdfX_store( output5+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output5+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output5+(3*stbir__simdfX_float_count), o3 ); ) + stbIF6( stbir__simdfX_load( o0, output6 ); stbir__simdfX_load( o1, output6+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output6+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output6+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c6 ); stbir__simdfX_madd( o1, o1, r1, c6 ); stbir__simdfX_madd( o2, o2, r2, c6 ); stbir__simdfX_madd( o3, o3, r3, c6 ); + stbir__simdfX_store( output6, o0 ); stbir__simdfX_store( output6+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output6+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output6+(3*stbir__simdfX_float_count), o3 ); ) + stbIF7( stbir__simdfX_load( o0, output7 ); stbir__simdfX_load( o1, output7+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output7+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output7+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c7 ); stbir__simdfX_madd( o1, o1, r1, c7 ); stbir__simdfX_madd( o2, o2, r2, c7 ); stbir__simdfX_madd( o3, o3, r3, c7 ); + stbir__simdfX_store( output7, o0 ); stbir__simdfX_store( output7+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output7+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output7+(3*stbir__simdfX_float_count), o3 ); ) + #else + stbIF0( stbir__simdfX_mult( o0, r0, c0 ); stbir__simdfX_mult( o1, r1, c0 ); stbir__simdfX_mult( o2, r2, c0 ); stbir__simdfX_mult( o3, r3, c0 ); + stbir__simdfX_store( output0, o0 ); stbir__simdfX_store( output0+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output0+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output0+(3*stbir__simdfX_float_count), o3 ); ) + stbIF1( stbir__simdfX_mult( o0, r0, c1 ); stbir__simdfX_mult( o1, r1, c1 ); stbir__simdfX_mult( o2, r2, c1 ); stbir__simdfX_mult( o3, r3, c1 ); + stbir__simdfX_store( output1, o0 ); stbir__simdfX_store( output1+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output1+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output1+(3*stbir__simdfX_float_count), o3 ); ) + stbIF2( stbir__simdfX_mult( o0, r0, c2 ); stbir__simdfX_mult( o1, r1, c2 ); stbir__simdfX_mult( o2, r2, c2 ); stbir__simdfX_mult( o3, r3, c2 ); + stbir__simdfX_store( output2, o0 ); stbir__simdfX_store( output2+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output2+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output2+(3*stbir__simdfX_float_count), o3 ); ) + stbIF3( stbir__simdfX_mult( o0, r0, c3 ); stbir__simdfX_mult( o1, r1, c3 ); stbir__simdfX_mult( o2, r2, c3 ); stbir__simdfX_mult( o3, r3, c3 ); + stbir__simdfX_store( output3, o0 ); stbir__simdfX_store( output3+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output3+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output3+(3*stbir__simdfX_float_count), o3 ); ) + stbIF4( stbir__simdfX_mult( o0, r0, c4 ); stbir__simdfX_mult( o1, r1, c4 ); stbir__simdfX_mult( o2, r2, c4 ); stbir__simdfX_mult( o3, r3, c4 ); + stbir__simdfX_store( output4, o0 ); stbir__simdfX_store( output4+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output4+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output4+(3*stbir__simdfX_float_count), o3 ); ) + stbIF5( stbir__simdfX_mult( o0, r0, c5 ); stbir__simdfX_mult( o1, r1, c5 ); stbir__simdfX_mult( o2, r2, c5 ); stbir__simdfX_mult( o3, r3, c5 ); + stbir__simdfX_store( output5, o0 ); stbir__simdfX_store( output5+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output5+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output5+(3*stbir__simdfX_float_count), o3 ); ) + stbIF6( stbir__simdfX_mult( o0, r0, c6 ); stbir__simdfX_mult( o1, r1, c6 ); stbir__simdfX_mult( o2, r2, c6 ); stbir__simdfX_mult( o3, r3, c6 ); + stbir__simdfX_store( output6, o0 ); stbir__simdfX_store( output6+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output6+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output6+(3*stbir__simdfX_float_count), o3 ); ) + stbIF7( stbir__simdfX_mult( o0, r0, c7 ); stbir__simdfX_mult( o1, r1, c7 ); stbir__simdfX_mult( o2, r2, c7 ); stbir__simdfX_mult( o3, r3, c7 ); + stbir__simdfX_store( output7, o0 ); stbir__simdfX_store( output7+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output7+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output7+(3*stbir__simdfX_float_count), o3 ); ) + #endif + + input += (4*stbir__simdfX_float_count); + stbIF0( output0 += (4*stbir__simdfX_float_count); ) stbIF1( output1 += (4*stbir__simdfX_float_count); ) stbIF2( output2 += (4*stbir__simdfX_float_count); ) stbIF3( output3 += (4*stbir__simdfX_float_count); ) stbIF4( output4 += (4*stbir__simdfX_float_count); ) stbIF5( output5 += (4*stbir__simdfX_float_count); ) stbIF6( output6 += (4*stbir__simdfX_float_count); ) stbIF7( output7 += (4*stbir__simdfX_float_count); ) + } + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( ( (char*)input_end - (char*) input ) >= 16 ) + { + stbir__simdf o0, r0; + STBIR_SIMD_NO_UNROLL(output0); + + stbir__simdf_load( r0, input ); + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( stbir__simdf_load( o0, output0 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); stbir__simdf_store( output0, o0 ); ) + stbIF1( stbir__simdf_load( o0, output1 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) ); stbir__simdf_store( output1, o0 ); ) + stbIF2( stbir__simdf_load( o0, output2 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) ); stbir__simdf_store( output2, o0 ); ) + stbIF3( stbir__simdf_load( o0, output3 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) ); stbir__simdf_store( output3, o0 ); ) + stbIF4( stbir__simdf_load( o0, output4 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) ); stbir__simdf_store( output4, o0 ); ) + stbIF5( stbir__simdf_load( o0, output5 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) ); stbir__simdf_store( output5, o0 ); ) + stbIF6( stbir__simdf_load( o0, output6 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) ); stbir__simdf_store( output6, o0 ); ) + stbIF7( stbir__simdf_load( o0, output7 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) ); stbir__simdf_store( output7, o0 ); ) + #else + stbIF0( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); stbir__simdf_store( output0, o0 ); ) + stbIF1( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) ); stbir__simdf_store( output1, o0 ); ) + stbIF2( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) ); stbir__simdf_store( output2, o0 ); ) + stbIF3( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) ); stbir__simdf_store( output3, o0 ); ) + stbIF4( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) ); stbir__simdf_store( output4, o0 ); ) + stbIF5( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) ); stbir__simdf_store( output5, o0 ); ) + stbIF6( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) ); stbir__simdf_store( output6, o0 ); ) + stbIF7( stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) ); stbir__simdf_store( output7, o0 ); ) + #endif + + input += 4; + stbIF0( output0 += 4; ) stbIF1( output1 += 4; ) stbIF2( output2 += 4; ) stbIF3( output3 += 4; ) stbIF4( output4 += 4; ) stbIF5( output5 += 4; ) stbIF6( output6 += 4; ) stbIF7( output7 += 4; ) + } + } + #else + STBIR_NO_UNROLL_LOOP_START + while ( ( (char*)input_end - (char*) input ) >= 16 ) + { + float r0, r1, r2, r3; + STBIR_NO_UNROLL(input); + + r0 = input[0], r1 = input[1], r2 = input[2], r3 = input[3]; + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( output0[0] += ( r0 * c0s ); output0[1] += ( r1 * c0s ); output0[2] += ( r2 * c0s ); output0[3] += ( r3 * c0s ); ) + stbIF1( output1[0] += ( r0 * c1s ); output1[1] += ( r1 * c1s ); output1[2] += ( r2 * c1s ); output1[3] += ( r3 * c1s ); ) + stbIF2( output2[0] += ( r0 * c2s ); output2[1] += ( r1 * c2s ); output2[2] += ( r2 * c2s ); output2[3] += ( r3 * c2s ); ) + stbIF3( output3[0] += ( r0 * c3s ); output3[1] += ( r1 * c3s ); output3[2] += ( r2 * c3s ); output3[3] += ( r3 * c3s ); ) + stbIF4( output4[0] += ( r0 * c4s ); output4[1] += ( r1 * c4s ); output4[2] += ( r2 * c4s ); output4[3] += ( r3 * c4s ); ) + stbIF5( output5[0] += ( r0 * c5s ); output5[1] += ( r1 * c5s ); output5[2] += ( r2 * c5s ); output5[3] += ( r3 * c5s ); ) + stbIF6( output6[0] += ( r0 * c6s ); output6[1] += ( r1 * c6s ); output6[2] += ( r2 * c6s ); output6[3] += ( r3 * c6s ); ) + stbIF7( output7[0] += ( r0 * c7s ); output7[1] += ( r1 * c7s ); output7[2] += ( r2 * c7s ); output7[3] += ( r3 * c7s ); ) + #else + stbIF0( output0[0] = ( r0 * c0s ); output0[1] = ( r1 * c0s ); output0[2] = ( r2 * c0s ); output0[3] = ( r3 * c0s ); ) + stbIF1( output1[0] = ( r0 * c1s ); output1[1] = ( r1 * c1s ); output1[2] = ( r2 * c1s ); output1[3] = ( r3 * c1s ); ) + stbIF2( output2[0] = ( r0 * c2s ); output2[1] = ( r1 * c2s ); output2[2] = ( r2 * c2s ); output2[3] = ( r3 * c2s ); ) + stbIF3( output3[0] = ( r0 * c3s ); output3[1] = ( r1 * c3s ); output3[2] = ( r2 * c3s ); output3[3] = ( r3 * c3s ); ) + stbIF4( output4[0] = ( r0 * c4s ); output4[1] = ( r1 * c4s ); output4[2] = ( r2 * c4s ); output4[3] = ( r3 * c4s ); ) + stbIF5( output5[0] = ( r0 * c5s ); output5[1] = ( r1 * c5s ); output5[2] = ( r2 * c5s ); output5[3] = ( r3 * c5s ); ) + stbIF6( output6[0] = ( r0 * c6s ); output6[1] = ( r1 * c6s ); output6[2] = ( r2 * c6s ); output6[3] = ( r3 * c6s ); ) + stbIF7( output7[0] = ( r0 * c7s ); output7[1] = ( r1 * c7s ); output7[2] = ( r2 * c7s ); output7[3] = ( r3 * c7s ); ) + #endif + + input += 4; + stbIF0( output0 += 4; ) stbIF1( output1 += 4; ) stbIF2( output2 += 4; ) stbIF3( output3 += 4; ) stbIF4( output4 += 4; ) stbIF5( output5 += 4; ) stbIF6( output6 += 4; ) stbIF7( output7 += 4; ) + } + #endif + STBIR_NO_UNROLL_LOOP_START + while ( input < input_end ) + { + float r = input[0]; + STBIR_NO_UNROLL(output0); + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( output0[0] += ( r * c0s ); ) + stbIF1( output1[0] += ( r * c1s ); ) + stbIF2( output2[0] += ( r * c2s ); ) + stbIF3( output3[0] += ( r * c3s ); ) + stbIF4( output4[0] += ( r * c4s ); ) + stbIF5( output5[0] += ( r * c5s ); ) + stbIF6( output6[0] += ( r * c6s ); ) + stbIF7( output7[0] += ( r * c7s ); ) + #else + stbIF0( output0[0] = ( r * c0s ); ) + stbIF1( output1[0] = ( r * c1s ); ) + stbIF2( output2[0] = ( r * c2s ); ) + stbIF3( output3[0] = ( r * c3s ); ) + stbIF4( output4[0] = ( r * c4s ); ) + stbIF5( output5[0] = ( r * c5s ); ) + stbIF6( output6[0] = ( r * c6s ); ) + stbIF7( output7[0] = ( r * c7s ); ) + #endif + + ++input; + stbIF0( ++output0; ) stbIF1( ++output1; ) stbIF2( ++output2; ) stbIF3( ++output3; ) stbIF4( ++output4; ) stbIF5( ++output5; ) stbIF6( ++output6; ) stbIF7( ++output7; ) + } +} + +static void STBIR_chans( stbir__vertical_gather_with_,_coeffs)( float * outputp, float const * vertical_coefficients, float const ** inputs, float const * input0_end ) +{ + float STBIR_SIMD_STREAMOUT_PTR( * ) output = outputp; + + stbIF0( float const * input0 = inputs[0]; float c0s = vertical_coefficients[0]; ) + stbIF1( float const * input1 = inputs[1]; float c1s = vertical_coefficients[1]; ) + stbIF2( float const * input2 = inputs[2]; float c2s = vertical_coefficients[2]; ) + stbIF3( float const * input3 = inputs[3]; float c3s = vertical_coefficients[3]; ) + stbIF4( float const * input4 = inputs[4]; float c4s = vertical_coefficients[4]; ) + stbIF5( float const * input5 = inputs[5]; float c5s = vertical_coefficients[5]; ) + stbIF6( float const * input6 = inputs[6]; float c6s = vertical_coefficients[6]; ) + stbIF7( float const * input7 = inputs[7]; float c7s = vertical_coefficients[7]; ) + +#if ( STBIR__vertical_channels == 1 ) && !defined(STB_IMAGE_RESIZE_VERTICAL_CONTINUE) + // check single channel one weight + if ( ( c0s >= (1.0f-0.000001f) ) && ( c0s <= (1.0f+0.000001f) ) ) + { + STBIR_MEMCPY( output, input0, (char*)input0_end - (char*)input0 ); + return; + } +#endif + + #ifdef STBIR_SIMD + { + stbIF0(stbir__simdfX c0 = stbir__simdf_frepX( c0s ); ) + stbIF1(stbir__simdfX c1 = stbir__simdf_frepX( c1s ); ) + stbIF2(stbir__simdfX c2 = stbir__simdf_frepX( c2s ); ) + stbIF3(stbir__simdfX c3 = stbir__simdf_frepX( c3s ); ) + stbIF4(stbir__simdfX c4 = stbir__simdf_frepX( c4s ); ) + stbIF5(stbir__simdfX c5 = stbir__simdf_frepX( c5s ); ) + stbIF6(stbir__simdfX c6 = stbir__simdf_frepX( c6s ); ) + stbIF7(stbir__simdfX c7 = stbir__simdf_frepX( c7s ); ) + + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( ( (char*)input0_end - (char*) input0 ) >= (16*stbir__simdfX_float_count) ) + { + stbir__simdfX o0, o1, o2, o3, r0, r1, r2, r3; + STBIR_SIMD_NO_UNROLL(output); + + // prefetch four loop iterations ahead (doesn't affect much for small resizes, but helps with big ones) + stbIF0( stbir__prefetch( input0 + (16*stbir__simdfX_float_count) ); ) + stbIF1( stbir__prefetch( input1 + (16*stbir__simdfX_float_count) ); ) + stbIF2( stbir__prefetch( input2 + (16*stbir__simdfX_float_count) ); ) + stbIF3( stbir__prefetch( input3 + (16*stbir__simdfX_float_count) ); ) + stbIF4( stbir__prefetch( input4 + (16*stbir__simdfX_float_count) ); ) + stbIF5( stbir__prefetch( input5 + (16*stbir__simdfX_float_count) ); ) + stbIF6( stbir__prefetch( input6 + (16*stbir__simdfX_float_count) ); ) + stbIF7( stbir__prefetch( input7 + (16*stbir__simdfX_float_count) ); ) + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( stbir__simdfX_load( o0, output ); stbir__simdfX_load( o1, output+stbir__simdfX_float_count ); stbir__simdfX_load( o2, output+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( o3, output+(3*stbir__simdfX_float_count) ); + stbir__simdfX_load( r0, input0 ); stbir__simdfX_load( r1, input0+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input0+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input0+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c0 ); stbir__simdfX_madd( o1, o1, r1, c0 ); stbir__simdfX_madd( o2, o2, r2, c0 ); stbir__simdfX_madd( o3, o3, r3, c0 ); ) + #else + stbIF0( stbir__simdfX_load( r0, input0 ); stbir__simdfX_load( r1, input0+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input0+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input0+(3*stbir__simdfX_float_count) ); + stbir__simdfX_mult( o0, r0, c0 ); stbir__simdfX_mult( o1, r1, c0 ); stbir__simdfX_mult( o2, r2, c0 ); stbir__simdfX_mult( o3, r3, c0 ); ) + #endif + + stbIF1( stbir__simdfX_load( r0, input1 ); stbir__simdfX_load( r1, input1+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input1+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input1+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c1 ); stbir__simdfX_madd( o1, o1, r1, c1 ); stbir__simdfX_madd( o2, o2, r2, c1 ); stbir__simdfX_madd( o3, o3, r3, c1 ); ) + stbIF2( stbir__simdfX_load( r0, input2 ); stbir__simdfX_load( r1, input2+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input2+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input2+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c2 ); stbir__simdfX_madd( o1, o1, r1, c2 ); stbir__simdfX_madd( o2, o2, r2, c2 ); stbir__simdfX_madd( o3, o3, r3, c2 ); ) + stbIF3( stbir__simdfX_load( r0, input3 ); stbir__simdfX_load( r1, input3+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input3+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input3+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c3 ); stbir__simdfX_madd( o1, o1, r1, c3 ); stbir__simdfX_madd( o2, o2, r2, c3 ); stbir__simdfX_madd( o3, o3, r3, c3 ); ) + stbIF4( stbir__simdfX_load( r0, input4 ); stbir__simdfX_load( r1, input4+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input4+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input4+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c4 ); stbir__simdfX_madd( o1, o1, r1, c4 ); stbir__simdfX_madd( o2, o2, r2, c4 ); stbir__simdfX_madd( o3, o3, r3, c4 ); ) + stbIF5( stbir__simdfX_load( r0, input5 ); stbir__simdfX_load( r1, input5+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input5+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input5+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c5 ); stbir__simdfX_madd( o1, o1, r1, c5 ); stbir__simdfX_madd( o2, o2, r2, c5 ); stbir__simdfX_madd( o3, o3, r3, c5 ); ) + stbIF6( stbir__simdfX_load( r0, input6 ); stbir__simdfX_load( r1, input6+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input6+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input6+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c6 ); stbir__simdfX_madd( o1, o1, r1, c6 ); stbir__simdfX_madd( o2, o2, r2, c6 ); stbir__simdfX_madd( o3, o3, r3, c6 ); ) + stbIF7( stbir__simdfX_load( r0, input7 ); stbir__simdfX_load( r1, input7+stbir__simdfX_float_count ); stbir__simdfX_load( r2, input7+(2*stbir__simdfX_float_count) ); stbir__simdfX_load( r3, input7+(3*stbir__simdfX_float_count) ); + stbir__simdfX_madd( o0, o0, r0, c7 ); stbir__simdfX_madd( o1, o1, r1, c7 ); stbir__simdfX_madd( o2, o2, r2, c7 ); stbir__simdfX_madd( o3, o3, r3, c7 ); ) + + stbir__simdfX_store( output, o0 ); stbir__simdfX_store( output+stbir__simdfX_float_count, o1 ); stbir__simdfX_store( output+(2*stbir__simdfX_float_count), o2 ); stbir__simdfX_store( output+(3*stbir__simdfX_float_count), o3 ); + output += (4*stbir__simdfX_float_count); + stbIF0( input0 += (4*stbir__simdfX_float_count); ) stbIF1( input1 += (4*stbir__simdfX_float_count); ) stbIF2( input2 += (4*stbir__simdfX_float_count); ) stbIF3( input3 += (4*stbir__simdfX_float_count); ) stbIF4( input4 += (4*stbir__simdfX_float_count); ) stbIF5( input5 += (4*stbir__simdfX_float_count); ) stbIF6( input6 += (4*stbir__simdfX_float_count); ) stbIF7( input7 += (4*stbir__simdfX_float_count); ) + } + + STBIR_SIMD_NO_UNROLL_LOOP_START + while ( ( (char*)input0_end - (char*) input0 ) >= 16 ) + { + stbir__simdf o0, r0; + STBIR_SIMD_NO_UNROLL(output); + + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( stbir__simdf_load( o0, output ); stbir__simdf_load( r0, input0 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); ) + #else + stbIF0( stbir__simdf_load( r0, input0 ); stbir__simdf_mult( o0, r0, stbir__if_simdf8_cast_to_simdf4( c0 ) ); ) + #endif + stbIF1( stbir__simdf_load( r0, input1 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c1 ) ); ) + stbIF2( stbir__simdf_load( r0, input2 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c2 ) ); ) + stbIF3( stbir__simdf_load( r0, input3 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c3 ) ); ) + stbIF4( stbir__simdf_load( r0, input4 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c4 ) ); ) + stbIF5( stbir__simdf_load( r0, input5 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c5 ) ); ) + stbIF6( stbir__simdf_load( r0, input6 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c6 ) ); ) + stbIF7( stbir__simdf_load( r0, input7 ); stbir__simdf_madd( o0, o0, r0, stbir__if_simdf8_cast_to_simdf4( c7 ) ); ) + + stbir__simdf_store( output, o0 ); + output += 4; + stbIF0( input0 += 4; ) stbIF1( input1 += 4; ) stbIF2( input2 += 4; ) stbIF3( input3 += 4; ) stbIF4( input4 += 4; ) stbIF5( input5 += 4; ) stbIF6( input6 += 4; ) stbIF7( input7 += 4; ) + } + } + #else + STBIR_NO_UNROLL_LOOP_START + while ( ( (char*)input0_end - (char*) input0 ) >= 16 ) + { + float o0, o1, o2, o3; + STBIR_NO_UNROLL(output); + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( o0 = output[0] + input0[0] * c0s; o1 = output[1] + input0[1] * c0s; o2 = output[2] + input0[2] * c0s; o3 = output[3] + input0[3] * c0s; ) + #else + stbIF0( o0 = input0[0] * c0s; o1 = input0[1] * c0s; o2 = input0[2] * c0s; o3 = input0[3] * c0s; ) + #endif + stbIF1( o0 += input1[0] * c1s; o1 += input1[1] * c1s; o2 += input1[2] * c1s; o3 += input1[3] * c1s; ) + stbIF2( o0 += input2[0] * c2s; o1 += input2[1] * c2s; o2 += input2[2] * c2s; o3 += input2[3] * c2s; ) + stbIF3( o0 += input3[0] * c3s; o1 += input3[1] * c3s; o2 += input3[2] * c3s; o3 += input3[3] * c3s; ) + stbIF4( o0 += input4[0] * c4s; o1 += input4[1] * c4s; o2 += input4[2] * c4s; o3 += input4[3] * c4s; ) + stbIF5( o0 += input5[0] * c5s; o1 += input5[1] * c5s; o2 += input5[2] * c5s; o3 += input5[3] * c5s; ) + stbIF6( o0 += input6[0] * c6s; o1 += input6[1] * c6s; o2 += input6[2] * c6s; o3 += input6[3] * c6s; ) + stbIF7( o0 += input7[0] * c7s; o1 += input7[1] * c7s; o2 += input7[2] * c7s; o3 += input7[3] * c7s; ) + output[0] = o0; output[1] = o1; output[2] = o2; output[3] = o3; + output += 4; + stbIF0( input0 += 4; ) stbIF1( input1 += 4; ) stbIF2( input2 += 4; ) stbIF3( input3 += 4; ) stbIF4( input4 += 4; ) stbIF5( input5 += 4; ) stbIF6( input6 += 4; ) stbIF7( input7 += 4; ) + } + #endif + STBIR_NO_UNROLL_LOOP_START + while ( input0 < input0_end ) + { + float o0; + STBIR_NO_UNROLL(output); + #ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE + stbIF0( o0 = output[0] + input0[0] * c0s; ) + #else + stbIF0( o0 = input0[0] * c0s; ) + #endif + stbIF1( o0 += input1[0] * c1s; ) + stbIF2( o0 += input2[0] * c2s; ) + stbIF3( o0 += input3[0] * c3s; ) + stbIF4( o0 += input4[0] * c4s; ) + stbIF5( o0 += input5[0] * c5s; ) + stbIF6( o0 += input6[0] * c6s; ) + stbIF7( o0 += input7[0] * c7s; ) + output[0] = o0; + ++output; + stbIF0( ++input0; ) stbIF1( ++input1; ) stbIF2( ++input2; ) stbIF3( ++input3; ) stbIF4( ++input4; ) stbIF5( ++input5; ) stbIF6( ++input6; ) stbIF7( ++input7; ) + } +} + +#undef stbIF0 +#undef stbIF1 +#undef stbIF2 +#undef stbIF3 +#undef stbIF4 +#undef stbIF5 +#undef stbIF6 +#undef stbIF7 +#undef STB_IMAGE_RESIZE_DO_VERTICALS +#undef STBIR__vertical_channels +#undef STB_IMAGE_RESIZE_DO_HORIZONTALS +#undef STBIR_strs_join24 +#undef STBIR_strs_join14 +#undef STBIR_chans +#ifdef STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#undef STB_IMAGE_RESIZE_VERTICAL_CONTINUE +#endif + +#else // !STB_IMAGE_RESIZE_DO_VERTICALS + +#define STBIR_chans( start, end ) STBIR_strs_join1(start,STBIR__horizontal_channels,end) + +#ifndef stbir__2_coeff_only +#define stbir__2_coeff_only() \ + stbir__1_coeff_only(); \ + stbir__1_coeff_remnant(1); +#endif + +#ifndef stbir__2_coeff_remnant +#define stbir__2_coeff_remnant( ofs ) \ + stbir__1_coeff_remnant(ofs); \ + stbir__1_coeff_remnant((ofs)+1); +#endif + +#ifndef stbir__3_coeff_only +#define stbir__3_coeff_only() \ + stbir__2_coeff_only(); \ + stbir__1_coeff_remnant(2); +#endif + +#ifndef stbir__3_coeff_remnant +#define stbir__3_coeff_remnant( ofs ) \ + stbir__2_coeff_remnant(ofs); \ + stbir__1_coeff_remnant((ofs)+2); +#endif + +#ifndef stbir__3_coeff_setup +#define stbir__3_coeff_setup() +#endif + +#ifndef stbir__4_coeff_start +#define stbir__4_coeff_start() \ + stbir__2_coeff_only(); \ + stbir__2_coeff_remnant(2); +#endif + +#ifndef stbir__4_coeff_continue_from_4 +#define stbir__4_coeff_continue_from_4( ofs ) \ + stbir__2_coeff_remnant(ofs); \ + stbir__2_coeff_remnant((ofs)+2); +#endif + +#ifndef stbir__store_output_tiny +#define stbir__store_output_tiny stbir__store_output +#endif + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_1_coeff)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__1_coeff_only(); + stbir__store_output_tiny(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_2_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__2_coeff_only(); + stbir__store_output_tiny(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_3_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__3_coeff_only(); + stbir__store_output_tiny(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_4_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_5_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__1_coeff_remnant(4); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_6_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__2_coeff_remnant(4); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_7_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + stbir__3_coeff_setup(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + stbir__3_coeff_remnant(4); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_8_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_9_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__1_coeff_remnant(8); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_10_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__2_coeff_remnant(8); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_11_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + stbir__3_coeff_setup(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__3_coeff_remnant(8); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_12_coeffs)( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + float const * hc = horizontal_coefficients; + stbir__4_coeff_start(); + stbir__4_coeff_continue_from_4(4); + stbir__4_coeff_continue_from_4(8); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod0 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 4 + 3 ) >> 2; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + hc += 4; + decode += STBIR__horizontal_channels * 4; + stbir__4_coeff_continue_from_4( 0 ); + --n; + } while ( n > 0 ); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod1 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 5 + 3 ) >> 2; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + hc += 4; + decode += STBIR__horizontal_channels * 4; + stbir__4_coeff_continue_from_4( 0 ); + --n; + } while ( n > 0 ); + stbir__1_coeff_remnant( 4 ); + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod2 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 6 + 3 ) >> 2; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + hc += 4; + decode += STBIR__horizontal_channels * 4; + stbir__4_coeff_continue_from_4( 0 ); + --n; + } while ( n > 0 ); + stbir__2_coeff_remnant( 4 ); + + stbir__store_output(); + } while ( output < output_end ); +} + +static void STBIR_chans( stbir__horizontal_gather_,_channels_with_n_coeffs_mod3 )( float * output_buffer, unsigned int output_sub_size, float const * decode_buffer, stbir__contributors const * horizontal_contributors, float const * horizontal_coefficients, int coefficient_width ) +{ + float const * output_end = output_buffer + output_sub_size * STBIR__horizontal_channels; + float STBIR_SIMD_STREAMOUT_PTR( * ) output = output_buffer; + stbir__3_coeff_setup(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + float const * decode = decode_buffer + horizontal_contributors->n0 * STBIR__horizontal_channels; + int n = ( ( horizontal_contributors->n1 - horizontal_contributors->n0 + 1 ) - 7 + 3 ) >> 2; + float const * hc = horizontal_coefficients; + + stbir__4_coeff_start(); + STBIR_SIMD_NO_UNROLL_LOOP_START + do { + hc += 4; + decode += STBIR__horizontal_channels * 4; + stbir__4_coeff_continue_from_4( 0 ); + --n; + } while ( n > 0 ); + stbir__3_coeff_remnant( 4 ); + + stbir__store_output(); + } while ( output < output_end ); +} + +static stbir__horizontal_gather_channels_func * STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_funcs)[4]= +{ + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod0), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod1), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod2), + STBIR_chans(stbir__horizontal_gather_,_channels_with_n_coeffs_mod3), +}; + +static stbir__horizontal_gather_channels_func * STBIR_chans(stbir__horizontal_gather_,_channels_funcs)[12]= +{ + STBIR_chans(stbir__horizontal_gather_,_channels_with_1_coeff), + STBIR_chans(stbir__horizontal_gather_,_channels_with_2_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_3_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_4_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_5_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_6_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_7_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_8_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_9_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_10_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_11_coeffs), + STBIR_chans(stbir__horizontal_gather_,_channels_with_12_coeffs), +}; + +#undef STBIR__horizontal_channels +#undef STB_IMAGE_RESIZE_DO_HORIZONTALS +#undef stbir__1_coeff_only +#undef stbir__1_coeff_remnant +#undef stbir__2_coeff_only +#undef stbir__2_coeff_remnant +#undef stbir__3_coeff_only +#undef stbir__3_coeff_remnant +#undef stbir__3_coeff_setup +#undef stbir__4_coeff_start +#undef stbir__4_coeff_continue_from_4 +#undef stbir__store_output +#undef stbir__store_output_tiny +#undef STBIR_chans + +#endif // HORIZONALS + +#undef STBIR_strs_join2 +#undef STBIR_strs_join1 + +#endif // STB_IMAGE_RESIZE_DO_HORIZONTALS/VERTICALS/CODERS + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_image_write.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_image_write.h new file mode 100644 index 0000000..e4b32ed --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_image_write.h @@ -0,0 +1,1724 @@ +/* stb_image_write - v1.16 - public domain - http://nothings.org/stb + writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio or a callback. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation; though providing a custom + zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that. + This library is designed for source code compactness and simplicity, + not optimal image file size or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can #define STBIW_MEMMOVE() to replace memmove() + You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function + for PNG compression (instead of the builtin one), it must have the following signature: + unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality); + The returned data will be freed with STBIW_FREE() (free() by default), + so it must be heap allocated with STBIW_MALLOC() (malloc() by default), + +UNICODE: + + If compiling for Windows and you wish to use Unicode filenames, compile + with + #define STBIW_WINDOWS_UTF8 + and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert + Windows wchar_t filenames to utf8. + +USAGE: + + There are five functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically + + There are also five equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can configure it with these global variables: + int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE + int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression + int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode + + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + PNG allows you to set the deflate compression level by setting the global + variable 'stbi_write_png_compression_level' (it defaults to 8). + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + + JPEG does ignore alpha channels in input data; quality is between 1 and 100. + Higher quality looks better but results in a bigger image. + JPEG baseline (no JPEG progressive). + +CREDITS: + + + Sean Barrett - PNG/BMP/TGA + Baldur Karlsson - HDR + Jean-Sebastien Guay - TGA monochrome + Tim Kelsey - misc enhancements + Alan Hickman - TGA RLE + Emmanuel Julien - initial file IO callback implementation + Jon Olick - original jo_jpeg.cpp code + Daniel Gibson - integrate JPEG, allow external zlib + Aarni Koskela - allow choosing PNG filter + + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + github:poppolopoppo + Patrick Boettcher + github:xeekworx + Cap Petschulat + Simon Rodriguez + Ivan Tikhonov + github:ignotion + Adam Schackart + Andrew Kensler + +LICENSE + + See end of file for license information. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#include + +// if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline' +#ifndef STBIWDEF +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#ifdef __cplusplus +#define STBIWDEF extern "C" +#else +#define STBIWDEF extern +#endif +#endif +#endif + +#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations +STBIWDEF int stbi_write_tga_with_rle; +STBIWDEF int stbi_write_png_compression_level; +STBIWDEF int stbi_write_force_png_filter; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); + +#ifdef STBIW_WINDOWS_UTF8 +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + +STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_png_compression_level = 8; +static int stbi_write_tga_with_rle = 1; +static int stbi_write_force_png_filter = -1; +#else +int stbi_write_png_compression_level = 8; +int stbi_write_tga_with_rle = 1; +int stbi_write_force_png_filter = -1; +#endif + +static int stbi__flip_vertically_on_write = 0; + +STBIWDEF void stbi_flip_vertically_on_write(int flag) +{ + stbi__flip_vertically_on_write = flag; +} + +typedef struct +{ + stbi_write_func *func; + void *context; + unsigned char buffer[64]; + int buf_used; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) +#ifdef __cplusplus +#define STBIW_EXTERN extern "C" +#else +#define STBIW_EXTERN extern +#endif +STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); + +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbiw__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) + return 0; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = stbiw__fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__write_flush(stbi__write_context *s) +{ + if (s->buf_used) { + s->func(s->context, &s->buffer, s->buf_used); + s->buf_used = 0; + } +} + +static void stbiw__putc(stbi__write_context *s, unsigned char c) +{ + s->func(s->context, &c, 1); +} + +static void stbiw__write1(stbi__write_context *s, unsigned char a) +{ + if ((size_t)s->buf_used + 1 > sizeof(s->buffer)) + stbiw__write_flush(s); + s->buffer[s->buf_used++] = a; +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + int n; + if ((size_t)s->buf_used + 3 > sizeof(s->buffer)) + stbiw__write_flush(s); + n = s->buf_used; + s->buf_used = n+3; + s->buffer[n+0] = a; + s->buffer[n+1] = b; + s->buffer[n+2] = c; +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + stbiw__write1(s, d[comp - 1]); + + switch (comp) { + case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case + case 1: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + stbiw__write1(s, d[0]); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + stbiw__write1(s, d[comp - 1]); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (stbi__flip_vertically_on_write) + vdir *= -1; + + if (vdir < 0) { + j_end = -1; j = y-1; + } else { + j_end = y; j = 0; + } + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + stbiw__write_flush(s); + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + if (comp != 4) { + // write RGB bitmap + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header + } else { + // RGBA bitmaps need a v4 header + // use BI_BITFIELDS mode with 32bpp and alpha mask + // (straight BI_RGB with alpha mask doesn't work in most readers) + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0, + "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444", + 'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header + 108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0); // bitmap V4 header + } +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + int jend, jdir; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + if (stbi__flip_vertically_on_write) { + j = 0; + jend = y; + jdir = 1; + } else { + j = y-1; + jend = -1; + jdir = -1; + } + for (; j != jend; j += jdir) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + stbiw__write1(s, header); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + stbiw__write1(s, header); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + stbiw__write_flush(s); + } + return 1; +} + +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +#ifndef STBI_WRITE_NO_STDIO + +static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + +#ifdef __STDC_LIB_EXT1__ + len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#else + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#endif + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)); + STBIW_FREE(scratch); + return 1; + } +} + +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +#ifndef STBIW_ZLIB_COMPRESS +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (void *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +#endif // STBIW_ZLIB_COMPRESS + +STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ +#ifdef STBIW_ZLIB_COMPRESS + // user provided a zlib compress implementation, use that + return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality); +#else // use builtin + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**)); + if (hash_table == NULL) + return NULL; + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) { best=d; bestloc=hlist[j]; } + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + // store uncompressed instead if compression was worse + if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) { + stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1 + for (j = 0; j < data_len;) { + int blocklen = data_len - j; + if (blocklen > 32767) blocklen = 32767; + stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression + stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN + stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN + stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8)); + memcpy(out+stbiw__sbn(out), data+j, blocklen); + stbiw__sbn(out) += blocklen; + j += blocklen; + } + } + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; } + s1 %= 65521; s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +#endif // STBIW_ZLIB_COMPRESS +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ +#ifdef STBIW_CRC32 + return STBIW_CRC32(buffer, len); +#else + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +#endif +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +// @OPTIMIZE: provide an option that always forces left-predict or paeth predict +static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n, int filter_type, signed char *line_buffer) +{ + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = (y != 0) ? mapping : firstmap; + int i; + int type = mymap[filter_type]; + unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y); + int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes; + + if (type==0) { + memcpy(line_buffer, z, width*n); + return; + } + + // first loop isn't optimized since it's just one pixel + for (i = 0; i < n; ++i) { + switch (type) { + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + } + switch (type) { + case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break; + case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break; + case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break; + case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } +} + +STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int force_filter = stbi_write_force_png_filter; + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int j,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + if (force_filter >= 5) { + force_filter = -1; + } + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + int filter_type; + if (force_filter > -1) { + filter_type = force_filter; + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer); + } else { // Estimate the best filter by running through all of them: + int best_filter = 0, best_filter_val = 0x7fffffff, est, i; + for (filter_type = 0; filter_type < 5; filter_type++) { + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer); + + // Estimate the entropy of the line using this filter; the less, the better. + est = 0; + for (i = 0; i < x*n; ++i) { + est += abs((signed char) line_buffer[i]); + } + if (est < best_filter_val) { + best_filter_val = est; + best_filter = filter_type; + } + } + if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer); + filter_type = best_filter; + } + } + // when we get here, filter_type contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) filter_type; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level); + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + + f = stbiw__fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + + +/* *************************************************************************** + * + * JPEG writer + * + * This is based on Jon Olick's jo_jpeg.cpp: + * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html + */ + +static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18, + 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 }; + +static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) { + int bitBuf = *bitBufP, bitCnt = *bitCntP; + bitCnt += bs[1]; + bitBuf |= bs[0] << (24 - bitCnt); + while(bitCnt >= 8) { + unsigned char c = (bitBuf >> 16) & 255; + stbiw__putc(s, c); + if(c == 255) { + stbiw__putc(s, 0); + } + bitBuf <<= 8; + bitCnt -= 8; + } + *bitBufP = bitBuf; + *bitCntP = bitCnt; +} + +static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) { + float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p; + float z1, z2, z3, z4, z5, z11, z13; + + float tmp0 = d0 + d7; + float tmp7 = d0 - d7; + float tmp1 = d1 + d6; + float tmp6 = d1 - d6; + float tmp2 = d2 + d5; + float tmp5 = d2 - d5; + float tmp3 = d3 + d4; + float tmp4 = d3 - d4; + + // Even part + float tmp10 = tmp0 + tmp3; // phase 2 + float tmp13 = tmp0 - tmp3; + float tmp11 = tmp1 + tmp2; + float tmp12 = tmp1 - tmp2; + + d0 = tmp10 + tmp11; // phase 3 + d4 = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * 0.707106781f; // c4 + d2 = tmp13 + z1; // phase 5 + d6 = tmp13 - z1; + + // Odd part + tmp10 = tmp4 + tmp5; // phase 2 + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + // The rotator is modified from fig 4-8 to avoid extra negations. + z5 = (tmp10 - tmp12) * 0.382683433f; // c6 + z2 = tmp10 * 0.541196100f + z5; // c2-c6 + z4 = tmp12 * 1.306562965f + z5; // c2+c6 + z3 = tmp11 * 0.707106781f; // c4 + + z11 = tmp7 + z3; // phase 5 + z13 = tmp7 - z3; + + *d5p = z13 + z2; // phase 6 + *d3p = z13 - z2; + *d1p = z11 + z4; + *d7p = z11 - z4; + + *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6; +} + +static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) { + int tmp1 = val < 0 ? -val : val; + val = val < 0 ? val-1 : val; + bits[1] = 1; + while(tmp1 >>= 1) { + ++bits[1]; + } + bits[0] = val & ((1<0)&&(DU[end0pos]==0); --end0pos) { + } + // end0pos = first element in reverse order !=0 + if(end0pos == 0) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + return DU[0]; + } + for(i = 1; i <= end0pos; ++i) { + int startpos = i; + int nrzeroes; + unsigned short bits[2]; + for (; DU[i]==0 && i<=end0pos; ++i) { + } + nrzeroes = i-startpos; + if ( nrzeroes >= 16 ) { + int lng = nrzeroes>>4; + int nrmarker; + for (nrmarker=1; nrmarker <= lng; ++nrmarker) + stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes); + nrzeroes &= 15; + } + stbiw__jpg_calcBits(DU[i], bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits); + } + if(end0pos != 63) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + } + return DU[0]; +} + +static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) { + // Constants that don't pollute global namespace + static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}; + static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d}; + static const unsigned char std_ac_luminance_values[] = { + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0}; + static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77}; + static const unsigned char std_ac_chrominance_values[] = { + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + // Huffman tables + static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}}; + static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}}; + static const unsigned short YAC_HT[256][2] = { + {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const unsigned short UVAC_HT[256][2] = { + {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22, + 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99}; + static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99, + 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99}; + static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, + 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; + + int row, col, i, k, subsample; + float fdtbl_Y[64], fdtbl_UV[64]; + unsigned char YTable[64], UVTable[64]; + + if(!data || !width || !height || comp > 4 || comp < 1) { + return 0; + } + + quality = quality ? quality : 90; + subsample = quality <= 90 ? 1 : 0; + quality = quality < 1 ? 1 : quality > 100 ? 100 : quality; + quality = quality < 50 ? 5000 / quality : 200 - quality * 2; + + for(i = 0; i < 64; ++i) { + int uvti, yti = (YQT[i]*quality+50)/100; + YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti); + uvti = (UVQT[i]*quality+50)/100; + UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti); + } + + for(row = 0, k = 0; row < 8; ++row) { + for(col = 0; col < 8; ++col, ++k) { + fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + } + } + + // Write Headers + { + static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 }; + static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 }; + const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width), + 3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; + s->func(s->context, (void*)head0, sizeof(head0)); + s->func(s->context, (void*)YTable, sizeof(YTable)); + stbiw__putc(s, 1); + s->func(s->context, UVTable, sizeof(UVTable)); + s->func(s->context, (void*)head1, sizeof(head1)); + s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1); + s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values)); + stbiw__putc(s, 0x10); // HTYACinfo + s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1); + s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values)); + stbiw__putc(s, 1); // HTUDCinfo + s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values)); + stbiw__putc(s, 0x11); // HTUACinfo + s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values)); + s->func(s->context, (void*)head2, sizeof(head2)); + } + + // Encode 8x8 macroblocks + { + static const unsigned short fillBits[] = {0x7F, 7}; + int DCY=0, DCU=0, DCV=0; + int bitBuf=0, bitCnt=0; + // comp == 2 is grey+alpha (alpha is ignored) + int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0; + const unsigned char *dataR = (const unsigned char *)data; + const unsigned char *dataG = dataR + ofsG; + const unsigned char *dataB = dataR + ofsB; + int x, y, pos; + if(subsample) { + for(y = 0; y < height; y += 16) { + for(x = 0; x < width; x += 16) { + float Y[256], U[256], V[256]; + for(row = y, pos = 0; row < y+16; ++row) { + // row >= height => use last input row + int clamped_row = (row < height) ? row : height - 1; + int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; + for(col = x; col < x+16; ++col, ++pos) { + // if col >= width => use pixel from last input column + int p = base_p + ((col < width) ? col : (width-1))*comp; + float r = dataR[p], g = dataG[p], b = dataB[p]; + Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128; + U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b; + V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b; + } + } + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + + // subsample U,V + { + float subU[64], subV[64]; + int yy, xx; + for(yy = 0, pos = 0; yy < 8; ++yy) { + for(xx = 0; xx < 8; ++xx, ++pos) { + int j = yy*32+xx*2; + subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f; + subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f; + } + } + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + } + } else { + for(y = 0; y < height; y += 8) { + for(x = 0; x < width; x += 8) { + float Y[64], U[64], V[64]; + for(row = y, pos = 0; row < y+8; ++row) { + // row >= height => use last input row + int clamped_row = (row < height) ? row : height - 1; + int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; + for(col = x; col < x+8; ++col, ++pos) { + // if col >= width => use pixel from last input column + int p = base_p + ((col < width) ? col : (width-1))*comp; + float r = dataR[p], g = dataG[p], b = dataB[p]; + Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128; + U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b; + V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b; + } + } + + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + } + + // Do the bit alignment of the EOI marker + stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits); + } + + // EOI + stbiw__putc(s, 0xFF); + stbiw__putc(s, 0xD9); + + return 1; +} + +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); +} + + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.16 (2021-07-11) + make Deflate code emit uncompressed blocks when it would otherwise expand + support writing BMPs with alpha channel + 1.15 (2020-07-13) unknown + 1.14 (2020-02-02) updated JPEG writer to downsample chroma channels + 1.13 + 1.12 + 1.11 (2019-08-11) + + 1.10 (2019-02-07) + support utf8 filenames in Windows; fix warnings and platform ifdefs + 1.09 (2018-02-11) + fix typo in zlib quality API, improve STB_I_W_STATIC in C++ + 1.08 (2018-01-29) + add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter + 1.07 (2017-07-24) + doc fix + 1.06 (2017-07-23) + writing JPEG (using Jon Olick's code) + 1.05 ??? + 1.04 (2017-03-03) + monochrome BMP expansion + 1.03 ??? + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_include.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_include.h new file mode 100644 index 0000000..c5db201 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_include.h @@ -0,0 +1,295 @@ +// stb_include.h - v0.02 - parse and process #include directives - public domain +// +// To build this, in one source file that includes this file do +// #define STB_INCLUDE_IMPLEMENTATION +// +// This program parses a string and replaces lines of the form +// #include "foo" +// with the contents of a file named "foo". It also embeds the +// appropriate #line directives. Note that all include files must +// reside in the location specified in the path passed to the API; +// it does not check multiple directories. +// +// If the string contains a line of the form +// #inject +// then it will be replaced with the contents of the string 'inject' passed to the API. +// +// Options: +// +// Define STB_INCLUDE_LINE_GLSL to get GLSL-style #line directives +// which use numbers instead of filenames. +// +// Define STB_INCLUDE_LINE_NONE to disable output of #line directives. +// +// Standard libraries: +// +// stdio.h FILE, fopen, fclose, fseek, ftell +// stdlib.h malloc, realloc, free +// string.h strcpy, strncmp, memcpy +// +// Credits: +// +// Written by Sean Barrett. +// +// Fixes: +// Michal Klos + +#ifndef STB_INCLUDE_STB_INCLUDE_H +#define STB_INCLUDE_STB_INCLUDE_H + +// Do include-processing on the string 'str'. To free the return value, pass it to free() +char *stb_include_string(char *str, char *inject, char *path_to_includes, char *filename_for_line_directive, char error[256]); + +// Concatenate the strings 'strs' and do include-processing on the result. To free the return value, pass it to free() +char *stb_include_strings(char **strs, int count, char *inject, char *path_to_includes, char *filename_for_line_directive, char error[256]); + +// Load the file 'filename' and do include-processing on the string therein. note that +// 'filename' is opened directly; 'path_to_includes' is not used. To free the return value, pass it to free() +char *stb_include_file(char *filename, char *inject, char *path_to_includes, char error[256]); + +#endif + + +#ifdef STB_INCLUDE_IMPLEMENTATION + +#include +#include +#include + +static char *stb_include_load_file(char *filename, size_t *plen) +{ + char *text; + size_t len; + FILE *f = fopen(filename, "rb"); + if (f == 0) return 0; + fseek(f, 0, SEEK_END); + len = (size_t) ftell(f); + if (plen) *plen = len; + text = (char *) malloc(len+1); + if (text == 0) return 0; + fseek(f, 0, SEEK_SET); + fread(text, 1, len, f); + fclose(f); + text[len] = 0; + return text; +} + +typedef struct +{ + int offset; + int end; + char *filename; + int next_line_after; +} include_info; + +static include_info *stb_include_append_include(include_info *array, int len, int offset, int end, char *filename, int next_line) +{ + include_info *z = (include_info *) realloc(array, sizeof(*z) * (len+1)); + z[len].offset = offset; + z[len].end = end; + z[len].filename = filename; + z[len].next_line_after = next_line; + return z; +} + +static void stb_include_free_includes(include_info *array, int len) +{ + int i; + for (i=0; i < len; ++i) + free(array[i].filename); + free(array); +} + +static int stb_include_isspace(int ch) +{ + return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'); +} + +// find location of all #include and #inject +static int stb_include_find_includes(char *text, include_info **plist) +{ + int line_count = 1; + int inc_count = 0; + char *s = text, *start; + include_info *list = NULL; + while (*s) { + // parse is always at start of line when we reach here + start = s; + while (*s == ' ' || *s == '\t') + ++s; + if (*s == '#') { + ++s; + while (*s == ' ' || *s == '\t') + ++s; + if (0==strncmp(s, "include", 7) && stb_include_isspace(s[7])) { + s += 7; + while (*s == ' ' || *s == '\t') + ++s; + if (*s == '"') { + char *t = ++s; + while (*t != '"' && *t != '\n' && *t != '\r' && *t != 0) + ++t; + if (*t == '"') { + char *filename = (char *) malloc(t-s+1); + memcpy(filename, s, t-s); + filename[t-s] = 0; + s=t; + while (*s != '\r' && *s != '\n' && *s != 0) + ++s; + // s points to the newline, so s-start is everything except the newline + list = stb_include_append_include(list, inc_count++, start-text, s-text, filename, line_count+1); + } + } + } else if (0==strncmp(s, "inject", 6) && (stb_include_isspace(s[6]) || s[6]==0)) { + while (*s != '\r' && *s != '\n' && *s != 0) + ++s; + list = stb_include_append_include(list, inc_count++, start-text, s-text, NULL, line_count+1); + } + } + while (*s != '\r' && *s != '\n' && *s != 0) + ++s; + if (*s == '\r' || *s == '\n') { + s = s + (s[0] + s[1] == '\r' + '\n' ? 2 : 1); + } + ++line_count; + } + *plist = list; + return inc_count; +} + +// avoid dependency on sprintf() +static void stb_include_itoa(char str[9], int n) +{ + int i; + for (i=0; i < 8; ++i) + str[i] = ' '; + str[i] = 0; + + for (i=1; i < 8; ++i) { + str[7-i] = '0' + (n % 10); + n /= 10; + if (n == 0) + break; + } +} + +static char *stb_include_append(char *str, size_t *curlen, char *addstr, size_t addlen) +{ + str = (char *) realloc(str, *curlen + addlen); + memcpy(str + *curlen, addstr, addlen); + *curlen += addlen; + return str; +} + +char *stb_include_string(char *str, char *inject, char *path_to_includes, char *filename, char error[256]) +{ + char temp[4096]; + include_info *inc_list; + int i, num = stb_include_find_includes(str, &inc_list); + size_t source_len = strlen(str); + char *text=0; + size_t textlen=0, last=0; + for (i=0; i < num; ++i) { + text = stb_include_append(text, &textlen, str+last, inc_list[i].offset - last); + // write out line directive for the include + #ifndef STB_INCLUDE_LINE_NONE + #ifdef STB_INCLUDE_LINE_GLSL + if (textlen != 0) // GLSL #version must appear first, so don't put a #line at the top + #endif + { + strcpy(temp, "#line "); + stb_include_itoa(temp+6, 1); + strcat(temp, " "); + #ifdef STB_INCLUDE_LINE_GLSL + stb_include_itoa(temp+15, i+1); + #else + strcat(temp, "\""); + if (inc_list[i].filename == 0) + strcmp(temp, "INJECT"); + else + strcat(temp, inc_list[i].filename); + strcat(temp, "\""); + #endif + strcat(temp, "\n"); + text = stb_include_append(text, &textlen, temp, strlen(temp)); + } + #endif + if (inc_list[i].filename == 0) { + if (inject != 0) + text = stb_include_append(text, &textlen, inject, strlen(inject)); + } else { + char *inc; + strcpy(temp, path_to_includes); + strcat(temp, "/"); + strcat(temp, inc_list[i].filename); + inc = stb_include_file(temp, inject, path_to_includes, error); + if (inc == NULL) { + stb_include_free_includes(inc_list, num); + return NULL; + } + text = stb_include_append(text, &textlen, inc, strlen(inc)); + free(inc); + } + // write out line directive + #ifndef STB_INCLUDE_LINE_NONE + strcpy(temp, "\n#line "); + stb_include_itoa(temp+6, inc_list[i].next_line_after); + strcat(temp, " "); + #ifdef STB_INCLUDE_LINE_GLSL + stb_include_itoa(temp+15, 0); + #else + strcat(temp, filename != 0 ? filename : "source-file"); + #endif + text = stb_include_append(text, &textlen, temp, strlen(temp)); + // no newlines, because we kept the #include newlines, which will get appended next + #endif + last = inc_list[i].end; + } + text = stb_include_append(text, &textlen, str+last, source_len - last + 1); // append '\0' + stb_include_free_includes(inc_list, num); + return text; +} + +char *stb_include_strings(char **strs, int count, char *inject, char *path_to_includes, char *filename, char error[256]) +{ + char *text; + char *result; + int i; + size_t length=0; + for (i=0; i < count; ++i) + length += strlen(strs[i]); + text = (char *) malloc(length+1); + length = 0; + for (i=0; i < count; ++i) { + strcpy(text + length, strs[i]); + length += strlen(strs[i]); + } + result = stb_include_string(text, inject, path_to_includes, filename, error); + free(text); + return result; +} + +char *stb_include_file(char *filename, char *inject, char *path_to_includes, char error[256]) +{ + size_t len; + char *result; + char *text = stb_include_load_file(filename, &len); + if (text == NULL) { + strcpy(error, "Error: couldn't load '"); + strcat(error, filename); + strcat(error, "'"); + return 0; + } + result = stb_include_string(text, inject, path_to_includes, filename, error); + free(text); + return result; +} + +#if 0 // @TODO, GL_ARB_shader_language_include-style system that doesn't touch filesystem +char *stb_include_preloaded(char *str, char *inject, char *includes[][2], char error[256]) +{ + +} +#endif + +#endif // STB_INCLUDE_IMPLEMENTATION diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_leakcheck.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_leakcheck.h new file mode 100644 index 0000000..19ee6e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_leakcheck.h @@ -0,0 +1,194 @@ +// stb_leakcheck.h - v0.6 - quick & dirty malloc leak-checking - public domain +// LICENSE +// +// See end of file. + +#ifdef STB_LEAKCHECK_IMPLEMENTATION +#undef STB_LEAKCHECK_IMPLEMENTATION // don't implement more than once + +// if we've already included leakcheck before, undefine the macros +#ifdef malloc +#undef malloc +#undef free +#undef realloc +#endif + +#ifndef STB_LEAKCHECK_OUTPUT_PIPE +#define STB_LEAKCHECK_OUTPUT_PIPE stdout +#endif + +#include +#include +#include +#include +#include +typedef struct malloc_info stb_leakcheck_malloc_info; + +struct malloc_info +{ + const char *file; + int line; + size_t size; + stb_leakcheck_malloc_info *next,*prev; +}; + +static stb_leakcheck_malloc_info *mi_head; + +void *stb_leakcheck_malloc(size_t sz, const char *file, int line) +{ + stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) malloc(sz + sizeof(*mi)); + if (mi == NULL) return mi; + mi->file = file; + mi->line = line; + mi->next = mi_head; + if (mi_head) + mi->next->prev = mi; + mi->prev = NULL; + mi->size = (int) sz; + mi_head = mi; + return mi+1; +} + +void stb_leakcheck_free(void *ptr) +{ + if (ptr != NULL) { + stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1; + mi->size = ~mi->size; + #ifndef STB_LEAKCHECK_SHOWALL + if (mi->prev == NULL) { + assert(mi_head == mi); + mi_head = mi->next; + } else + mi->prev->next = mi->next; + if (mi->next) + mi->next->prev = mi->prev; + free(mi); + #endif + } +} + +void *stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line) +{ + if (ptr == NULL) { + return stb_leakcheck_malloc(sz, file, line); + } else if (sz == 0) { + stb_leakcheck_free(ptr); + return NULL; + } else { + stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1; + if (sz <= mi->size) + return ptr; + else { + #ifdef STB_LEAKCHECK_REALLOC_PRESERVE_MALLOC_FILELINE + void *q = stb_leakcheck_malloc(sz, mi->file, mi->line); + #else + void *q = stb_leakcheck_malloc(sz, file, line); + #endif + if (q) { + memcpy(q, ptr, mi->size); + stb_leakcheck_free(ptr); + } + return q; + } + } +} + +static void stblkck_internal_print(const char *reason, stb_leakcheck_malloc_info *mi) +{ +#if defined(_MSC_VER) && _MSC_VER < 1900 // 1900=VS 2015 + // Compilers that use the old MS C runtime library don't have %zd + // and the older ones don't even have %lld either... however, the old compilers + // without "long long" don't support 64-bit targets either, so here's the + // compromise: + #if _MSC_VER < 1400 // before VS 2005 + fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %8d bytes at %p\n", reason, mi->file, mi->line, (int)mi->size, (void*)(mi+1)); + #else + fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %16lld bytes at %p\n", reason, mi->file, mi->line, (long long)mi->size, (void*)(mi+1)); + #endif +#else + // Assume we have %zd on other targets. + #ifdef __MINGW32__ + __mingw_fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1)); + #else + fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1)); + #endif +#endif +} + +void stb_leakcheck_dumpmem(void) +{ + stb_leakcheck_malloc_info *mi = mi_head; + while (mi) { + if ((ptrdiff_t) mi->size >= 0) + stblkck_internal_print("LEAKED", mi); + mi = mi->next; + } + #ifdef STB_LEAKCHECK_SHOWALL + mi = mi_head; + while (mi) { + if ((ptrdiff_t) mi->size < 0) + stblkck_internal_print("FREED ", mi); + mi = mi->next; + } + #endif +} +#endif // STB_LEAKCHECK_IMPLEMENTATION + +#if !defined(INCLUDE_STB_LEAKCHECK_H) || !defined(malloc) +#define INCLUDE_STB_LEAKCHECK_H + +#include // we want to define the macros *after* stdlib to avoid a slew of errors + +#define malloc(sz) stb_leakcheck_malloc(sz, __FILE__, __LINE__) +#define free(p) stb_leakcheck_free(p) +#define realloc(p,sz) stb_leakcheck_realloc(p,sz, __FILE__, __LINE__) + +extern void * stb_leakcheck_malloc(size_t sz, const char *file, int line); +extern void * stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line); +extern void stb_leakcheck_free(void *ptr); +extern void stb_leakcheck_dumpmem(void); + +#endif // INCLUDE_STB_LEAKCHECK_H + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_perlin.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_perlin.h new file mode 100644 index 0000000..47cb9a4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_perlin.h @@ -0,0 +1,428 @@ +// stb_perlin.h - v0.5 - perlin noise +// public domain single-file C implementation by Sean Barrett +// +// LICENSE +// +// See end of file. +// +// +// to create the implementation, +// #define STB_PERLIN_IMPLEMENTATION +// in *one* C/CPP file that includes this file. +// +// +// Documentation: +// +// float stb_perlin_noise3( float x, +// float y, +// float z, +// int x_wrap=0, +// int y_wrap=0, +// int z_wrap=0) +// +// This function computes a random value at the coordinate (x,y,z). +// Adjacent random values are continuous but the noise fluctuates +// its randomness with period 1, i.e. takes on wholly unrelated values +// at integer points. Specifically, this implements Ken Perlin's +// revised noise function from 2002. +// +// The "wrap" parameters can be used to create wraparound noise that +// wraps at powers of two. The numbers MUST be powers of two. Specify +// 0 to mean "don't care". (The noise always wraps every 256 due +// details of the implementation, even if you ask for larger or no +// wrapping.) +// +// float stb_perlin_noise3_seed( float x, +// float y, +// float z, +// int x_wrap=0, +// int y_wrap=0, +// int z_wrap=0, +// int seed) +// +// As above, but 'seed' selects from multiple different variations of the +// noise function. The current implementation only uses the bottom 8 bits +// of 'seed', but possibly in the future more bits will be used. +// +// +// Fractal Noise: +// +// Three common fractal noise functions are included, which produce +// a wide variety of nice effects depending on the parameters +// provided. Note that each function will call stb_perlin_noise3 +// 'octaves' times, so this parameter will affect runtime. +// +// float stb_perlin_ridge_noise3(float x, float y, float z, +// float lacunarity, float gain, float offset, int octaves) +// +// float stb_perlin_fbm_noise3(float x, float y, float z, +// float lacunarity, float gain, int octaves) +// +// float stb_perlin_turbulence_noise3(float x, float y, float z, +// float lacunarity, float gain, int octaves) +// +// Typical values to start playing with: +// octaves = 6 -- number of "octaves" of noise3() to sum +// lacunarity = ~ 2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output) +// gain = 0.5 -- relative weighting applied to each successive octave +// offset = 1.0? -- used to invert the ridges, may need to be larger, not sure +// +// +// Contributors: +// Jack Mott - additional noise functions +// Jordan Peck - seeded noise +// + + +#ifdef __cplusplus +extern "C" { +#endif +extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_noise3_seed(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed); +extern float stb_perlin_ridge_noise3(float x, float y, float z, float lacunarity, float gain, float offset, int octaves); +extern float stb_perlin_fbm_noise3(float x, float y, float z, float lacunarity, float gain, int octaves); +extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves); +extern float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed); +#ifdef __cplusplus +} +#endif + +#ifdef STB_PERLIN_IMPLEMENTATION + +#include // fabs() + +// not same permutation table as Perlin's reference to avoid copyright issues; +// Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/ +static unsigned char stb__perlin_randtab[512] = +{ + 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, + 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, + 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, + 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, + 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, + 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, + 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, + 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, + 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, + 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, + 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, + 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, + 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, + 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, + 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, + 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, + + // and a second copy so we don't need an extra mask or static initializer + 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, + 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, + 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, + 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, + 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, + 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, + 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, + 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, + 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, + 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, + 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, + 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, + 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, + 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, + 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, + 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, +}; + + +// perlin's gradient has 12 cases so some get used 1/16th of the time +// and some 2/16ths. We reduce bias by changing those fractions +// to 5/64ths and 6/64ths + +// this array is designed to match the previous implementation +// of gradient hash: indices[stb__perlin_randtab[i]&63] +static unsigned char stb__perlin_randtab_grad_idx[512] = +{ + 7, 9, 5, 0, 11, 1, 6, 9, 3, 9, 11, 1, 8, 10, 4, 7, + 8, 6, 1, 5, 3, 10, 9, 10, 0, 8, 4, 1, 5, 2, 7, 8, + 7, 11, 9, 10, 1, 0, 4, 7, 5, 0, 11, 6, 1, 4, 2, 8, + 8, 10, 4, 9, 9, 2, 5, 7, 9, 1, 7, 2, 2, 6, 11, 5, + 5, 4, 6, 9, 0, 1, 1, 0, 7, 6, 9, 8, 4, 10, 3, 1, + 2, 8, 8, 9, 10, 11, 5, 11, 11, 2, 6, 10, 3, 4, 2, 4, + 9, 10, 3, 2, 6, 3, 6, 10, 5, 3, 4, 10, 11, 2, 9, 11, + 1, 11, 10, 4, 9, 4, 11, 0, 4, 11, 4, 0, 0, 0, 7, 6, + 10, 4, 1, 3, 11, 5, 3, 4, 2, 9, 1, 3, 0, 1, 8, 0, + 6, 7, 8, 7, 0, 4, 6, 10, 8, 2, 3, 11, 11, 8, 0, 2, + 4, 8, 3, 0, 0, 10, 6, 1, 2, 2, 4, 5, 6, 0, 1, 3, + 11, 9, 5, 5, 9, 6, 9, 8, 3, 8, 1, 8, 9, 6, 9, 11, + 10, 7, 5, 6, 5, 9, 1, 3, 7, 0, 2, 10, 11, 2, 6, 1, + 3, 11, 7, 7, 2, 1, 7, 3, 0, 8, 1, 1, 5, 0, 6, 10, + 11, 11, 0, 2, 7, 0, 10, 8, 3, 5, 7, 1, 11, 1, 0, 7, + 9, 0, 11, 5, 10, 3, 2, 3, 5, 9, 7, 9, 8, 4, 6, 5, + + // and a second copy so we don't need an extra mask or static initializer + 7, 9, 5, 0, 11, 1, 6, 9, 3, 9, 11, 1, 8, 10, 4, 7, + 8, 6, 1, 5, 3, 10, 9, 10, 0, 8, 4, 1, 5, 2, 7, 8, + 7, 11, 9, 10, 1, 0, 4, 7, 5, 0, 11, 6, 1, 4, 2, 8, + 8, 10, 4, 9, 9, 2, 5, 7, 9, 1, 7, 2, 2, 6, 11, 5, + 5, 4, 6, 9, 0, 1, 1, 0, 7, 6, 9, 8, 4, 10, 3, 1, + 2, 8, 8, 9, 10, 11, 5, 11, 11, 2, 6, 10, 3, 4, 2, 4, + 9, 10, 3, 2, 6, 3, 6, 10, 5, 3, 4, 10, 11, 2, 9, 11, + 1, 11, 10, 4, 9, 4, 11, 0, 4, 11, 4, 0, 0, 0, 7, 6, + 10, 4, 1, 3, 11, 5, 3, 4, 2, 9, 1, 3, 0, 1, 8, 0, + 6, 7, 8, 7, 0, 4, 6, 10, 8, 2, 3, 11, 11, 8, 0, 2, + 4, 8, 3, 0, 0, 10, 6, 1, 2, 2, 4, 5, 6, 0, 1, 3, + 11, 9, 5, 5, 9, 6, 9, 8, 3, 8, 1, 8, 9, 6, 9, 11, + 10, 7, 5, 6, 5, 9, 1, 3, 7, 0, 2, 10, 11, 2, 6, 1, + 3, 11, 7, 7, 2, 1, 7, 3, 0, 8, 1, 1, 5, 0, 6, 10, + 11, 11, 0, 2, 7, 0, 10, 8, 3, 5, 7, 1, 11, 1, 0, 7, + 9, 0, 11, 5, 10, 3, 2, 3, 5, 9, 7, 9, 8, 4, 6, 5, +}; + +static float stb__perlin_lerp(float a, float b, float t) +{ + return a + (b-a) * t; +} + +static int stb__perlin_fastfloor(float a) +{ + int ai = (int) a; + return (a < ai) ? ai-1 : ai; +} + +// different grad function from Perlin's, but easy to modify to match reference +static float stb__perlin_grad(int grad_idx, float x, float y, float z) +{ + static float basis[12][4] = + { + { 1, 1, 0 }, + { -1, 1, 0 }, + { 1,-1, 0 }, + { -1,-1, 0 }, + { 1, 0, 1 }, + { -1, 0, 1 }, + { 1, 0,-1 }, + { -1, 0,-1 }, + { 0, 1, 1 }, + { 0,-1, 1 }, + { 0, 1,-1 }, + { 0,-1,-1 }, + }; + + float *grad = basis[grad_idx]; + return grad[0]*x + grad[1]*y + grad[2]*z; +} + +float stb_perlin_noise3_internal(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed) +{ + float u,v,w; + float n000,n001,n010,n011,n100,n101,n110,n111; + float n00,n01,n10,n11; + float n0,n1; + + unsigned int x_mask = (x_wrap-1) & 255; + unsigned int y_mask = (y_wrap-1) & 255; + unsigned int z_mask = (z_wrap-1) & 255; + int px = stb__perlin_fastfloor(x); + int py = stb__perlin_fastfloor(y); + int pz = stb__perlin_fastfloor(z); + int x0 = px & x_mask, x1 = (px+1) & x_mask; + int y0 = py & y_mask, y1 = (py+1) & y_mask; + int z0 = pz & z_mask, z1 = (pz+1) & z_mask; + int r0,r1, r00,r01,r10,r11; + + #define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a) + + x -= px; u = stb__perlin_ease(x); + y -= py; v = stb__perlin_ease(y); + z -= pz; w = stb__perlin_ease(z); + + r0 = stb__perlin_randtab[x0+seed]; + r1 = stb__perlin_randtab[x1+seed]; + + r00 = stb__perlin_randtab[r0+y0]; + r01 = stb__perlin_randtab[r0+y1]; + r10 = stb__perlin_randtab[r1+y0]; + r11 = stb__perlin_randtab[r1+y1]; + + n000 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z0], x , y , z ); + n001 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z1], x , y , z-1 ); + n010 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z0], x , y-1, z ); + n011 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z1], x , y-1, z-1 ); + n100 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z0], x-1, y , z ); + n101 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z1], x-1, y , z-1 ); + n110 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z0], x-1, y-1, z ); + n111 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z1], x-1, y-1, z-1 ); + + n00 = stb__perlin_lerp(n000,n001,w); + n01 = stb__perlin_lerp(n010,n011,w); + n10 = stb__perlin_lerp(n100,n101,w); + n11 = stb__perlin_lerp(n110,n111,w); + + n0 = stb__perlin_lerp(n00,n01,v); + n1 = stb__perlin_lerp(n10,n11,v); + + return stb__perlin_lerp(n0,n1,u); +} + +float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap) +{ + return stb_perlin_noise3_internal(x,y,z,x_wrap,y_wrap,z_wrap,0); +} + +float stb_perlin_noise3_seed(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed) +{ + return stb_perlin_noise3_internal(x,y,z,x_wrap,y_wrap,z_wrap, (unsigned char) seed); +} + +float stb_perlin_ridge_noise3(float x, float y, float z, float lacunarity, float gain, float offset, int octaves) +{ + int i; + float frequency = 1.0f; + float prev = 1.0f; + float amplitude = 0.5f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + float r = stb_perlin_noise3_internal(x*frequency,y*frequency,z*frequency,0,0,0,(unsigned char)i); + r = offset - (float) fabs(r); + r = r*r; + sum += r*amplitude*prev; + prev = r; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_fbm_noise3(float x, float y, float z, float lacunarity, float gain, int octaves) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + sum += stb_perlin_noise3_internal(x*frequency,y*frequency,z*frequency,0,0,0,(unsigned char)i)*amplitude; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + float r = stb_perlin_noise3_internal(x*frequency,y*frequency,z*frequency,0,0,0,(unsigned char)i)*amplitude; + sum += (float) fabs(r); + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed) +{ + float u,v,w; + float n000,n001,n010,n011,n100,n101,n110,n111; + float n00,n01,n10,n11; + float n0,n1; + + int px = stb__perlin_fastfloor(x); + int py = stb__perlin_fastfloor(y); + int pz = stb__perlin_fastfloor(z); + int x_wrap2 = (x_wrap ? x_wrap : 256); + int y_wrap2 = (y_wrap ? y_wrap : 256); + int z_wrap2 = (z_wrap ? z_wrap : 256); + int x0 = px % x_wrap2, x1; + int y0 = py % y_wrap2, y1; + int z0 = pz % z_wrap2, z1; + int r0,r1, r00,r01,r10,r11; + + if (x0 < 0) x0 += x_wrap2; + if (y0 < 0) y0 += y_wrap2; + if (z0 < 0) z0 += z_wrap2; + x1 = (x0+1) % x_wrap2; + y1 = (y0+1) % y_wrap2; + z1 = (z0+1) % z_wrap2; + + #define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a) + + x -= px; u = stb__perlin_ease(x); + y -= py; v = stb__perlin_ease(y); + z -= pz; w = stb__perlin_ease(z); + + r0 = stb__perlin_randtab[x0]; + r0 = stb__perlin_randtab[r0+seed]; + r1 = stb__perlin_randtab[x1]; + r1 = stb__perlin_randtab[r1+seed]; + + r00 = stb__perlin_randtab[r0+y0]; + r01 = stb__perlin_randtab[r0+y1]; + r10 = stb__perlin_randtab[r1+y0]; + r11 = stb__perlin_randtab[r1+y1]; + + n000 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z0], x , y , z ); + n001 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z1], x , y , z-1 ); + n010 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z0], x , y-1, z ); + n011 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z1], x , y-1, z-1 ); + n100 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z0], x-1, y , z ); + n101 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z1], x-1, y , z-1 ); + n110 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z0], x-1, y-1, z ); + n111 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z1], x-1, y-1, z-1 ); + + n00 = stb__perlin_lerp(n000,n001,w); + n01 = stb__perlin_lerp(n010,n011,w); + n10 = stb__perlin_lerp(n100,n101,w); + n11 = stb__perlin_lerp(n110,n111,w); + + n0 = stb__perlin_lerp(n00,n01,v); + n1 = stb__perlin_lerp(n10,n11,v); + + return stb__perlin_lerp(n0,n1,u); +} +#endif // STB_PERLIN_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_rect_pack.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_rect_pack.h new file mode 100644 index 0000000..6a633ce --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_rect_pack.h @@ -0,0 +1,623 @@ +// stb_rect_pack.h - v1.01 - public domain - rectangle packing +// Sean Barrett 2014 +// +// Useful for e.g. packing rectangular textures into an atlas. +// Does not do rotation. +// +// Before #including, +// +// #define STB_RECT_PACK_IMPLEMENTATION +// +// in the file that you want to have the implementation. +// +// Not necessarily the awesomest packing method, but better than +// the totally naive one in stb_truetype (which is primarily what +// this is meant to replace). +// +// Has only had a few tests run, may have issues. +// +// More docs to come. +// +// No memory allocations; uses qsort() and assert() from stdlib. +// Can override those by defining STBRP_SORT and STBRP_ASSERT. +// +// This library currently uses the Skyline Bottom-Left algorithm. +// +// Please note: better rectangle packers are welcome! Please +// implement them to the same API, but with a different init +// function. +// +// Credits +// +// Library +// Sean Barrett +// Minor features +// Martins Mozeiko +// github:IntellectualKitty +// +// Bugfixes / warning fixes +// Jeremy Jaussaud +// Fabian Giesen +// +// Version history: +// +// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section +// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles +// 0.99 (2019-02-07) warning fixes +// 0.11 (2017-03-03) return packing success/fail result +// 0.10 (2016-10-25) remove cast-away-const to avoid warnings +// 0.09 (2016-08-27) fix compiler warnings +// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) +// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) +// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort +// 0.05: added STBRP_ASSERT to allow replacing assert +// 0.04: fixed minor bug in STBRP_LARGE_RECTS support +// 0.01: initial release +// +// LICENSE +// +// See end of file for license information. + +////////////////////////////////////////////////////////////////////////////// +// +// INCLUDE SECTION +// + +#ifndef STB_INCLUDE_STB_RECT_PACK_H +#define STB_INCLUDE_STB_RECT_PACK_H + +#define STB_RECT_PACK_VERSION 1 + +#ifdef STBRP_STATIC +#define STBRP_DEF static +#else +#define STBRP_DEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct stbrp_context stbrp_context; +typedef struct stbrp_node stbrp_node; +typedef struct stbrp_rect stbrp_rect; + +typedef int stbrp_coord; + +#define STBRP__MAXVAL 0x7fffffff +// Mostly for internal use, but this is the maximum supported coordinate value. + +STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); +// Assign packed locations to rectangles. The rectangles are of type +// 'stbrp_rect' defined below, stored in the array 'rects', and there +// are 'num_rects' many of them. +// +// Rectangles which are successfully packed have the 'was_packed' flag +// set to a non-zero value and 'x' and 'y' store the minimum location +// on each axis (i.e. bottom-left in cartesian coordinates, top-left +// if you imagine y increasing downwards). Rectangles which do not fit +// have the 'was_packed' flag set to 0. +// +// You should not try to access the 'rects' array from another thread +// while this function is running, as the function temporarily reorders +// the array while it executes. +// +// To pack into another rectangle, you need to call stbrp_init_target +// again. To continue packing into the same rectangle, you can call +// this function again. Calling this multiple times with multiple rect +// arrays will probably produce worse packing results than calling it +// a single time with the full rectangle array, but the option is +// available. +// +// The function returns 1 if all of the rectangles were successfully +// packed and 0 otherwise. + +struct stbrp_rect +{ + // reserved for your use: + int id; + + // input: + stbrp_coord w, h; + + // output: + stbrp_coord x, y; + int was_packed; // non-zero if valid packing + +}; // 16 bytes, nominally + + +STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); +// Initialize a rectangle packer to: +// pack a rectangle that is 'width' by 'height' in dimensions +// using temporary storage provided by the array 'nodes', which is 'num_nodes' long +// +// You must call this function every time you start packing into a new target. +// +// There is no "shutdown" function. The 'nodes' memory must stay valid for +// the following stbrp_pack_rects() call (or calls), but can be freed after +// the call (or calls) finish. +// +// Note: to guarantee best results, either: +// 1. make sure 'num_nodes' >= 'width' +// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' +// +// If you don't do either of the above things, widths will be quantized to multiples +// of small integers to guarantee the algorithm doesn't run out of temporary storage. +// +// If you do #2, then the non-quantized algorithm will be used, but the algorithm +// may run out of temporary storage and be unable to pack some rectangles. + +STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); +// Optionally call this function after init but before doing any packing to +// change the handling of the out-of-temp-memory scenario, described above. +// If you call init again, this will be reset to the default (false). + + +STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); +// Optionally select which packing heuristic the library should use. Different +// heuristics will produce better/worse results for different data sets. +// If you call init again, this will be reset to the default. + +enum +{ + STBRP_HEURISTIC_Skyline_default=0, + STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, + STBRP_HEURISTIC_Skyline_BF_sortHeight +}; + + +////////////////////////////////////////////////////////////////////////////// +// +// the details of the following structures don't matter to you, but they must +// be visible so you can handle the memory allocations for them + +struct stbrp_node +{ + stbrp_coord x,y; + stbrp_node *next; +}; + +struct stbrp_context +{ + int width; + int height; + int align; + int init_mode; + int heuristic; + int num_nodes; + stbrp_node *active_head; + stbrp_node *free_head; + stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' +}; + +#ifdef __cplusplus +} +#endif + +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// IMPLEMENTATION SECTION +// + +#ifdef STB_RECT_PACK_IMPLEMENTATION +#ifndef STBRP_SORT +#include +#define STBRP_SORT qsort +#endif + +#ifndef STBRP_ASSERT +#include +#define STBRP_ASSERT assert +#endif + +#ifdef _MSC_VER +#define STBRP__NOTUSED(v) (void)(v) +#define STBRP__CDECL __cdecl +#else +#define STBRP__NOTUSED(v) (void)sizeof(v) +#define STBRP__CDECL +#endif + +enum +{ + STBRP__INIT_skyline = 1 +}; + +STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) +{ + switch (context->init_mode) { + case STBRP__INIT_skyline: + STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); + context->heuristic = heuristic; + break; + default: + STBRP_ASSERT(0); + } +} + +STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) +{ + if (allow_out_of_mem) + // if it's ok to run out of memory, then don't bother aligning them; + // this gives better packing, but may fail due to OOM (even though + // the rectangles easily fit). @TODO a smarter approach would be to only + // quantize once we've hit OOM, then we could get rid of this parameter. + context->align = 1; + else { + // if it's not ok to run out of memory, then quantize the widths + // so that num_nodes is always enough nodes. + // + // I.e. num_nodes * align >= width + // align >= width / num_nodes + // align = ceil(width/num_nodes) + + context->align = (context->width + context->num_nodes-1) / context->num_nodes; + } +} + +STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) +{ + int i; + + for (i=0; i < num_nodes-1; ++i) + nodes[i].next = &nodes[i+1]; + nodes[i].next = NULL; + context->init_mode = STBRP__INIT_skyline; + context->heuristic = STBRP_HEURISTIC_Skyline_default; + context->free_head = &nodes[0]; + context->active_head = &context->extra[0]; + context->width = width; + context->height = height; + context->num_nodes = num_nodes; + stbrp_setup_allow_out_of_mem(context, 0); + + // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) + context->extra[0].x = 0; + context->extra[0].y = 0; + context->extra[0].next = &context->extra[1]; + context->extra[1].x = (stbrp_coord) width; + context->extra[1].y = (1<<30); + context->extra[1].next = NULL; +} + +// find minimum y position if it starts at x1 +static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) +{ + stbrp_node *node = first; + int x1 = x0 + width; + int min_y, visited_width, waste_area; + + STBRP__NOTUSED(c); + + STBRP_ASSERT(first->x <= x0); + + #if 0 + // skip in case we're past the node + while (node->next->x <= x0) + ++node; + #else + STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency + #endif + + STBRP_ASSERT(node->x <= x0); + + min_y = 0; + waste_area = 0; + visited_width = 0; + while (node->x < x1) { + if (node->y > min_y) { + // raise min_y higher. + // we've accounted for all waste up to min_y, + // but we'll now add more waste for everything we've visted + waste_area += visited_width * (node->y - min_y); + min_y = node->y; + // the first time through, visited_width might be reduced + if (node->x < x0) + visited_width += node->next->x - x0; + else + visited_width += node->next->x - node->x; + } else { + // add waste area + int under_width = node->next->x - node->x; + if (under_width + visited_width > width) + under_width = width - visited_width; + waste_area += under_width * (min_y - node->y); + visited_width += under_width; + } + node = node->next; + } + + *pwaste = waste_area; + return min_y; +} + +typedef struct +{ + int x,y; + stbrp_node **prev_link; +} stbrp__findresult; + +static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) +{ + int best_waste = (1<<30), best_x, best_y = (1 << 30); + stbrp__findresult fr; + stbrp_node **prev, *node, *tail, **best = NULL; + + // align to multiple of c->align + width = (width + c->align - 1); + width -= width % c->align; + STBRP_ASSERT(width % c->align == 0); + + // if it can't possibly fit, bail immediately + if (width > c->width || height > c->height) { + fr.prev_link = NULL; + fr.x = fr.y = 0; + return fr; + } + + node = c->active_head; + prev = &c->active_head; + while (node->x + width <= c->width) { + int y,waste; + y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); + if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL + // bottom left + if (y < best_y) { + best_y = y; + best = prev; + } + } else { + // best-fit + if (y + height <= c->height) { + // can only use it if it first vertically + if (y < best_y || (y == best_y && waste < best_waste)) { + best_y = y; + best_waste = waste; + best = prev; + } + } + } + prev = &node->next; + node = node->next; + } + + best_x = (best == NULL) ? 0 : (*best)->x; + + // if doing best-fit (BF), we also have to try aligning right edge to each node position + // + // e.g, if fitting + // + // ____________________ + // |____________________| + // + // into + // + // | | + // | ____________| + // |____________| + // + // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned + // + // This makes BF take about 2x the time + + if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { + tail = c->active_head; + node = c->active_head; + prev = &c->active_head; + // find first node that's admissible + while (tail->x < width) + tail = tail->next; + while (tail) { + int xpos = tail->x - width; + int y,waste; + STBRP_ASSERT(xpos >= 0); + // find the left position that matches this + while (node->next->x <= xpos) { + prev = &node->next; + node = node->next; + } + STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); + y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); + if (y + height <= c->height) { + if (y <= best_y) { + if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { + best_x = xpos; + STBRP_ASSERT(y <= best_y); + best_y = y; + best_waste = waste; + best = prev; + } + } + } + tail = tail->next; + } + } + + fr.prev_link = best; + fr.x = best_x; + fr.y = best_y; + return fr; +} + +static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) +{ + // find best position according to heuristic + stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); + stbrp_node *node, *cur; + + // bail if: + // 1. it failed + // 2. the best node doesn't fit (we don't always check this) + // 3. we're out of memory + if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { + res.prev_link = NULL; + return res; + } + + // on success, create new node + node = context->free_head; + node->x = (stbrp_coord) res.x; + node->y = (stbrp_coord) (res.y + height); + + context->free_head = node->next; + + // insert the new node into the right starting point, and + // let 'cur' point to the remaining nodes needing to be + // stiched back in + + cur = *res.prev_link; + if (cur->x < res.x) { + // preserve the existing one, so start testing with the next one + stbrp_node *next = cur->next; + cur->next = node; + cur = next; + } else { + *res.prev_link = node; + } + + // from here, traverse cur and free the nodes, until we get to one + // that shouldn't be freed + while (cur->next && cur->next->x <= res.x + width) { + stbrp_node *next = cur->next; + // move the current node to the free list + cur->next = context->free_head; + context->free_head = cur; + cur = next; + } + + // stitch the list back in + node->next = cur; + + if (cur->x < res.x + width) + cur->x = (stbrp_coord) (res.x + width); + +#ifdef _DEBUG + cur = context->active_head; + while (cur->x < context->width) { + STBRP_ASSERT(cur->x < cur->next->x); + cur = cur->next; + } + STBRP_ASSERT(cur->next == NULL); + + { + int count=0; + cur = context->active_head; + while (cur) { + cur = cur->next; + ++count; + } + cur = context->free_head; + while (cur) { + cur = cur->next; + ++count; + } + STBRP_ASSERT(count == context->num_nodes+2); + } +#endif + + return res; +} + +static int STBRP__CDECL rect_height_compare(const void *a, const void *b) +{ + const stbrp_rect *p = (const stbrp_rect *) a; + const stbrp_rect *q = (const stbrp_rect *) b; + if (p->h > q->h) + return -1; + if (p->h < q->h) + return 1; + return (p->w > q->w) ? -1 : (p->w < q->w); +} + +static int STBRP__CDECL rect_original_order(const void *a, const void *b) +{ + const stbrp_rect *p = (const stbrp_rect *) a; + const stbrp_rect *q = (const stbrp_rect *) b; + return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); +} + +STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) +{ + int i, all_rects_packed = 1; + + // we use the 'was_packed' field internally to allow sorting/unsorting + for (i=0; i < num_rects; ++i) { + rects[i].was_packed = i; + } + + // sort according to heuristic + STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); + + for (i=0; i < num_rects; ++i) { + if (rects[i].w == 0 || rects[i].h == 0) { + rects[i].x = rects[i].y = 0; // empty rect needs no space + } else { + stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); + if (fr.prev_link) { + rects[i].x = (stbrp_coord) fr.x; + rects[i].y = (stbrp_coord) fr.y; + } else { + rects[i].x = rects[i].y = STBRP__MAXVAL; + } + } + } + + // unsort + STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); + + // set was_packed flags and all_rects_packed status + for (i=0; i < num_rects; ++i) { + rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); + if (!rects[i].was_packed) + all_rects_packed = 0; + } + + // return the all_rects_packed status + return all_rects_packed; +} +#endif + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_sprintf.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_sprintf.h new file mode 100644 index 0000000..ca432a6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_sprintf.h @@ -0,0 +1,1906 @@ +// stb_sprintf - v1.10 - public domain snprintf() implementation +// originally by Jeff Roberts / RAD Game Tools, 2015/10/20 +// http://github.com/nothings/stb +// +// allowed types: sc uidBboXx p AaGgEef n +// lengths : hh h ll j z t I64 I32 I +// +// Contributors: +// Fabian "ryg" Giesen (reformatting) +// github:aganm (attribute format) +// +// Contributors (bugfixes): +// github:d26435 +// github:trex78 +// github:account-login +// Jari Komppa (SI suffixes) +// Rohit Nirmal +// Marcin Wojdyr +// Leonard Ritter +// Stefano Zanotti +// Adam Allison +// Arvid Gerstmann +// Markus Kolb +// +// LICENSE: +// +// See end of file for license information. + +#ifndef STB_SPRINTF_H_INCLUDE +#define STB_SPRINTF_H_INCLUDE + +/* +Single file sprintf replacement. + +Originally written by Jeff Roberts at RAD Game Tools - 2015/10/20. +Hereby placed in public domain. + +This is a full sprintf replacement that supports everything that +the C runtime sprintfs support, including float/double, 64-bit integers, +hex floats, field parameters (%*.*d stuff), length reads backs, etc. + +Why would you need this if sprintf already exists? Well, first off, +it's *much* faster (see below). It's also much smaller than the CRT +versions code-space-wise. We've also added some simple improvements +that are super handy (commas in thousands, callbacks at buffer full, +for example). Finally, the format strings for MSVC and GCC differ +for 64-bit integers (among other small things), so this lets you use +the same format strings in cross platform code. + +It uses the standard single file trick of being both the header file +and the source itself. If you just include it normally, you just get +the header file function definitions. To get the code, you include +it from a C or C++ file and define STB_SPRINTF_IMPLEMENTATION first. + +It only uses va_args macros from the C runtime to do it's work. It +does cast doubles to S64s and shifts and divides U64s, which does +drag in CRT code on most platforms. + +It compiles to roughly 8K with float support, and 4K without. +As a comparison, when using MSVC static libs, calling sprintf drags +in 16K. + +API: +==== +int stbsp_sprintf( char * buf, char const * fmt, ... ) +int stbsp_snprintf( char * buf, int count, char const * fmt, ... ) + Convert an arg list into a buffer. stbsp_snprintf always returns + a zero-terminated string (unlike regular snprintf). + +int stbsp_vsprintf( char * buf, char const * fmt, va_list va ) +int stbsp_vsnprintf( char * buf, int count, char const * fmt, va_list va ) + Convert a va_list arg list into a buffer. stbsp_vsnprintf always returns + a zero-terminated string (unlike regular snprintf). + +int stbsp_vsprintfcb( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) + typedef char * STBSP_SPRINTFCB( char const * buf, void * user, int len ); + Convert into a buffer, calling back every STB_SPRINTF_MIN chars. + Your callback can then copy the chars out, print them or whatever. + This function is actually the workhorse for everything else. + The buffer you pass in must hold at least STB_SPRINTF_MIN characters. + // you return the next buffer to use or 0 to stop converting + +void stbsp_set_separators( char comma, char period ) + Set the comma and period characters to use. + +FLOATS/DOUBLES: +=============== +This code uses a internal float->ascii conversion method that uses +doubles with error correction (double-doubles, for ~105 bits of +precision). This conversion is round-trip perfect - that is, an atof +of the values output here will give you the bit-exact double back. + +One difference is that our insignificant digits will be different than +with MSVC or GCC (but they don't match each other either). We also +don't attempt to find the minimum length matching float (pre-MSVC15 +doesn't either). + +If you don't need float or doubles at all, define STB_SPRINTF_NOFLOAT +and you'll save 4K of code space. + +64-BIT INTS: +============ +This library also supports 64-bit integers and you can use MSVC style or +GCC style indicators (%I64d or %lld). It supports the C99 specifiers +for size_t and ptr_diff_t (%jd %zd) as well. + +EXTRAS: +======= +Like some GCCs, for integers and floats, you can use a ' (single quote) +specifier and commas will be inserted on the thousands: "%'d" on 12345 +would print 12,345. + +For integers and floats, you can use a "$" specifier and the number +will be converted to float and then divided to get kilo, mega, giga or +tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is +"2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn +2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three +$:s: "%$$$d" -> "2.42 M". To remove the space between the number and the +suffix, add "_" specifier: "%_$d" -> "2.53M". + +In addition to octal and hexadecimal conversions, you can print +integers in binary: "%b" for 256 would print 100. + +PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): +=================================================================== +"%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC) +"%24d" across all 32-bit ints (4.5x/4.2x faster) +"%x" across all 32-bit ints (4.5x/3.8x faster) +"%08x" across all 32-bit ints (4.3x/3.8x faster) +"%f" across e-10 to e+10 floats (7.3x/6.0x faster) +"%e" across e-10 to e+10 floats (8.1x/6.0x faster) +"%g" across e-10 to e+10 floats (10.0x/7.1x faster) +"%f" for values near e-300 (7.9x/6.5x faster) +"%f" for values near e+300 (10.0x/9.1x faster) +"%e" for values near e-300 (10.1x/7.0x faster) +"%e" for values near e+300 (9.2x/6.0x faster) +"%.320f" for values near e-300 (12.6x/11.2x faster) +"%a" for random values (8.6x/4.3x faster) +"%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster) +"%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster) +"%s%s%s" for 64 char strings (7.1x/7.3x faster) +"...512 char string..." ( 35.0x/32.5x faster!) +*/ + +#if defined(__clang__) + #if defined(__has_feature) && defined(__has_attribute) + #if __has_feature(address_sanitizer) + #if __has_attribute(__no_sanitize__) + #define STBSP__ASAN __attribute__((__no_sanitize__("address"))) + #elif __has_attribute(__no_sanitize_address__) + #define STBSP__ASAN __attribute__((__no_sanitize_address__)) + #elif __has_attribute(__no_address_safety_analysis__) + #define STBSP__ASAN __attribute__((__no_address_safety_analysis__)) + #endif + #endif + #endif +#elif defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) + #if defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__ + #define STBSP__ASAN __attribute__((__no_sanitize_address__)) + #endif +#endif + +#ifndef STBSP__ASAN +#define STBSP__ASAN +#endif + +#ifdef STB_SPRINTF_STATIC +#define STBSP__PUBLICDEC static +#define STBSP__PUBLICDEF static STBSP__ASAN +#else +#ifdef __cplusplus +#define STBSP__PUBLICDEC extern "C" +#define STBSP__PUBLICDEF extern "C" STBSP__ASAN +#else +#define STBSP__PUBLICDEC extern +#define STBSP__PUBLICDEF STBSP__ASAN +#endif +#endif + +#if defined(__has_attribute) + #if __has_attribute(format) + #define STBSP__ATTRIBUTE_FORMAT(fmt,va) __attribute__((format(printf,fmt,va))) + #endif +#endif + +#ifndef STBSP__ATTRIBUTE_FORMAT +#define STBSP__ATTRIBUTE_FORMAT(fmt,va) +#endif + +#ifdef _MSC_VER +#define STBSP__NOTUSED(v) (void)(v) +#else +#define STBSP__NOTUSED(v) (void)sizeof(v) +#endif + +#include // for va_arg(), va_list() +#include // size_t, ptrdiff_t + +#ifndef STB_SPRINTF_MIN +#define STB_SPRINTF_MIN 512 // how many characters per callback +#endif +typedef char *STBSP_SPRINTFCB(const char *buf, void *user, int len); + +#ifndef STB_SPRINTF_DECORATE +#define STB_SPRINTF_DECORATE(name) stbsp_##name // define this before including if you want to change the names +#endif + +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va); +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va); +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3); +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(3,4); + +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va); +STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char period); + +#endif // STB_SPRINTF_H_INCLUDE + +#ifdef STB_SPRINTF_IMPLEMENTATION + +#define stbsp__uint32 unsigned int +#define stbsp__int32 signed int + +#ifdef _MSC_VER +#define stbsp__uint64 unsigned __int64 +#define stbsp__int64 signed __int64 +#else +#define stbsp__uint64 unsigned long long +#define stbsp__int64 signed long long +#endif +#define stbsp__uint16 unsigned short + +#ifndef stbsp__uintptr +#if defined(__ppc64__) || defined(__powerpc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__s390x__) +#define stbsp__uintptr stbsp__uint64 +#else +#define stbsp__uintptr stbsp__uint32 +#endif +#endif + +#ifndef STB_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC) +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define STB_SPRINTF_MSVC_MODE +#endif +#endif + +#ifdef STB_SPRINTF_NOUNALIGNED // define this before inclusion to force stbsp_sprintf to always use aligned accesses +#define STBSP__UNALIGNED(code) +#else +#define STBSP__UNALIGNED(code) code +#endif + +#ifndef STB_SPRINTF_NOFLOAT +// internal float utility functions +static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits); +static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value); +#define STBSP__SPECIAL 0x7000 +#endif + +static char stbsp__period = '.'; +static char stbsp__comma = ','; +static struct +{ + short temp; // force next field to be 2-byte aligned + char pair[201]; +} stbsp__digitpair = +{ + 0, + "00010203040506070809101112131415161718192021222324" + "25262728293031323334353637383940414243444546474849" + "50515253545556575859606162636465666768697071727374" + "75767778798081828384858687888990919293949596979899" +}; + +STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char pcomma, char pperiod) +{ + stbsp__period = pperiod; + stbsp__comma = pcomma; +} + +#define STBSP__LEFTJUST 1 +#define STBSP__LEADINGPLUS 2 +#define STBSP__LEADINGSPACE 4 +#define STBSP__LEADING_0X 8 +#define STBSP__LEADINGZERO 16 +#define STBSP__INTMAX 32 +#define STBSP__TRIPLET_COMMA 64 +#define STBSP__NEGATIVE 128 +#define STBSP__METRIC_SUFFIX 256 +#define STBSP__HALFWIDTH 512 +#define STBSP__METRIC_NOSPACE 1024 +#define STBSP__METRIC_1024 2048 +#define STBSP__METRIC_JEDEC 4096 + +static void stbsp__lead_sign(stbsp__uint32 fl, char *sign) +{ + sign[0] = 0; + if (fl & STBSP__NEGATIVE) { + sign[0] = 1; + sign[1] = '-'; + } else if (fl & STBSP__LEADINGSPACE) { + sign[0] = 1; + sign[1] = ' '; + } else if (fl & STBSP__LEADINGPLUS) { + sign[0] = 1; + sign[1] = '+'; + } +} + +static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit) +{ + char const * sn = s; + + // get up to 4-byte alignment + for (;;) { + if (((stbsp__uintptr)sn & 3) == 0) + break; + + if (!limit || *sn == 0) + return (stbsp__uint32)(sn - s); + + ++sn; + --limit; + } + + // scan over 4 bytes at a time to find terminating 0 + // this will intentionally scan up to 3 bytes past the end of buffers, + // but becase it works 4B aligned, it will never cross page boundaries + // (hence the STBSP__ASAN markup; the over-read here is intentional + // and harmless) + while (limit >= 4) { + stbsp__uint32 v = *(stbsp__uint32 *)sn; + // bit hack to find if there's a 0 byte in there + if ((v - 0x01010101) & (~v) & 0x80808080UL) + break; + + sn += 4; + limit -= 4; + } + + // handle the last few characters to find actual size + while (limit && *sn) { + ++sn; + --limit; + } + + return (stbsp__uint32)(sn - s); +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va) +{ + static char hex[] = "0123456789abcdefxp"; + static char hexu[] = "0123456789ABCDEFXP"; + char *bf; + char const *f; + int tlen = 0; + + bf = buf; + f = fmt; + for (;;) { + stbsp__int32 fw, pr, tz; + stbsp__uint32 fl; + + // macros for the callback buffer stuff + #define stbsp__chk_cb_bufL(bytes) \ + { \ + int len = (int)(bf - buf); \ + if ((len + (bytes)) >= STB_SPRINTF_MIN) { \ + tlen += len; \ + if (0 == (bf = buf = callback(buf, user, len))) \ + goto done; \ + } \ + } + #define stbsp__chk_cb_buf(bytes) \ + { \ + if (callback) { \ + stbsp__chk_cb_bufL(bytes); \ + } \ + } + #define stbsp__flush_cb() \ + { \ + stbsp__chk_cb_bufL(STB_SPRINTF_MIN - 1); \ + } // flush if there is even one byte in the buffer + #define stbsp__cb_buf_clamp(cl, v) \ + cl = v; \ + if (callback) { \ + int lg = STB_SPRINTF_MIN - (int)(bf - buf); \ + if (cl > lg) \ + cl = lg; \ + } + + // fast copy everything up to the next % (or end of string) + for (;;) { + while (((stbsp__uintptr)f) & 3) { + schk1: + if (f[0] == '%') + goto scandd; + schk2: + if (f[0] == 0) + goto endfmt; + stbsp__chk_cb_buf(1); + *bf++ = f[0]; + ++f; + } + for (;;) { + // Check if the next 4 bytes contain %(0x25) or end of string. + // Using the 'hasless' trick: + // https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord + stbsp__uint32 v, c; + v = *(stbsp__uint32 *)f; + c = (~v) & 0x80808080; + if (((v ^ 0x25252525) - 0x01010101) & c) + goto schk1; + if ((v - 0x01010101) & c) + goto schk2; + if (callback) + if ((STB_SPRINTF_MIN - (int)(bf - buf)) < 4) + goto schk1; + #ifdef STB_SPRINTF_NOUNALIGNED + if(((stbsp__uintptr)bf) & 3) { + bf[0] = f[0]; + bf[1] = f[1]; + bf[2] = f[2]; + bf[3] = f[3]; + } else + #endif + { + *(stbsp__uint32 *)bf = v; + } + bf += 4; + f += 4; + } + } + scandd: + + ++f; + + // ok, we have a percent, read the modifiers first + fw = 0; + pr = -1; + fl = 0; + tz = 0; + + // flags + for (;;) { + switch (f[0]) { + // if we have left justify + case '-': + fl |= STBSP__LEFTJUST; + ++f; + continue; + // if we have leading plus + case '+': + fl |= STBSP__LEADINGPLUS; + ++f; + continue; + // if we have leading space + case ' ': + fl |= STBSP__LEADINGSPACE; + ++f; + continue; + // if we have leading 0x + case '#': + fl |= STBSP__LEADING_0X; + ++f; + continue; + // if we have thousand commas + case '\'': + fl |= STBSP__TRIPLET_COMMA; + ++f; + continue; + // if we have kilo marker (none->kilo->kibi->jedec) + case '$': + if (fl & STBSP__METRIC_SUFFIX) { + if (fl & STBSP__METRIC_1024) { + fl |= STBSP__METRIC_JEDEC; + } else { + fl |= STBSP__METRIC_1024; + } + } else { + fl |= STBSP__METRIC_SUFFIX; + } + ++f; + continue; + // if we don't want space between metric suffix and number + case '_': + fl |= STBSP__METRIC_NOSPACE; + ++f; + continue; + // if we have leading zero + case '0': + fl |= STBSP__LEADINGZERO; + ++f; + goto flags_done; + default: goto flags_done; + } + } + flags_done: + + // get the field width + if (f[0] == '*') { + fw = va_arg(va, stbsp__uint32); + ++f; + } else { + while ((f[0] >= '0') && (f[0] <= '9')) { + fw = fw * 10 + f[0] - '0'; + f++; + } + } + // get the precision + if (f[0] == '.') { + ++f; + if (f[0] == '*') { + pr = va_arg(va, stbsp__uint32); + ++f; + } else { + pr = 0; + while ((f[0] >= '0') && (f[0] <= '9')) { + pr = pr * 10 + f[0] - '0'; + f++; + } + } + } + + // handle integer size overrides + switch (f[0]) { + // are we halfwidth? + case 'h': + fl |= STBSP__HALFWIDTH; + ++f; + if (f[0] == 'h') + ++f; // QUARTERWIDTH + break; + // are we 64-bit (unix style) + case 'l': + fl |= ((sizeof(long) == 8) ? STBSP__INTMAX : 0); + ++f; + if (f[0] == 'l') { + fl |= STBSP__INTMAX; + ++f; + } + break; + // are we 64-bit on intmax? (c99) + case 'j': + fl |= (sizeof(size_t) == 8) ? STBSP__INTMAX : 0; + ++f; + break; + // are we 64-bit on size_t or ptrdiff_t? (c99) + case 'z': + fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0; + ++f; + break; + case 't': + fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0; + ++f; + break; + // are we 64-bit (msft style) + case 'I': + if ((f[1] == '6') && (f[2] == '4')) { + fl |= STBSP__INTMAX; + f += 3; + } else if ((f[1] == '3') && (f[2] == '2')) { + f += 3; + } else { + fl |= ((sizeof(void *) == 8) ? STBSP__INTMAX : 0); + ++f; + } + break; + default: break; + } + + // handle each replacement + switch (f[0]) { + #define STBSP__NUMSZ 512 // big enough for e308 (with commas) or e-307 + char num[STBSP__NUMSZ]; + char lead[8]; + char tail[8]; + char *s; + char const *h; + stbsp__uint32 l, n, cs; + stbsp__uint64 n64; +#ifndef STB_SPRINTF_NOFLOAT + double fv; +#endif + stbsp__int32 dp; + char const *sn; + + case 's': + // get the string + s = va_arg(va, char *); + if (s == 0) + s = (char *)"null"; + // get the length, limited to desired precision + // always limit to ~0u chars since our counts are 32b + l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u); + lead[0] = 0; + tail[0] = 0; + pr = 0; + dp = 0; + cs = 0; + // copy the string in + goto scopy; + + case 'c': // char + // get the character + s = num + STBSP__NUMSZ - 1; + *s = (char)va_arg(va, int); + l = 1; + lead[0] = 0; + tail[0] = 0; + pr = 0; + dp = 0; + cs = 0; + goto scopy; + + case 'n': // weird write-bytes specifier + { + int *d = va_arg(va, int *); + *d = tlen + (int)(bf - buf); + } break; + +#ifdef STB_SPRINTF_NOFLOAT + case 'A': // float + case 'a': // hex float + case 'G': // float + case 'g': // float + case 'E': // float + case 'e': // float + case 'f': // float + va_arg(va, double); // eat it + s = (char *)"No float"; + l = 8; + lead[0] = 0; + tail[0] = 0; + pr = 0; + cs = 0; + STBSP__NOTUSED(dp); + goto scopy; +#else + case 'A': // hex float + case 'a': // hex float + h = (f[0] == 'A') ? hexu : hex; + fv = va_arg(va, double); + if (pr == -1) + pr = 6; // default is 6 + // read the double into a string + if (stbsp__real_to_parts((stbsp__int64 *)&n64, &dp, fv)) + fl |= STBSP__NEGATIVE; + + s = num + 64; + + stbsp__lead_sign(fl, lead); + + if (dp == -1023) + dp = (n64) ? -1022 : 0; + else + n64 |= (((stbsp__uint64)1) << 52); + n64 <<= (64 - 56); + if (pr < 15) + n64 += ((((stbsp__uint64)8) << 56) >> (pr * 4)); +// add leading chars + +#ifdef STB_SPRINTF_MSVC_MODE + *s++ = '0'; + *s++ = 'x'; +#else + lead[1 + lead[0]] = '0'; + lead[2 + lead[0]] = 'x'; + lead[0] += 2; +#endif + *s++ = h[(n64 >> 60) & 15]; + n64 <<= 4; + if (pr) + *s++ = stbsp__period; + sn = s; + + // print the bits + n = pr; + if (n > 13) + n = 13; + if (pr > (stbsp__int32)n) + tz = pr - n; + pr = 0; + while (n--) { + *s++ = h[(n64 >> 60) & 15]; + n64 <<= 4; + } + + // print the expo + tail[1] = h[17]; + if (dp < 0) { + tail[2] = '-'; + dp = -dp; + } else + tail[2] = '+'; + n = (dp >= 1000) ? 6 : ((dp >= 100) ? 5 : ((dp >= 10) ? 4 : 3)); + tail[0] = (char)n; + for (;;) { + tail[n] = '0' + dp % 10; + if (n <= 3) + break; + --n; + dp /= 10; + } + + dp = (int)(s - sn); + l = (int)(s - (num + 64)); + s = num + 64; + cs = 1 + (3 << 24); + goto scopy; + + case 'G': // float + case 'g': // float + h = (f[0] == 'G') ? hexu : hex; + fv = va_arg(va, double); + if (pr == -1) + pr = 6; + else if (pr == 0) + pr = 1; // default is 6 + // read the double into a string + if (stbsp__real_to_str(&sn, &l, num, &dp, fv, (pr - 1) | 0x80000000)) + fl |= STBSP__NEGATIVE; + + // clamp the precision and delete extra zeros after clamp + n = pr; + if (l > (stbsp__uint32)pr) + l = pr; + while ((l > 1) && (pr) && (sn[l - 1] == '0')) { + --pr; + --l; + } + + // should we use %e + if ((dp <= -4) || (dp > (stbsp__int32)n)) { + if (pr > (stbsp__int32)l) + pr = l - 1; + else if (pr) + --pr; // when using %e, there is one digit before the decimal + goto doexpfromg; + } + // this is the insane action to get the pr to match %g semantics for %f + if (dp > 0) { + pr = (dp < (stbsp__int32)l) ? l - dp : 0; + } else { + pr = -dp + ((pr > (stbsp__int32)l) ? (stbsp__int32) l : pr); + } + goto dofloatfromg; + + case 'E': // float + case 'e': // float + h = (f[0] == 'E') ? hexu : hex; + fv = va_arg(va, double); + if (pr == -1) + pr = 6; // default is 6 + // read the double into a string + if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr | 0x80000000)) + fl |= STBSP__NEGATIVE; + doexpfromg: + tail[0] = 0; + stbsp__lead_sign(fl, lead); + if (dp == STBSP__SPECIAL) { + s = (char *)sn; + cs = 0; + pr = 0; + goto scopy; + } + s = num + 64; + // handle leading chars + *s++ = sn[0]; + + if (pr) + *s++ = stbsp__period; + + // handle after decimal + if ((l - 1) > (stbsp__uint32)pr) + l = pr + 1; + for (n = 1; n < l; n++) + *s++ = sn[n]; + // trailing zeros + tz = pr - (l - 1); + pr = 0; + // dump expo + tail[1] = h[0xe]; + dp -= 1; + if (dp < 0) { + tail[2] = '-'; + dp = -dp; + } else + tail[2] = '+'; +#ifdef STB_SPRINTF_MSVC_MODE + n = 5; +#else + n = (dp >= 100) ? 5 : 4; +#endif + tail[0] = (char)n; + for (;;) { + tail[n] = '0' + dp % 10; + if (n <= 3) + break; + --n; + dp /= 10; + } + cs = 1 + (3 << 24); // how many tens + goto flt_lead; + + case 'f': // float + fv = va_arg(va, double); + doafloat: + // do kilos + if (fl & STBSP__METRIC_SUFFIX) { + double divisor; + divisor = 1000.0f; + if (fl & STBSP__METRIC_1024) + divisor = 1024.0; + while (fl < 0x4000000) { + if ((fv < divisor) && (fv > -divisor)) + break; + fv /= divisor; + fl += 0x1000000; + } + } + if (pr == -1) + pr = 6; // default is 6 + // read the double into a string + if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr)) + fl |= STBSP__NEGATIVE; + dofloatfromg: + tail[0] = 0; + stbsp__lead_sign(fl, lead); + if (dp == STBSP__SPECIAL) { + s = (char *)sn; + cs = 0; + pr = 0; + goto scopy; + } + s = num + 64; + + // handle the three decimal varieties + if (dp <= 0) { + stbsp__int32 i; + // handle 0.000*000xxxx + *s++ = '0'; + if (pr) + *s++ = stbsp__period; + n = -dp; + if ((stbsp__int32)n > pr) + n = pr; + i = n; + while (i) { + if ((((stbsp__uintptr)s) & 3) == 0) + break; + *s++ = '0'; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)s = 0x30303030; + s += 4; + i -= 4; + } + while (i) { + *s++ = '0'; + --i; + } + if ((stbsp__int32)(l + n) > pr) + l = pr - n; + i = l; + while (i) { + *s++ = *sn++; + --i; + } + tz = pr - (n + l); + cs = 1 + (3 << 24); // how many tens did we write (for commas below) + } else { + cs = (fl & STBSP__TRIPLET_COMMA) ? ((600 - (stbsp__uint32)dp) % 3) : 0; + if ((stbsp__uint32)dp >= l) { + // handle xxxx000*000.0 + n = 0; + for (;;) { + if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { + cs = 0; + *s++ = stbsp__comma; + } else { + *s++ = sn[n]; + ++n; + if (n >= l) + break; + } + } + if (n < (stbsp__uint32)dp) { + n = dp - n; + if ((fl & STBSP__TRIPLET_COMMA) == 0) { + while (n) { + if ((((stbsp__uintptr)s) & 3) == 0) + break; + *s++ = '0'; + --n; + } + while (n >= 4) { + *(stbsp__uint32 *)s = 0x30303030; + s += 4; + n -= 4; + } + } + while (n) { + if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { + cs = 0; + *s++ = stbsp__comma; + } else { + *s++ = '0'; + --n; + } + } + } + cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens + if (pr) { + *s++ = stbsp__period; + tz = pr; + } + } else { + // handle xxxxx.xxxx000*000 + n = 0; + for (;;) { + if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { + cs = 0; + *s++ = stbsp__comma; + } else { + *s++ = sn[n]; + ++n; + if (n >= (stbsp__uint32)dp) + break; + } + } + cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens + if (pr) + *s++ = stbsp__period; + if ((l - dp) > (stbsp__uint32)pr) + l = pr + dp; + while (n < l) { + *s++ = sn[n]; + ++n; + } + tz = pr - (l - dp); + } + } + pr = 0; + + // handle k,m,g,t + if (fl & STBSP__METRIC_SUFFIX) { + char idx; + idx = 1; + if (fl & STBSP__METRIC_NOSPACE) + idx = 0; + tail[0] = idx; + tail[1] = ' '; + { + if (fl >> 24) { // SI kilo is 'k', JEDEC and SI kibits are 'K'. + if (fl & STBSP__METRIC_1024) + tail[idx + 1] = "_KMGT"[fl >> 24]; + else + tail[idx + 1] = "_kMGT"[fl >> 24]; + idx++; + // If printing kibits and not in jedec, add the 'i'. + if (fl & STBSP__METRIC_1024 && !(fl & STBSP__METRIC_JEDEC)) { + tail[idx + 1] = 'i'; + idx++; + } + tail[0] = idx; + } + } + }; + + flt_lead: + // get the length that we copied + l = (stbsp__uint32)(s - (num + 64)); + s = num + 64; + goto scopy; +#endif + + case 'B': // upper binary + case 'b': // lower binary + h = (f[0] == 'B') ? hexu : hex; + lead[0] = 0; + if (fl & STBSP__LEADING_0X) { + lead[0] = 2; + lead[1] = '0'; + lead[2] = h[0xb]; + } + l = (8 << 4) | (1 << 8); + goto radixnum; + + case 'o': // octal + h = hexu; + lead[0] = 0; + if (fl & STBSP__LEADING_0X) { + lead[0] = 1; + lead[1] = '0'; + } + l = (3 << 4) | (3 << 8); + goto radixnum; + + case 'p': // pointer + fl |= (sizeof(void *) == 8) ? STBSP__INTMAX : 0; + pr = sizeof(void *) * 2; + fl &= ~STBSP__LEADINGZERO; // 'p' only prints the pointer with zeros + // fall through - to X + + case 'X': // upper hex + case 'x': // lower hex + h = (f[0] == 'X') ? hexu : hex; + l = (4 << 4) | (4 << 8); + lead[0] = 0; + if (fl & STBSP__LEADING_0X) { + lead[0] = 2; + lead[1] = '0'; + lead[2] = h[16]; + } + radixnum: + // get the number + if (fl & STBSP__INTMAX) + n64 = va_arg(va, stbsp__uint64); + else + n64 = va_arg(va, stbsp__uint32); + + s = num + STBSP__NUMSZ; + dp = 0; + // clear tail, and clear leading if value is zero + tail[0] = 0; + if (n64 == 0) { + lead[0] = 0; + if (pr == 0) { + l = 0; + cs = 0; + goto scopy; + } + } + // convert to string + for (;;) { + *--s = h[n64 & ((1 << (l >> 8)) - 1)]; + n64 >>= (l >> 8); + if (!((n64) || ((stbsp__int32)((num + STBSP__NUMSZ) - s) < pr))) + break; + if (fl & STBSP__TRIPLET_COMMA) { + ++l; + if ((l & 15) == ((l >> 4) & 15)) { + l &= ~15; + *--s = stbsp__comma; + } + } + }; + // get the tens and the comma pos + cs = (stbsp__uint32)((num + STBSP__NUMSZ) - s) + ((((l >> 4) & 15)) << 24); + // get the length that we copied + l = (stbsp__uint32)((num + STBSP__NUMSZ) - s); + // copy it + goto scopy; + + case 'u': // unsigned + case 'i': + case 'd': // integer + // get the integer and abs it + if (fl & STBSP__INTMAX) { + stbsp__int64 i64 = va_arg(va, stbsp__int64); + n64 = (stbsp__uint64)i64; + if ((f[0] != 'u') && (i64 < 0)) { + n64 = (stbsp__uint64)-i64; + fl |= STBSP__NEGATIVE; + } + } else { + stbsp__int32 i = va_arg(va, stbsp__int32); + n64 = (stbsp__uint32)i; + if ((f[0] != 'u') && (i < 0)) { + n64 = (stbsp__uint32)-i; + fl |= STBSP__NEGATIVE; + } + } + +#ifndef STB_SPRINTF_NOFLOAT + if (fl & STBSP__METRIC_SUFFIX) { + if (n64 < 1024) + pr = 0; + else if (pr == -1) + pr = 1; + fv = (double)(stbsp__int64)n64; + goto doafloat; + } +#endif + + // convert to string + s = num + STBSP__NUMSZ; + l = 0; + + for (;;) { + // do in 32-bit chunks (avoid lots of 64-bit divides even with constant denominators) + char *o = s - 8; + if (n64 >= 100000000) { + n = (stbsp__uint32)(n64 % 100000000); + n64 /= 100000000; + } else { + n = (stbsp__uint32)n64; + n64 = 0; + } + if ((fl & STBSP__TRIPLET_COMMA) == 0) { + do { + s -= 2; + *(stbsp__uint16 *)s = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2]; + n /= 100; + } while (n); + } + while (n) { + if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { + l = 0; + *--s = stbsp__comma; + --o; + } else { + *--s = (char)(n % 10) + '0'; + n /= 10; + } + } + if (n64 == 0) { + if ((s[0] == '0') && (s != (num + STBSP__NUMSZ))) + ++s; + break; + } + while (s != o) + if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { + l = 0; + *--s = stbsp__comma; + --o; + } else { + *--s = '0'; + } + } + + tail[0] = 0; + stbsp__lead_sign(fl, lead); + + // get the length that we copied + l = (stbsp__uint32)((num + STBSP__NUMSZ) - s); + if (l == 0) { + *--s = '0'; + l = 1; + } + cs = l + (3 << 24); + if (pr < 0) + pr = 0; + + scopy: + // get fw=leading/trailing space, pr=leading zeros + if (pr < (stbsp__int32)l) + pr = l; + n = pr + lead[0] + tail[0] + tz; + if (fw < (stbsp__int32)n) + fw = n; + fw -= n; + pr -= l; + + // handle right justify and leading zeros + if ((fl & STBSP__LEFTJUST) == 0) { + if (fl & STBSP__LEADINGZERO) // if leading zeros, everything is in pr + { + pr = (fw > pr) ? fw : pr; + fw = 0; + } else { + fl &= ~STBSP__TRIPLET_COMMA; // if no leading zeros, then no commas + } + } + + // copy the spaces and/or zeros + if (fw + pr) { + stbsp__int32 i; + stbsp__uint32 c; + + // copy leading spaces (or when doing %8.4d stuff) + if ((fl & STBSP__LEFTJUST) == 0) + while (fw > 0) { + stbsp__cb_buf_clamp(i, fw); + fw -= i; + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = ' '; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x20202020; + bf += 4; + i -= 4; + } + while (i) { + *bf++ = ' '; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy leader + sn = lead + 1; + while (lead[0]) { + stbsp__cb_buf_clamp(i, lead[0]); + lead[0] -= (char)i; + while (i) { + *bf++ = *sn++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy leading zeros + c = cs >> 24; + cs &= 0xffffff; + cs = (fl & STBSP__TRIPLET_COMMA) ? ((stbsp__uint32)(c - ((pr + cs) % (c + 1)))) : 0; + while (pr > 0) { + stbsp__cb_buf_clamp(i, pr); + pr -= i; + if ((fl & STBSP__TRIPLET_COMMA) == 0) { + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = '0'; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x30303030; + bf += 4; + i -= 4; + } + } + while (i) { + if ((fl & STBSP__TRIPLET_COMMA) && (cs++ == c)) { + cs = 0; + *bf++ = stbsp__comma; + } else + *bf++ = '0'; + --i; + } + stbsp__chk_cb_buf(1); + } + } + + // copy leader if there is still one + sn = lead + 1; + while (lead[0]) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, lead[0]); + lead[0] -= (char)i; + while (i) { + *bf++ = *sn++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy the string + n = l; + while (n) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, n); + n -= i; + STBSP__UNALIGNED(while (i >= 4) { + *(stbsp__uint32 volatile *)bf = *(stbsp__uint32 volatile *)s; + bf += 4; + s += 4; + i -= 4; + }) + while (i) { + *bf++ = *s++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy trailing zeros + while (tz) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, tz); + tz -= i; + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = '0'; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x30303030; + bf += 4; + i -= 4; + } + while (i) { + *bf++ = '0'; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy tail if there is one + sn = tail + 1; + while (tail[0]) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, tail[0]); + tail[0] -= (char)i; + while (i) { + *bf++ = *sn++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // handle the left justify + if (fl & STBSP__LEFTJUST) + if (fw > 0) { + while (fw) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, fw); + fw -= i; + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = ' '; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x20202020; + bf += 4; + i -= 4; + } + while (i--) + *bf++ = ' '; + stbsp__chk_cb_buf(1); + } + } + break; + + default: // unknown, just copy code + s = num + STBSP__NUMSZ - 1; + *s = f[0]; + l = 1; + fw = fl = 0; + lead[0] = 0; + tail[0] = 0; + pr = 0; + dp = 0; + cs = 0; + goto scopy; + } + ++f; + } +endfmt: + + if (!callback) + *bf = 0; + else + stbsp__flush_cb(); + +done: + return tlen + (int)(bf - buf); +} + +// cleanup +#undef STBSP__LEFTJUST +#undef STBSP__LEADINGPLUS +#undef STBSP__LEADINGSPACE +#undef STBSP__LEADING_0X +#undef STBSP__LEADINGZERO +#undef STBSP__INTMAX +#undef STBSP__TRIPLET_COMMA +#undef STBSP__NEGATIVE +#undef STBSP__METRIC_SUFFIX +#undef STBSP__NUMSZ +#undef stbsp__chk_cb_bufL +#undef stbsp__chk_cb_buf +#undef stbsp__flush_cb +#undef stbsp__cb_buf_clamp + +// ============================================================================ +// wrapper functions + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) +{ + int result; + va_list va; + va_start(va, fmt); + result = STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va); + va_end(va); + return result; +} + +typedef struct stbsp__context { + char *buf; + int count; + int length; + char tmp[STB_SPRINTF_MIN]; +} stbsp__context; + +static char *stbsp__clamp_callback(const char *buf, void *user, int len) +{ + stbsp__context *c = (stbsp__context *)user; + c->length += len; + + if (len > c->count) + len = c->count; + + if (len) { + if (buf != c->buf) { + const char *s, *se; + char *d; + d = c->buf; + s = buf; + se = buf + len; + do { + *d++ = *s++; + } while (s < se); + } + c->buf += len; + c->count -= len; + } + + if (c->count <= 0) + return c->tmp; + return (c->count >= STB_SPRINTF_MIN) ? c->buf : c->tmp; // go direct into buffer if you can +} + +static char * stbsp__count_clamp_callback( const char * buf, void * user, int len ) +{ + stbsp__context * c = (stbsp__context*)user; + (void) sizeof(buf); + + c->length += len; + return c->tmp; // go direct into buffer if you can +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ) +{ + stbsp__context c; + + if ( (count == 0) && !buf ) + { + c.length = 0; + + STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__count_clamp_callback, &c, c.tmp, fmt, va ); + } + else + { + int l; + + c.buf = buf; + c.count = count; + c.length = 0; + + STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__clamp_callback, &c, stbsp__clamp_callback(0,&c,0), fmt, va ); + + // zero-terminate + l = (int)( c.buf - buf ); + if ( l >= count ) // should never be greater, only equal (or less) than count + l = count - 1; + buf[l] = 0; + } + + return c.length; +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) +{ + int result; + va_list va; + va_start(va, fmt); + + result = STB_SPRINTF_DECORATE(vsnprintf)(buf, count, fmt, va); + va_end(va); + + return result; +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va) +{ + return STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va); +} + +// ======================================================================= +// low level float utility functions + +#ifndef STB_SPRINTF_NOFLOAT + +// copies d to bits w/ strict aliasing (this compiles to nothing on /Ox) +#define STBSP__COPYFP(dest, src) \ + { \ + int cn; \ + for (cn = 0; cn < 8; cn++) \ + ((char *)&dest)[cn] = ((char *)&src)[cn]; \ + } + +// get float info +static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value) +{ + double d; + stbsp__int64 b = 0; + + // load value and round at the frac_digits + d = value; + + STBSP__COPYFP(b, d); + + *bits = b & ((((stbsp__uint64)1) << 52) - 1); + *expo = (stbsp__int32)(((b >> 52) & 2047) - 1023); + + return (stbsp__int32)((stbsp__uint64) b >> 63); +} + +static double const stbsp__bot[23] = { + 1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009, 1e+010, 1e+011, + 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019, 1e+020, 1e+021, 1e+022 +}; +static double const stbsp__negbot[22] = { + 1e-001, 1e-002, 1e-003, 1e-004, 1e-005, 1e-006, 1e-007, 1e-008, 1e-009, 1e-010, 1e-011, + 1e-012, 1e-013, 1e-014, 1e-015, 1e-016, 1e-017, 1e-018, 1e-019, 1e-020, 1e-021, 1e-022 +}; +static double const stbsp__negboterr[22] = { + -5.551115123125783e-018, -2.0816681711721684e-019, -2.0816681711721686e-020, -4.7921736023859299e-021, -8.1803053914031305e-022, 4.5251888174113741e-023, + 4.5251888174113739e-024, -2.0922560830128471e-025, -6.2281591457779853e-026, -3.6432197315497743e-027, 6.0503030718060191e-028, 2.0113352370744385e-029, + -3.0373745563400371e-030, 1.1806906454401013e-032, -7.7705399876661076e-032, 2.0902213275965398e-033, -7.1542424054621921e-034, -7.1542424054621926e-035, + 2.4754073164739869e-036, 5.4846728545790429e-037, 9.2462547772103625e-038, -4.8596774326570872e-039 +}; +static double const stbsp__top[13] = { + 1e+023, 1e+046, 1e+069, 1e+092, 1e+115, 1e+138, 1e+161, 1e+184, 1e+207, 1e+230, 1e+253, 1e+276, 1e+299 +}; +static double const stbsp__negtop[13] = { + 1e-023, 1e-046, 1e-069, 1e-092, 1e-115, 1e-138, 1e-161, 1e-184, 1e-207, 1e-230, 1e-253, 1e-276, 1e-299 +}; +static double const stbsp__toperr[13] = { + 8388608, + 6.8601809640529717e+028, + -7.253143638152921e+052, + -4.3377296974619174e+075, + -1.5559416129466825e+098, + -3.2841562489204913e+121, + -3.7745893248228135e+144, + -1.7356668416969134e+167, + -3.8893577551088374e+190, + -9.9566444326005119e+213, + 6.3641293062232429e+236, + -5.2069140800249813e+259, + -5.2504760255204387e+282 +}; +static double const stbsp__negtoperr[13] = { + 3.9565301985100693e-040, -2.299904345391321e-063, 3.6506201437945798e-086, 1.1875228833981544e-109, + -5.0644902316928607e-132, -6.7156837247865426e-155, -2.812077463003139e-178, -5.7778912386589953e-201, + 7.4997100559334532e-224, -4.6439668915134491e-247, -6.3691100762962136e-270, -9.436808465446358e-293, + 8.0970921678014997e-317 +}; + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) +static stbsp__uint64 const stbsp__powten[20] = { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000, + 100000000000, + 1000000000000, + 10000000000000, + 100000000000000, + 1000000000000000, + 10000000000000000, + 100000000000000000, + 1000000000000000000, + 10000000000000000000U +}; +#define stbsp__tento19th ((stbsp__uint64)1000000000000000000) +#else +static stbsp__uint64 const stbsp__powten[20] = { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000ULL, + 100000000000ULL, + 1000000000000ULL, + 10000000000000ULL, + 100000000000000ULL, + 1000000000000000ULL, + 10000000000000000ULL, + 100000000000000000ULL, + 1000000000000000000ULL, + 10000000000000000000ULL +}; +#define stbsp__tento19th (1000000000000000000ULL) +#endif + +#define stbsp__ddmulthi(oh, ol, xh, yh) \ + { \ + double ahi = 0, alo, bhi = 0, blo; \ + stbsp__int64 bt; \ + oh = xh * yh; \ + STBSP__COPYFP(bt, xh); \ + bt &= ((~(stbsp__uint64)0) << 27); \ + STBSP__COPYFP(ahi, bt); \ + alo = xh - ahi; \ + STBSP__COPYFP(bt, yh); \ + bt &= ((~(stbsp__uint64)0) << 27); \ + STBSP__COPYFP(bhi, bt); \ + blo = yh - bhi; \ + ol = ((ahi * bhi - oh) + ahi * blo + alo * bhi) + alo * blo; \ + } + +#define stbsp__ddtoS64(ob, xh, xl) \ + { \ + double ahi = 0, alo, vh, t; \ + ob = (stbsp__int64)xh; \ + vh = (double)ob; \ + ahi = (xh - vh); \ + t = (ahi - xh); \ + alo = (xh - (ahi - t)) - (vh + t); \ + ob += (stbsp__int64)(ahi + alo + xl); \ + } + +#define stbsp__ddrenorm(oh, ol) \ + { \ + double s; \ + s = oh + ol; \ + ol = ol - (s - oh); \ + oh = s; \ + } + +#define stbsp__ddmultlo(oh, ol, xh, xl, yh, yl) ol = ol + (xh * yl + xl * yh); + +#define stbsp__ddmultlos(oh, ol, xh, yl) ol = ol + (xh * yl); + +static void stbsp__raise_to_power10(double *ohi, double *olo, double d, stbsp__int32 power) // power can be -323 to +350 +{ + double ph, pl; + if ((power >= 0) && (power <= 22)) { + stbsp__ddmulthi(ph, pl, d, stbsp__bot[power]); + } else { + stbsp__int32 e, et, eb; + double p2h, p2l; + + e = power; + if (power < 0) + e = -e; + et = (e * 0x2c9) >> 14; /* %23 */ + if (et > 13) + et = 13; + eb = e - (et * 23); + + ph = d; + pl = 0.0; + if (power < 0) { + if (eb) { + --eb; + stbsp__ddmulthi(ph, pl, d, stbsp__negbot[eb]); + stbsp__ddmultlos(ph, pl, d, stbsp__negboterr[eb]); + } + if (et) { + stbsp__ddrenorm(ph, pl); + --et; + stbsp__ddmulthi(p2h, p2l, ph, stbsp__negtop[et]); + stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__negtop[et], stbsp__negtoperr[et]); + ph = p2h; + pl = p2l; + } + } else { + if (eb) { + e = eb; + if (eb > 22) + eb = 22; + e -= eb; + stbsp__ddmulthi(ph, pl, d, stbsp__bot[eb]); + if (e) { + stbsp__ddrenorm(ph, pl); + stbsp__ddmulthi(p2h, p2l, ph, stbsp__bot[e]); + stbsp__ddmultlos(p2h, p2l, stbsp__bot[e], pl); + ph = p2h; + pl = p2l; + } + } + if (et) { + stbsp__ddrenorm(ph, pl); + --et; + stbsp__ddmulthi(p2h, p2l, ph, stbsp__top[et]); + stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__top[et], stbsp__toperr[et]); + ph = p2h; + pl = p2l; + } + } + } + stbsp__ddrenorm(ph, pl); + *ohi = ph; + *olo = pl; +} + +// given a float value, returns the significant bits in bits, and the position of the +// decimal point in decimal_pos. +/-INF and NAN are specified by special values +// returned in the decimal_pos parameter. +// frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000 +static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits) +{ + double d; + stbsp__int64 bits = 0; + stbsp__int32 expo, e, ng, tens; + + d = value; + STBSP__COPYFP(bits, d); + expo = (stbsp__int32)((bits >> 52) & 2047); + ng = (stbsp__int32)((stbsp__uint64) bits >> 63); + if (ng) + d = -d; + + if (expo == 2047) // is nan or inf? + { + *start = (bits & ((((stbsp__uint64)1) << 52) - 1)) ? "NaN" : "Inf"; + *decimal_pos = STBSP__SPECIAL; + *len = 3; + return ng; + } + + if (expo == 0) // is zero or denormal + { + if (((stbsp__uint64) bits << 1) == 0) // do zero + { + *decimal_pos = 1; + *start = out; + out[0] = '0'; + *len = 1; + return ng; + } + // find the right expo for denormals + { + stbsp__int64 v = ((stbsp__uint64)1) << 51; + while ((bits & v) == 0) { + --expo; + v >>= 1; + } + } + } + + // find the decimal exponent as well as the decimal bits of the value + { + double ph, pl; + + // log10 estimate - very specifically tweaked to hit or undershoot by no more than 1 of log10 of all expos 1..2046 + tens = expo - 1023; + tens = (tens < 0) ? ((tens * 617) / 2048) : (((tens * 1233) / 4096) + 1); + + // move the significant bits into position and stick them into an int + stbsp__raise_to_power10(&ph, &pl, d, 18 - tens); + + // get full as much precision from double-double as possible + stbsp__ddtoS64(bits, ph, pl); + + // check if we undershot + if (((stbsp__uint64)bits) >= stbsp__tento19th) + ++tens; + } + + // now do the rounding in integer land + frac_digits = (frac_digits & 0x80000000) ? ((frac_digits & 0x7ffffff) + 1) : (tens + frac_digits); + if ((frac_digits < 24)) { + stbsp__uint32 dg = 1; + if ((stbsp__uint64)bits >= stbsp__powten[9]) + dg = 10; + while ((stbsp__uint64)bits >= stbsp__powten[dg]) { + ++dg; + if (dg == 20) + goto noround; + } + if (frac_digits < dg) { + stbsp__uint64 r; + // add 0.5 at the right position and round + e = dg - frac_digits; + if ((stbsp__uint32)e >= 24) + goto noround; + r = stbsp__powten[e]; + bits = bits + (r / 2); + if ((stbsp__uint64)bits >= stbsp__powten[dg]) + ++tens; + bits /= r; + } + noround:; + } + + // kill long trailing runs of zeros + if (bits) { + stbsp__uint32 n; + for (;;) { + if (bits <= 0xffffffff) + break; + if (bits % 1000) + goto donez; + bits /= 1000; + } + n = (stbsp__uint32)bits; + while ((n % 1000) == 0) + n /= 1000; + bits = n; + donez:; + } + + // convert to string + out += 64; + e = 0; + for (;;) { + stbsp__uint32 n; + char *o = out - 8; + // do the conversion in chunks of U32s (avoid most 64-bit divides, worth it, constant denomiators be damned) + if (bits >= 100000000) { + n = (stbsp__uint32)(bits % 100000000); + bits /= 100000000; + } else { + n = (stbsp__uint32)bits; + bits = 0; + } + while (n) { + out -= 2; + *(stbsp__uint16 *)out = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2]; + n /= 100; + e += 2; + } + if (bits == 0) { + if ((e) && (out[0] == '0')) { + ++out; + --e; + } + break; + } + while (out != o) { + *--out = '0'; + ++e; + } + } + + *decimal_pos = tens; + *start = out; + *len = e; + return ng; +} + +#undef stbsp__ddmulthi +#undef stbsp__ddrenorm +#undef stbsp__ddmultlo +#undef stbsp__ddmultlos +#undef STBSP__SPECIAL +#undef STBSP__COPYFP + +#endif // STB_SPRINTF_NOFLOAT + +// clean up +#undef stbsp__uint16 +#undef stbsp__uint32 +#undef stbsp__int32 +#undef stbsp__uint64 +#undef stbsp__int64 +#undef STBSP__UNALIGNED + +#endif // STB_SPRINTF_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_textedit.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_textedit.h new file mode 100644 index 0000000..1442493 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_textedit.h @@ -0,0 +1,1429 @@ +// stb_textedit.h - v1.14 - public domain - Sean Barrett +// Development of this library was sponsored by RAD Game Tools +// +// This C header file implements the guts of a multi-line text-editing +// widget; you implement display, word-wrapping, and low-level string +// insertion/deletion, and stb_textedit will map user inputs into +// insertions & deletions, plus updates to the cursor position, +// selection state, and undo state. +// +// It is intended for use in games and other systems that need to build +// their own custom widgets and which do not have heavy text-editing +// requirements (this library is not recommended for use for editing large +// texts, as its performance does not scale and it has limited undo). +// +// Non-trivial behaviors are modelled after Windows text controls. +// +// +// LICENSE +// +// See end of file for license information. +// +// +// DEPENDENCIES +// +// Uses the C runtime function 'memmove', which you can override +// by defining STB_TEXTEDIT_memmove before the implementation. +// Uses no other functions. Performs no runtime allocations. +// +// +// VERSION HISTORY +// +// 1.14 (2021-07-11) page up/down, various fixes +// 1.13 (2019-02-07) fix bug in undo size management +// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash +// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield +// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual +// 1.9 (2016-08-27) customizable move-by-word +// 1.8 (2016-04-02) better keyboard handling when mouse button is down +// 1.7 (2015-09-13) change y range handling in case baseline is non-0 +// 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove +// 1.5 (2014-09-10) add support for secondary keys for OS X +// 1.4 (2014-08-17) fix signed/unsigned warnings +// 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary +// 1.2 (2014-05-27) fix some RAD types that had crept into the new code +// 1.1 (2013-12-15) move-by-word (requires STB_TEXTEDIT_IS_SPACE ) +// 1.0 (2012-07-26) improve documentation, initial public release +// 0.3 (2012-02-24) bugfixes, single-line mode; insert mode +// 0.2 (2011-11-28) fixes to undo/redo +// 0.1 (2010-07-08) initial version +// +// ADDITIONAL CONTRIBUTORS +// +// Ulf Winklemann: move-by-word in 1.1 +// Fabian Giesen: secondary key inputs in 1.5 +// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 +// Louis Schnellbach: page up/down in 1.14 +// +// Bugfixes: +// Scott Graham +// Daniel Keller +// Omar Cornut +// Dan Thompson +// +// USAGE +// +// This file behaves differently depending on what symbols you define +// before including it. +// +// +// Header-file mode: +// +// If you do not define STB_TEXTEDIT_IMPLEMENTATION before including this, +// it will operate in "header file" mode. In this mode, it declares a +// single public symbol, STB_TexteditState, which encapsulates the current +// state of a text widget (except for the string, which you will store +// separately). +// +// To compile in this mode, you must define STB_TEXTEDIT_CHARTYPE to a +// primitive type that defines a single character (e.g. char, wchar_t, etc). +// +// To save space or increase undo-ability, you can optionally define the +// following things that are used by the undo system: +// +// STB_TEXTEDIT_POSITIONTYPE small int type encoding a valid cursor position +// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow +// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer +// +// If you don't define these, they are set to permissive types and +// moderate sizes. The undo system does no memory allocations, so +// it grows STB_TexteditState by the worst-case storage which is (in bytes): +// +// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATECOUNT +// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHARCOUNT +// +// +// Implementation mode: +// +// If you define STB_TEXTEDIT_IMPLEMENTATION before including this, it +// will compile the implementation of the text edit widget, depending +// on a large number of symbols which must be defined before the include. +// +// The implementation is defined only as static functions. You will then +// need to provide your own APIs in the same file which will access the +// static functions. +// +// The basic concept is that you provide a "string" object which +// behaves like an array of characters. stb_textedit uses indices to +// refer to positions in the string, implicitly representing positions +// in the displayed textedit. This is true for both plain text and +// rich text; even with rich text stb_truetype interacts with your +// code as if there was an array of all the displayed characters. +// +// Symbols that must be the same in header-file and implementation mode: +// +// STB_TEXTEDIT_CHARTYPE the character type +// STB_TEXTEDIT_POSITIONTYPE small type that is a valid cursor position +// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow +// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer +// +// Symbols you must define for implementation mode: +// +// STB_TEXTEDIT_STRING the type of object representing a string being edited, +// typically this is a wrapper object with other data you need +// +// STB_TEXTEDIT_STRINGLEN(obj) the length of the string (ideally O(1)) +// STB_TEXTEDIT_LAYOUTROW(&r,obj,n) returns the results of laying out a line of characters +// starting from character #n (see discussion below) +// STB_TEXTEDIT_GETWIDTH(obj,n,i) returns the pixel delta from the xpos of the i'th character +// to the xpos of the i+1'th char for a line of characters +// starting at character #n (i.e. accounts for kerning +// with previous char) +// STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character +// (return type is int, -1 means not valid to insert) +// STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based +// STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize +// as manually wordwrapping for end-of-line positioning +// +// STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i +// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*) +// +// STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key +// +// STB_TEXTEDIT_K_LEFT keyboard input to move cursor left +// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right +// STB_TEXTEDIT_K_UP keyboard input to move cursor up +// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down +// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page +// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page +// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME +// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END +// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME +// STB_TEXTEDIT_K_TEXTEND keyboard input to move cursor to end of text // e.g. ctrl-END +// STB_TEXTEDIT_K_DELETE keyboard input to delete selection or character under cursor +// STB_TEXTEDIT_K_BACKSPACE keyboard input to delete selection or character left of cursor +// STB_TEXTEDIT_K_UNDO keyboard input to perform undo +// STB_TEXTEDIT_K_REDO keyboard input to perform redo +// +// Optional: +// STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode +// STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'), +// required for default WORDLEFT/WORDRIGHT handlers +// STB_TEXTEDIT_MOVEWORDLEFT(obj,i) custom handler for WORDLEFT, returns index to move cursor to +// STB_TEXTEDIT_MOVEWORDRIGHT(obj,i) custom handler for WORDRIGHT, returns index to move cursor to +// STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT +// STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT +// STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line +// STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line +// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text +// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text +// +// Keyboard input must be encoded as a single integer value; e.g. a character code +// and some bitflags that represent shift states. to simplify the interface, SHIFT must +// be a bitflag, so we can test the shifted state of cursor movements to allow selection, +// i.e. (STB_TEXTEDIT_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow. +// +// You can encode other things, such as CONTROL or ALT, in additional bits, and +// then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example, +// my Windows implementations add an additional CONTROL bit, and an additional KEYDOWN +// bit. Then all of the STB_TEXTEDIT_K_ values bitwise-or in the KEYDOWN bit, +// and I pass both WM_KEYDOWN and WM_CHAR events to the "key" function in the +// API below. The control keys will only match WM_KEYDOWN events because of the +// keydown bit I add, and STB_TEXTEDIT_KEYTOTEXT only tests for the KEYDOWN +// bit so it only decodes WM_CHAR events. +// +// STB_TEXTEDIT_LAYOUTROW returns information about the shape of one displayed +// row of characters assuming they start on the i'th character--the width and +// the height and the number of characters consumed. This allows this library +// to traverse the entire layout incrementally. You need to compute word-wrapping +// here. +// +// Each textfield keeps its own insert mode state, which is not how normal +// applications work. To keep an app-wide insert mode, update/copy the +// "insert_mode" field of STB_TexteditState before/after calling API functions. +// +// API +// +// void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) +// +// void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) +// void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) +// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) +// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) +// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key) +// +// Each of these functions potentially updates the string and updates the +// state. +// +// initialize_state: +// set the textedit state to a known good default state when initially +// constructing the textedit. +// +// click: +// call this with the mouse x,y on a mouse down; it will update the cursor +// and reset the selection start/end to the cursor point. the x,y must +// be relative to the text widget, with (0,0) being the top left. +// +// drag: +// call this with the mouse x,y on a mouse drag/up; it will update the +// cursor and the selection end point +// +// cut: +// call this to delete the current selection; returns true if there was +// one. you should FIRST copy the current selection to the system paste buffer. +// (To copy, just copy the current selection out of the string yourself.) +// +// paste: +// call this to paste text at the current cursor point or over the current +// selection if there is one. +// +// key: +// call this for keyboard inputs sent to the textfield. you can use it +// for "key down" events or for "translated" key events. if you need to +// do both (as in Win32), or distinguish Unicode characters from control +// inputs, set a high bit to distinguish the two; then you can define the +// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit +// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is +// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to +// anything other type you wante before including. +// +// +// When rendering, you can read the cursor position and selection state from +// the STB_TexteditState. +// +// +// Notes: +// +// This is designed to be usable in IMGUI, so it allows for the possibility of +// running in an IMGUI that has NOT cached the multi-line layout. For this +// reason, it provides an interface that is compatible with computing the +// layout incrementally--we try to make sure we make as few passes through +// as possible. (For example, to locate the mouse pointer in the text, we +// could define functions that return the X and Y positions of characters +// and binary search Y and then X, but if we're doing dynamic layout this +// will run the layout algorithm many times, so instead we manually search +// forward in one pass. Similar logic applies to e.g. up-arrow and +// down-arrow movement.) +// +// If it's run in a widget that *has* cached the layout, then this is less +// efficient, but it's not horrible on modern computers. But you wouldn't +// want to edit million-line files with it. + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//// +//// Header-file mode +//// +//// + +#ifndef INCLUDE_STB_TEXTEDIT_H +#define INCLUDE_STB_TEXTEDIT_H + +//////////////////////////////////////////////////////////////////////// +// +// STB_TexteditState +// +// Definition of STB_TexteditState which you should store +// per-textfield; it includes cursor position, selection state, +// and undo state. +// + +#ifndef STB_TEXTEDIT_UNDOSTATECOUNT +#define STB_TEXTEDIT_UNDOSTATECOUNT 99 +#endif +#ifndef STB_TEXTEDIT_UNDOCHARCOUNT +#define STB_TEXTEDIT_UNDOCHARCOUNT 999 +#endif +#ifndef STB_TEXTEDIT_CHARTYPE +#define STB_TEXTEDIT_CHARTYPE int +#endif +#ifndef STB_TEXTEDIT_POSITIONTYPE +#define STB_TEXTEDIT_POSITIONTYPE int +#endif + +typedef struct +{ + // private data + STB_TEXTEDIT_POSITIONTYPE where; + STB_TEXTEDIT_POSITIONTYPE insert_length; + STB_TEXTEDIT_POSITIONTYPE delete_length; + int char_storage; +} StbUndoRecord; + +typedef struct +{ + // private data + StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT]; + STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT]; + short undo_point, redo_point; + int undo_char_point, redo_char_point; +} StbUndoState; + +typedef struct +{ + ///////////////////// + // + // public data + // + + int cursor; + // position of the text cursor within the string + + int select_start; // selection start point + int select_end; + // selection start and end point in characters; if equal, no selection. + // note that start may be less than or greater than end (e.g. when + // dragging the mouse, start is where the initial click was, and you + // can drag in either direction) + + unsigned char insert_mode; + // each textfield keeps its own insert mode state. to keep an app-wide + // insert mode, copy this value in/out of the app state + + int row_count_per_page; + // page size in number of row. + // this value MUST be set to >0 for pageup or pagedown in multilines documents. + + ///////////////////// + // + // private data + // + unsigned char cursor_at_end_of_line; // not implemented yet + unsigned char initialized; + unsigned char has_preferred_x; + unsigned char single_line; + unsigned char padding1, padding2, padding3; + float preferred_x; // this determines where the cursor up/down tries to seek to along x + StbUndoState undostate; +} STB_TexteditState; + + +//////////////////////////////////////////////////////////////////////// +// +// StbTexteditRow +// +// Result of layout query, used by stb_textedit to determine where +// the text in each row is. + +// result of layout query +typedef struct +{ + float x0,x1; // starting x location, end x location (allows for align=right, etc) + float baseline_y_delta; // position of baseline relative to previous row's baseline + float ymin,ymax; // height of row above and below baseline + int num_chars; +} StbTexteditRow; +#endif //INCLUDE_STB_TEXTEDIT_H + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//// +//// Implementation mode +//// +//// + + +// implementation isn't include-guarded, since it might have indirectly +// included just the "header" portion +#ifdef STB_TEXTEDIT_IMPLEMENTATION + +#ifndef STB_TEXTEDIT_memmove +#include +#define STB_TEXTEDIT_memmove memmove +#endif + + +///////////////////////////////////////////////////////////////////////////// +// +// Mouse input handling +// + +// traverse the layout to locate the nearest character to a display position +static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y) +{ + StbTexteditRow r; + int n = STB_TEXTEDIT_STRINGLEN(str); + float base_y = 0, prev_x; + int i=0, k; + + r.x0 = r.x1 = 0; + r.ymin = r.ymax = 0; + r.num_chars = 0; + + // search rows to find one that straddles 'y' + while (i < n) { + STB_TEXTEDIT_LAYOUTROW(&r, str, i); + if (r.num_chars <= 0) + return n; + + if (i==0 && y < base_y + r.ymin) + return 0; + + if (y < base_y + r.ymax) + break; + + i += r.num_chars; + base_y += r.baseline_y_delta; + } + + // below all text, return 'after' last character + if (i >= n) + return n; + + // check if it's before the beginning of the line + if (x < r.x0) + return i; + + // check if it's before the end of the line + if (x < r.x1) { + // search characters in row for one that straddles 'x' + prev_x = r.x0; + for (k=0; k < r.num_chars; ++k) { + float w = STB_TEXTEDIT_GETWIDTH(str, i, k); + if (x < prev_x+w) { + if (x < prev_x+w/2) + return k+i; + else + return k+i+1; + } + prev_x += w; + } + // shouldn't happen, but if it does, fall through to end-of-line case + } + + // if the last character is a newline, return that. otherwise return 'after' the last character + if (STB_TEXTEDIT_GETCHAR(str, i+r.num_chars-1) == STB_TEXTEDIT_NEWLINE) + return i+r.num_chars-1; + else + return i+r.num_chars; +} + +// API click: on mouse down, move the cursor to the clicked location, and reset the selection +static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) +{ + // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse + // goes off the top or bottom of the text + if( state->single_line ) + { + StbTexteditRow r; + STB_TEXTEDIT_LAYOUTROW(&r, str, 0); + y = r.ymin; + } + + state->cursor = stb_text_locate_coord(str, x, y); + state->select_start = state->cursor; + state->select_end = state->cursor; + state->has_preferred_x = 0; +} + +// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location +static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) +{ + int p = 0; + + // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse + // goes off the top or bottom of the text + if( state->single_line ) + { + StbTexteditRow r; + STB_TEXTEDIT_LAYOUTROW(&r, str, 0); + y = r.ymin; + } + + if (state->select_start == state->select_end) + state->select_start = state->cursor; + + p = stb_text_locate_coord(str, x, y); + state->cursor = state->select_end = p; +} + +///////////////////////////////////////////////////////////////////////////// +// +// Keyboard input handling +// + +// forward declarations +static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); +static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); +static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length); +static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length); +static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length); + +typedef struct +{ + float x,y; // position of n'th character + float height; // height of line + int first_char, length; // first char of row, and length + int prev_first; // first char of previous row +} StbFindState; + +// find the x/y location of a character, and remember info about the previous row in +// case we get a move-up event (for page up, we'll have to rescan) +static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line) +{ + StbTexteditRow r; + int prev_start = 0; + int z = STB_TEXTEDIT_STRINGLEN(str); + int i=0, first; + + if (n == z) { + // if it's at the end, then find the last line -- simpler than trying to + // explicitly handle this case in the regular code + if (single_line) { + STB_TEXTEDIT_LAYOUTROW(&r, str, 0); + find->y = 0; + find->first_char = 0; + find->length = z; + find->height = r.ymax - r.ymin; + find->x = r.x1; + } else { + find->y = 0; + find->x = 0; + find->height = 1; + while (i < z) { + STB_TEXTEDIT_LAYOUTROW(&r, str, i); + prev_start = i; + i += r.num_chars; + } + find->first_char = i; + find->length = 0; + find->prev_first = prev_start; + } + return; + } + + // search rows to find the one that straddles character n + find->y = 0; + + for(;;) { + STB_TEXTEDIT_LAYOUTROW(&r, str, i); + if (n < i + r.num_chars) + break; + prev_start = i; + i += r.num_chars; + find->y += r.baseline_y_delta; + } + + find->first_char = first = i; + find->length = r.num_chars; + find->height = r.ymax - r.ymin; + find->prev_first = prev_start; + + // now scan to find xpos + find->x = r.x0; + for (i=0; first+i < n; ++i) + find->x += STB_TEXTEDIT_GETWIDTH(str, first, i); +} + +#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) + +// make the selection/cursor state valid if client altered the string +static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) +{ + int n = STB_TEXTEDIT_STRINGLEN(str); + if (STB_TEXT_HAS_SELECTION(state)) { + if (state->select_start > n) state->select_start = n; + if (state->select_end > n) state->select_end = n; + // if clamping forced them to be equal, move the cursor to match + if (state->select_start == state->select_end) + state->cursor = state->select_start; + } + if (state->cursor > n) state->cursor = n; +} + +// delete characters while updating undo +static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len) +{ + stb_text_makeundo_delete(str, state, where, len); + STB_TEXTEDIT_DELETECHARS(str, where, len); + state->has_preferred_x = 0; +} + +// delete the section +static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) +{ + stb_textedit_clamp(str, state); + if (STB_TEXT_HAS_SELECTION(state)) { + if (state->select_start < state->select_end) { + stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start); + state->select_end = state->cursor = state->select_start; + } else { + stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end); + state->select_start = state->cursor = state->select_end; + } + state->has_preferred_x = 0; + } +} + +// canoncialize the selection so start <= end +static void stb_textedit_sortselection(STB_TexteditState *state) +{ + if (state->select_end < state->select_start) { + int temp = state->select_end; + state->select_end = state->select_start; + state->select_start = temp; + } +} + +// move cursor to first character of selection +static void stb_textedit_move_to_first(STB_TexteditState *state) +{ + if (STB_TEXT_HAS_SELECTION(state)) { + stb_textedit_sortselection(state); + state->cursor = state->select_start; + state->select_end = state->select_start; + state->has_preferred_x = 0; + } +} + +// move cursor to last character of selection +static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) +{ + if (STB_TEXT_HAS_SELECTION(state)) { + stb_textedit_sortselection(state); + stb_textedit_clamp(str, state); + state->cursor = state->select_end; + state->select_start = state->select_end; + state->has_preferred_x = 0; + } +} + +#ifdef STB_TEXTEDIT_IS_SPACE +static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx ) +{ + return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1; +} + +#ifndef STB_TEXTEDIT_MOVEWORDLEFT +static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c ) +{ + --c; // always move at least one character + while( c >= 0 && !is_word_boundary( str, c ) ) + --c; + + if( c < 0 ) + c = 0; + + return c; +} +#define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous +#endif + +#ifndef STB_TEXTEDIT_MOVEWORDRIGHT +static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c ) +{ + const int len = STB_TEXTEDIT_STRINGLEN(str); + ++c; // always move at least one character + while( c < len && !is_word_boundary( str, c ) ) + ++c; + + if( c > len ) + c = len; + + return c; +} +#define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next +#endif + +#endif + +// update selection and cursor to match each other +static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state) +{ + if (!STB_TEXT_HAS_SELECTION(state)) + state->select_start = state->select_end = state->cursor; + else + state->cursor = state->select_end; +} + +// API cut: delete selection +static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) +{ + if (STB_TEXT_HAS_SELECTION(state)) { + stb_textedit_delete_selection(str,state); // implicitly clamps + state->has_preferred_x = 0; + return 1; + } + return 0; +} + +// API paste: replace existing selection with passed-in text +static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) +{ + // if there's a selection, the paste should delete it + stb_textedit_clamp(str, state); + stb_textedit_delete_selection(str,state); + // try to insert the characters + if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) { + stb_text_makeundo_insert(state, state->cursor, len); + state->cursor += len; + state->has_preferred_x = 0; + return 1; + } + // note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details) + return 0; +} + +#ifndef STB_TEXTEDIT_KEYTYPE +#define STB_TEXTEDIT_KEYTYPE int +#endif + +// API key: process a keyboard input +static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key) +{ +retry: + switch (key) { + default: { + int c = STB_TEXTEDIT_KEYTOTEXT(key); + if (c > 0) { + STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c; + + // can't add newline in single-line mode + if (c == '\n' && state->single_line) + break; + + if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) { + stb_text_makeundo_replace(str, state, state->cursor, 1, 1); + STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1); + if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { + ++state->cursor; + state->has_preferred_x = 0; + } + } else { + stb_textedit_delete_selection(str,state); // implicitly clamps + if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { + stb_text_makeundo_insert(state, state->cursor, 1); + ++state->cursor; + state->has_preferred_x = 0; + } + } + } + break; + } + +#ifdef STB_TEXTEDIT_K_INSERT + case STB_TEXTEDIT_K_INSERT: + state->insert_mode = !state->insert_mode; + break; +#endif + + case STB_TEXTEDIT_K_UNDO: + stb_text_undo(str, state); + state->has_preferred_x = 0; + break; + + case STB_TEXTEDIT_K_REDO: + stb_text_redo(str, state); + state->has_preferred_x = 0; + break; + + case STB_TEXTEDIT_K_LEFT: + // if currently there's a selection, move cursor to start of selection + if (STB_TEXT_HAS_SELECTION(state)) + stb_textedit_move_to_first(state); + else + if (state->cursor > 0) + --state->cursor; + state->has_preferred_x = 0; + break; + + case STB_TEXTEDIT_K_RIGHT: + // if currently there's a selection, move cursor to end of selection + if (STB_TEXT_HAS_SELECTION(state)) + stb_textedit_move_to_last(str, state); + else + ++state->cursor; + stb_textedit_clamp(str, state); + state->has_preferred_x = 0; + break; + + case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT: + stb_textedit_clamp(str, state); + stb_textedit_prep_selection_at_cursor(state); + // move selection left + if (state->select_end > 0) + --state->select_end; + state->cursor = state->select_end; + state->has_preferred_x = 0; + break; + +#ifdef STB_TEXTEDIT_MOVEWORDLEFT + case STB_TEXTEDIT_K_WORDLEFT: + if (STB_TEXT_HAS_SELECTION(state)) + stb_textedit_move_to_first(state); + else { + state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); + stb_textedit_clamp( str, state ); + } + break; + + case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT: + if( !STB_TEXT_HAS_SELECTION( state ) ) + stb_textedit_prep_selection_at_cursor(state); + + state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); + state->select_end = state->cursor; + + stb_textedit_clamp( str, state ); + break; +#endif + +#ifdef STB_TEXTEDIT_MOVEWORDRIGHT + case STB_TEXTEDIT_K_WORDRIGHT: + if (STB_TEXT_HAS_SELECTION(state)) + stb_textedit_move_to_last(str, state); + else { + state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); + stb_textedit_clamp( str, state ); + } + break; + + case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT: + if( !STB_TEXT_HAS_SELECTION( state ) ) + stb_textedit_prep_selection_at_cursor(state); + + state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); + state->select_end = state->cursor; + + stb_textedit_clamp( str, state ); + break; +#endif + + case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT: + stb_textedit_prep_selection_at_cursor(state); + // move selection right + ++state->select_end; + stb_textedit_clamp(str, state); + state->cursor = state->select_end; + state->has_preferred_x = 0; + break; + + case STB_TEXTEDIT_K_DOWN: + case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: + case STB_TEXTEDIT_K_PGDOWN: + case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: { + StbFindState find; + StbTexteditRow row; + int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; + int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN; + int row_count = is_page ? state->row_count_per_page : 1; + + if (!is_page && state->single_line) { + // on windows, up&down in single-line behave like left&right + key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT); + goto retry; + } + + if (sel) + stb_textedit_prep_selection_at_cursor(state); + else if (STB_TEXT_HAS_SELECTION(state)) + stb_textedit_move_to_last(str, state); + + // compute current position of cursor point + stb_textedit_clamp(str, state); + stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); + + for (j = 0; j < row_count; ++j) { + float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x; + int start = find.first_char + find.length; + + if (find.length == 0) + break; + + // now find character position down a row + state->cursor = start; + STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); + x = row.x0; + for (i=0; i < row.num_chars; ++i) { + float dx = STB_TEXTEDIT_GETWIDTH(str, start, i); + #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE + if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) + break; + #endif + x += dx; + if (x > goal_x) + break; + ++state->cursor; + } + stb_textedit_clamp(str, state); + + state->has_preferred_x = 1; + state->preferred_x = goal_x; + + if (sel) + state->select_end = state->cursor; + + // go to next line + find.first_char = find.first_char + find.length; + find.length = row.num_chars; + } + break; + } + + case STB_TEXTEDIT_K_UP: + case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: + case STB_TEXTEDIT_K_PGUP: + case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: { + StbFindState find; + StbTexteditRow row; + int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; + int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP; + int row_count = is_page ? state->row_count_per_page : 1; + + if (!is_page && state->single_line) { + // on windows, up&down become left&right + key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT); + goto retry; + } + + if (sel) + stb_textedit_prep_selection_at_cursor(state); + else if (STB_TEXT_HAS_SELECTION(state)) + stb_textedit_move_to_first(state); + + // compute current position of cursor point + stb_textedit_clamp(str, state); + stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); + + for (j = 0; j < row_count; ++j) { + float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x; + + // can only go up if there's a previous row + if (find.prev_first == find.first_char) + break; + + // now find character position up a row + state->cursor = find.prev_first; + STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); + x = row.x0; + for (i=0; i < row.num_chars; ++i) { + float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i); + #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE + if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) + break; + #endif + x += dx; + if (x > goal_x) + break; + ++state->cursor; + } + stb_textedit_clamp(str, state); + + state->has_preferred_x = 1; + state->preferred_x = goal_x; + + if (sel) + state->select_end = state->cursor; + + // go to previous line + // (we need to scan previous line the hard way. maybe we could expose this as a new API function?) + prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0; + while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE) + --prev_scan; + find.first_char = find.prev_first; + find.prev_first = prev_scan; + } + break; + } + + case STB_TEXTEDIT_K_DELETE: + case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT: + if (STB_TEXT_HAS_SELECTION(state)) + stb_textedit_delete_selection(str, state); + else { + int n = STB_TEXTEDIT_STRINGLEN(str); + if (state->cursor < n) + stb_textedit_delete(str, state, state->cursor, 1); + } + state->has_preferred_x = 0; + break; + + case STB_TEXTEDIT_K_BACKSPACE: + case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT: + if (STB_TEXT_HAS_SELECTION(state)) + stb_textedit_delete_selection(str, state); + else { + stb_textedit_clamp(str, state); + if (state->cursor > 0) { + stb_textedit_delete(str, state, state->cursor-1, 1); + --state->cursor; + } + } + state->has_preferred_x = 0; + break; + +#ifdef STB_TEXTEDIT_K_TEXTSTART2 + case STB_TEXTEDIT_K_TEXTSTART2: +#endif + case STB_TEXTEDIT_K_TEXTSTART: + state->cursor = state->select_start = state->select_end = 0; + state->has_preferred_x = 0; + break; + +#ifdef STB_TEXTEDIT_K_TEXTEND2 + case STB_TEXTEDIT_K_TEXTEND2: +#endif + case STB_TEXTEDIT_K_TEXTEND: + state->cursor = STB_TEXTEDIT_STRINGLEN(str); + state->select_start = state->select_end = 0; + state->has_preferred_x = 0; + break; + +#ifdef STB_TEXTEDIT_K_TEXTSTART2 + case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT: +#endif + case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT: + stb_textedit_prep_selection_at_cursor(state); + state->cursor = state->select_end = 0; + state->has_preferred_x = 0; + break; + +#ifdef STB_TEXTEDIT_K_TEXTEND2 + case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT: +#endif + case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT: + stb_textedit_prep_selection_at_cursor(state); + state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str); + state->has_preferred_x = 0; + break; + + +#ifdef STB_TEXTEDIT_K_LINESTART2 + case STB_TEXTEDIT_K_LINESTART2: +#endif + case STB_TEXTEDIT_K_LINESTART: + stb_textedit_clamp(str, state); + stb_textedit_move_to_first(state); + if (state->single_line) + state->cursor = 0; + else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) + --state->cursor; + state->has_preferred_x = 0; + break; + +#ifdef STB_TEXTEDIT_K_LINEEND2 + case STB_TEXTEDIT_K_LINEEND2: +#endif + case STB_TEXTEDIT_K_LINEEND: { + int n = STB_TEXTEDIT_STRINGLEN(str); + stb_textedit_clamp(str, state); + stb_textedit_move_to_first(state); + if (state->single_line) + state->cursor = n; + else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) + ++state->cursor; + state->has_preferred_x = 0; + break; + } + +#ifdef STB_TEXTEDIT_K_LINESTART2 + case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT: +#endif + case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: + stb_textedit_clamp(str, state); + stb_textedit_prep_selection_at_cursor(state); + if (state->single_line) + state->cursor = 0; + else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) + --state->cursor; + state->select_end = state->cursor; + state->has_preferred_x = 0; + break; + +#ifdef STB_TEXTEDIT_K_LINEEND2 + case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT: +#endif + case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: { + int n = STB_TEXTEDIT_STRINGLEN(str); + stb_textedit_clamp(str, state); + stb_textedit_prep_selection_at_cursor(state); + if (state->single_line) + state->cursor = n; + else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) + ++state->cursor; + state->select_end = state->cursor; + state->has_preferred_x = 0; + break; + } + } +} + +///////////////////////////////////////////////////////////////////////////// +// +// Undo processing +// +// @OPTIMIZE: the undo/redo buffer should be circular + +static void stb_textedit_flush_redo(StbUndoState *state) +{ + state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; + state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; +} + +// discard the oldest entry in the undo list +static void stb_textedit_discard_undo(StbUndoState *state) +{ + if (state->undo_point > 0) { + // if the 0th undo state has characters, clean those up + if (state->undo_rec[0].char_storage >= 0) { + int n = state->undo_rec[0].insert_length, i; + // delete n characters from all other records + state->undo_char_point -= n; + STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE))); + for (i=0; i < state->undo_point; ++i) + if (state->undo_rec[i].char_storage >= 0) + state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it + } + --state->undo_point; + STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0]))); + } +} + +// discard the oldest entry in the redo list--it's bad if this +// ever happens, but because undo & redo have to store the actual +// characters in different cases, the redo character buffer can +// fill up even though the undo buffer didn't +static void stb_textedit_discard_redo(StbUndoState *state) +{ + int k = STB_TEXTEDIT_UNDOSTATECOUNT-1; + + if (state->redo_point <= k) { + // if the k'th undo state has characters, clean those up + if (state->undo_rec[k].char_storage >= 0) { + int n = state->undo_rec[k].insert_length, i; + // move the remaining redo character data to the end of the buffer + state->redo_char_point += n; + STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE))); + // adjust the position of all the other records to account for above memmove + for (i=state->redo_point; i < k; ++i) + if (state->undo_rec[i].char_storage >= 0) + state->undo_rec[i].char_storage += n; + } + // now move all the redo records towards the end of the buffer; the first one is at 'redo_point' + STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0]))); + // now move redo_point to point to the new one + ++state->redo_point; + } +} + +static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars) +{ + // any time we create a new undo record, we discard redo + stb_textedit_flush_redo(state); + + // if we have no free records, we have to make room, by sliding the + // existing records down + if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT) + stb_textedit_discard_undo(state); + + // if the characters to store won't possibly fit in the buffer, we can't undo + if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) { + state->undo_point = 0; + state->undo_char_point = 0; + return NULL; + } + + // if we don't have enough free characters in the buffer, we have to make room + while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT) + stb_textedit_discard_undo(state); + + return &state->undo_rec[state->undo_point++]; +} + +static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len) +{ + StbUndoRecord *r = stb_text_create_undo_record(state, insert_len); + if (r == NULL) + return NULL; + + r->where = pos; + r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len; + r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len; + + if (insert_len == 0) { + r->char_storage = -1; + return NULL; + } else { + r->char_storage = state->undo_char_point; + state->undo_char_point += insert_len; + return &state->undo_char[r->char_storage]; + } +} + +static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) +{ + StbUndoState *s = &state->undostate; + StbUndoRecord u, *r; + if (s->undo_point == 0) + return; + + // we need to do two things: apply the undo record, and create a redo record + u = s->undo_rec[s->undo_point-1]; + r = &s->undo_rec[s->redo_point-1]; + r->char_storage = -1; + + r->insert_length = u.delete_length; + r->delete_length = u.insert_length; + r->where = u.where; + + if (u.delete_length) { + // if the undo record says to delete characters, then the redo record will + // need to re-insert the characters that get deleted, so we need to store + // them. + + // there are three cases: + // there's enough room to store the characters + // characters stored for *redoing* don't leave room for redo + // characters stored for *undoing* don't leave room for redo + // if the last is true, we have to bail + + if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) { + // the undo records take up too much character space; there's no space to store the redo characters + r->insert_length = 0; + } else { + int i; + + // there's definitely room to store the characters eventually + while (s->undo_char_point + u.delete_length > s->redo_char_point) { + // should never happen: + if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) + return; + // there's currently not enough room, so discard a redo record + stb_textedit_discard_redo(s); + } + r = &s->undo_rec[s->redo_point-1]; + + r->char_storage = s->redo_char_point - u.delete_length; + s->redo_char_point = s->redo_char_point - u.delete_length; + + // now save the characters + for (i=0; i < u.delete_length; ++i) + s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i); + } + + // now we can carry out the deletion + STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length); + } + + // check type of recorded action: + if (u.insert_length) { + // easy case: was a deletion, so we need to insert n characters + STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length); + s->undo_char_point -= u.insert_length; + } + + state->cursor = u.where + u.insert_length; + + s->undo_point--; + s->redo_point--; +} + +static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) +{ + StbUndoState *s = &state->undostate; + StbUndoRecord *u, r; + if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) + return; + + // we need to do two things: apply the redo record, and create an undo record + u = &s->undo_rec[s->undo_point]; + r = s->undo_rec[s->redo_point]; + + // we KNOW there must be room for the undo record, because the redo record + // was derived from an undo record + + u->delete_length = r.insert_length; + u->insert_length = r.delete_length; + u->where = r.where; + u->char_storage = -1; + + if (r.delete_length) { + // the redo record requires us to delete characters, so the undo record + // needs to store the characters + + if (s->undo_char_point + u->insert_length > s->redo_char_point) { + u->insert_length = 0; + u->delete_length = 0; + } else { + int i; + u->char_storage = s->undo_char_point; + s->undo_char_point = s->undo_char_point + u->insert_length; + + // now save the characters + for (i=0; i < u->insert_length; ++i) + s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i); + } + + STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length); + } + + if (r.insert_length) { + // easy case: need to insert n characters + STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length); + s->redo_char_point += r.insert_length; + } + + state->cursor = r.where + r.insert_length; + + s->undo_point++; + s->redo_point++; +} + +static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length) +{ + stb_text_createundo(&state->undostate, where, 0, length); +} + +static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length) +{ + int i; + STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0); + if (p) { + for (i=0; i < length; ++i) + p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); + } +} + +static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length) +{ + int i; + STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length); + if (p) { + for (i=0; i < old_length; ++i) + p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); + } +} + +// reset the state to default +static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line) +{ + state->undostate.undo_point = 0; + state->undostate.undo_char_point = 0; + state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; + state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; + state->select_end = state->select_start = 0; + state->cursor = 0; + state->has_preferred_x = 0; + state->preferred_x = 0; + state->cursor_at_end_of_line = 0; + state->initialized = 1; + state->single_line = (unsigned char) is_single_line; + state->insert_mode = 0; + state->row_count_per_page = 0; +} + +// API initialize +static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) +{ + stb_textedit_clear_state(state, is_single_line); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len) +{ + return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif//STB_TEXTEDIT_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_tilemap_editor.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_tilemap_editor.h new file mode 100644 index 0000000..fbd3388 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_tilemap_editor.h @@ -0,0 +1,4187 @@ +// stb_tilemap_editor.h - v0.42 - Sean Barrett - http://nothings.org/stb +// placed in the public domain - not copyrighted - first released 2014-09 +// +// Embeddable tilemap editor for C/C++ +// +// +// TABLE OF CONTENTS +// FAQ +// How to compile/use the library +// Additional configuration macros +// API documentation +// Info on editing multiple levels +// Revision history +// Todo +// Credits +// License +// +// +// FAQ +// +// Q: What counts as a tilemap for this library? +// +// A: An array of rectangles, where each rectangle contains a small +// stack of images. +// +// Q: What are the limitations? +// +// A: Maps are limited to 4096x4096 in dimension. +// Each map square can only contain a stack of at most 32 images. +// A map can only use up to 32768 distinct image tiles. +// +// Q: How do I compile this? +// +// A: You need to #define several symbols before #including it, but only +// in one file. This will cause all the function definitions to be +// generated in that file. See the "HOW TO COMPILE" section. +// +// Q: What advantages does this have over a standalone editor? +// +// A: For one, you can integrate the editor into your game so you can +// flip between editing and testing without even switching windows. +// For another, you don't need an XML parser to get at the map data. +// +// Q: Can I live-edit my game maps? +// +// A: Not really, the editor keeps its own map representation. +// +// Q: How do I save and load maps? +// +// A: You have to do this yourself. The editor provides serialization +// functions (get & set) for reading and writing the map it holds. +// You can choose whatever format you want to store the map to on +// disk; you just need to provide functions to convert. (For example, +// I actually store the editor's map representation to disk basically +// as-is; then I have a single function that converts from the editor +// map representation to the game representation, which is used both +// to go from editor-to-game and from loaded-map-to-game.) +// +// Q: I want to have tiles change appearance based on what's +// adjacent, or other tile-display/substitution trickiness. +// +// A: You can do this when you convert from the editor's map +// representation to the game representation, but there's +// no way to show this live in the editor. +// +// Q: The editor appears to be put map location (0,0) at the top left? +// I want to use a different coordinate system in my game (e.g. y +// increasing upwards, or origin at the center). +// +// A: You can do this when you convert from the editor's map +// representation to the game representation. (Don't forget to +// translate link coordinates as well!) +// +// Q: The editor appears to put pixel (0,0) at the top left? I want +// to use a different coordinate system in my game. +// +// A: The editor defines an "editor pixel coordinate system" with +// (0,0) at the top left and requires you to display things in +// that coordinate system. You can freely remap those coordinates +// to anything you want on screen. +// +// Q: How do I scale the user interface? +// +// A: Since you do all the rendering, you can scale up all the rendering +// calls that the library makes to you. If you do, (a) you need +// to also scale up the mouse coordinates, and (b) you may want +// to scale the map display back down so that you're only scaling +// the UI and not everything. See the next question. +// +// Q: How do I scale the map display? +// +// A: Use stbte_set_spacing() to change the size that the map is displayed +// at. Note that the "callbacks" to draw tiles are used for both drawing +// the map and drawing the tile palette, so that callback may need to +// draw at two different scales. You should choose the scales to match +// You can tell them apart because the +// tile palette gets NULL for the property pointer. +// +// Q: How does object editing work? +// +// A: One way to think of this is that in the editor, you're placing +// spawners, not objects. Each spawner must be tile-aligned, because +// it's only a tile editor. Each tile (stack of layers) gets +// an associated set of properties, and it's up to you to +// determine what properties should appear for a given tile, +// based on e.g. the spawners that are in it. +// +// Q: How are properties themselves handled? +// +// A: All properties, regardless of UI behavior, are internally floats. +// Each tile has an array of floats associated with it, which is +// passed back to you when drawing the tiles so you can draw +// objects appropriately modified by the properties. +// +// Q: What if I want to have two different objects/spawners in +// one tile, both of which have their own properties? +// +// A: Make sure STBTE_MAX_PROPERTIES is large enough for the sum of +// properties in both objects, and then you have to explicitly +// map the property slot #s to the appropriate objects. They'll +// still all appear in a single property panel; there's no way +// to get multiple panels. +// +// Q: Can I do one-to-many linking? +// +// A: The library only supports one link per tile. However, you +// can have multiple tiles all link to a single tile. So, you +// can fake one-to-many linking by linking in the reverse +// direction. +// +// Q: What if I have two objects in the same tile, and they each +// need an independent link? Or I have two kinds of link associated +// with a single object? +// +// A: There is no way to do this. (Unless you can reverse one link.) +// +// Q: How does cut & paste interact with object properties & links? +// +// A: Currently the library has no idea which properties or links +// are associated with which layers of a tile. So currently, the +// library will only copy properties & links if the layer panel +// is set to allow all layers to be copied, OR if you set the +// "props" in the layer panel to "always". Similarly, you can +// set "props" to "none" so it will never copy. +// +// Q: What happens if the library gets a memory allocation failure +// while I'm editing? Will I lose my work? +// +// A: The library allocates all editor memory when you create +// the tilemap. It allocates a maximally-sized map and a +// fixed-size undo buffer (and the fixed-size copy buffer +// is static), and never allocates memory while it's running. +// So it can't fail due to running out of memory. +// +// Q: What happens if the library crashes while I'm editing? Will +// I lose my work? +// +// A: Yes. Save often. +// +// +// HOW TO COMPILE +// +// This header file contains both the header file and the +// implementation file in one. To create the implementation, +// in one source file define a few symbols first and then +// include this header: +// +// #define STB_TILEMAP_EDITOR_IMPLEMENTATION +// // this triggers the implementation +// +// void STBTE_DRAW_RECT(int x0, int y0, int x1, int y1, unsigned int color); +// // this must draw a filled rectangle (exclusive on right/bottom) +// // color = (r<<16)|(g<<8)|(b) +// +// void STBTE_DRAW_TILE(int x0, int y0, +// unsigned short id, int highlight, float *data); +// // this draws the tile image identified by 'id' in one of several +// // highlight modes (see STBTE_drawmode_* in the header section); +// // if 'data' is NULL, it's drawing the tile in the palette; if 'data' +// // is not NULL, it's drawing a tile on the map, and that is the data +// // associated with that map tile +// +// #include "stb_tilemap_editor.h" +// +// Optionally you can define the following functions before the include; +// note these must be macros (but they can just call a function) so +// this library can #ifdef to detect if you've defined them: +// +// #define STBTE_PROP_TYPE(int n, short *tiledata, float *params) ... +// // Returns the type of the n'th property of a given tile, which +// // controls how it is edited. Legal types are: +// // 0 /* no editable property in this slot */ +// // STBTE_PROP_int /* uses a slider to adjust value */ +// // STBTE_PROP_float /* uses a weird multi-axis control */ +// // STBTE_PROP_bool /* uses a checkbox to change value */ +// // And you can bitwise-OR in the following flags: +// // STBTE_PROP_disabled +// // Note that all of these are stored as floats in the param array. +// // The integer slider is limited in precision based on the space +// // available on screen, so for wide-ranged integers you may want +// // to use floats instead. +// // +// // Since the tiledata is passed to you, you can choose which property +// // is bound to that slot based on that data. +// // +// // Changing the type of a parameter does not cause the underlying +// // value to be clamped to the type min/max except when the tile is +// // explicitly selected. +// +// #define STBTE_PROP_NAME(int n, short *tiledata, float *params) ... +// // these return a string with the name for slot #n in the float +// // property list for the tile. +// +// #define STBTE_PROP_MIN(int n, short *tiledata) ...your code here... +// #define STBTE_PROP_MAX(int n, short *tiledata) ...your code here... +// // These return the allowable range for the property values for +// // the specified slot. It is never called for boolean types. +// +// #define STBTE_PROP_FLOAT_SCALE(int n, short *tiledata, float *params) +// // This rescales the float control for a given property; by default +// // left mouse drags add integers, right mouse drags adds fractions, +// // but you can rescale this per-property. +// +// #define STBTE_FLOAT_CONTROL_GRANULARITY ... value ... +// // This returns the number of pixels of mouse motion necessary +// // to advance the object float control. Default is 4 +// +// #define STBTE_ALLOW_LINK(short *src, float *src_data, \ +// short *dest, float *dest_data) ...your code... +// // this returns true or false depending on whether you allow a link +// // to be drawn from a tile 'src' to a tile 'dest'. if you don't +// // define this, linking will not be supported +// +// #define STBTE_LINK_COLOR(short *src, float *src_data, \ +// short *dest, float *dest_data) ...your code... +// // return a color encoded as a 24-bit unsigned integer in the +// // form 0xRRGGBB. If you don't define this, default colors will +// // be used. +// +// +// [[ support for those below is not implemented yet ]] +// +// #define STBTE_HITTEST_TILE(x0,y0,id,mx,my) ...your code here... +// // this returns true or false depending on whether the mouse +// // pointer at mx,my is over (touching) a tile of type 'id' +// // displayed at x0,y0. Normally stb_tilemap_editor just does +// // this hittest based on the tile geometry, but if you have +// // tiles whose images extend out of the tile, you'll need this. +// +// ADDITIONAL CONFIGURATION +// +// The following symbols set static limits which determine how much +// memory will be allocated for the editor. You can override them +// by making similar definitions, but memory usage will increase. +// +// #define STBTE_MAX_TILEMAP_X 200 // max 4096 +// #define STBTE_MAX_TILEMAP_Y 200 // max 4096 +// #define STBTE_MAX_LAYERS 8 // max 32 +// #define STBTE_MAX_CATEGORIES 100 +// #define STBTE_UNDO_BUFFER_BYTES (1 << 24) // 16 MB +// #define STBTE_MAX_COPY 90000 // e.g. 300x300 +// #define STBTE_MAX_PROPERTIES 10 // max properties per tile +// +// API +// +// Further documentation appears in the header-file section below. +// +// EDITING MULTIPLE LEVELS +// +// You can only have one active editor instance. To switch between multiple +// levels, you can either store the levels in your own format and copy them +// in and out of the editor format, or you can create multiple stbte_tilemap +// objects and switch between them. The latter has the advantage that each +// stbte_tilemap keeps its own undo state. (The clipboard is global, so +// either approach allows cut&pasting between levels.) +// +// REVISION HISTORY +// 0.42 fix compilation errors +// 0.41 fix warnings +// 0.40 fix warning +// 0.39 fix warning +// 0.38 fix warning +// 0.37 fix warning +// 0.36 minor compiler support +// 0.35 layername button changes +// - layername buttons grow with the layer panel +// - fix stbte_create_map being declared as stbte_create +// - fix declaration of stbte_create_map +// 0.30 properties release +// - properties panel for editing user-defined "object" properties +// - can link each tile to one other tile +// - keyboard interface +// - fix eraser tool bug (worked in complex cases, failed in simple) +// - undo/redo tools have visible disabled state +// - tiles on higher layers draw on top of adjacent lower-layer tiles +// 0.20 erasable release +// - eraser tool +// - fix bug when pasting into protected layer +// - better color scheme +// - internal-use color picker +// 0.10 initial release +// +// TODO +// +// Separate scroll state for each category +// Implement paint bucket +// Support STBTE_HITTEST_TILE above +// ?Cancel drags by clicking other button? - may be fixed +// Finish support for toolbar at side +// +// CREDITS +// +// +// Main editor & features +// Sean Barrett +// Additional features: +// Josh Huelsman +// Bugfixes: +// Ryan Whitworth +// Eugene Opalev +// Rob Loach +// github:wernsey +// +// LICENSE +// +// See end of file for license information. + + + +/////////////////////////////////////////////////////////////////////// +// +// HEADER SECTION + +#ifndef STB_TILEMAP_INCLUDE_STB_TILEMAP_EDITOR_H +#define STB_TILEMAP_INCLUDE_STB_TILEMAP_EDITOR_H + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #include + #include +#endif + +typedef struct stbte_tilemap stbte_tilemap; + +// these are the drawmodes used in STBTE_DRAW_TILE +enum +{ + STBTE_drawmode_deemphasize = -1, + STBTE_drawmode_normal = 0, + STBTE_drawmode_emphasize = 1, +}; + +// these are the property types +#define STBTE_PROP_none 0 +#define STBTE_PROP_int 1 +#define STBTE_PROP_float 2 +#define STBTE_PROP_bool 3 +#define STBTE_PROP_disabled 4 + +//////// +// +// creation +// + +extern stbte_tilemap *stbte_create_map(int map_x, int map_y, int map_layers, int spacing_x, int spacing_y, int max_tiles); +// create an editable tilemap +// map_x : dimensions of map horizontally (user can change this in editor), <= STBTE_MAX_TILEMAP_X +// map_y : dimensions of map vertically (user can change this in editor) <= STBTE_MAX_TILEMAP_Y +// map_layers : number of layers to use (fixed), <= STBTE_MAX_LAYERS +// spacing_x : initial horizontal distance between left edges of map tiles in stb_tilemap_editor pixels +// spacing_y : initial vertical distance between top edges of map tiles in stb_tilemap_editor pixels +// max_tiles : maximum number of tiles that can defined +// +// If insufficient memory, returns NULL + +extern void stbte_define_tile(stbte_tilemap *tm, unsigned short id, unsigned int layermask, const char * category); +// call this repeatedly for each tile to install the tile definitions into the editable tilemap +// tm : tilemap created by stbte_create_map +// id : unique identifier for each tile, 0 <= id < 32768 +// layermask : bitmask of which layers tile is allowed on: 1 = layer 0, 255 = layers 0..7 +// (note that onscreen, the editor numbers the layers from 1 not 0) +// layer 0 is the furthest back, layer 1 is just in front of layer 0, etc +// category : which category this tile is grouped in + +extern void stbte_set_display(int x0, int y0, int x1, int y1); +// call this once to set the size; if you resize, call it again + + +///////// +// +// every frame +// + +extern void stbte_draw(stbte_tilemap *tm); + +extern void stbte_tick(stbte_tilemap *tm, float time_in_seconds_since_last_frame); + +//////////// +// +// user input +// + +// if you're using SDL, call the next function for SDL_MOUSEMOTION, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP, SDL_MOUSEWHEEL; +// the transformation lets you scale from SDL mouse coords to stb_tilemap_editor coords +extern void stbte_mouse_sdl(stbte_tilemap *tm, const void *sdl_event, float xscale, float yscale, int xoffset, int yoffset); + +// otherwise, hook these up explicitly: +extern void stbte_mouse_move(stbte_tilemap *tm, int x, int y, int shifted, int scrollkey); +extern void stbte_mouse_button(stbte_tilemap *tm, int x, int y, int right, int down, int shifted, int scrollkey); +extern void stbte_mouse_wheel(stbte_tilemap *tm, int x, int y, int vscroll); + +// note: at the moment, mouse wheel events (SDL_MOUSEWHEEL) are ignored. + +// for keyboard, define your own mapping from keys to the following actions. +// this is totally optional, as all features are accessible with the mouse +enum stbte_action +{ + STBTE_tool_select, + STBTE_tool_brush, + STBTE_tool_erase, + STBTE_tool_rectangle, + STBTE_tool_eyedropper, + STBTE_tool_link, + STBTE_act_toggle_grid, + STBTE_act_toggle_links, + STBTE_act_undo, + STBTE_act_redo, + STBTE_act_cut, + STBTE_act_copy, + STBTE_act_paste, + STBTE_scroll_left, + STBTE_scroll_right, + STBTE_scroll_up, + STBTE_scroll_down, +}; +extern void stbte_action(stbte_tilemap *tm, enum stbte_action act); + +//////////////// +// +// save/load +// +// There is no editor file format. You have to save and load the data yourself +// through the following functions. You can also use these functions to get the +// data to generate game-formatted levels directly. (But make sure you save +// first! You may also want to autosave to a temp file periodically, etc etc.) + +#define STBTE_EMPTY -1 + +extern void stbte_get_dimensions(stbte_tilemap *tm, int *max_x, int *max_y); +// get the dimensions of the level, since the user can change them + +extern short* stbte_get_tile(stbte_tilemap *tm, int x, int y); +// returns an array of shorts that is 'map_layers' in length. each short is +// either one of the tile_id values from define_tile, or STBTE_EMPTY. + +extern float *stbte_get_properties(stbte_tilemap *tm, int x, int y); +// get the property array associated with the tile at x,y. this is an +// array of floats that is STBTE_MAX_PROPERTIES in length; you have to +// interpret the slots according to the semantics you've chosen + +extern void stbte_get_link(stbte_tilemap *tm, int x, int y, int *destx, int *desty); +// gets the link associated with the tile at x,y. + +extern void stbte_set_dimensions(stbte_tilemap *tm, int max_x, int max_y); +// set the dimensions of the level, overrides previous stbte_create_map() +// values or anything the user has changed + +extern void stbte_clear_map(stbte_tilemap *tm); +// clears the map, including the region outside the defined region, so if the +// user expands the map, they won't see garbage there + +extern void stbte_set_tile(stbte_tilemap *tm, int x, int y, int layer, signed short tile); +// tile is your tile_id from define_tile, or STBTE_EMPTY + +extern void stbte_set_property(stbte_tilemap *tm, int x, int y, int n, float val); +// set the value of the n'th slot of the tile at x,y + +extern void stbte_set_link(stbte_tilemap *tm, int x, int y, int destx, int desty); +// set a link going from x,y to destx,desty. to force no link, +// use destx=desty=-1 + +//////// +// +// optional +// + +extern void stbte_set_background_tile(stbte_tilemap *tm, short id); +// selects the tile to fill the bottom layer with and used to clear bottom tiles to; +// should be same ID as + +extern void stbte_set_sidewidths(int left, int right); +// call this once to set the left & right side widths. don't call +// it again since the user can change it + +extern void stbte_set_spacing(stbte_tilemap *tm, int spacing_x, int spacing_y, int palette_spacing_x, int palette_spacing_y); +// call this to set the spacing of map tiles and the spacing of palette tiles. +// if you rescale your display, call it again (e.g. you can implement map zooming yourself) + +extern void stbte_set_layername(stbte_tilemap *tm, int layer, const char *layername); +// sets a string name for your layer that shows in the layer selector. note that this +// makes the layer selector wider. 'layer' is from 0..(map_layers-1) + +#endif + +#ifdef STB_TILEMAP_EDITOR_IMPLEMENTATION + +#ifndef STBTE_ASSERT +#define STBTE_ASSERT assert +#include +#endif + +#ifdef _MSC_VER +#define STBTE__NOTUSED(v) (void)(v) +#else +#define STBTE__NOTUSED(v) (void)sizeof(v) +#endif + +#ifndef STBTE_MAX_TILEMAP_X +#define STBTE_MAX_TILEMAP_X 200 +#endif + +#ifndef STBTE_MAX_TILEMAP_Y +#define STBTE_MAX_TILEMAP_Y 200 +#endif + +#ifndef STBTE_MAX_LAYERS +#define STBTE_MAX_LAYERS 8 +#endif + +#ifndef STBTE_MAX_CATEGORIES +#define STBTE_MAX_CATEGORIES 100 +#endif + +#ifndef STBTE_MAX_COPY +#define STBTE_MAX_COPY 65536 +#endif + +#ifndef STBTE_UNDO_BUFFER_BYTES +#define STBTE_UNDO_BUFFER_BYTES (1 << 24) // 16 MB +#endif + +#ifndef STBTE_PROP_TYPE +#define STBTE__NO_PROPS +#define STBTE_PROP_TYPE(n,td,tp) 0 +#endif + +#ifndef STBTE_PROP_NAME +#define STBTE_PROP_NAME(n,td,tp) "" +#endif + +#ifndef STBTE_MAX_PROPERTIES +#define STBTE_MAX_PROPERTIES 10 +#endif + +#ifndef STBTE_PROP_MIN +#define STBTE_PROP_MIN(n,td,tp) 0 +#endif + +#ifndef STBTE_PROP_MAX +#define STBTE_PROP_MAX(n,td,tp) 100.0 +#endif + +#ifndef STBTE_PROP_FLOAT_SCALE +#define STBTE_PROP_FLOAT_SCALE(n,td,tp) 1 // default scale size +#endif + +#ifndef STBTE_FLOAT_CONTROL_GRANULARITY +#define STBTE_FLOAT_CONTROL_GRANULARITY 4 +#endif + + +#define STBTE__UNDO_BUFFER_COUNT (STBTE_UNDO_BUFFER_BYTES>>1) + +#if STBTE_MAX_TILEMAP_X > 4096 || STBTE_MAX_TILEMAP_Y > 4096 +#error "Maximum editable map size is 4096 x 4096" +#endif +#if STBTE_MAX_LAYERS > 32 +#error "Maximum layers allowed is 32" +#endif +#if STBTE_UNDO_BUFFER_COUNT & (STBTE_UNDO_BUFFER_COUNT-1) +#error "Undo buffer size must be a power of 2" +#endif + +#if STBTE_MAX_PROPERTIES == 0 +#define STBTE__NO_PROPS +#endif + +#ifdef STBTE__NO_PROPS +#undef STBTE_MAX_PROPERTIES +#define STBTE_MAX_PROPERTIES 1 // so we can declare arrays +#endif + +typedef struct +{ + short x,y; +} stbte__link; + +enum +{ + STBTE__base, + STBTE__outline, + STBTE__text, + + STBTE__num_color_aspects, +}; + +enum +{ + STBTE__idle, + STBTE__over, + STBTE__down, + STBTE__over_down, + STBTE__selected, + STBTE__selected_over, + STBTE__disabled, + STBTE__num_color_states, +}; + +enum +{ + STBTE__cexpander, + STBTE__ctoolbar, + STBTE__ctoolbar_button, + STBTE__cpanel, + STBTE__cpanel_sider, + STBTE__cpanel_sizer, + STBTE__cscrollbar, + STBTE__cmapsize, + STBTE__clayer_button, + STBTE__clayer_hide, + STBTE__clayer_lock, + STBTE__clayer_solo, + STBTE__ccategory_button, + + STBTE__num_color_modes, +}; + +#ifdef STBTE__COLORPICKER +static char *stbte__color_names[] = +{ + "expander", "toolbar", "tool button", "panel", + "panel c1", "panel c2", "scollbar", "map button", + "layer", "hide", "lock", "solo", + "category", +}; +#endif // STBTE__COLORPICKER + + // idle, over, down, over&down, selected, sel&over, disabled +static int stbte__color_table[STBTE__num_color_modes][STBTE__num_color_aspects][STBTE__num_color_states] = +{ + { + { 0x000000, 0x84987c, 0xdcdca8, 0xdcdca8, 0x40c040, 0x60d060, 0x505050, }, + { 0xa4b090, 0xe0ec80, 0xffffc0, 0xffffc0, 0x80ff80, 0x80ff80, 0x606060, }, + { 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0x909090, }, + }, { + { 0x808890, 0x606060, 0x606060, 0x606060, 0x606060, 0x606060, 0x606060, }, + { 0x605860, 0x606060, 0x606060, 0x606060, 0x606060, 0x606060, 0x606060, }, + { 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, }, + }, { + { 0x3c5068, 0x7088a8, 0x647488, 0x94b4dc, 0x8890c4, 0x9caccc, 0x404040, }, + { 0x889cb8, 0x889cb8, 0x889cb8, 0x889cb8, 0x84c4e8, 0xacc8ff, 0x0c0c08, }, + { 0xbcc4cc, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0x707074, }, + }, { + { 0x403848, 0x403010, 0x403010, 0x403010, 0x403010, 0x403010, 0x303024, }, + { 0x68546c, 0xc08040, 0xc08040, 0xc08040, 0xc08040, 0xc08040, 0x605030, }, + { 0xf4e4ff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0x909090, }, + }, { + { 0xb4b04c, 0xacac60, 0xc0ffc0, 0xc0ffc0, 0x40c040, 0x60d060, 0x505050, }, + { 0xa0a04c, 0xd0d04c, 0xffff80, 0xffff80, 0x80ff80, 0x80ff80, 0x606060, }, + { 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0x909090, }, + }, { + { 0x40c440, 0x60d060, 0xc0ffc0, 0xc0ffc0, 0x40c040, 0x60d060, 0x505050, }, + { 0x40c040, 0x80ff80, 0x80ff80, 0x80ff80, 0x80ff80, 0x80ff80, 0x606060, }, + { 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0x909090, }, + }, { + { 0x9090ac, 0xa0a0b8, 0xbcb8cc, 0xbcb8cc, 0x909040, 0x909040, 0x909040, }, + { 0xa0a0b8, 0xb0b4d0, 0xa0a0b8, 0xa0a0b8, 0xa0a050, 0xa0a050, 0xa0a050, }, + { 0x808088, 0x808030, 0x808030, 0x808030, 0x808030, 0x808030, 0x808030, }, + }, { + { 0x704c70, 0x885c8c, 0x9c68a4, 0xb870bc, 0xb490bc, 0xb490bc, 0x302828, }, + { 0x646064, 0xcca8d4, 0xc060c0, 0xa07898, 0xe0b8e0, 0xe0b8e0, 0x403838, }, + { 0xdccce4, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0x909090, }, + }, { + { 0x704c70, 0x885c8c, 0x9c68a4, 0xb870bc, 0xb490bc, 0xb490bc, 0x302828, }, + { 0xb09cb4, 0xcca8d4, 0xc060c0, 0xa07898, 0xe0b8e0, 0xe0b8e0, 0x403838, }, + { 0xdccce4, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0x909090, }, + }, { + { 0x646494, 0x888cb8, 0xb0b0b0, 0xb0b0cc, 0x9c9cf4, 0x8888b0, 0x50506c, }, + { 0x9090a4, 0xb0b4d4, 0xb0b0dc, 0xb0b0cc, 0xd0d0fc, 0xd0d4f0, 0x606060, }, + { 0xb4b4d4, 0xe4e4ff, 0xffffff, 0xffffff, 0xe0e4ff, 0xececff, 0x909090, }, + }, { + { 0x646444, 0x888c64, 0xb0b0b0, 0xb0b088, 0xaca858, 0x88886c, 0x505050, }, + { 0x88886c, 0xb0b490, 0xb0b0b0, 0xb0b088, 0xd8d898, 0xd0d4b0, 0x606060, }, + { 0xb4b49c, 0xffffd8, 0xffffff, 0xffffd4, 0xffffdc, 0xffffcc, 0x909090, }, + }, { + { 0x906464, 0xb48c8c, 0xd4b0b0, 0xdcb0b0, 0xff9c9c, 0xc88888, 0x505050, }, + { 0xb47c80, 0xd4b4b8, 0xc4a8a8, 0xdcb0b0, 0xffc0c0, 0xfce8ec, 0x606060, }, + { 0xe0b4b4, 0xffdcd8, 0xffd8d4, 0xffe0e4, 0xffece8, 0xffffff, 0x909090, }, + }, { + { 0x403848, 0x403848, 0x403848, 0x886894, 0x7c80c8, 0x7c80c8, 0x302828, }, + { 0x403848, 0x403848, 0x403848, 0x403848, 0x7c80c8, 0x7c80c8, 0x403838, }, + { 0xc8c4c8, 0xffffff, 0xffffff, 0xffffff, 0xe8e8ec, 0xffffff, 0x909090, }, + }, +}; + +#define STBTE_COLOR_TILEMAP_BACKGROUND 0x000000 +#define STBTE_COLOR_TILEMAP_BORDER 0x203060 +#define STBTE_COLOR_TILEMAP_HIGHLIGHT 0xffffff +#define STBTE_COLOR_GRID 0x404040 +#define STBTE_COLOR_SELECTION_OUTLINE1 0xdfdfdf +#define STBTE_COLOR_SELECTION_OUTLINE2 0x303030 +#define STBTE_COLOR_TILEPALETTE_OUTLINE 0xffffff +#define STBTE_COLOR_TILEPALETTE_BACKGROUND 0x000000 + +#ifndef STBTE_LINK_COLOR +#define STBTE_LINK_COLOR(src,sp,dest,dp) 0x5030ff +#endif + +#ifndef STBTE_LINK_COLOR_DRAWING +#define STBTE_LINK_COLOR_DRAWING 0xff40ff +#endif + +#ifndef STBTE_LINK_COLOR_DISALLOWED +#define STBTE_LINK_COLOR_DISALLOWED 0x602060 +#endif + + +// disabled, selected, down, over +static unsigned char stbte__state_to_index[2][2][2][2] = +{ + { + { { STBTE__idle , STBTE__over }, { STBTE__down , STBTE__over_down }, }, + { { STBTE__selected, STBTE__selected_over }, { STBTE__down , STBTE__over_down }, }, + },{ + { { STBTE__disabled, STBTE__disabled }, { STBTE__disabled, STBTE__disabled }, }, + { { STBTE__selected, STBTE__selected_over }, { STBTE__disabled, STBTE__disabled }, }, + } +}; +#define STBTE__INDEX_FOR_STATE(disable,select,down,over) stbte__state_to_index[disable][select][down][over] +#define STBTE__INDEX_FOR_ID(id,disable,select) STBTE__INDEX_FOR_STATE(disable,select,STBTE__IS_ACTIVE(id),STBTE__IS_HOT(id)) + +#define STBTE__FONT_HEIGHT 9 +static short stbte__font_offset[95+16]; +static short stbte__fontdata[769] = +{ + 4,9,6,9,9,9,9,8,9,8,4,9,7,7,7,7,4,2,6,8,6,6,7,3,4,4,8,6,3,6,2,6,6,6,6,6,6, + 6,6,6,6,6,2,3,5,4,5,6,6,6,6,6,6,6,6,6,6,6,6,7,6,7,7,7,6,7,6,6,6,6,7,7,6,6, + 6,4,6,4,7,7,3,6,6,5,6,6,5,6,6,4,5,6,4,7,6,6,6,6,6,6,6,6,6,7,6,6,6,5,2,5,8, + 0,0,0,0,2,253,130,456,156,8,72,184,64,2,125,66,64,160,64,146,511,146,146, + 511,146,146,511,146,511,257,341,297,341,297,341,257,511,16,56,124,16,16,16, + 124,56,16,96,144,270,261,262,136,80,48,224,192,160,80,40,22,14,15,3,448,496, + 496,240,232,20,10,5,2,112,232,452,450,225,113,58,28,63,30,60,200,455,257, + 257,0,0,0,257,257,455,120,204,132,132,159,14,4,4,14,159,132,132,204,120,8, + 24,56,120,56,24,8,32,48,56,60,56,48,32,0,0,0,0,111,111,7,7,0,0,7,7,34,127, + 127,34,34,127,127,34,36,46,107,107,58,18,99,51,24,12,102,99,48,122,79,93, + 55,114,80,4,7,3,62,127,99,65,65,99,127,62,8,42,62,28,28,62,42,8,8,8,62,62, + 8,8,128,224,96,8,8,8,8,8,8,96,96,96,48,24,12,6,3,62,127,89,77,127,62,64,66, + 127,127,64,64,98,115,89,77,71,66,33,97,73,93,119,35,24,28,22,127,127,16,39, + 103,69,69,125,57,62,127,73,73,121,48,1,1,113,121,15,7,54,127,73,73,127,54, + 6,79,73,105,63,30,54,54,128,246,118,8,28,54,99,65,20,20,20,20,65,99,54,28, + 8,2,3,105,109,7,2,30,63,33,45,47,46,124,126,19,19,126,124,127,127,73,73,127, + 54,62,127,65,65,99,34,127,127,65,99,62,28,127,127,73,73,73,65,127,127,9,9, + 9,1,62,127,65,73,121,121,127,127,8,8,127,127,65,65,127,127,65,65,32,96,64, + 64,127,63,127,127,8,28,54,99,65,127,127,64,64,64,64,127,127,6,12,6,127,127, + 127,127,6,12,24,127,127,62,127,65,65,65,127,62,127,127,9,9,15,6,62,127,65, + 81,49,127,94,127,127,9,25,127,102,70,79,73,73,121,49,1,1,127,127,1,1,63,127, + 64,64,127,63,15,31,48,96,48,31,15,127,127,48,24,48,127,127,99,119,28,28,119, + 99,7,15,120,120,15,7,97,113,89,77,71,67,127,127,65,65,3,6,12,24,48,96,65, + 65,127,127,8,12,6,3,6,12,8,64,64,64,64,64,64,64,3,7,4,32,116,84,84,124,120, + 127,127,68,68,124,56,56,124,68,68,68,56,124,68,68,127,127,56,124,84,84,92, + 24,8,124,126,10,10,56,380,324,324,508,252,127,127,4,4,124,120,72,122,122, + 64,256,256,256,506,250,126,126,16,56,104,64,66,126,126,64,124,124,24,56,28, + 124,120,124,124,4,4,124,120,56,124,68,68,124,56,508,508,68,68,124,56,56,124, + 68,68,508,508,124,124,4,4,12,8,72,92,84,84,116,36,4,4,62,126,68,68,60,124, + 64,64,124,124,28,60,96,96,60,28,28,124,112,56,112,124,28,68,108,56,56,108, + 68,284,316,352,320,508,252,68,100,116,92,76,68,8,62,119,65,65,127,127,65, + 65,119,62,8,16,24,12,12,24,24,12,4, +}; + +typedef struct +{ + short id; + unsigned short category_id; + char *category; + unsigned int layermask; +} stbte__tileinfo; + +#define MAX_LAYERMASK (1 << (8*sizeof(unsigned int))) + +typedef short stbte__tiledata; + +#define STBTE__NO_TILE -1 + +enum +{ + STBTE__panel_toolbar, + STBTE__panel_colorpick, + STBTE__panel_info, + STBTE__panel_layers, + STBTE__panel_props, + STBTE__panel_categories, + STBTE__panel_tiles, + + STBTE__num_panel, +}; + +enum +{ + STBTE__side_left, + STBTE__side_right, + STBTE__side_top, + STBTE__side_bottom, +}; + +enum +{ + STBTE__tool_select, + STBTE__tool_brush, + STBTE__tool_erase, + STBTE__tool_rect, + STBTE__tool_eyedrop, + STBTE__tool_fill, + STBTE__tool_link, + + STBTE__tool_showgrid, + STBTE__tool_showlinks, + + STBTE__tool_undo, + STBTE__tool_redo, + // copy/cut/paste aren't included here because they're displayed differently + + STBTE__num_tool, +}; + +// icons are stored in the 0-31 range of ASCII in the font +static int toolchar[] = { 26,24,25,20,23,22,18, 19,17, 29,28, }; + +enum +{ + STBTE__propmode_default, + STBTE__propmode_always, + STBTE__propmode_never, +}; + +enum +{ + STBTE__paint, + + // from here down does hittesting + STBTE__tick, + STBTE__mousemove, + STBTE__mousewheel, + STBTE__leftdown, + STBTE__leftup, + STBTE__rightdown, + STBTE__rightup, +}; + +typedef struct +{ + int expanded, mode; + int delta_height; // number of rows they've requested for this + int side; + int width,height; + int x0,y0; +} stbte__panel; + +typedef struct +{ + int x0,y0,x1,y1,color; +} stbte__colorrect; + +#define STBTE__MAX_DELAYRECT 256 + +typedef struct +{ + int tool, active_event; + int active_id, hot_id, next_hot_id; + int event; + int mx,my, dx,dy; + int ms_time; + int shift, scrollkey; + int initted; + int side_extended[2]; + stbte__colorrect delayrect[STBTE__MAX_DELAYRECT]; + int delaycount; + int show_grid, show_links; + int brush_state; // used to decide which kind of erasing + int eyedrop_x, eyedrop_y, eyedrop_last_layer; + int pasting, paste_x, paste_y; + int scrolling, start_x, start_y; + int last_mouse_x, last_mouse_y; + int accum_x, accum_y; + int linking; + int dragging; + int drag_x, drag_y, drag_w, drag_h; + int drag_offx, drag_offy, drag_dest_x, drag_dest_y; + int undoing; + int has_selection, select_x0, select_y0, select_x1, select_y1; + int sx,sy; + int x0,y0,x1,y1, left_width, right_width; // configurable widths + float alert_timer; + const char *alert_msg; + float dt; + stbte__panel panel[STBTE__num_panel]; + short copybuffer[STBTE_MAX_COPY][STBTE_MAX_LAYERS]; + float copyprops[STBTE_MAX_COPY][STBTE_MAX_PROPERTIES]; +#ifdef STBTE_ALLOW_LINK + stbte__link copylinks[STBTE_MAX_COPY]; +#endif + int copy_src_x, copy_src_y; + stbte_tilemap *copy_src; + int copy_width,copy_height,has_copy,copy_has_props; +} stbte__ui_t; + +// there's only one UI system at a time, so we can globalize this +static stbte__ui_t stbte__ui = { STBTE__tool_brush, 0 }; + +#define STBTE__INACTIVE() (stbte__ui.active_id == 0) +#define STBTE__IS_ACTIVE(id) (stbte__ui.active_id == (id)) +#define STBTE__IS_HOT(id) (stbte__ui.hot_id == (id)) + +#define STBTE__BUTTON_HEIGHT (STBTE__FONT_HEIGHT + 2 * STBTE__BUTTON_INTERNAL_SPACING) +#define STBTE__BUTTON_INTERNAL_SPACING (2 + (STBTE__FONT_HEIGHT>>4)) + +typedef struct +{ + const char *name; + int locked; + int hidden; +} stbte__layer; + +enum +{ + STBTE__unlocked, + STBTE__protected, + STBTE__locked, +}; + +struct stbte_tilemap +{ + stbte__tiledata data[STBTE_MAX_TILEMAP_Y][STBTE_MAX_TILEMAP_X][STBTE_MAX_LAYERS]; + float props[STBTE_MAX_TILEMAP_Y][STBTE_MAX_TILEMAP_X][STBTE_MAX_PROPERTIES]; + #ifdef STBTE_ALLOW_LINK + stbte__link link[STBTE_MAX_TILEMAP_Y][STBTE_MAX_TILEMAP_X]; + int linkcount[STBTE_MAX_TILEMAP_Y][STBTE_MAX_TILEMAP_X]; + #endif + int max_x, max_y, num_layers; + int spacing_x, spacing_y; + int palette_spacing_x, palette_spacing_y; + int scroll_x,scroll_y; + int cur_category, cur_tile, cur_layer; + char *categories[STBTE_MAX_CATEGORIES]; + int num_categories, category_scroll; + stbte__tileinfo *tiles; + int num_tiles, max_tiles, digits; + unsigned char undo_available_valid; + unsigned char undo_available; + unsigned char redo_available; + unsigned char padding; + int cur_palette_count; + int palette_scroll; + int tileinfo_dirty; + stbte__layer layerinfo[STBTE_MAX_LAYERS]; + int has_layer_names; + int layername_width; + int layer_scroll; + int propmode; + int solo_layer; + int undo_pos, undo_len, redo_len; + short background_tile; + unsigned char id_in_use[32768>>3]; + short *undo_buffer; +}; + +static char *default_category = (char*) "[unassigned]"; + +static void stbte__init_gui(void) +{ + int i,n; + stbte__ui.initted = 1; + // init UI state + stbte__ui.show_links = 1; + for (i=0; i < STBTE__num_panel; ++i) { + stbte__ui.panel[i].expanded = 1; // visible if not autohidden + stbte__ui.panel[i].delta_height = 0; + stbte__ui.panel[i].side = STBTE__side_left; + } + stbte__ui.panel[STBTE__panel_toolbar ].side = STBTE__side_top; + stbte__ui.panel[STBTE__panel_colorpick].side = STBTE__side_right; + + if (stbte__ui.left_width == 0) + stbte__ui.left_width = 80; + if (stbte__ui.right_width == 0) + stbte__ui.right_width = 80; + + // init font + n=95+16; + for (i=0; i < 95+16; ++i) { + stbte__font_offset[i] = n; + n += stbte__fontdata[i]; + } +} + +stbte_tilemap *stbte_create_map(int map_x, int map_y, int map_layers, int spacing_x, int spacing_y, int max_tiles) +{ + int i; + stbte_tilemap *tm; + STBTE_ASSERT(map_layers >= 0 && map_layers <= STBTE_MAX_LAYERS); + STBTE_ASSERT(map_x >= 0 && map_x <= STBTE_MAX_TILEMAP_X); + STBTE_ASSERT(map_y >= 0 && map_y <= STBTE_MAX_TILEMAP_Y); + if (map_x < 0 || map_y < 0 || map_layers < 0 || + map_x > STBTE_MAX_TILEMAP_X || map_y > STBTE_MAX_TILEMAP_Y || map_layers > STBTE_MAX_LAYERS) + return NULL; + + if (!stbte__ui.initted) + stbte__init_gui(); + + tm = (stbte_tilemap *) malloc(sizeof(*tm) + sizeof(*tm->tiles) * max_tiles + STBTE_UNDO_BUFFER_BYTES); + if (tm == NULL) + return NULL; + + tm->tiles = (stbte__tileinfo *) (tm+1); + tm->undo_buffer = (short *) (tm->tiles + max_tiles); + tm->num_layers = map_layers; + tm->max_x = map_x; + tm->max_y = map_y; + tm->spacing_x = spacing_x; + tm->spacing_y = spacing_y; + tm->scroll_x = 0; + tm->scroll_y = 0; + tm->palette_scroll = 0; + tm->palette_spacing_x = spacing_x+1; + tm->palette_spacing_y = spacing_y+1; + tm->cur_category = -1; + tm->cur_tile = 0; + tm->solo_layer = -1; + tm->undo_len = 0; + tm->redo_len = 0; + tm->undo_pos = 0; + tm->category_scroll = 0; + tm->layer_scroll = 0; + tm->propmode = 0; + tm->has_layer_names = 0; + tm->layername_width = 0; + tm->undo_available_valid = 0; + + for (i=0; i < tm->num_layers; ++i) { + tm->layerinfo[i].hidden = 0; + tm->layerinfo[i].locked = STBTE__unlocked; + tm->layerinfo[i].name = 0; + } + + tm->background_tile = STBTE__NO_TILE; + stbte_clear_map(tm); + + tm->max_tiles = max_tiles; + tm->num_tiles = 0; + for (i=0; i < 32768/8; ++i) + tm->id_in_use[i] = 0; + tm->tileinfo_dirty = 1; + return tm; +} + +void stbte_set_background_tile(stbte_tilemap *tm, short id) +{ + int i; + STBTE_ASSERT(id >= -1); + // STBTE_ASSERT(id < 32768); + if (id < -1) + return; + for (i=0; i < STBTE_MAX_TILEMAP_X * STBTE_MAX_TILEMAP_Y; ++i) + if (tm->data[0][i][0] == -1) + tm->data[0][i][0] = id; + tm->background_tile = id; +} + +void stbte_set_spacing(stbte_tilemap *tm, int spacing_x, int spacing_y, int palette_spacing_x, int palette_spacing_y) +{ + tm->spacing_x = spacing_x; + tm->spacing_y = spacing_y; + tm->palette_spacing_x = palette_spacing_x; + tm->palette_spacing_y = palette_spacing_y; +} + +void stbte_set_sidewidths(int left, int right) +{ + stbte__ui.left_width = left; + stbte__ui.right_width = right; +} + +void stbte_set_display(int x0, int y0, int x1, int y1) +{ + stbte__ui.x0 = x0; + stbte__ui.y0 = y0; + stbte__ui.x1 = x1; + stbte__ui.y1 = y1; +} + +void stbte_define_tile(stbte_tilemap *tm, unsigned short id, unsigned int layermask, const char * category_c) +{ + char *category = (char *) category_c; + STBTE_ASSERT(id < 32768); + STBTE_ASSERT(tm->num_tiles < tm->max_tiles); + STBTE_ASSERT((tm->id_in_use[id>>3]&(1<<(id&7))) == 0); + if (id >= 32768 || tm->num_tiles >= tm->max_tiles || (tm->id_in_use[id>>3]&(1<<(id&7)))) + return; + + if (category == NULL) + category = (char*) default_category; + tm->id_in_use[id>>3] |= 1 << (id&7); + tm->tiles[tm->num_tiles].category = category; + tm->tiles[tm->num_tiles].id = id; + tm->tiles[tm->num_tiles].layermask = layermask; + ++tm->num_tiles; + tm->tileinfo_dirty = 1; +} + +static int stbte__text_width(const char *str); + +void stbte_set_layername(stbte_tilemap *tm, int layer, const char *layername) +{ + STBTE_ASSERT(layer >= 0 && layer < tm->num_layers); + if (layer >= 0 && layer < tm->num_layers) { + int width; + tm->layerinfo[layer].name = layername; + tm->has_layer_names = 1; + width = stbte__text_width(layername); + tm->layername_width = (width > tm->layername_width ? width : tm->layername_width); + } +} + +void stbte_get_dimensions(stbte_tilemap *tm, int *max_x, int *max_y) +{ + *max_x = tm->max_x; + *max_y = tm->max_y; +} + +short* stbte_get_tile(stbte_tilemap *tm, int x, int y) +{ + STBTE_ASSERT(x >= 0 && x < tm->max_x && y >= 0 && y < tm->max_y); + if (x < 0 || x >= STBTE_MAX_TILEMAP_X || y < 0 || y >= STBTE_MAX_TILEMAP_Y) + return NULL; + return tm->data[y][x]; +} + +float *stbte_get_properties(stbte_tilemap *tm, int x, int y) +{ + STBTE_ASSERT(x >= 0 && x < tm->max_x && y >= 0 && y < tm->max_y); + if (x < 0 || x >= STBTE_MAX_TILEMAP_X || y < 0 || y >= STBTE_MAX_TILEMAP_Y) + return NULL; + return tm->props[y][x]; +} + +void stbte_get_link(stbte_tilemap *tm, int x, int y, int *destx, int *desty) +{ + int gx=-1,gy=-1; + STBTE_ASSERT(x >= 0 && x < tm->max_x && y >= 0 && y < tm->max_y); +#ifdef STBTE_ALLOW_LINK + if (x >= 0 && x < STBTE_MAX_TILEMAP_X && y >= 0 && y < STBTE_MAX_TILEMAP_Y) { + gx = tm->link[y][x].x; + gy = tm->link[y][x].y; + if (gx >= 0) + if (!STBTE_ALLOW_LINK(tm->data[y][x], tm->props[y][x], tm->data[gy][gx], tm->props[gy][gx])) + gx = gy = -1; + } +#endif + *destx = gx; + *desty = gy; +} + +void stbte_set_property(stbte_tilemap *tm, int x, int y, int n, float val) +{ + tm->props[y][x][n] = val; +} + +#ifdef STBTE_ALLOW_LINK +static void stbte__set_link(stbte_tilemap *tm, int src_x, int src_y, int dest_x, int dest_y, int undo_mode); +#endif + +enum +{ + STBTE__undo_none, + STBTE__undo_record, + STBTE__undo_block, +}; + +void stbte_set_link(stbte_tilemap *tm, int x, int y, int destx, int desty) +{ +#ifdef STBTE_ALLOW_LINK + stbte__set_link(tm, x, y, destx, desty, STBTE__undo_none); +#else + STBTE_ASSERT(0); +#endif +} + + +// returns an array of map_layers shorts. each short is either +// one of the tile_id values from define_tile, or STBTE_EMPTY + +void stbte_set_dimensions(stbte_tilemap *tm, int map_x, int map_y) +{ + STBTE_ASSERT(map_x >= 0 && map_x <= STBTE_MAX_TILEMAP_X); + STBTE_ASSERT(map_y >= 0 && map_y <= STBTE_MAX_TILEMAP_Y); + if (map_x < 0 || map_y < 0 || map_x > STBTE_MAX_TILEMAP_X || map_y > STBTE_MAX_TILEMAP_Y) + return; + tm->max_x = map_x; + tm->max_y = map_y; +} + +void stbte_clear_map(stbte_tilemap *tm) +{ + int i,j; + for (i=0; i < STBTE_MAX_TILEMAP_X * STBTE_MAX_TILEMAP_Y; ++i) { + tm->data[0][i][0] = tm->background_tile; + for (j=1; j < tm->num_layers; ++j) + tm->data[0][i][j] = STBTE__NO_TILE; + for (j=0; j < STBTE_MAX_PROPERTIES; ++j) + tm->props[0][i][j] = 0; + #ifdef STBTE_ALLOW_LINK + tm->link[0][i].x = -1; + tm->link[0][i].y = -1; + tm->linkcount[0][i] = 0; + #endif + } +} + +void stbte_set_tile(stbte_tilemap *tm, int x, int y, int layer, signed short tile) +{ + STBTE_ASSERT(x >= 0 && x < tm->max_x && y >= 0 && y < tm->max_y); + STBTE_ASSERT(layer >= 0 && layer < tm->num_layers); + STBTE_ASSERT(tile >= -1); + //STBTE_ASSERT(tile < 32768); + if (x < 0 || x >= STBTE_MAX_TILEMAP_X || y < 0 || y >= STBTE_MAX_TILEMAP_Y) + return; + if (layer < 0 || layer >= tm->num_layers || tile < -1) + return; + tm->data[y][x][layer] = tile; +} + +static void stbte__choose_category(stbte_tilemap *tm, int category) +{ + int i,n=0; + tm->cur_category = category; + for (i=0; i < tm->num_tiles; ++i) + if (tm->tiles[i].category_id == category || category == -1) + ++n; + tm->cur_palette_count = n; + tm->palette_scroll = 0; +} + +static int stbte__strequal(char *p, char *q) +{ + while (*p) + if (*p++ != *q++) return 0; + return *q == 0; +} + +static void stbte__compute_tileinfo(stbte_tilemap *tm) +{ + int i,j; + + tm->num_categories=0; + + for (i=0; i < tm->num_tiles; ++i) { + stbte__tileinfo *t = &tm->tiles[i]; + // find category + for (j=0; j < tm->num_categories; ++j) + if (stbte__strequal(t->category, tm->categories[j])) + goto found; + tm->categories[j] = t->category; + ++tm->num_categories; + found: + t->category_id = (unsigned short) j; + } + + // currently number of categories can never decrease because you + // can't remove tile definitions, but let's get it right anyway + if (tm->cur_category > tm->num_categories) { + tm->cur_category = -1; + } + + stbte__choose_category(tm, tm->cur_category); + + tm->tileinfo_dirty = 0; +} + +static void stbte__prepare_tileinfo(stbte_tilemap *tm) +{ + if (tm->tileinfo_dirty) + stbte__compute_tileinfo(tm); +} + + +/////////////////////// undo system //////////////////////// + +// the undo system works by storing "commands" into a buffer, and +// then playing back those commands. undo and redo have to store +// the commands in different order. +// +// the commands are: +// +// 1) end_of_undo_record +// -1:short +// +// 2) end_of_redo_record +// -2:short +// +// 3) tile update +// tile_id:short (-1..32767) +// x_coord:short +// y_coord:short +// layer:short (0..31) +// +// 4) property update (also used for links) +// value_hi:short +// value_lo:short +// y_coord:short +// x_coord:short +// property:short (256+prop#) +// +// Since we use a circular buffer, we might overwrite the undo storage. +// To detect this, before playing back commands we scan back and see +// if we see an end_of_undo_record before hitting the relevant boundary, +// it's wholly contained. +// +// When we read back through, we see them in reverse order, so +// we'll see the layer number or property number first +// +// To be clearer about the circular buffer, there are two cases: +// 1. a single record is larger than the whole buffer. +// this is caught because the end_of_undo_record will +// get overwritten. +// 2. multiple records written are larger than the whole +// buffer, so some of them have been overwritten by +// the later ones. this is handled by explicitly tracking +// the undo length; we never try to parse the data that +// got overwritten + +// given two points, compute the length between them +#define stbte__wrap(pos) ((pos) & (STBTE__UNDO_BUFFER_COUNT-1)) + +#define STBTE__undo_record -2 +#define STBTE__redo_record -3 +#define STBTE__undo_junk -4 // this is written underneath the undo pointer, never used + +static void stbte__write_undo(stbte_tilemap *tm, short value) +{ + int pos = tm->undo_pos; + tm->undo_buffer[pos] = value; + tm->undo_pos = stbte__wrap(pos+1); + tm->undo_len += (tm->undo_len < STBTE__UNDO_BUFFER_COUNT-2); + tm->redo_len -= (tm->redo_len > 0); + tm->undo_available_valid = 0; +} + +static void stbte__write_redo(stbte_tilemap *tm, short value) +{ + int pos = tm->undo_pos; + tm->undo_buffer[pos] = value; + tm->undo_pos = stbte__wrap(pos-1); + tm->redo_len += (tm->redo_len < STBTE__UNDO_BUFFER_COUNT-2); + tm->undo_len -= (tm->undo_len > 0); + tm->undo_available_valid = 0; +} + +static void stbte__begin_undo(stbte_tilemap *tm) +{ + tm->redo_len = 0; + stbte__write_undo(tm, STBTE__undo_record); + stbte__ui.undoing = 1; + stbte__ui.alert_msg = 0; // clear alert if they start doing something +} + +static void stbte__end_undo(stbte_tilemap *tm) +{ + if (stbte__ui.undoing) { + // check if anything got written + int pos = stbte__wrap(tm->undo_pos-1); + if (tm->undo_buffer[pos] == STBTE__undo_record) { + // empty undo record, move back + tm->undo_pos = pos; + STBTE_ASSERT(tm->undo_len > 0); + tm->undo_len -= 1; + } + tm->undo_buffer[tm->undo_pos] = STBTE__undo_junk; + // otherwise do nothing + + stbte__ui.undoing = 0; + } +} + +static void stbte__undo_record(stbte_tilemap *tm, int x, int y, int i, int v) +{ + STBTE_ASSERT(stbte__ui.undoing); + if (stbte__ui.undoing) { + stbte__write_undo(tm, v); + stbte__write_undo(tm, x); + stbte__write_undo(tm, y); + stbte__write_undo(tm, i); + } +} + +static void stbte__redo_record(stbte_tilemap *tm, int x, int y, int i, int v) +{ + stbte__write_redo(tm, v); + stbte__write_redo(tm, x); + stbte__write_redo(tm, y); + stbte__write_redo(tm, i); +} + +static float stbte__extract_float(short s0, short s1) +{ + union { float f; short s[2]; } converter; + converter.s[0] = s0; + converter.s[1] = s1; + return converter.f; +} + +static short stbte__extract_short(float f, int slot) +{ + union { float f; short s[2]; } converter; + converter.f = f; + return converter.s[slot]; +} + +static void stbte__undo_record_prop(stbte_tilemap *tm, int x, int y, int i, short s0, short s1) +{ + STBTE_ASSERT(stbte__ui.undoing); + if (stbte__ui.undoing) { + stbte__write_undo(tm, s1); + stbte__write_undo(tm, s0); + stbte__write_undo(tm, x); + stbte__write_undo(tm, y); + stbte__write_undo(tm, 256+i); + } +} + +static void stbte__undo_record_prop_float(stbte_tilemap *tm, int x, int y, int i, float f) +{ + stbte__undo_record_prop(tm, x,y,i, stbte__extract_short(f,0), stbte__extract_short(f,1)); +} + +static void stbte__redo_record_prop(stbte_tilemap *tm, int x, int y, int i, short s0, short s1) +{ + stbte__write_redo(tm, s1); + stbte__write_redo(tm, s0); + stbte__write_redo(tm, x); + stbte__write_redo(tm, y); + stbte__write_redo(tm, 256+i); +} + + +static int stbte__undo_find_end(stbte_tilemap *tm) +{ + // first scan through for the end record + int i, pos = stbte__wrap(tm->undo_pos-1); + for (i=0; i < tm->undo_len;) { + STBTE_ASSERT(tm->undo_buffer[pos] != STBTE__undo_junk); + if (tm->undo_buffer[pos] == STBTE__undo_record) + break; + if (tm->undo_buffer[pos] >= 255) + pos = stbte__wrap(pos-5), i += 5; + else + pos = stbte__wrap(pos-4), i += 4; + } + if (i >= tm->undo_len) + return -1; + return pos; +} + +static void stbte__undo(stbte_tilemap *tm) +{ + int i, pos, endpos; + endpos = stbte__undo_find_end(tm); + if (endpos < 0) + return; + + // we found a complete undo record + pos = stbte__wrap(tm->undo_pos-1); + + // start a redo record + stbte__write_redo(tm, STBTE__redo_record); + + // so now go back through undo and apply in reverse + // order, and copy it to redo + for (i=0; endpos != pos; i += 4) { + int x,y,n,v; + // get the undo entry + n = tm->undo_buffer[pos]; + y = tm->undo_buffer[stbte__wrap(pos-1)]; + x = tm->undo_buffer[stbte__wrap(pos-2)]; + v = tm->undo_buffer[stbte__wrap(pos-3)]; + if (n >= 255) { + short s0=0,s1=0; + int v2 = tm->undo_buffer[stbte__wrap(pos-4)]; + pos = stbte__wrap(pos-5); + if (n > 255) { + float vf = stbte__extract_float(v, v2); + s0 = stbte__extract_short(tm->props[y][x][n-256], 0); + s1 = stbte__extract_short(tm->props[y][x][n-256], 1); + tm->props[y][x][n-256] = vf; + } else { +#ifdef STBTE_ALLOW_LINK + s0 = tm->link[y][x].x; + s1 = tm->link[y][x].y; + stbte__set_link(tm, x,y, v, v2, STBTE__undo_none); +#endif + } + // write the redo entry + stbte__redo_record_prop(tm, x, y, n-256, s0,s1); + // apply the undo entry + } else { + pos = stbte__wrap(pos-4); + // write the redo entry + stbte__redo_record(tm, x, y, n, tm->data[y][x][n]); + // apply the undo entry + tm->data[y][x][n] = (short) v; + } + } + // overwrite undo record with junk + tm->undo_buffer[tm->undo_pos] = STBTE__undo_junk; +} + +static int stbte__redo_find_end(stbte_tilemap *tm) +{ + // first scan through for the end record + int i, pos = stbte__wrap(tm->undo_pos+1); + for (i=0; i < tm->redo_len;) { + STBTE_ASSERT(tm->undo_buffer[pos] != STBTE__undo_junk); + if (tm->undo_buffer[pos] == STBTE__redo_record) + break; + if (tm->undo_buffer[pos] >= 255) + pos = stbte__wrap(pos+5), i += 5; + else + pos = stbte__wrap(pos+4), i += 4; + } + if (i >= tm->redo_len) + return -1; // this should only ever happen if redo buffer is empty + return pos; +} + +static void stbte__redo(stbte_tilemap *tm) +{ + // first scan through for the end record + int i, pos, endpos; + endpos = stbte__redo_find_end(tm); + if (endpos < 0) + return; + + // we found a complete redo record + pos = stbte__wrap(tm->undo_pos+1); + + // start an undo record + stbte__write_undo(tm, STBTE__undo_record); + + for (i=0; pos != endpos; i += 4) { + int x,y,n,v; + n = tm->undo_buffer[pos]; + y = tm->undo_buffer[stbte__wrap(pos+1)]; + x = tm->undo_buffer[stbte__wrap(pos+2)]; + v = tm->undo_buffer[stbte__wrap(pos+3)]; + if (n >= 255) { + int v2 = tm->undo_buffer[stbte__wrap(pos+4)]; + short s0=0,s1=0; + pos = stbte__wrap(pos+5); + if (n > 255) { + float vf = stbte__extract_float(v, v2); + s0 = stbte__extract_short(tm->props[y][x][n-256],0); + s1 = stbte__extract_short(tm->props[y][x][n-256],1); + tm->props[y][x][n-256] = vf; + } else { +#ifdef STBTE_ALLOW_LINK + s0 = tm->link[y][x].x; + s1 = tm->link[y][x].y; + stbte__set_link(tm, x,y,v,v2, STBTE__undo_none); +#endif + } + // don't use stbte__undo_record_prop because it's guarded + stbte__write_undo(tm, s1); + stbte__write_undo(tm, s0); + stbte__write_undo(tm, x); + stbte__write_undo(tm, y); + stbte__write_undo(tm, n); + } else { + pos = stbte__wrap(pos+4); + // don't use stbte__undo_record because it's guarded + stbte__write_undo(tm, tm->data[y][x][n]); + stbte__write_undo(tm, x); + stbte__write_undo(tm, y); + stbte__write_undo(tm, n); + tm->data[y][x][n] = (short) v; + } + } + tm->undo_buffer[tm->undo_pos] = STBTE__undo_junk; +} + +// because detecting that undo is available +static void stbte__recompute_undo_available(stbte_tilemap *tm) +{ + tm->undo_available = (stbte__undo_find_end(tm) >= 0); + tm->redo_available = (stbte__redo_find_end(tm) >= 0); +} + +static int stbte__undo_available(stbte_tilemap *tm) +{ + if (!tm->undo_available_valid) + stbte__recompute_undo_available(tm); + return tm->undo_available; +} + +static int stbte__redo_available(stbte_tilemap *tm) +{ + if (!tm->undo_available_valid) + stbte__recompute_undo_available(tm); + return tm->redo_available; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef STBTE_ALLOW_LINK +static void stbte__set_link(stbte_tilemap *tm, int src_x, int src_y, int dest_x, int dest_y, int undo_mode) +{ + stbte__link *a; + STBTE_ASSERT(src_x >= 0 && src_x < STBTE_MAX_TILEMAP_X && src_y >= 0 && src_y < STBTE_MAX_TILEMAP_Y); + a = &tm->link[src_y][src_x]; + // check if it's a do nothing + if (a->x == dest_x && a->y == dest_y) + return; + if (undo_mode != STBTE__undo_none ) { + if (undo_mode == STBTE__undo_block) stbte__begin_undo(tm); + stbte__undo_record_prop(tm, src_x, src_y, -1, a->x, a->y); + if (undo_mode == STBTE__undo_block) stbte__end_undo(tm); + } + // check if there's an existing link + if (a->x >= 0) { + // decrement existing link refcount + STBTE_ASSERT(tm->linkcount[a->y][a->x] > 0); + --tm->linkcount[a->y][a->x]; + } + // increment new dest + if (dest_x >= 0) { + ++tm->linkcount[dest_y][dest_x]; + } + a->x = dest_x; + a->y = dest_y; +} +#endif + + +static void stbte__draw_rect(int x0, int y0, int x1, int y1, unsigned int color) +{ + STBTE_DRAW_RECT(x0,y0,x1,y1, color); +} + +#ifdef STBTE_ALLOW_LINK +static void stbte__draw_line(int x0, int y0, int x1, int y1, unsigned int color) +{ + int temp; + if (x1 < x0) temp=x0,x0=x1,x1=temp; + if (y1 < y0) temp=y0,y0=y1,y1=temp; + stbte__draw_rect(x0,y0,x1+1,y1+1,color); +} + +static void stbte__draw_link(int x0, int y0, int x1, int y1, unsigned int color) +{ + stbte__draw_line(x0,y0,x0,y1, color); + stbte__draw_line(x0,y1,x1,y1, color); +} +#endif + +static void stbte__draw_frame(int x0, int y0, int x1, int y1, unsigned int color) +{ + stbte__draw_rect(x0,y0,x1-1,y0+1,color); + stbte__draw_rect(x1-1,y0,x1,y1-1,color); + stbte__draw_rect(x0+1,y1-1,x1,y1,color); + stbte__draw_rect(x0,y0+1,x0+1,y1,color); +} + +static int stbte__get_char_width(int ch) +{ + return stbte__fontdata[ch-16]; +} + +static short *stbte__get_char_bitmap(int ch) +{ + return stbte__fontdata + stbte__font_offset[ch-16]; +} + +static void stbte__draw_bitmask_as_columns(int x, int y, short bitmask, int color) +{ + int start_i = -1, i=0; + while (bitmask) { + if (bitmask & (1<= 0) { + stbte__draw_rect(x, y+start_i, x+1, y+i, color); + start_i = -1; + bitmask &= ~((1< x_end) + break; + stbte__draw_bitmap(x, y, cw, stbte__get_char_bitmap(c), color); + if (digitspace && c == ' ') + cw = stbte__get_char_width('0'); + x += cw+1; + } +} + +static void stbte__draw_text(int x, int y, const char *str, int w, int color) +{ + stbte__draw_text_core(x,y,str,w,color,0); +} + +static int stbte__text_width(const char *str) +{ + int x = 0; + while (*str) { + int c = *str++; + int cw = stbte__get_char_width(c); + x += cw+1; + } + return x; +} + +static void stbte__draw_frame_delayed(int x0, int y0, int x1, int y1, int color) +{ + if (stbte__ui.delaycount < STBTE__MAX_DELAYRECT) { + stbte__colorrect r = { x0,y0,x1,y1,color }; + stbte__ui.delayrect[stbte__ui.delaycount++] = r; + } +} + +static void stbte__flush_delay(void) +{ + stbte__colorrect *r; + int i; + r = stbte__ui.delayrect; + for (i=0; i < stbte__ui.delaycount; ++i,++r) + stbte__draw_frame(r->x0,r->y0,r->x1,r->y1,r->color); + stbte__ui.delaycount = 0; +} + +static void stbte__activate(int id) +{ + stbte__ui.active_id = id; + stbte__ui.active_event = stbte__ui.event; + stbte__ui.accum_x = 0; + stbte__ui.accum_y = 0; +} + +static int stbte__hittest(int x0, int y0, int x1, int y1, int id) +{ + int over = stbte__ui.mx >= x0 && stbte__ui.my >= y0 + && stbte__ui.mx < x1 && stbte__ui.my < y1; + + if (over && stbte__ui.event >= STBTE__tick) + stbte__ui.next_hot_id = id; + + return over; +} + +static int stbte__button_core(int id) +{ + switch (stbte__ui.event) { + case STBTE__leftdown: + if (stbte__ui.hot_id == id && STBTE__INACTIVE()) + stbte__activate(id); + break; + case STBTE__leftup: + if (stbte__ui.active_id == id && STBTE__IS_HOT(id)) { + stbte__activate(0); + return 1; + } + break; + case STBTE__rightdown: + if (stbte__ui.hot_id == id && STBTE__INACTIVE()) + stbte__activate(id); + break; + case STBTE__rightup: + if (stbte__ui.active_id == id && STBTE__IS_HOT(id)) { + stbte__activate(0); + return -1; + } + break; + } + return 0; +} + +static void stbte__draw_box(int x0, int y0, int x1, int y1, int colormode, int colorindex) +{ + stbte__draw_rect (x0,y0,x1,y1, stbte__color_table[colormode][STBTE__base ][colorindex]); + stbte__draw_frame(x0,y0,x1,y1, stbte__color_table[colormode][STBTE__outline][colorindex]); +} + +static void stbte__draw_textbox(int x0, int y0, int x1, int y1, char *text, int xoff, int yoff, int colormode, int colorindex) +{ + stbte__draw_box(x0,y0,x1,y1,colormode,colorindex); + stbte__draw_text(x0+xoff,y0+yoff, text, x1-x0-xoff-1, stbte__color_table[colormode][STBTE__text][colorindex]); +} + +static int stbte__button(int colormode, const char *label, int x, int y, int textoff, int width, int id, int toggled, int disabled) +{ + int x0=x,y0=y, x1=x+width,y1=y+STBTE__BUTTON_HEIGHT; + int s = STBTE__BUTTON_INTERNAL_SPACING; + + if(!disabled) stbte__hittest(x0,y0,x1,y1,id); + + if (stbte__ui.event == STBTE__paint) + stbte__draw_textbox(x0,y0,x1,y1, (char*) label,s+textoff,s, colormode, STBTE__INDEX_FOR_ID(id,disabled,toggled)); + if (disabled) + return 0; + return (stbte__button_core(id) == 1); +} + +static int stbte__button_icon(int colormode, char ch, int x, int y, int width, int id, int toggled, int disabled) +{ + int x0=x,y0=y, x1=x+width,y1=y+STBTE__BUTTON_HEIGHT; + int s = STBTE__BUTTON_INTERNAL_SPACING; + + stbte__hittest(x0,y0,x1,y1,id); + + if (stbte__ui.event == STBTE__paint) { + char label[2] = { ch, 0 }; + int pad = (9 - stbte__get_char_width(ch))/2; + stbte__draw_textbox(x0,y0,x1,y1, label,s+pad,s, colormode, STBTE__INDEX_FOR_ID(id,disabled,toggled)); + } + if (disabled) + return 0; + return (stbte__button_core(id) == 1); +} + +static int stbte__minibutton(int colormode, int x, int y, int ch, int id) +{ + int x0 = x, y0 = y, x1 = x+8, y1 = y+7; + stbte__hittest(x0,y0,x1,y1,id); + if (stbte__ui.event == STBTE__paint) { + char str[2] = { (char)ch, 0 }; + stbte__draw_textbox(x0,y0,x1,y1, str,1,0,colormode, STBTE__INDEX_FOR_ID(id,0,0)); + } + return stbte__button_core(id); +} + +static int stbte__layerbutton(int x, int y, int ch, int id, int toggled, int disabled, int colormode) +{ + int x0 = x, y0 = y, x1 = x+10, y1 = y+11; + if(!disabled) stbte__hittest(x0,y0,x1,y1,id); + if (stbte__ui.event == STBTE__paint) { + char str[2] = { (char)ch, 0 }; + int off = (9-stbte__get_char_width(ch))/2; + stbte__draw_textbox(x0,y0,x1,y1, str, off+1,2, colormode, STBTE__INDEX_FOR_ID(id,disabled,toggled)); + } + if (disabled) + return 0; + return stbte__button_core(id); +} + +static int stbte__microbutton(int x, int y, int size, int id, int colormode) +{ + int x0 = x, y0 = y, x1 = x+size, y1 = y+size; + stbte__hittest(x0,y0,x1,y1,id); + if (stbte__ui.event == STBTE__paint) { + stbte__draw_box(x0,y0,x1,y1, colormode, STBTE__INDEX_FOR_ID(id,0,0)); + } + return stbte__button_core(id); +} + +static int stbte__microbutton_dragger(int x, int y, int size, int id, int *pos) +{ + int x0 = x, y0 = y, x1 = x+size, y1 = y+size; + stbte__hittest(x0,y0,x1,y1,id); + switch (stbte__ui.event) { + case STBTE__paint: + stbte__draw_box(x0,y0,x1,y1, STBTE__cexpander, STBTE__INDEX_FOR_ID(id,0,0)); + break; + case STBTE__leftdown: + if (STBTE__IS_HOT(id) && STBTE__INACTIVE()) { + stbte__activate(id); + stbte__ui.sx = stbte__ui.mx - *pos; + } + break; + case STBTE__mousemove: + if (STBTE__IS_ACTIVE(id) && stbte__ui.active_event == STBTE__leftdown) { + *pos = stbte__ui.mx - stbte__ui.sx; + } + break; + case STBTE__leftup: + if (STBTE__IS_ACTIVE(id)) + stbte__activate(0); + break; + default: + return stbte__button_core(id); + } + return 0; +} + +static int stbte__category_button(const char *label, int x, int y, int width, int id, int toggled) +{ + int x0=x,y0=y, x1=x+width,y1=y+STBTE__BUTTON_HEIGHT; + int s = STBTE__BUTTON_INTERNAL_SPACING; + + stbte__hittest(x0,y0,x1,y1,id); + + if (stbte__ui.event == STBTE__paint) + stbte__draw_textbox(x0,y0,x1,y1, (char*) label, s,s, STBTE__ccategory_button, STBTE__INDEX_FOR_ID(id,0,toggled)); + + return (stbte__button_core(id) == 1); +} + +enum +{ + STBTE__none, + STBTE__begin, + STBTE__end, + STBTE__change, +}; + +// returns -1 if value changes, 1 at end of drag +static int stbte__slider(int x0, int w, int y, int range, int *value, int id) +{ + int x1 = x0+w; + int pos = *value * w / (range+1); + stbte__hittest(x0,y-2,x1,y+3,id); + int event_mouse_move = STBTE__change; + switch (stbte__ui.event) { + case STBTE__paint: + stbte__draw_rect(x0,y,x1,y+1, 0x808080); + stbte__draw_rect(x0+pos-1,y-1,x0+pos+2,y+2, 0xffffff); + break; + case STBTE__leftdown: + if (STBTE__IS_HOT(id) && STBTE__INACTIVE()) { + stbte__activate(id); + event_mouse_move = STBTE__begin; + } + // fall through + case STBTE__mousemove: + if (STBTE__IS_ACTIVE(id)) { + int v = (stbte__ui.mx-x0)*(range+1)/w; + if (v < 0) v = 0; else if (v > range) v = range; + *value = v; + return event_mouse_move; + } + break; + case STBTE__leftup: + if (STBTE__IS_ACTIVE(id)) { + stbte__activate(0); + return STBTE__end; + } + break; + } + return STBTE__none; +} + +#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__) + #define stbte__sprintf sprintf_s + #define stbte__sizeof(s) , sizeof(s) +#else + #define stbte__sprintf sprintf + #define stbte__sizeof(s) +#endif + +static int stbte__float_control(int x0, int y0, int w, float minv, float maxv, float scale, const char *fmt, float *value, int colormode, int id) +{ + int x1 = x0+w; + int y1 = y0+11; + stbte__hittest(x0,y0,x1,y1,id); + switch (stbte__ui.event) { + case STBTE__paint: { + char text[32]; + stbte__sprintf(text stbte__sizeof(text), fmt ? fmt : "%6.2f", *value); + stbte__draw_textbox(x0,y0,x1,y1, text, 1,2, colormode, STBTE__INDEX_FOR_ID(id,0,0)); + break; + } + case STBTE__leftdown: + case STBTE__rightdown: + if (STBTE__IS_HOT(id) && STBTE__INACTIVE()) + stbte__activate(id); + return STBTE__begin; + break; + case STBTE__leftup: + case STBTE__rightup: + if (STBTE__IS_ACTIVE(id)) { + stbte__activate(0); + return STBTE__end; + } + break; + case STBTE__mousemove: + if (STBTE__IS_ACTIVE(id)) { + float v = *value, delta; + int ax = stbte__ui.accum_x/STBTE_FLOAT_CONTROL_GRANULARITY; + int ay = stbte__ui.accum_y/STBTE_FLOAT_CONTROL_GRANULARITY; + stbte__ui.accum_x -= ax*STBTE_FLOAT_CONTROL_GRANULARITY; + stbte__ui.accum_y -= ay*STBTE_FLOAT_CONTROL_GRANULARITY; + if (stbte__ui.shift) { + if (stbte__ui.active_event == STBTE__leftdown) + delta = ax * 16.0f + ay; + else + delta = ax / 16.0f + ay / 256.0f; + } else { + if (stbte__ui.active_event == STBTE__leftdown) + delta = ax*10.0f + ay; + else + delta = ax * 0.1f + ay * 0.01f; + } + v += delta * scale; + if (v < minv) v = minv; + if (v > maxv) v = maxv; + *value = v; + return STBTE__change; + } + break; + } + return STBTE__none; +} + +static void stbte__scrollbar(int x, int y0, int y1, int *val, int v0, int v1, int num_vis, int id) +{ + int thumbpos; + if (v1 - v0 <= num_vis) + return; + + // generate thumbpos from numvis + thumbpos = y0+2 + (y1-y0-4) * *val / (v1 - v0 - num_vis); + if (thumbpos < y0) thumbpos = y0; + if (thumbpos >= y1) thumbpos = y1; + stbte__hittest(x-1,y0,x+2,y1,id); + switch (stbte__ui.event) { + case STBTE__paint: + stbte__draw_rect(x,y0,x+1,y1, stbte__color_table[STBTE__cscrollbar][STBTE__text][STBTE__idle]); + stbte__draw_box(x-1,thumbpos-3,x+2,thumbpos+4, STBTE__cscrollbar, STBTE__INDEX_FOR_ID(id,0,0)); + break; + case STBTE__leftdown: + if (STBTE__IS_HOT(id) && STBTE__INACTIVE()) { + // check if it's over the thumb + stbte__activate(id); + *val = ((stbte__ui.my-y0) * (v1 - v0 - num_vis) + (y1-y0)/2)/ (y1-y0); + } + break; + case STBTE__mousemove: + if (STBTE__IS_ACTIVE(id) && stbte__ui.mx >= x-15 && stbte__ui.mx <= x+15) + *val = ((stbte__ui.my-y0) * (v1 - v0 - num_vis) + (y1-y0)/2)/ (y1-y0); + break; + case STBTE__leftup: + if (STBTE__IS_ACTIVE(id)) + stbte__activate(0); + break; + + } + + if (*val >= v1-num_vis) + *val = v1-num_vis; + if (*val <= v0) + *val = v0; +} + + +static void stbte__compute_digits(stbte_tilemap *tm) +{ + if (tm->max_x >= 1000 || tm->max_y >= 1000) + tm->digits = 4; + else if (tm->max_x >= 100 || tm->max_y >= 100) + tm->digits = 3; + else + tm->digits = 2; +} + +static int stbte__is_single_selection(void) +{ + return stbte__ui.has_selection + && stbte__ui.select_x0 == stbte__ui.select_x1 + && stbte__ui.select_y0 == stbte__ui.select_y1; +} + +typedef struct +{ + int width, height; + int x,y; + int active; + float retracted; +} stbte__region_t; + +static stbte__region_t stbte__region[4]; + +#define STBTE__TOOLBAR_ICON_SIZE (9+2*2) +#define STBTE__TOOLBAR_PASTE_SIZE (34+2*2) + +// This routine computes where every panel goes onscreen: computes +// a minimum width for each side based on which panels are on that +// side, and accounts for width-dependent layout of certain panels. +static void stbte__compute_panel_locations(stbte_tilemap *tm) +{ + int i, limit, w, k; + int window_width = stbte__ui.x1 - stbte__ui.x0; + int window_height = stbte__ui.y1 - stbte__ui.y0; + int min_width[STBTE__num_panel]={0,0,0,0,0,0,0}; + int height[STBTE__num_panel]={0,0,0,0,0,0,0}; + int panel_active[STBTE__num_panel]={1,0,1,1,1,1,1}; + int vpos[4] = { 0,0,0,0 }; + stbte__panel *p = stbte__ui.panel; + stbte__panel *pt = &p[STBTE__panel_toolbar]; +#ifdef STBTE__NO_PROPS + int props = 0; +#else + int props = 1; +#endif + + for (i=0; i < 4; ++i) { + stbte__region[i].active = 0; + stbte__region[i].width = 0; + stbte__region[i].height = 0; + } + + // compute number of digits needs for info panel + stbte__compute_digits(tm); + + // determine which panels are active + panel_active[STBTE__panel_categories] = tm->num_categories != 0; + panel_active[STBTE__panel_layers ] = tm->num_layers > 1; +#ifdef STBTE__COLORPICKER + panel_active[STBTE__panel_colorpick ] = 1; +#endif + + panel_active[STBTE__panel_props ] = props && stbte__is_single_selection(); + + // compute minimum widths for each panel (assuming they're on sides not top) + min_width[STBTE__panel_info ] = 8 + 11 + 7*tm->digits+17+7; // estimate min width of "w:0000" + min_width[STBTE__panel_colorpick ] = 120; + min_width[STBTE__panel_tiles ] = 4 + tm->palette_spacing_x + 5; // 5 for scrollbar + min_width[STBTE__panel_categories] = 4 + 42 + 5; // 42 is enough to show ~7 chars; 5 for scrollbar + min_width[STBTE__panel_layers ] = 4 + 54 + 30*tm->has_layer_names; // 2 digits plus 3 buttons plus scrollbar + min_width[STBTE__panel_toolbar ] = 4 + STBTE__TOOLBAR_PASTE_SIZE; // wide enough for 'Paste' button + min_width[STBTE__panel_props ] = 80; // narrowest info panel + + // compute minimum widths for left & right panels based on the above + stbte__region[0].width = stbte__ui.left_width; + stbte__region[1].width = stbte__ui.right_width; + + for (i=0; i < STBTE__num_panel; ++i) { + if (panel_active[i]) { + int side = stbte__ui.panel[i].side; + if (min_width[i] > stbte__region[side].width) + stbte__region[side].width = min_width[i]; + stbte__region[side].active = 1; + } + } + + // now compute the heights of each panel + + // if toolbar at top, compute its size & push the left and right start points down + if (stbte__region[STBTE__side_top].active) { + int height = STBTE__TOOLBAR_ICON_SIZE+2; + pt->x0 = stbte__ui.x0; + pt->y0 = stbte__ui.y0; + pt->width = window_width; + pt->height = height; + vpos[STBTE__side_left] = vpos[STBTE__side_right] = height; + } else { + int num_rows = STBTE__num_tool * ((stbte__region[pt->side].width-4)/STBTE__TOOLBAR_ICON_SIZE); + height[STBTE__panel_toolbar] = num_rows*13 + 3*15 + 4; // 3*15 for cut/copy/paste, which are stacked vertically + } + + for (i=0; i < 4; ++i) + stbte__region[i].y = stbte__ui.y0 + vpos[i]; + + for (i=0; i < 2; ++i) { + int anim = (int) (stbte__region[i].width * stbte__region[i].retracted); + stbte__region[i].x = (i == STBTE__side_left) ? stbte__ui.x0 - anim : stbte__ui.x1 - stbte__region[i].width + anim; + } + + // color picker + height[STBTE__panel_colorpick] = 300; + + // info panel + w = stbte__region[p[STBTE__panel_info].side].width; + p[STBTE__panel_info].mode = (w >= 8 + (11+7*tm->digits+17)*2 + 4); + if (p[STBTE__panel_info].mode) + height[STBTE__panel_info] = 5 + 11*2 + 2 + tm->palette_spacing_y; + else + height[STBTE__panel_info] = 5 + 11*4 + 2 + tm->palette_spacing_y; + + // layers + limit = 6 + stbte__ui.panel[STBTE__panel_layers].delta_height; + height[STBTE__panel_layers] = (tm->num_layers > limit ? limit : tm->num_layers)*15 + 7 + (tm->has_layer_names ? 0 : 11) + props*13; + + // categories + limit = 6 + stbte__ui.panel[STBTE__panel_categories].delta_height; + height[STBTE__panel_categories] = (tm->num_categories+1 > limit ? limit : tm->num_categories+1)*11 + 14; + if (stbte__ui.panel[STBTE__panel_categories].side == stbte__ui.panel[STBTE__panel_categories].side) + height[STBTE__panel_categories] -= 4; + + // palette + k = (stbte__region[p[STBTE__panel_tiles].side].width - 8) / tm->palette_spacing_x; + if (k == 0) k = 1; + height[STBTE__panel_tiles] = ((tm->num_tiles+k-1)/k) * tm->palette_spacing_y + 8; + + // properties panel + height[STBTE__panel_props] = 9 + STBTE_MAX_PROPERTIES*14; + + // now compute the locations of all the panels + for (i=0; i < STBTE__num_panel; ++i) { + if (panel_active[i]) { + int side = p[i].side; + if (side == STBTE__side_left || side == STBTE__side_right) { + p[i].width = stbte__region[side].width; + p[i].x0 = stbte__region[side].x; + p[i].y0 = stbte__ui.y0 + vpos[side]; + p[i].height = height[i]; + vpos[side] += height[i]; + if (vpos[side] > window_height) { + vpos[side] = window_height; + p[i].height = stbte__ui.y1 - p[i].y0; + } + } else { + ; // it's at top, it's already been explicitly set up earlier + } + } else { + // inactive panel + p[i].height = 0; + p[i].width = 0; + p[i].x0 = stbte__ui.x1; + p[i].y0 = stbte__ui.y1; + } + } +} + +// unique identifiers for imgui +enum +{ + STBTE__map=1, + STBTE__region, + STBTE__panel, // panel background to hide map, and misc controls + STBTE__info, // info data + STBTE__toolbarA, STBTE__toolbarB, // toolbar buttons: param is tool number + STBTE__palette, // palette selectors: param is tile index + STBTE__categories, // category selectors: param is category index + STBTE__layer, // + STBTE__solo, STBTE__hide, STBTE__lock, // layer controls: param is layer + STBTE__scrollbar, // param is panel ID + STBTE__panel_mover, // p1 is panel ID, p2 is destination side + STBTE__panel_sizer, // param panel ID + STBTE__scrollbar_id, + STBTE__colorpick_id, + STBTE__prop_flag, + STBTE__prop_float, + STBTE__prop_int, +}; + +// id is: [ 24-bit data : 7-bit identifier ] +// map id is: [ 12-bit y : 12 bit x : 7-bit identifier ] + +#define STBTE__ID(n,p) ((n) + ((p)<<7)) +#define STBTE__ID2(n,p,q) STBTE__ID(n, ((p)<<12)+(q) ) +#define STBTE__IDMAP(x,y) STBTE__ID2(STBTE__map, x,y) + +static void stbte__activate_map(int x, int y) +{ + stbte__ui.active_id = STBTE__IDMAP(x,y); + stbte__ui.active_event = stbte__ui.event; + stbte__ui.sx = x; + stbte__ui.sy = y; +} + +static void stbte__alert(const char *msg) +{ + stbte__ui.alert_msg = msg; + stbte__ui.alert_timer = 3; +} + +#define STBTE__BG(tm,layer) ((layer) == 0 ? (tm)->background_tile : STBTE__NO_TILE) + + + +static void stbte__brush_predict(stbte_tilemap *tm, short result[]) +{ + stbte__tileinfo *ti; + int i; + + if (tm->cur_tile < 0) return; + + ti = &tm->tiles[tm->cur_tile]; + + // find lowest legit layer to paint it on, and put it there + for (i=0; i < tm->num_layers; ++i) { + // check if object is allowed on layer + if (!(ti->layermask & (1 << i))) + continue; + + if (i != tm->solo_layer) { + // if there's a selected layer, can only paint on that + if (tm->cur_layer >= 0 && i != tm->cur_layer) + continue; + + // if the layer is hidden, we can't see it + if (tm->layerinfo[i].hidden) + continue; + + // if the layer is locked, we can't write to it + if (tm->layerinfo[i].locked == STBTE__locked) + continue; + + // if the layer is non-empty and protected, can't write to it + if (tm->layerinfo[i].locked == STBTE__protected && result[i] != STBTE__BG(tm,i)) + continue; + } + + result[i] = ti->id; + return; + } +} + +static void stbte__brush(stbte_tilemap *tm, int x, int y) +{ + stbte__tileinfo *ti; + + // find lowest legit layer to paint it on, and put it there + int i; + + if (tm->cur_tile < 0) return; + + ti = &tm->tiles[tm->cur_tile]; + + for (i=0; i < tm->num_layers; ++i) { + // check if object is allowed on layer + if (!(ti->layermask & (1 << i))) + continue; + + if (i != tm->solo_layer) { + // if there's a selected layer, can only paint on that + if (tm->cur_layer >= 0 && i != tm->cur_layer) + continue; + + // if the layer is hidden, we can't see it + if (tm->layerinfo[i].hidden) + continue; + + // if the layer is locked, we can't write to it + if (tm->layerinfo[i].locked == STBTE__locked) + continue; + + // if the layer is non-empty and protected, can't write to it + if (tm->layerinfo[i].locked == STBTE__protected && tm->data[y][x][i] != STBTE__BG(tm,i)) + continue; + } + + stbte__undo_record(tm,x,y,i,tm->data[y][x][i]); + tm->data[y][x][i] = ti->id; + return; + } + + //stbte__alert("Selected tile not valid on active layer(s)"); +} + +enum +{ + STBTE__erase_none = -1, + STBTE__erase_brushonly = 0, + STBTE__erase_any = 1, + STBTE__erase_all = 2, +}; + +static int stbte__erase_predict(stbte_tilemap *tm, short result[], int allow_any) +{ + stbte__tileinfo *ti = tm->cur_tile >= 0 ? &tm->tiles[tm->cur_tile] : NULL; + int i; + + if (allow_any == STBTE__erase_none) + return allow_any; + + // first check if only one layer is legit + i = tm->cur_layer; + if (tm->solo_layer >= 0) + i = tm->solo_layer; + + // if only one layer is legit, directly process that one for clarity + if (i >= 0) { + short bg = (i == 0 ? tm->background_tile : -1); + if (tm->solo_layer < 0) { + // check that we're allowed to write to it + if (tm->layerinfo[i].hidden) return STBTE__erase_none; + if (tm->layerinfo[i].locked) return STBTE__erase_none; + } + if (result[i] == bg) + return STBTE__erase_none; // didn't erase anything + if (ti && result[i] == ti->id && (i != 0 || ti->id != tm->background_tile)) { + result[i] = bg; + return STBTE__erase_brushonly; + } + if (allow_any == STBTE__erase_any) { + result[i] = bg; + return STBTE__erase_any; + } + return STBTE__erase_none; + } + + // if multiple layers are legit, first scan all for brush data + + if (ti && allow_any != STBTE__erase_all) { + for (i=tm->num_layers-1; i >= 0; --i) { + if (result[i] != ti->id) + continue; + if (tm->layerinfo[i].locked || tm->layerinfo[i].hidden) + continue; + if (i == 0 && result[i] == tm->background_tile) + return STBTE__erase_none; + result[i] = STBTE__BG(tm,i); + return STBTE__erase_brushonly; + } + } + + if (allow_any != STBTE__erase_any && allow_any != STBTE__erase_all) + return STBTE__erase_none; + + // apply layer filters, erase from top + for (i=tm->num_layers-1; i >= 0; --i) { + if (result[i] < 0) + continue; + if (tm->layerinfo[i].locked || tm->layerinfo[i].hidden) + continue; + if (i == 0 && result[i] == tm->background_tile) + return STBTE__erase_none; + result[i] = STBTE__BG(tm,i); + if (allow_any != STBTE__erase_all) + return STBTE__erase_any; + } + + if (allow_any == STBTE__erase_all) + return allow_any; + return STBTE__erase_none; +} + +static int stbte__erase(stbte_tilemap *tm, int x, int y, int allow_any) +{ + stbte__tileinfo *ti = tm->cur_tile >= 0 ? &tm->tiles[tm->cur_tile] : NULL; + int i; + + if (allow_any == STBTE__erase_none) + return allow_any; + + // first check if only one layer is legit + i = tm->cur_layer; + if (tm->solo_layer >= 0) + i = tm->solo_layer; + + // if only one layer is legit, directly process that one for clarity + if (i >= 0) { + short bg = (i == 0 ? tm->background_tile : -1); + if (tm->solo_layer < 0) { + // check that we're allowed to write to it + if (tm->layerinfo[i].hidden) return STBTE__erase_none; + if (tm->layerinfo[i].locked) return STBTE__erase_none; + } + if (tm->data[y][x][i] == bg) + return -1; // didn't erase anything + if (ti && tm->data[y][x][i] == ti->id && (i != 0 || ti->id != tm->background_tile)) { + stbte__undo_record(tm,x,y,i,tm->data[y][x][i]); + tm->data[y][x][i] = bg; + return STBTE__erase_brushonly; + } + if (allow_any == STBTE__erase_any) { + stbte__undo_record(tm,x,y,i,tm->data[y][x][i]); + tm->data[y][x][i] = bg; + return STBTE__erase_any; + } + return STBTE__erase_none; + } + + // if multiple layers are legit, first scan all for brush data + + if (ti && allow_any != STBTE__erase_all) { + for (i=tm->num_layers-1; i >= 0; --i) { + if (tm->data[y][x][i] != ti->id) + continue; + if (tm->layerinfo[i].locked || tm->layerinfo[i].hidden) + continue; + if (i == 0 && tm->data[y][x][i] == tm->background_tile) + return STBTE__erase_none; + stbte__undo_record(tm,x,y,i,tm->data[y][x][i]); + tm->data[y][x][i] = STBTE__BG(tm,i); + return STBTE__erase_brushonly; + } + } + + if (allow_any != STBTE__erase_any && allow_any != STBTE__erase_all) + return STBTE__erase_none; + + // apply layer filters, erase from top + for (i=tm->num_layers-1; i >= 0; --i) { + if (tm->data[y][x][i] < 0) + continue; + if (tm->layerinfo[i].locked || tm->layerinfo[i].hidden) + continue; + if (i == 0 && tm->data[y][x][i] == tm->background_tile) + return STBTE__erase_none; + stbte__undo_record(tm,x,y,i,tm->data[y][x][i]); + tm->data[y][x][i] = STBTE__BG(tm,i); + if (allow_any != STBTE__erase_all) + return STBTE__erase_any; + } + if (allow_any == STBTE__erase_all) + return allow_any; + return STBTE__erase_none; +} + +static int stbte__find_tile(stbte_tilemap *tm, int tile_id) +{ + int i; + for (i=0; i < tm->num_tiles; ++i) + if (tm->tiles[i].id == tile_id) + return i; + stbte__alert("Eyedropped tile that isn't in tileset"); + return -1; +} + +static void stbte__eyedrop(stbte_tilemap *tm, int x, int y) +{ + int i,j; + + // flush eyedropper state + if (stbte__ui.eyedrop_x != x || stbte__ui.eyedrop_y != y) { + stbte__ui.eyedrop_x = x; + stbte__ui.eyedrop_y = y; + stbte__ui.eyedrop_last_layer = tm->num_layers; + } + + // if only one layer is active, query that + i = tm->cur_layer; + if (tm->solo_layer >= 0) + i = tm->solo_layer; + if (i >= 0) { + if (tm->data[y][x][i] == STBTE__NO_TILE) + return; + tm->cur_tile = stbte__find_tile(tm, tm->data[y][x][i]); + return; + } + + // if multiple layers, continue from previous + i = stbte__ui.eyedrop_last_layer; + for (j=0; j < tm->num_layers; ++j) { + if (--i < 0) + i = tm->num_layers-1; + if (tm->layerinfo[i].hidden) + continue; + if (tm->data[y][x][i] == STBTE__NO_TILE) + continue; + stbte__ui.eyedrop_last_layer = i; + tm->cur_tile = stbte__find_tile(tm, tm->data[y][x][i]); + return; + } +} + +static int stbte__should_copy_properties(stbte_tilemap *tm) +{ + int i; + if (tm->propmode == STBTE__propmode_always) + return 1; + if (tm->propmode == STBTE__propmode_never) + return 0; + if (tm->solo_layer >= 0 || tm->cur_layer >= 0) + return 0; + for (i=0; i < tm->num_layers; ++i) + if (tm->layerinfo[i].hidden || tm->layerinfo[i].locked) + return 0; + return 1; +} + +// compute the result of pasting into a tile non-destructively so we can preview it +static void stbte__paste_stack(stbte_tilemap *tm, short result[], short dest[], short src[], int dragging) +{ + int i; + + // special case single-layer + i = tm->cur_layer; + if (tm->solo_layer >= 0) + i = tm->solo_layer; + if (i >= 0) { + if (tm->solo_layer < 0) { + // check that we're allowed to write to it + if (tm->layerinfo[i].hidden) return; + if (tm->layerinfo[i].locked == STBTE__locked) return; + // if protected, dest has to be empty + if (tm->layerinfo[i].locked == STBTE__protected && dest[i] != STBTE__BG(tm,i)) return; + // if dragging w/o copy, we will try to erase stuff, which protection disallows + if (dragging && tm->layerinfo[i].locked == STBTE__protected) + return; + } + result[i] = dest[i]; + if (src[i] != STBTE__BG(tm,i)) + result[i] = src[i]; + return; + } + + for (i=0; i < tm->num_layers; ++i) { + result[i] = dest[i]; + if (src[i] != STBTE__NO_TILE) + if (!tm->layerinfo[i].hidden && tm->layerinfo[i].locked != STBTE__locked) + if (tm->layerinfo[i].locked == STBTE__unlocked || (!dragging && dest[i] == STBTE__BG(tm,i))) + result[i] = src[i]; + } +} + +// compute the result of dragging away from a tile +static void stbte__clear_stack(stbte_tilemap *tm, short result[]) +{ + int i; + // special case single-layer + i = tm->cur_layer; + if (tm->solo_layer >= 0) + i = tm->solo_layer; + if (i >= 0) + result[i] = STBTE__BG(tm,i); + else + for (i=0; i < tm->num_layers; ++i) + if (!tm->layerinfo[i].hidden && tm->layerinfo[i].locked == STBTE__unlocked) + result[i] = STBTE__BG(tm,i); +} + +// check if some map square is active +#define STBTE__IS_MAP_ACTIVE() ((stbte__ui.active_id & 127) == STBTE__map) +#define STBTE__IS_MAP_HOT() ((stbte__ui.hot_id & 127) == STBTE__map) + +static void stbte__fillrect(stbte_tilemap *tm, int x0, int y0, int x1, int y1, int fill) +{ + int i,j; + + stbte__begin_undo(tm); + if (x0 > x1) i=x0,x0=x1,x1=i; + if (y0 > y1) j=y0,y0=y1,y1=j; + for (j=y0; j <= y1; ++j) + for (i=x0; i <= x1; ++i) + if (fill) + stbte__brush(tm, i,j); + else + stbte__erase(tm, i,j,STBTE__erase_any); + stbte__end_undo(tm); + // suppress warning from brush + stbte__ui.alert_msg = 0; +} + +static void stbte__select_rect(stbte_tilemap *tm, int x0, int y0, int x1, int y1) +{ + stbte__ui.has_selection = 1; + stbte__ui.select_x0 = (x0 < x1 ? x0 : x1); + stbte__ui.select_x1 = (x0 < x1 ? x1 : x0); + stbte__ui.select_y0 = (y0 < y1 ? y0 : y1); + stbte__ui.select_y1 = (y0 < y1 ? y1 : y0); +} + +static void stbte__copy_properties(float *dest, float *src) +{ + int i; + for (i=0; i < STBTE_MAX_PROPERTIES; ++i) + dest[i] = src[i]; +} + +static void stbte__copy_cut(stbte_tilemap *tm, int cut) +{ + int i,j,n,w,h,p=0; + int copy_props = stbte__should_copy_properties(tm); + if (!stbte__ui.has_selection) + return; + w = stbte__ui.select_x1 - stbte__ui.select_x0 + 1; + h = stbte__ui.select_y1 - stbte__ui.select_y0 + 1; + if (STBTE_MAX_COPY / w < h) { + stbte__alert("Selection too large for copy buffer, increase STBTE_MAX_COPY"); + return; + } + + for (i=0; i < w*h; ++i) + for (n=0; n < tm->num_layers; ++n) + stbte__ui.copybuffer[i][n] = STBTE__NO_TILE; + + if (cut) + stbte__begin_undo(tm); + for (j=stbte__ui.select_y0; j <= stbte__ui.select_y1; ++j) { + for (i=stbte__ui.select_x0; i <= stbte__ui.select_x1; ++i) { + for (n=0; n < tm->num_layers; ++n) { + if (tm->solo_layer >= 0) { + if (tm->solo_layer != n) + continue; + } else { + if (tm->cur_layer >= 0) + if (tm->cur_layer != n) + continue; + if (tm->layerinfo[n].hidden) + continue; + if (cut && tm->layerinfo[n].locked) + continue; + } + stbte__ui.copybuffer[p][n] = tm->data[j][i][n]; + if (cut) { + stbte__undo_record(tm,i,j,n, tm->data[j][i][n]); + tm->data[j][i][n] = (n==0 ? tm->background_tile : -1); + } + } + if (copy_props) { + stbte__copy_properties(stbte__ui.copyprops[p], tm->props[j][i]); +#ifdef STBTE_ALLOW_LINK + stbte__ui.copylinks[p] = tm->link[j][i]; + if (cut) + stbte__set_link(tm, i,j,-1,-1, STBTE__undo_record); +#endif + } + ++p; + } + } + if (cut) + stbte__end_undo(tm); + stbte__ui.copy_width = w; + stbte__ui.copy_height = h; + stbte__ui.has_copy = 1; + //stbte__ui.has_selection = 0; + stbte__ui.copy_has_props = copy_props; + stbte__ui.copy_src = tm; // used to give better semantics when copying links + stbte__ui.copy_src_x = stbte__ui.select_x0; + stbte__ui.copy_src_y = stbte__ui.select_y0; +} + +static int stbte__in_rect(int x, int y, int x0, int y0, int w, int h) +{ + return x >= x0 && x < x0+w && y >= y0 && y < y0+h; +} + +#ifdef STBTE_ALLOW_LINK +static int stbte__in_src_rect(int x, int y) +{ + return stbte__in_rect(x,y, stbte__ui.copy_src_x, stbte__ui.copy_src_y, stbte__ui.copy_width, stbte__ui.copy_height); +} + +static int stbte__in_dest_rect(int x, int y, int destx, int desty) +{ + return stbte__in_rect(x,y, destx, desty, stbte__ui.copy_width, stbte__ui.copy_height); +} +#endif + +static void stbte__paste(stbte_tilemap *tm, int mapx, int mapy) +{ + int w = stbte__ui.copy_width; + int h = stbte__ui.copy_height; + int i,j,k,p; + int x = mapx - (w>>1); + int y = mapy - (h>>1); + int copy_props = stbte__should_copy_properties(tm) && stbte__ui.copy_has_props; + if (stbte__ui.has_copy == 0) + return; + stbte__begin_undo(tm); + p = 0; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + if (y+j >= 0 && y+j < tm->max_y && x+i >= 0 && x+i < tm->max_x) { + // compute the new stack + short tilestack[STBTE_MAX_LAYERS]; + for (k=0; k < tm->num_layers; ++k) + tilestack[k] = tm->data[y+j][x+i][k]; + stbte__paste_stack(tm, tilestack, tilestack, stbte__ui.copybuffer[p], 0); + // update anything that changed + for (k=0; k < tm->num_layers; ++k) { + if (tilestack[k] != tm->data[y+j][x+i][k]) { + stbte__undo_record(tm, x+i,y+j,k, tm->data[y+j][x+i][k]); + tm->data[y+j][x+i][k] = tilestack[k]; + } + } + } + if (copy_props) { +#ifdef STBTE_ALLOW_LINK + // need to decide how to paste a link, so there's a few cases + int destx = -1, desty = -1; + stbte__link *link = &stbte__ui.copylinks[p]; + + // check if link is within-rect + if (stbte__in_src_rect(link->x, link->y)) { + // new link should point to copy (but only if copy is within map) + destx = x + (link->x - stbte__ui.copy_src_x); + desty = y + (link->y - stbte__ui.copy_src_y); + } else if (tm == stbte__ui.copy_src) { + // if same map, then preserve link unless target is overwritten + if (!stbte__in_dest_rect(link->x,link->y,x,y)) { + destx = link->x; + desty = link->y; + } + } + // this is necessary for offset-copy, but also in case max_x/max_y has changed + if (destx < 0 || destx >= tm->max_x || desty < 0 || desty >= tm->max_y) + destx = -1, desty = -1; + stbte__set_link(tm, x+i, y+j, destx, desty, STBTE__undo_record); +#endif + for (k=0; k < STBTE_MAX_PROPERTIES; ++k) { + if (tm->props[y+j][x+i][k] != stbte__ui.copyprops[p][k]) + stbte__undo_record_prop_float(tm, x+i, y+j, k, tm->props[y+j][x+i][k]); + } + stbte__copy_properties(tm->props[y+j][x+i], stbte__ui.copyprops[p]); + } + ++p; + } + } + stbte__end_undo(tm); +} + +static void stbte__drag_update(stbte_tilemap *tm, int mapx, int mapy, int copy_props) +{ + int w = stbte__ui.drag_w, h = stbte__ui.drag_h; + int ox,oy,i,deleted=0,written=0; + short temp[STBTE_MAX_LAYERS]; + short *data = NULL; + + STBTE__NOTUSED(deleted); + STBTE__NOTUSED(written); + + if (!stbte__ui.shift) { + ox = mapx - stbte__ui.drag_x; + oy = mapy - stbte__ui.drag_y; + if (ox >= 0 && ox < w && oy >= 0 && oy < h) { + deleted=1; + for (i=0; i < tm->num_layers; ++i) + temp[i] = tm->data[mapy][mapx][i]; + data = temp; + stbte__clear_stack(tm, data); + } + } + ox = mapx - stbte__ui.drag_dest_x; + oy = mapy - stbte__ui.drag_dest_y; + // if this map square is in the target drag region + if (ox >= 0 && ox < w && oy >= 0 && oy < h) { + // and the src map square is on the map + if (stbte__in_rect(stbte__ui.drag_x+ox, stbte__ui.drag_y+oy, 0, 0, tm->max_x, tm->max_y)) { + written = 1; + if (data == NULL) { + for (i=0; i < tm->num_layers; ++i) + temp[i] = tm->data[mapy][mapx][i]; + data = temp; + } + stbte__paste_stack(tm, data, data, tm->data[stbte__ui.drag_y+oy][stbte__ui.drag_x+ox], !stbte__ui.shift); + if (copy_props) { + for (i=0; i < STBTE_MAX_PROPERTIES; ++i) { + if (tm->props[mapy][mapx][i] != tm->props[stbte__ui.drag_y+oy][stbte__ui.drag_x+ox][i]) { + stbte__undo_record_prop_float(tm, mapx, mapy, i, tm->props[mapy][mapx][i]); + tm->props[mapy][mapx][i] = tm->props[stbte__ui.drag_y+oy][stbte__ui.drag_x+ox][i]; + } + } + } + } + } + if (data) { + for (i=0; i < tm->num_layers; ++i) { + if (tm->data[mapy][mapx][i] != data[i]) { + stbte__undo_record(tm, mapx, mapy, i, tm->data[mapy][mapx][i]); + tm->data[mapy][mapx][i] = data[i]; + } + } + } + #ifdef STBTE_ALLOW_LINK + if (copy_props) { + int overwritten=0, moved=0, copied=0; + // since this function is called on EVERY tile, we can fix up even tiles not + // involved in the move + + stbte__link *k; + // first, determine what src link ends up here + k = &tm->link[mapy][mapx]; // by default, it's the one currently here + if (deleted) // if dragged away, it's erased + k = NULL; + if (written) // if dragged into, it gets that link + k = &tm->link[stbte__ui.drag_y+oy][stbte__ui.drag_x+ox]; + + // now check whether the *target* gets moved or overwritten + if (k && k->x >= 0) { + overwritten = stbte__in_rect(k->x, k->y, stbte__ui.drag_dest_x, stbte__ui.drag_dest_y, w, h); + if (!stbte__ui.shift) + moved = stbte__in_rect(k->x, k->y, stbte__ui.drag_x , stbte__ui.drag_y , w, h); + else + copied = stbte__in_rect(k->x, k->y, stbte__ui.drag_x , stbte__ui.drag_y , w, h); + } + + if (deleted || written || overwritten || moved || copied) { + // choose the final link value based on the above + if (k == NULL || k->x < 0) + stbte__set_link(tm, mapx, mapy, -1, -1, STBTE__undo_record); + else if (moved || (copied && written)) { + // if we move the target, we update to point to the new target; + // or, if we copy the target and the source is part of the copy, then update to new target + int x = k->x + (stbte__ui.drag_dest_x - stbte__ui.drag_x); + int y = k->y + (stbte__ui.drag_dest_y - stbte__ui.drag_y); + if (!(x >= 0 && y >= 0 && x < tm->max_x && y < tm->max_y)) + x = -1, y = -1; + stbte__set_link(tm, mapx, mapy, x, y, STBTE__undo_record); + } else if (overwritten) { + stbte__set_link(tm, mapx, mapy, -1, -1, STBTE__undo_record); + } else + stbte__set_link(tm, mapx, mapy, k->x, k->y, STBTE__undo_record); + } + } + #endif +} + +static void stbte__drag_place(stbte_tilemap *tm, int mapx, int mapy) +{ + int i,j; + int copy_props = stbte__should_copy_properties(tm); + int move_x = (stbte__ui.drag_dest_x - stbte__ui.drag_x); + int move_y = (stbte__ui.drag_dest_y - stbte__ui.drag_y); + if (move_x == 0 && move_y == 0) + return; + + stbte__begin_undo(tm); + // we now need a 2D memmove-style mover that doesn't + // overwrite any data as it goes. this requires being + // direction sensitive in the same way as memmove + if (move_y > 0 || (move_y == 0 && move_x > 0)) { + for (j=tm->max_y-1; j >= 0; --j) + for (i=tm->max_x-1; i >= 0; --i) + stbte__drag_update(tm,i,j,copy_props); + } else { + for (j=0; j < tm->max_y; ++j) + for (i=0; i < tm->max_x; ++i) + stbte__drag_update(tm,i,j,copy_props); + } + stbte__end_undo(tm); + + stbte__ui.has_selection = 1; + stbte__ui.select_x0 = stbte__ui.drag_dest_x; + stbte__ui.select_y0 = stbte__ui.drag_dest_y; + stbte__ui.select_x1 = stbte__ui.select_x0 + stbte__ui.drag_w - 1; + stbte__ui.select_y1 = stbte__ui.select_y0 + stbte__ui.drag_h - 1; +} + +static void stbte__tile_paint(stbte_tilemap *tm, int sx, int sy, int mapx, int mapy, int layer) +{ + int i; + int id = STBTE__IDMAP(mapx,mapy); + int x0=sx, y0=sy; + int x1=sx+tm->spacing_x, y1=sy+tm->spacing_y; + stbte__hittest(x0,y0,x1,y1, id); + short *data = tm->data[mapy][mapx]; + short temp[STBTE_MAX_LAYERS]; + + if (STBTE__IS_MAP_HOT()) { + if (stbte__ui.pasting) { + int ox = mapx - stbte__ui.paste_x; + int oy = mapy - stbte__ui.paste_y; + if (ox >= 0 && ox < stbte__ui.copy_width && oy >= 0 && oy < stbte__ui.copy_height) { + stbte__paste_stack(tm, temp, tm->data[mapy][mapx], stbte__ui.copybuffer[oy*stbte__ui.copy_width+ox], 0); + data = temp; + } + } else if (stbte__ui.dragging) { + int ox,oy; + for (i=0; i < tm->num_layers; ++i) + temp[i] = tm->data[mapy][mapx][i]; + data = temp; + + // if it's in the source area, remove things unless shift-dragging + ox = mapx - stbte__ui.drag_x; + oy = mapy - stbte__ui.drag_y; + if (!stbte__ui.shift && ox >= 0 && ox < stbte__ui.drag_w && oy >= 0 && oy < stbte__ui.drag_h) { + stbte__clear_stack(tm, temp); + } + + ox = mapx - stbte__ui.drag_dest_x; + oy = mapy - stbte__ui.drag_dest_y; + if (ox >= 0 && ox < stbte__ui.drag_w && oy >= 0 && oy < stbte__ui.drag_h) { + stbte__paste_stack(tm, temp, temp, tm->data[stbte__ui.drag_y+oy][stbte__ui.drag_x+ox], !stbte__ui.shift); + } + } else if (STBTE__IS_MAP_ACTIVE()) { + if (stbte__ui.tool == STBTE__tool_rect) { + if ((stbte__ui.ms_time & 511) < 380) { + int ex = ((stbte__ui.hot_id >> 19) & 4095); + int ey = ((stbte__ui.hot_id >> 7) & 4095); + int sx = stbte__ui.sx; + int sy = stbte__ui.sy; + + if ( ((mapx >= sx && mapx < ex+1) || (mapx >= ex && mapx < sx+1)) + && ((mapy >= sy && mapy < ey+1) || (mapy >= ey && mapy < sy+1))) { + int i; + for (i=0; i < tm->num_layers; ++i) + temp[i] = tm->data[mapy][mapx][i]; + data = temp; + if (stbte__ui.active_event == STBTE__leftdown) + stbte__brush_predict(tm, temp); + else + stbte__erase_predict(tm, temp, STBTE__erase_any); + } + } + } + } + } + + if (STBTE__IS_HOT(id) && STBTE__INACTIVE() && !stbte__ui.pasting) { + if (stbte__ui.tool == STBTE__tool_brush) { + if ((stbte__ui.ms_time & 511) < 300) { + data = temp; + for (i=0; i < tm->num_layers; ++i) + temp[i] = tm->data[mapy][mapx][i]; + stbte__brush_predict(tm, temp); + } + } + } + + { + i = layer; + if (i == tm->solo_layer || (!tm->layerinfo[i].hidden && tm->solo_layer < 0)) + if (data[i] >= 0) + STBTE_DRAW_TILE(sx,sy, (unsigned short) data[i], 0, tm->props[mapy][mapx]); + } +} + +static void stbte__tile(stbte_tilemap *tm, int sx, int sy, int mapx, int mapy) +{ + int tool = stbte__ui.tool; + int x0=sx, y0=sy; + int x1=sx+tm->spacing_x, y1=sy+tm->spacing_y; + int id = STBTE__IDMAP(mapx,mapy); + int over = stbte__hittest(x0,y0,x1,y1, id); + switch (stbte__ui.event) { + case STBTE__paint: { + if (stbte__ui.pasting || stbte__ui.dragging || stbte__ui.scrolling) + break; + if (stbte__ui.scrollkey && !STBTE__IS_MAP_ACTIVE()) + break; + if (STBTE__IS_HOT(id) && STBTE__IS_MAP_ACTIVE() && (tool == STBTE__tool_rect || tool == STBTE__tool_select)) { + int rx0,ry0,rx1,ry1,t; + // compute the center of each rect + rx0 = x0 + tm->spacing_x/2; + ry0 = y0 + tm->spacing_y/2; + rx1 = rx0 + (stbte__ui.sx - mapx) * tm->spacing_x; + ry1 = ry0 + (stbte__ui.sy - mapy) * tm->spacing_y; + if (rx0 > rx1) t=rx0,rx0=rx1,rx1=t; + if (ry0 > ry1) t=ry0,ry0=ry1,ry1=t; + rx0 -= tm->spacing_x/2; + ry0 -= tm->spacing_y/2; + rx1 += tm->spacing_x/2; + ry1 += tm->spacing_y/2; + stbte__draw_frame(rx0-1,ry0-1,rx1+1,ry1+1, STBTE_COLOR_TILEMAP_HIGHLIGHT); + break; + } + if (STBTE__IS_HOT(id) && STBTE__INACTIVE()) { + stbte__draw_frame(x0-1,y0-1,x1+1,y1+1, STBTE_COLOR_TILEMAP_HIGHLIGHT); + } +#ifdef STBTE_ALLOW_LINK + if (stbte__ui.show_links && tm->link[mapy][mapx].x >= 0) { + int tx = tm->link[mapy][mapx].x; + int ty = tm->link[mapy][mapx].y; + int lx0,ly0,lx1,ly1; + if (STBTE_ALLOW_LINK(tm->data[mapy][mapx], tm->props[mapy][mapx], + tm->data[ty ][tx ], tm->props[ty ][tx ])) + { + lx0 = x0 + (tm->spacing_x >> 1) - 1; + ly0 = y0 + (tm->spacing_y >> 1) - 1; + lx1 = lx0 + (tx - mapx) * tm->spacing_x + 2; + ly1 = ly0 + (ty - mapy) * tm->spacing_y + 2; + stbte__draw_link(lx0,ly0,lx1,ly1, + STBTE_LINK_COLOR(tm->data[mapy][mapx], tm->props[mapy][mapx], + tm->data[ty ][tx ], tm->props[ty ][tx])); + } + } +#endif + break; + } + } + + if (stbte__ui.pasting) { + switch (stbte__ui.event) { + case STBTE__leftdown: + if (STBTE__IS_HOT(id)) { + stbte__ui.pasting = 0; + stbte__paste(tm, mapx, mapy); + stbte__activate(0); + } + break; + case STBTE__leftup: + // just clear it no matter what, since they might click away to clear it + stbte__activate(0); + break; + case STBTE__rightdown: + if (STBTE__IS_HOT(id)) { + stbte__activate(0); + stbte__ui.pasting = 0; + } + break; + } + return; + } + + if (stbte__ui.scrolling) { + if (stbte__ui.event == STBTE__leftup) { + stbte__activate(0); + stbte__ui.scrolling = 0; + } + if (stbte__ui.event == STBTE__mousemove) { + tm->scroll_x += (stbte__ui.start_x - stbte__ui.mx); + tm->scroll_y += (stbte__ui.start_y - stbte__ui.my); + stbte__ui.start_x = stbte__ui.mx; + stbte__ui.start_y = stbte__ui.my; + } + return; + } + + // regardless of tool, leftdown is a scrolldrag + if (STBTE__IS_HOT(id) && stbte__ui.scrollkey && stbte__ui.event == STBTE__leftdown) { + stbte__ui.scrolling = 1; + stbte__ui.start_x = stbte__ui.mx; + stbte__ui.start_y = stbte__ui.my; + return; + } + + switch (tool) { + case STBTE__tool_brush: + switch (stbte__ui.event) { + case STBTE__mousemove: + if (STBTE__IS_MAP_ACTIVE() && over) { + // don't brush/erase same tile multiple times unless they move away and back @TODO should just be only once, but that needs another data structure + if (!STBTE__IS_ACTIVE(id)) { + if (stbte__ui.active_event == STBTE__leftdown) + stbte__brush(tm, mapx, mapy); + else + stbte__erase(tm, mapx, mapy, stbte__ui.brush_state); + stbte__ui.active_id = id; // switch to this map square so we don't rebrush IT multiple times + } + } + break; + case STBTE__leftdown: + if (STBTE__IS_HOT(id) && STBTE__INACTIVE()) { + stbte__activate(id); + stbte__begin_undo(tm); + stbte__brush(tm, mapx, mapy); + } + break; + case STBTE__rightdown: + if (STBTE__IS_HOT(id) && STBTE__INACTIVE()) { + stbte__activate(id); + stbte__begin_undo(tm); + if (stbte__erase(tm, mapx, mapy, STBTE__erase_any) == STBTE__erase_brushonly) + stbte__ui.brush_state = STBTE__erase_brushonly; + else + stbte__ui.brush_state = STBTE__erase_any; + } + break; + case STBTE__leftup: + case STBTE__rightup: + if (STBTE__IS_MAP_ACTIVE()) { + stbte__end_undo(tm); + stbte__activate(0); + } + break; + } + break; + +#ifdef STBTE_ALLOW_LINK + case STBTE__tool_link: + switch (stbte__ui.event) { + case STBTE__leftdown: + if (STBTE__IS_HOT(id) && STBTE__INACTIVE()) { + stbte__activate(id); + stbte__ui.linking = 1; + stbte__ui.sx = mapx; + stbte__ui.sy = mapy; + // @TODO: undo + } + break; + case STBTE__leftup: + if (STBTE__IS_HOT(id) && STBTE__IS_MAP_ACTIVE()) { + if ((mapx != stbte__ui.sx || mapy != stbte__ui.sy) && + STBTE_ALLOW_LINK(tm->data[stbte__ui.sy][stbte__ui.sx], tm->props[stbte__ui.sy][stbte__ui.sx], + tm->data[mapy][mapx], tm->props[mapy][mapx])) + stbte__set_link(tm, stbte__ui.sx, stbte__ui.sy, mapx, mapy, STBTE__undo_block); + else + stbte__set_link(tm, stbte__ui.sx, stbte__ui.sy, -1,-1, STBTE__undo_block); + stbte__ui.linking = 0; + stbte__activate(0); + } + break; + + case STBTE__rightdown: + if (STBTE__IS_ACTIVE(id)) { + stbte__activate(0); + stbte__ui.linking = 0; + } + break; + } + break; +#endif + + case STBTE__tool_erase: + switch (stbte__ui.event) { + case STBTE__mousemove: + if (STBTE__IS_MAP_ACTIVE() && over) + stbte__erase(tm, mapx, mapy, STBTE__erase_all); + break; + case STBTE__leftdown: + if (STBTE__IS_HOT(id) && STBTE__INACTIVE()) { + stbte__activate(id); + stbte__begin_undo(tm); + stbte__erase(tm, mapx, mapy, STBTE__erase_all); + } + break; + case STBTE__leftup: + if (STBTE__IS_MAP_ACTIVE()) { + stbte__end_undo(tm); + stbte__activate(0); + } + break; + } + break; + + case STBTE__tool_select: + if (STBTE__IS_HOT(id)) { + switch (stbte__ui.event) { + case STBTE__leftdown: + if (STBTE__INACTIVE()) { + // if we're clicking in an existing selection... + if (stbte__ui.has_selection) { + if ( mapx >= stbte__ui.select_x0 && mapx <= stbte__ui.select_x1 + && mapy >= stbte__ui.select_y0 && mapy <= stbte__ui.select_y1) + { + stbte__ui.dragging = 1; + stbte__ui.drag_x = stbte__ui.select_x0; + stbte__ui.drag_y = stbte__ui.select_y0; + stbte__ui.drag_w = stbte__ui.select_x1 - stbte__ui.select_x0 + 1; + stbte__ui.drag_h = stbte__ui.select_y1 - stbte__ui.select_y0 + 1; + stbte__ui.drag_offx = mapx - stbte__ui.select_x0; + stbte__ui.drag_offy = mapy - stbte__ui.select_y0; + } + } + stbte__ui.has_selection = 0; // no selection until it completes + stbte__activate_map(mapx,mapy); + } + break; + case STBTE__leftup: + if (STBTE__IS_MAP_ACTIVE()) { + if (stbte__ui.dragging) { + stbte__drag_place(tm, mapx,mapy); + stbte__ui.dragging = 0; + stbte__activate(0); + } else { + stbte__select_rect(tm, stbte__ui.sx, stbte__ui.sy, mapx, mapy); + stbte__activate(0); + } + } + break; + case STBTE__rightdown: + stbte__ui.has_selection = 0; + break; + } + } + break; + + case STBTE__tool_rect: + if (STBTE__IS_HOT(id)) { + switch (stbte__ui.event) { + case STBTE__leftdown: + if (STBTE__INACTIVE()) + stbte__activate_map(mapx,mapy); + break; + case STBTE__leftup: + if (STBTE__IS_MAP_ACTIVE()) { + stbte__fillrect(tm, stbte__ui.sx, stbte__ui.sy, mapx, mapy, 1); + stbte__activate(0); + } + break; + case STBTE__rightdown: + if (STBTE__INACTIVE()) + stbte__activate_map(mapx,mapy); + break; + case STBTE__rightup: + if (STBTE__IS_MAP_ACTIVE()) { + stbte__fillrect(tm, stbte__ui.sx, stbte__ui.sy, mapx, mapy, 0); + stbte__activate(0); + } + break; + } + } + break; + + + case STBTE__tool_eyedrop: + switch (stbte__ui.event) { + case STBTE__leftdown: + if (STBTE__IS_HOT(id) && STBTE__INACTIVE()) + stbte__eyedrop(tm,mapx,mapy); + break; + } + break; + } +} + +static void stbte__start_paste(stbte_tilemap *tm) +{ + if (stbte__ui.has_copy) { + stbte__ui.pasting = 1; + stbte__activate(STBTE__ID(STBTE__toolbarB,3)); + } +} + +static void stbte__toolbar(stbte_tilemap *tm, int x0, int y0, int w, int h) +{ + int i; + int estimated_width = 13 * STBTE__num_tool + 8+8+ 120+4 - 30; + int x = x0 + w/2 - estimated_width/2; + int y = y0+1; + + for (i=0; i < STBTE__num_tool; ++i) { + int highlight=0, disable=0; + highlight = (stbte__ui.tool == i); + if (i == STBTE__tool_undo || i == STBTE__tool_showgrid) + x += 8; + if (i == STBTE__tool_showgrid && stbte__ui.show_grid) + highlight = 1; + if (i == STBTE__tool_showlinks && stbte__ui.show_links) + highlight = 1; + if (i == STBTE__tool_fill) + continue; + #ifndef STBTE_ALLOW_LINK + if (i == STBTE__tool_link || i == STBTE__tool_showlinks) + disable = 1; + #endif + if (i == STBTE__tool_undo && !stbte__undo_available(tm)) + disable = 1; + if (i == STBTE__tool_redo && !stbte__redo_available(tm)) + disable = 1; + if (stbte__button_icon(STBTE__ctoolbar_button, toolchar[i], x, y, 13, STBTE__ID(STBTE__toolbarA, i), highlight, disable)) { + switch (i) { + case STBTE__tool_eyedrop: + stbte__ui.eyedrop_last_layer = tm->num_layers; // flush eyedropper state + // fallthrough + default: + stbte__ui.tool = i; + stbte__ui.has_selection = 0; + break; + case STBTE__tool_showlinks: + stbte__ui.show_links = !stbte__ui.show_links; + break; + case STBTE__tool_showgrid: + stbte__ui.show_grid = (stbte__ui.show_grid+1)%3; + break; + case STBTE__tool_undo: + stbte__undo(tm); + break; + case STBTE__tool_redo: + stbte__redo(tm); + break; + } + } + x += 13; + } + + x += 8; + if (stbte__button(STBTE__ctoolbar_button, "cut" , x, y,10, 40, STBTE__ID(STBTE__toolbarB,0), 0, !stbte__ui.has_selection)) + stbte__copy_cut(tm, 1); + x += 42; + if (stbte__button(STBTE__ctoolbar_button, "copy" , x, y, 5, 40, STBTE__ID(STBTE__toolbarB,1), 0, !stbte__ui.has_selection)) + stbte__copy_cut(tm, 0); + x += 42; + if (stbte__button(STBTE__ctoolbar_button, "paste", x, y, 0, 40, STBTE__ID(STBTE__toolbarB,2), stbte__ui.pasting, !stbte__ui.has_copy)) + stbte__start_paste(tm); +} + +#define STBTE__TEXTCOLOR(n) stbte__color_table[n][STBTE__text][STBTE__idle] + +static int stbte__info_value(const char *label, int x, int y, int val, int digits, int id) +{ + if (stbte__ui.event == STBTE__paint) { + int off = 9-stbte__get_char_width(label[0]); + char text[16]; + stbte__sprintf(text stbte__sizeof(text), label, digits, val); + stbte__draw_text_core(x+off,y, text, 999, STBTE__TEXTCOLOR(STBTE__cpanel),1); + } + if (id) { + x += 9+7*digits+4; + if (stbte__minibutton(STBTE__cmapsize, x,y, '+', STBTE__ID2(id,1,0))) + val += (stbte__ui.shift ? 10 : 1); + x += 9; + if (stbte__minibutton(STBTE__cmapsize, x,y, '-', STBTE__ID2(id,2,0))) + val -= (stbte__ui.shift ? 10 : 1); + if (val < 1) val = 1; else if (val > 4096) val = 4096; + } + return val; +} + +static void stbte__info(stbte_tilemap *tm, int x0, int y0, int w, int h) +{ + int mode = stbte__ui.panel[STBTE__panel_info].mode; + int s = 11+7*tm->digits+4+15; + int x,y; + int in_region; + + x = x0+2; + y = y0+2; + tm->max_x = stbte__info_value("w:%*d",x,y, tm->max_x, tm->digits, STBTE__ID(STBTE__info,0)); + if (mode) + x += s; + else + y += 11; + tm->max_y = stbte__info_value("h:%*d",x,y, tm->max_y, tm->digits, STBTE__ID(STBTE__info,1)); + x = x0+2; + y += 11; + in_region = (stbte__ui.hot_id & 127) == STBTE__map; + stbte__info_value(in_region ? "x:%*d" : "x:",x,y, (stbte__ui.hot_id>>19)&4095, tm->digits, 0); + if (mode) + x += s; + else + y += 11; + stbte__info_value(in_region ? "y:%*d" : "y:",x,y, (stbte__ui.hot_id>> 7)&4095, tm->digits, 0); + y += 15; + x = x0+2; + stbte__draw_text(x,y,"brush:",40,STBTE__TEXTCOLOR(STBTE__cpanel)); + if (tm->cur_tile >= 0) + STBTE_DRAW_TILE(x+43,y-3,tm->tiles[tm->cur_tile].id,1,0); +} + +static void stbte__layers(stbte_tilemap *tm, int x0, int y0, int w, int h) +{ + static const char *propmodes[3] = { + "default", "always", "never" + }; + int num_rows; + int i, y, n; + int x1 = x0+w; + int y1 = y0+h; + int xoff = 20; + + if (tm->has_layer_names) { + int side = stbte__ui.panel[STBTE__panel_layers].side; + xoff = stbte__region[side].width - 42; + xoff = (xoff < tm->layername_width + 10 ? xoff : tm->layername_width + 10); + } + + x0 += 2; + y0 += 5; + if (!tm->has_layer_names) { + if (stbte__ui.event == STBTE__paint) { + stbte__draw_text(x0,y0, "Layers", w-4, STBTE__TEXTCOLOR(STBTE__cpanel)); + } + y0 += 11; + } + num_rows = (y1-y0)/15; +#ifndef STBTE_NO_PROPS + --num_rows; +#endif + y = y0; + for (i=0; i < tm->num_layers; ++i) { + char text[3], *str = (char *) tm->layerinfo[i].name; + static char lockedchar[3] = { 'U', 'P', 'L' }; + int locked = tm->layerinfo[i].locked; + int disabled = (tm->solo_layer >= 0 && tm->solo_layer != i); + if (i-tm->layer_scroll >= 0 && i-tm->layer_scroll < num_rows) { + if (str == NULL) + stbte__sprintf(str=text stbte__sizeof(text), "%2d", i+1); + if (stbte__button(STBTE__clayer_button, str, x0,y,(i+1<10)*2,xoff-2, STBTE__ID(STBTE__layer,i), tm->cur_layer==i,0)) + tm->cur_layer = (tm->cur_layer == i ? -1 : i); + if (stbte__layerbutton(x0+xoff + 0,y+1,'H',STBTE__ID(STBTE__hide,i), tm->layerinfo[i].hidden,disabled,STBTE__clayer_hide)) + tm->layerinfo[i].hidden = !tm->layerinfo[i].hidden; + if (stbte__layerbutton(x0+xoff + 12,y+1,lockedchar[locked],STBTE__ID(STBTE__lock,i), locked!=0,disabled,STBTE__clayer_lock)) + tm->layerinfo[i].locked = (locked+1)%3; + if (stbte__layerbutton(x0+xoff + 24,y+1,'S',STBTE__ID(STBTE__solo,i), tm->solo_layer==i,0,STBTE__clayer_solo)) + tm->solo_layer = (tm->solo_layer == i ? -1 : i); + y += 15; + } + } + stbte__scrollbar(x1-4, y0,y-2, &tm->layer_scroll, 0, tm->num_layers, num_rows, STBTE__ID(STBTE__scrollbar_id, STBTE__layer)); +#ifndef STBTE_NO_PROPS + n = stbte__text_width("prop:")+2; + stbte__draw_text(x0,y+2, "prop:", w, STBTE__TEXTCOLOR(STBTE__cpanel)); + i = w - n - 4; + if (i > 50) i = 50; + if (stbte__button(STBTE__clayer_button, propmodes[tm->propmode], x0+n,y,0,i, STBTE__ID(STBTE__layer,256), 0,0)) + tm->propmode = (tm->propmode+1)%3; +#endif +} + +static void stbte__categories(stbte_tilemap *tm, int x0, int y0, int w, int h) +{ + int s=11, x,y, i; + int num_rows = h / s; + + w -= 4; + x = x0+2; + y = y0+4; + if (tm->category_scroll == 0) { + if (stbte__category_button("*ALL*", x,y, w, STBTE__ID(STBTE__categories, 65535), tm->cur_category == -1)) { + stbte__choose_category(tm, -1); + } + y += s; + } + + for (i=0; i < tm->num_categories; ++i) { + if (i+1 - tm->category_scroll >= 0 && i+1 - tm->category_scroll < num_rows) { + if (y + 10 > y0+h) + return; + if (stbte__category_button(tm->categories[i], x,y,w, STBTE__ID(STBTE__categories,i), tm->cur_category == i)) + stbte__choose_category(tm, i); + y += s; + } + } + stbte__scrollbar(x0+w, y0+4, y0+h-4, &tm->category_scroll, 0, tm->num_categories+1, num_rows, STBTE__ID(STBTE__scrollbar_id, STBTE__categories)); +} + +static void stbte__tile_in_palette(stbte_tilemap *tm, int x, int y, int slot) +{ + stbte__tileinfo *t = &tm->tiles[slot]; + int x0=x, y0=y, x1 = x+tm->palette_spacing_x - 1, y1 = y+tm->palette_spacing_y; + int id = STBTE__ID(STBTE__palette, slot); + stbte__hittest(x0,y0,x1,y1, id); + switch (stbte__ui.event) { + case STBTE__paint: + stbte__draw_rect(x,y,x+tm->palette_spacing_x-1,y+tm->palette_spacing_x-1, STBTE_COLOR_TILEPALETTE_BACKGROUND); + STBTE_DRAW_TILE(x,y,id, slot == tm->cur_tile,0); + if (slot == tm->cur_tile) + stbte__draw_frame_delayed(x-1,y-1,x+tm->palette_spacing_x,y+tm->palette_spacing_y, STBTE_COLOR_TILEPALETTE_OUTLINE); + break; + default: + if (stbte__button_core(id)) + tm->cur_tile = slot; + break; + } +} + +static void stbte__palette_of_tiles(stbte_tilemap *tm, int x0, int y0, int w, int h) +{ + int i,x,y; + int num_vis_rows = (h-6) / tm->palette_spacing_y; + int num_columns = (w-2-6) / tm->palette_spacing_x; + int num_total_rows; + int column,row; + int x1 = x0+w, y1=y0+h; + x = x0+2; + y = y0+6; + + if (num_columns == 0) + return; + + num_total_rows = (tm->cur_palette_count + num_columns-1) / num_columns; // ceil() + + column = 0; + row = -tm->palette_scroll; + for (i=0; i < tm->num_tiles; ++i) { + stbte__tileinfo *t = &tm->tiles[i]; + + // filter based on category + if (tm->cur_category >= 0 && t->category_id != tm->cur_category) + continue; + + // display it + if (row >= 0 && row < num_vis_rows) { + x = x0 + 2 + tm->palette_spacing_x * column; + y = y0 + 6 + tm->palette_spacing_y * row; + stbte__tile_in_palette(tm,x,y,i); + } + + ++column; + if (column == num_columns) { + column = 0; + ++row; + } + } + stbte__flush_delay(); + stbte__scrollbar(x1-4, y0+6, y1-2, &tm->palette_scroll, 0, num_total_rows, num_vis_rows, STBTE__ID(STBTE__scrollbar_id, STBTE__palette)); +} + +static float stbte__saved; +static void stbte__props_panel(stbte_tilemap *tm, int x0, int y0, int w, int h) +{ + int x1 = x0+w; + int i; + int y = y0 + 5, x = x0+2; + int slider_width = 60; + int mx,my; + float *p; + short *data; + if (!stbte__is_single_selection()) + return; + mx = stbte__ui.select_x0; + my = stbte__ui.select_y0; + p = tm->props[my][mx]; + data = tm->data[my][mx]; + STBTE__NOTUSED(data); + for (i=0; i < STBTE_MAX_PROPERTIES; ++i) { + unsigned int n = STBTE_PROP_TYPE(i, data, p); + if (n) { + char *s = (char*) STBTE_PROP_NAME(i, data, p); + if (s == NULL) s = (char*) ""; + switch (n & 3) { + case STBTE_PROP_bool: { + int flag = (int) p[i]; + if (stbte__layerbutton(x,y, flag ? 'x' : ' ', STBTE__ID(STBTE__prop_flag,i), flag, 0, 2)) { + stbte__begin_undo(tm); + stbte__undo_record_prop_float(tm,mx,my,i,(float) flag); + p[i] = (float) !flag; + stbte__end_undo(tm); + } + stbte__draw_text(x+13,y+1,s,x1-(x+13)-2,STBTE__TEXTCOLOR(STBTE__cpanel)); + y += 13; + break; + } + case STBTE_PROP_int: { + int a = (int) STBTE_PROP_MIN(i,data,p); + int b = (int) STBTE_PROP_MAX(i,data,p); + int v = (int) p[i] - a; + if (a+v != p[i] || v < 0 || v > b-a) { + if (v < 0) v = 0; + if (v > b-a) v = b-a; + p[i] = (float) (a+v); // @TODO undo + } + switch (stbte__slider(x, slider_width, y+7, b-a, &v, STBTE__ID(STBTE__prop_int,i))) + { + case STBTE__begin: + stbte__saved = p[i]; + // fallthrough + case STBTE__change: + p[i] = (float) (a+v); // @TODO undo + break; + case STBTE__end: + if (p[i] != stbte__saved) { + stbte__begin_undo(tm); + stbte__undo_record_prop_float(tm,mx,my,i,stbte__saved); + stbte__end_undo(tm); + } + break; + } + stbte__draw_text(x+slider_width+2,y+2, s, x1-1-(x+slider_width+2), STBTE__TEXTCOLOR(STBTE__cpanel)); + y += 12; + break; + } + case STBTE_PROP_float: { + float a = (float) STBTE_PROP_MIN(i, data,p); + float b = (float) STBTE_PROP_MAX(i, data,p); + float c = STBTE_PROP_FLOAT_SCALE(i, data, p); + float old; + if (p[i] < a || p[i] > b) { + // @TODO undo + if (p[i] < a) p[i] = a; + if (p[i] > b) p[i] = b; + } + old = p[i]; + switch (stbte__float_control(x, y, 50, a, b, c, "%8.4f", &p[i], STBTE__layer,STBTE__ID(STBTE__prop_float,i))) { + case STBTE__begin: + stbte__saved = old; + break; + case STBTE__end: + if (stbte__saved != p[i]) { + stbte__begin_undo(tm); + stbte__undo_record_prop_float(tm,mx,my,i, stbte__saved); + stbte__end_undo(tm); + } + break; + } + stbte__draw_text(x+53,y+1, s, x1-1-(x+53), STBTE__TEXTCOLOR(STBTE__cpanel)); + y += 12; + break; + } + } + } + } +} + +static int stbte__cp_mode, stbte__cp_aspect, stbte__save, stbte__cp_altered; +#ifdef STBTE__COLORPICKER +static int stbte__cp_state, stbte__cp_index, stbte__color_copy; +static void stbte__dump_colorstate(void) +{ + int i,j,k; + printf("static int stbte__color_table[STBTE__num_color_modes][STBTE__num_color_aspects][STBTE__num_color_states] =\n"); + printf("{\n"); + printf(" {\n"); + for (k=0; k < STBTE__num_color_modes; ++k) { + for (j=0; j < STBTE__num_color_aspects; ++j) { + printf(" { "); + for (i=0; i < STBTE__num_color_states; ++i) { + printf("0x%06x, ", stbte__color_table[k][j][i]); + } + printf("},\n"); + } + if (k+1 < STBTE__num_color_modes) + printf(" }, {\n"); + else + printf(" },\n"); + } + printf("};\n"); +} + +static void stbte__colorpicker(int x0, int y0, int w, int h) +{ + int x1 = x0+w, y1 = y0+h, x,y, i; + + x = x0+2; y = y0+6; + + y += 5; + x += 8; + + + { + int color = stbte__color_table[stbte__cp_mode][stbte__cp_aspect][stbte__cp_index]; + int rgb[3]; + if (stbte__cp_altered && stbte__cp_index == STBTE__idle) + color = stbte__save; + + if (stbte__minibutton(STBTE__cmapsize, x1-20,y+ 5, 'C', STBTE__ID2(STBTE__colorpick_id,4,0))) + stbte__color_copy = color; + if (stbte__minibutton(STBTE__cmapsize, x1-20,y+15, 'P', STBTE__ID2(STBTE__colorpick_id,4,1))) + color = stbte__color_copy; + + rgb[0] = color >> 16; rgb[1] = (color>>8)&255; rgb[2] = color & 255; + for (i=0; i < 3; ++i) { + if (stbte__slider(x+8,64, y, 255, rgb+i, STBTE__ID2(STBTE__colorpick_id,3,i)) > 0) + stbte__dump_colorstate(); + y += 15; + } + if (stbte__ui.event != STBTE__paint && stbte__ui.event != STBTE__tick) + stbte__color_table[stbte__cp_mode][stbte__cp_aspect][stbte__cp_index] = (rgb[0]<<16)|(rgb[1]<<8)|(rgb[2]); + } + + y += 5; + + // states + x = x0+2+35; + if (stbte__ui.event == STBTE__paint) { + static char *states[] = { "idle", "over", "down", "down&over", "selected", "selected&over", "disabled" }; + stbte__draw_text(x, y+1, states[stbte__cp_index], x1-x-1, 0xffffff); + } + + x = x0+24; y += 12; + + for (i=3; i >= 0; --i) { + int state = 0 != (stbte__cp_state & (1 << i)); + if (stbte__layerbutton(x,y, "OASD"[i], STBTE__ID2(STBTE__colorpick_id, 0,i), state,0, STBTE__clayer_button)) { + stbte__cp_state ^= (1 << i); + stbte__cp_index = stbte__state_to_index[0][0][0][stbte__cp_state]; + } + x += 16; + } + x = x0+2; y += 18; + + for (i=0; i < 3; ++i) { + static char *labels[] = { "Base", "Edge", "Text" }; + if (stbte__button(STBTE__ctoolbar_button, labels[i], x,y,0,36, STBTE__ID2(STBTE__colorpick_id,1,i), stbte__cp_aspect==i,0)) + stbte__cp_aspect = i; + x += 40; + } + + y += 18; + x = x0+2; + + for (i=0; i < STBTE__num_color_modes; ++i) { + if (stbte__button(STBTE__ctoolbar_button, stbte__color_names[i], x, y, 0,80, STBTE__ID2(STBTE__colorpick_id,2,i), stbte__cp_mode == i,0)) + stbte__cp_mode = i; + y += 12; + } + + // make the currently selected aspect flash, unless we're actively dragging color slider etc + if (stbte__ui.event == STBTE__tick) { + stbte__save = stbte__color_table[stbte__cp_mode][stbte__cp_aspect][STBTE__idle]; + if ((stbte__ui.active_id & 127) != STBTE__colorpick_id) { + if ((stbte__ui.ms_time & 2047) < 200) { + stbte__color_table[stbte__cp_mode][stbte__cp_aspect][STBTE__idle] ^= 0x1f1f1f; + stbte__cp_altered = 1; + } + } + } +} +#endif + +static void stbte__editor_traverse(stbte_tilemap *tm) +{ + int i,j,i0,j0,i1,j1,n; + + if (tm == NULL) + return; + if (stbte__ui.x0 == stbte__ui.x1 || stbte__ui.y0 == stbte__ui.y1) + return; + + stbte__prepare_tileinfo(tm); + + stbte__compute_panel_locations(tm); // @OPTIMIZE: we don't need to recompute this every time + + if (stbte__ui.event == STBTE__paint) { + // fill screen with border + stbte__draw_rect(stbte__ui.x0, stbte__ui.y0, stbte__ui.x1, stbte__ui.y1, STBTE_COLOR_TILEMAP_BORDER); + // fill tilemap with tilemap background + stbte__draw_rect(stbte__ui.x0 - tm->scroll_x, stbte__ui.y0 - tm->scroll_y, + stbte__ui.x0 - tm->scroll_x + tm->spacing_x * tm->max_x, + stbte__ui.y0 - tm->scroll_y + tm->spacing_y * tm->max_y, STBTE_COLOR_TILEMAP_BACKGROUND); + } + + // step 1: traverse all the tilemap data... + + i0 = (tm->scroll_x - tm->spacing_x) / tm->spacing_x; + j0 = (tm->scroll_y - tm->spacing_y) / tm->spacing_y; + i1 = (tm->scroll_x + stbte__ui.x1 - stbte__ui.x0) / tm->spacing_x + 1; + j1 = (tm->scroll_y + stbte__ui.y1 - stbte__ui.y0) / tm->spacing_y + 1; + + if (i0 < 0) i0 = 0; + if (j0 < 0) j0 = 0; + if (i1 > tm->max_x) i1 = tm->max_x; + if (j1 > tm->max_y) j1 = tm->max_y; + + if (stbte__ui.event == STBTE__paint) { + // draw all of layer 0, then all of layer 1, etc, instead of old + // way which drew entire stack of each tile at once + for (n=0; n < tm->num_layers; ++n) { + for (j=j0; j < j1; ++j) { + for (i=i0; i < i1; ++i) { + int x = stbte__ui.x0 + i * tm->spacing_x - tm->scroll_x; + int y = stbte__ui.y0 + j * tm->spacing_y - tm->scroll_y; + stbte__tile_paint(tm, x, y, i, j, n); + } + } + if (n == 0 && stbte__ui.show_grid == 1) { + int x = stbte__ui.x0 + i0 * tm->spacing_x - tm->scroll_x; + int y = stbte__ui.y0 + j0 * tm->spacing_y - tm->scroll_y; + for (i=0; x < stbte__ui.x1 && i <= i1; ++i, x += tm->spacing_x) + stbte__draw_rect(x, stbte__ui.y0, x+1, stbte__ui.y1, STBTE_COLOR_GRID); + for (j=0; y < stbte__ui.y1 && j <= j1; ++j, y += tm->spacing_y) + stbte__draw_rect(stbte__ui.x0, y, stbte__ui.x1, y+1, STBTE_COLOR_GRID); + } + } + } + + if (stbte__ui.event == STBTE__paint) { + // draw grid on top of everything except UI + if (stbte__ui.show_grid == 2) { + int x = stbte__ui.x0 + i0 * tm->spacing_x - tm->scroll_x; + int y = stbte__ui.y0 + j0 * tm->spacing_y - tm->scroll_y; + for (i=0; x < stbte__ui.x1 && i <= i1; ++i, x += tm->spacing_x) + stbte__draw_rect(x, stbte__ui.y0, x+1, stbte__ui.y1, STBTE_COLOR_GRID); + for (j=0; y < stbte__ui.y1 && j <= j1; ++j, y += tm->spacing_y) + stbte__draw_rect(stbte__ui.x0, y, stbte__ui.x1, y+1, STBTE_COLOR_GRID); + } + } + + for (j=j0; j < j1; ++j) { + for (i=i0; i < i1; ++i) { + int x = stbte__ui.x0 + i * tm->spacing_x - tm->scroll_x; + int y = stbte__ui.y0 + j * tm->spacing_y - tm->scroll_y; + stbte__tile(tm, x, y, i, j); + } + } + + if (stbte__ui.event == STBTE__paint) { + // draw the selection border + if (stbte__ui.has_selection) { + int x0,y0,x1,y1; + x0 = stbte__ui.x0 + (stbte__ui.select_x0 ) * tm->spacing_x - tm->scroll_x; + y0 = stbte__ui.y0 + (stbte__ui.select_y0 ) * tm->spacing_y - tm->scroll_y; + x1 = stbte__ui.x0 + (stbte__ui.select_x1 + 1) * tm->spacing_x - tm->scroll_x + 1; + y1 = stbte__ui.y0 + (stbte__ui.select_y1 + 1) * tm->spacing_y - tm->scroll_y + 1; + stbte__draw_frame(x0,y0,x1,y1, (stbte__ui.ms_time & 256 ? STBTE_COLOR_SELECTION_OUTLINE1 : STBTE_COLOR_SELECTION_OUTLINE2)); + } + + stbte__flush_delay(); // draw a dynamic link on top of the queued links + + #ifdef STBTE_ALLOW_LINK + if (stbte__ui.linking && STBTE__IS_MAP_HOT()) { + int x0,y0,x1,y1; + int color; + int ex = ((stbte__ui.hot_id >> 19) & 4095); + int ey = ((stbte__ui.hot_id >> 7) & 4095); + x0 = stbte__ui.x0 + (stbte__ui.sx ) * tm->spacing_x - tm->scroll_x + (tm->spacing_x>>1)+1; + y0 = stbte__ui.y0 + (stbte__ui.sy ) * tm->spacing_y - tm->scroll_y + (tm->spacing_y>>1)+1; + x1 = stbte__ui.x0 + (ex ) * tm->spacing_x - tm->scroll_x + (tm->spacing_x>>1)-1; + y1 = stbte__ui.y0 + (ey ) * tm->spacing_y - tm->scroll_y + (tm->spacing_y>>1)-1; + if (STBTE_ALLOW_LINK(tm->data[stbte__ui.sy][stbte__ui.sx], tm->props[stbte__ui.sy][stbte__ui.sx], tm->data[ey][ex], tm->props[ey][ex])) + color = STBTE_LINK_COLOR_DRAWING; + else + color = STBTE_LINK_COLOR_DISALLOWED; + stbte__draw_link(x0,y0,x1,y1, color); + } + #endif + } + stbte__flush_delay(); + + // step 2: traverse the panels + for (i=0; i < STBTE__num_panel; ++i) { + stbte__panel *p = &stbte__ui.panel[i]; + if (stbte__ui.event == STBTE__paint) { + stbte__draw_box(p->x0,p->y0,p->x0+p->width,p->y0+p->height, STBTE__cpanel, STBTE__idle); + } + // obscure tilemap data underneath panel + stbte__hittest(p->x0,p->y0,p->x0+p->width,p->y0+p->height, STBTE__ID2(STBTE__panel, i, 0)); + switch (i) { + case STBTE__panel_toolbar: + if (stbte__ui.event == STBTE__paint) + stbte__draw_rect(p->x0,p->y0,p->x0+p->width,p->y0+p->height, stbte__color_table[STBTE__ctoolbar][STBTE__base][STBTE__idle]); + stbte__toolbar(tm,p->x0,p->y0,p->width,p->height); + break; + case STBTE__panel_info: + stbte__info(tm,p->x0,p->y0,p->width,p->height); + break; + case STBTE__panel_layers: + stbte__layers(tm,p->x0,p->y0,p->width,p->height); + break; + case STBTE__panel_categories: + stbte__categories(tm,p->x0,p->y0,p->width,p->height); + break; + case STBTE__panel_colorpick: +#ifdef STBTE__COLORPICKER + stbte__colorpicker(p->x0,p->y0,p->width,p->height); +#endif + break; + case STBTE__panel_tiles: + // erase boundary between categories and tiles if they're on same side + if (stbte__ui.event == STBTE__paint && p->side == stbte__ui.panel[STBTE__panel_categories].side) + stbte__draw_rect(p->x0+1,p->y0-1,p->x0+p->width-1,p->y0+1, stbte__color_table[STBTE__cpanel][STBTE__base][STBTE__idle]); + stbte__palette_of_tiles(tm,p->x0,p->y0,p->width,p->height); + break; + case STBTE__panel_props: + stbte__props_panel(tm,p->x0,p->y0,p->width,p->height); + break; + } + // draw the panel side selectors + for (j=0; j < 2; ++j) { + int result; + if (i == STBTE__panel_toolbar) continue; + result = stbte__microbutton(p->x0+p->width - 1 - 2*4 + 4*j,p->y0+2,3, STBTE__ID2(STBTE__panel, i, j+1), STBTE__cpanel_sider+j); + if (result) { + switch (j) { + case 0: p->side = result > 0 ? STBTE__side_left : STBTE__side_right; break; + case 1: p->delta_height += result; break; + } + } + } + } + + if (stbte__ui.panel[STBTE__panel_categories].delta_height < -5) stbte__ui.panel[STBTE__panel_categories].delta_height = -5; + if (stbte__ui.panel[STBTE__panel_layers ].delta_height < -5) stbte__ui.panel[STBTE__panel_layers ].delta_height = -5; + + + // step 3: traverse the regions to place expander controls on them + for (i=0; i < 2; ++i) { + if (stbte__region[i].active) { + int x = stbte__region[i].x; + int width; + if (i == STBTE__side_left) + width = stbte__ui.left_width , x += stbte__region[i].width + 1; + else + width = -stbte__ui.right_width, x -= 6; + if (stbte__microbutton_dragger(x, stbte__region[i].y+2, 5, STBTE__ID(STBTE__region,i), &width)) { + // if non-0, it is expanding, so retract it + if (stbte__region[i].retracted == 0.0) + stbte__region[i].retracted = 0.01f; + else + stbte__region[i].retracted = 0.0; + } + if (i == STBTE__side_left) + stbte__ui.left_width = width; + else + stbte__ui.right_width = -width; + if (stbte__ui.event == STBTE__tick) { + if (stbte__region[i].retracted && stbte__region[i].retracted < 1.0f) { + stbte__region[i].retracted += stbte__ui.dt*4; + if (stbte__region[i].retracted > 1) + stbte__region[i].retracted = 1; + } + } + } + } + + if (stbte__ui.event == STBTE__paint && stbte__ui.alert_msg) { + int w = stbte__text_width(stbte__ui.alert_msg); + int x = (stbte__ui.x0+stbte__ui.x1)/2; + int y = (stbte__ui.y0+stbte__ui.y1)*5/6; + stbte__draw_rect (x-w/2-4,y-8, x+w/2+4,y+8, 0x604020); + stbte__draw_frame(x-w/2-4,y-8, x+w/2+4,y+8, 0x906030); + stbte__draw_text (x-w/2,y-4, stbte__ui.alert_msg, w+1, 0xff8040); + } + +#ifdef STBTE_SHOW_CURSOR + if (stbte__ui.event == STBTE__paint) + stbte__draw_bitmap(stbte__ui.mx, stbte__ui.my, stbte__get_char_width(26), stbte__get_char_bitmap(26), 0xe0e0e0); +#endif + + if (stbte__ui.event == STBTE__tick && stbte__ui.alert_msg) { + stbte__ui.alert_timer -= stbte__ui.dt; + if (stbte__ui.alert_timer < 0) { + stbte__ui.alert_timer = 0; + stbte__ui.alert_msg = 0; + } + } + + if (stbte__ui.event == STBTE__paint) { + stbte__color_table[stbte__cp_mode][stbte__cp_aspect][STBTE__idle] = stbte__save; + stbte__cp_altered = 0; + } +} + +static void stbte__do_event(stbte_tilemap *tm) +{ + stbte__ui.next_hot_id = 0; + stbte__editor_traverse(tm); + stbte__ui.hot_id = stbte__ui.next_hot_id; + + // automatically cancel on mouse-up in case the object that triggered it + // doesn't exist anymore + if (stbte__ui.active_id) { + if (stbte__ui.event == STBTE__leftup || stbte__ui.event == STBTE__rightup) { + if (!stbte__ui.pasting) { + stbte__activate(0); + if (stbte__ui.undoing) + stbte__end_undo(tm); + stbte__ui.scrolling = 0; + stbte__ui.dragging = 0; + stbte__ui.linking = 0; + } + } + } + + // we could do this stuff in the widgets directly, but it would keep recomputing + // the same thing on every tile, which seems dumb. + + if (stbte__ui.pasting) { + if (STBTE__IS_MAP_HOT()) { + // compute pasting location based on last hot + stbte__ui.paste_x = ((stbte__ui.hot_id >> 19) & 4095) - (stbte__ui.copy_width >> 1); + stbte__ui.paste_y = ((stbte__ui.hot_id >> 7) & 4095) - (stbte__ui.copy_height >> 1); + } + } + if (stbte__ui.dragging) { + if (STBTE__IS_MAP_HOT()) { + stbte__ui.drag_dest_x = ((stbte__ui.hot_id >> 19) & 4095) - stbte__ui.drag_offx; + stbte__ui.drag_dest_y = ((stbte__ui.hot_id >> 7) & 4095) - stbte__ui.drag_offy; + } + } +} + +static void stbte__set_event(int event, int x, int y) +{ + stbte__ui.event = event; + stbte__ui.mx = x; + stbte__ui.my = y; + stbte__ui.dx = x - stbte__ui.last_mouse_x; + stbte__ui.dy = y - stbte__ui.last_mouse_y; + stbte__ui.last_mouse_x = x; + stbte__ui.last_mouse_y = y; + stbte__ui.accum_x += stbte__ui.dx; + stbte__ui.accum_y += stbte__ui.dy; +} + +void stbte_draw(stbte_tilemap *tm) +{ + stbte__ui.event = STBTE__paint; + stbte__editor_traverse(tm); +} + +void stbte_mouse_move(stbte_tilemap *tm, int x, int y, int shifted, int scrollkey) +{ + stbte__set_event(STBTE__mousemove, x,y); + stbte__ui.shift = shifted; + stbte__ui.scrollkey = scrollkey; + stbte__do_event(tm); +} + +void stbte_mouse_button(stbte_tilemap *tm, int x, int y, int right, int down, int shifted, int scrollkey) +{ + static int events[2][2] = { { STBTE__leftup , STBTE__leftdown }, + { STBTE__rightup, STBTE__rightdown } }; + stbte__set_event(events[right][down], x,y); + stbte__ui.shift = shifted; + stbte__ui.scrollkey = scrollkey; + + stbte__do_event(tm); +} + +void stbte_mouse_wheel(stbte_tilemap *tm, int x, int y, int vscroll) +{ + // not implemented yet -- need different way of hittesting +} + +void stbte_action(stbte_tilemap *tm, enum stbte_action act) +{ + switch (act) { + case STBTE_tool_select: stbte__ui.tool = STBTE__tool_select; break; + case STBTE_tool_brush: stbte__ui.tool = STBTE__tool_brush; break; + case STBTE_tool_erase: stbte__ui.tool = STBTE__tool_erase; break; + case STBTE_tool_rectangle: stbte__ui.tool = STBTE__tool_rect; break; + case STBTE_tool_eyedropper: stbte__ui.tool = STBTE__tool_eyedrop; break; + case STBTE_tool_link: stbte__ui.tool = STBTE__tool_link; break; + case STBTE_act_toggle_grid: stbte__ui.show_grid = (stbte__ui.show_grid+1) % 3; break; + case STBTE_act_toggle_links: stbte__ui.show_links ^= 1; break; + case STBTE_act_undo: stbte__undo(tm); break; + case STBTE_act_redo: stbte__redo(tm); break; + case STBTE_act_cut: stbte__copy_cut(tm, 1); break; + case STBTE_act_copy: stbte__copy_cut(tm, 0); break; + case STBTE_act_paste: stbte__start_paste(tm); break; + case STBTE_scroll_left: tm->scroll_x -= tm->spacing_x; break; + case STBTE_scroll_right: tm->scroll_x += tm->spacing_x; break; + case STBTE_scroll_up: tm->scroll_y -= tm->spacing_y; break; + case STBTE_scroll_down: tm->scroll_y += tm->spacing_y; break; + } +} + +void stbte_tick(stbte_tilemap *tm, float dt) +{ + stbte__ui.event = STBTE__tick; + stbte__ui.dt = dt; + stbte__do_event(tm); + stbte__ui.ms_time += (int) (dt * 1024) + 1; // make sure if time is superfast it always updates a little +} + +void stbte_mouse_sdl(stbte_tilemap *tm, const void *sdl_event, float xs, float ys, int xo, int yo) +{ +#ifdef _SDL_H + SDL_Event *event = (SDL_Event *) sdl_event; + SDL_Keymod km = SDL_GetModState(); + int shift = (km & KMOD_LCTRL) || (km & KMOD_RCTRL); + int scrollkey = 0 != SDL_GetKeyboardState(NULL)[SDL_SCANCODE_SPACE]; + switch (event->type) { + case SDL_MOUSEMOTION: + stbte_mouse_move(tm, (int) (xs*event->motion.x+xo), (int) (ys*event->motion.y+yo), shift, scrollkey); + break; + case SDL_MOUSEBUTTONUP: + stbte_mouse_button(tm, (int) (xs*event->button.x+xo), (int) (ys*event->button.y+yo), event->button.button != SDL_BUTTON_LEFT, 0, shift, scrollkey); + break; + case SDL_MOUSEBUTTONDOWN: + stbte_mouse_button(tm, (int) (xs*event->button.x+xo), (int) (ys*event->button.y+yo), event->button.button != SDL_BUTTON_LEFT, 1, shift, scrollkey); + break; + case SDL_MOUSEWHEEL: + stbte_mouse_wheel(tm, stbte__ui.mx, stbte__ui.my, event->wheel.y); + break; + } +#else + STBTE__NOTUSED(tm); + STBTE__NOTUSED(sdl_event); + STBTE__NOTUSED(xs); + STBTE__NOTUSED(ys); + STBTE__NOTUSED(xo); + STBTE__NOTUSED(yo); +#endif +} + +#endif // STB_TILEMAP_EDITOR_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_truetype.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_truetype.h new file mode 100644 index 0000000..90a5c2e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_truetype.h @@ -0,0 +1,5079 @@ +// stb_truetype.h - v1.26 - public domain +// authored from 2009-2021 by Sean Barrett / RAD Game Tools +// +// ======================================================================= +// +// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES +// +// This library does no range checking of the offsets found in the file, +// meaning an attacker can use it to read arbitrary memory. +// +// ======================================================================= +// +// This library processes TrueType files: +// parse files +// extract glyph metrics +// extract glyph shapes +// render glyphs to one-channel bitmaps with antialiasing (box filter) +// render glyphs to one-channel SDF bitmaps (signed-distance field/function) +// +// Todo: +// non-MS cmaps +// crashproof on bad data +// hinting? (no longer patented) +// cleartype-style AA? +// optimize: use simple memory allocator for intermediates +// optimize: build edge-list directly from curves +// optimize: rasterize directly from curves? +// +// ADDITIONAL CONTRIBUTORS +// +// Mikko Mononen: compound shape support, more cmap formats +// Tor Andersson: kerning, subpixel rendering +// Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning +// +// Misc other: +// Ryan Gordon +// Simon Glass +// github:IntellectualKitty +// Imanol Celaya +// Daniel Ribeiro Maciel +// +// Bug/warning reports/fixes: +// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe +// Cass Everitt Martins Mozeiko github:aloucks +// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam +// Brian Hook Omar Cornut github:vassvik +// Walter van Niftrik Ryan Griege +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. Brian Costabile +// Ken Voskuil (kaesve) Yakov Galka +// +// VERSION HISTORY +// +// 1.26 (2021-08-28) fix broken rasterizer +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// variant PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// +// Full history can be found at the end of this file. +// +// LICENSE +// +// See end of file for license information. +// +// USAGE +// +// Include this file in whatever places need to refer to it. In ONE C/C++ +// file, write: +// #define STB_TRUETYPE_IMPLEMENTATION +// before the #include of this file. This expands out the actual +// implementation into that C/C++ file. +// +// To make the implementation private to the file that generates the implementation, +// #define STBTT_STATIC +// +// Simple 3D API (don't ship this, but it's fine for tools and quick start) +// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture +// stbtt_GetBakedQuad() -- compute quad to draw for a given char +// +// Improved 3D API (more shippable): +// #include "stb_rect_pack.h" -- optional, but you really want it +// stbtt_PackBegin() +// stbtt_PackSetOversampling() -- for improved quality on small fonts +// stbtt_PackFontRanges() -- pack and renders +// stbtt_PackEnd() +// stbtt_GetPackedQuad() +// +// "Load" a font file from a memory buffer (you have to keep the buffer loaded) +// stbtt_InitFont() +// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections +// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections +// +// Render a unicode codepoint to a bitmap +// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap +// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide +// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be +// +// Character advance/positioning +// stbtt_GetCodepointHMetrics() +// stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() +// stbtt_GetCodepointKernAdvance() +// +// Starting with version 1.06, the rasterizer was replaced with a new, +// faster and generally-more-precise rasterizer. The new rasterizer more +// accurately measures pixel coverage for anti-aliasing, except in the case +// where multiple shapes overlap, in which case it overestimates the AA pixel +// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If +// this turns out to be a problem, you can re-enable the old rasterizer with +// #define STBTT_RASTERIZER_VERSION 1 +// which will incur about a 15% speed hit. +// +// ADDITIONAL DOCUMENTATION +// +// Immediately after this block comment are a series of sample programs. +// +// After the sample programs is the "header file" section. This section +// includes documentation for each API function. +// +// Some important concepts to understand to use this library: +// +// Codepoint +// Characters are defined by unicode codepoints, e.g. 65 is +// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is +// the hiragana for "ma". +// +// Glyph +// A visual character shape (every codepoint is rendered as +// some glyph) +// +// Glyph index +// A font-specific integer ID representing a glyph +// +// Baseline +// Glyph shapes are defined relative to a baseline, which is the +// bottom of uppercase characters. Characters extend both above +// and below the baseline. +// +// Current Point +// As you draw text to the screen, you keep track of a "current point" +// which is the origin of each character. The current point's vertical +// position is the baseline. Even "baked fonts" use this model. +// +// Vertical Font Metrics +// The vertical qualities of the font, used to vertically position +// and space the characters. See docs for stbtt_GetFontVMetrics. +// +// Font Size in Pixels or Points +// The preferred interface for specifying font sizes in stb_truetype +// is to specify how tall the font's vertical extent should be in pixels. +// If that sounds good enough, skip the next paragraph. +// +// Most font APIs instead use "points", which are a common typographic +// measurement for describing font size, defined as 72 points per inch. +// stb_truetype provides a point API for compatibility. However, true +// "per inch" conventions don't make much sense on computer displays +// since different monitors have different number of pixels per +// inch. For example, Windows traditionally uses a convention that +// there are 96 pixels per inch, thus making 'inch' measurements have +// nothing to do with inches, and thus effectively defining a point to +// be 1.333 pixels. Additionally, the TrueType font data provides +// an explicit scale factor to scale a given font's glyphs to points, +// but the author has observed that this scale factor is often wrong +// for non-commercial fonts, thus making fonts scaled in points +// according to the TrueType spec incoherently sized in practice. +// +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to . I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// to = 32 && *text < 128) { + stbtt_aligned_quad q; + stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 + glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); + glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); + glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); + glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); + } + ++text; + } + glEnd(); +} +#endif +// +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program (this compiles): get a single bitmap, print as ASCII art +// +#if 0 +#include +#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation +#include "stb_truetype.h" + +char ttf_buffer[1<<25]; + +int main(int argc, char **argv) +{ + stbtt_fontinfo font; + unsigned char *bitmap; + int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); + + fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); + + stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); + bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); + + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) + putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); + putchar('\n'); + } + return 0; +} +#endif +// +// Output: +// +// .ii. +// @@@@@@. +// V@Mio@@o +// :i. V@V +// :oM@@M +// :@@@MM@M +// @@o o@M +// :@@. M@M +// @@@o@@@@ +// :M@@V:@@. +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program: print "Hello World!" banner, with bugs +// +#if 0 +char buffer[24<<20]; +unsigned char screen[20][79]; + +int main(int arg, char **argv) +{ + stbtt_fontinfo font; + int i,j,ascent,baseline,ch=0; + float scale, xpos=2; // leave a little padding in case the character extends left + char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness + + fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); + stbtt_InitFont(&font, buffer, 0); + + scale = stbtt_ScaleForPixelHeight(&font, 15); + stbtt_GetFontVMetrics(&font, &ascent,0,0); + baseline = (int) (ascent*scale); + + while (text[ch]) { + int advance,lsb,x0,y0,x1,y1; + float x_shift = xpos - (float) floor(xpos); + stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); + stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); + stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); + // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong + // because this API is really for baking character bitmaps into textures. if you want to render + // a sequence of characters, you really need to render each bitmap to a temp buffer, then + // "alpha blend" that into the working buffer + xpos += (advance * scale); + if (text[ch+1]) + xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); + ++ch; + } + + for (j=0; j < 20; ++j) { + for (i=0; i < 78; ++i) + putchar(" .:ioVM@"[screen[j][i]>>5]); + putchar('\n'); + } + + return 0; +} +#endif + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//// +//// INTEGRATION WITH YOUR CODEBASE +//// +//// The following sections allow you to supply alternate definitions +//// of C library functions used by stb_truetype, e.g. if you don't +//// link with the C runtime library. + +#ifdef STB_TRUETYPE_IMPLEMENTATION + // #define your own (u)stbtt_int8/16/32 before including to override this + #ifndef stbtt_uint8 + typedef unsigned char stbtt_uint8; + typedef signed char stbtt_int8; + typedef unsigned short stbtt_uint16; + typedef signed short stbtt_int16; + typedef unsigned int stbtt_uint32; + typedef signed int stbtt_int32; + #endif + + typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; + typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; + + // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + #ifndef STBTT_ifloor + #include + #define STBTT_ifloor(x) ((int) floor(x)) + #define STBTT_iceil(x) ((int) ceil(x)) + #endif + + #ifndef STBTT_sqrt + #include + #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_fmod + #include + #define STBTT_fmod(x,y) fmod(x,y) + #endif + + #ifndef STBTT_cos + #include + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) + #endif + + #ifndef STBTT_fabs + #include + #define STBTT_fabs(x) fabs(x) + #endif + + // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h + #ifndef STBTT_malloc + #include + #define STBTT_malloc(x,u) ((void)(u),malloc(x)) + #define STBTT_free(x,u) ((void)(u),free(x)) + #endif + + #ifndef STBTT_assert + #include + #define STBTT_assert(x) assert(x) + #endif + + #ifndef STBTT_strlen + #include + #define STBTT_strlen(x) strlen(x) + #endif + + #ifndef STBTT_memcpy + #include + #define STBTT_memcpy memcpy + #define STBTT_memset memset + #endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// INTERFACE +//// +//// + +#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ +#define __STB_INCLUDE_STB_TRUETYPE_H__ + +#ifdef STBTT_STATIC +#define STBTT_DEF static +#else +#define STBTT_DEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// private structure +typedef struct +{ + unsigned char *data; + int cursor; + int size; +} stbtt__buf; + +////////////////////////////////////////////////////////////////////////////// +// +// TEXTURE BAKING API +// +// If you use this API, you only have to call two functions ever. +// + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; +} stbtt_bakedchar; + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata); // you allocate this, it's num_chars long +// if return is positive, the first unused row of the bitmap +// if return is negative, returns the negative of the number of characters that fit +// if return is 0, no characters fit and no rows were used +// This uses a very crappy packing. + +typedef struct +{ + float x0,y0,s0,t0; // top-left + float x1,y1,s1,t1; // bottom-right +} stbtt_aligned_quad; + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier +// Call GetBakedQuad with char_index = 'character - first_char', and it +// creates the quad you need to draw and advances the current position. +// +// The coordinate system used assumes y increases downwards. +// +// Characters will extend both above and below the current position; +// see discussion of "BASELINE" above. +// +// It's inefficient; you might want to c&p it and optimize it. + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); +// Query the font vertical metrics without having to create a font first. + + +////////////////////////////////////////////////////////////////////////////// +// +// NEW TEXTURE BAKING API +// +// This provides options for packing multiple fonts into one atlas, not +// perfectly but better than nothing. + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; + float xoff2,yoff2; +} stbtt_packedchar; + +typedef struct stbtt_pack_context stbtt_pack_context; +typedef struct stbtt_fontinfo stbtt_fontinfo; +#ifndef STB_RECT_PACK_VERSION +typedef struct stbrp_rect stbrp_rect; +#endif + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); +// Initializes a packing context stored in the passed-in stbtt_pack_context. +// Future calls using this context will pack characters into the bitmap passed +// in here: a 1-channel bitmap that is width * height. stride_in_bytes is +// the distance from one row to the next (or 0 to mean they are packed tightly +// together). "padding" is the amount of padding to leave between each +// character (normally you want '1' for bitmaps you'll use as textures with +// bilinear filtering). +// +// Returns 0 on failure, 1 on success. + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); +// Cleans up the packing context and frees all memory. + +#define STBTT_POINT_SIZE(x) (-(x)) + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); +// Creates character bitmaps from the font_index'th font found in fontdata (use +// font_index=0 if you don't know what that is). It creates num_chars_in_range +// bitmaps for characters with unicode values starting at first_unicode_char_in_range +// and increasing. Data for how to render them is stored in chardata_for_range; +// pass these to stbtt_GetPackedQuad to get back renderable quads. +// +// font_size is the full height of the character from ascender to descender, +// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed +// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() +// and pass that result as 'font_size': +// ..., 20 , ... // font max minus min y is 20 pixels tall +// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall + +typedef struct +{ + float font_size; + int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint + int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints + int num_chars; + stbtt_packedchar *chardata_for_range; // output + unsigned char h_oversample, v_oversample; // don't set these, they're used internally +} stbtt_pack_range; + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +// Creates character bitmaps from multiple ranges of characters stored in +// ranges. This will usually create a better-packed bitmap than multiple +// calls to stbtt_PackFontRange. Note that you can call this multiple +// times within a single PackBegin/PackEnd. + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); +// Oversampling a font increases the quality by allowing higher-quality subpixel +// positioning, and is especially valuable at smaller text sizes. +// +// This function sets the amount of oversampling for all following calls to +// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given +// pack context. The default (no oversampling) is achieved by h_oversample=1 +// and v_oversample=1. The total number of pixels required is +// h_oversample*v_oversample larger than the default; for example, 2x2 +// oversampling requires 4x the storage of 1x1. For best results, render +// oversampled textures with bilinear filtering. Look at the readme in +// stb/tests/oversample for information about oversampled fonts +// +// To use with PackFontRangesGather etc., you must set it before calls +// call to PackFontRangesGatherRects. + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); +// If skip != 0, this tells stb_truetype to skip any codepoints for which +// there is no corresponding glyph. If skip=0, which is the default, then +// codepoints without a glyph recived the font's "missing character" glyph, +// typically an empty box by convention. + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int align_to_integer); + +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +// Calling these functions in sequence is roughly equivalent to calling +// stbtt_PackFontRanges(). If you more control over the packing of multiple +// fonts, or if you want to pack custom data into a font texture, take a look +// at the source to of stbtt_PackFontRanges() and create a custom version +// using these functions, e.g. call GatherRects multiple times, +// building up a single array of rects, then call PackRects once, +// then call RenderIntoRects repeatedly. This may result in a +// better packing than calling PackFontRanges multiple times +// (or it may not). + +// this is an opaque structure that you shouldn't mess with which holds +// all the context needed from PackBegin to PackEnd. +struct stbtt_pack_context { + void *user_allocator_context; + void *pack_info; + int width; + int height; + int stride_in_bytes; + int padding; + int skip_missing; + unsigned int h_oversample, v_oversample; + unsigned char *pixels; + void *nodes; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// FONT LOADING +// +// + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); +// This function will determine the number of fonts in a font file. TrueType +// collection (.ttc) files may contain multiple fonts, while TrueType font +// (.ttf) files only contain one font. The number of fonts can be used for +// indexing with the previous function where the index is between zero and one +// less than the total fonts. If an error occurs, -1 is returned. + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); +// Each .ttf/.ttc file may have more than one font. Each font has a sequential +// index number starting from 0. Call this function to get the font offset for +// a given index; it returns -1 if the index is out of range. A regular .ttf +// file will only define one font and it always be at offset 0, so it will +// return '0' for index 0, and -1 for all other indices. + +// The following structure is defined publicly so you can declare one on +// the stack or as a global or etc, but you should treat it as opaque. +struct stbtt_fontinfo +{ + void * userdata; + unsigned char * data; // pointer to .ttf file + int fontstart; // offset of start of font + + int numGlyphs; // number of glyphs, needed for range checking + + int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf + int index_map; // a cmap mapping for our chosen character encoding + int indexToLocFormat; // format needed to map from glyph index to glyph + + stbtt__buf cff; // cff font data + stbtt__buf charstrings; // the charstring index + stbtt__buf gsubrs; // global charstring subroutines index + stbtt__buf subrs; // private charstring subroutines index + stbtt__buf fontdicts; // array of font dicts + stbtt__buf fdselect; // map from glyph to fontdict +}; + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); +// Given an offset into the file that defines a font, this function builds +// the necessary cached info for the rest of the system. You must allocate +// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't +// need to do anything special to free it, because the contents are pure +// value data with no additional data structures. Returns 0 on failure. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER TO GLYPH-INDEX CONVERSIOn + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); +// If you're going to perform multiple operations on the same character +// and you want a speed-up, call this function with the character you're +// going to process, then use glyph-based functions instead of the +// codepoint-based functions. +// Returns 0 if the character codepoint is not defined in the font. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER PROPERTIES +// + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose "height" is 'pixels' tall. +// Height is measured as the distance from the highest ascender to the lowest +// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics +// and computing: +// scale = pixels / (ascent - descent) +// so if you prefer to measure height by the ascent only, use a similar calculation. + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose EM size is mapped to +// 'pixels' tall. This is probably what traditional APIs compute, but +// I'm not positive. + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); +// ascent is the coordinate above the baseline the font extends; descent +// is the coordinate below the baseline the font extends (i.e. it is typically negative) +// lineGap is the spacing between one row's descent and the next row's ascent... +// so you should advance the vertical position by "*ascent - *descent + *lineGap" +// these are expressed in unscaled coordinates, so you must multiply by +// the scale factor for a given size + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); +// the bounding box around all possible characters + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); +// leftSideBearing is the offset from the current horizontal position to the left edge of the character +// advanceWidth is the offset from the current horizontal position to the next horizontal position +// these are expressed in unscaled coordinates + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); +// an additional amount to add to the 'advance' value between ch1 and ch2 + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); +// Gets the bounding box of the visible part of the glyph, in unscaled coordinates + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); +// as above, but takes one or more glyph indices for greater efficiency + +typedef struct stbtt_kerningentry +{ + int glyph1; // use stbtt_FindGlyphIndex + int glyph2; + int advance; +} stbtt_kerningentry; + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); +// Retrieves a complete list of all of the kerning pairs provided by the font +// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. +// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) + +////////////////////////////////////////////////////////////////////////////// +// +// GLYPH SHAPES (you probably don't need these, but they have to go before +// the bitmaps for C declaration-order reasons) +// + +#ifndef STBTT_vmove // you can predefine these to use different values (but why?) + enum { + STBTT_vmove=1, + STBTT_vline, + STBTT_vcurve, + STBTT_vcubic + }; +#endif + +#ifndef stbtt_vertex // you can predefine this to use different values + // (we share this with other code at RAD) + #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file + typedef struct + { + stbtt_vertex_type x,y,cx,cy,cx1,cy1; + unsigned char type,padding; + } stbtt_vertex; +#endif + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); +// returns non-zero if nothing is drawn for this glyph + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); +// returns # of vertices and fills *vertices with the pointer to them +// these are expressed in "unscaled" coordinates +// +// The shape is a series of contours. Each one starts with +// a STBTT_moveto, then consists of a series of mixed +// STBTT_lineto and STBTT_curveto segments. A lineto +// draws a line from previous endpoint to its x,y; a curveto +// draws a quadratic bezier from previous endpoint to +// its x,y, using cx,cy as the bezier control point. + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); +// frees the data allocated above + +STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl); +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); +// fills svg with the character's SVG data. +// returns data size or 0 if SVG not found. + +////////////////////////////////////////////////////////////////////////////// +// +// BITMAP RENDERING +// + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); +// frees the bitmap allocated below + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// allocates a large-enough single-channel 8bpp bitmap and renders the +// specified character/glyph at the specified scale into it, with +// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). +// *width & *height are filled out with the width & height of the bitmap, +// which is stored left-to-right, top-to-bottom. +// +// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); +// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap +// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap +// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the +// width and height and positioning info for it first. + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); +// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); +// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering +// is performed (see stbtt_PackSetOversampling) + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +// get the bbox of the bitmap centered around the glyph origin; so the +// bitmap width is ix1-ix0, height is iy1-iy0, and location to place +// the bitmap top left is (leftSideBearing*scale,iy0). +// (Note that the bitmap uses y-increases-down, but the shape uses +// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); +// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel +// shift for the character + +// the following functions are equivalent to the above functions, but operate +// on glyph indices instead of Unicode codepoints (for efficiency) +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + + +// @TODO: don't expose this structure +typedef struct +{ + int w,h,stride; + unsigned char *pixels; +} stbtt__bitmap; + +// rasterize a shape with quadratic beziers into a bitmap +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into + float flatness_in_pixels, // allowable error of curve in pixels + stbtt_vertex *vertices, // array of vertices defining shape + int num_verts, // number of vertices in above array + float scale_x, float scale_y, // scale applied to input vertices + float shift_x, float shift_y, // translation applied to input vertices + int x_off, int y_off, // another translation applied to input + int invert, // if non-zero, vertically flip shape + void *userdata); // context for to STBTT_MALLOC + +////////////////////////////////////////////////////////////////////////////// +// +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + +////////////////////////////////////////////////////////////////////////////// +// +// Finding the right font... +// +// You should really just solve this offline, keep your own tables +// of what font is what, and don't try to get it out of the .ttf file. +// That's because getting it out of the .ttf file is really hard, because +// the names in the file can appear in many possible encodings, in many +// possible languages, and e.g. if you need a case-insensitive comparison, +// the details of that depend on the encoding & language in a complex way +// (actually underspecified in truetype, but also gigantic). +// +// But you can use the provided functions in two possible ways: +// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on +// unicode-encoded names to try to find the font you want; +// you can run this before calling stbtt_InitFont() +// +// stbtt_GetFontNameString() lets you get any of the various strings +// from the file yourself and do your own comparisons on them. +// You have to have called stbtt_InitFont() first. + + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); +// returns the offset (not index) of the font that matches, or -1 if none +// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". +// if you use any other flag, use a font name like "Arial"; this checks +// the 'macStyle' header field; i don't know if fonts set this consistently +#define STBTT_MACSTYLE_DONTCARE 0 +#define STBTT_MACSTYLE_BOLD 1 +#define STBTT_MACSTYLE_ITALIC 2 +#define STBTT_MACSTYLE_UNDERSCORE 4 +#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); +// returns 1/0 whether the first string interpreted as utf8 is identical to +// the second string interpreted as big-endian utf16... useful for strings from next func + +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); +// returns the string (which may be big-endian double byte, e.g. for unicode) +// and puts the length in bytes in *length. +// +// some of the values for the IDs are below; for more see the truetype spec: +// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html +// http://www.microsoft.com/typography/otspec/name.htm + +enum { // platformID + STBTT_PLATFORM_ID_UNICODE =0, + STBTT_PLATFORM_ID_MAC =1, + STBTT_PLATFORM_ID_ISO =2, + STBTT_PLATFORM_ID_MICROSOFT =3 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_UNICODE + STBTT_UNICODE_EID_UNICODE_1_0 =0, + STBTT_UNICODE_EID_UNICODE_1_1 =1, + STBTT_UNICODE_EID_ISO_10646 =2, + STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, + STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT + STBTT_MS_EID_SYMBOL =0, + STBTT_MS_EID_UNICODE_BMP =1, + STBTT_MS_EID_SHIFTJIS =2, + STBTT_MS_EID_UNICODE_FULL =10 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes + STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, + STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, + STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, + STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 +}; + +enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... + // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs + STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, + STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, + STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, + STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, + STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, + STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D +}; + +enum { // languageID for STBTT_PLATFORM_ID_MAC + STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, + STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, + STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, + STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , + STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , + STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, + STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 +}; + +#ifdef __cplusplus +} +#endif + +#endif // __STB_INCLUDE_STB_TRUETYPE_H__ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// IMPLEMENTATION +//// +//// + +#ifdef STB_TRUETYPE_IMPLEMENTATION + +#ifndef STBTT_MAX_OVERSAMPLE +#define STBTT_MAX_OVERSAMPLE 8 +#endif + +#if STBTT_MAX_OVERSAMPLE > 255 +#error "STBTT_MAX_OVERSAMPLE cannot be > 255" +#endif + +typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; + +#ifndef STBTT_RASTERIZER_VERSION +#define STBTT_RASTERIZER_VERSION 2 +#endif + +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + +////////////////////////////////////////////////////////////////////////// +// +// stbtt__buf helpers to parse data from file +// + +static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor++]; +} + +static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor]; +} + +static void stbtt__buf_seek(stbtt__buf *b, int o) +{ + STBTT_assert(!(o > b->size || o < 0)); + b->cursor = (o > b->size || o < 0) ? b->size : o; +} + +static void stbtt__buf_skip(stbtt__buf *b, int o) +{ + stbtt__buf_seek(b, b->cursor + o); +} + +static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) +{ + stbtt_uint32 v = 0; + int i; + STBTT_assert(n >= 1 && n <= 4); + for (i = 0; i < n; i++) + v = (v << 8) | stbtt__buf_get8(b); + return v; +} + +static stbtt__buf stbtt__new_buf(const void *p, size_t size) +{ + stbtt__buf r; + STBTT_assert(size < 0x40000000); + r.data = (stbtt_uint8*) p; + r.size = (int) size; + r.cursor = 0; + return r; +} + +#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) +#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) + +static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) +{ + stbtt__buf r = stbtt__new_buf(NULL, 0); + if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; + r.data = b->data + o; + r.size = s; + return r; +} + +static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) +{ + int count, start, offsize; + start = b->cursor; + count = stbtt__buf_get16(b); + if (count) { + offsize = stbtt__buf_get8(b); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(b, offsize * count); + stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); + } + return stbtt__buf_range(b, start, b->cursor - start); +} + +static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) +{ + int b0 = stbtt__buf_get8(b); + if (b0 >= 32 && b0 <= 246) return b0 - 139; + else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; + else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; + else if (b0 == 28) return stbtt__buf_get16(b); + else if (b0 == 29) return stbtt__buf_get32(b); + STBTT_assert(0); + return 0; +} + +static void stbtt__cff_skip_operand(stbtt__buf *b) { + int v, b0 = stbtt__buf_peek8(b); + STBTT_assert(b0 >= 28); + if (b0 == 30) { + stbtt__buf_skip(b, 1); + while (b->cursor < b->size) { + v = stbtt__buf_get8(b); + if ((v & 0xF) == 0xF || (v >> 4) == 0xF) + break; + } + } else { + stbtt__cff_int(b); + } +} + +static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) +{ + stbtt__buf_seek(b, 0); + while (b->cursor < b->size) { + int start = b->cursor, end, op; + while (stbtt__buf_peek8(b) >= 28) + stbtt__cff_skip_operand(b); + end = b->cursor; + op = stbtt__buf_get8(b); + if (op == 12) op = stbtt__buf_get8(b) | 0x100; + if (op == key) return stbtt__buf_range(b, start, end-start); + } + return stbtt__buf_range(b, 0, 0); +} + +static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) +{ + int i; + stbtt__buf operands = stbtt__dict_get(b, key); + for (i = 0; i < outcount && operands.cursor < operands.size; i++) + out[i] = stbtt__cff_int(&operands); +} + +static int stbtt__cff_index_count(stbtt__buf *b) +{ + stbtt__buf_seek(b, 0); + return stbtt__buf_get16(b); +} + +static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) +{ + int count, offsize, start, end; + stbtt__buf_seek(&b, 0); + count = stbtt__buf_get16(&b); + offsize = stbtt__buf_get8(&b); + STBTT_assert(i >= 0 && i < count); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(&b, i*offsize); + start = stbtt__buf_get(&b, offsize); + end = stbtt__buf_get(&b, offsize); + return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); +} + +////////////////////////////////////////////////////////////////////////// +// +// accessors to parse data from file +// + +// on platforms that don't allow misaligned reads, if we want to allow +// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE + +#define ttBYTE(p) (* (stbtt_uint8 *) (p)) +#define ttCHAR(p) (* (stbtt_int8 *) (p)) +#define ttFixed(p) ttLONG(p) + +static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } +static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } + +#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) +#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) + +static int stbtt__isfont(stbtt_uint8 *font) +{ + // check the version number + if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 + if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! + if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF + if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 + if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts + return 0; +} + +// @OPTIMIZE: binary search +static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) +{ + stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); + stbtt_uint32 tabledir = fontstart + 12; + stbtt_int32 i; + for (i=0; i < num_tables; ++i) { + stbtt_uint32 loc = tabledir + 16*i; + if (stbtt_tag(data+loc+0, tag)) + return ttULONG(data+loc+8); + } + return 0; +} + +static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) +{ + // if it's just a font, there's only one valid index + if (stbtt__isfont(font_collection)) + return index == 0 ? 0 : -1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + stbtt_int32 n = ttLONG(font_collection+8); + if (index >= n) + return -1; + return ttULONG(font_collection+12+index*4); + } + } + return -1; +} + +static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) +{ + // if it's just a font, there's only one valid font + if (stbtt__isfont(font_collection)) + return 1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + return ttLONG(font_collection+8); + } + } + return 0; +} + +static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) +{ + stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; + stbtt__buf pdict; + stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); + if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); + pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); + stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); + if (!subrsoff) return stbtt__new_buf(NULL, 0); + stbtt__buf_seek(&cff, private_loc[1]+subrsoff); + return stbtt__cff_get_index(&cff); +} + +// since most people won't use this, find this table the first time it's needed +static int stbtt__get_svg(stbtt_fontinfo *info) +{ + stbtt_uint32 t; + if (info->svg < 0) { + t = stbtt__find_table(info->data, info->fontstart, "SVG "); + if (t) { + stbtt_uint32 offset = ttULONG(info->data + t + 2); + info->svg = t + offset; + } else { + info->svg = 0; + } + } + return info->svg; +} + +static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) +{ + stbtt_uint32 cmap, t; + stbtt_int32 i,numTables; + + info->data = data; + info->fontstart = fontstart; + info->cff = stbtt__new_buf(NULL, 0); + + cmap = stbtt__find_table(data, fontstart, "cmap"); // required + info->loca = stbtt__find_table(data, fontstart, "loca"); // required + info->head = stbtt__find_table(data, fontstart, "head"); // required + info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required + info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required + info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required + info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required + + if (!cmap || !info->head || !info->hhea || !info->hmtx) + return 0; + if (info->glyf) { + // required for truetype + if (!info->loca) return 0; + } else { + // initialization for CFF / Type2 fonts (OTF) + stbtt__buf b, topdict, topdictidx; + stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; + stbtt_uint32 cff; + + cff = stbtt__find_table(data, fontstart, "CFF "); + if (!cff) return 0; + + info->fontdicts = stbtt__new_buf(NULL, 0); + info->fdselect = stbtt__new_buf(NULL, 0); + + // @TODO this should use size from table (not 512MB) + info->cff = stbtt__new_buf(data+cff, 512*1024*1024); + b = info->cff; + + // read the header + stbtt__buf_skip(&b, 2); + stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize + + // @TODO the name INDEX could list multiple fonts, + // but we just use the first one. + stbtt__cff_get_index(&b); // name INDEX + topdictidx = stbtt__cff_get_index(&b); + topdict = stbtt__cff_index_get(topdictidx, 0); + stbtt__cff_get_index(&b); // string INDEX + info->gsubrs = stbtt__cff_get_index(&b); + + stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); + stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); + stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); + stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); + info->subrs = stbtt__get_subrs(b, topdict); + + // we only support Type 2 charstrings + if (cstype != 2) return 0; + if (charstrings == 0) return 0; + + if (fdarrayoff) { + // looks like a CID font + if (!fdselectoff) return 0; + stbtt__buf_seek(&b, fdarrayoff); + info->fontdicts = stbtt__cff_get_index(&b); + info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); + } + + stbtt__buf_seek(&b, charstrings); + info->charstrings = stbtt__cff_get_index(&b); + } + + t = stbtt__find_table(data, fontstart, "maxp"); + if (t) + info->numGlyphs = ttUSHORT(data+t+4); + else + info->numGlyphs = 0xffff; + + info->svg = -1; + + // find a cmap encoding table we understand *now* to avoid searching + // later. (todo: could make this installable) + // the same regardless of glyph. + numTables = ttUSHORT(data + cmap + 2); + info->index_map = 0; + for (i=0; i < numTables; ++i) { + stbtt_uint32 encoding_record = cmap + 4 + 8 * i; + // find an encoding we understand: + switch(ttUSHORT(data+encoding_record)) { + case STBTT_PLATFORM_ID_MICROSOFT: + switch (ttUSHORT(data+encoding_record+2)) { + case STBTT_MS_EID_UNICODE_BMP: + case STBTT_MS_EID_UNICODE_FULL: + // MS/Unicode + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + break; + case STBTT_PLATFORM_ID_UNICODE: + // Mac/iOS has these + // all the encodingIDs are unicode, so we don't bother to check it + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + } + if (info->index_map == 0) + return 0; + + info->indexToLocFormat = ttUSHORT(data+info->head + 50); + return 1; +} + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) +{ + stbtt_uint8 *data = info->data; + stbtt_uint32 index_map = info->index_map; + + stbtt_uint16 format = ttUSHORT(data + index_map + 0); + if (format == 0) { // apple byte encoding + stbtt_int32 bytes = ttUSHORT(data + index_map + 2); + if (unicode_codepoint < bytes-6) + return ttBYTE(data + index_map + 6 + unicode_codepoint); + return 0; + } else if (format == 6) { + stbtt_uint32 first = ttUSHORT(data + index_map + 6); + stbtt_uint32 count = ttUSHORT(data + index_map + 8); + if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) + return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); + return 0; + } else if (format == 2) { + STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean + return 0; + } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges + stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; + stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; + stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); + stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; + + // do a binary search of the segments + stbtt_uint32 endCount = index_map + 14; + stbtt_uint32 search = endCount; + + if (unicode_codepoint > 0xffff) + return 0; + + // they lie from endCount .. endCount + segCount + // but searchRange is the nearest power of two, so... + if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) + search += rangeShift*2; + + // now decrement to bias correctly to find smallest + search -= 2; + while (entrySelector) { + stbtt_uint16 end; + searchRange >>= 1; + end = ttUSHORT(data + search + searchRange*2); + if (unicode_codepoint > end) + search += searchRange*2; + --entrySelector; + } + search += 2; + + { + stbtt_uint16 offset, start, last; + stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); + + start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); + last = ttUSHORT(data + endCount + 2*item); + if (unicode_codepoint < start || unicode_codepoint > last) + return 0; + + offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); + if (offset == 0) + return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); + + return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); + } + } else if (format == 12 || format == 13) { + stbtt_uint32 ngroups = ttULONG(data+index_map+12); + stbtt_int32 low,high; + low = 0; high = (stbtt_int32)ngroups; + // Binary search the right group. + while (low < high) { + stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high + stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); + stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); + if ((stbtt_uint32) unicode_codepoint < start_char) + high = mid; + else if ((stbtt_uint32) unicode_codepoint > end_char) + low = mid+1; + else { + stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); + if (format == 12) + return start_glyph + unicode_codepoint-start_char; + else // format == 13 + return start_glyph; + } + } + return 0; // not found + } + // @TODO + STBTT_assert(0); + return 0; +} + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) +{ + return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); +} + +static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) +{ + v->type = type; + v->x = (stbtt_int16) x; + v->y = (stbtt_int16) y; + v->cx = (stbtt_int16) cx; + v->cy = (stbtt_int16) cy; +} + +static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) +{ + int g1,g2; + + STBTT_assert(!info->cff.size); + + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range + if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format + + if (info->indexToLocFormat == 0) { + g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; + g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; + } else { + g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); + g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); + } + + return g1==g2 ? -1 : g1; // if length is 0, return -1 +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + if (info->cff.size) { + stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); + } else { + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; + + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + } + return 1; +} + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) +{ + return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); +} + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt_int16 numberOfContours; + int g; + if (info->cff.size) + return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; + g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 1; + numberOfContours = ttSHORT(info->data + g); + return numberOfContours == 0; +} + +static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, + stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) +{ + if (start_off) { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); + } + return num_vertices; +} + +static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + stbtt_int16 numberOfContours; + stbtt_uint8 *endPtsOfContours; + stbtt_uint8 *data = info->data; + stbtt_vertex *vertices=0; + int num_vertices=0; + int g = stbtt__GetGlyfOffset(info, glyph_index); + + *pvertices = NULL; + + if (g < 0) return 0; + + numberOfContours = ttSHORT(data + g); + + if (numberOfContours > 0) { + stbtt_uint8 flags=0,flagcount; + stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; + stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; + stbtt_uint8 *points; + endPtsOfContours = (data + g + 10); + ins = ttUSHORT(data + g + 10 + numberOfContours * 2); + points = data + g + 10 + numberOfContours * 2 + 2 + ins; + + n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); + + m = n + 2*numberOfContours; // a loose bound on how many vertices we might need + vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); + if (vertices == 0) + return 0; + + next_move = 0; + flagcount=0; + + // in first pass, we load uninterpreted data into the allocated array + // above, shifted to the end of the array so we won't overwrite it when + // we create our final data starting from the front + + off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated + + // first load flags + + for (i=0; i < n; ++i) { + if (flagcount == 0) { + flags = *points++; + if (flags & 8) + flagcount = *points++; + } else + --flagcount; + vertices[off+i].type = flags; + } + + // now load x coordinates + x=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 2) { + stbtt_int16 dx = *points++; + x += (flags & 16) ? dx : -dx; // ??? + } else { + if (!(flags & 16)) { + x = x + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].x = (stbtt_int16) x; + } + + // now load y coordinates + y=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 4) { + stbtt_int16 dy = *points++; + y += (flags & 32) ? dy : -dy; // ??? + } else { + if (!(flags & 32)) { + y = y + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].y = (stbtt_int16) y; + } + + // now convert them to our format + num_vertices=0; + sx = sy = cx = cy = scx = scy = 0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + x = (stbtt_int16) vertices[off+i].x; + y = (stbtt_int16) vertices[off+i].y; + + if (next_move == i) { + if (i != 0) + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + + // now start the new one + start_off = !(flags & 1); + if (start_off) { + // if we start off with an off-curve point, then when we need to find a point on the curve + // where we can start, and we need to save some state for when we wraparound. + scx = x; + scy = y; + if (!(vertices[off+i+1].type & 1)) { + // next point is also a curve point, so interpolate an on-point curve + sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; + sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; + } else { + // otherwise just use the next point as our start point + sx = (stbtt_int32) vertices[off+i+1].x; + sy = (stbtt_int32) vertices[off+i+1].y; + ++i; // we're using point i+1 as the starting point, so skip it + } + } else { + sx = x; + sy = y; + } + stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); + was_off = 0; + next_move = 1 + ttUSHORT(endPtsOfContours+j*2); + ++j; + } else { + if (!(flags & 1)) { // if it's a curve + if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); + cx = x; + cy = y; + was_off = 1; + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); + was_off = 0; + } + } + } + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + } else if (numberOfContours < 0) { + // Compound shapes. + int more = 1; + stbtt_uint8 *comp = data + g + 10; + num_vertices = 0; + vertices = 0; + while (more) { + stbtt_uint16 flags, gidx; + int comp_num_verts = 0, i; + stbtt_vertex *comp_verts = 0, *tmp = 0; + float mtx[6] = {1,0,0,1,0,0}, m, n; + + flags = ttSHORT(comp); comp+=2; + gidx = ttSHORT(comp); comp+=2; + + if (flags & 2) { // XY values + if (flags & 1) { // shorts + mtx[4] = ttSHORT(comp); comp+=2; + mtx[5] = ttSHORT(comp); comp+=2; + } else { + mtx[4] = ttCHAR(comp); comp+=1; + mtx[5] = ttCHAR(comp); comp+=1; + } + } + else { + // @TODO handle matching point + STBTT_assert(0); + } + if (flags & (1<<3)) { // WE_HAVE_A_SCALE + mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } + + // Find transformation scales. + m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); + n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); + + // Get indexed glyph. + comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); + if (comp_num_verts > 0) { + // Transform vertices. + for (i = 0; i < comp_num_verts; ++i) { + stbtt_vertex* v = &comp_verts[i]; + stbtt_vertex_type x,y; + x=v->x; y=v->y; + v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + x=v->cx; y=v->cy; + v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + } + // Append vertices. + tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); + if (!tmp) { + if (vertices) STBTT_free(vertices, info->userdata); + if (comp_verts) STBTT_free(comp_verts, info->userdata); + return 0; + } + if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); + STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); + if (vertices) STBTT_free(vertices, info->userdata); + vertices = tmp; + STBTT_free(comp_verts, info->userdata); + num_vertices += comp_num_verts; + } + // More components ? + more = flags & (1<<5); + } + } else { + // numberOfCounters == 0, do nothing + } + + *pvertices = vertices; + return num_vertices; +} + +typedef struct +{ + int bounds; + int started; + float first_x, first_y; + float x, y; + stbtt_int32 min_x, max_x, min_y, max_y; + + stbtt_vertex *pvertices; + int num_vertices; +} stbtt__csctx; + +#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} + +static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) +{ + if (x > c->max_x || !c->started) c->max_x = x; + if (y > c->max_y || !c->started) c->max_y = y; + if (x < c->min_x || !c->started) c->min_x = x; + if (y < c->min_y || !c->started) c->min_y = y; + c->started = 1; +} + +static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) +{ + if (c->bounds) { + stbtt__track_vertex(c, x, y); + if (type == STBTT_vcubic) { + stbtt__track_vertex(c, cx, cy); + stbtt__track_vertex(c, cx1, cy1); + } + } else { + stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); + c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; + c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; + } + c->num_vertices++; +} + +static void stbtt__csctx_close_shape(stbtt__csctx *ctx) +{ + if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) +{ + stbtt__csctx_close_shape(ctx); + ctx->first_x = ctx->x = ctx->x + dx; + ctx->first_y = ctx->y = ctx->y + dy; + stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) +{ + ctx->x += dx; + ctx->y += dy; + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) +{ + float cx1 = ctx->x + dx1; + float cy1 = ctx->y + dy1; + float cx2 = cx1 + dx2; + float cy2 = cy1 + dy2; + ctx->x = cx2 + dx3; + ctx->y = cy2 + dy3; + stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); +} + +static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) +{ + int count = stbtt__cff_index_count(&idx); + int bias = 107; + if (count >= 33900) + bias = 32768; + else if (count >= 1240) + bias = 1131; + n += bias; + if (n < 0 || n >= count) + return stbtt__new_buf(NULL, 0); + return stbtt__cff_index_get(idx, n); +} + +static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt__buf fdselect = info->fdselect; + int nranges, start, end, v, fmt, fdselector = -1, i; + + stbtt__buf_seek(&fdselect, 0); + fmt = stbtt__buf_get8(&fdselect); + if (fmt == 0) { + // untested + stbtt__buf_skip(&fdselect, glyph_index); + fdselector = stbtt__buf_get8(&fdselect); + } else if (fmt == 3) { + nranges = stbtt__buf_get16(&fdselect); + start = stbtt__buf_get16(&fdselect); + for (i = 0; i < nranges; i++) { + v = stbtt__buf_get8(&fdselect); + end = stbtt__buf_get16(&fdselect); + if (glyph_index >= start && glyph_index < end) { + fdselector = v; + break; + } + start = end; + } + } + if (fdselector == -1) stbtt__new_buf(NULL, 0); + return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); +} + +static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) +{ + int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; + int has_subrs = 0, clear_stack; + float s[48]; + stbtt__buf subr_stack[10], subrs = info->subrs, b; + float f; + +#define STBTT__CSERR(s) (0) + + // this currently ignores the initial width value, which isn't needed if we have hmtx + b = stbtt__cff_index_get(info->charstrings, glyph_index); + while (b.cursor < b.size) { + i = 0; + clear_stack = 1; + b0 = stbtt__buf_get8(&b); + switch (b0) { + // @TODO implement hinting + case 0x13: // hintmask + case 0x14: // cntrmask + if (in_header) + maskbits += (sp / 2); // implicit "vstem" + in_header = 0; + stbtt__buf_skip(&b, (maskbits + 7) / 8); + break; + + case 0x01: // hstem + case 0x03: // vstem + case 0x12: // hstemhm + case 0x17: // vstemhm + maskbits += (sp / 2); + break; + + case 0x15: // rmoveto + in_header = 0; + if (sp < 2) return STBTT__CSERR("rmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); + break; + case 0x04: // vmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("vmoveto stack"); + stbtt__csctx_rmove_to(c, 0, s[sp-1]); + break; + case 0x16: // hmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("hmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-1], 0); + break; + + case 0x05: // rlineto + if (sp < 2) return STBTT__CSERR("rlineto stack"); + for (; i + 1 < sp; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical + // starting from a different place. + + case 0x07: // vlineto + if (sp < 1) return STBTT__CSERR("vlineto stack"); + goto vlineto; + case 0x06: // hlineto + if (sp < 1) return STBTT__CSERR("hlineto stack"); + for (;;) { + if (i >= sp) break; + stbtt__csctx_rline_to(c, s[i], 0); + i++; + vlineto: + if (i >= sp) break; + stbtt__csctx_rline_to(c, 0, s[i]); + i++; + } + break; + + case 0x1F: // hvcurveto + if (sp < 4) return STBTT__CSERR("hvcurveto stack"); + goto hvcurveto; + case 0x1E: // vhcurveto + if (sp < 4) return STBTT__CSERR("vhcurveto stack"); + for (;;) { + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); + i += 4; + hvcurveto: + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); + i += 4; + } + break; + + case 0x08: // rrcurveto + if (sp < 6) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x18: // rcurveline + if (sp < 8) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp - 2; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + case 0x19: // rlinecurve + if (sp < 8) return STBTT__CSERR("rlinecurve stack"); + for (; i + 1 < sp - 6; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x1A: // vvcurveto + case 0x1B: // hhcurveto + if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); + f = 0.0; + if (sp & 1) { f = s[i]; i++; } + for (; i + 3 < sp; i += 4) { + if (b0 == 0x1B) + stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); + else + stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); + f = 0.0; + } + break; + + case 0x0A: // callsubr + if (!has_subrs) { + if (info->fdselect.size) + subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); + has_subrs = 1; + } + // FALLTHROUGH + case 0x1D: // callgsubr + if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); + v = (int) s[--sp]; + if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); + subr_stack[subr_stack_height++] = b; + b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); + if (b.size == 0) return STBTT__CSERR("subr not found"); + b.cursor = 0; + clear_stack = 0; + break; + + case 0x0B: // return + if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); + b = subr_stack[--subr_stack_height]; + clear_stack = 0; + break; + + case 0x0E: // endchar + stbtt__csctx_close_shape(c); + return 1; + + case 0x0C: { // two-byte escape + float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; + float dx, dy; + int b1 = stbtt__buf_get8(&b); + switch (b1) { + // @TODO These "flex" implementations ignore the flex-depth and resolution, + // and always draw beziers. + case 0x22: // hflex + if (sp < 7) return STBTT__CSERR("hflex stack"); + dx1 = s[0]; + dx2 = s[1]; + dy2 = s[2]; + dx3 = s[3]; + dx4 = s[4]; + dx5 = s[5]; + dx6 = s[6]; + stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + break; + + case 0x23: // flex + if (sp < 13) return STBTT__CSERR("flex stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = s[10]; + dy6 = s[11]; + //fd is s[12] + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + case 0x24: // hflex1 + if (sp < 9) return STBTT__CSERR("hflex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dx4 = s[5]; + dx5 = s[6]; + dy5 = s[7]; + dx6 = s[8]; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); + break; + + case 0x25: // flex1 + if (sp < 11) return STBTT__CSERR("flex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = dy6 = s[10]; + dx = dx1+dx2+dx3+dx4+dx5; + dy = dy1+dy2+dy3+dy4+dy5; + if (STBTT_fabs(dx) > STBTT_fabs(dy)) + dy6 = -dy; + else + dx6 = -dx; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + default: + return STBTT__CSERR("unimplemented"); + } + } break; + + default: + if (b0 != 255 && b0 != 28 && b0 < 32) + return STBTT__CSERR("reserved operator"); + + // push immediate + if (b0 == 255) { + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; + } else { + stbtt__buf_skip(&b, -1); + f = (float)(stbtt_int16)stbtt__cff_int(&b); + } + if (sp >= 48) return STBTT__CSERR("push stack overflow"); + s[sp++] = f; + clear_stack = 0; + break; + } + if (clear_stack) sp = 0; + } + return STBTT__CSERR("no endchar"); + +#undef STBTT__CSERR +} + +static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + // runs the charstring twice, once to count and once to output (to avoid realloc) + stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); + stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); + if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { + *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); + output_ctx.pvertices = *pvertices; + if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { + STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); + return output_ctx.num_vertices; + } + } + *pvertices = NULL; + return 0; +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + stbtt__csctx c = STBTT__CSCTX_INIT(1); + int r = stbtt__run_charstring(info, glyph_index, &c); + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; + return r ? c.num_vertices : 0; +} + +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + if (!info->cff.size) + return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); + else + return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); +} + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) +{ + stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); + if (glyph_index < numOfLongHorMetrics) { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); + } else { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); + } +} + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) +{ + stbtt_uint8 *data = info->data + info->kern; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + return ttUSHORT(data+10); +} + +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) +{ + stbtt_uint8 *data = info->data + info->kern; + int k, length; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + length = ttUSHORT(data+10); + if (table_length < length) + length = table_length; + + for (k = 0; k < length; k++) + { + table[k].glyph1 = ttUSHORT(data+18+(k*6)); + table[k].glyph2 = ttUSHORT(data+20+(k*6)); + table[k].advance = ttSHORT(data+22+(k*6)); + } + + return length; +} + +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint8 *data = info->data + info->kern; + stbtt_uint32 needle, straw; + int l, r, m; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + l = 0; + r = ttUSHORT(data+10) - 1; + needle = glyph1 << 16 | glyph2; + while (l <= r) { + m = (l + r) >> 1; + straw = ttULONG(data+18+(m*6)); // note: unaligned read + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else + return ttSHORT(data+22+(m*6)); + } + return 0; +} + +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch (coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + break; + } + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + break; + } + + default: return -1; // unsupported + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch (classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + break; + } + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + break; + } + + default: + return -1; // Unsupported definition type, return an error. + } + + // "All glyphs not assigned to a class fall into class 0". (OpenType spec) + return 0; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i, sti; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i= pairSetCount) return 0; + + needle=glyph2; + r=pairValueCount-1; + l=0; + + // Binary search. + while (l <= r) { + stbtt_uint16 secondGlyph; + stbtt_uint8 *pairValue; + m = (l + r) >> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } else + return 0; + break; + } + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + stbtt_uint8 *class1Records, *class2Records; + stbtt_int16 xAdvance; + + if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed + if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed + + class1Records = table + 16; + class2Records = class1Records + 2 * (glyph1class * class2Count); + xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } else + return 0; + break; + } + + default: + return 0; // Unsupported position format + } + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + else if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) +{ + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs + return 0; + return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); +} + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) +{ + stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); +} + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) +{ + if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); + if (descent) *descent = ttSHORT(info->data+info->hhea + 6); + if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); +} + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) +{ + *x0 = ttSHORT(info->data + info->head + 36); + *y0 = ttSHORT(info->data + info->head + 38); + *x1 = ttSHORT(info->data + info->head + 40); + *y1 = ttSHORT(info->data + info->head + 42); +} + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) +{ + int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); + return (float) height / fheight; +} + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) +{ + int unitsPerEm = ttUSHORT(info->data + info->head + 18); + return pixels / unitsPerEm; +} + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) +{ + STBTT_free(v, info->userdata); +} + +STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) +{ + int i; + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); + + int numEntries = ttUSHORT(svg_doc_list); + stbtt_uint8 *svg_docs = svg_doc_list + 2; + + for(i=0; i= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) + return svg_doc; + } + return 0; +} + +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) +{ + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc; + + if (info->svg == 0) + return 0; + + svg_doc = stbtt_FindSVGDoc(info, gl); + if (svg_doc != NULL) { + *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); + return ttULONG(svg_doc + 8); + } else { + return 0; + } +} + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) +{ + return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); +} + +////////////////////////////////////////////////////////////////////////////// +// +// antialiasing software rasterizer +// + +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning + if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { + // e.g. space character + if (ix0) *ix0 = 0; + if (iy0) *iy0 = 0; + if (ix1) *ix1 = 0; + if (iy1) *iy1 = 0; + } else { + // move to integral bboxes (treating pixels as little squares, what pixels get touched)? + if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); + if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); + if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); + if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); + } +} + +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); +} + +////////////////////////////////////////////////////////////////////////////// +// +// Rasterizer + +typedef struct stbtt__hheap_chunk +{ + struct stbtt__hheap_chunk *next; +} stbtt__hheap_chunk; + +typedef struct stbtt__hheap +{ + struct stbtt__hheap_chunk *head; + void *first_free; + int num_remaining_in_head_chunk; +} stbtt__hheap; + +static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) +{ + if (hh->first_free) { + void *p = hh->first_free; + hh->first_free = * (void **) p; + return p; + } else { + if (hh->num_remaining_in_head_chunk == 0) { + int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); + stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); + if (c == NULL) + return NULL; + c->next = hh->head; + hh->head = c; + hh->num_remaining_in_head_chunk = count; + } + --hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; + } +} + +static void stbtt__hheap_free(stbtt__hheap *hh, void *p) +{ + *(void **) p = hh->first_free; + hh->first_free = p; +} + +static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) +{ + stbtt__hheap_chunk *c = hh->head; + while (c) { + stbtt__hheap_chunk *n = c->next; + STBTT_free(c, userdata); + c = n; + } +} + +typedef struct stbtt__edge { + float x0,y0, x1,y1; + int invert; +} stbtt__edge; + + +typedef struct stbtt__active_edge +{ + struct stbtt__active_edge *next; + #if STBTT_RASTERIZER_VERSION==1 + int x,dx; + float ey; + int direction; + #elif STBTT_RASTERIZER_VERSION==2 + float fx,fdx,fdy; + float direction; + float sy; + float ey; + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif +} stbtt__active_edge; + +#if STBTT_RASTERIZER_VERSION == 1 +#define STBTT_FIXSHIFT 10 +#define STBTT_FIX (1 << STBTT_FIXSHIFT) +#define STBTT_FIXMASK (STBTT_FIX-1) + +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + if (!z) return z; + + // round dx down to avoid overshooting + if (dxdy < 0) + z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); + else + z->dx = STBTT_ifloor(STBTT_FIX * dxdy); + + z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount + z->x -= off_x * STBTT_FIX; + + z->ey = e->y1; + z->next = 0; + z->direction = e->invert ? 1 : -1; + return z; +} +#elif STBTT_RASTERIZER_VERSION == 2 +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + //STBTT_assert(e->y0 <= start_point); + if (!z) return z; + z->fdx = dxdy; + z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; + z->fx = e->x0 + dxdy * (start_point - e->y0); + z->fx -= off_x; + z->direction = e->invert ? 1.0f : -1.0f; + z->sy = e->y0; + z->ey = e->y1; + z->next = 0; + return z; +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#if STBTT_RASTERIZER_VERSION == 1 +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) +{ + // non-zero winding fill + int x0=0, w=0; + + while (e) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w += e->direction; + } else { + int x1 = e->x; w += e->direction; + // if we went to zero, we need to draw + if (w == 0) { + int i = x0 >> STBTT_FIXSHIFT; + int j = x1 >> STBTT_FIXSHIFT; + + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = scanline[i] + (stbtt_uint8) max_weight; + } + } + } + } + + e = e->next; + } +} + +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0; + int max_weight = (255 / vsubsample); // weight per vertical scanline + int s; // vertical subsample index + unsigned char scanline_data[512], *scanline; + + if (result->w > 512) + scanline = (unsigned char *) STBTT_malloc(result->w, userdata); + else + scanline = scanline_data; + + y = off_y * vsubsample; + e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; + + while (j < result->h) { + STBTT_memset(scanline, 0, result->w); + for (s=0; s < vsubsample; ++s) { + // find center of pixel for this scanline + float scan_y = y + 0.5f; + stbtt__active_edge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for(;;) { + int changed=0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + stbtt__active_edge *t = *step; + stbtt__active_edge *q = t->next; + + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e->y0 <= scan_y) { + if (e->y1 > scan_y) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); + if (z != NULL) { + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + } + ++e; + } + + // now process all active edges in XOR fashion + if (active) + stbtt__fill_active_edges(scanline, result->w, active, max_weight); + + ++y; + } + STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} + +#elif STBTT_RASTERIZER_VERSION == 2 + +// the edge passed in here does not cross the vertical line at x or the vertical line at x+1 +// (i.e. it has already been clipped to those) +static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) +{ + if (y0 == y1) return; + STBTT_assert(y0 < y1); + STBTT_assert(e->sy <= e->ey); + if (y0 > e->ey) return; + if (y1 < e->sy) return; + if (y0 < e->sy) { + x0 += (x1-x0) * (e->sy - y0) / (y1-y0); + y0 = e->sy; + } + if (y1 > e->ey) { + x1 += (x1-x0) * (e->ey - y1) / (y1-y0); + y1 = e->ey; + } + + if (x0 == x) + STBTT_assert(x1 <= x+1); + else if (x0 == x+1) + STBTT_assert(x1 >= x); + else if (x0 <= x) + STBTT_assert(x1 <= x); + else if (x0 >= x+1) + STBTT_assert(x1 >= x+1); + else + STBTT_assert(x1 >= x && x1 <= x+1); + + if (x0 <= x && x1 <= x) + scanline[x] += e->direction * (y1-y0); + else if (x0 >= x+1 && x1 >= x+1) + ; + else { + STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); + scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position + } +} + +static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width) +{ + STBTT_assert(top_width >= 0); + STBTT_assert(bottom_width >= 0); + return (top_width + bottom_width) / 2.0f * height; +} + +static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1) +{ + return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0); +} + +static float stbtt__sized_triangle_area(float height, float width) +{ + return height * width / 2; +} + +static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) +{ + float y_bottom = y_top+1; + + while (e) { + // brute force every pixel + + // compute intersection points with top & bottom + STBTT_assert(e->ey >= y_top); + + if (e->fdx == 0) { + float x0 = e->fx; + if (x0 < len) { + if (x0 >= 0) { + stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); + stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); + } else { + stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); + } + } + } else { + float x0 = e->fx; + float dx = e->fdx; + float xb = x0 + dx; + float x_top, x_bottom; + float sy0,sy1; + float dy = e->fdy; + STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); + + // compute endpoints of line segment clipped to this scanline (if the + // line segment starts on this scanline. x0 is the intersection of the + // line with y_top, but that may be off the line segment. + if (e->sy > y_top) { + x_top = x0 + dx * (e->sy - y_top); + sy0 = e->sy; + } else { + x_top = x0; + sy0 = y_top; + } + if (e->ey < y_bottom) { + x_bottom = x0 + dx * (e->ey - y_top); + sy1 = e->ey; + } else { + x_bottom = xb; + sy1 = y_bottom; + } + + if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { + // from here on, we don't have to range check x values + + if ((int) x_top == (int) x_bottom) { + float height; + // simple case, only spans one pixel + int x = (int) x_top; + height = (sy1 - sy0) * e->direction; + STBTT_assert(x >= 0 && x < len); + scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f); + scanline_fill[x] += height; // everything right of this pixel is filled + } else { + int x,x1,x2; + float y_crossing, y_final, step, sign, area; + // covers 2+ pixels + if (x_top > x_bottom) { + // flip scanline vertically; signed area is the same + float t; + sy0 = y_bottom - (sy0 - y_top); + sy1 = y_bottom - (sy1 - y_top); + t = sy0, sy0 = sy1, sy1 = t; + t = x_bottom, x_bottom = x_top, x_top = t; + dx = -dx; + dy = -dy; + t = x0, x0 = xb, xb = t; + } + STBTT_assert(dy >= 0); + STBTT_assert(dx >= 0); + + x1 = (int) x_top; + x2 = (int) x_bottom; + // compute intersection with y axis at x1+1 + y_crossing = y_top + dy * (x1+1 - x0); + + // compute intersection with y axis at x2 + y_final = y_top + dy * (x2 - x0); + + // x1 x_top x2 x_bottom + // y_top +------|-----+------------+------------+--------|---+------------+ + // | | | | | | + // | | | | | | + // sy0 | Txxxxx|............|............|............|............| + // y_crossing | *xxxxx.......|............|............|............| + // | | xxxxx..|............|............|............| + // | | /- xx*xxxx........|............|............| + // | | dy < | xxxxxx..|............|............| + // y_final | | \- | xx*xxx.........|............| + // sy1 | | | | xxxxxB...|............| + // | | | | | | + // | | | | | | + // y_bottom +------------+------------+------------+------------+------------+ + // + // goal is to measure the area covered by '.' in each pixel + + // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 + // @TODO: maybe test against sy1 rather than y_bottom? + if (y_crossing > y_bottom) + y_crossing = y_bottom; + + sign = e->direction; + + // area of the rectangle covered from sy0..y_crossing + area = sign * (y_crossing-sy0); + + // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) + scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top); + + // check if final y_crossing is blown up; no test case for this + if (y_final > y_bottom) { + y_final = y_bottom; + dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom + } + + // in second pixel, area covered by line segment found in first pixel + // is always a rectangle 1 wide * the height of that line segment; this + // is exactly what the variable 'area' stores. it also gets a contribution + // from the line segment within it. the THIRD pixel will get the first + // pixel's rectangle contribution, the second pixel's rectangle contribution, + // and its own contribution. the 'own contribution' is the same in every pixel except + // the leftmost and rightmost, a trapezoid that slides down in each pixel. + // the second pixel's contribution to the third pixel will be the + // rectangle 1 wide times the height change in the second pixel, which is dy. + + step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x, + // which multiplied by 1-pixel-width is how much pixel area changes for each step in x + // so the area advances by 'step' every time + + for (x = x1+1; x < x2; ++x) { + scanline[x] += area + step/2; // area of trapezoid is 1*step/2 + area += step; + } + STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down + STBTT_assert(sy1 > y_final-0.01f); + + // area covered in the last pixel is the rectangle from all the pixels to the left, + // plus the trapezoid filled by the line segment in this pixel all the way to the right edge + scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f); + + // the rest of the line is filled based on the total height of the line segment in this pixel + scanline_fill[x2] += sign * (sy1-sy0); + } + } else { + // if edge goes outside of box we're drawing, we require + // clipping logic. since this does not match the intended use + // of this library, we use a different, very slow brute + // force implementation + // note though that this does happen some of the time because + // x_top and x_bottom can be extrapolated at the top & bottom of + // the shape and actually lie outside the bounding box + int x; + for (x=0; x < len; ++x) { + // cases: + // + // there can be up to two intersections with the pixel. any intersection + // with left or right edges can be handled by splitting into two (or three) + // regions. intersections with top & bottom do not necessitate case-wise logic. + // + // the old way of doing this found the intersections with the left & right edges, + // then used some simple logic to produce up to three segments in sorted order + // from top-to-bottom. however, this had a problem: if an x edge was epsilon + // across the x border, then the corresponding y position might not be distinct + // from the other y segment, and it might ignored as an empty segment. to avoid + // that, we need to explicitly produce segments based on x positions. + + // rename variables to clearly-defined pairs + float y0 = y_top; + float x1 = (float) (x); + float x2 = (float) (x+1); + float x3 = xb; + float y3 = y_bottom; + + // x = e->x + e->dx * (y-y_top) + // (y-y_top) = (x - e->x) / e->dx + // y = (x - e->x) / e->dx + y_top + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; + + if (x0 < x1 && x3 > x2) { // three segments descending down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x1 && x0 > x2) { // three segments descending down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else { // one segment + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); + } + } + } + } + e = e->next; + } +} + +// directly AA rasterize edges w/o supersampling +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0, i; + float scanline_data[129], *scanline, *scanline2; + + STBTT__NOTUSED(vsubsample); + + if (result->w > 64) + scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); + else + scanline = scanline_data; + + scanline2 = scanline + result->w; + + y = off_y; + e[n].y0 = (float) (off_y + result->h) + 1; + + while (j < result->h) { + // find center of pixel for this scanline + float scan_y_top = y + 0.0f; + float scan_y_bottom = y + 1.0f; + stbtt__active_edge **step = &active; + + STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); + STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); + + // update all active edges; + // remove all active edges that terminate before the top of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y_top) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + step = &((*step)->next); // advance through list + } + } + + // insert all edges that start before the bottom of this scanline + while (e->y0 <= scan_y_bottom) { + if (e->y0 != e->y1) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); + if (z != NULL) { + if (j == 0 && off_y != 0) { + if (z->ey < scan_y_top) { + // this can happen due to subpixel positioning and some kind of fp rounding error i think + z->ey = scan_y_top; + } + } + STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds + // insert at front + z->next = active; + active = z; + } + } + ++e; + } + + // now process all active edges + if (active) + stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); + + { + float sum = 0; + for (i=0; i < result->w; ++i) { + float k; + int m; + sum += scanline2[i]; + k = scanline[i] + sum; + k = (float) STBTT_fabs(k)*255 + 0.5f; + m = (int) k; + if (m > 255) m = 255; + result->pixels[j*result->stride + i] = (unsigned char) m; + } + } + // advance all the edges + step = &active; + while (*step) { + stbtt__active_edge *z = *step; + z->fx += z->fdx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + + ++y; + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) + +static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) +{ + int i,j; + for (i=1; i < n; ++i) { + stbtt__edge t = p[i], *a = &t; + j = i; + while (j > 0) { + stbtt__edge *b = &p[j-1]; + int c = STBTT__COMPARE(a,b); + if (!c) break; + p[j] = p[j-1]; + --j; + } + if (i != j) + p[j] = t; + } +} + +static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) +{ + /* threshold for transitioning to insertion sort */ + while (n > 12) { + stbtt__edge t; + int c01,c12,c,m,i,j; + + /* compute median of three */ + m = n >> 1; + c01 = STBTT__COMPARE(&p[0],&p[m]); + c12 = STBTT__COMPARE(&p[m],&p[n-1]); + /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ + if (c01 != c12) { + /* otherwise, we'll need to swap something else to middle */ + int z; + c = STBTT__COMPARE(&p[0],&p[n-1]); + /* 0>mid && midn => n; 0 0 */ + /* 0n: 0>n => 0; 0 n */ + z = (c == c12) ? 0 : n-1; + t = p[z]; + p[z] = p[m]; + p[m] = t; + } + /* now p[m] is the median-of-three */ + /* swap it to the beginning so it won't move around */ + t = p[0]; + p[0] = p[m]; + p[m] = t; + + /* partition loop */ + i=1; + j=n-1; + for(;;) { + /* handling of equality is crucial here */ + /* for sentinels & efficiency with duplicates */ + for (;;++i) { + if (!STBTT__COMPARE(&p[i], &p[0])) break; + } + for (;;--j) { + if (!STBTT__COMPARE(&p[0], &p[j])) break; + } + /* make sure we haven't crossed */ + if (i >= j) break; + t = p[i]; + p[i] = p[j]; + p[j] = t; + + ++i; + --j; + } + /* recurse on smaller side, iterate on larger */ + if (j < (n-i)) { + stbtt__sort_edges_quicksort(p,j); + p = p+i; + n = n-i; + } else { + stbtt__sort_edges_quicksort(p+i, n-i); + n = j; + } + } +} + +static void stbtt__sort_edges(stbtt__edge *p, int n) +{ + stbtt__sort_edges_quicksort(p, n); + stbtt__sort_edges_ins_sort(p, n); +} + +typedef struct +{ + float x,y; +} stbtt__point; + +static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) +{ + float y_scale_inv = invert ? -scale_y : scale_y; + stbtt__edge *e; + int n,i,j,k,m; +#if STBTT_RASTERIZER_VERSION == 1 + int vsubsample = result->h < 8 ? 15 : 5; +#elif STBTT_RASTERIZER_VERSION == 2 + int vsubsample = 1; +#else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + // vsubsample should divide 255 evenly; otherwise we won't reach full opacity + + // now we have to blow out the windings into explicit edge lists + n = 0; + for (i=0; i < windings; ++i) + n += wcount[i]; + + e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel + if (e == 0) return; + n = 0; + + m=0; + for (i=0; i < windings; ++i) { + stbtt__point *p = pts + m; + m += wcount[i]; + j = wcount[i]-1; + for (k=0; k < wcount[i]; j=k++) { + int a=k,b=j; + // skip the edge if horizontal + if (p[j].y == p[k].y) + continue; + // add edge from j to k to the list + e[n].invert = 0; + if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { + e[n].invert = 1; + a=j,b=k; + } + e[n].x0 = p[a].x * scale_x + shift_x; + e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; + e[n].x1 = p[b].x * scale_x + shift_x; + e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; + ++n; + } + } + + // now sort the edges by their highest point (should snap to integer, and then by x) + //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + stbtt__sort_edges(e, n); + + // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule + stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); + + STBTT_free(e, userdata); +} + +static void stbtt__add_point(stbtt__point *points, int n, float x, float y) +{ + if (!points) return; // during first pass, it's unallocated + points[n].x = x; + points[n].y = y; +} + +// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching +static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) +{ + // midpoint + float mx = (x0 + 2*x1 + x2)/4; + float my = (y0 + 2*y1 + y2)/4; + // versus directly drawn line + float dx = (x0+x2)/2 - mx; + float dy = (y0+y2)/2 - my; + if (n > 16) // 65536 segments on one curve better be enough! + return 1; + if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA + stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x2,y2); + *num_points = *num_points+1; + } + return 1; +} + +static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) +{ + // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough + float dx0 = x1-x0; + float dy0 = y1-y0; + float dx1 = x2-x1; + float dy1 = y2-y1; + float dx2 = x3-x2; + float dy2 = y3-y2; + float dx = x3-x0; + float dy = y3-y0; + float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); + float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); + float flatness_squared = longlen*longlen-shortlen*shortlen; + + if (n > 16) // 65536 segments on one curve better be enough! + return; + + if (flatness_squared > objspace_flatness_squared) { + float x01 = (x0+x1)/2; + float y01 = (y0+y1)/2; + float x12 = (x1+x2)/2; + float y12 = (y1+y2)/2; + float x23 = (x2+x3)/2; + float y23 = (y2+y3)/2; + + float xa = (x01+x12)/2; + float ya = (y01+y12)/2; + float xb = (x12+x23)/2; + float yb = (y12+y23)/2; + + float mx = (xa+xb)/2; + float my = (ya+yb)/2; + + stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x3,y3); + *num_points = *num_points+1; + } +} + +// returns number of contours +static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) +{ + stbtt__point *points=0; + int num_points=0; + + float objspace_flatness_squared = objspace_flatness * objspace_flatness; + int i,n=0,start=0, pass; + + // count how many "moves" there are to get the contour count + for (i=0; i < num_verts; ++i) + if (vertices[i].type == STBTT_vmove) + ++n; + + *num_contours = n; + if (n == 0) return 0; + + *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); + + if (*contour_lengths == 0) { + *num_contours = 0; + return 0; + } + + // make two passes through the points so we don't need to realloc + for (pass=0; pass < 2; ++pass) { + float x=0,y=0; + if (pass == 1) { + points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); + if (points == NULL) goto error; + } + num_points = 0; + n= -1; + for (i=0; i < num_verts; ++i) { + switch (vertices[i].type) { + case STBTT_vmove: + // start the next contour + if (n >= 0) + (*contour_lengths)[n] = num_points - start; + ++n; + start = num_points; + + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x,y); + break; + case STBTT_vline: + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; + case STBTT_vcurve: + stbtt__tesselate_curve(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + case STBTT_vcubic: + stbtt__tesselate_cubic(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].cx1, vertices[i].cy1, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + } + } + (*contour_lengths)[n] = num_points - start; + } + + return points; +error: + STBTT_free(points, userdata); + STBTT_free(*contour_lengths, userdata); + *contour_lengths = 0; + *num_contours = 0; + return NULL; +} + +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) +{ + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; + stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + if (windings) { + stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); + STBTT_free(winding_lengths, userdata); + STBTT_free(windings, userdata); + } +} + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + int ix0,iy0,ix1,iy1; + stbtt__bitmap gbm; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) { + STBTT_free(vertices, info->userdata); + return NULL; + } + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); + + // now we get the size + gbm.w = (ix1 - ix0); + gbm.h = (iy1 - iy0); + gbm.pixels = NULL; // in case we error + + if (width ) *width = gbm.w; + if (height) *height = gbm.h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + if (gbm.w && gbm.h) { + gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); + if (gbm.pixels) { + gbm.stride = gbm.w; + + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); + } + } + STBTT_free(vertices, info->userdata); + return gbm.pixels; +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) +{ + int ix0,iy0; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + stbtt__bitmap gbm; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); + gbm.pixels = output; + gbm.w = out_w; + gbm.h = out_h; + gbm.stride = out_stride; + + if (gbm.w && gbm.h) + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); + + STBTT_free(vertices, info->userdata); +} + +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) +{ + stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); +} + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-CRAPPY packing to keep source code small + +static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata) +{ + float scale; + int x,y,bottom_y, i; + stbtt_fontinfo f; + f.userdata = NULL; + if (!stbtt_InitFont(&f, data, offset)) + return -1; + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + x=y=1; + bottom_y = 1; + + scale = stbtt_ScaleForPixelHeight(&f, pixel_height); + + for (i=0; i < num_chars; ++i) { + int advance, lsb, x0,y0,x1,y1,gw,gh; + int g = stbtt_FindGlyphIndex(&f, first_char + i); + stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); + gw = x1-x0; + gh = y1-y0; + if (x + gw + 1 >= pw) + y = bottom_y, x = 1; // advance to next row + if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row + return -i; + STBTT_assert(x+gw < pw); + STBTT_assert(y+gh < ph); + stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); + chardata[i].x0 = (stbtt_int16) x; + chardata[i].y0 = (stbtt_int16) y; + chardata[i].x1 = (stbtt_int16) (x + gw); + chardata[i].y1 = (stbtt_int16) (y + gh); + chardata[i].xadvance = scale * advance; + chardata[i].xoff = (float) x0; + chardata[i].yoff = (float) y0; + x = x + gw + 1; + if (y+gh+1 > bottom_y) + bottom_y = y+gh+1; + } + return bottom_y; +} + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +{ + float d3d_bias = opengl_fillrule ? 0 : -0.5f; + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_bakedchar *b = chardata + char_index; + int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); + int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); + + q->x0 = round_x + d3d_bias; + q->y0 = round_y + d3d_bias; + q->x1 = round_x + b->x1 - b->x0 + d3d_bias; + q->y1 = round_y + b->y1 - b->y0 + d3d_bias; + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// rectangle packing replacement routines if you don't have stb_rect_pack.h +// + +#ifndef STB_RECT_PACK_VERSION + +typedef int stbrp_coord; + +//////////////////////////////////////////////////////////////////////////////////// +// // +// // +// COMPILER WARNING ?!?!? // +// // +// // +// if you get a compile warning due to these symbols being defined more than // +// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // +// // +//////////////////////////////////////////////////////////////////////////////////// + +typedef struct +{ + int width,height; + int x,y,bottom_y; +} stbrp_context; + +typedef struct +{ + unsigned char x; +} stbrp_node; + +struct stbrp_rect +{ + stbrp_coord x,y; + int id,w,h,was_packed; +}; + +static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) +{ + con->width = pw; + con->height = ph; + con->x = 0; + con->y = 0; + con->bottom_y = 0; + STBTT__NOTUSED(nodes); + STBTT__NOTUSED(num_nodes); +} + +static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) +{ + int i; + for (i=0; i < num_rects; ++i) { + if (con->x + rects[i].w > con->width) { + con->x = 0; + con->y = con->bottom_y; + } + if (con->y + rects[i].h > con->height) + break; + rects[i].x = con->x; + rects[i].y = con->y; + rects[i].was_packed = 1; + con->x += rects[i].w; + if (con->y + rects[i].h > con->bottom_y) + con->bottom_y = con->y + rects[i].h; + } + for ( ; i < num_rects; ++i) + rects[i].was_packed = 0; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If +// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) +{ + stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); + int num_nodes = pw - padding; + stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); + + if (context == NULL || nodes == NULL) { + if (context != NULL) STBTT_free(context, alloc_context); + if (nodes != NULL) STBTT_free(nodes , alloc_context); + return 0; + } + + spc->user_allocator_context = alloc_context; + spc->width = pw; + spc->height = ph; + spc->pixels = pixels; + spc->pack_info = context; + spc->nodes = nodes; + spc->padding = padding; + spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; + spc->h_oversample = 1; + spc->v_oversample = 1; + spc->skip_missing = 0; + + stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); + + if (pixels) + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + + return 1; +} + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) +{ + STBTT_free(spc->nodes , spc->user_allocator_context); + STBTT_free(spc->pack_info, spc->user_allocator_context); +} + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) +{ + STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); + STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); + if (h_oversample <= STBTT_MAX_OVERSAMPLE) + spc->h_oversample = h_oversample; + if (v_oversample <= STBTT_MAX_OVERSAMPLE) + spc->v_oversample = v_oversample; +} + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) +{ + spc->skip_missing = skip; +} + +#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) + +static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_w = w - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < h; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < w; ++i) { + STBTT_assert(pixels[i] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i] = (unsigned char) (total / kernel_width); + } + + pixels += stride_in_bytes; + } +} + +static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_h = h - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < w; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < h; ++i) { + STBTT_assert(pixels[i*stride_in_bytes] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + + pixels += 1; + } +} + +static float stbtt__oversample_shift(int oversample) +{ + if (!oversample) + return 0.0f; + + // The prefilter is a box filter of width "oversample", + // which shifts phase by (oversample - 1)/2 pixels in + // oversampled space. We want to shift in the opposite + // direction to counter this. + return (float)-(oversample - 1) / (2.0f * (float)oversample); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k; + int missing_glyph_added = 0; + + k=0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + ranges[i].h_oversample = (unsigned char) spc->h_oversample; + ranges[i].v_oversample = (unsigned char) spc->v_oversample; + for (j=0; j < ranges[i].num_chars; ++j) { + int x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { + rects[k].w = rects[k].h = 0; + } else { + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0) + missing_glyph_added = 1; + } + ++k; + } + } + + return k; +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k, missing_glyph = -1, return_value = 1; + + // save current values + int old_h_over = spc->h_oversample; + int old_v_over = spc->v_oversample; + + k = 0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + float recip_h,recip_v,sub_x,sub_y; + spc->h_oversample = ranges[i].h_oversample; + spc->v_oversample = ranges[i].v_oversample; + recip_h = 1.0f / spc->h_oversample; + recip_v = 1.0f / spc->v_oversample; + sub_x = stbtt__oversample_shift(spc->h_oversample); + sub_y = stbtt__oversample_shift(spc->v_oversample); + for (j=0; j < ranges[i].num_chars; ++j) { + stbrp_rect *r = &rects[k]; + if (r->was_packed && r->w != 0 && r->h != 0) { + stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; + int advance, lsb, x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + stbrp_coord pad = (stbrp_coord) spc->padding; + + // pad on left and top + r->x += pad; + r->y += pad; + r->w -= pad; + r->h -= pad; + stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); + stbtt_GetGlyphBitmapBox(info, glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + &x0,&y0,&x1,&y1); + stbtt_MakeGlyphBitmapSubpixel(info, + spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w - spc->h_oversample+1, + r->h - spc->v_oversample+1, + spc->stride_in_bytes, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + glyph); + + if (spc->h_oversample > 1) + stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->h_oversample); + + if (spc->v_oversample > 1) + stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->v_oversample); + + bc->x0 = (stbtt_int16) r->x; + bc->y0 = (stbtt_int16) r->y; + bc->x1 = (stbtt_int16) (r->x + r->w); + bc->y1 = (stbtt_int16) (r->y + r->h); + bc->xadvance = scale * advance; + bc->xoff = (float) x0 * recip_h + sub_x; + bc->yoff = (float) y0 * recip_v + sub_y; + bc->xoff2 = (x0 + r->w) * recip_h + sub_x; + bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + + if (glyph == 0) + missing_glyph = j; + } else if (spc->skip_missing) { + return_value = 0; + } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { + ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; + } else { + return_value = 0; // if any fail, report failure + } + + ++k; + } + } + + // restore original values + spc->h_oversample = old_h_over; + spc->v_oversample = old_v_over; + + return return_value; +} + +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) +{ + stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); +} + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +{ + stbtt_fontinfo info; + int i,j,n, return_value = 1; + //stbrp_context *context = (stbrp_context *) spc->pack_info; + stbrp_rect *rects; + + // flag all characters as NOT packed + for (i=0; i < num_ranges; ++i) + for (j=0; j < ranges[i].num_chars; ++j) + ranges[i].chardata_for_range[j].x0 = + ranges[i].chardata_for_range[j].y0 = + ranges[i].chardata_for_range[j].x1 = + ranges[i].chardata_for_range[j].y1 = 0; + + n = 0; + for (i=0; i < num_ranges; ++i) + n += ranges[i].num_chars; + + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); + if (rects == NULL) + return 0; + + info.userdata = spc->user_allocator_context; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); + + n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); + + stbtt_PackFontRangesPackRects(spc, rects, n); + + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); + + STBTT_free(rects, spc->user_allocator_context); + return return_value; +} + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) +{ + stbtt_pack_range range; + range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; + range.array_of_unicode_codepoints = NULL; + range.num_chars = num_chars_in_range; + range.chardata_for_range = chardata_for_range; + range.font_size = font_size; + return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); +} + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) +{ + int i_ascent, i_descent, i_lineGap; + float scale; + stbtt_fontinfo info; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); + scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); + stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); + *ascent = (float) i_ascent * scale; + *descent = (float) i_descent * scale; + *lineGap = (float) i_lineGap * scale; +} + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +{ + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_packedchar *b = chardata + char_index; + + if (align_to_integer) { + float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); + float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); + q->x0 = x; + q->y0 = y; + q->x1 = x + b->xoff2 - b->xoff; + q->y1 = y + b->yoff2 - b->yoff; + } else { + q->x0 = *xpos + b->xoff; + q->y0 = *ypos + b->yoff; + q->x1 = *xpos + b->xoff2; + q->y1 = *ypos + b->yoff2; + } + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) +#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) STBTT_sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + // make sure y never passes through a vertex of the shape + y_frac = (float) STBTT_fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + + orig[0] = x; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + a*x^2 + b*x + c = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int ix0,iy0,ix1,iy1; + int w,h; + unsigned char *data; + + if (scale == 0) return NULL; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) + return NULL; + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + // distance from singular values (in the same units as the pixel grid) + const float eps = 1./1024, eps2 = eps*eps; + int x,y,i,j; + float *precompute; + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist < eps) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 >= eps2) + precompute[i] = 1.0f / len2; + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3] = {0.f,0.f,0.f}; + float px,py,t,it,dist2; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (STBTT_fabs(a) < eps2) { // if a is 0, it's linear + if (STBTT_fabs(b) >= eps2) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +////////////////////////////////////////////////////////////////////////////// +// +// font name matching -- recommended not to use this +// + +// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) +{ + stbtt_int32 i=0; + + // convert utf16 to utf8 and compare the results while converting + while (len2) { + stbtt_uint16 ch = s2[0]*256 + s2[1]; + if (ch < 0x80) { + if (i >= len1) return -1; + if (s1[i++] != ch) return -1; + } else if (ch < 0x800) { + if (i+1 >= len1) return -1; + if (s1[i++] != 0xc0 + (ch >> 6)) return -1; + if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; + } else if (ch >= 0xd800 && ch < 0xdc00) { + stbtt_uint32 c; + stbtt_uint16 ch2 = s2[2]*256 + s2[3]; + if (i+3 >= len1) return -1; + c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; + if (s1[i++] != 0xf0 + (c >> 18)) return -1; + if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; + s2 += 2; // plus another 2 below + len2 -= 2; + } else if (ch >= 0xdc00 && ch < 0xe000) { + return -1; + } else { + if (i+2 >= len1) return -1; + if (s1[i++] != 0xe0 + (ch >> 12)) return -1; + if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; + } + s2 += 2; + len2 -= 2; + } + return i; +} + +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) +{ + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); +} + +// returns results in whatever encoding you request... but note that 2-byte encodings +// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) +{ + stbtt_int32 i,count,stringOffset; + stbtt_uint8 *fc = font->data; + stbtt_uint32 offset = font->fontstart; + stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return NULL; + + count = ttUSHORT(fc+nm+2); + stringOffset = nm + ttUSHORT(fc+nm+4); + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) + && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { + *length = ttUSHORT(fc+loc+8); + return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); + } + } + return NULL; +} + +static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) +{ + stbtt_int32 i; + stbtt_int32 count = ttUSHORT(fc+nm+2); + stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); + + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + stbtt_int32 id = ttUSHORT(fc+loc+6); + if (id == target_id) { + // find the encoding + stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); + + // is this a Unicode encoding? + if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { + stbtt_int32 slen = ttUSHORT(fc+loc+8); + stbtt_int32 off = ttUSHORT(fc+loc+10); + + // check if there's a prefix match + stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); + if (matchlen >= 0) { + // check for target_id+1 immediately following, with same encoding & language + if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { + slen = ttUSHORT(fc+loc+12+8); + off = ttUSHORT(fc+loc+12+10); + if (slen == 0) { + if (matchlen == nlen) + return 1; + } else if (matchlen < nlen && name[matchlen] == ' ') { + ++matchlen; + if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) + return 1; + } + } else { + // if nothing immediately following + if (matchlen == nlen) + return 1; + } + } + } + + // @TODO handle other encodings + } + } + return 0; +} + +static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) +{ + stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); + stbtt_uint32 nm,hd; + if (!stbtt__isfont(fc+offset)) return 0; + + // check italics/bold/underline flags in macStyle... + if (flags) { + hd = stbtt__find_table(fc, offset, "head"); + if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; + } + + nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return 0; + + if (flags) { + // if we checked the macStyle flags, then just check the family and ignore the subfamily + if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } else { + if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + + return 0; +} + +static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) +{ + stbtt_int32 i; + for (i=0;;++i) { + stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); + if (off < 0) return off; + if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) + return off; + } +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, + float pixel_height, unsigned char *pixels, int pw, int ph, + int first_char, int num_chars, stbtt_bakedchar *chardata) +{ + return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); +} + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) +{ + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); +} + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) +{ + return stbtt_GetNumberOfFonts_internal((unsigned char *) data); +} + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) +{ + return stbtt_InitFont_internal(info, (unsigned char *) data, offset); +} + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) +{ + return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); +} + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif // STB_TRUETYPE_IMPLEMENTATION + + +// FULL VERSION HISTORY +// +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) allow user-defined fabs() replacement +// fix memory leak if fontsize=0.0 +// fix warning from duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// allow PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) +// also more precise AA rasterizer, except if shapes overlap +// remove need for STBTT_sort +// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC +// 1.04 (2015-04-15) typo in example +// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes +// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ +// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match +// non-oversampled; STBTT_POINT_SIZE for packed case only +// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling +// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) +// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID +// 0.8b (2014-07-07) fix a warning +// 0.8 (2014-05-25) fix a few more warnings +// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back +// 0.6c (2012-07-24) improve documentation +// 0.6b (2012-07-20) fix a few more warnings +// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, +// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty +// 0.5 (2011-12-09) bugfixes: +// subpixel glyph renderer computed wrong bounding box +// first vertex of shape can be off-curve (FreeSans) +// 0.4b (2011-12-03) fixed an error in the font baking example +// 0.4 (2011-12-01) kerning, subpixel rendering (tor) +// bugfixes for: +// codepoint-to-glyph conversion using table fmt=12 +// codepoint-to-glyph conversion using table fmt=4 +// stbtt_GetBakedQuad with non-square texture (Zer) +// updated Hello World! sample to use kerning and subpixel +// fixed some warnings +// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) +// userdata, malloc-from-userdata, non-zero fill (stb) +// 0.2 (2009-03-11) Fix unsigned/signed char warnings +// 0.1 (2009-03-09) First public release +// + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_vorbis.c b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_vorbis.c new file mode 100644 index 0000000..3e5c250 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_vorbis.c @@ -0,0 +1,5584 @@ +// Ogg Vorbis audio decoder - v1.22 - public domain +// http://nothings.org/stb_vorbis/ +// +// Original version written by Sean Barrett in 2007. +// +// Originally sponsored by RAD Game Tools. Seeking implementation +// sponsored by Phillip Bennefall, Marc Andersen, Aaron Baker, +// Elias Software, Aras Pranckevicius, and Sean Barrett. +// +// LICENSE +// +// See end of file for license information. +// +// Limitations: +// +// - floor 0 not supported (used in old ogg vorbis files pre-2004) +// - lossless sample-truncation at beginning ignored +// - cannot concatenate multiple vorbis streams +// - sample positions are 32-bit, limiting seekable 192Khz +// files to around 6 hours (Ogg supports 64-bit) +// +// Feature contributors: +// Dougall Johnson (sample-exact seeking) +// +// Bugfix/warning contributors: +// Terje Mathisen Niklas Frykholm Andy Hill +// Casey Muratori John Bolton Gargaj +// Laurent Gomila Marc LeBlanc Ronny Chevalier +// Bernhard Wodo Evan Balster github:alxprd +// Tom Beaumont Ingo Leitgeb Nicolas Guillemot +// Phillip Bennefall Rohit Thiago Goulart +// github:manxorist Saga Musix github:infatum +// Timur Gagiev Maxwell Koo Peter Waller +// github:audinowho Dougall Johnson David Reid +// github:Clownacy Pedro J. Estebanez Remi Verschelde +// AnthoFoxo github:morlat Gabriel Ravier +// +// Partial history: +// 1.22 - 2021-07-11 - various small fixes +// 1.21 - 2021-07-02 - fix bug for files with no comments +// 1.20 - 2020-07-11 - several small fixes +// 1.19 - 2020-02-05 - warnings +// 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc. +// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure) +// 1.16 - 2019-03-04 - fix warnings +// 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found +// 1.14 - 2018-02-11 - delete bogus dealloca usage +// 1.13 - 2018-01-29 - fix truncation of last frame (hopefully) +// 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files +// 1.11 - 2017-07-23 - fix MinGW compilation +// 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory +// 1.09 - 2016-04-04 - back out 'truncation of last frame' fix from previous version +// 1.08 - 2016-04-02 - warnings; setup memory leaks; truncation of last frame +// 1.07 - 2015-01-16 - fixes for crashes on invalid files; warning fixes; const +// 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson) +// some crash fixes when out of memory or with corrupt files +// fix some inappropriately signed shifts +// 1.05 - 2015-04-19 - don't define __forceinline if it's redundant +// 1.04 - 2014-08-27 - fix missing const-correct case in API +// 1.03 - 2014-08-07 - warning fixes +// 1.02 - 2014-07-09 - declare qsort comparison as explicitly _cdecl in Windows +// 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float (interleaved was correct) +// 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in >2-channel; +// (API change) report sample rate for decode-full-file funcs +// +// See end of file for full version history. + + +////////////////////////////////////////////////////////////////////////////// +// +// HEADER BEGINS HERE +// + +#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H +#define STB_VORBIS_INCLUDE_STB_VORBIS_H + +#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO) +#define STB_VORBIS_NO_STDIO 1 +#endif + +#ifndef STB_VORBIS_NO_STDIO +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/////////// THREAD SAFETY + +// Individual stb_vorbis* handles are not thread-safe; you cannot decode from +// them from multiple threads at the same time. However, you can have multiple +// stb_vorbis* handles and decode from them independently in multiple thrads. + + +/////////// MEMORY ALLOCATION + +// normally stb_vorbis uses malloc() to allocate memory at startup, +// and alloca() to allocate temporary memory during a frame on the +// stack. (Memory consumption will depend on the amount of setup +// data in the file and how you set the compile flags for speed +// vs. size. In my test files the maximal-size usage is ~150KB.) +// +// You can modify the wrapper functions in the source (setup_malloc, +// setup_temp_malloc, temp_malloc) to change this behavior, or you +// can use a simpler allocation model: you pass in a buffer from +// which stb_vorbis will allocate _all_ its memory (including the +// temp memory). "open" may fail with a VORBIS_outofmem if you +// do not pass in enough data; there is no way to determine how +// much you do need except to succeed (at which point you can +// query get_info to find the exact amount required. yes I know +// this is lame). +// +// If you pass in a non-NULL buffer of the type below, allocation +// will occur from it as described above. Otherwise just pass NULL +// to use malloc()/alloca() + +typedef struct +{ + char *alloc_buffer; + int alloc_buffer_length_in_bytes; +} stb_vorbis_alloc; + + +/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES + +typedef struct stb_vorbis stb_vorbis; + +typedef struct +{ + unsigned int sample_rate; + int channels; + + unsigned int setup_memory_required; + unsigned int setup_temp_memory_required; + unsigned int temp_memory_required; + + int max_frame_size; +} stb_vorbis_info; + +typedef struct +{ + char *vendor; + + int comment_list_length; + char **comment_list; +} stb_vorbis_comment; + +// get general information about the file +extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f); + +// get ogg comments +extern stb_vorbis_comment stb_vorbis_get_comment(stb_vorbis *f); + +// get the last error detected (clears it, too) +extern int stb_vorbis_get_error(stb_vorbis *f); + +// close an ogg vorbis file and free all memory in use +extern void stb_vorbis_close(stb_vorbis *f); + +// this function returns the offset (in samples) from the beginning of the +// file that will be returned by the next decode, if it is known, or -1 +// otherwise. after a flush_pushdata() call, this may take a while before +// it becomes valid again. +// NOT WORKING YET after a seek with PULLDATA API +extern int stb_vorbis_get_sample_offset(stb_vorbis *f); + +// returns the current seek point within the file, or offset from the beginning +// of the memory buffer. In pushdata mode it returns 0. +extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f); + +/////////// PUSHDATA API + +#ifndef STB_VORBIS_NO_PUSHDATA_API + +// this API allows you to get blocks of data from any source and hand +// them to stb_vorbis. you have to buffer them; stb_vorbis will tell +// you how much it used, and you have to give it the rest next time; +// and stb_vorbis may not have enough data to work with and you will +// need to give it the same data again PLUS more. Note that the Vorbis +// specification does not bound the size of an individual frame. + +extern stb_vorbis *stb_vorbis_open_pushdata( + const unsigned char * datablock, int datablock_length_in_bytes, + int *datablock_memory_consumed_in_bytes, + int *error, + const stb_vorbis_alloc *alloc_buffer); +// create a vorbis decoder by passing in the initial data block containing +// the ogg&vorbis headers (you don't need to do parse them, just provide +// the first N bytes of the file--you're told if it's not enough, see below) +// on success, returns an stb_vorbis *, does not set error, returns the amount of +// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes; +// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed +// if returns NULL and *error is VORBIS_need_more_data, then the input block was +// incomplete and you need to pass in a larger block from the start of the file + +extern int stb_vorbis_decode_frame_pushdata( + stb_vorbis *f, + const unsigned char *datablock, int datablock_length_in_bytes, + int *channels, // place to write number of float * buffers + float ***output, // place to write float ** array of float * buffers + int *samples // place to write number of output samples + ); +// decode a frame of audio sample data if possible from the passed-in data block +// +// return value: number of bytes we used from datablock +// +// possible cases: +// 0 bytes used, 0 samples output (need more data) +// N bytes used, 0 samples output (resynching the stream, keep going) +// N bytes used, M samples output (one frame of data) +// note that after opening a file, you will ALWAYS get one N-bytes,0-sample +// frame, because Vorbis always "discards" the first frame. +// +// Note that on resynch, stb_vorbis will rarely consume all of the buffer, +// instead only datablock_length_in_bytes-3 or less. This is because it wants +// to avoid missing parts of a page header if they cross a datablock boundary, +// without writing state-machiney code to record a partial detection. +// +// The number of channels returned are stored in *channels (which can be +// NULL--it is always the same as the number of channels reported by +// get_info). *output will contain an array of float* buffers, one per +// channel. In other words, (*output)[0][0] contains the first sample from +// the first channel, and (*output)[1][0] contains the first sample from +// the second channel. +// +// *output points into stb_vorbis's internal output buffer storage; these +// buffers are owned by stb_vorbis and application code should not free +// them or modify their contents. They are transient and will be overwritten +// once you ask for more data to get decoded, so be sure to grab any data +// you need before then. + +extern void stb_vorbis_flush_pushdata(stb_vorbis *f); +// inform stb_vorbis that your next datablock will not be contiguous with +// previous ones (e.g. you've seeked in the data); future attempts to decode +// frames will cause stb_vorbis to resynchronize (as noted above), and +// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it +// will begin decoding the _next_ frame. +// +// if you want to seek using pushdata, you need to seek in your file, then +// call stb_vorbis_flush_pushdata(), then start calling decoding, then once +// decoding is returning you data, call stb_vorbis_get_sample_offset, and +// if you don't like the result, seek your file again and repeat. +#endif + + +////////// PULLING INPUT API + +#ifndef STB_VORBIS_NO_PULLDATA_API +// This API assumes stb_vorbis is allowed to pull data from a source-- +// either a block of memory containing the _entire_ vorbis stream, or a +// FILE * that you or it create, or possibly some other reading mechanism +// if you go modify the source to replace the FILE * case with some kind +// of callback to your code. (But if you don't support seeking, you may +// just want to go ahead and use pushdata.) + +#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION) +extern int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output); +#endif +#if !defined(STB_VORBIS_NO_INTEGER_CONVERSION) +extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *channels, int *sample_rate, short **output); +#endif +// decode an entire file and output the data interleaved into a malloc()ed +// buffer stored in *output. The return value is the number of samples +// decoded, or -1 if the file could not be opened or was not an ogg vorbis file. +// When you're done with it, just free() the pointer returned in *output. + +extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, + int *error, const stb_vorbis_alloc *alloc_buffer); +// create an ogg vorbis decoder from an ogg vorbis stream in memory (note +// this must be the entire stream!). on failure, returns NULL and sets *error + +#ifndef STB_VORBIS_NO_STDIO +extern stb_vorbis * stb_vorbis_open_filename(const char *filename, + int *error, const stb_vorbis_alloc *alloc_buffer); +// create an ogg vorbis decoder from a filename via fopen(). on failure, +// returns NULL and sets *error (possibly to VORBIS_file_open_failure). + +extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close, + int *error, const stb_vorbis_alloc *alloc_buffer); +// create an ogg vorbis decoder from an open FILE *, looking for a stream at +// the _current_ seek point (ftell). on failure, returns NULL and sets *error. +// note that stb_vorbis must "own" this stream; if you seek it in between +// calls to stb_vorbis, it will become confused. Moreover, if you attempt to +// perform stb_vorbis_seek_*() operations on this file, it will assume it +// owns the _entire_ rest of the file after the start point. Use the next +// function, stb_vorbis_open_file_section(), to limit it. + +extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close, + int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len); +// create an ogg vorbis decoder from an open FILE *, looking for a stream at +// the _current_ seek point (ftell); the stream will be of length 'len' bytes. +// on failure, returns NULL and sets *error. note that stb_vorbis must "own" +// this stream; if you seek it in between calls to stb_vorbis, it will become +// confused. +#endif + +extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number); +extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number); +// these functions seek in the Vorbis file to (approximately) 'sample_number'. +// after calling seek_frame(), the next call to get_frame_*() will include +// the specified sample. after calling stb_vorbis_seek(), the next call to +// stb_vorbis_get_samples_* will start with the specified sample. If you +// do not need to seek to EXACTLY the target sample when using get_samples_*, +// you can also use seek_frame(). + +extern int stb_vorbis_seek_start(stb_vorbis *f); +// this function is equivalent to stb_vorbis_seek(f,0) + +extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f); +extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f); +// these functions return the total length of the vorbis stream + +extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output); +// decode the next frame and return the number of samples. the number of +// channels returned are stored in *channels (which can be NULL--it is always +// the same as the number of channels reported by get_info). *output will +// contain an array of float* buffers, one per channel. These outputs will +// be overwritten on the next call to stb_vorbis_get_frame_*. +// +// You generally should not intermix calls to stb_vorbis_get_frame_*() +// and stb_vorbis_get_samples_*(), since the latter calls the former. + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts); +extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples); +#endif +// decode the next frame and return the number of *samples* per channel. +// Note that for interleaved data, you pass in the number of shorts (the +// size of your array), but the return value is the number of samples per +// channel, not the total number of samples. +// +// The data is coerced to the number of channels you request according to the +// channel coercion rules (see below). You must pass in the size of your +// buffer(s) so that stb_vorbis will not overwrite the end of the buffer. +// The maximum buffer size needed can be gotten from get_info(); however, +// the Vorbis I specification implies an absolute maximum of 4096 samples +// per channel. + +// Channel coercion rules: +// Let M be the number of channels requested, and N the number of channels present, +// and Cn be the nth channel; let stereo L be the sum of all L and center channels, +// and stereo R be the sum of all R and center channels (channel assignment from the +// vorbis spec). +// M N output +// 1 k sum(Ck) for all k +// 2 * stereo L, stereo R +// k l k > l, the first l channels, then 0s +// k l k <= l, the first k channels +// Note that this is not _good_ surround etc. mixing at all! It's just so +// you get something useful. + +extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats); +extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples); +// gets num_samples samples, not necessarily on a frame boundary--this requires +// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES. +// Returns the number of samples stored per channel; it may be less than requested +// at the end of the file. If there are no more samples in the file, returns 0. + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts); +extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples); +#endif +// gets num_samples samples, not necessarily on a frame boundary--this requires +// buffering so you have to supply the buffers. Applies the coercion rules above +// to produce 'channels' channels. Returns the number of samples stored per channel; +// it may be less than requested at the end of the file. If there are no more +// samples in the file, returns 0. + +#endif + +//////// ERROR CODES + +enum STBVorbisError +{ + VORBIS__no_error, + + VORBIS_need_more_data=1, // not a real error + + VORBIS_invalid_api_mixing, // can't mix API modes + VORBIS_outofmem, // not enough memory + VORBIS_feature_not_supported, // uses floor 0 + VORBIS_too_many_channels, // STB_VORBIS_MAX_CHANNELS is too small + VORBIS_file_open_failure, // fopen() failed + VORBIS_seek_without_length, // can't seek in unknown-length file + + VORBIS_unexpected_eof=10, // file is truncated? + VORBIS_seek_invalid, // seek past EOF + + // decoding errors (corrupt/invalid stream) -- you probably + // don't care about the exact details of these + + // vorbis errors: + VORBIS_invalid_setup=20, + VORBIS_invalid_stream, + + // ogg errors: + VORBIS_missing_capture_pattern=30, + VORBIS_invalid_stream_structure_version, + VORBIS_continued_packet_flag_invalid, + VORBIS_incorrect_stream_serial_number, + VORBIS_invalid_first_page, + VORBIS_bad_packet_type, + VORBIS_cant_find_last_page, + VORBIS_seek_failed, + VORBIS_ogg_skeleton_not_supported +}; + + +#ifdef __cplusplus +} +#endif + +#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H +// +// HEADER ENDS HERE +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef STB_VORBIS_HEADER_ONLY + +// global configuration settings (e.g. set these in the project/makefile), +// or just set them in this file at the top (although ideally the first few +// should be visible when the header file is compiled too, although it's not +// crucial) + +// STB_VORBIS_NO_PUSHDATA_API +// does not compile the code for the various stb_vorbis_*_pushdata() +// functions +// #define STB_VORBIS_NO_PUSHDATA_API + +// STB_VORBIS_NO_PULLDATA_API +// does not compile the code for the non-pushdata APIs +// #define STB_VORBIS_NO_PULLDATA_API + +// STB_VORBIS_NO_STDIO +// does not compile the code for the APIs that use FILE *s internally +// or externally (implied by STB_VORBIS_NO_PULLDATA_API) +// #define STB_VORBIS_NO_STDIO + +// STB_VORBIS_NO_INTEGER_CONVERSION +// does not compile the code for converting audio sample data from +// float to integer (implied by STB_VORBIS_NO_PULLDATA_API) +// #define STB_VORBIS_NO_INTEGER_CONVERSION + +// STB_VORBIS_NO_FAST_SCALED_FLOAT +// does not use a fast float-to-int trick to accelerate float-to-int on +// most platforms which requires endianness be defined correctly. +//#define STB_VORBIS_NO_FAST_SCALED_FLOAT + + +// STB_VORBIS_MAX_CHANNELS [number] +// globally define this to the maximum number of channels you need. +// The spec does not put a restriction on channels except that +// the count is stored in a byte, so 255 is the hard limit. +// Reducing this saves about 16 bytes per value, so using 16 saves +// (255-16)*16 or around 4KB. Plus anything other memory usage +// I forgot to account for. Can probably go as low as 8 (7.1 audio), +// 6 (5.1 audio), or 2 (stereo only). +#ifndef STB_VORBIS_MAX_CHANNELS +#define STB_VORBIS_MAX_CHANNELS 16 // enough for anyone? +#endif + +// STB_VORBIS_PUSHDATA_CRC_COUNT [number] +// after a flush_pushdata(), stb_vorbis begins scanning for the +// next valid page, without backtracking. when it finds something +// that looks like a page, it streams through it and verifies its +// CRC32. Should that validation fail, it keeps scanning. But it's +// possible that _while_ streaming through to check the CRC32 of +// one candidate page, it sees another candidate page. This #define +// determines how many "overlapping" candidate pages it can search +// at once. Note that "real" pages are typically ~4KB to ~8KB, whereas +// garbage pages could be as big as 64KB, but probably average ~16KB. +// So don't hose ourselves by scanning an apparent 64KB page and +// missing a ton of real ones in the interim; so minimum of 2 +#ifndef STB_VORBIS_PUSHDATA_CRC_COUNT +#define STB_VORBIS_PUSHDATA_CRC_COUNT 4 +#endif + +// STB_VORBIS_FAST_HUFFMAN_LENGTH [number] +// sets the log size of the huffman-acceleration table. Maximum +// supported value is 24. with larger numbers, more decodings are O(1), +// but the table size is larger so worse cache missing, so you'll have +// to probe (and try multiple ogg vorbis files) to find the sweet spot. +#ifndef STB_VORBIS_FAST_HUFFMAN_LENGTH +#define STB_VORBIS_FAST_HUFFMAN_LENGTH 10 +#endif + +// STB_VORBIS_FAST_BINARY_LENGTH [number] +// sets the log size of the binary-search acceleration table. this +// is used in similar fashion to the fast-huffman size to set initial +// parameters for the binary search + +// STB_VORBIS_FAST_HUFFMAN_INT +// The fast huffman tables are much more efficient if they can be +// stored as 16-bit results instead of 32-bit results. This restricts +// the codebooks to having only 65535 possible outcomes, though. +// (At least, accelerated by the huffman table.) +#ifndef STB_VORBIS_FAST_HUFFMAN_INT +#define STB_VORBIS_FAST_HUFFMAN_SHORT +#endif + +// STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH +// If the 'fast huffman' search doesn't succeed, then stb_vorbis falls +// back on binary searching for the correct one. This requires storing +// extra tables with the huffman codes in sorted order. Defining this +// symbol trades off space for speed by forcing a linear search in the +// non-fast case, except for "sparse" codebooks. +// #define STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH + +// STB_VORBIS_DIVIDES_IN_RESIDUE +// stb_vorbis precomputes the result of the scalar residue decoding +// that would otherwise require a divide per chunk. you can trade off +// space for time by defining this symbol. +// #define STB_VORBIS_DIVIDES_IN_RESIDUE + +// STB_VORBIS_DIVIDES_IN_CODEBOOK +// vorbis VQ codebooks can be encoded two ways: with every case explicitly +// stored, or with all elements being chosen from a small range of values, +// and all values possible in all elements. By default, stb_vorbis expands +// this latter kind out to look like the former kind for ease of decoding, +// because otherwise an integer divide-per-vector-element is required to +// unpack the index. If you define STB_VORBIS_DIVIDES_IN_CODEBOOK, you can +// trade off storage for speed. +//#define STB_VORBIS_DIVIDES_IN_CODEBOOK + +#ifdef STB_VORBIS_CODEBOOK_SHORTS +#error "STB_VORBIS_CODEBOOK_SHORTS is no longer supported as it produced incorrect results for some input formats" +#endif + +// STB_VORBIS_DIVIDE_TABLE +// this replaces small integer divides in the floor decode loop with +// table lookups. made less than 1% difference, so disabled by default. + +// STB_VORBIS_NO_INLINE_DECODE +// disables the inlining of the scalar codebook fast-huffman decode. +// might save a little codespace; useful for debugging +// #define STB_VORBIS_NO_INLINE_DECODE + +// STB_VORBIS_NO_DEFER_FLOOR +// Normally we only decode the floor without synthesizing the actual +// full curve. We can instead synthesize the curve immediately. This +// requires more memory and is very likely slower, so I don't think +// you'd ever want to do it except for debugging. +// #define STB_VORBIS_NO_DEFER_FLOOR + + + + +////////////////////////////////////////////////////////////////////////////// + +#ifdef STB_VORBIS_NO_PULLDATA_API + #define STB_VORBIS_NO_INTEGER_CONVERSION + #define STB_VORBIS_NO_STDIO +#endif + +#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO) + #define STB_VORBIS_NO_STDIO 1 +#endif + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT + + // only need endianness for fast-float-to-int, which we don't + // use for pushdata + + #ifndef STB_VORBIS_BIG_ENDIAN + #define STB_VORBIS_ENDIAN 0 + #else + #define STB_VORBIS_ENDIAN 1 + #endif + +#endif +#endif + + +#ifndef STB_VORBIS_NO_STDIO +#include +#endif + +#ifndef STB_VORBIS_NO_CRT + #include + #include + #include + #include + + // find definition of alloca if it's not in stdlib.h: + #if defined(_MSC_VER) || defined(__MINGW32__) + #include + #endif + #if defined(__linux__) || defined(__linux) || defined(__sun__) || defined(__EMSCRIPTEN__) || defined(__NEWLIB__) + #include + #endif +#else // STB_VORBIS_NO_CRT + #define NULL 0 + #define malloc(s) 0 + #define free(s) ((void) 0) + #define realloc(s) 0 +#endif // STB_VORBIS_NO_CRT + +#include + +#ifdef __MINGW32__ + // eff you mingw: + // "fixed": + // http://sourceforge.net/p/mingw-w64/mailman/message/32882927/ + // "no that broke the build, reverted, who cares about C": + // http://sourceforge.net/p/mingw-w64/mailman/message/32890381/ + #ifdef __forceinline + #undef __forceinline + #endif + #define __forceinline + #ifndef alloca + #define alloca __builtin_alloca + #endif +#elif !defined(_MSC_VER) + #if __GNUC__ + #define __forceinline inline + #else + #define __forceinline + #endif +#endif + +#if STB_VORBIS_MAX_CHANNELS > 256 +#error "Value of STB_VORBIS_MAX_CHANNELS outside of allowed range" +#endif + +#if STB_VORBIS_FAST_HUFFMAN_LENGTH > 24 +#error "Value of STB_VORBIS_FAST_HUFFMAN_LENGTH outside of allowed range" +#endif + + +#if 0 +#include +#define CHECK(f) _CrtIsValidHeapPointer(f->channel_buffers[1]) +#else +#define CHECK(f) ((void) 0) +#endif + +#define MAX_BLOCKSIZE_LOG 13 // from specification +#define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG) + + +typedef unsigned char uint8; +typedef signed char int8; +typedef unsigned short uint16; +typedef signed short int16; +typedef unsigned int uint32; +typedef signed int int32; + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +typedef float codetype; + +#ifdef _MSC_VER +#define STBV_NOTUSED(v) (void)(v) +#else +#define STBV_NOTUSED(v) (void)sizeof(v) +#endif + +// @NOTE +// +// Some arrays below are tagged "//varies", which means it's actually +// a variable-sized piece of data, but rather than malloc I assume it's +// small enough it's better to just allocate it all together with the +// main thing +// +// Most of the variables are specified with the smallest size I could pack +// them into. It might give better performance to make them all full-sized +// integers. It should be safe to freely rearrange the structures or change +// the sizes larger--nothing relies on silently truncating etc., nor the +// order of variables. + +#define FAST_HUFFMAN_TABLE_SIZE (1 << STB_VORBIS_FAST_HUFFMAN_LENGTH) +#define FAST_HUFFMAN_TABLE_MASK (FAST_HUFFMAN_TABLE_SIZE - 1) + +typedef struct +{ + int dimensions, entries; + uint8 *codeword_lengths; + float minimum_value; + float delta_value; + uint8 value_bits; + uint8 lookup_type; + uint8 sequence_p; + uint8 sparse; + uint32 lookup_values; + codetype *multiplicands; + uint32 *codewords; + #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT + int16 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; + #else + int32 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; + #endif + uint32 *sorted_codewords; + int *sorted_values; + int sorted_entries; +} Codebook; + +typedef struct +{ + uint8 order; + uint16 rate; + uint16 bark_map_size; + uint8 amplitude_bits; + uint8 amplitude_offset; + uint8 number_of_books; + uint8 book_list[16]; // varies +} Floor0; + +typedef struct +{ + uint8 partitions; + uint8 partition_class_list[32]; // varies + uint8 class_dimensions[16]; // varies + uint8 class_subclasses[16]; // varies + uint8 class_masterbooks[16]; // varies + int16 subclass_books[16][8]; // varies + uint16 Xlist[31*8+2]; // varies + uint8 sorted_order[31*8+2]; + uint8 neighbors[31*8+2][2]; + uint8 floor1_multiplier; + uint8 rangebits; + int values; +} Floor1; + +typedef union +{ + Floor0 floor0; + Floor1 floor1; +} Floor; + +typedef struct +{ + uint32 begin, end; + uint32 part_size; + uint8 classifications; + uint8 classbook; + uint8 **classdata; + int16 (*residue_books)[8]; +} Residue; + +typedef struct +{ + uint8 magnitude; + uint8 angle; + uint8 mux; +} MappingChannel; + +typedef struct +{ + uint16 coupling_steps; + MappingChannel *chan; + uint8 submaps; + uint8 submap_floor[15]; // varies + uint8 submap_residue[15]; // varies +} Mapping; + +typedef struct +{ + uint8 blockflag; + uint8 mapping; + uint16 windowtype; + uint16 transformtype; +} Mode; + +typedef struct +{ + uint32 goal_crc; // expected crc if match + int bytes_left; // bytes left in packet + uint32 crc_so_far; // running crc + int bytes_done; // bytes processed in _current_ chunk + uint32 sample_loc; // granule pos encoded in page +} CRCscan; + +typedef struct +{ + uint32 page_start, page_end; + uint32 last_decoded_sample; +} ProbedPage; + +struct stb_vorbis +{ + // user-accessible info + unsigned int sample_rate; + int channels; + + unsigned int setup_memory_required; + unsigned int temp_memory_required; + unsigned int setup_temp_memory_required; + + char *vendor; + int comment_list_length; + char **comment_list; + + // input config +#ifndef STB_VORBIS_NO_STDIO + FILE *f; + uint32 f_start; + int close_on_free; +#endif + + uint8 *stream; + uint8 *stream_start; + uint8 *stream_end; + + uint32 stream_len; + + uint8 push_mode; + + // the page to seek to when seeking to start, may be zero + uint32 first_audio_page_offset; + + // p_first is the page on which the first audio packet ends + // (but not necessarily the page on which it starts) + ProbedPage p_first, p_last; + + // memory management + stb_vorbis_alloc alloc; + int setup_offset; + int temp_offset; + + // run-time results + int eof; + enum STBVorbisError error; + + // user-useful data + + // header info + int blocksize[2]; + int blocksize_0, blocksize_1; + int codebook_count; + Codebook *codebooks; + int floor_count; + uint16 floor_types[64]; // varies + Floor *floor_config; + int residue_count; + uint16 residue_types[64]; // varies + Residue *residue_config; + int mapping_count; + Mapping *mapping; + int mode_count; + Mode mode_config[64]; // varies + + uint32 total_samples; + + // decode buffer + float *channel_buffers[STB_VORBIS_MAX_CHANNELS]; + float *outputs [STB_VORBIS_MAX_CHANNELS]; + + float *previous_window[STB_VORBIS_MAX_CHANNELS]; + int previous_length; + + #ifndef STB_VORBIS_NO_DEFER_FLOOR + int16 *finalY[STB_VORBIS_MAX_CHANNELS]; + #else + float *floor_buffers[STB_VORBIS_MAX_CHANNELS]; + #endif + + uint32 current_loc; // sample location of next frame to decode + int current_loc_valid; + + // per-blocksize precomputed data + + // twiddle factors + float *A[2],*B[2],*C[2]; + float *window[2]; + uint16 *bit_reverse[2]; + + // current page/packet/segment streaming info + uint32 serial; // stream serial number for verification + int last_page; + int segment_count; + uint8 segments[255]; + uint8 page_flag; + uint8 bytes_in_seg; + uint8 first_decode; + int next_seg; + int last_seg; // flag that we're on the last segment + int last_seg_which; // what was the segment number of the last seg? + uint32 acc; + int valid_bits; + int packet_bytes; + int end_seg_with_known_loc; + uint32 known_loc_for_packet; + int discard_samples_deferred; + uint32 samples_output; + + // push mode scanning + int page_crc_tests; // only in push_mode: number of tests active; -1 if not searching +#ifndef STB_VORBIS_NO_PUSHDATA_API + CRCscan scan[STB_VORBIS_PUSHDATA_CRC_COUNT]; +#endif + + // sample-access + int channel_buffer_start; + int channel_buffer_end; +}; + +#if defined(STB_VORBIS_NO_PUSHDATA_API) + #define IS_PUSH_MODE(f) FALSE +#elif defined(STB_VORBIS_NO_PULLDATA_API) + #define IS_PUSH_MODE(f) TRUE +#else + #define IS_PUSH_MODE(f) ((f)->push_mode) +#endif + +typedef struct stb_vorbis vorb; + +static int error(vorb *f, enum STBVorbisError e) +{ + f->error = e; + if (!f->eof && e != VORBIS_need_more_data) { + f->error=e; // breakpoint for debugging + } + return 0; +} + + +// these functions are used for allocating temporary memory +// while decoding. if you can afford the stack space, use +// alloca(); otherwise, provide a temp buffer and it will +// allocate out of those. + +#define array_size_required(count,size) (count*(sizeof(void *)+(size))) + +#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size)) +#define temp_free(f,p) (void)0 +#define temp_alloc_save(f) ((f)->temp_offset) +#define temp_alloc_restore(f,p) ((f)->temp_offset = (p)) + +#define temp_block_array(f,count,size) make_block_array(temp_alloc(f,array_size_required(count,size)), count, size) + +// given a sufficiently large block of memory, make an array of pointers to subblocks of it +static void *make_block_array(void *mem, int count, int size) +{ + int i; + void ** p = (void **) mem; + char *q = (char *) (p + count); + for (i=0; i < count; ++i) { + p[i] = q; + q += size; + } + return p; +} + +static void *setup_malloc(vorb *f, int sz) +{ + sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs. + f->setup_memory_required += sz; + if (f->alloc.alloc_buffer) { + void *p = (char *) f->alloc.alloc_buffer + f->setup_offset; + if (f->setup_offset + sz > f->temp_offset) return NULL; + f->setup_offset += sz; + return p; + } + return sz ? malloc(sz) : NULL; +} + +static void setup_free(vorb *f, void *p) +{ + if (f->alloc.alloc_buffer) return; // do nothing; setup mem is a stack + free(p); +} + +static void *setup_temp_malloc(vorb *f, int sz) +{ + sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs. + if (f->alloc.alloc_buffer) { + if (f->temp_offset - sz < f->setup_offset) return NULL; + f->temp_offset -= sz; + return (char *) f->alloc.alloc_buffer + f->temp_offset; + } + return malloc(sz); +} + +static void setup_temp_free(vorb *f, void *p, int sz) +{ + if (f->alloc.alloc_buffer) { + f->temp_offset += (sz+7)&~7; + return; + } + free(p); +} + +#define CRC32_POLY 0x04c11db7 // from spec + +static uint32 crc_table[256]; +static void crc32_init(void) +{ + int i,j; + uint32 s; + for(i=0; i < 256; i++) { + for (s=(uint32) i << 24, j=0; j < 8; ++j) + s = (s << 1) ^ (s >= (1U<<31) ? CRC32_POLY : 0); + crc_table[i] = s; + } +} + +static __forceinline uint32 crc32_update(uint32 crc, uint8 byte) +{ + return (crc << 8) ^ crc_table[byte ^ (crc >> 24)]; +} + + +// used in setup, and for huffman that doesn't go fast path +static unsigned int bit_reverse(unsigned int n) +{ + n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1); + n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2); + n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4); + n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8); + return (n >> 16) | (n << 16); +} + +static float square(float x) +{ + return x*x; +} + +// this is a weird definition of log2() for which log2(1) = 1, log2(2) = 2, log2(4) = 3 +// as required by the specification. fast(?) implementation from stb.h +// @OPTIMIZE: called multiple times per-packet with "constants"; move to setup +static int ilog(int32 n) +{ + static signed char log2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 }; + + if (n < 0) return 0; // signed n returns 0 + + // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29) + if (n < (1 << 14)) + if (n < (1 << 4)) return 0 + log2_4[n ]; + else if (n < (1 << 9)) return 5 + log2_4[n >> 5]; + else return 10 + log2_4[n >> 10]; + else if (n < (1 << 24)) + if (n < (1 << 19)) return 15 + log2_4[n >> 15]; + else return 20 + log2_4[n >> 20]; + else if (n < (1 << 29)) return 25 + log2_4[n >> 25]; + else return 30 + log2_4[n >> 30]; +} + +#ifndef M_PI + #define M_PI 3.14159265358979323846264f // from CRC +#endif + +// code length assigned to a value with no huffman encoding +#define NO_CODE 255 + +/////////////////////// LEAF SETUP FUNCTIONS ////////////////////////// +// +// these functions are only called at setup, and only a few times +// per file + +static float float32_unpack(uint32 x) +{ + // from the specification + uint32 mantissa = x & 0x1fffff; + uint32 sign = x & 0x80000000; + uint32 exp = (x & 0x7fe00000) >> 21; + double res = sign ? -(double)mantissa : (double)mantissa; + return (float) ldexp((float)res, (int)exp-788); +} + + +// zlib & jpeg huffman tables assume that the output symbols +// can either be arbitrarily arranged, or have monotonically +// increasing frequencies--they rely on the lengths being sorted; +// this makes for a very simple generation algorithm. +// vorbis allows a huffman table with non-sorted lengths. This +// requires a more sophisticated construction, since symbols in +// order do not map to huffman codes "in order". +static void add_entry(Codebook *c, uint32 huff_code, int symbol, int count, int len, uint32 *values) +{ + if (!c->sparse) { + c->codewords [symbol] = huff_code; + } else { + c->codewords [count] = huff_code; + c->codeword_lengths[count] = len; + values [count] = symbol; + } +} + +static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) +{ + int i,k,m=0; + uint32 available[32]; + + memset(available, 0, sizeof(available)); + // find the first entry + for (k=0; k < n; ++k) if (len[k] < NO_CODE) break; + if (k == n) { assert(c->sorted_entries == 0); return TRUE; } + assert(len[k] < 32); // no error return required, code reading lens checks this + // add to the list + add_entry(c, 0, k, m++, len[k], values); + // add all available leaves + for (i=1; i <= len[k]; ++i) + available[i] = 1U << (32-i); + // note that the above code treats the first case specially, + // but it's really the same as the following code, so they + // could probably be combined (except the initial code is 0, + // and I use 0 in available[] to mean 'empty') + for (i=k+1; i < n; ++i) { + uint32 res; + int z = len[i], y; + if (z == NO_CODE) continue; + assert(z < 32); // no error return required, code reading lens checks this + // find lowest available leaf (should always be earliest, + // which is what the specification calls for) + // note that this property, and the fact we can never have + // more than one free leaf at a given level, isn't totally + // trivial to prove, but it seems true and the assert never + // fires, so! + while (z > 0 && !available[z]) --z; + if (z == 0) { return FALSE; } + res = available[z]; + available[z] = 0; + add_entry(c, bit_reverse(res), i, m++, len[i], values); + // propagate availability up the tree + if (z != len[i]) { + for (y=len[i]; y > z; --y) { + assert(available[y] == 0); + available[y] = res + (1 << (32-y)); + } + } + } + return TRUE; +} + +// accelerated huffman table allows fast O(1) match of all symbols +// of length <= STB_VORBIS_FAST_HUFFMAN_LENGTH +static void compute_accelerated_huffman(Codebook *c) +{ + int i, len; + for (i=0; i < FAST_HUFFMAN_TABLE_SIZE; ++i) + c->fast_huffman[i] = -1; + + len = c->sparse ? c->sorted_entries : c->entries; + #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT + if (len > 32767) len = 32767; // largest possible value we can encode! + #endif + for (i=0; i < len; ++i) { + if (c->codeword_lengths[i] <= STB_VORBIS_FAST_HUFFMAN_LENGTH) { + uint32 z = c->sparse ? bit_reverse(c->sorted_codewords[i]) : c->codewords[i]; + // set table entries for all bit combinations in the higher bits + while (z < FAST_HUFFMAN_TABLE_SIZE) { + c->fast_huffman[z] = i; + z += 1 << c->codeword_lengths[i]; + } + } + } +} + +#ifdef _MSC_VER +#define STBV_CDECL __cdecl +#else +#define STBV_CDECL +#endif + +static int STBV_CDECL uint32_compare(const void *p, const void *q) +{ + uint32 x = * (uint32 *) p; + uint32 y = * (uint32 *) q; + return x < y ? -1 : x > y; +} + +static int include_in_sort(Codebook *c, uint8 len) +{ + if (c->sparse) { assert(len != NO_CODE); return TRUE; } + if (len == NO_CODE) return FALSE; + if (len > STB_VORBIS_FAST_HUFFMAN_LENGTH) return TRUE; + return FALSE; +} + +// if the fast table above doesn't work, we want to binary +// search them... need to reverse the bits +static void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values) +{ + int i, len; + // build a list of all the entries + // OPTIMIZATION: don't include the short ones, since they'll be caught by FAST_HUFFMAN. + // this is kind of a frivolous optimization--I don't see any performance improvement, + // but it's like 4 extra lines of code, so. + if (!c->sparse) { + int k = 0; + for (i=0; i < c->entries; ++i) + if (include_in_sort(c, lengths[i])) + c->sorted_codewords[k++] = bit_reverse(c->codewords[i]); + assert(k == c->sorted_entries); + } else { + for (i=0; i < c->sorted_entries; ++i) + c->sorted_codewords[i] = bit_reverse(c->codewords[i]); + } + + qsort(c->sorted_codewords, c->sorted_entries, sizeof(c->sorted_codewords[0]), uint32_compare); + c->sorted_codewords[c->sorted_entries] = 0xffffffff; + + len = c->sparse ? c->sorted_entries : c->entries; + // now we need to indicate how they correspond; we could either + // #1: sort a different data structure that says who they correspond to + // #2: for each sorted entry, search the original list to find who corresponds + // #3: for each original entry, find the sorted entry + // #1 requires extra storage, #2 is slow, #3 can use binary search! + for (i=0; i < len; ++i) { + int huff_len = c->sparse ? lengths[values[i]] : lengths[i]; + if (include_in_sort(c,huff_len)) { + uint32 code = bit_reverse(c->codewords[i]); + int x=0, n=c->sorted_entries; + while (n > 1) { + // invariant: sc[x] <= code < sc[x+n] + int m = x + (n >> 1); + if (c->sorted_codewords[m] <= code) { + x = m; + n -= (n>>1); + } else { + n >>= 1; + } + } + assert(c->sorted_codewords[x] == code); + if (c->sparse) { + c->sorted_values[x] = values[i]; + c->codeword_lengths[x] = huff_len; + } else { + c->sorted_values[x] = i; + } + } + } +} + +// only run while parsing the header (3 times) +static int vorbis_validate(uint8 *data) +{ + static uint8 vorbis[6] = { 'v', 'o', 'r', 'b', 'i', 's' }; + return memcmp(data, vorbis, 6) == 0; +} + +// called from setup only, once per code book +// (formula implied by specification) +static int lookup1_values(int entries, int dim) +{ + int r = (int) floor(exp((float) log((float) entries) / dim)); + if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning; + ++r; // floor() to avoid _ftol() when non-CRT + if (pow((float) r+1, dim) <= entries) + return -1; + if ((int) floor(pow((float) r, dim)) > entries) + return -1; + return r; +} + +// called twice per file +static void compute_twiddle_factors(int n, float *A, float *B, float *C) +{ + int n4 = n >> 2, n8 = n >> 3; + int k,k2; + + for (k=k2=0; k < n4; ++k,k2+=2) { + A[k2 ] = (float) cos(4*k*M_PI/n); + A[k2+1] = (float) -sin(4*k*M_PI/n); + B[k2 ] = (float) cos((k2+1)*M_PI/n/2) * 0.5f; + B[k2+1] = (float) sin((k2+1)*M_PI/n/2) * 0.5f; + } + for (k=k2=0; k < n8; ++k,k2+=2) { + C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); + C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); + } +} + +static void compute_window(int n, float *window) +{ + int n2 = n >> 1, i; + for (i=0; i < n2; ++i) + window[i] = (float) sin(0.5 * M_PI * square((float) sin((i - 0 + 0.5) / n2 * 0.5 * M_PI))); +} + +static void compute_bitreverse(int n, uint16 *rev) +{ + int ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + int i, n8 = n >> 3; + for (i=0; i < n8; ++i) + rev[i] = (bit_reverse(i) >> (32-ld+3)) << 2; +} + +static int init_blocksize(vorb *f, int b, int n) +{ + int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3; + f->A[b] = (float *) setup_malloc(f, sizeof(float) * n2); + f->B[b] = (float *) setup_malloc(f, sizeof(float) * n2); + f->C[b] = (float *) setup_malloc(f, sizeof(float) * n4); + if (!f->A[b] || !f->B[b] || !f->C[b]) return error(f, VORBIS_outofmem); + compute_twiddle_factors(n, f->A[b], f->B[b], f->C[b]); + f->window[b] = (float *) setup_malloc(f, sizeof(float) * n2); + if (!f->window[b]) return error(f, VORBIS_outofmem); + compute_window(n, f->window[b]); + f->bit_reverse[b] = (uint16 *) setup_malloc(f, sizeof(uint16) * n8); + if (!f->bit_reverse[b]) return error(f, VORBIS_outofmem); + compute_bitreverse(n, f->bit_reverse[b]); + return TRUE; +} + +static void neighbors(uint16 *x, int n, int *plow, int *phigh) +{ + int low = -1; + int high = 65536; + int i; + for (i=0; i < n; ++i) { + if (x[i] > low && x[i] < x[n]) { *plow = i; low = x[i]; } + if (x[i] < high && x[i] > x[n]) { *phigh = i; high = x[i]; } + } +} + +// this has been repurposed so y is now the original index instead of y +typedef struct +{ + uint16 x,id; +} stbv__floor_ordering; + +static int STBV_CDECL point_compare(const void *p, const void *q) +{ + stbv__floor_ordering *a = (stbv__floor_ordering *) p; + stbv__floor_ordering *b = (stbv__floor_ordering *) q; + return a->x < b->x ? -1 : a->x > b->x; +} + +// +/////////////////////// END LEAF SETUP FUNCTIONS ////////////////////////// + + +#if defined(STB_VORBIS_NO_STDIO) + #define USE_MEMORY(z) TRUE +#else + #define USE_MEMORY(z) ((z)->stream) +#endif + +static uint8 get8(vorb *z) +{ + if (USE_MEMORY(z)) { + if (z->stream >= z->stream_end) { z->eof = TRUE; return 0; } + return *z->stream++; + } + + #ifndef STB_VORBIS_NO_STDIO + { + int c = fgetc(z->f); + if (c == EOF) { z->eof = TRUE; return 0; } + return c; + } + #endif +} + +static uint32 get32(vorb *f) +{ + uint32 x; + x = get8(f); + x += get8(f) << 8; + x += get8(f) << 16; + x += (uint32) get8(f) << 24; + return x; +} + +static int getn(vorb *z, uint8 *data, int n) +{ + if (USE_MEMORY(z)) { + if (z->stream+n > z->stream_end) { z->eof = 1; return 0; } + memcpy(data, z->stream, n); + z->stream += n; + return 1; + } + + #ifndef STB_VORBIS_NO_STDIO + if (fread(data, n, 1, z->f) == 1) + return 1; + else { + z->eof = 1; + return 0; + } + #endif +} + +static void skip(vorb *z, int n) +{ + if (USE_MEMORY(z)) { + z->stream += n; + if (z->stream >= z->stream_end) z->eof = 1; + return; + } + #ifndef STB_VORBIS_NO_STDIO + { + long x = ftell(z->f); + fseek(z->f, x+n, SEEK_SET); + } + #endif +} + +static int set_file_offset(stb_vorbis *f, unsigned int loc) +{ + #ifndef STB_VORBIS_NO_PUSHDATA_API + if (f->push_mode) return 0; + #endif + f->eof = 0; + if (USE_MEMORY(f)) { + if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) { + f->stream = f->stream_end; + f->eof = 1; + return 0; + } else { + f->stream = f->stream_start + loc; + return 1; + } + } + #ifndef STB_VORBIS_NO_STDIO + if (loc + f->f_start < loc || loc >= 0x80000000) { + loc = 0x7fffffff; + f->eof = 1; + } else { + loc += f->f_start; + } + if (!fseek(f->f, loc, SEEK_SET)) + return 1; + f->eof = 1; + fseek(f->f, f->f_start, SEEK_END); + return 0; + #endif +} + + +static uint8 ogg_page_header[4] = { 0x4f, 0x67, 0x67, 0x53 }; + +static int capture_pattern(vorb *f) +{ + if (0x4f != get8(f)) return FALSE; + if (0x67 != get8(f)) return FALSE; + if (0x67 != get8(f)) return FALSE; + if (0x53 != get8(f)) return FALSE; + return TRUE; +} + +#define PAGEFLAG_continued_packet 1 +#define PAGEFLAG_first_page 2 +#define PAGEFLAG_last_page 4 + +static int start_page_no_capturepattern(vorb *f) +{ + uint32 loc0,loc1,n; + if (f->first_decode && !IS_PUSH_MODE(f)) { + f->p_first.page_start = stb_vorbis_get_file_offset(f) - 4; + } + // stream structure version + if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version); + // header flag + f->page_flag = get8(f); + // absolute granule position + loc0 = get32(f); + loc1 = get32(f); + // @TODO: validate loc0,loc1 as valid positions? + // stream serial number -- vorbis doesn't interleave, so discard + get32(f); + //if (f->serial != get32(f)) return error(f, VORBIS_incorrect_stream_serial_number); + // page sequence number + n = get32(f); + f->last_page = n; + // CRC32 + get32(f); + // page_segments + f->segment_count = get8(f); + if (!getn(f, f->segments, f->segment_count)) + return error(f, VORBIS_unexpected_eof); + // assume we _don't_ know any the sample position of any segments + f->end_seg_with_known_loc = -2; + if (loc0 != ~0U || loc1 != ~0U) { + int i; + // determine which packet is the last one that will complete + for (i=f->segment_count-1; i >= 0; --i) + if (f->segments[i] < 255) + break; + // 'i' is now the index of the _last_ segment of a packet that ends + if (i >= 0) { + f->end_seg_with_known_loc = i; + f->known_loc_for_packet = loc0; + } + } + if (f->first_decode) { + int i,len; + len = 0; + for (i=0; i < f->segment_count; ++i) + len += f->segments[i]; + len += 27 + f->segment_count; + f->p_first.page_end = f->p_first.page_start + len; + f->p_first.last_decoded_sample = loc0; + } + f->next_seg = 0; + return TRUE; +} + +static int start_page(vorb *f) +{ + if (!capture_pattern(f)) return error(f, VORBIS_missing_capture_pattern); + return start_page_no_capturepattern(f); +} + +static int start_packet(vorb *f) +{ + while (f->next_seg == -1) { + if (!start_page(f)) return FALSE; + if (f->page_flag & PAGEFLAG_continued_packet) + return error(f, VORBIS_continued_packet_flag_invalid); + } + f->last_seg = FALSE; + f->valid_bits = 0; + f->packet_bytes = 0; + f->bytes_in_seg = 0; + // f->next_seg is now valid + return TRUE; +} + +static int maybe_start_packet(vorb *f) +{ + if (f->next_seg == -1) { + int x = get8(f); + if (f->eof) return FALSE; // EOF at page boundary is not an error! + if (0x4f != x ) return error(f, VORBIS_missing_capture_pattern); + if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (0x53 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (!start_page_no_capturepattern(f)) return FALSE; + if (f->page_flag & PAGEFLAG_continued_packet) { + // set up enough state that we can read this packet if we want, + // e.g. during recovery + f->last_seg = FALSE; + f->bytes_in_seg = 0; + return error(f, VORBIS_continued_packet_flag_invalid); + } + } + return start_packet(f); +} + +static int next_segment(vorb *f) +{ + int len; + if (f->last_seg) return 0; + if (f->next_seg == -1) { + f->last_seg_which = f->segment_count-1; // in case start_page fails + if (!start_page(f)) { f->last_seg = 1; return 0; } + if (!(f->page_flag & PAGEFLAG_continued_packet)) return error(f, VORBIS_continued_packet_flag_invalid); + } + len = f->segments[f->next_seg++]; + if (len < 255) { + f->last_seg = TRUE; + f->last_seg_which = f->next_seg-1; + } + if (f->next_seg >= f->segment_count) + f->next_seg = -1; + assert(f->bytes_in_seg == 0); + f->bytes_in_seg = len; + return len; +} + +#define EOP (-1) +#define INVALID_BITS (-1) + +static int get8_packet_raw(vorb *f) +{ + if (!f->bytes_in_seg) { // CLANG! + if (f->last_seg) return EOP; + else if (!next_segment(f)) return EOP; + } + assert(f->bytes_in_seg > 0); + --f->bytes_in_seg; + ++f->packet_bytes; + return get8(f); +} + +static int get8_packet(vorb *f) +{ + int x = get8_packet_raw(f); + f->valid_bits = 0; + return x; +} + +static int get32_packet(vorb *f) +{ + uint32 x; + x = get8_packet(f); + x += get8_packet(f) << 8; + x += get8_packet(f) << 16; + x += (uint32) get8_packet(f) << 24; + return x; +} + +static void flush_packet(vorb *f) +{ + while (get8_packet_raw(f) != EOP); +} + +// @OPTIMIZE: this is the secondary bit decoder, so it's probably not as important +// as the huffman decoder? +static uint32 get_bits(vorb *f, int n) +{ + uint32 z; + + if (f->valid_bits < 0) return 0; + if (f->valid_bits < n) { + if (n > 24) { + // the accumulator technique below would not work correctly in this case + z = get_bits(f, 24); + z += get_bits(f, n-24) << 24; + return z; + } + if (f->valid_bits == 0) f->acc = 0; + while (f->valid_bits < n) { + int z = get8_packet_raw(f); + if (z == EOP) { + f->valid_bits = INVALID_BITS; + return 0; + } + f->acc += z << f->valid_bits; + f->valid_bits += 8; + } + } + + assert(f->valid_bits >= n); + z = f->acc & ((1 << n)-1); + f->acc >>= n; + f->valid_bits -= n; + return z; +} + +// @OPTIMIZE: primary accumulator for huffman +// expand the buffer to as many bits as possible without reading off end of packet +// it might be nice to allow f->valid_bits and f->acc to be stored in registers, +// e.g. cache them locally and decode locally +static __forceinline void prep_huffman(vorb *f) +{ + if (f->valid_bits <= 24) { + if (f->valid_bits == 0) f->acc = 0; + do { + int z; + if (f->last_seg && !f->bytes_in_seg) return; + z = get8_packet_raw(f); + if (z == EOP) return; + f->acc += (unsigned) z << f->valid_bits; + f->valid_bits += 8; + } while (f->valid_bits <= 24); + } +} + +enum +{ + VORBIS_packet_id = 1, + VORBIS_packet_comment = 3, + VORBIS_packet_setup = 5 +}; + +static int codebook_decode_scalar_raw(vorb *f, Codebook *c) +{ + int i; + prep_huffman(f); + + if (c->codewords == NULL && c->sorted_codewords == NULL) + return -1; + + // cases to use binary search: sorted_codewords && !c->codewords + // sorted_codewords && c->entries > 8 + if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) { + // binary search + uint32 code = bit_reverse(f->acc); + int x=0, n=c->sorted_entries, len; + + while (n > 1) { + // invariant: sc[x] <= code < sc[x+n] + int m = x + (n >> 1); + if (c->sorted_codewords[m] <= code) { + x = m; + n -= (n>>1); + } else { + n >>= 1; + } + } + // x is now the sorted index + if (!c->sparse) x = c->sorted_values[x]; + // x is now sorted index if sparse, or symbol otherwise + len = c->codeword_lengths[x]; + if (f->valid_bits >= len) { + f->acc >>= len; + f->valid_bits -= len; + return x; + } + + f->valid_bits = 0; + return -1; + } + + // if small, linear search + assert(!c->sparse); + for (i=0; i < c->entries; ++i) { + if (c->codeword_lengths[i] == NO_CODE) continue; + if (c->codewords[i] == (f->acc & ((1 << c->codeword_lengths[i])-1))) { + if (f->valid_bits >= c->codeword_lengths[i]) { + f->acc >>= c->codeword_lengths[i]; + f->valid_bits -= c->codeword_lengths[i]; + return i; + } + f->valid_bits = 0; + return -1; + } + } + + error(f, VORBIS_invalid_stream); + f->valid_bits = 0; + return -1; +} + +#ifndef STB_VORBIS_NO_INLINE_DECODE + +#define DECODE_RAW(var, f,c) \ + if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) \ + prep_huffman(f); \ + var = f->acc & FAST_HUFFMAN_TABLE_MASK; \ + var = c->fast_huffman[var]; \ + if (var >= 0) { \ + int n = c->codeword_lengths[var]; \ + f->acc >>= n; \ + f->valid_bits -= n; \ + if (f->valid_bits < 0) { f->valid_bits = 0; var = -1; } \ + } else { \ + var = codebook_decode_scalar_raw(f,c); \ + } + +#else + +static int codebook_decode_scalar(vorb *f, Codebook *c) +{ + int i; + if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) + prep_huffman(f); + // fast huffman table lookup + i = f->acc & FAST_HUFFMAN_TABLE_MASK; + i = c->fast_huffman[i]; + if (i >= 0) { + f->acc >>= c->codeword_lengths[i]; + f->valid_bits -= c->codeword_lengths[i]; + if (f->valid_bits < 0) { f->valid_bits = 0; return -1; } + return i; + } + return codebook_decode_scalar_raw(f,c); +} + +#define DECODE_RAW(var,f,c) var = codebook_decode_scalar(f,c); + +#endif + +#define DECODE(var,f,c) \ + DECODE_RAW(var,f,c) \ + if (c->sparse) var = c->sorted_values[var]; + +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + #define DECODE_VQ(var,f,c) DECODE_RAW(var,f,c) +#else + #define DECODE_VQ(var,f,c) DECODE(var,f,c) +#endif + + + + + + +// CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case +// where we avoid one addition +#define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off]) +#define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off]) +#define CODEBOOK_ELEMENT_BASE(c) (0) + +static int codebook_decode_start(vorb *f, Codebook *c) +{ + int z = -1; + + // type 0 is only legal in a scalar context + if (c->lookup_type == 0) + error(f, VORBIS_invalid_stream); + else { + DECODE_VQ(z,f,c); + if (c->sparse) assert(z < c->sorted_entries); + if (z < 0) { // check for EOP + if (!f->bytes_in_seg) + if (f->last_seg) + return z; + error(f, VORBIS_invalid_stream); + } + } + return z; +} + +static int codebook_decode(vorb *f, Codebook *c, float *output, int len) +{ + int i,z = codebook_decode_start(f,c); + if (z < 0) return FALSE; + if (len > c->dimensions) len = c->dimensions; + +#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + float last = CODEBOOK_ELEMENT_BASE(c); + int div = 1; + for (i=0; i < len; ++i) { + int off = (z / div) % c->lookup_values; + float val = CODEBOOK_ELEMENT_FAST(c,off) + last; + output[i] += val; + if (c->sequence_p) last = val + c->minimum_value; + div *= c->lookup_values; + } + return TRUE; + } +#endif + + z *= c->dimensions; + if (c->sequence_p) { + float last = CODEBOOK_ELEMENT_BASE(c); + for (i=0; i < len; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + output[i] += val; + last = val + c->minimum_value; + } + } else { + float last = CODEBOOK_ELEMENT_BASE(c); + for (i=0; i < len; ++i) { + output[i] += CODEBOOK_ELEMENT_FAST(c,z+i) + last; + } + } + + return TRUE; +} + +static int codebook_decode_step(vorb *f, Codebook *c, float *output, int len, int step) +{ + int i,z = codebook_decode_start(f,c); + float last = CODEBOOK_ELEMENT_BASE(c); + if (z < 0) return FALSE; + if (len > c->dimensions) len = c->dimensions; + +#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + int div = 1; + for (i=0; i < len; ++i) { + int off = (z / div) % c->lookup_values; + float val = CODEBOOK_ELEMENT_FAST(c,off) + last; + output[i*step] += val; + if (c->sequence_p) last = val; + div *= c->lookup_values; + } + return TRUE; + } +#endif + + z *= c->dimensions; + for (i=0; i < len; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + output[i*step] += val; + if (c->sequence_p) last = val; + } + + return TRUE; +} + +static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **outputs, int ch, int *c_inter_p, int *p_inter_p, int len, int total_decode) +{ + int c_inter = *c_inter_p; + int p_inter = *p_inter_p; + int i,z, effective = c->dimensions; + + // type 0 is only legal in a scalar context + if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); + + while (total_decode > 0) { + float last = CODEBOOK_ELEMENT_BASE(c); + DECODE_VQ(z,f,c); + #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + assert(!c->sparse || z < c->sorted_entries); + #endif + if (z < 0) { + if (!f->bytes_in_seg) + if (f->last_seg) return FALSE; + return error(f, VORBIS_invalid_stream); + } + + // if this will take us off the end of the buffers, stop short! + // we check by computing the length of the virtual interleaved + // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), + // and the length we'll be using (effective) + if (c_inter + p_inter*ch + effective > len * ch) { + effective = len*ch - (p_inter*ch - c_inter); + } + + #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + int div = 1; + for (i=0; i < effective; ++i) { + int off = (z / div) % c->lookup_values; + float val = CODEBOOK_ELEMENT_FAST(c,off) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) { c_inter = 0; ++p_inter; } + if (c->sequence_p) last = val; + div *= c->lookup_values; + } + } else + #endif + { + z *= c->dimensions; + if (c->sequence_p) { + for (i=0; i < effective; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) { c_inter = 0; ++p_inter; } + last = val; + } + } else { + for (i=0; i < effective; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) { c_inter = 0; ++p_inter; } + } + } + } + + total_decode -= effective; + } + *c_inter_p = c_inter; + *p_inter_p = p_inter; + return TRUE; +} + +static int predict_point(int x, int x0, int x1, int y0, int y1) +{ + int dy = y1 - y0; + int adx = x1 - x0; + // @OPTIMIZE: force int division to round in the right direction... is this necessary on x86? + int err = abs(dy) * (x - x0); + int off = err / adx; + return dy < 0 ? y0 - off : y0 + off; +} + +// the following table is block-copied from the specification +static float inverse_db_table[256] = +{ + 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, + 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, + 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, + 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, + 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, + 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, + 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, + 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, + 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, + 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, + 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, + 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, + 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, + 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, + 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, + 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, + 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, + 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, + 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, + 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, + 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, + 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, + 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, + 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, + 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, + 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, + 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, + 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, + 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, + 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, + 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, + 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, + 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, + 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, + 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, + 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, + 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f, + 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f, + 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, + 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f, + 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f, + 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f, + 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f, + 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f, + 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f, + 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f, + 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, + 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f, + 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f, + 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f, + 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f, + 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f, + 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f, + 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f, + 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f, + 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, + 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f, + 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f, + 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f, + 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f, + 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f, + 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f, + 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f, + 0.82788260f, 0.88168307f, 0.9389798f, 1.0f +}; + + +// @OPTIMIZE: if you want to replace this bresenham line-drawing routine, +// note that you must produce bit-identical output to decode correctly; +// this specific sequence of operations is specified in the spec (it's +// drawing integer-quantized frequency-space lines that the encoder +// expects to be exactly the same) +// ... also, isn't the whole point of Bresenham's algorithm to NOT +// have to divide in the setup? sigh. +#ifndef STB_VORBIS_NO_DEFER_FLOOR +#define LINE_OP(a,b) a *= b +#else +#define LINE_OP(a,b) a = b +#endif + +#ifdef STB_VORBIS_DIVIDE_TABLE +#define DIVTAB_NUMER 32 +#define DIVTAB_DENOM 64 +int8 integer_divide_table[DIVTAB_NUMER][DIVTAB_DENOM]; // 2KB +#endif + +static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y1, int n) +{ + int dy = y1 - y0; + int adx = x1 - x0; + int ady = abs(dy); + int base; + int x=x0,y=y0; + int err = 0; + int sy; + +#ifdef STB_VORBIS_DIVIDE_TABLE + if (adx < DIVTAB_DENOM && ady < DIVTAB_NUMER) { + if (dy < 0) { + base = -integer_divide_table[ady][adx]; + sy = base-1; + } else { + base = integer_divide_table[ady][adx]; + sy = base+1; + } + } else { + base = dy / adx; + if (dy < 0) + sy = base - 1; + else + sy = base+1; + } +#else + base = dy / adx; + if (dy < 0) + sy = base - 1; + else + sy = base+1; +#endif + ady -= abs(base) * adx; + if (x1 > n) x1 = n; + if (x < x1) { + LINE_OP(output[x], inverse_db_table[y&255]); + for (++x; x < x1; ++x) { + err += ady; + if (err >= adx) { + err -= adx; + y += sy; + } else + y += base; + LINE_OP(output[x], inverse_db_table[y&255]); + } + } +} + +static int residue_decode(vorb *f, Codebook *book, float *target, int offset, int n, int rtype) +{ + int k; + if (rtype == 0) { + int step = n / book->dimensions; + for (k=0; k < step; ++k) + if (!codebook_decode_step(f, book, target+offset+k, n-offset-k, step)) + return FALSE; + } else { + for (k=0; k < n; ) { + if (!codebook_decode(f, book, target+offset, n-k)) + return FALSE; + k += book->dimensions; + offset += book->dimensions; + } + } + return TRUE; +} + +// n is 1/2 of the blocksize -- +// specification: "Correct per-vector decode length is [n]/2" +static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode) +{ + int i,j,pass; + Residue *r = f->residue_config + rn; + int rtype = f->residue_types[rn]; + int c = r->classbook; + int classwords = f->codebooks[c].dimensions; + unsigned int actual_size = rtype == 2 ? n*2 : n; + unsigned int limit_r_begin = (r->begin < actual_size ? r->begin : actual_size); + unsigned int limit_r_end = (r->end < actual_size ? r->end : actual_size); + int n_read = limit_r_end - limit_r_begin; + int part_read = n_read / r->part_size; + int temp_alloc_point = temp_alloc_save(f); + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + uint8 ***part_classdata = (uint8 ***) temp_block_array(f,f->channels, part_read * sizeof(**part_classdata)); + #else + int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications)); + #endif + + CHECK(f); + + for (i=0; i < ch; ++i) + if (!do_not_decode[i]) + memset(residue_buffers[i], 0, sizeof(float) * n); + + if (rtype == 2 && ch != 1) { + for (j=0; j < ch; ++j) + if (!do_not_decode[j]) + break; + if (j == ch) + goto done; + + for (pass=0; pass < 8; ++pass) { + int pcount = 0, class_set = 0; + if (ch == 2) { + while (pcount < part_read) { + int z = r->begin + pcount*r->part_size; + int c_inter = (z & 1), p_inter = z>>1; + if (pass == 0) { + Codebook *c = f->codebooks+r->classbook; + int q; + DECODE(q,f,c); + if (q == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[0][i+pcount] = q % r->classifications; + q /= r->classifications; + } + #endif + } + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + int z = r->begin + pcount*r->part_size; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; + #else + int c = classifications[0][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + Codebook *book = f->codebooks + b; + #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) + goto done; + #else + // saves 1% + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) + goto done; + #endif + } else { + z += r->part_size; + c_inter = z & 1; + p_inter = z >> 1; + } + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } else if (ch > 2) { + while (pcount < part_read) { + int z = r->begin + pcount*r->part_size; + int c_inter = z % ch, p_inter = z/ch; + if (pass == 0) { + Codebook *c = f->codebooks+r->classbook; + int q; + DECODE(q,f,c); + if (q == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[0][i+pcount] = q % r->classifications; + q /= r->classifications; + } + #endif + } + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + int z = r->begin + pcount*r->part_size; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; + #else + int c = classifications[0][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + Codebook *book = f->codebooks + b; + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) + goto done; + } else { + z += r->part_size; + c_inter = z % ch; + p_inter = z / ch; + } + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } + } + goto done; + } + CHECK(f); + + for (pass=0; pass < 8; ++pass) { + int pcount = 0, class_set=0; + while (pcount < part_read) { + if (pass == 0) { + for (j=0; j < ch; ++j) { + if (!do_not_decode[j]) { + Codebook *c = f->codebooks+r->classbook; + int temp; + DECODE(temp,f,c); + if (temp == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[j][class_set] = r->classdata[temp]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[j][i+pcount] = temp % r->classifications; + temp /= r->classifications; + } + #endif + } + } + } + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + for (j=0; j < ch; ++j) { + if (!do_not_decode[j]) { + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[j][class_set][i]; + #else + int c = classifications[j][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + float *target = residue_buffers[j]; + int offset = r->begin + pcount * r->part_size; + int n = r->part_size; + Codebook *book = f->codebooks + b; + if (!residue_decode(f, book, target, offset, n, rtype)) + goto done; + } + } + } + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } + done: + CHECK(f); + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + temp_free(f,part_classdata); + #else + temp_free(f,classifications); + #endif + temp_alloc_restore(f,temp_alloc_point); +} + + +#if 0 +// slow way for debugging +void inverse_mdct_slow(float *buffer, int n) +{ + int i,j; + int n2 = n >> 1; + float *x = (float *) malloc(sizeof(*x) * n2); + memcpy(x, buffer, sizeof(*x) * n2); + for (i=0; i < n; ++i) { + float acc = 0; + for (j=0; j < n2; ++j) + // formula from paper: + //acc += n/4.0f * x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1)); + // formula from wikipedia + //acc += 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5)); + // these are equivalent, except the formula from the paper inverts the multiplier! + // however, what actually works is NO MULTIPLIER!?! + //acc += 64 * 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5)); + acc += x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1)); + buffer[i] = acc; + } + free(x); +} +#elif 0 +// same as above, but just barely able to run in real time on modern machines +void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) +{ + float mcos[16384]; + int i,j; + int n2 = n >> 1, nmask = (n << 2) -1; + float *x = (float *) malloc(sizeof(*x) * n2); + memcpy(x, buffer, sizeof(*x) * n2); + for (i=0; i < 4*n; ++i) + mcos[i] = (float) cos(M_PI / 2 * i / n); + + for (i=0; i < n; ++i) { + float acc = 0; + for (j=0; j < n2; ++j) + acc += x[j] * mcos[(2 * i + 1 + n2)*(2*j+1) & nmask]; + buffer[i] = acc; + } + free(x); +} +#elif 0 +// transform to use a slow dct-iv; this is STILL basically trivial, +// but only requires half as many ops +void dct_iv_slow(float *buffer, int n) +{ + float mcos[16384]; + float x[2048]; + int i,j; + int n2 = n >> 1, nmask = (n << 3) - 1; + memcpy(x, buffer, sizeof(*x) * n); + for (i=0; i < 8*n; ++i) + mcos[i] = (float) cos(M_PI / 4 * i / n); + for (i=0; i < n; ++i) { + float acc = 0; + for (j=0; j < n; ++j) + acc += x[j] * mcos[((2 * i + 1)*(2*j+1)) & nmask]; + buffer[i] = acc; + } +} + +void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) +{ + int i, n4 = n >> 2, n2 = n >> 1, n3_4 = n - n4; + float temp[4096]; + + memcpy(temp, buffer, n2 * sizeof(float)); + dct_iv_slow(temp, n2); // returns -c'-d, a-b' + + for (i=0; i < n4 ; ++i) buffer[i] = temp[i+n4]; // a-b' + for ( ; i < n3_4; ++i) buffer[i] = -temp[n3_4 - i - 1]; // b-a', c+d' + for ( ; i < n ; ++i) buffer[i] = -temp[i - n3_4]; // c'+d +} +#endif + +#ifndef LIBVORBIS_MDCT +#define LIBVORBIS_MDCT 0 +#endif + +#if LIBVORBIS_MDCT +// directly call the vorbis MDCT using an interface documented +// by Jeff Roberts... useful for performance comparison +typedef struct +{ + int n; + int log2n; + + float *trig; + int *bitrev; + + float scale; +} mdct_lookup; + +extern void mdct_init(mdct_lookup *lookup, int n); +extern void mdct_clear(mdct_lookup *l); +extern void mdct_backward(mdct_lookup *init, float *in, float *out); + +mdct_lookup M1,M2; + +void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) +{ + mdct_lookup *M; + if (M1.n == n) M = &M1; + else if (M2.n == n) M = &M2; + else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; } + else { + if (M2.n) __asm int 3; + mdct_init(&M2, n); + M = &M2; + } + + mdct_backward(M, buffer, buffer); +} +#endif + + +// the following were split out into separate functions while optimizing; +// they could be pushed back up but eh. __forceinline showed no change; +// they're probably already being inlined. +static void imdct_step3_iter0_loop(int n, float *e, int i_off, int k_off, float *A) +{ + float *ee0 = e + i_off; + float *ee2 = ee0 + k_off; + int i; + + assert((n & 3) == 0); + for (i=(n>>2); i > 0; --i) { + float k00_20, k01_21; + k00_20 = ee0[ 0] - ee2[ 0]; + k01_21 = ee0[-1] - ee2[-1]; + ee0[ 0] += ee2[ 0];//ee0[ 0] = ee0[ 0] + ee2[ 0]; + ee0[-1] += ee2[-1];//ee0[-1] = ee0[-1] + ee2[-1]; + ee2[ 0] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-1] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + + k00_20 = ee0[-2] - ee2[-2]; + k01_21 = ee0[-3] - ee2[-3]; + ee0[-2] += ee2[-2];//ee0[-2] = ee0[-2] + ee2[-2]; + ee0[-3] += ee2[-3];//ee0[-3] = ee0[-3] + ee2[-3]; + ee2[-2] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-3] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + + k00_20 = ee0[-4] - ee2[-4]; + k01_21 = ee0[-5] - ee2[-5]; + ee0[-4] += ee2[-4];//ee0[-4] = ee0[-4] + ee2[-4]; + ee0[-5] += ee2[-5];//ee0[-5] = ee0[-5] + ee2[-5]; + ee2[-4] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-5] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + + k00_20 = ee0[-6] - ee2[-6]; + k01_21 = ee0[-7] - ee2[-7]; + ee0[-6] += ee2[-6];//ee0[-6] = ee0[-6] + ee2[-6]; + ee0[-7] += ee2[-7];//ee0[-7] = ee0[-7] + ee2[-7]; + ee2[-6] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-7] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + ee0 -= 8; + ee2 -= 8; + } +} + +static void imdct_step3_inner_r_loop(int lim, float *e, int d0, int k_off, float *A, int k1) +{ + int i; + float k00_20, k01_21; + + float *e0 = e + d0; + float *e2 = e0 + k_off; + + for (i=lim >> 2; i > 0; --i) { + k00_20 = e0[-0] - e2[-0]; + k01_21 = e0[-1] - e2[-1]; + e0[-0] += e2[-0];//e0[-0] = e0[-0] + e2[-0]; + e0[-1] += e2[-1];//e0[-1] = e0[-1] + e2[-1]; + e2[-0] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-1] = (k01_21)*A[0] + (k00_20) * A[1]; + + A += k1; + + k00_20 = e0[-2] - e2[-2]; + k01_21 = e0[-3] - e2[-3]; + e0[-2] += e2[-2];//e0[-2] = e0[-2] + e2[-2]; + e0[-3] += e2[-3];//e0[-3] = e0[-3] + e2[-3]; + e2[-2] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-3] = (k01_21)*A[0] + (k00_20) * A[1]; + + A += k1; + + k00_20 = e0[-4] - e2[-4]; + k01_21 = e0[-5] - e2[-5]; + e0[-4] += e2[-4];//e0[-4] = e0[-4] + e2[-4]; + e0[-5] += e2[-5];//e0[-5] = e0[-5] + e2[-5]; + e2[-4] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-5] = (k01_21)*A[0] + (k00_20) * A[1]; + + A += k1; + + k00_20 = e0[-6] - e2[-6]; + k01_21 = e0[-7] - e2[-7]; + e0[-6] += e2[-6];//e0[-6] = e0[-6] + e2[-6]; + e0[-7] += e2[-7];//e0[-7] = e0[-7] + e2[-7]; + e2[-6] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-7] = (k01_21)*A[0] + (k00_20) * A[1]; + + e0 -= 8; + e2 -= 8; + + A += k1; + } +} + +static void imdct_step3_inner_s_loop(int n, float *e, int i_off, int k_off, float *A, int a_off, int k0) +{ + int i; + float A0 = A[0]; + float A1 = A[0+1]; + float A2 = A[0+a_off]; + float A3 = A[0+a_off+1]; + float A4 = A[0+a_off*2+0]; + float A5 = A[0+a_off*2+1]; + float A6 = A[0+a_off*3+0]; + float A7 = A[0+a_off*3+1]; + + float k00,k11; + + float *ee0 = e +i_off; + float *ee2 = ee0+k_off; + + for (i=n; i > 0; --i) { + k00 = ee0[ 0] - ee2[ 0]; + k11 = ee0[-1] - ee2[-1]; + ee0[ 0] = ee0[ 0] + ee2[ 0]; + ee0[-1] = ee0[-1] + ee2[-1]; + ee2[ 0] = (k00) * A0 - (k11) * A1; + ee2[-1] = (k11) * A0 + (k00) * A1; + + k00 = ee0[-2] - ee2[-2]; + k11 = ee0[-3] - ee2[-3]; + ee0[-2] = ee0[-2] + ee2[-2]; + ee0[-3] = ee0[-3] + ee2[-3]; + ee2[-2] = (k00) * A2 - (k11) * A3; + ee2[-3] = (k11) * A2 + (k00) * A3; + + k00 = ee0[-4] - ee2[-4]; + k11 = ee0[-5] - ee2[-5]; + ee0[-4] = ee0[-4] + ee2[-4]; + ee0[-5] = ee0[-5] + ee2[-5]; + ee2[-4] = (k00) * A4 - (k11) * A5; + ee2[-5] = (k11) * A4 + (k00) * A5; + + k00 = ee0[-6] - ee2[-6]; + k11 = ee0[-7] - ee2[-7]; + ee0[-6] = ee0[-6] + ee2[-6]; + ee0[-7] = ee0[-7] + ee2[-7]; + ee2[-6] = (k00) * A6 - (k11) * A7; + ee2[-7] = (k11) * A6 + (k00) * A7; + + ee0 -= k0; + ee2 -= k0; + } +} + +static __forceinline void iter_54(float *z) +{ + float k00,k11,k22,k33; + float y0,y1,y2,y3; + + k00 = z[ 0] - z[-4]; + y0 = z[ 0] + z[-4]; + y2 = z[-2] + z[-6]; + k22 = z[-2] - z[-6]; + + z[-0] = y0 + y2; // z0 + z4 + z2 + z6 + z[-2] = y0 - y2; // z0 + z4 - z2 - z6 + + // done with y0,y2 + + k33 = z[-3] - z[-7]; + + z[-4] = k00 + k33; // z0 - z4 + z3 - z7 + z[-6] = k00 - k33; // z0 - z4 - z3 + z7 + + // done with k33 + + k11 = z[-1] - z[-5]; + y1 = z[-1] + z[-5]; + y3 = z[-3] + z[-7]; + + z[-1] = y1 + y3; // z1 + z5 + z3 + z7 + z[-3] = y1 - y3; // z1 + z5 - z3 - z7 + z[-5] = k11 - k22; // z1 - z5 + z2 - z6 + z[-7] = k11 + k22; // z1 - z5 - z2 + z6 +} + +static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, int base_n) +{ + int a_off = base_n >> 3; + float A2 = A[0+a_off]; + float *z = e + i_off; + float *base = z - 16 * n; + + while (z > base) { + float k00,k11; + float l00,l11; + + k00 = z[-0] - z[ -8]; + k11 = z[-1] - z[ -9]; + l00 = z[-2] - z[-10]; + l11 = z[-3] - z[-11]; + z[ -0] = z[-0] + z[ -8]; + z[ -1] = z[-1] + z[ -9]; + z[ -2] = z[-2] + z[-10]; + z[ -3] = z[-3] + z[-11]; + z[ -8] = k00; + z[ -9] = k11; + z[-10] = (l00+l11) * A2; + z[-11] = (l11-l00) * A2; + + k00 = z[ -4] - z[-12]; + k11 = z[ -5] - z[-13]; + l00 = z[ -6] - z[-14]; + l11 = z[ -7] - z[-15]; + z[ -4] = z[ -4] + z[-12]; + z[ -5] = z[ -5] + z[-13]; + z[ -6] = z[ -6] + z[-14]; + z[ -7] = z[ -7] + z[-15]; + z[-12] = k11; + z[-13] = -k00; + z[-14] = (l11-l00) * A2; + z[-15] = (l00+l11) * -A2; + + iter_54(z); + iter_54(z-8); + z -= 16; + } +} + +static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) +{ + int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; + int ld; + // @OPTIMIZE: reduce register pressure by using fewer variables? + int save_point = temp_alloc_save(f); + float *buf2 = (float *) temp_alloc(f, n2 * sizeof(*buf2)); + float *u=NULL,*v=NULL; + // twiddle factors + float *A = f->A[blocktype]; + + // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" + // See notes about bugs in that paper in less-optimal implementation 'inverse_mdct_old' after this function. + + // kernel from paper + + + // merged: + // copy and reflect spectral data + // step 0 + + // note that it turns out that the items added together during + // this step are, in fact, being added to themselves (as reflected + // by step 0). inexplicable inefficiency! this became obvious + // once I combined the passes. + + // so there's a missing 'times 2' here (for adding X to itself). + // this propagates through linearly to the end, where the numbers + // are 1/2 too small, and need to be compensated for. + + { + float *d,*e, *AA, *e_stop; + d = &buf2[n2-2]; + AA = A; + e = &buffer[0]; + e_stop = &buffer[n2]; + while (e != e_stop) { + d[1] = (e[0] * AA[0] - e[2]*AA[1]); + d[0] = (e[0] * AA[1] + e[2]*AA[0]); + d -= 2; + AA += 2; + e += 4; + } + + e = &buffer[n2-3]; + while (d >= buf2) { + d[1] = (-e[2] * AA[0] - -e[0]*AA[1]); + d[0] = (-e[2] * AA[1] + -e[0]*AA[0]); + d -= 2; + AA += 2; + e -= 4; + } + } + + // now we use symbolic names for these, so that we can + // possibly swap their meaning as we change which operations + // are in place + + u = buffer; + v = buf2; + + // step 2 (paper output is w, now u) + // this could be in place, but the data ends up in the wrong + // place... _somebody_'s got to swap it, so this is nominated + { + float *AA = &A[n2-8]; + float *d0,*d1, *e0, *e1; + + e0 = &v[n4]; + e1 = &v[0]; + + d0 = &u[n4]; + d1 = &u[0]; + + while (AA >= A) { + float v40_20, v41_21; + + v41_21 = e0[1] - e1[1]; + v40_20 = e0[0] - e1[0]; + d0[1] = e0[1] + e1[1]; + d0[0] = e0[0] + e1[0]; + d1[1] = v41_21*AA[4] - v40_20*AA[5]; + d1[0] = v40_20*AA[4] + v41_21*AA[5]; + + v41_21 = e0[3] - e1[3]; + v40_20 = e0[2] - e1[2]; + d0[3] = e0[3] + e1[3]; + d0[2] = e0[2] + e1[2]; + d1[3] = v41_21*AA[0] - v40_20*AA[1]; + d1[2] = v40_20*AA[0] + v41_21*AA[1]; + + AA -= 8; + + d0 += 4; + d1 += 4; + e0 += 4; + e1 += 4; + } + } + + // step 3 + ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + + // optimized step 3: + + // the original step3 loop can be nested r inside s or s inside r; + // it's written originally as s inside r, but this is dumb when r + // iterates many times, and s few. So I have two copies of it and + // switch between them halfway. + + // this is iteration 0 of step 3 + imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*0, -(n >> 3), A); + imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*1, -(n >> 3), A); + + // this is iteration 1 of step 3 + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*0, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*1, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*2, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*3, -(n >> 4), A, 16); + + l=2; + for (; l < (ld-3)>>1; ++l) { + int k0 = n >> (l+2), k0_2 = k0>>1; + int lim = 1 << (l+1); + int i; + for (i=0; i < lim; ++i) + imdct_step3_inner_r_loop(n >> (l+4), u, n2-1 - k0*i, -k0_2, A, 1 << (l+3)); + } + + for (; l < ld-6; ++l) { + int k0 = n >> (l+2), k1 = 1 << (l+3), k0_2 = k0>>1; + int rlim = n >> (l+6), r; + int lim = 1 << (l+1); + int i_off; + float *A0 = A; + i_off = n2-1; + for (r=rlim; r > 0; --r) { + imdct_step3_inner_s_loop(lim, u, i_off, -k0_2, A0, k1, k0); + A0 += k1*4; + i_off -= 8; + } + } + + // iterations with count: + // ld-6,-5,-4 all interleaved together + // the big win comes from getting rid of needless flops + // due to the constants on pass 5 & 4 being all 1 and 0; + // combining them to be simultaneous to improve cache made little difference + imdct_step3_inner_s_loop_ld654(n >> 5, u, n2-1, A, n); + + // output is u + + // step 4, 5, and 6 + // cannot be in-place because of step 5 + { + uint16 *bitrev = f->bit_reverse[blocktype]; + // weirdly, I'd have thought reading sequentially and writing + // erratically would have been better than vice-versa, but in + // fact that's not what my testing showed. (That is, with + // j = bitreverse(i), do you read i and write j, or read j and write i.) + + float *d0 = &v[n4-4]; + float *d1 = &v[n2-4]; + while (d0 >= v) { + int k4; + + k4 = bitrev[0]; + d1[3] = u[k4+0]; + d1[2] = u[k4+1]; + d0[3] = u[k4+2]; + d0[2] = u[k4+3]; + + k4 = bitrev[1]; + d1[1] = u[k4+0]; + d1[0] = u[k4+1]; + d0[1] = u[k4+2]; + d0[0] = u[k4+3]; + + d0 -= 4; + d1 -= 4; + bitrev += 2; + } + } + // (paper output is u, now v) + + + // data must be in buf2 + assert(v == buf2); + + // step 7 (paper output is v, now v) + // this is now in place + { + float *C = f->C[blocktype]; + float *d, *e; + + d = v; + e = v + n2 - 4; + + while (d < e) { + float a02,a11,b0,b1,b2,b3; + + a02 = d[0] - e[2]; + a11 = d[1] + e[3]; + + b0 = C[1]*a02 + C[0]*a11; + b1 = C[1]*a11 - C[0]*a02; + + b2 = d[0] + e[ 2]; + b3 = d[1] - e[ 3]; + + d[0] = b2 + b0; + d[1] = b3 + b1; + e[2] = b2 - b0; + e[3] = b1 - b3; + + a02 = d[2] - e[0]; + a11 = d[3] + e[1]; + + b0 = C[3]*a02 + C[2]*a11; + b1 = C[3]*a11 - C[2]*a02; + + b2 = d[2] + e[ 0]; + b3 = d[3] - e[ 1]; + + d[2] = b2 + b0; + d[3] = b3 + b1; + e[0] = b2 - b0; + e[1] = b1 - b3; + + C += 4; + d += 4; + e -= 4; + } + } + + // data must be in buf2 + + + // step 8+decode (paper output is X, now buffer) + // this generates pairs of data a la 8 and pushes them directly through + // the decode kernel (pushing rather than pulling) to avoid having + // to make another pass later + + // this cannot POSSIBLY be in place, so we refer to the buffers directly + + { + float *d0,*d1,*d2,*d3; + + float *B = f->B[blocktype] + n2 - 8; + float *e = buf2 + n2 - 8; + d0 = &buffer[0]; + d1 = &buffer[n2-4]; + d2 = &buffer[n2]; + d3 = &buffer[n-4]; + while (e >= v) { + float p0,p1,p2,p3; + + p3 = e[6]*B[7] - e[7]*B[6]; + p2 = -e[6]*B[6] - e[7]*B[7]; + + d0[0] = p3; + d1[3] = - p3; + d2[0] = p2; + d3[3] = p2; + + p1 = e[4]*B[5] - e[5]*B[4]; + p0 = -e[4]*B[4] - e[5]*B[5]; + + d0[1] = p1; + d1[2] = - p1; + d2[1] = p0; + d3[2] = p0; + + p3 = e[2]*B[3] - e[3]*B[2]; + p2 = -e[2]*B[2] - e[3]*B[3]; + + d0[2] = p3; + d1[1] = - p3; + d2[2] = p2; + d3[1] = p2; + + p1 = e[0]*B[1] - e[1]*B[0]; + p0 = -e[0]*B[0] - e[1]*B[1]; + + d0[3] = p1; + d1[0] = - p1; + d2[3] = p0; + d3[0] = p0; + + B -= 8; + e -= 8; + d0 += 4; + d2 += 4; + d1 -= 4; + d3 -= 4; + } + } + + temp_free(f,buf2); + temp_alloc_restore(f,save_point); +} + +#if 0 +// this is the original version of the above code, if you want to optimize it from scratch +void inverse_mdct_naive(float *buffer, int n) +{ + float s; + float A[1 << 12], B[1 << 12], C[1 << 11]; + int i,k,k2,k4, n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; + int n3_4 = n - n4, ld; + // how can they claim this only uses N words?! + // oh, because they're only used sparsely, whoops + float u[1 << 13], X[1 << 13], v[1 << 13], w[1 << 13]; + // set up twiddle factors + + for (k=k2=0; k < n4; ++k,k2+=2) { + A[k2 ] = (float) cos(4*k*M_PI/n); + A[k2+1] = (float) -sin(4*k*M_PI/n); + B[k2 ] = (float) cos((k2+1)*M_PI/n/2); + B[k2+1] = (float) sin((k2+1)*M_PI/n/2); + } + for (k=k2=0; k < n8; ++k,k2+=2) { + C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); + C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); + } + + // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" + // Note there are bugs in that pseudocode, presumably due to them attempting + // to rename the arrays nicely rather than representing the way their actual + // implementation bounces buffers back and forth. As a result, even in the + // "some formulars corrected" version, a direct implementation fails. These + // are noted below as "paper bug". + + // copy and reflect spectral data + for (k=0; k < n2; ++k) u[k] = buffer[k]; + for ( ; k < n ; ++k) u[k] = -buffer[n - k - 1]; + // kernel from paper + // step 1 + for (k=k2=k4=0; k < n4; k+=1, k2+=2, k4+=4) { + v[n-k4-1] = (u[k4] - u[n-k4-1]) * A[k2] - (u[k4+2] - u[n-k4-3])*A[k2+1]; + v[n-k4-3] = (u[k4] - u[n-k4-1]) * A[k2+1] + (u[k4+2] - u[n-k4-3])*A[k2]; + } + // step 2 + for (k=k4=0; k < n8; k+=1, k4+=4) { + w[n2+3+k4] = v[n2+3+k4] + v[k4+3]; + w[n2+1+k4] = v[n2+1+k4] + v[k4+1]; + w[k4+3] = (v[n2+3+k4] - v[k4+3])*A[n2-4-k4] - (v[n2+1+k4]-v[k4+1])*A[n2-3-k4]; + w[k4+1] = (v[n2+1+k4] - v[k4+1])*A[n2-4-k4] + (v[n2+3+k4]-v[k4+3])*A[n2-3-k4]; + } + // step 3 + ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + for (l=0; l < ld-3; ++l) { + int k0 = n >> (l+2), k1 = 1 << (l+3); + int rlim = n >> (l+4), r4, r; + int s2lim = 1 << (l+2), s2; + for (r=r4=0; r < rlim; r4+=4,++r) { + for (s2=0; s2 < s2lim; s2+=2) { + u[n-1-k0*s2-r4] = w[n-1-k0*s2-r4] + w[n-1-k0*(s2+1)-r4]; + u[n-3-k0*s2-r4] = w[n-3-k0*s2-r4] + w[n-3-k0*(s2+1)-r4]; + u[n-1-k0*(s2+1)-r4] = (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1] + - (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1+1]; + u[n-3-k0*(s2+1)-r4] = (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1] + + (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1+1]; + } + } + if (l+1 < ld-3) { + // paper bug: ping-ponging of u&w here is omitted + memcpy(w, u, sizeof(u)); + } + } + + // step 4 + for (i=0; i < n8; ++i) { + int j = bit_reverse(i) >> (32-ld+3); + assert(j < n8); + if (i == j) { + // paper bug: original code probably swapped in place; if copying, + // need to directly copy in this case + int i8 = i << 3; + v[i8+1] = u[i8+1]; + v[i8+3] = u[i8+3]; + v[i8+5] = u[i8+5]; + v[i8+7] = u[i8+7]; + } else if (i < j) { + int i8 = i << 3, j8 = j << 3; + v[j8+1] = u[i8+1], v[i8+1] = u[j8 + 1]; + v[j8+3] = u[i8+3], v[i8+3] = u[j8 + 3]; + v[j8+5] = u[i8+5], v[i8+5] = u[j8 + 5]; + v[j8+7] = u[i8+7], v[i8+7] = u[j8 + 7]; + } + } + // step 5 + for (k=0; k < n2; ++k) { + w[k] = v[k*2+1]; + } + // step 6 + for (k=k2=k4=0; k < n8; ++k, k2 += 2, k4 += 4) { + u[n-1-k2] = w[k4]; + u[n-2-k2] = w[k4+1]; + u[n3_4 - 1 - k2] = w[k4+2]; + u[n3_4 - 2 - k2] = w[k4+3]; + } + // step 7 + for (k=k2=0; k < n8; ++k, k2 += 2) { + v[n2 + k2 ] = ( u[n2 + k2] + u[n-2-k2] + C[k2+1]*(u[n2+k2]-u[n-2-k2]) + C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2; + v[n-2 - k2] = ( u[n2 + k2] + u[n-2-k2] - C[k2+1]*(u[n2+k2]-u[n-2-k2]) - C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2; + v[n2+1+ k2] = ( u[n2+1+k2] - u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2; + v[n-1 - k2] = (-u[n2+1+k2] + u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2; + } + // step 8 + for (k=k2=0; k < n4; ++k,k2 += 2) { + X[k] = v[k2+n2]*B[k2 ] + v[k2+1+n2]*B[k2+1]; + X[n2-1-k] = v[k2+n2]*B[k2+1] - v[k2+1+n2]*B[k2 ]; + } + + // decode kernel to output + // determined the following value experimentally + // (by first figuring out what made inverse_mdct_slow work); then matching that here + // (probably vorbis encoder premultiplies by n or n/2, to save it on the decoder?) + s = 0.5; // theoretically would be n4 + + // [[[ note! the s value of 0.5 is compensated for by the B[] in the current code, + // so it needs to use the "old" B values to behave correctly, or else + // set s to 1.0 ]]] + for (i=0; i < n4 ; ++i) buffer[i] = s * X[i+n4]; + for ( ; i < n3_4; ++i) buffer[i] = -s * X[n3_4 - i - 1]; + for ( ; i < n ; ++i) buffer[i] = -s * X[i - n3_4]; +} +#endif + +static float *get_window(vorb *f, int len) +{ + len <<= 1; + if (len == f->blocksize_0) return f->window[0]; + if (len == f->blocksize_1) return f->window[1]; + return NULL; +} + +#ifndef STB_VORBIS_NO_DEFER_FLOOR +typedef int16 YTYPE; +#else +typedef int YTYPE; +#endif +static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *finalY, uint8 *step2_flag) +{ + int n2 = n >> 1; + int s = map->chan[i].mux, floor; + floor = map->submap_floor[s]; + if (f->floor_types[floor] == 0) { + return error(f, VORBIS_invalid_stream); + } else { + Floor1 *g = &f->floor_config[floor].floor1; + int j,q; + int lx = 0, ly = finalY[0] * g->floor1_multiplier; + for (q=1; q < g->values; ++q) { + j = g->sorted_order[q]; + #ifndef STB_VORBIS_NO_DEFER_FLOOR + STBV_NOTUSED(step2_flag); + if (finalY[j] >= 0) + #else + if (step2_flag[j]) + #endif + { + int hy = finalY[j] * g->floor1_multiplier; + int hx = g->Xlist[j]; + if (lx != hx) + draw_line(target, lx,ly, hx,hy, n2); + CHECK(f); + lx = hx, ly = hy; + } + } + if (lx < n2) { + // optimization of: draw_line(target, lx,ly, n,ly, n2); + for (j=lx; j < n2; ++j) + LINE_OP(target[j], inverse_db_table[ly]); + CHECK(f); + } + } + return TRUE; +} + +// The meaning of "left" and "right" +// +// For a given frame: +// we compute samples from 0..n +// window_center is n/2 +// we'll window and mix the samples from left_start to left_end with data from the previous frame +// all of the samples from left_end to right_start can be output without mixing; however, +// this interval is 0-length except when transitioning between short and long frames +// all of the samples from right_start to right_end need to be mixed with the next frame, +// which we don't have, so those get saved in a buffer +// frame N's right_end-right_start, the number of samples to mix with the next frame, +// has to be the same as frame N+1's left_end-left_start (which they are by +// construction) + +static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) +{ + Mode *m; + int i, n, prev, next, window_center; + f->channel_buffer_start = f->channel_buffer_end = 0; + + retry: + if (f->eof) return FALSE; + if (!maybe_start_packet(f)) + return FALSE; + // check packet type + if (get_bits(f,1) != 0) { + if (IS_PUSH_MODE(f)) + return error(f,VORBIS_bad_packet_type); + while (EOP != get8_packet(f)); + goto retry; + } + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + + i = get_bits(f, ilog(f->mode_count-1)); + if (i == EOP) return FALSE; + if (i >= f->mode_count) return FALSE; + *mode = i; + m = f->mode_config + i; + if (m->blockflag) { + n = f->blocksize_1; + prev = get_bits(f,1); + next = get_bits(f,1); + } else { + prev = next = 0; + n = f->blocksize_0; + } + +// WINDOWING + + window_center = n >> 1; + if (m->blockflag && !prev) { + *p_left_start = (n - f->blocksize_0) >> 2; + *p_left_end = (n + f->blocksize_0) >> 2; + } else { + *p_left_start = 0; + *p_left_end = window_center; + } + if (m->blockflag && !next) { + *p_right_start = (n*3 - f->blocksize_0) >> 2; + *p_right_end = (n*3 + f->blocksize_0) >> 2; + } else { + *p_right_start = window_center; + *p_right_end = n; + } + + return TRUE; +} + +static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, int left_end, int right_start, int right_end, int *p_left) +{ + Mapping *map; + int i,j,k,n,n2; + int zero_channel[256]; + int really_zero_channel[256]; + +// WINDOWING + + STBV_NOTUSED(left_end); + n = f->blocksize[m->blockflag]; + map = &f->mapping[m->mapping]; + +// FLOORS + n2 = n >> 1; + + CHECK(f); + + for (i=0; i < f->channels; ++i) { + int s = map->chan[i].mux, floor; + zero_channel[i] = FALSE; + floor = map->submap_floor[s]; + if (f->floor_types[floor] == 0) { + return error(f, VORBIS_invalid_stream); + } else { + Floor1 *g = &f->floor_config[floor].floor1; + if (get_bits(f, 1)) { + short *finalY; + uint8 step2_flag[256]; + static int range_list[4] = { 256, 128, 86, 64 }; + int range = range_list[g->floor1_multiplier-1]; + int offset = 2; + finalY = f->finalY[i]; + finalY[0] = get_bits(f, ilog(range)-1); + finalY[1] = get_bits(f, ilog(range)-1); + for (j=0; j < g->partitions; ++j) { + int pclass = g->partition_class_list[j]; + int cdim = g->class_dimensions[pclass]; + int cbits = g->class_subclasses[pclass]; + int csub = (1 << cbits)-1; + int cval = 0; + if (cbits) { + Codebook *c = f->codebooks + g->class_masterbooks[pclass]; + DECODE(cval,f,c); + } + for (k=0; k < cdim; ++k) { + int book = g->subclass_books[pclass][cval & csub]; + cval = cval >> cbits; + if (book >= 0) { + int temp; + Codebook *c = f->codebooks + book; + DECODE(temp,f,c); + finalY[offset++] = temp; + } else + finalY[offset++] = 0; + } + } + if (f->valid_bits == INVALID_BITS) goto error; // behavior according to spec + step2_flag[0] = step2_flag[1] = 1; + for (j=2; j < g->values; ++j) { + int low, high, pred, highroom, lowroom, room, val; + low = g->neighbors[j][0]; + high = g->neighbors[j][1]; + //neighbors(g->Xlist, j, &low, &high); + pred = predict_point(g->Xlist[j], g->Xlist[low], g->Xlist[high], finalY[low], finalY[high]); + val = finalY[j]; + highroom = range - pred; + lowroom = pred; + if (highroom < lowroom) + room = highroom * 2; + else + room = lowroom * 2; + if (val) { + step2_flag[low] = step2_flag[high] = 1; + step2_flag[j] = 1; + if (val >= room) + if (highroom > lowroom) + finalY[j] = val - lowroom + pred; + else + finalY[j] = pred - val + highroom - 1; + else + if (val & 1) + finalY[j] = pred - ((val+1)>>1); + else + finalY[j] = pred + (val>>1); + } else { + step2_flag[j] = 0; + finalY[j] = pred; + } + } + +#ifdef STB_VORBIS_NO_DEFER_FLOOR + do_floor(f, map, i, n, f->floor_buffers[i], finalY, step2_flag); +#else + // defer final floor computation until _after_ residue + for (j=0; j < g->values; ++j) { + if (!step2_flag[j]) + finalY[j] = -1; + } +#endif + } else { + error: + zero_channel[i] = TRUE; + } + // So we just defer everything else to later + + // at this point we've decoded the floor into buffer + } + } + CHECK(f); + // at this point we've decoded all floors + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + + // re-enable coupled channels if necessary + memcpy(really_zero_channel, zero_channel, sizeof(really_zero_channel[0]) * f->channels); + for (i=0; i < map->coupling_steps; ++i) + if (!zero_channel[map->chan[i].magnitude] || !zero_channel[map->chan[i].angle]) { + zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE; + } + + CHECK(f); +// RESIDUE DECODE + for (i=0; i < map->submaps; ++i) { + float *residue_buffers[STB_VORBIS_MAX_CHANNELS]; + int r; + uint8 do_not_decode[256]; + int ch = 0; + for (j=0; j < f->channels; ++j) { + if (map->chan[j].mux == i) { + if (zero_channel[j]) { + do_not_decode[ch] = TRUE; + residue_buffers[ch] = NULL; + } else { + do_not_decode[ch] = FALSE; + residue_buffers[ch] = f->channel_buffers[j]; + } + ++ch; + } + } + r = map->submap_residue[i]; + decode_residue(f, residue_buffers, ch, n2, r, do_not_decode); + } + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + CHECK(f); + +// INVERSE COUPLING + for (i = map->coupling_steps-1; i >= 0; --i) { + int n2 = n >> 1; + float *m = f->channel_buffers[map->chan[i].magnitude]; + float *a = f->channel_buffers[map->chan[i].angle ]; + for (j=0; j < n2; ++j) { + float a2,m2; + if (m[j] > 0) + if (a[j] > 0) + m2 = m[j], a2 = m[j] - a[j]; + else + a2 = m[j], m2 = m[j] + a[j]; + else + if (a[j] > 0) + m2 = m[j], a2 = m[j] + a[j]; + else + a2 = m[j], m2 = m[j] - a[j]; + m[j] = m2; + a[j] = a2; + } + } + CHECK(f); + + // finish decoding the floors +#ifndef STB_VORBIS_NO_DEFER_FLOOR + for (i=0; i < f->channels; ++i) { + if (really_zero_channel[i]) { + memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); + } else { + do_floor(f, map, i, n, f->channel_buffers[i], f->finalY[i], NULL); + } + } +#else + for (i=0; i < f->channels; ++i) { + if (really_zero_channel[i]) { + memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); + } else { + for (j=0; j < n2; ++j) + f->channel_buffers[i][j] *= f->floor_buffers[i][j]; + } + } +#endif + +// INVERSE MDCT + CHECK(f); + for (i=0; i < f->channels; ++i) + inverse_mdct(f->channel_buffers[i], n, f, m->blockflag); + CHECK(f); + + // this shouldn't be necessary, unless we exited on an error + // and want to flush to get to the next packet + flush_packet(f); + + if (f->first_decode) { + // assume we start so first non-discarded sample is sample 0 + // this isn't to spec, but spec would require us to read ahead + // and decode the size of all current frames--could be done, + // but presumably it's not a commonly used feature + f->current_loc = 0u - n2; // start of first frame is positioned for discard (NB this is an intentional unsigned overflow/wrap-around) + // we might have to discard samples "from" the next frame too, + // if we're lapping a large block then a small at the start? + f->discard_samples_deferred = n - right_end; + f->current_loc_valid = TRUE; + f->first_decode = FALSE; + } else if (f->discard_samples_deferred) { + if (f->discard_samples_deferred >= right_start - left_start) { + f->discard_samples_deferred -= (right_start - left_start); + left_start = right_start; + *p_left = left_start; + } else { + left_start += f->discard_samples_deferred; + *p_left = left_start; + f->discard_samples_deferred = 0; + } + } else if (f->previous_length == 0 && f->current_loc_valid) { + // we're recovering from a seek... that means we're going to discard + // the samples from this packet even though we know our position from + // the last page header, so we need to update the position based on + // the discarded samples here + // but wait, the code below is going to add this in itself even + // on a discard, so we don't need to do it here... + } + + // check if we have ogg information about the sample # for this packet + if (f->last_seg_which == f->end_seg_with_known_loc) { + // if we have a valid current loc, and this is final: + if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) { + uint32 current_end = f->known_loc_for_packet; + // then let's infer the size of the (probably) short final frame + if (current_end < f->current_loc + (right_end-left_start)) { + if (current_end < f->current_loc) { + // negative truncation, that's impossible! + *len = 0; + } else { + *len = current_end - f->current_loc; + } + *len += left_start; // this doesn't seem right, but has no ill effect on my test files + if (*len > right_end) *len = right_end; // this should never happen + f->current_loc += *len; + return TRUE; + } + } + // otherwise, just set our sample loc + // guess that the ogg granule pos refers to the _middle_ of the + // last frame? + // set f->current_loc to the position of left_start + f->current_loc = f->known_loc_for_packet - (n2-left_start); + f->current_loc_valid = TRUE; + } + if (f->current_loc_valid) + f->current_loc += (right_start - left_start); + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + *len = right_end; // ignore samples after the window goes to 0 + CHECK(f); + + return TRUE; +} + +static int vorbis_decode_packet(vorb *f, int *len, int *p_left, int *p_right) +{ + int mode, left_end, right_end; + if (!vorbis_decode_initial(f, p_left, &left_end, p_right, &right_end, &mode)) return 0; + return vorbis_decode_packet_rest(f, len, f->mode_config + mode, *p_left, left_end, *p_right, right_end, p_left); +} + +static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right) +{ + int prev,i,j; + // we use right&left (the start of the right- and left-window sin()-regions) + // to determine how much to return, rather than inferring from the rules + // (same result, clearer code); 'left' indicates where our sin() window + // starts, therefore where the previous window's right edge starts, and + // therefore where to start mixing from the previous buffer. 'right' + // indicates where our sin() ending-window starts, therefore that's where + // we start saving, and where our returned-data ends. + + // mixin from previous window + if (f->previous_length) { + int i,j, n = f->previous_length; + float *w = get_window(f, n); + if (w == NULL) return 0; + for (i=0; i < f->channels; ++i) { + for (j=0; j < n; ++j) + f->channel_buffers[i][left+j] = + f->channel_buffers[i][left+j]*w[ j] + + f->previous_window[i][ j]*w[n-1-j]; + } + } + + prev = f->previous_length; + + // last half of this data becomes previous window + f->previous_length = len - right; + + // @OPTIMIZE: could avoid this copy by double-buffering the + // output (flipping previous_window with channel_buffers), but + // then previous_window would have to be 2x as large, and + // channel_buffers couldn't be temp mem (although they're NOT + // currently temp mem, they could be (unless we want to level + // performance by spreading out the computation)) + for (i=0; i < f->channels; ++i) + for (j=0; right+j < len; ++j) + f->previous_window[i][j] = f->channel_buffers[i][right+j]; + + if (!prev) + // there was no previous packet, so this data isn't valid... + // this isn't entirely true, only the would-have-overlapped data + // isn't valid, but this seems to be what the spec requires + return 0; + + // truncate a short frame + if (len < right) right = len; + + f->samples_output += right-left; + + return right - left; +} + +static int vorbis_pump_first_frame(stb_vorbis *f) +{ + int len, right, left, res; + res = vorbis_decode_packet(f, &len, &left, &right); + if (res) + vorbis_finish_frame(f, len, left, right); + return res; +} + +#ifndef STB_VORBIS_NO_PUSHDATA_API +static int is_whole_packet_present(stb_vorbis *f) +{ + // make sure that we have the packet available before continuing... + // this requires a full ogg parse, but we know we can fetch from f->stream + + // instead of coding this out explicitly, we could save the current read state, + // read the next packet with get8() until end-of-packet, check f->eof, then + // reset the state? but that would be slower, esp. since we'd have over 256 bytes + // of state to restore (primarily the page segment table) + + int s = f->next_seg, first = TRUE; + uint8 *p = f->stream; + + if (s != -1) { // if we're not starting the packet with a 'continue on next page' flag + for (; s < f->segment_count; ++s) { + p += f->segments[s]; + if (f->segments[s] < 255) // stop at first short segment + break; + } + // either this continues, or it ends it... + if (s == f->segment_count) + s = -1; // set 'crosses page' flag + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + first = FALSE; + } + for (; s == -1;) { + uint8 *q; + int n; + + // check that we have the page header ready + if (p + 26 >= f->stream_end) return error(f, VORBIS_need_more_data); + // validate the page + if (memcmp(p, ogg_page_header, 4)) return error(f, VORBIS_invalid_stream); + if (p[4] != 0) return error(f, VORBIS_invalid_stream); + if (first) { // the first segment must NOT have 'continued_packet', later ones MUST + if (f->previous_length) + if ((p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); + // if no previous length, we're resynching, so we can come in on a continued-packet, + // which we'll just drop + } else { + if (!(p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); + } + n = p[26]; // segment counts + q = p+27; // q points to segment table + p = q + n; // advance past header + // make sure we've read the segment table + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + for (s=0; s < n; ++s) { + p += q[s]; + if (q[s] < 255) + break; + } + if (s == n) + s = -1; // set 'crosses page' flag + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + first = FALSE; + } + return TRUE; +} +#endif // !STB_VORBIS_NO_PUSHDATA_API + +static int start_decoder(vorb *f) +{ + uint8 header[6], x,y; + int len,i,j,k, max_submaps = 0; + int longest_floorlist=0; + + // first page, first packet + f->first_decode = TRUE; + + if (!start_page(f)) return FALSE; + // validate page flag + if (!(f->page_flag & PAGEFLAG_first_page)) return error(f, VORBIS_invalid_first_page); + if (f->page_flag & PAGEFLAG_last_page) return error(f, VORBIS_invalid_first_page); + if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page); + // check for expected packet length + if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page); + if (f->segments[0] != 30) { + // check for the Ogg skeleton fishead identifying header to refine our error + if (f->segments[0] == 64 && + getn(f, header, 6) && + header[0] == 'f' && + header[1] == 'i' && + header[2] == 's' && + header[3] == 'h' && + header[4] == 'e' && + header[5] == 'a' && + get8(f) == 'd' && + get8(f) == '\0') return error(f, VORBIS_ogg_skeleton_not_supported); + else + return error(f, VORBIS_invalid_first_page); + } + + // read packet + // check packet header + if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page); + if (!getn(f, header, 6)) return error(f, VORBIS_unexpected_eof); + if (!vorbis_validate(header)) return error(f, VORBIS_invalid_first_page); + // vorbis_version + if (get32(f) != 0) return error(f, VORBIS_invalid_first_page); + f->channels = get8(f); if (!f->channels) return error(f, VORBIS_invalid_first_page); + if (f->channels > STB_VORBIS_MAX_CHANNELS) return error(f, VORBIS_too_many_channels); + f->sample_rate = get32(f); if (!f->sample_rate) return error(f, VORBIS_invalid_first_page); + get32(f); // bitrate_maximum + get32(f); // bitrate_nominal + get32(f); // bitrate_minimum + x = get8(f); + { + int log0,log1; + log0 = x & 15; + log1 = x >> 4; + f->blocksize_0 = 1 << log0; + f->blocksize_1 = 1 << log1; + if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup); + if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup); + if (log0 > log1) return error(f, VORBIS_invalid_setup); + } + + // framing_flag + x = get8(f); + if (!(x & 1)) return error(f, VORBIS_invalid_first_page); + + // second packet! + if (!start_page(f)) return FALSE; + + if (!start_packet(f)) return FALSE; + + if (!next_segment(f)) return FALSE; + + if (get8_packet(f) != VORBIS_packet_comment) return error(f, VORBIS_invalid_setup); + for (i=0; i < 6; ++i) header[i] = get8_packet(f); + if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup); + //file vendor + len = get32_packet(f); + f->vendor = (char*)setup_malloc(f, sizeof(char) * (len+1)); + if (f->vendor == NULL) return error(f, VORBIS_outofmem); + for(i=0; i < len; ++i) { + f->vendor[i] = get8_packet(f); + } + f->vendor[len] = (char)'\0'; + //user comments + f->comment_list_length = get32_packet(f); + f->comment_list = NULL; + if (f->comment_list_length > 0) + { + f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length)); + if (f->comment_list == NULL) return error(f, VORBIS_outofmem); + } + + for(i=0; i < f->comment_list_length; ++i) { + len = get32_packet(f); + f->comment_list[i] = (char*)setup_malloc(f, sizeof(char) * (len+1)); + if (f->comment_list[i] == NULL) return error(f, VORBIS_outofmem); + + for(j=0; j < len; ++j) { + f->comment_list[i][j] = get8_packet(f); + } + f->comment_list[i][len] = (char)'\0'; + } + + // framing_flag + x = get8_packet(f); + if (!(x & 1)) return error(f, VORBIS_invalid_setup); + + + skip(f, f->bytes_in_seg); + f->bytes_in_seg = 0; + + do { + len = next_segment(f); + skip(f, len); + f->bytes_in_seg = 0; + } while (len); + + // third packet! + if (!start_packet(f)) return FALSE; + + #ifndef STB_VORBIS_NO_PUSHDATA_API + if (IS_PUSH_MODE(f)) { + if (!is_whole_packet_present(f)) { + // convert error in ogg header to write type + if (f->error == VORBIS_invalid_stream) + f->error = VORBIS_invalid_setup; + return FALSE; + } + } + #endif + + crc32_init(); // always init it, to avoid multithread race conditions + + if (get8_packet(f) != VORBIS_packet_setup) return error(f, VORBIS_invalid_setup); + for (i=0; i < 6; ++i) header[i] = get8_packet(f); + if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup); + + // codebooks + + f->codebook_count = get_bits(f,8) + 1; + f->codebooks = (Codebook *) setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count); + if (f->codebooks == NULL) return error(f, VORBIS_outofmem); + memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count); + for (i=0; i < f->codebook_count; ++i) { + uint32 *values; + int ordered, sorted_count; + int total=0; + uint8 *lengths; + Codebook *c = f->codebooks+i; + CHECK(f); + x = get_bits(f, 8); if (x != 0x42) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); if (x != 0x43) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); if (x != 0x56) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); + c->dimensions = (get_bits(f, 8)<<8) + x; + x = get_bits(f, 8); + y = get_bits(f, 8); + c->entries = (get_bits(f, 8)<<16) + (y<<8) + x; + ordered = get_bits(f,1); + c->sparse = ordered ? 0 : get_bits(f,1); + + if (c->dimensions == 0 && c->entries != 0) return error(f, VORBIS_invalid_setup); + + if (c->sparse) + lengths = (uint8 *) setup_temp_malloc(f, c->entries); + else + lengths = c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); + + if (!lengths) return error(f, VORBIS_outofmem); + + if (ordered) { + int current_entry = 0; + int current_length = get_bits(f,5) + 1; + while (current_entry < c->entries) { + int limit = c->entries - current_entry; + int n = get_bits(f, ilog(limit)); + if (current_length >= 32) return error(f, VORBIS_invalid_setup); + if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); } + memset(lengths + current_entry, current_length, n); + current_entry += n; + ++current_length; + } + } else { + for (j=0; j < c->entries; ++j) { + int present = c->sparse ? get_bits(f,1) : 1; + if (present) { + lengths[j] = get_bits(f, 5) + 1; + ++total; + if (lengths[j] == 32) + return error(f, VORBIS_invalid_setup); + } else { + lengths[j] = NO_CODE; + } + } + } + + if (c->sparse && total >= c->entries >> 2) { + // convert sparse items to non-sparse! + if (c->entries > (int) f->setup_temp_memory_required) + f->setup_temp_memory_required = c->entries; + + c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); + if (c->codeword_lengths == NULL) return error(f, VORBIS_outofmem); + memcpy(c->codeword_lengths, lengths, c->entries); + setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs! + lengths = c->codeword_lengths; + c->sparse = 0; + } + + // compute the size of the sorted tables + if (c->sparse) { + sorted_count = total; + } else { + sorted_count = 0; + #ifndef STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH + for (j=0; j < c->entries; ++j) + if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] != NO_CODE) + ++sorted_count; + #endif + } + + c->sorted_entries = sorted_count; + values = NULL; + + CHECK(f); + if (!c->sparse) { + c->codewords = (uint32 *) setup_malloc(f, sizeof(c->codewords[0]) * c->entries); + if (!c->codewords) return error(f, VORBIS_outofmem); + } else { + unsigned int size; + if (c->sorted_entries) { + c->codeword_lengths = (uint8 *) setup_malloc(f, c->sorted_entries); + if (!c->codeword_lengths) return error(f, VORBIS_outofmem); + c->codewords = (uint32 *) setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries); + if (!c->codewords) return error(f, VORBIS_outofmem); + values = (uint32 *) setup_temp_malloc(f, sizeof(*values) * c->sorted_entries); + if (!values) return error(f, VORBIS_outofmem); + } + size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries; + if (size > f->setup_temp_memory_required) + f->setup_temp_memory_required = size; + } + + if (!compute_codewords(c, lengths, c->entries, values)) { + if (c->sparse) setup_temp_free(f, values, 0); + return error(f, VORBIS_invalid_setup); + } + + if (c->sorted_entries) { + // allocate an extra slot for sentinels + c->sorted_codewords = (uint32 *) setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1)); + if (c->sorted_codewords == NULL) return error(f, VORBIS_outofmem); + // allocate an extra slot at the front so that c->sorted_values[-1] is defined + // so that we can catch that case without an extra if + c->sorted_values = ( int *) setup_malloc(f, sizeof(*c->sorted_values ) * (c->sorted_entries+1)); + if (c->sorted_values == NULL) return error(f, VORBIS_outofmem); + ++c->sorted_values; + c->sorted_values[-1] = -1; + compute_sorted_huffman(c, lengths, values); + } + + if (c->sparse) { + setup_temp_free(f, values, sizeof(*values)*c->sorted_entries); + setup_temp_free(f, c->codewords, sizeof(*c->codewords)*c->sorted_entries); + setup_temp_free(f, lengths, c->entries); + c->codewords = NULL; + } + + compute_accelerated_huffman(c); + + CHECK(f); + c->lookup_type = get_bits(f, 4); + if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup); + if (c->lookup_type > 0) { + uint16 *mults; + c->minimum_value = float32_unpack(get_bits(f, 32)); + c->delta_value = float32_unpack(get_bits(f, 32)); + c->value_bits = get_bits(f, 4)+1; + c->sequence_p = get_bits(f,1); + if (c->lookup_type == 1) { + int values = lookup1_values(c->entries, c->dimensions); + if (values < 0) return error(f, VORBIS_invalid_setup); + c->lookup_values = (uint32) values; + } else { + c->lookup_values = c->entries * c->dimensions; + } + if (c->lookup_values == 0) return error(f, VORBIS_invalid_setup); + mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values); + if (mults == NULL) return error(f, VORBIS_outofmem); + for (j=0; j < (int) c->lookup_values; ++j) { + int q = get_bits(f, c->value_bits); + if (q == EOP) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_invalid_setup); } + mults[j] = q; + } + +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + int len, sparse = c->sparse; + float last=0; + // pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop + if (sparse) { + if (c->sorted_entries == 0) goto skip; + c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions); + } else + c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries * c->dimensions); + if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } + len = sparse ? c->sorted_entries : c->entries; + for (j=0; j < len; ++j) { + unsigned int z = sparse ? c->sorted_values[j] : j; + unsigned int div=1; + for (k=0; k < c->dimensions; ++k) { + int off = (z / div) % c->lookup_values; + float val = mults[off]*c->delta_value + c->minimum_value + last; + c->multiplicands[j*c->dimensions + k] = val; + if (c->sequence_p) + last = val; + if (k+1 < c->dimensions) { + if (div > UINT_MAX / (unsigned int) c->lookup_values) { + setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); + return error(f, VORBIS_invalid_setup); + } + div *= c->lookup_values; + } + } + } + c->lookup_type = 2; + } + else +#endif + { + float last=0; + CHECK(f); + c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values); + if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } + for (j=0; j < (int) c->lookup_values; ++j) { + float val = mults[j] * c->delta_value + c->minimum_value + last; + c->multiplicands[j] = val; + if (c->sequence_p) + last = val; + } + } +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + skip:; +#endif + setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values); + + CHECK(f); + } + CHECK(f); + } + + // time domain transfers (notused) + + x = get_bits(f, 6) + 1; + for (i=0; i < x; ++i) { + uint32 z = get_bits(f, 16); + if (z != 0) return error(f, VORBIS_invalid_setup); + } + + // Floors + f->floor_count = get_bits(f, 6)+1; + f->floor_config = (Floor *) setup_malloc(f, f->floor_count * sizeof(*f->floor_config)); + if (f->floor_config == NULL) return error(f, VORBIS_outofmem); + for (i=0; i < f->floor_count; ++i) { + f->floor_types[i] = get_bits(f, 16); + if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup); + if (f->floor_types[i] == 0) { + Floor0 *g = &f->floor_config[i].floor0; + g->order = get_bits(f,8); + g->rate = get_bits(f,16); + g->bark_map_size = get_bits(f,16); + g->amplitude_bits = get_bits(f,6); + g->amplitude_offset = get_bits(f,8); + g->number_of_books = get_bits(f,4) + 1; + for (j=0; j < g->number_of_books; ++j) + g->book_list[j] = get_bits(f,8); + return error(f, VORBIS_feature_not_supported); + } else { + stbv__floor_ordering p[31*8+2]; + Floor1 *g = &f->floor_config[i].floor1; + int max_class = -1; + g->partitions = get_bits(f, 5); + for (j=0; j < g->partitions; ++j) { + g->partition_class_list[j] = get_bits(f, 4); + if (g->partition_class_list[j] > max_class) + max_class = g->partition_class_list[j]; + } + for (j=0; j <= max_class; ++j) { + g->class_dimensions[j] = get_bits(f, 3)+1; + g->class_subclasses[j] = get_bits(f, 2); + if (g->class_subclasses[j]) { + g->class_masterbooks[j] = get_bits(f, 8); + if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } + for (k=0; k < 1 << g->class_subclasses[j]; ++k) { + g->subclass_books[j][k] = (int16)get_bits(f,8)-1; + if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } + } + g->floor1_multiplier = get_bits(f,2)+1; + g->rangebits = get_bits(f,4); + g->Xlist[0] = 0; + g->Xlist[1] = 1 << g->rangebits; + g->values = 2; + for (j=0; j < g->partitions; ++j) { + int c = g->partition_class_list[j]; + for (k=0; k < g->class_dimensions[c]; ++k) { + g->Xlist[g->values] = get_bits(f, g->rangebits); + ++g->values; + } + } + // precompute the sorting + for (j=0; j < g->values; ++j) { + p[j].x = g->Xlist[j]; + p[j].id = j; + } + qsort(p, g->values, sizeof(p[0]), point_compare); + for (j=0; j < g->values-1; ++j) + if (p[j].x == p[j+1].x) + return error(f, VORBIS_invalid_setup); + for (j=0; j < g->values; ++j) + g->sorted_order[j] = (uint8) p[j].id; + // precompute the neighbors + for (j=2; j < g->values; ++j) { + int low = 0,hi = 0; + neighbors(g->Xlist, j, &low,&hi); + g->neighbors[j][0] = low; + g->neighbors[j][1] = hi; + } + + if (g->values > longest_floorlist) + longest_floorlist = g->values; + } + } + + // Residue + f->residue_count = get_bits(f, 6)+1; + f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(f->residue_config[0])); + if (f->residue_config == NULL) return error(f, VORBIS_outofmem); + memset(f->residue_config, 0, f->residue_count * sizeof(f->residue_config[0])); + for (i=0; i < f->residue_count; ++i) { + uint8 residue_cascade[64]; + Residue *r = f->residue_config+i; + f->residue_types[i] = get_bits(f, 16); + if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup); + r->begin = get_bits(f, 24); + r->end = get_bits(f, 24); + if (r->end < r->begin) return error(f, VORBIS_invalid_setup); + r->part_size = get_bits(f,24)+1; + r->classifications = get_bits(f,6)+1; + r->classbook = get_bits(f,8); + if (r->classbook >= f->codebook_count) return error(f, VORBIS_invalid_setup); + for (j=0; j < r->classifications; ++j) { + uint8 high_bits=0; + uint8 low_bits=get_bits(f,3); + if (get_bits(f,1)) + high_bits = get_bits(f,5); + residue_cascade[j] = high_bits*8 + low_bits; + } + r->residue_books = (short (*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications); + if (r->residue_books == NULL) return error(f, VORBIS_outofmem); + for (j=0; j < r->classifications; ++j) { + for (k=0; k < 8; ++k) { + if (residue_cascade[j] & (1 << k)) { + r->residue_books[j][k] = get_bits(f, 8); + if (r->residue_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } else { + r->residue_books[j][k] = -1; + } + } + } + // precompute the classifications[] array to avoid inner-loop mod/divide + // call it 'classdata' since we already have r->classifications + r->classdata = (uint8 **) setup_malloc(f, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); + if (!r->classdata) return error(f, VORBIS_outofmem); + memset(r->classdata, 0, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); + for (j=0; j < f->codebooks[r->classbook].entries; ++j) { + int classwords = f->codebooks[r->classbook].dimensions; + int temp = j; + r->classdata[j] = (uint8 *) setup_malloc(f, sizeof(r->classdata[j][0]) * classwords); + if (r->classdata[j] == NULL) return error(f, VORBIS_outofmem); + for (k=classwords-1; k >= 0; --k) { + r->classdata[j][k] = temp % r->classifications; + temp /= r->classifications; + } + } + } + + f->mapping_count = get_bits(f,6)+1; + f->mapping = (Mapping *) setup_malloc(f, f->mapping_count * sizeof(*f->mapping)); + if (f->mapping == NULL) return error(f, VORBIS_outofmem); + memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping)); + for (i=0; i < f->mapping_count; ++i) { + Mapping *m = f->mapping + i; + int mapping_type = get_bits(f,16); + if (mapping_type != 0) return error(f, VORBIS_invalid_setup); + m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan)); + if (m->chan == NULL) return error(f, VORBIS_outofmem); + if (get_bits(f,1)) + m->submaps = get_bits(f,4)+1; + else + m->submaps = 1; + if (m->submaps > max_submaps) + max_submaps = m->submaps; + if (get_bits(f,1)) { + m->coupling_steps = get_bits(f,8)+1; + if (m->coupling_steps > f->channels) return error(f, VORBIS_invalid_setup); + for (k=0; k < m->coupling_steps; ++k) { + m->chan[k].magnitude = get_bits(f, ilog(f->channels-1)); + m->chan[k].angle = get_bits(f, ilog(f->channels-1)); + if (m->chan[k].magnitude >= f->channels) return error(f, VORBIS_invalid_setup); + if (m->chan[k].angle >= f->channels) return error(f, VORBIS_invalid_setup); + if (m->chan[k].magnitude == m->chan[k].angle) return error(f, VORBIS_invalid_setup); + } + } else + m->coupling_steps = 0; + + // reserved field + if (get_bits(f,2)) return error(f, VORBIS_invalid_setup); + if (m->submaps > 1) { + for (j=0; j < f->channels; ++j) { + m->chan[j].mux = get_bits(f, 4); + if (m->chan[j].mux >= m->submaps) return error(f, VORBIS_invalid_setup); + } + } else + // @SPECIFICATION: this case is missing from the spec + for (j=0; j < f->channels; ++j) + m->chan[j].mux = 0; + + for (j=0; j < m->submaps; ++j) { + get_bits(f,8); // discard + m->submap_floor[j] = get_bits(f,8); + m->submap_residue[j] = get_bits(f,8); + if (m->submap_floor[j] >= f->floor_count) return error(f, VORBIS_invalid_setup); + if (m->submap_residue[j] >= f->residue_count) return error(f, VORBIS_invalid_setup); + } + } + + // Modes + f->mode_count = get_bits(f, 6)+1; + for (i=0; i < f->mode_count; ++i) { + Mode *m = f->mode_config+i; + m->blockflag = get_bits(f,1); + m->windowtype = get_bits(f,16); + m->transformtype = get_bits(f,16); + m->mapping = get_bits(f,8); + if (m->windowtype != 0) return error(f, VORBIS_invalid_setup); + if (m->transformtype != 0) return error(f, VORBIS_invalid_setup); + if (m->mapping >= f->mapping_count) return error(f, VORBIS_invalid_setup); + } + + flush_packet(f); + + f->previous_length = 0; + + for (i=0; i < f->channels; ++i) { + f->channel_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1); + f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); + f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist); + if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem); + memset(f->channel_buffers[i], 0, sizeof(float) * f->blocksize_1); + #ifdef STB_VORBIS_NO_DEFER_FLOOR + f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); + if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem); + #endif + } + + if (!init_blocksize(f, 0, f->blocksize_0)) return FALSE; + if (!init_blocksize(f, 1, f->blocksize_1)) return FALSE; + f->blocksize[0] = f->blocksize_0; + f->blocksize[1] = f->blocksize_1; + +#ifdef STB_VORBIS_DIVIDE_TABLE + if (integer_divide_table[1][1]==0) + for (i=0; i < DIVTAB_NUMER; ++i) + for (j=1; j < DIVTAB_DENOM; ++j) + integer_divide_table[i][j] = i / j; +#endif + + // compute how much temporary memory is needed + + // 1. + { + uint32 imdct_mem = (f->blocksize_1 * sizeof(float) >> 1); + uint32 classify_mem; + int i,max_part_read=0; + for (i=0; i < f->residue_count; ++i) { + Residue *r = f->residue_config + i; + unsigned int actual_size = f->blocksize_1 / 2; + unsigned int limit_r_begin = r->begin < actual_size ? r->begin : actual_size; + unsigned int limit_r_end = r->end < actual_size ? r->end : actual_size; + int n_read = limit_r_end - limit_r_begin; + int part_read = n_read / r->part_size; + if (part_read > max_part_read) + max_part_read = part_read; + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(uint8 *)); + #else + classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *)); + #endif + + // maximum reasonable partition size is f->blocksize_1 + + f->temp_memory_required = classify_mem; + if (imdct_mem > f->temp_memory_required) + f->temp_memory_required = imdct_mem; + } + + + if (f->alloc.alloc_buffer) { + assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes); + // check if there's enough temp memory so we don't error later + if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned) f->temp_offset) + return error(f, VORBIS_outofmem); + } + + // @TODO: stb_vorbis_seek_start expects first_audio_page_offset to point to a page + // without PAGEFLAG_continued_packet, so this either points to the first page, or + // the page after the end of the headers. It might be cleaner to point to a page + // in the middle of the headers, when that's the page where the first audio packet + // starts, but we'd have to also correctly skip the end of any continued packet in + // stb_vorbis_seek_start. + if (f->next_seg == -1) { + f->first_audio_page_offset = stb_vorbis_get_file_offset(f); + } else { + f->first_audio_page_offset = 0; + } + + return TRUE; +} + +static void vorbis_deinit(stb_vorbis *p) +{ + int i,j; + + setup_free(p, p->vendor); + for (i=0; i < p->comment_list_length; ++i) { + setup_free(p, p->comment_list[i]); + } + setup_free(p, p->comment_list); + + if (p->residue_config) { + for (i=0; i < p->residue_count; ++i) { + Residue *r = p->residue_config+i; + if (r->classdata) { + for (j=0; j < p->codebooks[r->classbook].entries; ++j) + setup_free(p, r->classdata[j]); + setup_free(p, r->classdata); + } + setup_free(p, r->residue_books); + } + } + + if (p->codebooks) { + CHECK(p); + for (i=0; i < p->codebook_count; ++i) { + Codebook *c = p->codebooks + i; + setup_free(p, c->codeword_lengths); + setup_free(p, c->multiplicands); + setup_free(p, c->codewords); + setup_free(p, c->sorted_codewords); + // c->sorted_values[-1] is the first entry in the array + setup_free(p, c->sorted_values ? c->sorted_values-1 : NULL); + } + setup_free(p, p->codebooks); + } + setup_free(p, p->floor_config); + setup_free(p, p->residue_config); + if (p->mapping) { + for (i=0; i < p->mapping_count; ++i) + setup_free(p, p->mapping[i].chan); + setup_free(p, p->mapping); + } + CHECK(p); + for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) { + setup_free(p, p->channel_buffers[i]); + setup_free(p, p->previous_window[i]); + #ifdef STB_VORBIS_NO_DEFER_FLOOR + setup_free(p, p->floor_buffers[i]); + #endif + setup_free(p, p->finalY[i]); + } + for (i=0; i < 2; ++i) { + setup_free(p, p->A[i]); + setup_free(p, p->B[i]); + setup_free(p, p->C[i]); + setup_free(p, p->window[i]); + setup_free(p, p->bit_reverse[i]); + } + #ifndef STB_VORBIS_NO_STDIO + if (p->close_on_free) fclose(p->f); + #endif +} + +void stb_vorbis_close(stb_vorbis *p) +{ + if (p == NULL) return; + vorbis_deinit(p); + setup_free(p,p); +} + +static void vorbis_init(stb_vorbis *p, const stb_vorbis_alloc *z) +{ + memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start + if (z) { + p->alloc = *z; + p->alloc.alloc_buffer_length_in_bytes &= ~7; + p->temp_offset = p->alloc.alloc_buffer_length_in_bytes; + } + p->eof = 0; + p->error = VORBIS__no_error; + p->stream = NULL; + p->codebooks = NULL; + p->page_crc_tests = -1; + #ifndef STB_VORBIS_NO_STDIO + p->close_on_free = FALSE; + p->f = NULL; + #endif +} + +int stb_vorbis_get_sample_offset(stb_vorbis *f) +{ + if (f->current_loc_valid) + return f->current_loc; + else + return -1; +} + +stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f) +{ + stb_vorbis_info d; + d.channels = f->channels; + d.sample_rate = f->sample_rate; + d.setup_memory_required = f->setup_memory_required; + d.setup_temp_memory_required = f->setup_temp_memory_required; + d.temp_memory_required = f->temp_memory_required; + d.max_frame_size = f->blocksize_1 >> 1; + return d; +} + +stb_vorbis_comment stb_vorbis_get_comment(stb_vorbis *f) +{ + stb_vorbis_comment d; + d.vendor = f->vendor; + d.comment_list_length = f->comment_list_length; + d.comment_list = f->comment_list; + return d; +} + +int stb_vorbis_get_error(stb_vorbis *f) +{ + int e = f->error; + f->error = VORBIS__no_error; + return e; +} + +static stb_vorbis * vorbis_alloc(stb_vorbis *f) +{ + stb_vorbis *p = (stb_vorbis *) setup_malloc(f, sizeof(*p)); + return p; +} + +#ifndef STB_VORBIS_NO_PUSHDATA_API + +void stb_vorbis_flush_pushdata(stb_vorbis *f) +{ + f->previous_length = 0; + f->page_crc_tests = 0; + f->discard_samples_deferred = 0; + f->current_loc_valid = FALSE; + f->first_decode = FALSE; + f->samples_output = 0; + f->channel_buffer_start = 0; + f->channel_buffer_end = 0; +} + +static int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len) +{ + int i,n; + for (i=0; i < f->page_crc_tests; ++i) + f->scan[i].bytes_done = 0; + + // if we have room for more scans, search for them first, because + // they may cause us to stop early if their header is incomplete + if (f->page_crc_tests < STB_VORBIS_PUSHDATA_CRC_COUNT) { + if (data_len < 4) return 0; + data_len -= 3; // need to look for 4-byte sequence, so don't miss + // one that straddles a boundary + for (i=0; i < data_len; ++i) { + if (data[i] == 0x4f) { + if (0==memcmp(data+i, ogg_page_header, 4)) { + int j,len; + uint32 crc; + // make sure we have the whole page header + if (i+26 >= data_len || i+27+data[i+26] >= data_len) { + // only read up to this page start, so hopefully we'll + // have the whole page header start next time + data_len = i; + break; + } + // ok, we have it all; compute the length of the page + len = 27 + data[i+26]; + for (j=0; j < data[i+26]; ++j) + len += data[i+27+j]; + // scan everything up to the embedded crc (which we must 0) + crc = 0; + for (j=0; j < 22; ++j) + crc = crc32_update(crc, data[i+j]); + // now process 4 0-bytes + for ( ; j < 26; ++j) + crc = crc32_update(crc, 0); + // len is the total number of bytes we need to scan + n = f->page_crc_tests++; + f->scan[n].bytes_left = len-j; + f->scan[n].crc_so_far = crc; + f->scan[n].goal_crc = data[i+22] + (data[i+23] << 8) + (data[i+24]<<16) + (data[i+25]<<24); + // if the last frame on a page is continued to the next, then + // we can't recover the sample_loc immediately + if (data[i+27+data[i+26]-1] == 255) + f->scan[n].sample_loc = ~0; + else + f->scan[n].sample_loc = data[i+6] + (data[i+7] << 8) + (data[i+ 8]<<16) + (data[i+ 9]<<24); + f->scan[n].bytes_done = i+j; + if (f->page_crc_tests == STB_VORBIS_PUSHDATA_CRC_COUNT) + break; + // keep going if we still have room for more + } + } + } + } + + for (i=0; i < f->page_crc_tests;) { + uint32 crc; + int j; + int n = f->scan[i].bytes_done; + int m = f->scan[i].bytes_left; + if (m > data_len - n) m = data_len - n; + // m is the bytes to scan in the current chunk + crc = f->scan[i].crc_so_far; + for (j=0; j < m; ++j) + crc = crc32_update(crc, data[n+j]); + f->scan[i].bytes_left -= m; + f->scan[i].crc_so_far = crc; + if (f->scan[i].bytes_left == 0) { + // does it match? + if (f->scan[i].crc_so_far == f->scan[i].goal_crc) { + // Houston, we have page + data_len = n+m; // consumption amount is wherever that scan ended + f->page_crc_tests = -1; // drop out of page scan mode + f->previous_length = 0; // decode-but-don't-output one frame + f->next_seg = -1; // start a new page + f->current_loc = f->scan[i].sample_loc; // set the current sample location + // to the amount we'd have decoded had we decoded this page + f->current_loc_valid = f->current_loc != ~0U; + return data_len; + } + // delete entry + f->scan[i] = f->scan[--f->page_crc_tests]; + } else { + ++i; + } + } + + return data_len; +} + +// return value: number of bytes we used +int stb_vorbis_decode_frame_pushdata( + stb_vorbis *f, // the file we're decoding + const uint8 *data, int data_len, // the memory available for decoding + int *channels, // place to write number of float * buffers + float ***output, // place to write float ** array of float * buffers + int *samples // place to write number of output samples + ) +{ + int i; + int len,right,left; + + if (!IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + if (f->page_crc_tests >= 0) { + *samples = 0; + return vorbis_search_for_page_pushdata(f, (uint8 *) data, data_len); + } + + f->stream = (uint8 *) data; + f->stream_end = (uint8 *) data + data_len; + f->error = VORBIS__no_error; + + // check that we have the entire packet in memory + if (!is_whole_packet_present(f)) { + *samples = 0; + return 0; + } + + if (!vorbis_decode_packet(f, &len, &left, &right)) { + // save the actual error we encountered + enum STBVorbisError error = f->error; + if (error == VORBIS_bad_packet_type) { + // flush and resynch + f->error = VORBIS__no_error; + while (get8_packet(f) != EOP) + if (f->eof) break; + *samples = 0; + return (int) (f->stream - data); + } + if (error == VORBIS_continued_packet_flag_invalid) { + if (f->previous_length == 0) { + // we may be resynching, in which case it's ok to hit one + // of these; just discard the packet + f->error = VORBIS__no_error; + while (get8_packet(f) != EOP) + if (f->eof) break; + *samples = 0; + return (int) (f->stream - data); + } + } + // if we get an error while parsing, what to do? + // well, it DEFINITELY won't work to continue from where we are! + stb_vorbis_flush_pushdata(f); + // restore the error that actually made us bail + f->error = error; + *samples = 0; + return 1; + } + + // success! + len = vorbis_finish_frame(f, len, left, right); + for (i=0; i < f->channels; ++i) + f->outputs[i] = f->channel_buffers[i] + left; + + if (channels) *channels = f->channels; + *samples = len; + *output = f->outputs; + return (int) (f->stream - data); +} + +stb_vorbis *stb_vorbis_open_pushdata( + const unsigned char *data, int data_len, // the memory available for decoding + int *data_used, // only defined if result is not NULL + int *error, const stb_vorbis_alloc *alloc) +{ + stb_vorbis *f, p; + vorbis_init(&p, alloc); + p.stream = (uint8 *) data; + p.stream_end = (uint8 *) data + data_len; + p.push_mode = TRUE; + if (!start_decoder(&p)) { + if (p.eof) + *error = VORBIS_need_more_data; + else + *error = p.error; + vorbis_deinit(&p); + return NULL; + } + f = vorbis_alloc(&p); + if (f) { + *f = p; + *data_used = (int) (f->stream - data); + *error = 0; + return f; + } else { + vorbis_deinit(&p); + return NULL; + } +} +#endif // STB_VORBIS_NO_PUSHDATA_API + +unsigned int stb_vorbis_get_file_offset(stb_vorbis *f) +{ + #ifndef STB_VORBIS_NO_PUSHDATA_API + if (f->push_mode) return 0; + #endif + if (USE_MEMORY(f)) return (unsigned int) (f->stream - f->stream_start); + #ifndef STB_VORBIS_NO_STDIO + return (unsigned int) (ftell(f->f) - f->f_start); + #endif +} + +#ifndef STB_VORBIS_NO_PULLDATA_API +// +// DATA-PULLING API +// + +static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) +{ + for(;;) { + int n; + if (f->eof) return 0; + n = get8(f); + if (n == 0x4f) { // page header candidate + unsigned int retry_loc = stb_vorbis_get_file_offset(f); + int i; + // check if we're off the end of a file_section stream + if (retry_loc - 25 > f->stream_len) + return 0; + // check the rest of the header + for (i=1; i < 4; ++i) + if (get8(f) != ogg_page_header[i]) + break; + if (f->eof) return 0; + if (i == 4) { + uint8 header[27]; + uint32 i, crc, goal, len; + for (i=0; i < 4; ++i) + header[i] = ogg_page_header[i]; + for (; i < 27; ++i) + header[i] = get8(f); + if (f->eof) return 0; + if (header[4] != 0) goto invalid; + goal = header[22] + (header[23] << 8) + (header[24]<<16) + ((uint32)header[25]<<24); + for (i=22; i < 26; ++i) + header[i] = 0; + crc = 0; + for (i=0; i < 27; ++i) + crc = crc32_update(crc, header[i]); + len = 0; + for (i=0; i < header[26]; ++i) { + int s = get8(f); + crc = crc32_update(crc, s); + len += s; + } + if (len && f->eof) return 0; + for (i=0; i < len; ++i) + crc = crc32_update(crc, get8(f)); + // finished parsing probable page + if (crc == goal) { + // we could now check that it's either got the last + // page flag set, OR it's followed by the capture + // pattern, but I guess TECHNICALLY you could have + // a file with garbage between each ogg page and recover + // from it automatically? So even though that paranoia + // might decrease the chance of an invalid decode by + // another 2^32, not worth it since it would hose those + // invalid-but-useful files? + if (end) + *end = stb_vorbis_get_file_offset(f); + if (last) { + if (header[5] & 0x04) + *last = 1; + else + *last = 0; + } + set_file_offset(f, retry_loc-1); + return 1; + } + } + invalid: + // not a valid page, so rewind and look for next one + set_file_offset(f, retry_loc); + } + } +} + + +#define SAMPLE_unknown 0xffffffff + +// seeking is implemented with a binary search, which narrows down the range to +// 64K, before using a linear search (because finding the synchronization +// pattern can be expensive, and the chance we'd find the end page again is +// relatively high for small ranges) +// +// two initial interpolation-style probes are used at the start of the search +// to try to bound either side of the binary search sensibly, while still +// working in O(log n) time if they fail. + +static int get_seek_page_info(stb_vorbis *f, ProbedPage *z) +{ + uint8 header[27], lacing[255]; + int i,len; + + // record where the page starts + z->page_start = stb_vorbis_get_file_offset(f); + + // parse the header + getn(f, header, 27); + if (header[0] != 'O' || header[1] != 'g' || header[2] != 'g' || header[3] != 'S') + return 0; + getn(f, lacing, header[26]); + + // determine the length of the payload + len = 0; + for (i=0; i < header[26]; ++i) + len += lacing[i]; + + // this implies where the page ends + z->page_end = z->page_start + 27 + header[26] + len; + + // read the last-decoded sample out of the data + z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 24); + + // restore file state to where we were + set_file_offset(f, z->page_start); + return 1; +} + +// rarely used function to seek back to the preceding page while finding the +// start of a packet +static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset) +{ + unsigned int previous_safe, end; + + // now we want to seek back 64K from the limit + if (limit_offset >= 65536 && limit_offset-65536 >= f->first_audio_page_offset) + previous_safe = limit_offset - 65536; + else + previous_safe = f->first_audio_page_offset; + + set_file_offset(f, previous_safe); + + while (vorbis_find_page(f, &end, NULL)) { + if (end >= limit_offset && stb_vorbis_get_file_offset(f) < limit_offset) + return 1; + set_file_offset(f, end); + } + + return 0; +} + +// implements the search logic for finding a page and starting decoding. if +// the function succeeds, current_loc_valid will be true and current_loc will +// be less than or equal to the provided sample number (the closer the +// better). +static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number) +{ + ProbedPage left, right, mid; + int i, start_seg_with_known_loc, end_pos, page_start; + uint32 delta, stream_length, padding, last_sample_limit; + double offset = 0.0, bytes_per_sample = 0.0; + int probe = 0; + + // find the last page and validate the target sample + stream_length = stb_vorbis_stream_length_in_samples(f); + if (stream_length == 0) return error(f, VORBIS_seek_without_length); + if (sample_number > stream_length) return error(f, VORBIS_seek_invalid); + + // this is the maximum difference between the window-center (which is the + // actual granule position value), and the right-start (which the spec + // indicates should be the granule position (give or take one)). + padding = ((f->blocksize_1 - f->blocksize_0) >> 2); + if (sample_number < padding) + last_sample_limit = 0; + else + last_sample_limit = sample_number - padding; + + left = f->p_first; + while (left.last_decoded_sample == ~0U) { + // (untested) the first page does not have a 'last_decoded_sample' + set_file_offset(f, left.page_end); + if (!get_seek_page_info(f, &left)) goto error; + } + + right = f->p_last; + assert(right.last_decoded_sample != ~0U); + + // starting from the start is handled differently + if (last_sample_limit <= left.last_decoded_sample) { + if (stb_vorbis_seek_start(f)) { + if (f->current_loc > sample_number) + return error(f, VORBIS_seek_failed); + return 1; + } + return 0; + } + + while (left.page_end != right.page_start) { + assert(left.page_end < right.page_start); + // search range in bytes + delta = right.page_start - left.page_end; + if (delta <= 65536) { + // there's only 64K left to search - handle it linearly + set_file_offset(f, left.page_end); + } else { + if (probe < 2) { + if (probe == 0) { + // first probe (interpolate) + double data_bytes = right.page_end - left.page_start; + bytes_per_sample = data_bytes / right.last_decoded_sample; + offset = left.page_start + bytes_per_sample * (last_sample_limit - left.last_decoded_sample); + } else { + // second probe (try to bound the other side) + double error = ((double) last_sample_limit - mid.last_decoded_sample) * bytes_per_sample; + if (error >= 0 && error < 8000) error = 8000; + if (error < 0 && error > -8000) error = -8000; + offset += error * 2; + } + + // ensure the offset is valid + if (offset < left.page_end) + offset = left.page_end; + if (offset > right.page_start - 65536) + offset = right.page_start - 65536; + + set_file_offset(f, (unsigned int) offset); + } else { + // binary search for large ranges (offset by 32K to ensure + // we don't hit the right page) + set_file_offset(f, left.page_end + (delta / 2) - 32768); + } + + if (!vorbis_find_page(f, NULL, NULL)) goto error; + } + + for (;;) { + if (!get_seek_page_info(f, &mid)) goto error; + if (mid.last_decoded_sample != ~0U) break; + // (untested) no frames end on this page + set_file_offset(f, mid.page_end); + assert(mid.page_start < right.page_start); + } + + // if we've just found the last page again then we're in a tricky file, + // and we're close enough (if it wasn't an interpolation probe). + if (mid.page_start == right.page_start) { + if (probe >= 2 || delta <= 65536) + break; + } else { + if (last_sample_limit < mid.last_decoded_sample) + right = mid; + else + left = mid; + } + + ++probe; + } + + // seek back to start of the last packet + page_start = left.page_start; + set_file_offset(f, page_start); + if (!start_page(f)) return error(f, VORBIS_seek_failed); + end_pos = f->end_seg_with_known_loc; + assert(end_pos >= 0); + + for (;;) { + for (i = end_pos; i > 0; --i) + if (f->segments[i-1] != 255) + break; + + start_seg_with_known_loc = i; + + if (start_seg_with_known_loc > 0 || !(f->page_flag & PAGEFLAG_continued_packet)) + break; + + // (untested) the final packet begins on an earlier page + if (!go_to_page_before(f, page_start)) + goto error; + + page_start = stb_vorbis_get_file_offset(f); + if (!start_page(f)) goto error; + end_pos = f->segment_count - 1; + } + + // prepare to start decoding + f->current_loc_valid = FALSE; + f->last_seg = FALSE; + f->valid_bits = 0; + f->packet_bytes = 0; + f->bytes_in_seg = 0; + f->previous_length = 0; + f->next_seg = start_seg_with_known_loc; + + for (i = 0; i < start_seg_with_known_loc; i++) + skip(f, f->segments[i]); + + // start decoding (optimizable - this frame is generally discarded) + if (!vorbis_pump_first_frame(f)) + return 0; + if (f->current_loc > sample_number) + return error(f, VORBIS_seek_failed); + return 1; + +error: + // try to restore the file to a valid state + stb_vorbis_seek_start(f); + return error(f, VORBIS_seek_failed); +} + +// the same as vorbis_decode_initial, but without advancing +static int peek_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) +{ + int bits_read, bytes_read; + + if (!vorbis_decode_initial(f, p_left_start, p_left_end, p_right_start, p_right_end, mode)) + return 0; + + // either 1 or 2 bytes were read, figure out which so we can rewind + bits_read = 1 + ilog(f->mode_count-1); + if (f->mode_config[*mode].blockflag) + bits_read += 2; + bytes_read = (bits_read + 7) / 8; + + f->bytes_in_seg += bytes_read; + f->packet_bytes -= bytes_read; + skip(f, -bytes_read); + if (f->next_seg == -1) + f->next_seg = f->segment_count - 1; + else + f->next_seg--; + f->valid_bits = 0; + + return 1; +} + +int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number) +{ + uint32 max_frame_samples; + + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + // fast page-level search + if (!seek_to_sample_coarse(f, sample_number)) + return 0; + + assert(f->current_loc_valid); + assert(f->current_loc <= sample_number); + + // linear search for the relevant packet + max_frame_samples = (f->blocksize_1*3 - f->blocksize_0) >> 2; + while (f->current_loc < sample_number) { + int left_start, left_end, right_start, right_end, mode, frame_samples; + if (!peek_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode)) + return error(f, VORBIS_seek_failed); + // calculate the number of samples returned by the next frame + frame_samples = right_start - left_start; + if (f->current_loc + frame_samples > sample_number) { + return 1; // the next frame will contain the sample + } else if (f->current_loc + frame_samples + max_frame_samples > sample_number) { + // there's a chance the frame after this could contain the sample + vorbis_pump_first_frame(f); + } else { + // this frame is too early to be relevant + f->current_loc += frame_samples; + f->previous_length = 0; + maybe_start_packet(f); + flush_packet(f); + } + } + // the next frame should start with the sample + if (f->current_loc != sample_number) return error(f, VORBIS_seek_failed); + return 1; +} + +int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) +{ + if (!stb_vorbis_seek_frame(f, sample_number)) + return 0; + + if (sample_number != f->current_loc) { + int n; + uint32 frame_start = f->current_loc; + stb_vorbis_get_frame_float(f, &n, NULL); + assert(sample_number > frame_start); + assert(f->channel_buffer_start + (int) (sample_number-frame_start) <= f->channel_buffer_end); + f->channel_buffer_start += (sample_number - frame_start); + } + + return 1; +} + +int stb_vorbis_seek_start(stb_vorbis *f) +{ + if (IS_PUSH_MODE(f)) { return error(f, VORBIS_invalid_api_mixing); } + set_file_offset(f, f->first_audio_page_offset); + f->previous_length = 0; + f->first_decode = TRUE; + f->next_seg = -1; + return vorbis_pump_first_frame(f); +} + +unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f) +{ + unsigned int restore_offset, previous_safe; + unsigned int end, last_page_loc; + + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + if (!f->total_samples) { + unsigned int last; + uint32 lo,hi; + char header[6]; + + // first, store the current decode position so we can restore it + restore_offset = stb_vorbis_get_file_offset(f); + + // now we want to seek back 64K from the end (the last page must + // be at most a little less than 64K, but let's allow a little slop) + if (f->stream_len >= 65536 && f->stream_len-65536 >= f->first_audio_page_offset) + previous_safe = f->stream_len - 65536; + else + previous_safe = f->first_audio_page_offset; + + set_file_offset(f, previous_safe); + // previous_safe is now our candidate 'earliest known place that seeking + // to will lead to the final page' + + if (!vorbis_find_page(f, &end, &last)) { + // if we can't find a page, we're hosed! + f->error = VORBIS_cant_find_last_page; + f->total_samples = 0xffffffff; + goto done; + } + + // check if there are more pages + last_page_loc = stb_vorbis_get_file_offset(f); + + // stop when the last_page flag is set, not when we reach eof; + // this allows us to stop short of a 'file_section' end without + // explicitly checking the length of the section + while (!last) { + set_file_offset(f, end); + if (!vorbis_find_page(f, &end, &last)) { + // the last page we found didn't have the 'last page' flag + // set. whoops! + break; + } + //previous_safe = last_page_loc+1; // NOTE: not used after this point, but note for debugging + last_page_loc = stb_vorbis_get_file_offset(f); + } + + set_file_offset(f, last_page_loc); + + // parse the header + getn(f, (unsigned char *)header, 6); + // extract the absolute granule position + lo = get32(f); + hi = get32(f); + if (lo == 0xffffffff && hi == 0xffffffff) { + f->error = VORBIS_cant_find_last_page; + f->total_samples = SAMPLE_unknown; + goto done; + } + if (hi) + lo = 0xfffffffe; // saturate + f->total_samples = lo; + + f->p_last.page_start = last_page_loc; + f->p_last.page_end = end; + f->p_last.last_decoded_sample = lo; + + done: + set_file_offset(f, restore_offset); + } + return f->total_samples == SAMPLE_unknown ? 0 : f->total_samples; +} + +float stb_vorbis_stream_length_in_seconds(stb_vorbis *f) +{ + return stb_vorbis_stream_length_in_samples(f) / (float) f->sample_rate; +} + + + +int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output) +{ + int len, right,left,i; + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + if (!vorbis_decode_packet(f, &len, &left, &right)) { + f->channel_buffer_start = f->channel_buffer_end = 0; + return 0; + } + + len = vorbis_finish_frame(f, len, left, right); + for (i=0; i < f->channels; ++i) + f->outputs[i] = f->channel_buffers[i] + left; + + f->channel_buffer_start = left; + f->channel_buffer_end = left+len; + + if (channels) *channels = f->channels; + if (output) *output = f->outputs; + return len; +} + +#ifndef STB_VORBIS_NO_STDIO + +stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc, unsigned int length) +{ + stb_vorbis *f, p; + vorbis_init(&p, alloc); + p.f = file; + p.f_start = (uint32) ftell(file); + p.stream_len = length; + p.close_on_free = close_on_free; + if (start_decoder(&p)) { + f = vorbis_alloc(&p); + if (f) { + *f = p; + vorbis_pump_first_frame(f); + return f; + } + } + if (error) *error = p.error; + vorbis_deinit(&p); + return NULL; +} + +stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc) +{ + unsigned int len, start; + start = (unsigned int) ftell(file); + fseek(file, 0, SEEK_END); + len = (unsigned int) (ftell(file) - start); + fseek(file, start, SEEK_SET); + return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); +} + +stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc) +{ + FILE *f; +#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__) + if (0 != fopen_s(&f, filename, "rb")) + f = NULL; +#else + f = fopen(filename, "rb"); +#endif + if (f) + return stb_vorbis_open_file(f, TRUE, error, alloc); + if (error) *error = VORBIS_file_open_failure; + return NULL; +} +#endif // STB_VORBIS_NO_STDIO + +stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc) +{ + stb_vorbis *f, p; + if (!data) { + if (error) *error = VORBIS_unexpected_eof; + return NULL; + } + vorbis_init(&p, alloc); + p.stream = (uint8 *) data; + p.stream_end = (uint8 *) data + len; + p.stream_start = (uint8 *) p.stream; + p.stream_len = len; + p.push_mode = FALSE; + if (start_decoder(&p)) { + f = vorbis_alloc(&p); + if (f) { + *f = p; + vorbis_pump_first_frame(f); + if (error) *error = VORBIS__no_error; + return f; + } + } + if (error) *error = p.error; + vorbis_deinit(&p); + return NULL; +} + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +#define PLAYBACK_MONO 1 +#define PLAYBACK_LEFT 2 +#define PLAYBACK_RIGHT 4 + +#define L (PLAYBACK_LEFT | PLAYBACK_MONO) +#define C (PLAYBACK_LEFT | PLAYBACK_RIGHT | PLAYBACK_MONO) +#define R (PLAYBACK_RIGHT | PLAYBACK_MONO) + +static int8 channel_position[7][6] = +{ + { 0 }, + { C }, + { L, R }, + { L, C, R }, + { L, R, L, R }, + { L, C, R, L, R }, + { L, C, R, L, R, C }, +}; + + +#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT + typedef union { + float f; + int i; + } float_conv; + typedef char stb_vorbis_float_size_test[sizeof(float)==4 && sizeof(int) == 4]; + #define FASTDEF(x) float_conv x + // add (1<<23) to convert to int, then divide by 2^SHIFT, then add 0.5/2^SHIFT to round + #define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT)) + #define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22)) + #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s)) + #define check_endianness() +#else + #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s)))) + #define check_endianness() + #define FASTDEF(x) +#endif + +static void copy_samples(short *dest, float *src, int len) +{ + int i; + check_endianness(); + for (i=0; i < len; ++i) { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp, src[i],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + dest[i] = v; + } +} + +static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len) +{ + #define STB_BUFFER_SIZE 32 + float buffer[STB_BUFFER_SIZE]; + int i,j,o,n = STB_BUFFER_SIZE; + check_endianness(); + for (o = 0; o < len; o += STB_BUFFER_SIZE) { + memset(buffer, 0, sizeof(buffer)); + if (o + n > len) n = len - o; + for (j=0; j < num_c; ++j) { + if (channel_position[num_c][j] & mask) { + for (i=0; i < n; ++i) + buffer[i] += data[j][d_offset+o+i]; + } + } + for (i=0; i < n; ++i) { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + output[o+i] = v; + } + } + #undef STB_BUFFER_SIZE +} + +static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len) +{ + #define STB_BUFFER_SIZE 32 + float buffer[STB_BUFFER_SIZE]; + int i,j,o,n = STB_BUFFER_SIZE >> 1; + // o is the offset in the source data + check_endianness(); + for (o = 0; o < len; o += STB_BUFFER_SIZE >> 1) { + // o2 is the offset in the output data + int o2 = o << 1; + memset(buffer, 0, sizeof(buffer)); + if (o + n > len) n = len - o; + for (j=0; j < num_c; ++j) { + int m = channel_position[num_c][j] & (PLAYBACK_LEFT | PLAYBACK_RIGHT); + if (m == (PLAYBACK_LEFT | PLAYBACK_RIGHT)) { + for (i=0; i < n; ++i) { + buffer[i*2+0] += data[j][d_offset+o+i]; + buffer[i*2+1] += data[j][d_offset+o+i]; + } + } else if (m == PLAYBACK_LEFT) { + for (i=0; i < n; ++i) { + buffer[i*2+0] += data[j][d_offset+o+i]; + } + } else if (m == PLAYBACK_RIGHT) { + for (i=0; i < n; ++i) { + buffer[i*2+1] += data[j][d_offset+o+i]; + } + } + } + for (i=0; i < (n<<1); ++i) { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + output[o2+i] = v; + } + } + #undef STB_BUFFER_SIZE +} + +static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples) +{ + int i; + if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { + static int channel_selector[3][2] = { {0}, {PLAYBACK_MONO}, {PLAYBACK_LEFT, PLAYBACK_RIGHT} }; + for (i=0; i < buf_c; ++i) + compute_samples(channel_selector[buf_c][i], buffer[i]+b_offset, data_c, data, d_offset, samples); + } else { + int limit = buf_c < data_c ? buf_c : data_c; + for (i=0; i < limit; ++i) + copy_samples(buffer[i]+b_offset, data[i]+d_offset, samples); + for ( ; i < buf_c; ++i) + memset(buffer[i]+b_offset, 0, sizeof(short) * samples); + } +} + +int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples) +{ + float **output = NULL; + int len = stb_vorbis_get_frame_float(f, NULL, &output); + if (len > num_samples) len = num_samples; + if (len) + convert_samples_short(num_c, buffer, 0, f->channels, output, 0, len); + return len; +} + +static void convert_channels_short_interleaved(int buf_c, short *buffer, int data_c, float **data, int d_offset, int len) +{ + int i; + check_endianness(); + if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { + assert(buf_c == 2); + for (i=0; i < buf_c; ++i) + compute_stereo_samples(buffer, data_c, data, d_offset, len); + } else { + int limit = buf_c < data_c ? buf_c : data_c; + int j; + for (j=0; j < len; ++j) { + for (i=0; i < limit; ++i) { + FASTDEF(temp); + float f = data[i][d_offset+j]; + int v = FAST_SCALED_FLOAT_TO_INT(temp, f,15);//data[i][d_offset+j],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + *buffer++ = v; + } + for ( ; i < buf_c; ++i) + *buffer++ = 0; + } + } +} + +int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts) +{ + float **output; + int len; + if (num_c == 1) return stb_vorbis_get_frame_short(f,num_c,&buffer, num_shorts); + len = stb_vorbis_get_frame_float(f, NULL, &output); + if (len) { + if (len*num_c > num_shorts) len = num_shorts / num_c; + convert_channels_short_interleaved(num_c, buffer, f->channels, output, 0, len); + } + return len; +} + +int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts) +{ + float **outputs; + int len = num_shorts / channels; + int n=0; + while (n < len) { + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= len) k = len - n; + if (k) + convert_channels_short_interleaved(channels, buffer, f->channels, f->channel_buffers, f->channel_buffer_start, k); + buffer += k*channels; + n += k; + f->channel_buffer_start += k; + if (n == len) break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; + } + return n; +} + +int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int len) +{ + float **outputs; + int n=0; + while (n < len) { + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= len) k = len - n; + if (k) + convert_samples_short(channels, buffer, n, f->channels, f->channel_buffers, f->channel_buffer_start, k); + n += k; + f->channel_buffer_start += k; + if (n == len) break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; + } + return n; +} + +#ifndef STB_VORBIS_NO_STDIO +int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output) +{ + int data_len, offset, total, limit, error; + short *data; + stb_vorbis *v = stb_vorbis_open_filename(filename, &error, NULL); + if (v == NULL) return -1; + limit = v->channels * 4096; + *channels = v->channels; + if (sample_rate) + *sample_rate = v->sample_rate; + offset = data_len = 0; + total = limit; + data = (short *) malloc(total * sizeof(*data)); + if (data == NULL) { + stb_vorbis_close(v); + return -2; + } + for (;;) { + int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); + if (n == 0) break; + data_len += n; + offset += n * v->channels; + if (offset + limit > total) { + short *data2; + total *= 2; + data2 = (short *) realloc(data, total * sizeof(*data)); + if (data2 == NULL) { + free(data); + stb_vorbis_close(v); + return -2; + } + data = data2; + } + } + *output = data; + stb_vorbis_close(v); + return data_len; +} +#endif // NO_STDIO + +int stb_vorbis_decode_memory(const uint8 *mem, int len, int *channels, int *sample_rate, short **output) +{ + int data_len, offset, total, limit, error; + short *data; + stb_vorbis *v = stb_vorbis_open_memory(mem, len, &error, NULL); + if (v == NULL) return -1; + limit = v->channels * 4096; + *channels = v->channels; + if (sample_rate) + *sample_rate = v->sample_rate; + offset = data_len = 0; + total = limit; + data = (short *) malloc(total * sizeof(*data)); + if (data == NULL) { + stb_vorbis_close(v); + return -2; + } + for (;;) { + int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); + if (n == 0) break; + data_len += n; + offset += n * v->channels; + if (offset + limit > total) { + short *data2; + total *= 2; + data2 = (short *) realloc(data, total * sizeof(*data)); + if (data2 == NULL) { + free(data); + stb_vorbis_close(v); + return -2; + } + data = data2; + } + } + *output = data; + stb_vorbis_close(v); + return data_len; +} +#endif // STB_VORBIS_NO_INTEGER_CONVERSION + +int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats) +{ + float **outputs; + int len = num_floats / channels; + int n=0; + int z = f->channels; + if (z > channels) z = channels; + while (n < len) { + int i,j; + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= len) k = len - n; + for (j=0; j < k; ++j) { + for (i=0; i < z; ++i) + *buffer++ = f->channel_buffers[i][f->channel_buffer_start+j]; + for ( ; i < channels; ++i) + *buffer++ = 0; + } + n += k; + f->channel_buffer_start += k; + if (n == len) + break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) + break; + } + return n; +} + +int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples) +{ + float **outputs; + int n=0; + int z = f->channels; + if (z > channels) z = channels; + while (n < num_samples) { + int i; + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= num_samples) k = num_samples - n; + if (k) { + for (i=0; i < z; ++i) + memcpy(buffer[i]+n, f->channel_buffers[i]+f->channel_buffer_start, sizeof(float)*k); + for ( ; i < channels; ++i) + memset(buffer[i]+n, 0, sizeof(float) * k); + } + n += k; + f->channel_buffer_start += k; + if (n == num_samples) + break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) + break; + } + return n; +} +#endif // STB_VORBIS_NO_PULLDATA_API + +/* Version history + 1.17 - 2019-07-08 - fix CVE-2019-13217, -13218, -13219, -13220, -13221, -13222, -13223 + found with Mayhem by ForAllSecure + 1.16 - 2019-03-04 - fix warnings + 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found + 1.14 - 2018-02-11 - delete bogus dealloca usage + 1.13 - 2018-01-29 - fix truncation of last frame (hopefully) + 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files + 1.11 - 2017-07-23 - fix MinGW compilation + 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory + 1.09 - 2016-04-04 - back out 'avoid discarding last frame' fix from previous version + 1.08 - 2016-04-02 - fixed multiple warnings; fix setup memory leaks; + avoid discarding last frame of audio data + 1.07 - 2015-01-16 - fixed some warnings, fix mingw, const-correct API + some more crash fixes when out of memory or with corrupt files + 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson) + some crash fixes when out of memory or with corrupt files + 1.05 - 2015-04-19 - don't define __forceinline if it's redundant + 1.04 - 2014-08-27 - fix missing const-correct case in API + 1.03 - 2014-08-07 - Warning fixes + 1.02 - 2014-07-09 - Declare qsort compare function _cdecl on windows + 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float + 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in multichannel + (API change) report sample rate for decode-full-file funcs + 0.99996 - bracket #include for macintosh compilation by Laurent Gomila + 0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem + 0.99994 - change fast-float-to-int to work in single-precision FPU mode, remove endian-dependence + 0.99993 - remove assert that fired on legal files with empty tables + 0.99992 - rewind-to-start + 0.99991 - bugfix to stb_vorbis_get_samples_short by Bernhard Wodo + 0.9999 - (should have been 0.99990) fix no-CRT support, compiling as C++ + 0.9998 - add a full-decode function with a memory source + 0.9997 - fix a bug in the read-from-FILE case in 0.9996 addition + 0.9996 - query length of vorbis stream in samples/seconds + 0.9995 - bugfix to another optimization that only happened in certain files + 0.9994 - bugfix to one of the optimizations that caused significant (but inaudible?) errors + 0.9993 - performance improvements; runs in 99% to 104% of time of reference implementation + 0.9992 - performance improvement of IMDCT; now performs close to reference implementation + 0.9991 - performance improvement of IMDCT + 0.999 - (should have been 0.9990) performance improvement of IMDCT + 0.998 - no-CRT support from Casey Muratori + 0.997 - bugfixes for bugs found by Terje Mathisen + 0.996 - bugfix: fast-huffman decode initialized incorrectly for sparse codebooks; fixing gives 10% speedup - found by Terje Mathisen + 0.995 - bugfix: fix to 'effective' overrun detection - found by Terje Mathisen + 0.994 - bugfix: garbage decode on final VQ symbol of a non-multiple - found by Terje Mathisen + 0.993 - bugfix: pushdata API required 1 extra byte for empty page (failed to consume final page if empty) - found by Terje Mathisen + 0.992 - fixes for MinGW warning + 0.991 - turn fast-float-conversion on by default + 0.990 - fix push-mode seek recovery if you seek into the headers + 0.98b - fix to bad release of 0.98 + 0.98 - fix push-mode seek recovery; robustify float-to-int and support non-fast mode + 0.97 - builds under c++ (typecasting, don't use 'class' keyword) + 0.96 - somehow MY 0.95 was right, but the web one was wrong, so here's my 0.95 rereleased as 0.96, fixes a typo in the clamping code + 0.95 - clamping code for 16-bit functions + 0.94 - not publically released + 0.93 - fixed all-zero-floor case (was decoding garbage) + 0.92 - fixed a memory leak + 0.91 - conditional compiles to omit parts of the API and the infrastructure to support them: STB_VORBIS_NO_PULLDATA_API, STB_VORBIS_NO_PUSHDATA_API, STB_VORBIS_NO_STDIO, STB_VORBIS_NO_INTEGER_CONVERSION + 0.90 - first public release +*/ + +#endif // STB_VORBIS_HEADER_ONLY + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_voxel_render.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_voxel_render.h new file mode 100644 index 0000000..2e7a372 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_voxel_render.h @@ -0,0 +1,3807 @@ +// stb_voxel_render.h - v0.89 - Sean Barrett, 2015 - public domain +// +// This library helps render large-scale "voxel" worlds for games, +// in this case, one with blocks that can have textures and that +// can also be a few shapes other than cubes. +// +// Video introduction: +// http://www.youtube.com/watch?v=2vnTtiLrV1w +// +// Minecraft-viewer sample app (not very simple though): +// http://github.com/nothings/stb/tree/master/tests/caveview +// +// It works by creating triangle meshes. The library includes +// +// - converter from dense 3D arrays of block info to vertex mesh +// - vertex & fragment shaders for the vertex mesh +// - assistance in setting up shader state +// +// For portability, none of the library code actually accesses +// the 3D graphics API. (At the moment, it's not actually portable +// since the shaders are GLSL only, but patches are welcome.) +// +// You have to do all the caching and tracking of vertex buffers +// yourself. However, you could also try making a game with +// a small enough world that it's fully loaded rather than +// streaming. Currently the preferred vertex format is 20 bytes +// per quad. There are designs to allow much more compact formats +// with a slight reduction in shader features, but no roadmap +// for actually implementing them. +// +// +// USAGE +// +// #define the symbol STB_VOXEL_RENDER_IMPLEMENTATION in *one* +// C/C++ file before the #include of this file; the implementation +// will be generated in that file. +// +// If you define the symbols STB_VOXEL_RENDER_STATIC, then the +// implementation will be private to that file. +// +// +// FEATURES +// +// - you can choose textured blocks with the features below, +// or colored voxels with 2^24 colors and no textures. +// +// - voxels are mostly just cubes, but there's support for +// half-height cubes and diagonal slopes, half-height +// diagonals, and even odder shapes especially for doing +// more-continuous "ground". +// +// - texture coordinates are projections along one of the major +// axes, with the per-texture scaling. +// +// - a number of aspects of the shader and the vertex format +// are configurable; the library generally takes care of +// coordinating the vertex format with the mesh for you. +// +// +// FEATURES (SHADER PERSPECTIVE) +// +// - vertices aligned on integer lattice, z on multiples of 0.5 +// - per-vertex "lighting" or "ambient occlusion" value (6 bits) +// - per-vertex texture crossfade (3 bits) +// +// - per-face texture #1 id (8-bit index into array texture) +// - per-face texture #2 id (8-bit index into second array texture) +// - per-face color (6-bit palette index, 2 bits of per-texture boolean enable) +// - per-face 5-bit normal for lighting calculations & texture coord computation +// - per-face 2-bit texture matrix rotation to rotate faces +// +// - indexed-by-texture-id scale factor (separate for texture #1 and texture #2) +// - indexed-by-texture-#2-id blend mode (alpha composite or modulate/multiply); +// the first is good for decals, the second for detail textures, "light maps", +// etc; both modes are controlled by texture #2's alpha, scaled by the +// per-vertex texture crossfade and the per-face color (if enabled on texture #2); +// modulate/multiply multiplies by an extra factor of 2.0 so that if you +// make detail maps whose average brightness is 0.5 everything works nicely. +// +// - ambient lighting: half-lambert directional plus constant, all scaled by vertex ao +// - face can be fullbright (emissive), controlled by per-face color +// - installable lighting, with default single-point-light +// - installable fog, with default hacked smoothstep +// +// Note that all the variations of lighting selection and texture +// blending are run-time conditions in the shader, so they can be +// intermixed in a single mesh. +// +// +// INTEGRATION ARC +// +// The way to get this library to work from scratch is to do the following: +// +// Step 1. define STBVOX_CONFIG_MODE to 0 +// +// This mode uses only vertex attributes and uniforms, and is easiest +// to get working. It requires 32 bytes per quad and limits the +// size of some tables to avoid hitting uniform limits. +// +// Step 2. define STBVOX_CONFIG_MODE to 1 +// +// This requires using a texture buffer to store the quad data, +// reducing the size to 20 bytes per quad. +// +// Step 3: define STBVOX_CONFIG_PREFER_TEXBUFFER +// +// This causes some uniforms to be stored as texture buffers +// instead. This increases the size of some of those tables, +// and avoids a potential slow path (gathering non-uniform +// data from uniforms) on some hardware. +// +// In the future I might add additional modes that have significantly +// smaller meshes but reduce features, down as small as 6 bytes per quad. +// See elsewhere in this file for a table of candidate modes. Switching +// to a mode will require changing some of your mesh creation code, but +// everything else should be seamless. (And I'd like to change the API +// so that mesh creation is data-driven the way the uniforms are, and +// then you wouldn't even have to change anything but the mode number.) +// +// +// IMPROVEMENTS FOR SHIP-WORTHY PROGRAMS USING THIS LIBRARY +// +// I currently tolerate a certain level of "bugginess" in this library. +// +// I'm referring to things which look a little wrong (as long as they +// don't cause holes or cracks in the output meshes), or things which +// do not produce as optimal a mesh as possible. Notable examples: +// +// - incorrect lighting on slopes +// - inefficient meshes for vheight blocks +// +// I am willing to do the work to improve these things if someone is +// going to ship a substantial program that would be improved by them. +// (It need not be commercial, nor need it be a game.) I just didn't +// want to do the work up front if it might never be leveraged. So just +// submit a bug report as usual (github is preferred), but add a note +// that this is for a thing that is really going to ship. (That means +// you need to be far enough into the project that it's clear you're +// committed to it; not during early exploratory development.) +// +// +// VOXEL MESH API +// +// Context +// +// To understand the API, make sure you first understand the feature set +// listed above. +// +// Because the vertices are compact, they have very limited spatial +// precision. Thus a single mesh can only contain the data for a limited +// area. To make very large voxel maps, you'll need to build multiple +// vertex buffers. (But you want this anyway for frustum culling.) +// +// Each generated mesh has three components: +// - vertex data (vertex buffer) +// - face data (optional, stored in texture buffer) +// - mesh transform (uniforms) +// +// Once you've generated the mesh with this library, it's up to you +// to upload it to the GPU, to keep track of the state, and to render +// it. +// +// Concept +// +// The basic design is that you pass in one or more 3D arrays; each array +// is (typically) one-byte-per-voxel and contains information about one +// or more properties of some particular voxel property. +// +// Because there is so much per-vertex and per-face data possible +// in the output, and each voxel can have 6 faces and 8 vertices, it +// would require an very large data structure to describe all +// of the possibilities, and this would cause the mesh-creation +// process to be slow. Instead, the API provides multiple ways +// to express each property, some more compact, others less so; +// each such way has some limitations on what it can express. +// +// Note that there are so many paths and combinations, not all of them +// have been tested. Just report bugs and I'll fix 'em. +// +// Details +// +// See the API documentation in the header-file section. +// +// +// CONTRIBUTORS +// +// Features Porting Bugfixes & Warnings +// Sean Barrett github:r-leyh Jesus Fernandez +// Miguel Lechon github:Arbeiterunfallversicherungsgesetz +// Thomas Frase James Hofmann +// Stephen Olsen github:guitarfreak +// +// VERSION HISTORY +// +// 0.89 (2020-02-02) bugfix in sample code +// 0.88 (2019-03-04) fix warnings +// 0.87 (2019-02-25) fix warning +// 0.86 (2019-02-07) fix typos in comments +// 0.85 (2017-03-03) add block_selector (by guitarfreak) +// 0.84 (2016-04-02) fix GLSL syntax error on glModelView path +// 0.83 (2015-09-13) remove non-constant struct initializers to support more compilers +// 0.82 (2015-08-01) added input.packed_compact to store rot, vheight & texlerp efficiently +// fix broken tex_overlay2 +// 0.81 (2015-05-28) fix broken STBVOX_CONFIG_OPTIMIZED_VHEIGHT +// 0.80 (2015-04-11) fix broken STBVOX_CONFIG_ROTATION_IN_LIGHTING refactoring +// change STBVOX_MAKE_LIGHTING to STBVOX_MAKE_LIGHTING_EXT so +// that header defs don't need to see config vars +// add STBVOX_CONFIG_VHEIGHT_IN_LIGHTING and other vheight fixes +// added documentation for vheight ("weird slopes") +// 0.79 (2015-04-01) fix the missing types from 0.78; fix string constants being const +// 0.78 (2015-04-02) bad "#else", compile as C++ +// 0.77 (2015-04-01) documentation tweaks, rename config var to STB_VOXEL_RENDER_STATIC +// 0.76 (2015-04-01) typos, signed/unsigned shader issue, more documentation +// 0.75 (2015-04-01) initial release +// +// +// HISTORICAL FOUNDATION +// +// stb_voxel_render 20-byte quads 2015/01 +// zmc engine 32-byte quads 2013/12 +// zmc engine 96-byte quads 2011/10 +// +// +// LICENSE +// +// See end of file for license information. + +#ifndef INCLUDE_STB_VOXEL_RENDER_H +#define INCLUDE_STB_VOXEL_RENDER_H + +#include + +typedef struct stbvox_mesh_maker stbvox_mesh_maker; +typedef struct stbvox_input_description stbvox_input_description; + +#ifdef STB_VOXEL_RENDER_STATIC +#define STBVXDEC static +#else +#define STBVXDEC extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// CONFIGURATION MACROS +// +// #define STBVOX_CONFIG_MODE // REQUIRED +// Configures the overall behavior of stb_voxel_render. This +// can affect the shaders, the uniform info, and other things. +// (If you need more than one mode in the same app, you can +// use STB_VOXEL_RENDER_STATIC to create multiple versions +// in separate files, and then wrap them.) +// +// Mode value Meaning +// 0 Textured blocks, 32-byte quads +// 1 Textured blocks, 20-byte quads +// 20 Untextured blocks, 32-byte quads +// 21 Untextured blocks, 20-byte quads +// +// +// #define STBVOX_CONFIG_PRECISION_Z // OPTIONAL +// Defines the number of bits of fractional position for Z. +// Only 0 or 1 are valid. 1 is the default. If 0, then a +// single mesh has twice the legal Z range; e.g. in +// modes 0,1,20,21, Z in the mesh can extend to 511 instead +// of 255. However, half-height blocks cannot be used. +// +// All of the following are just #ifdef tested so need no values, and are optional. +// +// STBVOX_CONFIG_BLOCKTYPE_SHORT +// use unsigned 16-bit values for 'blocktype' in the input instead of 8-bit values +// +// STBVOX_CONFIG_OPENGL_MODELVIEW +// use the gl_ModelView matrix rather than the explicit uniform +// +// STBVOX_CONFIG_HLSL +// NOT IMPLEMENTED! Define HLSL shaders instead of GLSL shaders +// +// STBVOX_CONFIG_PREFER_TEXBUFFER +// Stores many of the uniform arrays in texture buffers instead, +// so they can be larger and may be more efficient on some hardware. +// +// STBVOX_CONFIG_LIGHTING_SIMPLE +// Creates a simple lighting engine with a single point light source +// in addition to the default half-lambert ambient light. +// +// STBVOX_CONFIG_LIGHTING +// Declares a lighting function hook; you must append a lighting function +// to the shader before compiling it: +// vec3 compute_lighting(vec3 pos, vec3 norm, vec3 albedo, vec3 ambient); +// 'ambient' is the half-lambert ambient light with vertex ambient-occlusion applied +// +// STBVOX_CONFIG_FOG_SMOOTHSTEP +// Defines a simple unrealistic fog system designed to maximize +// unobscured view distance while not looking too weird when things +// emerge from the fog. Configured using an extra array element +// in the STBVOX_UNIFORM_ambient uniform. +// +// STBVOX_CONFIG_FOG +// Defines a fog function hook; you must append a fog function to +// the shader before compiling it: +// vec3 compute_fog(vec3 color, vec3 relative_pos, float fragment_alpha); +// "color" is the incoming pre-fogged color, fragment_alpha is the alpha value, +// and relative_pos is the vector from the point to the camera in worldspace +// +// STBVOX_CONFIG_DISABLE_TEX2 +// This disables all processing of texture 2 in the shader in case +// you don't use it. Eventually this could be replaced with a mode +// that omits the unused data entirely. +// +// STBVOX_CONFIG_TEX1_EDGE_CLAMP +// STBVOX_CONFIG_TEX2_EDGE_CLAMP +// If you want to edge clamp the textures, instead of letting them wrap, +// set this flag. By default stb_voxel_render relies on texture wrapping +// to simplify texture coordinate generation. This flag forces it to do +// it correctly, although there can still be minor artifacts. +// +// STBVOX_CONFIG_ROTATION_IN_LIGHTING +// Changes the meaning of the 'lighting' mesher input variable to also +// store the rotation; see later discussion. +// +// STBVOX_CONFIG_VHEIGHT_IN_LIGHTING +// Changes the meaning of the 'lighting' mesher input variable to also +// store the vheight; see later discussion. Cannot use both this and +// the previous variable. +// +// STBVOX_CONFIG_PREMULTIPLIED_ALPHA +// Adjusts the shader calculations on the assumption that tex1.rgba, +// tex2.rgba, and color.rgba all use premultiplied values, and that +// the output of the fragment shader should be premultiplied. +// +// STBVOX_CONFIG_UNPREMULTIPLY +// Only meaningful if STBVOX_CONFIG_PREMULTIPLIED_ALPHA is defined. +// Changes the behavior described above so that the inputs are +// still premultiplied alpha, but the output of the fragment +// shader is not premultiplied alpha. This is needed when allowing +// non-unit alpha values but not doing alpha-blending (for example +// when alpha testing). +// + +////////////////////////////////////////////////////////////////////////////// +// +// MESHING +// +// A mesh represents a (typically) small chunk of a larger world. +// Meshes encode coordinates using small integers, so those +// coordinates must be relative to some base location. +// All of the coordinates in the functions below use +// these relative coordinates unless explicitly stated +// otherwise. +// +// Input to the meshing step is documented further down + +STBVXDEC void stbvox_init_mesh_maker(stbvox_mesh_maker *mm); +// Call this function to initialize a mesh-maker context structure +// used to build meshes. You should have one context per thread +// that's building meshes. + +STBVXDEC void stbvox_set_buffer(stbvox_mesh_maker *mm, int mesh, int slot, void *buffer, size_t len); +// Call this to set the buffer into which stbvox will write the mesh +// it creates. It can build more than one mesh in parallel (distinguished +// by the 'mesh' parameter), and each mesh can be made up of more than +// one buffer (distinguished by the 'slot' parameter). +// +// Multiple meshes are under your control; use the 'selector' input +// variable to choose which mesh each voxel's vertices are written to. +// For example, you can use this to generate separate meshes for opaque +// and transparent data. +// +// You can query the number of slots by calling stbvox_get_buffer_count +// described below. The meaning of the buffer for each slot depends +// on STBVOX_CONFIG_MODE. +// +// In mode 0 & mode 20, there is only one slot. The mesh data for that +// slot is two interleaved vertex attributes: attr_vertex, a single +// 32-bit uint, and attr_face, a single 32-bit uint. +// +// In mode 1 & mode 21, there are two slots. The first buffer should +// be four times as large as the second buffer. The first buffer +// contains a single vertex attribute: 'attr_vertex', a single 32-bit uint. +// The second buffer contains texture buffer data (an array of 32-bit uints) +// that will be accessed through the sampler identified by STBVOX_UNIFORM_face_data. + +STBVXDEC int stbvox_get_buffer_count(stbvox_mesh_maker *mm); +// Returns the number of buffers needed per mesh as described above. + +STBVXDEC int stbvox_get_buffer_size_per_quad(stbvox_mesh_maker *mm, int slot); +// Returns how much of a given buffer will get used per quad. This +// allows you to choose correct relative sizes for each buffer, although +// the values are fixed based on the configuration you've selected at +// compile time, and the details are described in stbvox_set_buffer. + +STBVXDEC void stbvox_set_default_mesh(stbvox_mesh_maker *mm, int mesh); +// Selects which mesh the mesher will output to (see previous function) +// if the input doesn't specify a per-voxel selector. (I doubt this is +// useful, but it's here just in case.) + +STBVXDEC stbvox_input_description *stbvox_get_input_description(stbvox_mesh_maker *mm); +// This function call returns a pointer to the stbvox_input_description part +// of stbvox_mesh_maker (which you should otherwise treat as opaque). You +// zero this structure, then fill out the relevant pointers to the data +// describing your voxel object/world. +// +// See further documentation at the description of stbvox_input_description below. + +STBVXDEC void stbvox_set_input_stride(stbvox_mesh_maker *mm, int x_stride_in_elements, int y_stride_in_elements); +// This sets the stride between successive elements of the 3D arrays +// in the stbvox_input_description. Z values are always stored consecutively. +// (The preferred coordinate system for stbvox is X right, Y forwards, Z up.) + +STBVXDEC void stbvox_set_input_range(stbvox_mesh_maker *mm, int x0, int y0, int z0, int x1, int y1, int z1); +// This sets the range of values in the 3D array for the voxels that +// the mesh generator will convert. The lower values are inclusive, +// the higher values are exclusive, so (0,0,0) to (16,16,16) generates +// mesh data associated with voxels up to (15,15,15) but no higher. +// +// The mesh generate generates faces at the boundary between open space +// and solid space but associates them with the solid space, so if (15,0,0) +// is open and (16,0,0) is solid, then the mesh will contain the boundary +// between them if x0 <= 16 and x1 > 16. +// +// Note that the mesh generator will access array elements 1 beyond the +// limits set in these parameters. For example, if you set the limits +// to be (0,0,0) and (16,16,16), then the generator will access all of +// the voxels between (-1,-1,-1) and (16,16,16), including (16,16,16). +// You may have to do pointer arithmetic to make it work. +// +// For example, caveview processes mesh chunks that are 32x32x16, but it +// does this using input buffers that are 34x34x18. +// +// The lower limits are x0 >= 0, y0 >= 0, and z0 >= 0. +// +// The upper limits are mode dependent, but all the current methods are +// limited to x1 < 127, y1 < 127, z1 < 255. Note that these are not +// powers of two; if you want to use power-of-two chunks (to make +// it efficient to decide which chunk a coordinate falls in), you're +// limited to at most x1=64, y1=64, z1=128. For classic Minecraft-style +// worlds with limited vertical extent, I recommend using a single +// chunk for the entire height, which limits the height to 255 blocks +// (one less than Minecraft), and only chunk the map in X & Y. + +STBVXDEC int stbvox_make_mesh(stbvox_mesh_maker *mm); +// Call this function to create mesh data for the currently configured +// set of input data. This appends to the currently configured mesh output +// buffer. Returns 1 on success. If there is not enough room in the buffer, +// it outputs as much as it can, and returns 0; you need to switch output +// buffers (either by calling stbvox_set_buffer to set new buffers, or +// by copying the data out and calling stbvox_reset_buffers), and then +// call this function again without changing any of the input parameters. +// +// Note that this function appends; you can call it multiple times to +// build a single mesh. For example, caveview uses chunks that are +// 32x32x255, but builds the mesh for it by processing 32x32x16 at atime +// (this is faster as it is reuses the same 34x34x18 input buffers rather +// than needing 34x34x257 input buffers). + +// Once you're done creating a mesh into a given buffer, +// consider the following functions: + +STBVXDEC int stbvox_get_quad_count(stbvox_mesh_maker *mm, int mesh); +// Returns the number of quads in the mesh currently generated by mm. +// This is the sum of all consecutive stbvox_make_mesh runs appending +// to the same buffer. 'mesh' distinguishes between the multiple user +// meshes available via 'selector' or stbvox_set_default_mesh. +// +// Typically you use this function when you're done building the mesh +// and want to record how to draw it. +// +// Note that there are no index buffers; the data stored in the buffers +// should be drawn as quads (e.g. with GL_QUAD); if your API does not +// support quads, you can create a single index buffer large enough to +// draw your largest vertex buffer, and reuse it for every rendering. +// (Note that if you use 32-bit indices, you'll use 24 bytes of bandwidth +// per quad, more than the 20 bytes for the vertex/face mesh data.) + +STBVXDEC void stbvox_set_mesh_coordinates(stbvox_mesh_maker *mm, int x, int y, int z); +// Sets the global coordinates for this chunk, such that (0,0,0) relative +// coordinates will be at (x,y,z) in global coordinates. + +STBVXDEC void stbvox_get_bounds(stbvox_mesh_maker *mm, float bounds[2][3]); +// Returns the bounds for the mesh in global coordinates. Use this +// for e.g. frustum culling the mesh. @BUG: this just uses the +// values from stbvox_set_input_range(), so if you build by +// appending multiple values, this will be wrong, and you need to +// set stbvox_set_input_range() to the full size. Someday this +// will switch to tracking the actual bounds of the *mesh*, though. + +STBVXDEC void stbvox_get_transform(stbvox_mesh_maker *mm, float transform[3][3]); +// Returns the 'transform' data for the shader uniforms. It is your +// job to set this to the shader before drawing the mesh. It is the +// only uniform that needs to change per-mesh. Note that it is not +// a 3x3 matrix, but rather a scale to decode fixed point numbers as +// floats, a translate from relative to global space, and a special +// translation for texture coordinate generation that avoids +// floating-point precision issues. @TODO: currently we add the +// global translation to the vertex, than multiply by modelview, +// but this means if camera location and vertex are far from the +// origin, we lose precision. Need to make a special modelview with +// the translation (or some of it) factored out to avoid this. + +STBVXDEC void stbvox_reset_buffers(stbvox_mesh_maker *mm); +// Call this function if you're done with the current output buffer +// but want to reuse it (e.g. you're done appending with +// stbvox_make_mesh and you've copied the data out to your graphics API +// so can reuse the buffer). + +////////////////////////////////////////////////////////////////////////////// +// +// RENDERING +// + +STBVXDEC char *stbvox_get_vertex_shader(void); +// Returns the (currently GLSL-only) vertex shader. + +STBVXDEC char *stbvox_get_fragment_shader(void); +// Returns the (currently GLSL-only) fragment shader. +// You can override the lighting and fogging calculations +// by appending data to the end of these; see the #define +// documentation for more information. + +STBVXDEC char *stbvox_get_fragment_shader_alpha_only(void); +// Returns a slightly cheaper fragment shader that computes +// alpha but not color. This is useful for e.g. a depth-only +// pass when using alpha test. + +typedef struct stbvox_uniform_info stbvox_uniform_info; + +STBVXDEC int stbvox_get_uniform_info(stbvox_uniform_info *info, int uniform); +// Gets the information about a uniform necessary for you to +// set up each uniform with a minimal amount of explicit code. +// See the sample code after the structure definition for stbvox_uniform_info, +// further down in this header section. +// +// "uniform" is from the list immediately following. For many +// of these, default values are provided which you can set. +// Most values are shared for most draw calls; e.g. for stateful +// APIs you can set most of the state only once. Only +// STBVOX_UNIFORM_transform needs to change per draw call. +// +// STBVOX_UNIFORM_texscale +// 64- or 128-long vec4 array. (128 only if STBVOX_CONFIG_PREFER_TEXBUFFER) +// x: scale factor to apply to texture #1. must be a power of two. 1.0 means 'face-sized' +// y: scale factor to apply to texture #2. must be a power of two. 1.0 means 'face-sized' +// z: blend mode indexed by texture #2. 0.0 is alpha compositing; 1.0 is multiplication. +// w: unused currently. @TODO use to support texture animation? +// +// Texscale is indexed by the bottom 6 or 7 bits of the texture id; thus for +// example the texture at index 0 in the array and the texture in index 128 of +// the array must be scaled the same. This means that if you only have 64 or 128 +// unique textures, they all get distinct values anyway; otherwise you have +// to group them in pairs or sets of four. +// +// STBVOX_UNIFORM_ambient +// 4-long vec4 array: +// ambient[0].xyz - negative of direction of a directional light for half-lambert +// ambient[1].rgb - color of light scaled by NdotL (can be negative) +// ambient[2].rgb - constant light added to above calculation; +// effectively light ranges from ambient[2]-ambient[1] to ambient[2]+ambient[1] +// ambient[3].rgb - fog color for STBVOX_CONFIG_FOG_SMOOTHSTEP +// ambient[3].a - reciprocal of squared distance of farthest fog point (viewing distance) + + + // +----- has a default value + // | +-- you should always use the default value +enum // V V +{ // ------------------------------------------------ + STBVOX_UNIFORM_face_data, // n the sampler with the face texture buffer + STBVOX_UNIFORM_transform, // n the transform data from stbvox_get_transform + STBVOX_UNIFORM_tex_array, // n an array of two texture samplers containing the two texture arrays + STBVOX_UNIFORM_texscale, // Y a table of texture properties, see above + STBVOX_UNIFORM_color_table, // Y 64 vec4 RGBA values; a default palette is provided; if A > 1.0, fullbright + STBVOX_UNIFORM_normals, // Y Y table of normals, internal-only + STBVOX_UNIFORM_texgen, // Y Y table of texgen vectors, internal-only + STBVOX_UNIFORM_ambient, // n lighting & fog info, see above + STBVOX_UNIFORM_camera_pos, // Y camera position in global voxel space (for lighting & fog) + + STBVOX_UNIFORM_count, +}; + +enum +{ + STBVOX_UNIFORM_TYPE_none, + STBVOX_UNIFORM_TYPE_sampler, + STBVOX_UNIFORM_TYPE_vec2, + STBVOX_UNIFORM_TYPE_vec3, + STBVOX_UNIFORM_TYPE_vec4, +}; + +struct stbvox_uniform_info +{ + int type; // which type of uniform + int bytes_per_element; // the size of each uniform array element (e.g. vec3 = 12 bytes) + int array_length; // length of the uniform array + char *name; // name in the shader @TODO use numeric binding + float *default_value; // if not NULL, you can use this as the uniform pointer + int use_tex_buffer; // if true, then the uniform is a sampler but the data can come from default_value +}; + +////////////////////////////////////////////////////////////////////////////// +// +// Uniform sample code +// + +#if 0 +// Run this once per frame before drawing all the meshes. +// You still need to separately set the 'transform' uniform for every mesh. +void setup_uniforms(GLuint shader, float camera_pos[4], GLuint tex1, GLuint tex2) +{ + int i; + glUseProgram(shader); // so uniform binding works + for (i=0; i < STBVOX_UNIFORM_count; ++i) { + stbvox_uniform_info sui; + if (stbvox_get_uniform_info(&sui, i)) { + GLint loc = glGetUniformLocation(shader, sui.name); + if (loc != -1) { + switch (i) { + case STBVOX_UNIFORM_camera_pos: // only needed for fog + glUniform4fv(loc, sui.array_length, camera_pos); + break; + + case STBVOX_UNIFORM_tex_array: { + GLuint tex_unit[2] = { 0, 1 }; // your choice of samplers + glUniform1iv(loc, 2, tex_unit); + + glActiveTexture(GL_TEXTURE0 + tex_unit[0]); glBindTexture(GL_TEXTURE_2D_ARRAY, tex1); + glActiveTexture(GL_TEXTURE0 + tex_unit[1]); glBindTexture(GL_TEXTURE_2D_ARRAY, tex2); + glActiveTexture(GL_TEXTURE0); // reset to default + break; + } + + case STBVOX_UNIFORM_face_data: + glUniform1i(loc, SAMPLER_YOU_WILL_BIND_PER_MESH_FACE_DATA_TO); + break; + + case STBVOX_UNIFORM_ambient: // you definitely want to override this + case STBVOX_UNIFORM_color_table: // you might want to override this + case STBVOX_UNIFORM_texscale: // you may want to override this + glUniform4fv(loc, sui.array_length, sui.default_value); + break; + + case STBVOX_UNIFORM_normals: // you never want to override this + case STBVOX_UNIFORM_texgen: // you never want to override this + glUniform3fv(loc, sui.array_length, sui.default_value); + break; + } + } + } + } +} +#endif + +#ifdef __cplusplus +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// INPUT TO MESHING +// + +// Shapes of blocks that aren't always cubes +enum +{ + STBVOX_GEOM_empty, + STBVOX_GEOM_knockout, // creates a hole in the mesh + STBVOX_GEOM_solid, + STBVOX_GEOM_transp, // solid geometry, but transparent contents so neighbors generate normally, unless same blocktype + + // following 4 can be represented by vheight as well + STBVOX_GEOM_slab_upper, + STBVOX_GEOM_slab_lower, + STBVOX_GEOM_floor_slope_north_is_top, + STBVOX_GEOM_ceil_slope_north_is_bottom, + + STBVOX_GEOM_floor_slope_north_is_top_as_wall_UNIMPLEMENTED, // same as floor_slope above, but uses wall's texture & texture projection + STBVOX_GEOM_ceil_slope_north_is_bottom_as_wall_UNIMPLEMENTED, + STBVOX_GEOM_crossed_pair, // corner-to-corner pairs, with normal vector bumped upwards + STBVOX_GEOM_force, // like GEOM_transp, but faces visible even if neighbor is same type, e.g. minecraft fancy leaves + + // these access vheight input + STBVOX_GEOM_floor_vheight_03 = 12, // diagonal is SW-NE + STBVOX_GEOM_floor_vheight_12, // diagonal is SE-NW + STBVOX_GEOM_ceil_vheight_03, + STBVOX_GEOM_ceil_vheight_12, + + STBVOX_GEOM_count, // number of geom cases +}; + +enum +{ + STBVOX_FACE_east, + STBVOX_FACE_north, + STBVOX_FACE_west, + STBVOX_FACE_south, + STBVOX_FACE_up, + STBVOX_FACE_down, + + STBVOX_FACE_count, +}; + +#ifdef STBVOX_CONFIG_BLOCKTYPE_SHORT +typedef unsigned short stbvox_block_type; +#else +typedef unsigned char stbvox_block_type; +#endif + +// 24-bit color +typedef struct +{ + unsigned char r,g,b; +} stbvox_rgb; + +#define STBVOX_COLOR_TEX1_ENABLE 64 +#define STBVOX_COLOR_TEX2_ENABLE 128 + +// This is the data structure you fill out. Most of the arrays can be +// NULL, except when one is required to get the value to index another. +// +// The compass system used in the following descriptions is: +// east means increasing x +// north means increasing y +// up means increasing z +struct stbvox_input_description +{ + unsigned char lighting_at_vertices; + // The default is lighting values (i.e. ambient occlusion) are at block + // center, and the vertex light is gathered from those adjacent block + // centers that the vertex is facing. This makes smooth lighting + // consistent across adjacent faces with the same orientation. + // + // Setting this flag to non-zero gives you explicit control + // of light at each vertex, but now the lighting/ao will be + // shared by all vertices at the same point, even if they + // have different normals. + + // these are mostly 3D maps you use to define your voxel world, using x_stride and y_stride + // note that for cache efficiency, you want to use the block_foo palettes as much as possible instead + + stbvox_rgb *rgb; + // Indexed by 3D coordinate. + // 24-bit voxel color for STBVOX_CONFIG_MODE = 20 or 21 only + + unsigned char *lighting; + // Indexed by 3D coordinate. The lighting value / ambient occlusion + // value that is used to define the vertex lighting values. + // The raw lighting values are defined at the center of blocks + // (or at vertex if 'lighting_at_vertices' is true). + // + // If the macro STBVOX_CONFIG_ROTATION_IN_LIGHTING is defined, + // then an additional 2-bit block rotation value is stored + // in this field as well. + // + // Encode with STBVOX_MAKE_LIGHTING_EXT(lighting,rot)--here + // 'lighting' should still be 8 bits, as the macro will + // discard the bottom bits automatically. Similarly, if + // using STBVOX_CONFIG_VHEIGHT_IN_LIGHTING, encode with + // STBVOX_MAKE_LIGHTING_EXT(lighting,vheight). + // + // (Rationale: rotation needs to be independent of blocktype, + // but is only 2 bits so doesn't want to be its own array. + // Lighting is the one thing that was likely to already be + // in use and that I could easily steal 2 bits from.) + + stbvox_block_type *blocktype; + // Indexed by 3D coordinate. This is a core "block type" value, which is used + // to index into other arrays; essentially a "palette". This is much more + // memory-efficient and performance-friendly than storing the values explicitly, + // but only makes sense if the values are always synchronized. + // + // If a voxel's blocktype is 0, it is assumed to be empty (STBVOX_GEOM_empty), + // and no other blocktypes should be STBVOX_GEOM_empty. (Only if you do not + // have blocktypes should STBVOX_GEOM_empty ever used.) + // + // Normally it is an unsigned byte, but you can override it to be + // a short if you have too many blocktypes. + + unsigned char *geometry; + // Indexed by 3D coordinate. Contains the geometry type for the block. + // Also contains a 2-bit rotation for how the whole block is rotated. + // Also includes a 2-bit vheight value when using shared vheight values. + // See the separate vheight documentation. + // Encode with STBVOX_MAKE_GEOMETRY(geom, rot, vheight) + + unsigned char *block_geometry; + // Array indexed by blocktype containing the geometry for this block, plus + // a 2-bit "simple rotation". Note rotation has limited use since it's not + // independent of blocktype. + // + // Encode with STBVOX_MAKE_GEOMETRY(geom,simple_rot,0) + + unsigned char *block_tex1; + // Array indexed by blocktype containing the texture id for texture #1. + + unsigned char (*block_tex1_face)[6]; + // Array indexed by blocktype and face containing the texture id for texture #1. + // The N/E/S/W face choices can be rotated by one of the rotation selectors; + // The top & bottom face textures will rotate to match. + // Note that it only makes sense to use one of block_tex1 or block_tex1_face; + // this pattern repeats throughout and this notice is not repeated. + + unsigned char *tex2; + // Indexed by 3D coordinate. Contains the texture id for texture #2 + // to use on all faces of the block. + + unsigned char *block_tex2; + // Array indexed by blocktype containing the texture id for texture #2. + + unsigned char (*block_tex2_face)[6]; + // Array indexed by blocktype and face containing the texture id for texture #2. + // The N/E/S/W face choices can be rotated by one of the rotation selectors; + // The top & bottom face textures will rotate to match. + + unsigned char *color; + // Indexed by 3D coordinate. Contains the color for all faces of the block. + // The core color value is 0..63. + // Encode with STBVOX_MAKE_COLOR(color_number, tex1_enable, tex2_enable) + + unsigned char *block_color; + // Array indexed by blocktype containing the color value to apply to the faces. + // The core color value is 0..63. + // Encode with STBVOX_MAKE_COLOR(color_number, tex1_enable, tex2_enable) + + unsigned char (*block_color_face)[6]; + // Array indexed by blocktype and face containing the color value to apply to that face. + // The core color value is 0..63. + // Encode with STBVOX_MAKE_COLOR(color_number, tex1_enable, tex2_enable) + + unsigned char *block_texlerp; + // Array indexed by blocktype containing 3-bit scalar for texture #2 alpha + // (known throughout as 'texlerp'). This is constant over every face even + // though the property is potentially per-vertex. + + unsigned char (*block_texlerp_face)[6]; + // Array indexed by blocktype and face containing 3-bit scalar for texture #2 alpha. + // This is constant over the face even though the property is potentially per-vertex. + + unsigned char *block_vheight; + // Array indexed by blocktype containing the vheight values for the + // top or bottom face of this block. These will rotate properly if the + // block is rotated. See discussion of vheight. + // Encode with STBVOX_MAKE_VHEIGHT(sw_height, se_height, nw_height, ne_height) + + unsigned char *selector; + // Array indexed by 3D coordinates indicating which output mesh to select. + + unsigned char *block_selector; + // Array indexed by blocktype indicating which output mesh to select. + + unsigned char *side_texrot; + // Array indexed by 3D coordinates encoding 2-bit texture rotations for the + // faces on the E/N/W/S sides of the block. + // Encode with STBVOX_MAKE_SIDE_TEXROT(rot_e, rot_n, rot_w, rot_s) + + unsigned char *block_side_texrot; + // Array indexed by blocktype encoding 2-bit texture rotations for the faces + // on the E/N/W/S sides of the block. + // Encode with STBVOX_MAKE_SIDE_TEXROT(rot_e, rot_n, rot_w, rot_s) + + unsigned char *overlay; // index into palettes listed below + // Indexed by 3D coordinate. If 0, there is no overlay. If non-zero, + // it indexes into to the below arrays and overrides the values + // defined by the blocktype. + + unsigned char (*overlay_tex1)[6]; + // Array indexed by overlay value and face, containing an override value + // for the texture id for texture #1. If 0, the value defined by blocktype + // is used. + + unsigned char (*overlay_tex2)[6]; + // Array indexed by overlay value and face, containing an override value + // for the texture id for texture #2. If 0, the value defined by blocktype + // is used. + + unsigned char (*overlay_color)[6]; + // Array indexed by overlay value and face, containing an override value + // for the face color. If 0, the value defined by blocktype is used. + + unsigned char *overlay_side_texrot; + // Array indexed by overlay value, encoding 2-bit texture rotations for the faces + // on the E/N/W/S sides of the block. + // Encode with STBVOX_MAKE_SIDE_TEXROT(rot_e, rot_n, rot_w, rot_s) + + unsigned char *rotate; + // Indexed by 3D coordinate. Allows independent rotation of several + // parts of the voxel, where by rotation I mean swapping textures + // and colors between E/N/S/W faces. + // Block: rotates anything indexed by blocktype + // Overlay: rotates anything indexed by overlay + // EColor: rotates faces defined in ecolor_facemask + // Encode with STBVOX_MAKE_MATROT(block,overlay,ecolor) + + unsigned char *tex2_for_tex1; + // Array indexed by tex1 containing the texture id for texture #2. + // You can use this if the two are always/almost-always strictly + // correlated (e.g. if tex2 is a detail texture for tex1), as it + // will be more efficient (touching fewer cache lines) than using + // e.g. block_tex2_face. + + unsigned char *tex2_replace; + // Indexed by 3D coordinate. Specifies the texture id for texture #2 + // to use on a single face of the voxel, which must be E/N/W/S (not U/D). + // The texture id is limited to 6 bits unless tex2_facemask is also + // defined (see below). + // Encode with STBVOX_MAKE_TEX2_REPLACE(tex2, face) + + unsigned char *tex2_facemask; + // Indexed by 3D coordinate. Specifies which of the six faces should + // have their tex2 replaced by the value of tex2_replace. In this + // case, all 8 bits of tex2_replace are used as the texture id. + // Encode with STBVOX_MAKE_FACE_MASK(east,north,west,south,up,down) + + unsigned char *extended_color; + // Indexed by 3D coordinate. Specifies a value that indexes into + // the ecolor arrays below (both of which must be defined). + + unsigned char *ecolor_color; + // Indexed by extended_color value, specifies an optional override + // for the color value on some faces. + // Encode with STBVOX_MAKE_COLOR(color_number, tex1_enable, tex2_enable) + + unsigned char *ecolor_facemask; + // Indexed by extended_color value, this specifies which faces the + // color in ecolor_color should be applied to. The faces can be + // independently rotated by the ecolor value of 'rotate', if it exists. + // Encode with STBVOX_MAKE_FACE_MASK(e,n,w,s,u,d) + + unsigned char *color2; + // Indexed by 3D coordinates, specifies an alternative color to apply + // to some of the faces of the block. + // Encode with STBVOX_MAKE_COLOR(color_number, tex1_enable, tex2_enable) + + unsigned char *color2_facemask; + // Indexed by 3D coordinates, specifies which faces should use the + // color defined in color2. No rotation value is applied. + // Encode with STBVOX_MAKE_FACE_MASK(e,n,w,s,u,d) + + unsigned char *color3; + // Indexed by 3D coordinates, specifies an alternative color to apply + // to some of the faces of the block. + // Encode with STBVOX_MAKE_COLOR(color_number, tex1_enable, tex2_enable) + + unsigned char *color3_facemask; + // Indexed by 3D coordinates, specifies which faces should use the + // color defined in color3. No rotation value is applied. + // Encode with STBVOX_MAKE_FACE_MASK(e,n,w,s,u,d) + + unsigned char *texlerp_simple; + // Indexed by 3D coordinates, this is the smallest texlerp encoding + // that can do useful work. It consits of three values: baselerp, + // vertlerp, and face_vertlerp. Baselerp defines the value + // to use on all of the faces but one, from the STBVOX_TEXLERP_BASE + // values. face_vertlerp is one of the 6 face values (or STBVOX_FACE_NONE) + // which specifies the face should use the vertlerp values. + // Vertlerp defines a lerp value at every vertex of the mesh. + // Thus, one face can have per-vertex texlerp values, and those + // values are encoded in the space so that they will be shared + // by adjacent faces that also use vertlerp, allowing continuity + // (this is used for the "texture crossfade" bit of the release video). + // Encode with STBVOX_MAKE_TEXLERP_SIMPLE(baselerp, vertlerp, face_vertlerp) + + // The following texlerp encodings are experimental and maybe not + // that useful. + + unsigned char *texlerp; + // Indexed by 3D coordinates, this defines four values: + // vertlerp is a lerp value at every vertex of the mesh (using STBVOX_TEXLERP_BASE values). + // ud is the value to use on up and down faces, from STBVOX_TEXLERP_FACE values + // ew is the value to use on east and west faces, from STBVOX_TEXLERP_FACE values + // ns is the value to use on north and south faces, from STBVOX_TEXLERP_FACE values + // If any of ud, ew, or ns is STBVOX_TEXLERP_FACE_use_vert, then the + // vertlerp values for the vertices are gathered and used for those faces. + // Encode with STBVOX_MAKE_TEXLERP(vertlerp,ud,ew,sw) + + unsigned short *texlerp_vert3; + // Indexed by 3D coordinates, this works with texlerp and + // provides a unique texlerp value for every direction at + // every vertex. The same rules of whether faces share values + // applies. The STBVOX_TEXLERP_FACE vertlerp value defined in + // texlerp is only used for the down direction. The values at + // each vertex in other directions are defined in this array, + // and each uses the STBVOX_TEXLERP3 values (i.e. full precision + // 3-bit texlerp values). + // Encode with STBVOX_MAKE_VERT3(vertlerp_e,vertlerp_n,vertlerp_w,vertlerp_s,vertlerp_u) + + unsigned short *texlerp_face3; // e:3,n:3,w:3,s:3,u:2,d:2 + // Indexed by 3D coordinates, this provides a compact way to + // fully specify the texlerp value indepenendly for every face, + // but doesn't allow per-vertex variation. E/N/W/S values are + // encoded using STBVOX_TEXLERP3 values, whereas up and down + // use STBVOX_TEXLERP_SIMPLE values. + // Encode with STBVOX_MAKE_FACE3(face_e,face_n,face_w,face_s,face_u,face_d) + + unsigned char *vheight; // STBVOX_MAKE_VHEIGHT -- sw:2, se:2, nw:2, ne:2, doesn't rotate + // Indexed by 3D coordinates, this defines the four + // vheight values to use if the geometry is STBVOX_GEOM_vheight*. + // See the vheight discussion. + + unsigned char *packed_compact; + // Stores block rotation, vheight, and texlerp values: + // block rotation: 2 bits + // vertex vheight: 2 bits + // use_texlerp : 1 bit + // vertex texlerp: 3 bits + // If STBVOX_CONFIG_UP_TEXLERP_PACKED is defined, then 'vertex texlerp' is + // used for up faces if use_texlerp is 1. If STBVOX_CONFIG_DOWN_TEXLERP_PACKED + // is defined, then 'vertex texlerp' is used for down faces if use_texlerp is 1. + // Note if those symbols are defined but packed_compact is NULL, the normal + // texlerp default will be used. + // Encode with STBVOX_MAKE_PACKED_COMPACT(rot, vheight, texlerp, use_texlerp) +}; +// @OPTIMIZE allow specializing; build a single struct with all of the +// 3D-indexed arrays combined so it's AoS instead of SoA for better +// cache efficiency + + +////////////////////////////////////////////////////////////////////////////// +// +// VHEIGHT DOCUMENTATION +// +// "vheight" is the internal name for the special block types +// with sloped tops or bottoms. "vheight" stands for "vertex height". +// +// Note that these blocks are very flexible (there are 256 of them, +// although at least 17 of them should never be used), but they +// also have a disadvantage that they generate extra invisible +// faces; the generator does not currently detect whether adjacent +// vheight blocks hide each others sides, so those side faces are +// always generated. For a continuous ground terrain, this means +// that you may generate 5x as many quads as needed. See notes +// on "improvements for shipping products" in the introduction. + +enum +{ + STBVOX_VERTEX_HEIGHT_0, + STBVOX_VERTEX_HEIGHT_half, + STBVOX_VERTEX_HEIGHT_1, + STBVOX_VERTEX_HEIGHT_one_and_a_half, +}; +// These are the "vheight" values. Vheight stands for "vertex height". +// The idea is that for a "floor vheight" block, you take a cube and +// reposition the top-most vertices at various heights as specified by +// the vheight values. Similarly, a "ceiling vheight" block takes a +// cube and repositions the bottom-most vertices. +// +// A floor block only adjusts the top four vertices; the bottom four vertices +// remain at the bottom of the block. The height values are 2 bits, +// measured in halves of a block; so you can specify heights of 0/2, +// 1/2, 2/2, or 3/2. 0 is the bottom of the block, 1 is halfway +// up the block, 2 is the top of the block, and 3 is halfway up the +// next block (and actually outside of the block). The value 3 is +// actually legal for floor vheight (but not ceiling), and allows you to: +// +// (A) have smoother terrain by having slopes that cross blocks, +// e.g. (1,1,3,3) is a regular-seeming slope halfway between blocks +// (B) make slopes steeper than 45-degrees, e.g. (0,0,3,3) +// +// (Because only z coordinates have half-block precision, and x&y are +// limited to block corner precision, it's not possible to make these +// things "properly" out of blocks, e.g. a half-slope block on its side +// or a sloped block halfway between blocks that's made out of two blocks.) +// +// If you define STBVOX_CONFIG_OPTIMIZED_VHEIGHT, then the top face +// (or bottom face for a ceiling vheight block) will be drawn as a +// single quad even if the four vertex heights aren't planar, and a +// single normal will be used over the entire quad. If you +// don't define it, then if the top face is non-planar, it will be +// split into two triangles, each with their own normal/lighting. +// (Note that since all output from stb_voxel_render is quad meshes, +// triangles are actually rendered as degenerate quads.) In this case, +// the distinction between STBVOX_GEOM_floor_vheight_03 and +// STBVOX_GEOM_floor_vheight_12 comes into play; the former introduces +// an edge from the SW to NE corner (i.e. from <0,0,?> to <1,1,?>), +// while the latter introduces an edge from the NW to SE corner +// (i.e. from <0,1,?> to <1,0,?>.) For a "lazy mesh" look, use +// exclusively _03 or _12. For a "classic mesh" look, alternate +// _03 and _12 in a checkerboard pattern. For a "smoothest surface" +// look, choose the edge based on actual vertex heights. +// +// The four vertex heights can come from several places. The simplest +// encoding is to just use the 'vheight' parameter which stores four +// explicit vertex heights for every block. This allows total independence, +// but at the cost of the largest memory usage, 1 byte per 3D block. +// Encode this with STBVOX_MAKE_VHEIGHT(vh_sw, vh_se, vh_nw, vh_ne). +// These coordinates are absolute, not affected by block rotations. +// +// An alternative if you just want to encode some very specific block +// types, not all the possibilities--say you just want half-height slopes, +// so you want (0,0,1,1) and (1,1,2,2)--then you can use block_vheight +// to specify them. The geometry rotation will cause block_vheight values +// to be rotated (because it's as if you're just defining a type of +// block). This value is also encoded with STBVOX_MAKE_VHEIGHT. +// +// If you want to save memory and you're creating a "continuous ground" +// sort of effect, you can make each vertex of the lattice share the +// vheight value; that is, two adjacent blocks that share a vertex will +// always get the same vheight value for that vertex. Then you need to +// store two bits of vheight for every block, which you do by storing it +// as part another data structure. Store the south-west vertex's vheight +// with the block. You can either use the "geometry" mesh variable (it's +// a parameter to STBVOX_MAKE_GEOMETRY) or you can store it in the +// "lighting" mesh variable if you defined STBVOX_CONFIG_VHEIGHT_IN_LIGHTING, +// using STBVOX_MAKE_LIGHTING_EXT(lighting,vheight). +// +// Note that if you start with a 2D height map and generate vheight data from +// it, you don't necessarily store only one value per (x,y) coordinate, +// as the same value may need to be set up at multiple z heights. For +// example, if height(8,8) = 13.5, then you want the block at (8,8,13) +// to store STBVOX_VERTEX_HEIGHT_half, and this will be used by blocks +// at (7,7,13), (8,7,13), (7,8,13), and (8,8,13). However, if you're +// allowing steep slopes, it might be the case that you have a block +// at (7,7,12) which is supposed to stick up to 13.5; that means +// you also need to store STBVOX_VERTEX_HEIGHT_one_and_a_half at (8,8,12). + +enum +{ + STBVOX_TEXLERP_FACE_0, + STBVOX_TEXLERP_FACE_half, + STBVOX_TEXLERP_FACE_1, + STBVOX_TEXLERP_FACE_use_vert, +}; + +enum +{ + STBVOX_TEXLERP_BASE_0, // 0.0 + STBVOX_TEXLERP_BASE_2_7, // 2/7 + STBVOX_TEXLERP_BASE_5_7, // 4/7 + STBVOX_TEXLERP_BASE_1 // 1.0 +}; + +enum +{ + STBVOX_TEXLERP3_0_8, + STBVOX_TEXLERP3_1_8, + STBVOX_TEXLERP3_2_8, + STBVOX_TEXLERP3_3_8, + STBVOX_TEXLERP3_4_8, + STBVOX_TEXLERP3_5_8, + STBVOX_TEXLERP3_6_8, + STBVOX_TEXLERP3_7_8, +}; + +#define STBVOX_FACE_NONE 7 + +#define STBVOX_BLOCKTYPE_EMPTY 0 + +#ifdef STBVOX_BLOCKTYPE_SHORT +#define STBVOX_BLOCKTYPE_HOLE 65535 +#else +#define STBVOX_BLOCKTYPE_HOLE 255 +#endif + +#define STBVOX_MAKE_GEOMETRY(geom, rotate, vheight) ((geom) + (rotate)*16 + (vheight)*64) +#define STBVOX_MAKE_VHEIGHT(v_sw, v_se, v_nw, v_ne) ((v_sw) + (v_se)*4 + (v_nw)*16 + (v_ne)*64) +#define STBVOX_MAKE_MATROT(block, overlay, color) ((block) + (overlay)*4 + (color)*64) +#define STBVOX_MAKE_TEX2_REPLACE(tex2, tex2_replace_face) ((tex2) + ((tex2_replace_face) & 3)*64) +#define STBVOX_MAKE_TEXLERP(ns2, ew2, ud2, vert) ((ew2) + (ns2)*4 + (ud2)*16 + (vert)*64) +#define STBVOX_MAKE_TEXLERP_SIMPLE(baselerp,vert,face) ((vert)*32 + (face)*4 + (baselerp)) +#define STBVOX_MAKE_TEXLERP1(vert,e2,n2,w2,s2,u4,d2) STBVOX_MAKE_TEXLERP(s2, w2, d2, vert) +#define STBVOX_MAKE_TEXLERP2(vert,e2,n2,w2,s2,u4,d2) ((u2)*16 + (n2)*4 + (s2)) +#define STBVOX_MAKE_FACE_MASK(e,n,w,s,u,d) ((e)+(n)*2+(w)*4+(s)*8+(u)*16+(d)*32) +#define STBVOX_MAKE_SIDE_TEXROT(e,n,w,s) ((e)+(n)*4+(w)*16+(s)*64) +#define STBVOX_MAKE_COLOR(color,t1,t2) ((color)+(t1)*64+(t2)*128) +#define STBVOX_MAKE_TEXLERP_VERT3(e,n,w,s,u) ((e)+(n)*8+(w)*64+(s)*512+(u)*4096) +#define STBVOX_MAKE_TEXLERP_FACE3(e,n,w,s,u,d) ((e)+(n)*8+(w)*64+(s)*512+(u)*4096+(d)*16384) +#define STBVOX_MAKE_PACKED_COMPACT(rot, vheight, texlerp, def) ((rot)+4*(vheight)+16*(use)+32*(texlerp)) + +#define STBVOX_MAKE_LIGHTING_EXT(lighting, rot) (((lighting)&~3)+(rot)) +#define STBVOX_MAKE_LIGHTING(lighting) (lighting) + +#ifndef STBVOX_MAX_MESHES +#define STBVOX_MAX_MESHES 2 // opaque & transparent +#endif + +#define STBVOX_MAX_MESH_SLOTS 3 // one vertex & two faces, or two vertex and one face + + +// don't mess with this directly, it's just here so you can +// declare stbvox_mesh_maker on the stack or as a global +struct stbvox_mesh_maker +{ + stbvox_input_description input; + int cur_x, cur_y, cur_z; // last unprocessed voxel if it splits into multiple buffers + int x0,y0,z0,x1,y1,z1; + int x_stride_in_bytes; + int y_stride_in_bytes; + int config_dirty; + int default_mesh; + unsigned int tags; + + int cube_vertex_offset[6][4]; // this allows access per-vertex data stored block-centered (like texlerp, ambient) + int vertex_gather_offset[6][4]; + + int pos_x,pos_y,pos_z; + int full; + + // computed from user input + char *output_cur [STBVOX_MAX_MESHES][STBVOX_MAX_MESH_SLOTS]; + char *output_end [STBVOX_MAX_MESHES][STBVOX_MAX_MESH_SLOTS]; + char *output_buffer[STBVOX_MAX_MESHES][STBVOX_MAX_MESH_SLOTS]; + int output_len [STBVOX_MAX_MESHES][STBVOX_MAX_MESH_SLOTS]; + + // computed from config + int output_size [STBVOX_MAX_MESHES][STBVOX_MAX_MESH_SLOTS]; // per quad + int output_step [STBVOX_MAX_MESHES][STBVOX_MAX_MESH_SLOTS]; // per vertex or per face, depending + int num_mesh_slots; + + float default_tex_scale[128][2]; +}; + +#endif // INCLUDE_STB_VOXEL_RENDER_H + + +#ifdef STB_VOXEL_RENDER_IMPLEMENTATION + +#include +#include +#include // memset + +// have to use our own names to avoid the _MSC_VER path having conflicting type names +#ifndef _MSC_VER + #include + typedef uint16_t stbvox_uint16; + typedef uint32_t stbvox_uint32; +#else + typedef unsigned short stbvox_uint16; + typedef unsigned int stbvox_uint32; +#endif + +#ifdef _MSC_VER + #define STBVOX_NOTUSED(v) (void)(v) +#else + #define STBVOX_NOTUSED(v) (void)sizeof(v) +#endif + + + +#ifndef STBVOX_CONFIG_MODE +#error "Must defined STBVOX_CONFIG_MODE to select the mode" +#endif + +#if defined(STBVOX_CONFIG_ROTATION_IN_LIGHTING) && defined(STBVOX_CONFIG_VHEIGHT_IN_LIGHTING) +#error "Can't store both rotation and vheight in lighting" +#endif + + +// The following are candidate voxel modes. Only modes 0, 1, and 20, and 21 are +// currently implemented. Reducing the storage-per-quad further +// shouldn't improve performance, although obviously it allow you +// to create larger worlds without streaming. +// +// +// ----------- Two textures ----------- -- One texture -- ---- Color only ---- +// Mode: 0 1 2 3 4 5 6 10 11 12 20 21 22 23 24 +// ============================================================================================================ +// uses Tex Buffer n Y Y Y Y Y Y Y Y Y n Y Y Y Y +// bytes per quad 32 20 14 12 10 6 6 8 8 4 32 20 10 6 4 +// non-blocks all all some some some slabs stairs some some none all all slabs slabs none +// tex1 256 256 256 256 256 256 256 256 256 256 n n n n n +// tex2 256 256 256 256 256 256 128 n n n n n n n n +// colors 64 64 64 64 64 64 64 8 n n 2^24 2^24 2^24 2^24 256 +// vertex ao Y Y Y Y Y n n Y Y n Y Y Y n n +// vertex texlerp Y Y Y n n n n - - - - - - - - +// x&y extents 127 127 128 64 64 128 64 64 128 128 127 127 128 128 128 +// z extents 255 255 128 64? 64? 64 64 32 64 128 255 255 128 64 128 + +// not sure why I only wrote down the above "result data" and didn't preserve +// the vertex formats, but here I've tried to reconstruct the designs... +// mode # 3 is wrong, one byte too large, but they may have been an error originally + +// Mode: 0 1 2 3 4 5 6 10 11 12 20 21 22 23 24 +// ============================================================================================================= +// bytes per quad 32 20 14 12 10 6 6 8 8 4 20 10 6 4 +// +// vertex x bits 7 7 0 6 0 0 0 0 0 0 7 0 0 0 +// vertex y bits 7 7 0 0 0 0 0 0 0 0 7 0 0 0 +// vertex z bits 9 9 7 4 2 0 0 2 2 0 9 2 0 0 +// vertex ao bits 6 6 6 6 6 0 0 6 6 0 6 6 0 0 +// vertex txl bits 3 3 3 0 0 0 0 0 0 0 (3) 0 0 0 +// +// face tex1 bits (8) 8 8 8 8 8 8 8 8 8 +// face tex2 bits (8) 8 8 8 8 8 7 - - - +// face color bits (8) 8 8 8 8 8 8 3 0 0 24 24 24 8 +// face normal bits (8) 8 8 8 6 4 7 4 4 3 8 3 4 3 +// face x bits 7 0 6 7 6 6 7 7 0 7 7 7 +// face y bits 7 6 6 7 6 6 7 7 0 7 7 7 +// face z bits 2 2 6 6 6 5 6 7 0 7 6 7 + + +#if STBVOX_CONFIG_MODE==0 || STBVOX_CONFIG_MODE==1 + + #define STBVOX_ICONFIG_VERTEX_32 + #define STBVOX_ICONFIG_FACE1_1 + +#elif STBVOX_CONFIG_MODE==20 || STBVOX_CONFIG_MODE==21 + + #define STBVOX_ICONFIG_VERTEX_32 + #define STBVOX_ICONFIG_FACE1_1 + #define STBVOX_ICONFIG_UNTEXTURED + +#else +#error "Selected value of STBVOX_CONFIG_MODE is not supported" +#endif + +#if STBVOX_CONFIG_MODE==0 || STBVOX_CONFIG_MODE==20 +#define STBVOX_ICONFIG_FACE_ATTRIBUTE +#endif + +#ifndef STBVOX_CONFIG_HLSL +// the fallback if all others are exhausted is GLSL +#define STBVOX_ICONFIG_GLSL +#endif + +#ifdef STBVOX_CONFIG_OPENGL_MODELVIEW +#define STBVOX_ICONFIG_OPENGL_3_1_COMPATIBILITY +#endif + +#if defined(STBVOX_ICONFIG_VERTEX_32) + typedef stbvox_uint32 stbvox_mesh_vertex; + #define stbvox_vertex_encode(x,y,z,ao,texlerp) \ + ((stbvox_uint32) ((x)+((y)<<7)+((z)<<14)+((ao)<<23)+((texlerp)<<29))) +#elif defined(STBVOX_ICONFIG_VERTEX_16_1) // mode=2 + typedef stbvox_uint16 stbvox_mesh_vertex; + #define stbvox_vertex_encode(x,y,z,ao,texlerp) \ + ((stbvox_uint16) ((z)+((ao)<<7)+((texlerp)<<13) +#elif defined(STBVOX_ICONFIG_VERTEX_16_2) // mode=3 + typedef stbvox_uint16 stbvox_mesh_vertex; + #define stbvox_vertex_encode(x,y,z,ao,texlerp) \ + ((stbvox_uint16) ((x)+((z)<<6))+((ao)<<10)) +#elif defined(STBVOX_ICONFIG_VERTEX_8) + typedef stbvox_uint8 stbvox_mesh_vertex; + #define stbvox_vertex_encode(x,y,z,ao,texlerp) \ + ((stbvox_uint8) ((z)+((ao)<<6)) +#else + #error "internal error, no vertex type" +#endif + +#ifdef STBVOX_ICONFIG_FACE1_1 + typedef struct + { + unsigned char tex1,tex2,color,face_info; + } stbvox_mesh_face; +#else + #error "internal error, no face type" +#endif + + +// 20-byte quad format: +// +// per vertex: +// +// x:7 +// y:7 +// z:9 +// ao:6 +// tex_lerp:3 +// +// per face: +// +// tex1:8 +// tex2:8 +// face:8 +// color:8 + + +// Faces: +// +// Faces use the bottom 3 bits to choose the texgen +// mode, and all the bits to choose the normal. +// Thus the bottom 3 bits have to be: +// e, n, w, s, u, d, u, d +// +// These use compact names so tables are readable + +enum +{ + STBVF_e, + STBVF_n, + STBVF_w, + STBVF_s, + STBVF_u, + STBVF_d, + STBVF_eu, + STBVF_ed, + + STBVF_eu_wall, + STBVF_nu_wall, + STBVF_wu_wall, + STBVF_su_wall, + STBVF_ne_u, + STBVF_ne_d, + STBVF_nu, + STBVF_nd, + + STBVF_ed_wall, + STBVF_nd_wall, + STBVF_wd_wall, + STBVF_sd_wall, + STBVF_nw_u, + STBVF_nw_d, + STBVF_wu, + STBVF_wd, + + STBVF_ne_u_cross, + STBVF_nw_u_cross, + STBVF_sw_u_cross, + STBVF_se_u_cross, + STBVF_sw_u, + STBVF_sw_d, + STBVF_su, + STBVF_sd, + + // @TODO we need more than 5 bits to encode the normal to fit the following + // so for now we use the right projection but the wrong normal + STBVF_se_u = STBVF_su, + STBVF_se_d = STBVF_sd, + + STBVF_count, +}; + +///////////////////////////////////////////////////////////////////////////// +// +// tables -- i'd prefer if these were at the end of the file, but: C++ +// + +static float stbvox_default_texgen[2][32][3] = +{ + { { 0, 1,0 }, { 0, 0, 1 }, { 0,-1,0 }, { 0, 0,-1 }, + { -1, 0,0 }, { 0, 0, 1 }, { 1, 0,0 }, { 0, 0,-1 }, + { 0,-1,0 }, { 0, 0, 1 }, { 0, 1,0 }, { 0, 0,-1 }, + { 1, 0,0 }, { 0, 0, 1 }, { -1, 0,0 }, { 0, 0,-1 }, + + { 1, 0,0 }, { 0, 1, 0 }, { -1, 0,0 }, { 0,-1, 0 }, + { -1, 0,0 }, { 0,-1, 0 }, { 1, 0,0 }, { 0, 1, 0 }, + { 1, 0,0 }, { 0, 1, 0 }, { -1, 0,0 }, { 0,-1, 0 }, + { -1, 0,0 }, { 0,-1, 0 }, { 1, 0,0 }, { 0, 1, 0 }, + }, + { { 0, 0,-1 }, { 0, 1,0 }, { 0, 0, 1 }, { 0,-1,0 }, + { 0, 0,-1 }, { -1, 0,0 }, { 0, 0, 1 }, { 1, 0,0 }, + { 0, 0,-1 }, { 0,-1,0 }, { 0, 0, 1 }, { 0, 1,0 }, + { 0, 0,-1 }, { 1, 0,0 }, { 0, 0, 1 }, { -1, 0,0 }, + + { 0,-1, 0 }, { 1, 0,0 }, { 0, 1, 0 }, { -1, 0,0 }, + { 0, 1, 0 }, { -1, 0,0 }, { 0,-1, 0 }, { 1, 0,0 }, + { 0,-1, 0 }, { 1, 0,0 }, { 0, 1, 0 }, { -1, 0,0 }, + { 0, 1, 0 }, { -1, 0,0 }, { 0,-1, 0 }, { 1, 0,0 }, + }, +}; + +#define STBVOX_RSQRT2 0.7071067811865f +#define STBVOX_RSQRT3 0.5773502691896f + +static float stbvox_default_normals[32][3] = +{ + { 1,0,0 }, // east + { 0,1,0 }, // north + { -1,0,0 }, // west + { 0,-1,0 }, // south + { 0,0,1 }, // up + { 0,0,-1 }, // down + { STBVOX_RSQRT2,0, STBVOX_RSQRT2 }, // east & up + { STBVOX_RSQRT2,0, -STBVOX_RSQRT2 }, // east & down + + { STBVOX_RSQRT2,0, STBVOX_RSQRT2 }, // east & up + { 0, STBVOX_RSQRT2, STBVOX_RSQRT2 }, // north & up + { -STBVOX_RSQRT2,0, STBVOX_RSQRT2 }, // west & up + { 0,-STBVOX_RSQRT2, STBVOX_RSQRT2 }, // south & up + { STBVOX_RSQRT3, STBVOX_RSQRT3, STBVOX_RSQRT3 }, // ne & up + { STBVOX_RSQRT3, STBVOX_RSQRT3,-STBVOX_RSQRT3 }, // ne & down + { 0, STBVOX_RSQRT2, STBVOX_RSQRT2 }, // north & up + { 0, STBVOX_RSQRT2, -STBVOX_RSQRT2 }, // north & down + + { STBVOX_RSQRT2,0, -STBVOX_RSQRT2 }, // east & down + { 0, STBVOX_RSQRT2, -STBVOX_RSQRT2 }, // north & down + { -STBVOX_RSQRT2,0, -STBVOX_RSQRT2 }, // west & down + { 0,-STBVOX_RSQRT2, -STBVOX_RSQRT2 }, // south & down + { -STBVOX_RSQRT3, STBVOX_RSQRT3, STBVOX_RSQRT3 }, // NW & up + { -STBVOX_RSQRT3, STBVOX_RSQRT3,-STBVOX_RSQRT3 }, // NW & down + { -STBVOX_RSQRT2,0, STBVOX_RSQRT2 }, // west & up + { -STBVOX_RSQRT2,0, -STBVOX_RSQRT2 }, // west & down + + { STBVOX_RSQRT3, STBVOX_RSQRT3,STBVOX_RSQRT3 }, // NE & up crossed + { -STBVOX_RSQRT3, STBVOX_RSQRT3,STBVOX_RSQRT3 }, // NW & up crossed + { -STBVOX_RSQRT3,-STBVOX_RSQRT3,STBVOX_RSQRT3 }, // SW & up crossed + { STBVOX_RSQRT3,-STBVOX_RSQRT3,STBVOX_RSQRT3 }, // SE & up crossed + { -STBVOX_RSQRT3,-STBVOX_RSQRT3, STBVOX_RSQRT3 }, // SW & up + { -STBVOX_RSQRT3,-STBVOX_RSQRT3,-STBVOX_RSQRT3 }, // SW & up + { 0,-STBVOX_RSQRT2, STBVOX_RSQRT2 }, // south & up + { 0,-STBVOX_RSQRT2, -STBVOX_RSQRT2 }, // south & down +}; + +static float stbvox_default_texscale[128][4] = +{ + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, + {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}, +}; + +static unsigned char stbvox_default_palette_compact[64][3] = +{ + { 255,255,255 }, { 238,238,238 }, { 221,221,221 }, { 204,204,204 }, + { 187,187,187 }, { 170,170,170 }, { 153,153,153 }, { 136,136,136 }, + { 119,119,119 }, { 102,102,102 }, { 85, 85, 85 }, { 68, 68, 68 }, + { 51, 51, 51 }, { 34, 34, 34 }, { 17, 17, 17 }, { 0, 0, 0 }, + { 255,240,240 }, { 255,220,220 }, { 255,160,160 }, { 255, 32, 32 }, + { 200,120,160 }, { 200, 60,150 }, { 220,100,130 }, { 255, 0,128 }, + { 240,240,255 }, { 220,220,255 }, { 160,160,255 }, { 32, 32,255 }, + { 120,160,200 }, { 60,150,200 }, { 100,130,220 }, { 0,128,255 }, + { 240,255,240 }, { 220,255,220 }, { 160,255,160 }, { 32,255, 32 }, + { 160,200,120 }, { 150,200, 60 }, { 130,220,100 }, { 128,255, 0 }, + { 255,255,240 }, { 255,255,220 }, { 220,220,180 }, { 255,255, 32 }, + { 200,160,120 }, { 200,150, 60 }, { 220,130,100 }, { 255,128, 0 }, + { 255,240,255 }, { 255,220,255 }, { 220,180,220 }, { 255, 32,255 }, + { 160,120,200 }, { 150, 60,200 }, { 130,100,220 }, { 128, 0,255 }, + { 240,255,255 }, { 220,255,255 }, { 180,220,220 }, { 32,255,255 }, + { 120,200,160 }, { 60,200,150 }, { 100,220,130 }, { 0,255,128 }, +}; + +static float stbvox_default_ambient[4][4] = +{ + { 0,0,1 ,0 }, // reversed lighting direction + { 0.5,0.5,0.5,0 }, // directional color + { 0.5,0.5,0.5,0 }, // constant color + { 0.5,0.5,0.5,1.0f/1000.0f/1000.0f }, // fog data for simple_fog +}; + +static float stbvox_default_palette[64][4]; + +static void stbvox_build_default_palette(void) +{ + int i; + for (i=0; i < 64; ++i) { + stbvox_default_palette[i][0] = stbvox_default_palette_compact[i][0] / 255.0f; + stbvox_default_palette[i][1] = stbvox_default_palette_compact[i][1] / 255.0f; + stbvox_default_palette[i][2] = stbvox_default_palette_compact[i][2] / 255.0f; + stbvox_default_palette[i][3] = 1.0f; + } +} + +////////////////////////////////////////////////////////////////////////////// +// +// Shaders +// + +#if defined(STBVOX_ICONFIG_OPENGL_3_1_COMPATIBILITY) + #define STBVOX_SHADER_VERSION "#version 150 compatibility\n" +#elif defined(STBVOX_ICONFIG_OPENGL_3_0) + #define STBVOX_SHADER_VERSION "#version 130\n" +#elif defined(STBVOX_ICONFIG_GLSL) + #define STBVOX_SHADER_VERSION "#version 150\n" +#else + #define STBVOX_SHADER_VERSION "" +#endif + +static const char *stbvox_vertex_program = +{ + STBVOX_SHADER_VERSION + + #ifdef STBVOX_ICONFIG_FACE_ATTRIBUTE // NOT TAG_face_sampled + "in uvec4 attr_face;\n" + #else + "uniform usamplerBuffer facearray;\n" + #endif + + #ifdef STBVOX_ICONFIG_FACE_ARRAY_2 + "uniform usamplerBuffer facearray2;\n" + #endif + + // vertex input data + "in uint attr_vertex;\n" + + // per-buffer data + "uniform vec3 transform[3];\n" + + // per-frame data + "uniform vec4 camera_pos;\n" // 4th value is used for arbitrary hacking + + // to simplify things, we avoid using more than 256 uniform vectors + // in fragment shader to avoid possible 1024 component limit, so + // we access this table in the fragment shader. + "uniform vec3 normal_table[32];\n" + + #ifndef STBVOX_CONFIG_OPENGL_MODELVIEW + "uniform mat4x4 model_view;\n" + #endif + + // fragment output data + "flat out uvec4 facedata;\n" + " out vec3 voxelspace_pos;\n" + " out vec3 vnormal;\n" + " out float texlerp;\n" + " out float amb_occ;\n" + + // @TODO handle the HLSL way to do this + "void main()\n" + "{\n" + #ifdef STBVOX_ICONFIG_FACE_ATTRIBUTE + " facedata = attr_face;\n" + #else + " int faceID = gl_VertexID >> 2;\n" + " facedata = texelFetch(facearray, faceID);\n" + #endif + + // extract data for vertex + " vec3 offset;\n" + " offset.x = float( (attr_vertex ) & 127u );\n" // a[0..6] + " offset.y = float( (attr_vertex >> 7u) & 127u );\n" // a[7..13] + " offset.z = float( (attr_vertex >> 14u) & 511u );\n" // a[14..22] + " amb_occ = float( (attr_vertex >> 23u) & 63u ) / 63.0;\n" // a[23..28] + " texlerp = float( (attr_vertex >> 29u) ) / 7.0;\n" // a[29..31] + + " vnormal = normal_table[(facedata.w>>2u) & 31u];\n" + " voxelspace_pos = offset * transform[0];\n" // mesh-to-object scale + " vec3 position = voxelspace_pos + transform[1];\n" // mesh-to-object translate + + #ifdef STBVOX_DEBUG_TEST_NORMALS + " if ((facedata.w & 28u) == 16u || (facedata.w & 28u) == 24u)\n" + " position += vnormal.xyz * camera_pos.w;\n" + #endif + + #ifndef STBVOX_CONFIG_OPENGL_MODELVIEW + " gl_Position = model_view * vec4(position,1.0);\n" + #else + " gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);\n" + #endif + + "}\n" +}; + + +static const char *stbvox_fragment_program = +{ + STBVOX_SHADER_VERSION + + // rlerp is lerp but with t on the left, like god intended + #if defined(STBVOX_ICONFIG_GLSL) + "#define rlerp(t,x,y) mix(x,y,t)\n" + #elif defined(STBVOX_CONFIG_HLSL) + "#define rlerp(t,x,y) lerp(x,y,t)\n" + #else + #error "need definition of rlerp()" + #endif + + + // vertex-shader output data + "flat in uvec4 facedata;\n" + " in vec3 voxelspace_pos;\n" + " in vec3 vnormal;\n" + " in float texlerp;\n" + " in float amb_occ;\n" + + // per-buffer data + "uniform vec3 transform[3];\n" + + // per-frame data + "uniform vec4 camera_pos;\n" // 4th value is used for arbitrary hacking + + // probably constant data + "uniform vec4 ambient[4];\n" + + #ifndef STBVOX_ICONFIG_UNTEXTURED + // generally constant data + "uniform sampler2DArray tex_array[2];\n" + + #ifdef STBVOX_CONFIG_PREFER_TEXBUFFER + "uniform samplerBuffer color_table;\n" + "uniform samplerBuffer texscale;\n" + "uniform samplerBuffer texgen;\n" + #else + "uniform vec4 color_table[64];\n" + "uniform vec4 texscale[64];\n" // instead of 128, to avoid running out of uniforms + "uniform vec3 texgen[64];\n" + #endif + #endif + + "out vec4 outcolor;\n" + + #if defined(STBVOX_CONFIG_LIGHTING) || defined(STBVOX_CONFIG_LIGHTING_SIMPLE) + "vec3 compute_lighting(vec3 pos, vec3 norm, vec3 albedo, vec3 ambient);\n" + #endif + #if defined(STBVOX_CONFIG_FOG) || defined(STBVOX_CONFIG_FOG_SMOOTHSTEP) + "vec3 compute_fog(vec3 color, vec3 relative_pos, float fragment_alpha);\n" + #endif + + "void main()\n" + "{\n" + " vec3 albedo;\n" + " float fragment_alpha;\n" + + #ifndef STBVOX_ICONFIG_UNTEXTURED + // unpack the values + " uint tex1_id = facedata.x;\n" + " uint tex2_id = facedata.y;\n" + " uint texprojid = facedata.w & 31u;\n" + " uint color_id = facedata.z;\n" + + #ifndef STBVOX_CONFIG_PREFER_TEXBUFFER + // load from uniforms / texture buffers + " vec3 texgen_s = texgen[texprojid];\n" + " vec3 texgen_t = texgen[texprojid+32u];\n" + " float tex1_scale = texscale[tex1_id & 63u].x;\n" + " vec4 color = color_table[color_id & 63u];\n" + #ifndef STBVOX_CONFIG_DISABLE_TEX2 + " vec4 tex2_props = texscale[tex2_id & 63u];\n" + #endif + #else + " vec3 texgen_s = texelFetch(texgen, int(texprojid)).xyz;\n" + " vec3 texgen_t = texelFetch(texgen, int(texprojid+32u)).xyz;\n" + " float tex1_scale = texelFetch(texscale, int(tex1_id & 127u)).x;\n" + " vec4 color = texelFetch(color_table, int(color_id & 63u));\n" + #ifndef STBVOX_CONFIG_DISABLE_TEX2 + " vec4 tex2_props = texelFetch(texscale, int(tex1_id & 127u));\n" + #endif + #endif + + #ifndef STBVOX_CONFIG_DISABLE_TEX2 + " float tex2_scale = tex2_props.y;\n" + " bool texblend_mode = tex2_props.z != 0.0;\n" + #endif + " vec2 texcoord;\n" + " vec3 texturespace_pos = voxelspace_pos + transform[2].xyz;\n" + " texcoord.s = dot(texturespace_pos, texgen_s);\n" + " texcoord.t = dot(texturespace_pos, texgen_t);\n" + + " vec2 texcoord_1 = tex1_scale * texcoord;\n" + #ifndef STBVOX_CONFIG_DISABLE_TEX2 + " vec2 texcoord_2 = tex2_scale * texcoord;\n" + #endif + + #ifdef STBVOX_CONFIG_TEX1_EDGE_CLAMP + " texcoord_1 = texcoord_1 - floor(texcoord_1);\n" + " vec4 tex1 = textureGrad(tex_array[0], vec3(texcoord_1, float(tex1_id)), dFdx(tex1_scale*texcoord), dFdy(tex1_scale*texcoord));\n" + #else + " vec4 tex1 = texture(tex_array[0], vec3(texcoord_1, float(tex1_id)));\n" + #endif + + #ifndef STBVOX_CONFIG_DISABLE_TEX2 + #ifdef STBVOX_CONFIG_TEX2_EDGE_CLAMP + " texcoord_2 = texcoord_2 - floor(texcoord_2);\n" + " vec4 tex2 = textureGrad(tex_array[0], vec3(texcoord_2, float(tex2_id)), dFdx(tex2_scale*texcoord), dFdy(tex2_scale*texcoord));\n" + #else + " vec4 tex2 = texture(tex_array[1], vec3(texcoord_2, float(tex2_id)));\n" + #endif + #endif + + " bool emissive = (color.a > 1.0);\n" + " color.a = min(color.a, 1.0);\n" + + // recolor textures + " if ((color_id & 64u) != 0u) tex1.rgba *= color.rgba;\n" + " fragment_alpha = tex1.a;\n" + #ifndef STBVOX_CONFIG_DISABLE_TEX2 + " if ((color_id & 128u) != 0u) tex2.rgba *= color.rgba;\n" + + #ifdef STBVOX_CONFIG_PREMULTIPLIED_ALPHA + " tex2.rgba *= texlerp;\n" + #else + " tex2.a *= texlerp;\n" + #endif + + " if (texblend_mode)\n" + " albedo = tex1.xyz * rlerp(tex2.a, vec3(1.0,1.0,1.0), 2.0*tex2.xyz);\n" + " else {\n" + #ifdef STBVOX_CONFIG_PREMULTIPLIED_ALPHA + " albedo = (1.0-tex2.a)*tex1.xyz + tex2.xyz;\n" + #else + " albedo = rlerp(tex2.a, tex1.xyz, tex2.xyz);\n" + #endif + " fragment_alpha = tex1.a*(1-tex2.a)+tex2.a;\n" + " }\n" + #else + " albedo = tex1.xyz;\n" + #endif + + #else // UNTEXTURED + " vec4 color;" + " color.xyz = vec3(facedata.xyz) / 255.0;\n" + " bool emissive = false;\n" + " albedo = color.xyz;\n" + " fragment_alpha = 1.0;\n" + #endif + + #ifdef STBVOX_ICONFIG_VARYING_VERTEX_NORMALS + // currently, there are no modes that trigger this path; idea is that there + // could be a couple of bits per vertex to perturb the normal to e.g. get curved look + " vec3 normal = normalize(vnormal);\n" + #else + " vec3 normal = vnormal;\n" + #endif + + " vec3 ambient_color = dot(normal, ambient[0].xyz) * ambient[1].xyz + ambient[2].xyz;\n" + + " ambient_color = clamp(ambient_color, 0.0, 1.0);" + " ambient_color *= amb_occ;\n" + + " vec3 lit_color;\n" + " if (!emissive)\n" + #if defined(STBVOX_ICONFIG_LIGHTING) || defined(STBVOX_CONFIG_LIGHTING_SIMPLE) + " lit_color = compute_lighting(voxelspace_pos + transform[1], normal, albedo, ambient_color);\n" + #else + " lit_color = albedo * ambient_color ;\n" + #endif + " else\n" + " lit_color = albedo;\n" + + #if defined(STBVOX_ICONFIG_FOG) || defined(STBVOX_CONFIG_FOG_SMOOTHSTEP) + " vec3 dist = voxelspace_pos + (transform[1] - camera_pos.xyz);\n" + " lit_color = compute_fog(lit_color, dist, fragment_alpha);\n" + #endif + + #ifdef STBVOX_CONFIG_UNPREMULTIPLY + " vec4 final_color = vec4(lit_color/fragment_alpha, fragment_alpha);\n" + #else + " vec4 final_color = vec4(lit_color, fragment_alpha);\n" + #endif + " outcolor = final_color;\n" + "}\n" + + #ifdef STBVOX_CONFIG_LIGHTING_SIMPLE + "\n" + "uniform vec3 light_source[2];\n" + "vec3 compute_lighting(vec3 pos, vec3 norm, vec3 albedo, vec3 ambient)\n" + "{\n" + " vec3 light_dir = light_source[0] - pos;\n" + " float lambert = dot(light_dir, norm) / dot(light_dir, light_dir);\n" + " vec3 diffuse = clamp(light_source[1] * clamp(lambert, 0.0, 1.0), 0.0, 1.0);\n" + " return (diffuse + ambient) * albedo;\n" + "}\n" + #endif + + #ifdef STBVOX_CONFIG_FOG_SMOOTHSTEP + "\n" + "vec3 compute_fog(vec3 color, vec3 relative_pos, float fragment_alpha)\n" + "{\n" + " float f = dot(relative_pos,relative_pos)*ambient[3].w;\n" + //" f = rlerp(f, -2,1);\n" + " f = clamp(f, 0.0, 1.0);\n" + " f = 3.0*f*f - 2.0*f*f*f;\n" // smoothstep + //" f = f*f;\n" // fade in more smoothly + #ifdef STBVOX_CONFIG_PREMULTIPLIED_ALPHA + " return rlerp(f, color.xyz, ambient[3].xyz*fragment_alpha);\n" + #else + " return rlerp(f, color.xyz, ambient[3].xyz);\n" + #endif + "}\n" + #endif +}; + + +// still requires full alpha lookups, including tex2 if texblend is enabled +static const char *stbvox_fragment_program_alpha_only = +{ + STBVOX_SHADER_VERSION + + // vertex-shader output data + "flat in uvec4 facedata;\n" + " in vec3 voxelspace_pos;\n" + " in float texlerp;\n" + + // per-buffer data + "uniform vec3 transform[3];\n" + + #ifndef STBVOX_ICONFIG_UNTEXTURED + // generally constant data + "uniform sampler2DArray tex_array[2];\n" + + #ifdef STBVOX_CONFIG_PREFER_TEXBUFFER + "uniform samplerBuffer texscale;\n" + "uniform samplerBuffer texgen;\n" + #else + "uniform vec4 texscale[64];\n" // instead of 128, to avoid running out of uniforms + "uniform vec3 texgen[64];\n" + #endif + #endif + + "out vec4 outcolor;\n" + + "void main()\n" + "{\n" + " vec3 albedo;\n" + " float fragment_alpha;\n" + + #ifndef STBVOX_ICONFIG_UNTEXTURED + // unpack the values + " uint tex1_id = facedata.x;\n" + " uint tex2_id = facedata.y;\n" + " uint texprojid = facedata.w & 31u;\n" + " uint color_id = facedata.z;\n" + + #ifndef STBVOX_CONFIG_PREFER_TEXBUFFER + // load from uniforms / texture buffers + " vec3 texgen_s = texgen[texprojid];\n" + " vec3 texgen_t = texgen[texprojid+32u];\n" + " float tex1_scale = texscale[tex1_id & 63u].x;\n" + " vec4 color = color_table[color_id & 63u];\n" + " vec4 tex2_props = texscale[tex2_id & 63u];\n" + #else + " vec3 texgen_s = texelFetch(texgen, int(texprojid)).xyz;\n" + " vec3 texgen_t = texelFetch(texgen, int(texprojid+32u)).xyz;\n" + " float tex1_scale = texelFetch(texscale, int(tex1_id & 127u)).x;\n" + " vec4 color = texelFetch(color_table, int(color_id & 63u));\n" + " vec4 tex2_props = texelFetch(texscale, int(tex2_id & 127u));\n" + #endif + + #ifndef STBVOX_CONFIG_DISABLE_TEX2 + " float tex2_scale = tex2_props.y;\n" + " bool texblend_mode = tex2_props.z &((facedata.w & 128u) != 0u);\n" + #endif + + " color.a = min(color.a, 1.0);\n" + + " vec2 texcoord;\n" + " vec3 texturespace_pos = voxelspace_pos + transform[2].xyz;\n" + " texcoord.s = dot(texturespace_pos, texgen_s);\n" + " texcoord.t = dot(texturespace_pos, texgen_t);\n" + + " vec2 texcoord_1 = tex1_scale * texcoord;\n" + " vec2 texcoord_2 = tex2_scale * texcoord;\n" + + #ifdef STBVOX_CONFIG_TEX1_EDGE_CLAMP + " texcoord_1 = texcoord_1 - floor(texcoord_1);\n" + " vec4 tex1 = textureGrad(tex_array[0], vec3(texcoord_1, float(tex1_id)), dFdx(tex1_scale*texcoord), dFdy(tex1_scale*texcoord));\n" + #else + " vec4 tex1 = texture(tex_array[0], vec3(texcoord_1, float(tex1_id)));\n" + #endif + + " if ((color_id & 64u) != 0u) tex1.a *= color.a;\n" + " fragment_alpha = tex1.a;\n" + + #ifndef STBVOX_CONFIG_DISABLE_TEX2 + " if (!texblend_mode) {\n" + #ifdef STBVOX_CONFIG_TEX2_EDGE_CLAMP + " texcoord_2 = texcoord_2 - floor(texcoord_2);\n" + " vec4 tex2 = textureGrad(tex_array[0], vec3(texcoord_2, float(tex2_id)), dFdx(tex2_scale*texcoord), dFdy(tex2_scale*texcoord));\n" + #else + " vec4 tex2 = texture(tex_array[1], vec3(texcoord_2, float(tex2_id)));\n" + #endif + + " tex2.a *= texlerp;\n" + " if ((color_id & 128u) != 0u) tex2.rgba *= color.a;\n" + " fragment_alpha = tex1.a*(1-tex2.a)+tex2.a;\n" + "}\n" + "\n" + #endif + + #else // UNTEXTURED + " fragment_alpha = 1.0;\n" + #endif + + " outcolor = vec4(0.0, 0.0, 0.0, fragment_alpha);\n" + "}\n" +}; + + +STBVXDEC char *stbvox_get_vertex_shader(void) +{ + return (char *) stbvox_vertex_program; +} + +STBVXDEC char *stbvox_get_fragment_shader(void) +{ + return (char *) stbvox_fragment_program; +} + +STBVXDEC char *stbvox_get_fragment_shader_alpha_only(void) +{ + return (char *) stbvox_fragment_program_alpha_only; +} + +static float stbvox_dummy_transform[3][3]; + +#ifdef STBVOX_CONFIG_PREFER_TEXBUFFER +#define STBVOX_TEXBUF 1 +#else +#define STBVOX_TEXBUF 0 +#endif + +static stbvox_uniform_info stbvox_uniforms[] = +{ + { STBVOX_UNIFORM_TYPE_sampler , 4, 1, (char*) "facearray" , 0 }, + { STBVOX_UNIFORM_TYPE_vec3 , 12, 3, (char*) "transform" , stbvox_dummy_transform[0] }, + { STBVOX_UNIFORM_TYPE_sampler , 4, 2, (char*) "tex_array" , 0 }, + { STBVOX_UNIFORM_TYPE_vec4 , 16, 128, (char*) "texscale" , stbvox_default_texscale[0] , STBVOX_TEXBUF }, + { STBVOX_UNIFORM_TYPE_vec4 , 16, 64, (char*) "color_table" , stbvox_default_palette[0] , STBVOX_TEXBUF }, + { STBVOX_UNIFORM_TYPE_vec3 , 12, 32, (char*) "normal_table" , stbvox_default_normals[0] }, + { STBVOX_UNIFORM_TYPE_vec3 , 12, 64, (char*) "texgen" , stbvox_default_texgen[0][0], STBVOX_TEXBUF }, + { STBVOX_UNIFORM_TYPE_vec4 , 16, 4, (char*) "ambient" , stbvox_default_ambient[0] }, + { STBVOX_UNIFORM_TYPE_vec4 , 16, 1, (char*) "camera_pos" , stbvox_dummy_transform[0] }, +}; + +STBVXDEC int stbvox_get_uniform_info(stbvox_uniform_info *info, int uniform) +{ + if (uniform < 0 || uniform >= STBVOX_UNIFORM_count) + return 0; + + *info = stbvox_uniforms[uniform]; + return 1; +} + +#define STBVOX_GET_GEO(geom_data) ((geom_data) & 15) + +typedef struct +{ + unsigned char block:2; + unsigned char overlay:2; + unsigned char facerot:2; + unsigned char ecolor:2; +} stbvox_rotate; + +typedef struct +{ + unsigned char x,y,z; +} stbvox_pos; + +static unsigned char stbvox_rotate_face[6][4] = +{ + { 0,1,2,3 }, + { 1,2,3,0 }, + { 2,3,0,1 }, + { 3,0,1,2 }, + { 4,4,4,4 }, + { 5,5,5,5 }, +}; + +#define STBVOX_ROTATE(x,r) stbvox_rotate_face[x][r] // (((x)+(r))&3) + +stbvox_mesh_face stbvox_compute_mesh_face_value(stbvox_mesh_maker *mm, stbvox_rotate rot, int face, int v_off, int normal) +{ + stbvox_mesh_face face_data = { 0 }; + stbvox_block_type bt = mm->input.blocktype[v_off]; + unsigned char bt_face = STBVOX_ROTATE(face, rot.block); + int facerot = rot.facerot; + + #ifdef STBVOX_ICONFIG_UNTEXTURED + if (mm->input.rgb) { + face_data.tex1 = mm->input.rgb[v_off].r; + face_data.tex2 = mm->input.rgb[v_off].g; + face_data.color = mm->input.rgb[v_off].b; + face_data.face_info = (normal<<2); + return face_data; + } + #else + unsigned char color_face; + + if (mm->input.color) + face_data.color = mm->input.color[v_off]; + + if (mm->input.block_tex1) + face_data.tex1 = mm->input.block_tex1[bt]; + else if (mm->input.block_tex1_face) + face_data.tex1 = mm->input.block_tex1_face[bt][bt_face]; + else + face_data.tex1 = bt; + + if (mm->input.block_tex2) + face_data.tex2 = mm->input.block_tex2[bt]; + else if (mm->input.block_tex2_face) + face_data.tex2 = mm->input.block_tex2_face[bt][bt_face]; + + if (mm->input.block_color) { + unsigned char mcol = mm->input.block_color[bt]; + if (mcol) + face_data.color = mcol; + } else if (mm->input.block_color_face) { + unsigned char mcol = mm->input.block_color_face[bt][bt_face]; + if (mcol) + face_data.color = mcol; + } + + if (face <= STBVOX_FACE_south) { + if (mm->input.side_texrot) + facerot = mm->input.side_texrot[v_off] >> (2 * face); + else if (mm->input.block_side_texrot) + facerot = mm->input.block_side_texrot[v_off] >> (2 * bt_face); + } + + if (mm->input.overlay) { + int over_face = STBVOX_ROTATE(face, rot.overlay); + unsigned char over = mm->input.overlay[v_off]; + if (over) { + if (mm->input.overlay_tex1) { + unsigned char rep1 = mm->input.overlay_tex1[over][over_face]; + if (rep1) + face_data.tex1 = rep1; + } + if (mm->input.overlay_tex2) { + unsigned char rep2 = mm->input.overlay_tex2[over][over_face]; + if (rep2) + face_data.tex2 = rep2; + } + if (mm->input.overlay_color) { + unsigned char rep3 = mm->input.overlay_color[over][over_face]; + if (rep3) + face_data.color = rep3; + } + + if (mm->input.overlay_side_texrot && face <= STBVOX_FACE_south) + facerot = mm->input.overlay_side_texrot[over] >> (2*over_face); + } + } + + if (mm->input.tex2_for_tex1) + face_data.tex2 = mm->input.tex2_for_tex1[face_data.tex1]; + if (mm->input.tex2) + face_data.tex2 = mm->input.tex2[v_off]; + if (mm->input.tex2_replace) { + if (mm->input.tex2_facemask[v_off] & (1 << face)) + face_data.tex2 = mm->input.tex2_replace[v_off]; + } + + color_face = STBVOX_ROTATE(face, rot.ecolor); + if (mm->input.extended_color) { + unsigned char ec = mm->input.extended_color[v_off]; + if (mm->input.ecolor_facemask[ec] & (1 << color_face)) + face_data.color = mm->input.ecolor_color[ec]; + } + + if (mm->input.color2) { + if (mm->input.color2_facemask[v_off] & (1 << color_face)) + face_data.color = mm->input.color2[v_off]; + if (mm->input.color3 && (mm->input.color3_facemask[v_off] & (1 << color_face))) + face_data.color = mm->input.color3[v_off]; + } + #endif + + face_data.face_info = (normal<<2) + facerot; + return face_data; +} + +// these are the types of faces each block can have +enum +{ + STBVOX_FT_none , + STBVOX_FT_upper , + STBVOX_FT_lower , + STBVOX_FT_solid , + STBVOX_FT_diag_012, + STBVOX_FT_diag_023, + STBVOX_FT_diag_013, + STBVOX_FT_diag_123, + STBVOX_FT_force , // can't be covered up, used for internal faces, also hides nothing + STBVOX_FT_partial , // only covered by solid, never covers anything else + + STBVOX_FT_count +}; + +static unsigned char stbvox_face_lerp[6] = { 0,2,0,2,4,4 }; +static unsigned char stbvox_vert3_lerp[5] = { 0,3,6,9,12 }; +static unsigned char stbvox_vert_lerp_for_face_lerp[4] = { 0, 4, 7, 7 }; +static unsigned char stbvox_face3_lerp[6] = { 0,3,6,9,12,14 }; +static unsigned char stbvox_vert_lerp_for_simple[4] = { 0,2,5,7 }; +static unsigned char stbvox_face3_updown[8] = { 0,2,5,7,0,2,5,7 }; // ignore top bit + +// vertex offsets for face vertices +static unsigned char stbvox_vertex_vector[6][4][3] = +{ + { { 1,0,1 }, { 1,1,1 }, { 1,1,0 }, { 1,0,0 } }, // east + { { 1,1,1 }, { 0,1,1 }, { 0,1,0 }, { 1,1,0 } }, // north + { { 0,1,1 }, { 0,0,1 }, { 0,0,0 }, { 0,1,0 } }, // west + { { 0,0,1 }, { 1,0,1 }, { 1,0,0 }, { 0,0,0 } }, // south + { { 0,1,1 }, { 1,1,1 }, { 1,0,1 }, { 0,0,1 } }, // up + { { 0,0,0 }, { 1,0,0 }, { 1,1,0 }, { 0,1,0 } }, // down +}; + +// stbvox_vertex_vector, but read coordinates as binary numbers, zyx +static unsigned char stbvox_vertex_selector[6][4] = +{ + { 5,7,3,1 }, + { 7,6,2,3 }, + { 6,4,0,2 }, + { 4,5,1,0 }, + { 6,7,5,4 }, + { 0,1,3,2 }, +}; + +static stbvox_mesh_vertex stbvox_vmesh_delta_normal[6][4] = +{ + { stbvox_vertex_encode(1,0,1,0,0) , + stbvox_vertex_encode(1,1,1,0,0) , + stbvox_vertex_encode(1,1,0,0,0) , + stbvox_vertex_encode(1,0,0,0,0) }, + { stbvox_vertex_encode(1,1,1,0,0) , + stbvox_vertex_encode(0,1,1,0,0) , + stbvox_vertex_encode(0,1,0,0,0) , + stbvox_vertex_encode(1,1,0,0,0) }, + { stbvox_vertex_encode(0,1,1,0,0) , + stbvox_vertex_encode(0,0,1,0,0) , + stbvox_vertex_encode(0,0,0,0,0) , + stbvox_vertex_encode(0,1,0,0,0) }, + { stbvox_vertex_encode(0,0,1,0,0) , + stbvox_vertex_encode(1,0,1,0,0) , + stbvox_vertex_encode(1,0,0,0,0) , + stbvox_vertex_encode(0,0,0,0,0) }, + { stbvox_vertex_encode(0,1,1,0,0) , + stbvox_vertex_encode(1,1,1,0,0) , + stbvox_vertex_encode(1,0,1,0,0) , + stbvox_vertex_encode(0,0,1,0,0) }, + { stbvox_vertex_encode(0,0,0,0,0) , + stbvox_vertex_encode(1,0,0,0,0) , + stbvox_vertex_encode(1,1,0,0,0) , + stbvox_vertex_encode(0,1,0,0,0) } +}; + +static stbvox_mesh_vertex stbvox_vmesh_pre_vheight[6][4] = +{ + { stbvox_vertex_encode(1,0,0,0,0) , + stbvox_vertex_encode(1,1,0,0,0) , + stbvox_vertex_encode(1,1,0,0,0) , + stbvox_vertex_encode(1,0,0,0,0) }, + { stbvox_vertex_encode(1,1,0,0,0) , + stbvox_vertex_encode(0,1,0,0,0) , + stbvox_vertex_encode(0,1,0,0,0) , + stbvox_vertex_encode(1,1,0,0,0) }, + { stbvox_vertex_encode(0,1,0,0,0) , + stbvox_vertex_encode(0,0,0,0,0) , + stbvox_vertex_encode(0,0,0,0,0) , + stbvox_vertex_encode(0,1,0,0,0) }, + { stbvox_vertex_encode(0,0,0,0,0) , + stbvox_vertex_encode(1,0,0,0,0) , + stbvox_vertex_encode(1,0,0,0,0) , + stbvox_vertex_encode(0,0,0,0,0) }, + { stbvox_vertex_encode(0,1,0,0,0) , + stbvox_vertex_encode(1,1,0,0,0) , + stbvox_vertex_encode(1,0,0,0,0) , + stbvox_vertex_encode(0,0,0,0,0) }, + { stbvox_vertex_encode(0,0,0,0,0) , + stbvox_vertex_encode(1,0,0,0,0) , + stbvox_vertex_encode(1,1,0,0,0) , + stbvox_vertex_encode(0,1,0,0,0) } +}; + +static stbvox_mesh_vertex stbvox_vmesh_delta_half_z[6][4] = +{ + { stbvox_vertex_encode(1,0,2,0,0) , + stbvox_vertex_encode(1,1,2,0,0) , + stbvox_vertex_encode(1,1,0,0,0) , + stbvox_vertex_encode(1,0,0,0,0) }, + { stbvox_vertex_encode(1,1,2,0,0) , + stbvox_vertex_encode(0,1,2,0,0) , + stbvox_vertex_encode(0,1,0,0,0) , + stbvox_vertex_encode(1,1,0,0,0) }, + { stbvox_vertex_encode(0,1,2,0,0) , + stbvox_vertex_encode(0,0,2,0,0) , + stbvox_vertex_encode(0,0,0,0,0) , + stbvox_vertex_encode(0,1,0,0,0) }, + { stbvox_vertex_encode(0,0,2,0,0) , + stbvox_vertex_encode(1,0,2,0,0) , + stbvox_vertex_encode(1,0,0,0,0) , + stbvox_vertex_encode(0,0,0,0,0) }, + { stbvox_vertex_encode(0,1,2,0,0) , + stbvox_vertex_encode(1,1,2,0,0) , + stbvox_vertex_encode(1,0,2,0,0) , + stbvox_vertex_encode(0,0,2,0,0) }, + { stbvox_vertex_encode(0,0,0,0,0) , + stbvox_vertex_encode(1,0,0,0,0) , + stbvox_vertex_encode(1,1,0,0,0) , + stbvox_vertex_encode(0,1,0,0,0) } +}; + +static stbvox_mesh_vertex stbvox_vmesh_crossed_pair[6][4] = +{ + { stbvox_vertex_encode(1,0,2,0,0) , + stbvox_vertex_encode(0,1,2,0,0) , + stbvox_vertex_encode(0,1,0,0,0) , + stbvox_vertex_encode(1,0,0,0,0) }, + { stbvox_vertex_encode(1,1,2,0,0) , + stbvox_vertex_encode(0,0,2,0,0) , + stbvox_vertex_encode(0,0,0,0,0) , + stbvox_vertex_encode(1,1,0,0,0) }, + { stbvox_vertex_encode(0,1,2,0,0) , + stbvox_vertex_encode(1,0,2,0,0) , + stbvox_vertex_encode(1,0,0,0,0) , + stbvox_vertex_encode(0,1,0,0,0) }, + { stbvox_vertex_encode(0,0,2,0,0) , + stbvox_vertex_encode(1,1,2,0,0) , + stbvox_vertex_encode(1,1,0,0,0) , + stbvox_vertex_encode(0,0,0,0,0) }, + // not used, so we leave it non-degenerate to make sure it doesn't get gen'd accidentally + { stbvox_vertex_encode(0,1,2,0,0) , + stbvox_vertex_encode(1,1,2,0,0) , + stbvox_vertex_encode(1,0,2,0,0) , + stbvox_vertex_encode(0,0,2,0,0) }, + { stbvox_vertex_encode(0,0,0,0,0) , + stbvox_vertex_encode(1,0,0,0,0) , + stbvox_vertex_encode(1,1,0,0,0) , + stbvox_vertex_encode(0,1,0,0,0) } +}; + +#define STBVOX_MAX_GEOM 16 +#define STBVOX_NUM_ROTATION 4 + +// this is used to determine if a face is ever generated at all +static unsigned char stbvox_hasface[STBVOX_MAX_GEOM][STBVOX_NUM_ROTATION] = +{ + { 0,0,0,0 }, // empty + { 0,0,0,0 }, // knockout + { 63,63,63,63 }, // solid + { 63,63,63,63 }, // transp + { 63,63,63,63 }, // slab + { 63,63,63,63 }, // slab + { 1|2|4|48, 8|1|2|48, 4|8|1|48, 2|4|8|48, }, // floor slopes + { 1|2|4|48, 8|1|2|48, 4|8|1|48, 2|4|8|48, }, // ceil slopes + { 47,47,47,47 }, // wall-projected diagonal with down face + { 31,31,31,31 }, // wall-projected diagonal with up face + { 63,63,63,63 }, // crossed-pair has special handling, but avoid early-out + { 63,63,63,63 }, // force + { 63,63,63,63 }, // vheight + { 63,63,63,63 }, // vheight + { 63,63,63,63 }, // vheight + { 63,63,63,63 }, // vheight +}; + +// this determines which face type above is visible on each side of the geometry +static unsigned char stbvox_facetype[STBVOX_GEOM_count][6] = +{ + { 0, }, // STBVOX_GEOM_empty + { STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid }, // knockout + { STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid }, // solid + { STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force }, // transp + + { STBVOX_FT_upper, STBVOX_FT_upper, STBVOX_FT_upper, STBVOX_FT_upper, STBVOX_FT_solid, STBVOX_FT_force }, + { STBVOX_FT_lower, STBVOX_FT_lower, STBVOX_FT_lower, STBVOX_FT_lower, STBVOX_FT_force, STBVOX_FT_solid }, + { STBVOX_FT_diag_123, STBVOX_FT_solid, STBVOX_FT_diag_023, STBVOX_FT_none, STBVOX_FT_force, STBVOX_FT_solid }, + { STBVOX_FT_diag_012, STBVOX_FT_solid, STBVOX_FT_diag_013, STBVOX_FT_none, STBVOX_FT_solid, STBVOX_FT_force }, + + { STBVOX_FT_diag_123, STBVOX_FT_solid, STBVOX_FT_diag_023, STBVOX_FT_force, STBVOX_FT_none, STBVOX_FT_solid }, + { STBVOX_FT_diag_012, STBVOX_FT_solid, STBVOX_FT_diag_013, STBVOX_FT_force, STBVOX_FT_solid, STBVOX_FT_none }, + { STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, 0,0 }, // crossed pair + { STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force }, // GEOM_force + + { STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial, STBVOX_FT_force, STBVOX_FT_solid }, // floor vheight, all neighbors forced + { STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial, STBVOX_FT_force, STBVOX_FT_solid }, // floor vheight, all neighbors forced + { STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial, STBVOX_FT_solid, STBVOX_FT_force }, // ceil vheight, all neighbors forced + { STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial, STBVOX_FT_solid, STBVOX_FT_force }, // ceil vheight, all neighbors forced +}; + +// This table indicates what normal to use for the "up" face of a sloped geom +// @TODO this could be done with math given the current arrangement of the enum, but let's not require it +static unsigned char stbvox_floor_slope_for_rot[4] = +{ + STBVF_su, + STBVF_wu, // @TODO: why is this reversed from what it should be? this is a north-is-up face, so slope should be south&up + STBVF_nu, + STBVF_eu, +}; + +static unsigned char stbvox_ceil_slope_for_rot[4] = +{ + STBVF_sd, + STBVF_ed, + STBVF_nd, + STBVF_wd, +}; + +// this table indicates whether, for each pair of types above, a face is visible. +// each value indicates whether a given type is visible for all neighbor types +static unsigned short stbvox_face_visible[STBVOX_FT_count] = +{ + // we encode the table by listing which cases cause *obscuration*, and bitwise inverting that + // table is pre-shifted by 5 to save a shift when it's accessed + (unsigned short) ((~0x07ffu )<<5), // none is completely obscured by everything + (unsigned short) ((~((1u<output_cur[mesh][0]; + int step = mm->output_step[mesh][0]; + + // allocate a new quad from the mesh + vertices[0] = (stbvox_mesh_vertex *) p; p += step; + vertices[1] = (stbvox_mesh_vertex *) p; p += step; + vertices[2] = (stbvox_mesh_vertex *) p; p += step; + vertices[3] = (stbvox_mesh_vertex *) p; p += step; + mm->output_cur[mesh][0] = p; + + // output the face + #ifdef STBVOX_ICONFIG_FACE_ATTRIBUTE + // write face as interleaved vertex data + *(stbvox_mesh_face *) (vertices[0]+1) = face; + *(stbvox_mesh_face *) (vertices[1]+1) = face; + *(stbvox_mesh_face *) (vertices[2]+1) = face; + *(stbvox_mesh_face *) (vertices[3]+1) = face; + #else + *(stbvox_mesh_face *) mm->output_cur[mesh][1] = face; + mm->output_cur[mesh][1] += 4; + #endif +} + +void stbvox_make_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int face, int v_off, stbvox_pos pos, stbvox_mesh_vertex vertbase, stbvox_mesh_vertex *face_coord, unsigned char mesh, int normal) +{ + stbvox_mesh_face face_data = stbvox_compute_mesh_face_value(mm,rot,face,v_off, normal); + + // still need to compute ao & texlerp for each vertex + + // first compute texlerp into p1 + stbvox_mesh_vertex p1[4] = { 0 }; + + #if defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED) && defined(STBVOX_CONFIG_UP_TEXLERP_PACKED) + #define STBVOX_USE_PACKED(f) ((f) == STBVOX_FACE_up || (f) == STBVOX_FACE_down) + #elif defined(STBVOX_CONFIG_UP_TEXLERP_PACKED) + #define STBVOX_USE_PACKED(f) ((f) == STBVOX_FACE_up ) + #elif defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED) + #define STBVOX_USE_PACKED(f) ( (f) == STBVOX_FACE_down) + #endif + + #if defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED) || defined(STBVOX_CONFIG_UP_TEXLERP_PACKED) + if (STBVOX_USE_PACKED(face)) { + if (!mm->input.packed_compact || 0==(mm->input.packed_compact[v_off]&16)) + goto set_default; + p1[0] = (mm->input.packed_compact[v_off + mm->cube_vertex_offset[face][0]] >> 5); + p1[1] = (mm->input.packed_compact[v_off + mm->cube_vertex_offset[face][1]] >> 5); + p1[2] = (mm->input.packed_compact[v_off + mm->cube_vertex_offset[face][2]] >> 5); + p1[3] = (mm->input.packed_compact[v_off + mm->cube_vertex_offset[face][3]] >> 5); + p1[0] = stbvox_vertex_encode(0,0,0,0,p1[0]); + p1[1] = stbvox_vertex_encode(0,0,0,0,p1[1]); + p1[2] = stbvox_vertex_encode(0,0,0,0,p1[2]); + p1[3] = stbvox_vertex_encode(0,0,0,0,p1[3]); + goto skip; + } + #endif + + if (mm->input.block_texlerp) { + stbvox_block_type bt = mm->input.blocktype[v_off]; + unsigned char val = mm->input.block_texlerp[bt]; + p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,val); + } else if (mm->input.block_texlerp_face) { + stbvox_block_type bt = mm->input.blocktype[v_off]; + unsigned char bt_face = STBVOX_ROTATE(face, rot.block); + unsigned char val = mm->input.block_texlerp_face[bt][bt_face]; + p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,val); + } else if (mm->input.texlerp_face3) { + unsigned char val = (mm->input.texlerp_face3[v_off] >> stbvox_face3_lerp[face]) & 7; + if (face >= STBVOX_FACE_up) + val = stbvox_face3_updown[val]; + p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,val); + } else if (mm->input.texlerp_simple) { + unsigned char val = mm->input.texlerp_simple[v_off]; + unsigned char lerp_face = (val >> 2) & 7; + if (lerp_face == face) { + p1[0] = (mm->input.texlerp_simple[v_off + mm->cube_vertex_offset[face][0]] >> 5) & 7; + p1[1] = (mm->input.texlerp_simple[v_off + mm->cube_vertex_offset[face][1]] >> 5) & 7; + p1[2] = (mm->input.texlerp_simple[v_off + mm->cube_vertex_offset[face][2]] >> 5) & 7; + p1[3] = (mm->input.texlerp_simple[v_off + mm->cube_vertex_offset[face][3]] >> 5) & 7; + p1[0] = stbvox_vertex_encode(0,0,0,0,p1[0]); + p1[1] = stbvox_vertex_encode(0,0,0,0,p1[1]); + p1[2] = stbvox_vertex_encode(0,0,0,0,p1[2]); + p1[3] = stbvox_vertex_encode(0,0,0,0,p1[3]); + } else { + unsigned char base = stbvox_vert_lerp_for_simple[val&3]; + p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,base); + } + } else if (mm->input.texlerp) { + unsigned char facelerp = (mm->input.texlerp[v_off] >> stbvox_face_lerp[face]) & 3; + if (facelerp == STBVOX_TEXLERP_FACE_use_vert) { + if (mm->input.texlerp_vert3 && face != STBVOX_FACE_down) { + unsigned char shift = stbvox_vert3_lerp[face]; + p1[0] = (mm->input.texlerp_vert3[mm->cube_vertex_offset[face][0]] >> shift) & 7; + p1[1] = (mm->input.texlerp_vert3[mm->cube_vertex_offset[face][1]] >> shift) & 7; + p1[2] = (mm->input.texlerp_vert3[mm->cube_vertex_offset[face][2]] >> shift) & 7; + p1[3] = (mm->input.texlerp_vert3[mm->cube_vertex_offset[face][3]] >> shift) & 7; + } else { + p1[0] = stbvox_vert_lerp_for_simple[mm->input.texlerp[mm->cube_vertex_offset[face][0]]>>6]; + p1[1] = stbvox_vert_lerp_for_simple[mm->input.texlerp[mm->cube_vertex_offset[face][1]]>>6]; + p1[2] = stbvox_vert_lerp_for_simple[mm->input.texlerp[mm->cube_vertex_offset[face][2]]>>6]; + p1[3] = stbvox_vert_lerp_for_simple[mm->input.texlerp[mm->cube_vertex_offset[face][3]]>>6]; + } + p1[0] = stbvox_vertex_encode(0,0,0,0,p1[0]); + p1[1] = stbvox_vertex_encode(0,0,0,0,p1[1]); + p1[2] = stbvox_vertex_encode(0,0,0,0,p1[2]); + p1[3] = stbvox_vertex_encode(0,0,0,0,p1[3]); + } else { + p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,stbvox_vert_lerp_for_face_lerp[facelerp]); + } + } else { + #if defined(STBVOX_CONFIG_UP_TEXLERP_PACKED) || defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED) + set_default: + #endif + p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,7); // @TODO make this configurable + } + + #if defined(STBVOX_CONFIG_UP_TEXLERP_PACKED) || defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED) + skip: + #endif + + // now compute lighting and store to vertices + { + stbvox_mesh_vertex *mv[4]; + stbvox_get_quad_vertex_pointer(mm, mesh, mv, face_data); + + if (mm->input.lighting) { + // @TODO: lighting at block centers, but not gathered, instead constant-per-face + if (mm->input.lighting_at_vertices) { + int i; + for (i=0; i < 4; ++i) { + *mv[i] = vertbase + face_coord[i] + + stbvox_vertex_encode(0,0,0,mm->input.lighting[v_off + mm->cube_vertex_offset[face][i]] & 63,0) + + p1[i]; + } + } else { + unsigned char *amb = &mm->input.lighting[v_off]; + int i,j; + #if defined(STBVOX_CONFIG_ROTATION_IN_LIGHTING) || defined(STBVOX_CONFIG_VHEIGHT_IN_LIGHTING) + #define STBVOX_GET_LIGHTING(light) ((light) & ~3) + #define STBVOX_LIGHTING_ROUNDOFF 8 + #else + #define STBVOX_GET_LIGHTING(light) (light) + #define STBVOX_LIGHTING_ROUNDOFF 2 + #endif + + for (i=0; i < 4; ++i) { + // for each vertex, gather from the four neighbor blocks it's facing + unsigned char *vamb = &amb[mm->cube_vertex_offset[face][i]]; + int total=0; + for (j=0; j < 4; ++j) + total += STBVOX_GET_LIGHTING(vamb[mm->vertex_gather_offset[face][j]]); + *mv[i] = vertbase + face_coord[i] + + stbvox_vertex_encode(0,0,0,(total+STBVOX_LIGHTING_ROUNDOFF)>>4,0) + + p1[i]; + // >> 4 is because: + // >> 2 to divide by 4 to get average over 4 samples + // >> 2 because input is 8 bits, output is 6 bits + } + + // @TODO: note that gathering baked *lighting* + // is different from gathering baked ao; baked ao can count + // solid blocks as 0 ao, but baked lighting wants average + // of non-blocked--not take average & treat blocked as 0. And + // we can't bake the right value into the solid blocks + // because they can have different lighting values on + // different sides. So we need to actually gather and + // then divide by 0..4 (which we can do with a table-driven + // multiply, or have an 'if' for the 3 case) + + } + } else { + vertbase += stbvox_vertex_encode(0,0,0,63,0); + *mv[0] = vertbase + face_coord[0] + p1[0]; + *mv[1] = vertbase + face_coord[1] + p1[1]; + *mv[2] = vertbase + face_coord[2] + p1[2]; + *mv[3] = vertbase + face_coord[3] + p1[3]; + } + } +} + +// get opposite-facing normal & texgen for opposite face, used to map up-facing vheight data to down-facing data +static unsigned char stbvox_reverse_face[STBVF_count] = +{ + STBVF_w, STBVF_s, STBVF_e, STBVF_n, STBVF_d , STBVF_u , STBVF_wd, STBVF_wu, + 0, 0, 0, 0, STBVF_sw_d, STBVF_sw_u, STBVF_sd, STBVF_su, + 0, 0, 0, 0, STBVF_se_d, STBVF_se_u, STBVF_ed, STBVF_eu, + 0, 0, 0, 0, STBVF_ne_d, STBVF_ne_d, STBVF_nd, STBVF_nu +}; + +#ifndef STBVOX_CONFIG_OPTIMIZED_VHEIGHT +// render non-planar quads by splitting into two triangles, rendering each as a degenerate quad +static void stbvox_make_12_split_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int face, int v_off, stbvox_pos pos, stbvox_mesh_vertex vertbase, stbvox_mesh_vertex *face_coord, unsigned char mesh, unsigned char *ht) +{ + stbvox_mesh_vertex v[4]; + + unsigned char normal1 = stbvox_face_up_normal_012[ht[2]][ht[1]][ht[0]]; + unsigned char normal2 = stbvox_face_up_normal_123[ht[3]][ht[2]][ht[1]]; + + if (face == STBVOX_FACE_down) { + normal1 = stbvox_reverse_face[normal1]; + normal2 = stbvox_reverse_face[normal2]; + } + + // the floor side face_coord is stored in order NW,NE,SE,SW, but ht[] is stored SW,SE,NW,NE + v[0] = face_coord[2]; + v[1] = face_coord[3]; + v[2] = face_coord[0]; + v[3] = face_coord[2]; + stbvox_make_mesh_for_face(mm, rot, face, v_off, pos, vertbase, v, mesh, normal1); + v[1] = face_coord[0]; + v[2] = face_coord[1]; + stbvox_make_mesh_for_face(mm, rot, face, v_off, pos, vertbase, v, mesh, normal2); +} + +static void stbvox_make_03_split_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int face, int v_off, stbvox_pos pos, stbvox_mesh_vertex vertbase, stbvox_mesh_vertex *face_coord, unsigned char mesh, unsigned char *ht) +{ + stbvox_mesh_vertex v[4]; + + unsigned char normal1 = stbvox_face_up_normal_013[ht[3]][ht[1]][ht[0]]; + unsigned char normal2 = stbvox_face_up_normal_023[ht[3]][ht[2]][ht[0]]; + + if (face == STBVOX_FACE_down) { + normal1 = stbvox_reverse_face[normal1]; + normal2 = stbvox_reverse_face[normal2]; + } + + v[0] = face_coord[1]; + v[1] = face_coord[2]; + v[2] = face_coord[3]; + v[3] = face_coord[1]; + stbvox_make_mesh_for_face(mm, rot, face, v_off, pos, vertbase, v, mesh, normal1); + v[1] = face_coord[3]; + v[2] = face_coord[0]; + stbvox_make_mesh_for_face(mm, rot, face, v_off, pos, vertbase, v, mesh, normal2); // this one is correct! +} +#endif + +#ifndef STBVOX_CONFIG_PRECISION_Z +#define STBVOX_CONFIG_PRECISION_Z 1 +#endif + +// simple case for mesh generation: we have only solid and empty blocks +static void stbvox_make_mesh_for_block(stbvox_mesh_maker *mm, stbvox_pos pos, int v_off, stbvox_mesh_vertex *vmesh) +{ + int ns_off = mm->y_stride_in_bytes; + int ew_off = mm->x_stride_in_bytes; + + unsigned char *blockptr = &mm->input.blocktype[v_off]; + stbvox_mesh_vertex basevert = stbvox_vertex_encode(pos.x, pos.y, pos.z << STBVOX_CONFIG_PRECISION_Z , 0,0); + + stbvox_rotate rot = { 0,0,0,0 }; + unsigned char simple_rot = 0; + + unsigned char mesh = mm->default_mesh; + + if (mm->input.selector) + mesh = mm->input.selector[v_off]; + else if (mm->input.block_selector) + mesh = mm->input.block_selector[mm->input.blocktype[v_off]]; + + // check if we're going off the end + if (mm->output_cur[mesh][0] + mm->output_size[mesh][0]*6 > mm->output_end[mesh][0]) { + mm->full = 1; + return; + } + + #ifdef STBVOX_CONFIG_ROTATION_IN_LIGHTING + simple_rot = mm->input.lighting[v_off] & 3; + #endif + + if (mm->input.packed_compact) + simple_rot = mm->input.packed_compact[v_off] & 3; + + if (blockptr[ 1]==0) { + rot.facerot = simple_rot; + stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_up , v_off, pos, basevert, vmesh+4*STBVOX_FACE_up, mesh, STBVOX_FACE_up); + } + if (blockptr[-1]==0) { + rot.facerot = (-simple_rot) & 3; + stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_down, v_off, pos, basevert, vmesh+4*STBVOX_FACE_down, mesh, STBVOX_FACE_down); + } + + if (mm->input.rotate) { + unsigned char val = mm->input.rotate[v_off]; + rot.block = (val >> 0) & 3; + rot.overlay = (val >> 2) & 3; + //rot.tex2 = (val >> 4) & 3; + rot.ecolor = (val >> 6) & 3; + } else { + rot.block = rot.overlay = rot.ecolor = simple_rot; + } + rot.facerot = 0; + + if (blockptr[ ns_off]==0) + stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_north, v_off, pos, basevert, vmesh+4*STBVOX_FACE_north, mesh, STBVOX_FACE_north); + if (blockptr[-ns_off]==0) + stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_south, v_off, pos, basevert, vmesh+4*STBVOX_FACE_south, mesh, STBVOX_FACE_south); + if (blockptr[ ew_off]==0) + stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_east , v_off, pos, basevert, vmesh+4*STBVOX_FACE_east, mesh, STBVOX_FACE_east); + if (blockptr[-ew_off]==0) + stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_west , v_off, pos, basevert, vmesh+4*STBVOX_FACE_west, mesh, STBVOX_FACE_west); +} + +// complex case for mesh generation: we have lots of different +// block types, and we don't want to generate faces of blocks +// if they're hidden by neighbors. +// +// we use lots of tables to determine this: we have a table +// which tells us what face type is generated for each type of +// geometry, and then a table that tells us whether that type +// is hidden by a neighbor. +static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos, int v_off) +{ + int ns_off = mm->y_stride_in_bytes; + int ew_off = mm->x_stride_in_bytes; + int visible_faces, visible_base; + unsigned char mesh; + + // first gather the geometry info for this block and all neighbors + + unsigned char bt, nbt[6]; + unsigned char geo, ngeo[6]; + unsigned char rot, nrot[6]; + + bt = mm->input.blocktype[v_off]; + nbt[0] = mm->input.blocktype[v_off + ew_off]; + nbt[1] = mm->input.blocktype[v_off + ns_off]; + nbt[2] = mm->input.blocktype[v_off - ew_off]; + nbt[3] = mm->input.blocktype[v_off - ns_off]; + nbt[4] = mm->input.blocktype[v_off + 1]; + nbt[5] = mm->input.blocktype[v_off - 1]; + if (mm->input.geometry) { + int i; + geo = mm->input.geometry[v_off]; + ngeo[0] = mm->input.geometry[v_off + ew_off]; + ngeo[1] = mm->input.geometry[v_off + ns_off]; + ngeo[2] = mm->input.geometry[v_off - ew_off]; + ngeo[3] = mm->input.geometry[v_off - ns_off]; + ngeo[4] = mm->input.geometry[v_off + 1]; + ngeo[5] = mm->input.geometry[v_off - 1]; + + rot = (geo >> 4) & 3; + geo &= 15; + for (i=0; i < 6; ++i) { + nrot[i] = (ngeo[i] >> 4) & 3; + ngeo[i] &= 15; + } + } else { + int i; + assert(mm->input.block_geometry); + geo = mm->input.block_geometry[bt]; + for (i=0; i < 6; ++i) + ngeo[i] = mm->input.block_geometry[nbt[i]]; + if (mm->input.selector) { + #ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING + if (mm->input.packed_compact == NULL) { + rot = (mm->input.selector[v_off ] >> 4) & 3; + nrot[0] = (mm->input.selector[v_off + ew_off] >> 4) & 3; + nrot[1] = (mm->input.selector[v_off + ns_off] >> 4) & 3; + nrot[2] = (mm->input.selector[v_off - ew_off] >> 4) & 3; + nrot[3] = (mm->input.selector[v_off - ns_off] >> 4) & 3; + nrot[4] = (mm->input.selector[v_off + 1] >> 4) & 3; + nrot[5] = (mm->input.selector[v_off - 1] >> 4) & 3; + } + #endif + } else { + #ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING + if (mm->input.packed_compact == NULL) { + rot = (geo>>4)&3; + geo &= 15; + for (i=0; i < 6; ++i) { + nrot[i] = (ngeo[i]>>4)&3; + ngeo[i] &= 15; + } + } + #endif + } + } + + #ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING + if (mm->input.packed_compact) { + rot = mm->input.packed_compact[rot] & 3; + nrot[0] = mm->input.packed_compact[v_off + ew_off] & 3; + nrot[1] = mm->input.packed_compact[v_off + ns_off] & 3; + nrot[2] = mm->input.packed_compact[v_off - ew_off] & 3; + nrot[3] = mm->input.packed_compact[v_off - ns_off] & 3; + nrot[4] = mm->input.packed_compact[v_off + 1] & 3; + nrot[5] = mm->input.packed_compact[v_off - 1] & 3; + } + #else + rot = mm->input.lighting[v_off] & 3; + nrot[0] = (mm->input.lighting[v_off + ew_off]) & 3; + nrot[1] = (mm->input.lighting[v_off + ns_off]) & 3; + nrot[2] = (mm->input.lighting[v_off - ew_off]) & 3; + nrot[3] = (mm->input.lighting[v_off - ns_off]) & 3; + nrot[4] = (mm->input.lighting[v_off + 1]) & 3; + nrot[5] = (mm->input.lighting[v_off - 1]) & 3; + #endif + + if (geo == STBVOX_GEOM_transp) { + // transparency has a special rule: if the blocktype is the same, + // and the faces are compatible, then can hide them; otherwise, + // force them on + // Note that this means we don't support any transparentshapes other + // than solid blocks, since detecting them is too complicated. If + // you wanted to do something like minecraft water, you probably + // should just do that with a separate renderer anyway. (We don't + // support transparency sorting so you need to use alpha test + // anyway) + int i; + for (i=0; i < 6; ++i) + if (nbt[i] != bt) { + nbt[i] = 0; + ngeo[i] = STBVOX_GEOM_empty; + } else + ngeo[i] = STBVOX_GEOM_solid; + geo = STBVOX_GEOM_solid; + } + + // now compute the face visibility + visible_base = stbvox_hasface[geo][rot]; + // @TODO: assert(visible_base != 0); // we should have early-outted earlier in this case + visible_faces = 0; + + // now, for every face that might be visible, check if neighbor hides it + if (visible_base & (1 << STBVOX_FACE_east)) { + int type = stbvox_facetype[ geo ][(STBVOX_FACE_east+ rot )&3]; + int ntype = stbvox_facetype[ngeo[0]][(STBVOX_FACE_west+nrot[0])&3]; + visible_faces |= ((stbvox_face_visible[type]) >> (ntype + 5 - STBVOX_FACE_east)) & (1 << STBVOX_FACE_east); + } + if (visible_base & (1 << STBVOX_FACE_north)) { + int type = stbvox_facetype[ geo ][(STBVOX_FACE_north+ rot )&3]; + int ntype = stbvox_facetype[ngeo[1]][(STBVOX_FACE_south+nrot[1])&3]; + visible_faces |= ((stbvox_face_visible[type]) >> (ntype + 5 - STBVOX_FACE_north)) & (1 << STBVOX_FACE_north); + } + if (visible_base & (1 << STBVOX_FACE_west)) { + int type = stbvox_facetype[ geo ][(STBVOX_FACE_west+ rot )&3]; + int ntype = stbvox_facetype[ngeo[2]][(STBVOX_FACE_east+nrot[2])&3]; + visible_faces |= ((stbvox_face_visible[type]) >> (ntype + 5 - STBVOX_FACE_west)) & (1 << STBVOX_FACE_west); + } + if (visible_base & (1 << STBVOX_FACE_south)) { + int type = stbvox_facetype[ geo ][(STBVOX_FACE_south+ rot )&3]; + int ntype = stbvox_facetype[ngeo[3]][(STBVOX_FACE_north+nrot[3])&3]; + visible_faces |= ((stbvox_face_visible[type]) >> (ntype + 5 - STBVOX_FACE_south)) & (1 << STBVOX_FACE_south); + } + if (visible_base & (1 << STBVOX_FACE_up)) { + int type = stbvox_facetype[ geo ][STBVOX_FACE_up]; + int ntype = stbvox_facetype[ngeo[4]][STBVOX_FACE_down]; + visible_faces |= ((stbvox_face_visible[type]) >> (ntype + 5 - STBVOX_FACE_up)) & (1 << STBVOX_FACE_up); + } + if (visible_base & (1 << STBVOX_FACE_down)) { + int type = stbvox_facetype[ geo ][STBVOX_FACE_down]; + int ntype = stbvox_facetype[ngeo[5]][STBVOX_FACE_up]; + visible_faces |= ((stbvox_face_visible[type]) >> (ntype + 5 - STBVOX_FACE_down)) & (1 << STBVOX_FACE_down); + } + + if (geo == STBVOX_GEOM_force) + geo = STBVOX_GEOM_solid; + + assert((geo == STBVOX_GEOM_crossed_pair) ? (visible_faces == 15) : 1); + + // now we finally know for sure which faces are getting generated + if (visible_faces == 0) + return; + + mesh = mm->default_mesh; + if (mm->input.selector) + mesh = mm->input.selector[v_off]; + else if (mm->input.block_selector) + mesh = mm->input.block_selector[bt]; + + if (geo <= STBVOX_GEOM_ceil_slope_north_is_bottom) { + // this is the simple case, we can just use regular block gen with special vmesh calculated with vheight + stbvox_mesh_vertex basevert; + stbvox_mesh_vertex vmesh[6][4]; + stbvox_rotate rotate = { 0,0,0,0 }; + unsigned char simple_rot = rot; + int i; + // we only need to do this for the displayed faces, but it's easier + // to just do it up front; @OPTIMIZE check if it's faster to do it + // for visible faces only + for (i=0; i < 6*4; ++i) { + int vert = stbvox_vertex_selector[0][i]; + vert = stbvox_rotate_vertex[vert][rot]; + vmesh[0][i] = stbvox_vmesh_pre_vheight[0][i] + + stbvox_geometry_vheight[geo][vert]; + } + + basevert = stbvox_vertex_encode(pos.x, pos.y, pos.z << STBVOX_CONFIG_PRECISION_Z, 0,0); + if (mm->input.selector) { + mesh = mm->input.selector[v_off]; + } else if (mm->input.block_selector) + mesh = mm->input.block_selector[bt]; + + + // check if we're going off the end + if (mm->output_cur[mesh][0] + mm->output_size[mesh][0]*6 > mm->output_end[mesh][0]) { + mm->full = 1; + return; + } + + if (geo >= STBVOX_GEOM_floor_slope_north_is_top) { + if (visible_faces & (1 << STBVOX_FACE_up)) { + int normal = geo == STBVOX_GEOM_floor_slope_north_is_top ? stbvox_floor_slope_for_rot[simple_rot] : STBVOX_FACE_up; + rotate.facerot = simple_rot; + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, normal); + } + if (visible_faces & (1 << STBVOX_FACE_down)) { + int normal = geo == STBVOX_GEOM_ceil_slope_north_is_bottom ? stbvox_ceil_slope_for_rot[simple_rot] : STBVOX_FACE_down; + rotate.facerot = (-rotate.facerot) & 3; + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, normal); + } + } else { + if (visible_faces & (1 << STBVOX_FACE_up)) { + rotate.facerot = simple_rot; + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, STBVOX_FACE_up); + } + if (visible_faces & (1 << STBVOX_FACE_down)) { + rotate.facerot = (-rotate.facerot) & 3; + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, STBVOX_FACE_down); + } + } + + if (mm->input.rotate) { + unsigned char val = mm->input.rotate[v_off]; + rotate.block = (val >> 0) & 3; + rotate.overlay = (val >> 2) & 3; + //rotate.tex2 = (val >> 4) & 3; + rotate.ecolor = (val >> 6) & 3; + } else { + rotate.block = rotate.overlay = rotate.ecolor = simple_rot; + } + + rotate.facerot = 0; + + if (visible_faces & (1 << STBVOX_FACE_north)) + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_north, v_off, pos, basevert, vmesh[STBVOX_FACE_north], mesh, STBVOX_FACE_north); + if (visible_faces & (1 << STBVOX_FACE_south)) + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_south, v_off, pos, basevert, vmesh[STBVOX_FACE_south], mesh, STBVOX_FACE_south); + if (visible_faces & (1 << STBVOX_FACE_east)) + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_east , v_off, pos, basevert, vmesh[STBVOX_FACE_east ], mesh, STBVOX_FACE_east); + if (visible_faces & (1 << STBVOX_FACE_west)) + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_west , v_off, pos, basevert, vmesh[STBVOX_FACE_west ], mesh, STBVOX_FACE_west); + } + if (geo >= STBVOX_GEOM_floor_vheight_03) { + // this case can also be generated with regular block gen with special vmesh, + // except: + // if we want to generate middle diagonal for 'weird' blocks + // it's more complicated to detect neighbor matchups + stbvox_mesh_vertex vmesh[6][4]; + stbvox_mesh_vertex cube[8]; + stbvox_mesh_vertex basevert; + stbvox_rotate rotate = { 0,0,0,0 }; + unsigned char simple_rot = rot; + unsigned char ht[4]; + int extreme; + + // extract the heights + #ifdef STBVOX_CONFIG_VHEIGHT_IN_LIGHTING + ht[0] = mm->input.lighting[v_off ] & 3; + ht[1] = mm->input.lighting[v_off+ew_off ] & 3; + ht[2] = mm->input.lighting[v_off +ns_off] & 3; + ht[3] = mm->input.lighting[v_off+ew_off+ns_off] & 3; + #else + if (mm->input.vheight) { + unsigned char v = mm->input.vheight[v_off]; + ht[0] = (v >> 0) & 3; + ht[1] = (v >> 2) & 3; + ht[2] = (v >> 4) & 3; + ht[3] = (v >> 6) & 3; + } else if (mm->input.block_vheight) { + unsigned char v = mm->input.block_vheight[bt]; + unsigned char raw[4]; + int i; + + raw[0] = (v >> 0) & 3; + raw[1] = (v >> 2) & 3; + raw[2] = (v >> 4) & 3; + raw[3] = (v >> 6) & 3; + + for (i=0; i < 4; ++i) + ht[i] = raw[stbvox_rotate_vertex[i][rot]]; + } else if (mm->input.packed_compact) { + ht[0] = (mm->input.packed_compact[v_off ] >> 2) & 3; + ht[1] = (mm->input.packed_compact[v_off+ew_off ] >> 2) & 3; + ht[2] = (mm->input.packed_compact[v_off +ns_off] >> 2) & 3; + ht[3] = (mm->input.packed_compact[v_off+ew_off+ns_off] >> 2) & 3; + } else if (mm->input.geometry) { + ht[0] = mm->input.geometry[v_off ] >> 6; + ht[1] = mm->input.geometry[v_off+ew_off ] >> 6; + ht[2] = mm->input.geometry[v_off +ns_off] >> 6; + ht[3] = mm->input.geometry[v_off+ew_off+ns_off] >> 6; + } else { + assert(0); + } + #endif + + // flag whether any sides go off the top of the block, which means + // our visible_faces test was wrong + extreme = (ht[0] == 3 || ht[1] == 3 || ht[2] == 3 || ht[3] == 3); + + if (geo >= STBVOX_GEOM_ceil_vheight_03) { + cube[0] = stbvox_vertex_encode(0,0,ht[0],0,0); + cube[1] = stbvox_vertex_encode(0,0,ht[1],0,0); + cube[2] = stbvox_vertex_encode(0,0,ht[2],0,0); + cube[3] = stbvox_vertex_encode(0,0,ht[3],0,0); + cube[4] = stbvox_vertex_encode(0,0,2,0,0); + cube[5] = stbvox_vertex_encode(0,0,2,0,0); + cube[6] = stbvox_vertex_encode(0,0,2,0,0); + cube[7] = stbvox_vertex_encode(0,0,2,0,0); + } else { + cube[0] = stbvox_vertex_encode(0,0,0,0,0); + cube[1] = stbvox_vertex_encode(0,0,0,0,0); + cube[2] = stbvox_vertex_encode(0,0,0,0,0); + cube[3] = stbvox_vertex_encode(0,0,0,0,0); + cube[4] = stbvox_vertex_encode(0,0,ht[0],0,0); + cube[5] = stbvox_vertex_encode(0,0,ht[1],0,0); + cube[6] = stbvox_vertex_encode(0,0,ht[2],0,0); + cube[7] = stbvox_vertex_encode(0,0,ht[3],0,0); + } + if (!mm->input.vheight && mm->input.block_vheight) { + // @TODO: support block vheight here, I've forgotten what needs to be done specially + } + + // build vertex mesh + { + int i; + for (i=0; i < 6*4; ++i) { + int vert = stbvox_vertex_selector[0][i]; + vmesh[0][i] = stbvox_vmesh_pre_vheight[0][i] + + cube[vert]; + } + } + + basevert = stbvox_vertex_encode(pos.x, pos.y, pos.z << STBVOX_CONFIG_PRECISION_Z, 0,0); + // check if we're going off the end + if (mm->output_cur[mesh][0] + mm->output_size[mesh][0]*6 > mm->output_end[mesh][0]) { + mm->full = 1; + return; + } + + // @TODO generate split faces + if (visible_faces & (1 << STBVOX_FACE_up)) { + if (geo >= STBVOX_GEOM_ceil_vheight_03) + // flat + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, STBVOX_FACE_up); + else { + #ifndef STBVOX_CONFIG_OPTIMIZED_VHEIGHT + // check if it's non-planar + if (cube[5] + cube[6] != cube[4] + cube[7]) { + // not planar, split along diagonal and make degenerate quads + if (geo == STBVOX_GEOM_floor_vheight_03) + stbvox_make_03_split_mesh_for_face(mm, rotate, STBVOX_FACE_up, v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, ht); + else + stbvox_make_12_split_mesh_for_face(mm, rotate, STBVOX_FACE_up, v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, ht); + } else + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, stbvox_planar_face_up_normal[ht[2]][ht[1]][ht[0]]); + #else + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, stbvox_optimized_face_up_normal[ht[3]][ht[2]][ht[1]][ht[0]]); + #endif + } + } + if (visible_faces & (1 << STBVOX_FACE_down)) { + if (geo < STBVOX_GEOM_ceil_vheight_03) + // flat + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, STBVOX_FACE_down); + else { + #ifndef STBVOX_CONFIG_OPTIMIZED_VHEIGHT + // check if it's non-planar + if (cube[1] + cube[2] != cube[0] + cube[3]) { + // not planar, split along diagonal and make degenerate quads + if (geo == STBVOX_GEOM_ceil_vheight_03) + stbvox_make_03_split_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, ht); + else + stbvox_make_12_split_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, ht); + } else + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, stbvox_reverse_face[stbvox_planar_face_up_normal[ht[2]][ht[1]][ht[0]]]); + #else + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, stbvox_reverse_face[stbvox_optimized_face_up_normal[ht[3]][ht[2]][ht[1]][ht[0]]]); + #endif + } + } + + if (mm->input.rotate) { + unsigned char val = mm->input.rotate[v_off]; + rotate.block = (val >> 0) & 3; + rotate.overlay = (val >> 2) & 3; + //rotate.tex2 = (val >> 4) & 3; + rotate.ecolor = (val >> 6) & 3; + } else if (mm->input.selector) { + rotate.block = rotate.overlay = rotate.ecolor = simple_rot; + } + + if ((visible_faces & (1 << STBVOX_FACE_north)) || (extreme && (ht[2] == 3 || ht[3] == 3))) + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_north, v_off, pos, basevert, vmesh[STBVOX_FACE_north], mesh, STBVOX_FACE_north); + if ((visible_faces & (1 << STBVOX_FACE_south)) || (extreme && (ht[0] == 3 || ht[1] == 3))) + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_south, v_off, pos, basevert, vmesh[STBVOX_FACE_south], mesh, STBVOX_FACE_south); + if ((visible_faces & (1 << STBVOX_FACE_east)) || (extreme && (ht[1] == 3 || ht[3] == 3))) + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_east , v_off, pos, basevert, vmesh[STBVOX_FACE_east ], mesh, STBVOX_FACE_east); + if ((visible_faces & (1 << STBVOX_FACE_west)) || (extreme && (ht[0] == 3 || ht[2] == 3))) + stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_west , v_off, pos, basevert, vmesh[STBVOX_FACE_west ], mesh, STBVOX_FACE_west); + } + + if (geo == STBVOX_GEOM_crossed_pair) { + // this can be generated with a special vmesh + stbvox_mesh_vertex basevert = stbvox_vertex_encode(pos.x, pos.y, pos.z << STBVOX_CONFIG_PRECISION_Z , 0,0); + unsigned char simple_rot=0; + stbvox_rotate rot = { 0,0,0,0 }; + unsigned char mesh = mm->default_mesh; + if (mm->input.selector) { + mesh = mm->input.selector[v_off]; + simple_rot = mesh >> 4; + mesh &= 15; + } + if (mm->input.block_selector) { + mesh = mm->input.block_selector[bt]; + } + + // check if we're going off the end + if (mm->output_cur[mesh][0] + mm->output_size[mesh][0]*4 > mm->output_end[mesh][0]) { + mm->full = 1; + return; + } + + if (mm->input.rotate) { + unsigned char val = mm->input.rotate[v_off]; + rot.block = (val >> 0) & 3; + rot.overlay = (val >> 2) & 3; + //rot.tex2 = (val >> 4) & 3; + rot.ecolor = (val >> 6) & 3; + } else if (mm->input.selector) { + rot.block = rot.overlay = rot.ecolor = simple_rot; + } + rot.facerot = 0; + + stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_north, v_off, pos, basevert, stbvox_vmesh_crossed_pair[STBVOX_FACE_north], mesh, STBVF_ne_u_cross); + stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_south, v_off, pos, basevert, stbvox_vmesh_crossed_pair[STBVOX_FACE_south], mesh, STBVF_sw_u_cross); + stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_east , v_off, pos, basevert, stbvox_vmesh_crossed_pair[STBVOX_FACE_east ], mesh, STBVF_se_u_cross); + stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_west , v_off, pos, basevert, stbvox_vmesh_crossed_pair[STBVOX_FACE_west ], mesh, STBVF_nw_u_cross); + } + + + // @TODO + // STBVOX_GEOM_floor_slope_north_is_top_as_wall, + // STBVOX_GEOM_ceil_slope_north_is_bottom_as_wall, +} + +static void stbvox_make_mesh_for_column(stbvox_mesh_maker *mm, int x, int y, int z0) +{ + stbvox_pos pos; + int v_off = x * mm->x_stride_in_bytes + y * mm->y_stride_in_bytes; + int ns_off = mm->y_stride_in_bytes; + int ew_off = mm->x_stride_in_bytes; + pos.x = x; + pos.y = y; + pos.z = 0; + if (mm->input.geometry) { + unsigned char *bt = mm->input.blocktype + v_off; + unsigned char *geo = mm->input.geometry + v_off; + int z; + for (z=z0; z < mm->z1; ++z) { + if (bt[z] && ( !bt[z+ns_off] || !STBVOX_GET_GEO(geo[z+ns_off]) || !bt[z-ns_off] || !STBVOX_GET_GEO(geo[z-ns_off]) + || !bt[z+ew_off] || !STBVOX_GET_GEO(geo[z+ew_off]) || !bt[z-ew_off] || !STBVOX_GET_GEO(geo[z-ew_off]) + || !bt[z-1] || !STBVOX_GET_GEO(geo[z-1]) || !bt[z+1] || !STBVOX_GET_GEO(geo[z+1]))) + { // TODO check up and down + pos.z = z; + stbvox_make_mesh_for_block_with_geo(mm, pos, v_off+z); + if (mm->full) { + mm->cur_z = z; + return; + } + } + } + } else if (mm->input.block_geometry) { + int z; + unsigned char *bt = mm->input.blocktype + v_off; + unsigned char *geo = mm->input.block_geometry; + for (z=z0; z < mm->z1; ++z) { + if (bt[z] && ( geo[bt[z+ns_off]] != STBVOX_GEOM_solid + || geo[bt[z-ns_off]] != STBVOX_GEOM_solid + || geo[bt[z+ew_off]] != STBVOX_GEOM_solid + || geo[bt[z-ew_off]] != STBVOX_GEOM_solid + || geo[bt[z-1]] != STBVOX_GEOM_solid + || geo[bt[z+1]] != STBVOX_GEOM_solid)) + { + pos.z = z; + stbvox_make_mesh_for_block_with_geo(mm, pos, v_off+z); + if (mm->full) { + mm->cur_z = z; + return; + } + } + } + } else { + unsigned char *bt = mm->input.blocktype + v_off; + int z; + #if STBVOX_CONFIG_PRECISION_Z == 1 + stbvox_mesh_vertex *vmesh = stbvox_vmesh_delta_half_z[0]; + #else + stbvox_mesh_vertex *vmesh = stbvox_vmesh_delta_normal[0]; + #endif + for (z=z0; z < mm->z1; ++z) { + // if it's solid and at least one neighbor isn't solid + if (bt[z] && (!bt[z+ns_off] || !bt[z-ns_off] || !bt[z+ew_off] || !bt[z-ew_off] || !bt[z-1] || !bt[z+1])) { + pos.z = z; + stbvox_make_mesh_for_block(mm, pos, v_off+z, vmesh); + if (mm->full) { + mm->cur_z = z; + return; + } + } + } + } +} + +static void stbvox_bring_up_to_date(stbvox_mesh_maker *mm) +{ + if (mm->config_dirty) { + int i; + #ifdef STBVOX_ICONFIG_FACE_ATTRIBUTE + mm->num_mesh_slots = 1; + for (i=0; i < STBVOX_MAX_MESHES; ++i) { + mm->output_size[i][0] = 32; + mm->output_step[i][0] = 8; + } + #else + mm->num_mesh_slots = 2; + for (i=0; i < STBVOX_MAX_MESHES; ++i) { + mm->output_size[i][0] = 16; + mm->output_step[i][0] = 4; + mm->output_size[i][1] = 4; + mm->output_step[i][1] = 4; + } + #endif + + mm->config_dirty = 0; + } +} + +int stbvox_make_mesh(stbvox_mesh_maker *mm) +{ + int x,y; + stbvox_bring_up_to_date(mm); + mm->full = 0; + if (mm->cur_x > mm->x0 || mm->cur_y > mm->y0 || mm->cur_z > mm->z0) { + stbvox_make_mesh_for_column(mm, mm->cur_x, mm->cur_y, mm->cur_z); + if (mm->full) + return 0; + ++mm->cur_y; + while (mm->cur_y < mm->y1 && !mm->full) { + stbvox_make_mesh_for_column(mm, mm->cur_x, mm->cur_y, mm->z0); + if (mm->full) + return 0; + ++mm->cur_y; + } + ++mm->cur_x; + } + for (x=mm->cur_x; x < mm->x1; ++x) { + for (y=mm->y0; y < mm->y1; ++y) { + stbvox_make_mesh_for_column(mm, x, y, mm->z0); + if (mm->full) { + mm->cur_x = x; + mm->cur_y = y; + return 0; + } + } + } + return 1; +} + +void stbvox_init_mesh_maker(stbvox_mesh_maker *mm) +{ + memset(mm, 0, sizeof(*mm)); + stbvox_build_default_palette(); + + mm->config_dirty = 1; + mm->default_mesh = 0; +} + +int stbvox_get_buffer_count(stbvox_mesh_maker *mm) +{ + stbvox_bring_up_to_date(mm); + return mm->num_mesh_slots; +} + +int stbvox_get_buffer_size_per_quad(stbvox_mesh_maker *mm, int n) +{ + return mm->output_size[0][n]; +} + +void stbvox_reset_buffers(stbvox_mesh_maker *mm) +{ + int i; + for (i=0; i < STBVOX_MAX_MESHES*STBVOX_MAX_MESH_SLOTS; ++i) { + mm->output_cur[0][i] = 0; + mm->output_buffer[0][i] = 0; + } +} + +void stbvox_set_buffer(stbvox_mesh_maker *mm, int mesh, int slot, void *buffer, size_t len) +{ + int i; + stbvox_bring_up_to_date(mm); + mm->output_buffer[mesh][slot] = (char *) buffer; + mm->output_cur [mesh][slot] = (char *) buffer; + mm->output_len [mesh][slot] = (int) len; + mm->output_end [mesh][slot] = (char *) buffer + len; + for (i=0; i < STBVOX_MAX_MESH_SLOTS; ++i) { + if (mm->output_buffer[mesh][i]) { + assert(mm->output_len[mesh][i] / mm->output_size[mesh][i] == mm->output_len[mesh][slot] / mm->output_size[mesh][slot]); + } + } +} + +void stbvox_set_default_mesh(stbvox_mesh_maker *mm, int mesh) +{ + mm->default_mesh = mesh; +} + +int stbvox_get_quad_count(stbvox_mesh_maker *mm, int mesh) +{ + return (int) ((mm->output_cur[mesh][0] - mm->output_buffer[mesh][0]) / mm->output_size[mesh][0]); +} + +stbvox_input_description *stbvox_get_input_description(stbvox_mesh_maker *mm) +{ + return &mm->input; +} + +void stbvox_set_input_range(stbvox_mesh_maker *mm, int x0, int y0, int z0, int x1, int y1, int z1) +{ + mm->x0 = x0; + mm->y0 = y0; + mm->z0 = z0; + + mm->x1 = x1; + mm->y1 = y1; + mm->z1 = z1; + + mm->cur_x = x0; + mm->cur_y = y0; + mm->cur_z = z0; + + // @TODO validate that this range is representable in this mode +} + +void stbvox_get_transform(stbvox_mesh_maker *mm, float transform[3][3]) +{ + // scale + transform[0][0] = 1.0; + transform[0][1] = 1.0; + #if STBVOX_CONFIG_PRECISION_Z==1 + transform[0][2] = 0.5f; + #else + transform[0][2] = 1.0f; + #endif + // translation + transform[1][0] = (float) (mm->pos_x); + transform[1][1] = (float) (mm->pos_y); + transform[1][2] = (float) (mm->pos_z); + // texture coordinate projection translation + transform[2][0] = (float) (mm->pos_x & 255); // @TODO depends on max texture scale + transform[2][1] = (float) (mm->pos_y & 255); + transform[2][2] = (float) (mm->pos_z & 255); +} + +void stbvox_get_bounds(stbvox_mesh_maker *mm, float bounds[2][3]) +{ + bounds[0][0] = (float) (mm->pos_x + mm->x0); + bounds[0][1] = (float) (mm->pos_y + mm->y0); + bounds[0][2] = (float) (mm->pos_z + mm->z0); + bounds[1][0] = (float) (mm->pos_x + mm->x1); + bounds[1][1] = (float) (mm->pos_y + mm->y1); + bounds[1][2] = (float) (mm->pos_z + mm->z1); +} + +void stbvox_set_mesh_coordinates(stbvox_mesh_maker *mm, int x, int y, int z) +{ + mm->pos_x = x; + mm->pos_y = y; + mm->pos_z = z; +} + +void stbvox_set_input_stride(stbvox_mesh_maker *mm, int x_stride_in_bytes, int y_stride_in_bytes) +{ + int f,v; + mm->x_stride_in_bytes = x_stride_in_bytes; + mm->y_stride_in_bytes = y_stride_in_bytes; + for (f=0; f < 6; ++f) { + for (v=0; v < 4; ++v) { + mm->cube_vertex_offset[f][v] = stbvox_vertex_vector[f][v][0] * mm->x_stride_in_bytes + + stbvox_vertex_vector[f][v][1] * mm->y_stride_in_bytes + + stbvox_vertex_vector[f][v][2] ; + mm->vertex_gather_offset[f][v] = (stbvox_vertex_vector[f][v][0]-1) * mm->x_stride_in_bytes + + (stbvox_vertex_vector[f][v][1]-1) * mm->y_stride_in_bytes + + (stbvox_vertex_vector[f][v][2]-1) ; + } + } +} + +///////////////////////////////////////////////////////////////////////////// +// +// offline computation of tables +// + +#if 0 +// compute optimized vheight table +static char *normal_names[32] = +{ + 0,0,0,0,"u ",0, "eu ",0, + 0,0,0,0,"ne_u",0, "nu ",0, + 0,0,0,0,"nw_u",0, "wu ",0, + 0,0,0,0,"sw_u",0, "su ",0, +}; + +static char *find_best_normal(float x, float y, float z) +{ + int best_slot = 4; + float best_dot = 0; + int i; + for (i=0; i < 32; ++i) { + if (normal_names[i]) { + float dot = x * stbvox_default_normals[i][0] + y * stbvox_default_normals[i][1] + z * stbvox_default_normals[i][2]; + if (dot > best_dot) { + best_dot = dot; + best_slot = i; + } + } + } + return normal_names[best_slot]; +} + +int main(int argc, char **argv) +{ + int sw,se,nw,ne; + for (ne=0; ne < 4; ++ne) { + for (nw=0; nw < 4; ++nw) { + for (se=0; se < 4; ++se) { + printf(" { "); + for (sw=0; sw < 4; ++sw) { + float x = (float) (nw + sw - ne - se); + float y = (float) (sw + se - nw - ne); + float z = 2; + printf("STBVF_%s, ", find_best_normal(x,y,z)); + } + printf("},\n"); + } + } + } + return 0; +} +#endif + +// @TODO +// +// - test API for texture rotation on side faces +// - API for texture rotation on top & bottom +// - better culling of vheight faces with vheight neighbors +// - better culling of non-vheight faces with vheight neighbors +// - gather vertex lighting from slopes correctly +// - better support texture edge_clamp: currently if you fall +// exactly on 1.0 you get wrapped incorrectly; this is rare, but +// can avoid: compute texcoords in vertex shader, offset towards +// center before modding, need 2 bits per vertex to know offset direction) +// - other mesh modes (10,6,4-byte quads) +// +// +// With TexBuffer for the fixed vertex data, we can actually do +// minecrafty non-blocks like stairs -- we still probably only +// want 256 or so, so we can't do the equivalent of all the vheight +// combos, but that's ok. The 256 includes baked rotations, but only +// some of them need it, and lots of block types share some faces. +// +// mode 5 (6 bytes): mode 6 (6 bytes) +// x:7 x:6 +// y:7 y:6 +// z:6 z:6 +// tex1:8 tex1:8 +// tex2:8 tex2:7 +// color:8 color:8 +// face:4 face:7 +// +// +// side faces (all x4) top&bottom faces (2x) internal faces (1x) +// 1 regular 1 regular +// 2 slabs 2 +// 8 stairs 4 stairs 16 +// 4 diag side 8 +// 4 upper diag side 8 +// 4 lower diag side 8 +// 4 crossed pairs +// +// 23*4 + 5*4 + 46 +// == 92 + 20 + 46 = 158 +// +// Must drop 30 of them to fit in 7 bits: +// ceiling half diagonals: 16+8 = 24 +// Need to get rid of 6 more. +// ceiling diagonals: 8+4 = 12 +// This brings it to 122, so can add a crossed-pair variant. +// (diagonal and non-diagonal, or randomly offset) +// Or carpet, which would be 5 more. +// +// +// Mode 4 (10 bytes): +// v: z:2,light:6 +// f: x:6,y:6,z:7, t1:8,t2:8,c:8,f:5 +// +// Mode ? (10 bytes) +// v: xyz:5 (27 values), light:3 +// f: x:7,y:7,z:6, t1:8,t2:8,c:8,f:4 +// (v: x:2,y:2,z:2,light:2) + +#endif // STB_VOXEL_RENDER_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/swl/variant.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/swl/variant.hpp new file mode 100644 index 0000000..bed5feb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/swl/variant.hpp @@ -0,0 +1,849 @@ +/* +MIT License + +Copyright (c) 2021 Jean-Baptiste Vallon Hoarau + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef SWL_CPP_LIBRARY_VARIANT_HPP +#define SWL_CPP_LIBRARY_VARIANT_HPP + +#include +#include +#include // swap +#include // used for index_type +#include + +// a user-provided header for tweaks +// possible macros defined : +// SWL_VARIANT_NO_CONSTEXPR_EMPLACE +// SWL_VARIANT_NO_STD_HASH +#if __has_include("swl_variant_knobs.hpp") + #include "swl_variant_knobs.hpp" +#endif + +#ifndef SWL_VARIANT_NO_CONSTEXPR_EMPLACE + #include +#else + #include +#endif + +#ifndef SWL_VARIANT_NO_STD_HASH + #include +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#define SWL_FWD(x) static_cast(x) +#define SWL_MOV(x) static_cast< std::remove_reference_t&& >(x) + +#ifdef SWL_VARIANT_DEBUG + #include + #define DebugAssert(X) if (not (X)) std::cout << "Variant : assertion failed : [" << #X << "] at line : " << __LINE__ << "\n"; + #undef SWL_VARIANT_DEBUG +#else + #define DebugAssert(X) +#endif + +namespace swl { + +class bad_variant_access final : public std::exception { + const char* message = ""; // llvm test requires a well formed what() on default init + public : + bad_variant_access(const char* str) noexcept : message{str} {} + bad_variant_access() noexcept = default; + bad_variant_access(const bad_variant_access&) noexcept = default; + bad_variant_access& operator= (const bad_variant_access&) noexcept = default; + const char* what() const noexcept override { return message; } +}; + +namespace vimpl { + struct variant_tag{}; + struct emplacer_tag{}; +} + +template +struct in_place_type_t : private vimpl::emplacer_tag {}; + +template +struct in_place_index_t : private vimpl::emplacer_tag {}; + +template +inline static constexpr in_place_index_t in_place_index; + +template +inline static constexpr in_place_type_t in_place_type; + +namespace vimpl { + #include "variant_detail.hpp" + #include "variant_visit.hpp" + + struct variant_npos_t { + template + constexpr bool operator==(T idx) const noexcept { return idx == std::numeric_limits::max(); } + }; +} + +template +inline constexpr bool is_variant = std::is_base_of_v>; + +inline static constexpr vimpl::variant_npos_t variant_npos; + +template +class variant; + +// ill-formed variant, an empty specialization prevents some really bad errors messages on gcc +template + requires ( + (std::is_array_v || ...) + || (std::is_reference_v || ...) + || (std::is_void_v || ...) + || sizeof...(Ts) == 0 + ) +class variant { + static_assert( sizeof...(Ts) > 0, "A variant cannot be empty."); + static_assert( not (std::is_reference_v || ...), "A variant cannot contain references, consider using reference wrappers instead." ); + static_assert( not (std::is_void_v || ...), "A variant cannot contains void." ); + static_assert( not (std::is_array_v || ...), "A variant cannot contain a raw array type, consider using std::array instead." ); +}; + +template +class variant : private vimpl::variant_tag { + + using storage_t = vimpl::union_node, vimpl::dummy_type>; + + static constexpr bool is_trivial = std::is_trivial_v; + static constexpr bool has_copy_ctor = std::is_copy_constructible_v; + static constexpr bool trivial_copy_ctor = is_trivial || std::is_trivially_copy_constructible_v; + static constexpr bool has_copy_assign = std::is_copy_constructible_v; + static constexpr bool trivial_copy_assign = is_trivial || std::is_trivially_copy_assignable_v; + static constexpr bool has_move_ctor = std::is_move_constructible_v; + static constexpr bool trivial_move_ctor = is_trivial || std::is_trivially_move_constructible_v; + static constexpr bool has_move_assign = std::is_move_assignable_v; + static constexpr bool trivial_move_assign = is_trivial || std::is_trivially_move_assignable_v; + static constexpr bool trivial_dtor = std::is_trivially_destructible_v; + + public : + + template + using alternative = std::remove_reference_t< decltype( std::declval().template get() ) >; + + static constexpr bool can_be_valueless = not is_trivial; + + static constexpr unsigned size = sizeof...(Ts); + + using index_type = vimpl::smallest_suitable_integer_type; + + static constexpr index_type npos = -1; + + template + static constexpr int index_of = vimpl::find_first_true( {std::is_same_v...} ); + + // ============================================= constructors (20.7.3.2) + + // default constructor + constexpr variant() + noexcept (std::is_nothrow_default_constructible_v>) + requires std::is_default_constructible_v> + : storage{ in_place_index<0> }, current{0} + {} + + // copy constructor (trivial) + constexpr variant(const variant&) + requires trivial_copy_ctor + = default; + + // note : both the copy and move constructor cannot be meaningfully constexpr without std::construct_at + // copy constructor + constexpr variant(const variant& o) + requires (has_copy_ctor and not trivial_copy_ctor) + : storage{ vimpl::dummy_type{} } { + construct_from(o); + } + + // move constructor (trivial) + constexpr variant(variant&&) + requires trivial_move_ctor + = default; + + // move constructor + constexpr variant(variant&& o) + noexcept ((std::is_nothrow_move_constructible_v && ...)) + requires (has_move_ctor and not trivial_move_ctor) + : storage{ vimpl::dummy_type{} } { + construct_from(static_cast(o)); + } + + // generic constructor + template , class D = std::decay_t> + constexpr variant(T&& t) + noexcept ( std::is_nothrow_constructible_v ) + requires ( not std::is_same_v and not std::is_base_of_v ) + : variant{ in_place_index< index_of >, static_cast(t) } + {} + + // construct at index + template + requires (Index < size && std::is_constructible_v, Args&&...>) + explicit constexpr variant(in_place_index_t tag, Args&&... args) + : storage{tag, static_cast(args)...}, current(Index) + {} + + // construct a given type + template + requires (vimpl::appears_exactly_once && std::is_constructible_v) + explicit constexpr variant(in_place_type_t, Args&&... args) + : variant{ in_place_index< index_of >, static_cast(args)... } + {} + + // initializer-list constructors + template + requires ( + (Index < size) and + std::is_constructible_v< alternative, std::initializer_list&, Args&&... > + ) + explicit constexpr variant (in_place_index_t tag, std::initializer_list list, Args&&... args) + : storage{ tag, list, SWL_FWD(args)... }, current{Index} + {} + + template + requires ( + vimpl::appears_exactly_once + && std::is_constructible_v< T, std::initializer_list&, Args&&... > + ) + explicit constexpr variant (in_place_type_t, std::initializer_list list, Args&&... args) + : storage{ in_place_index>, list, SWL_FWD(args)... }, current{index_of} + {} + + // ================================ destructors (20.7.3.3) + + constexpr ~variant() requires trivial_dtor = default; + + constexpr ~variant() requires (not trivial_dtor) { + reset(); + } + + // ================================ assignment (20.7.3.4) + + // copy assignment (trivial) + constexpr variant& operator=(const variant& o) + requires trivial_copy_assign && trivial_copy_ctor + = default; + + // copy assignment + constexpr variant& operator=(const variant& rhs) + requires (has_copy_assign and not(trivial_copy_assign && trivial_copy_ctor)) + { + assign_from(rhs, [this] (const auto& elem, auto index_cst) { + if (index() == index_cst) + unsafe_get() = elem; + else{ + using type = alternative; + if constexpr (std::is_nothrow_copy_constructible_v + or not std::is_nothrow_move_constructible_v) + this->emplace(elem); + else{ + alternative tmp = elem; + this->emplace( SWL_MOV(tmp) ); + } + } + }); + return *this; + } + + // move assignment (trivial) + constexpr variant& operator=(variant&& o) + requires (trivial_move_assign and trivial_move_ctor and trivial_dtor) + = default; + + // move assignment + constexpr variant& operator=(variant&& o) + noexcept ((std::is_nothrow_move_constructible_v && ...) && (std::is_nothrow_move_assignable_v && ...)) + requires (has_move_assign && has_move_ctor and not(trivial_move_assign and trivial_move_ctor and trivial_dtor)) + { + this->assign_from( SWL_FWD(o), [this] (auto&& elem, auto index_cst) + { + if (index() == index_cst) + this->unsafe_get() = SWL_MOV(elem); + else + this->emplace( SWL_MOV(elem) ); + }); + return *this; + } + + // generic assignment + template + requires vimpl::has_non_ambiguous_match + constexpr variant& operator=(T&& t) + noexcept( std::is_nothrow_assignable_v, T&&> + && std::is_nothrow_constructible_v, T&&> ) + { + using related_type = vimpl::best_overload_match; + constexpr auto new_index = index_of; + + if (this->current == new_index) + this->unsafe_get() = SWL_FWD(t); + else { + + constexpr bool do_simple_emplace = + std::is_nothrow_constructible_v + or not std::is_nothrow_move_constructible_v; + + if constexpr ( do_simple_emplace ) + this->emplace( SWL_FWD(t) ); + else { + related_type tmp = t; + this->emplace( SWL_MOV(tmp) ); + } + } + + return *this; + } + + // ================================== modifiers (20.7.3.5) + + template + requires (std::is_constructible_v && vimpl::appears_exactly_once) + constexpr T& emplace(Args&&... args){ + return emplace>(static_cast(args)...); + } + + template + requires (Idx < size and std::is_constructible_v, Args&&...> ) + constexpr auto& emplace(Args&&... args){ + return emplace_impl(SWL_FWD(args)...); + } + + // emplace with initializer-lists + template + requires ( Idx < size + && std::is_constructible_v, std::initializer_list&, Args&&...> ) + constexpr auto& emplace(std::initializer_list list, Args&&... args){ + return emplace_impl(list, SWL_FWD(args)...); + } + + template + requires ( std::is_constructible_v&, Args&&...> + && vimpl::appears_exactly_once ) + constexpr T& emplace(std::initializer_list list, Args&&... args){ + return emplace_impl>( list, SWL_FWD(args)... ); + } + + // ==================================== value status (20.7.3.6) + + constexpr bool valueless_by_exception() const noexcept { + if constexpr ( can_be_valueless ) + return current == npos; + else return false; + } + + constexpr index_type index() const noexcept { + return current; + } + + // =================================== swap (20.7.3.7) + + constexpr void swap(variant& o) + noexcept ( (std::is_nothrow_move_constructible_v && ...) + && (vimpl::swap_trait::template nothrow && ...) ) + requires (has_move_ctor && (vimpl::swap_trait::template able && ...)) + { + + if constexpr (can_be_valueless){ + // if one is valueless, move the element form the non-empty variant, + // reset it, and set it to valueless + constexpr auto impl_one_valueless = [] (auto&& full, auto& empty) { + vimpl::visit_with_index( SWL_FWD(full), vimpl::emplace_no_dtor_from_elem{empty} ); + full.reset_no_check(); + full.current = npos; + }; + + switch( static_cast(this->index() == npos) + static_cast(o.index() == npos) * 2 ) + { + case 0 : + break; + case 1 : + // "this" is valueless + impl_one_valueless( SWL_MOV(o), *this ); + return; + case 2 : + // "other" is valueless + impl_one_valueless( SWL_MOV(*this), o ); + return; + case 3 : + // both are valueless, do nothing + return; + } + } + + DebugAssert( not (valueless_by_exception() && o.valueless_by_exception()) ); + + vimpl::visit_with_index( o, [&o, this] (auto&& elem, auto index_) { + + if (this->index() == index_){ + using std::swap; + swap( this->unsafe_get(), elem ); + return; + } + + using idx_t = decltype(index_); + vimpl::visit_with_index(*this, [this, &o, &elem] (auto&& this_elem, auto this_index) { + + auto tmp { SWL_MOV(this_elem) }; + + // destruct the element + vimpl::destruct>(this_elem); + + // ok, we just destroyed the element in this, don't call the dtor again + this->emplace_no_dtor( SWL_MOV(elem) ); + + // we could refactor this + vimpl::destruct>(elem); + o.template emplace_no_dtor< (unsigned)(this_index) >( SWL_MOV(tmp) ); + + }); + }); + } + + // +================================== methods for internal use + // these methods performs no errors checking at all + + template + constexpr auto& unsafe_get() & noexcept { + static_assert(Idx < size); + DebugAssert(current == Idx); + return storage.template get(); + } + + template + constexpr auto&& unsafe_get() && noexcept { + static_assert(Idx < size); + DebugAssert(current == Idx); + return SWL_MOV( storage.template get() ); + } + + template + constexpr const auto& unsafe_get() const & noexcept { + static_assert(Idx < size); + DebugAssert(current == Idx); + return const_cast(*this).unsafe_get(); + } + + template + constexpr const auto&& unsafe_get() const && noexcept { + static_assert(Idx < size); + DebugAssert(current == Idx); + return SWL_MOV(unsafe_get()); + } + + private : + + // assign from another variant + template + constexpr void assign_from(Other&& o, Fn&& fn){ + if constexpr (can_be_valueless){ + if (o.index() == npos){ + if (current != npos){ + reset_no_check(); + current = npos; + } + return; + } + } + DebugAssert(not o.valueless_by_exception()); + vimpl::visit_with_index( SWL_FWD(o), SWL_FWD(fn) ); + } + + template + constexpr auto& emplace_impl(Args&&... args) + { + reset(); + emplace_no_dtor( SWL_FWD(args)... ); + return unsafe_get(); + } + + // can be used directly only when the variant is in a known empty state + template + constexpr void emplace_no_dtor(Args&&... args) + { + using T = alternative; + + if constexpr ( not std::is_nothrow_constructible_v ) + { + if constexpr ( std::is_nothrow_move_constructible_v ) + do_emplace_no_dtor( T{SWL_FWD(args)...} ); + else if constexpr ( std::is_nothrow_copy_constructible_v ) + { + T tmp {SWL_FWD(args)...}; + do_emplace_no_dtor( tmp ); + } + else + { + static_assert( can_be_valueless && (Idx == Idx), + "Internal error : the possibly valueless branch of emplace was taken despite |can_be_valueless| being false"); + current = npos; + do_emplace_no_dtor( SWL_FWD(args)... ); + } + } + else + do_emplace_no_dtor( SWL_FWD(args)... ); + } + + template + constexpr void do_emplace_no_dtor(Args&&... args) + { + auto* ptr = vimpl::addressof( unsafe_get() ); + + #ifdef SWL_VARIANT_NO_CONSTEXPR_EMPLACE + using T = alternative; + new ((void*)(ptr)) T ( SWL_FWD(args)... ); + #else + std::construct_at( ptr, SWL_FWD(args)... ); + #endif + + current = static_cast(Idx); + } + + // destroy the current elem IFF not valueless + constexpr void reset() { + if constexpr (can_be_valueless) + if (valueless_by_exception()) return; + reset_no_check(); + } + + // destroy the current element without checking for valueless + constexpr void reset_no_check(){ + DebugAssert( index() < size ); + if constexpr ( not trivial_dtor ){ + vimpl::visit_with_index( *this, [] (auto& elem, auto index_) { + vimpl::destruct>(elem); + }); + } + } + + // construct this from another variant, for constructors only + template + constexpr void construct_from(Other&& o){ + if constexpr (can_be_valueless) + if (o.valueless_by_exception()){ + current = npos; + return; + } + + vimpl::visit_with_index( SWL_FWD(o), vimpl::emplace_no_dtor_from_elem{*this} ); + } + + template + friend struct vimpl::emplace_no_dtor_from_elem; + + storage_t storage; + index_type current; +}; + +// ================================= value access (20.7.5) + +template +constexpr bool holds_alternative(const variant& v) noexcept { + static_assert( (std::is_same_v || ...), "Requested type is not contained in the variant" ); + constexpr auto Index = variant::template index_of; + return v.index() == Index; +} + +// ========= get by index + +template +constexpr auto& get (variant& v){ + static_assert( Idx < sizeof...(Ts), "Index exceeds the variant size. "); + if (v.index() != Idx) throw bad_variant_access{"swl::variant : Bad variant access in get."}; + return (v.template unsafe_get()); +} + +template +constexpr const auto& get (const variant& v){ + return swl::get(const_cast&>(v)); +} + +template +constexpr auto&& get (variant&& v){ + return SWL_MOV( swl::get(v) ); +} + +template +constexpr const auto&& get (const variant&& v){ + return SWL_MOV( swl::get(v) ); +} + +// ========= get by type + +template +constexpr T& get (variant& v){ + return swl::get< variant::template index_of >(v); +} + +template +constexpr const T& get (const variant& v){ + return swl::get< variant::template index_of >(v); +} + +template +constexpr T&& get (variant&& v){ + return swl::get< variant::template index_of >( SWL_FWD(v) ); +} + +template +constexpr const T&& get (const variant&& v){ + return swl::get< variant::template index_of >( SWL_FWD(v) ); +} + +// ===== get_if by index + +template +constexpr const auto* get_if(const variant* v) noexcept { + using rtype = typename variant::template alternative*; + if (v == nullptr || v->index() != Idx) + return rtype{nullptr}; + else + return vimpl::addressof( v->template unsafe_get() ); +} + +template +constexpr auto* get_if(variant* v) noexcept { + using rtype = typename variant::template alternative; + return const_cast( + swl::get_if( static_cast*>(v) ) + ); +} + +// ====== get_if by type + +template +constexpr T* get_if(variant* v) noexcept { + static_assert( (std::is_same_v || ...), "Requested type is not contained in the variant" ); + return swl::get_if< variant::template index_of >(v); +} + +template +constexpr const T* get_if(const variant* v) noexcept { + static_assert( (std::is_same_v || ...), "Requested type is not contained in the variant" ); + return swl::get_if< variant::template index_of >(v); +} + +// =============================== visitation (20.7.7) + +template +constexpr decltype(auto) visit(Fn&& fn, Vs&&... vs){ + if constexpr ( (std::decay_t::can_be_valueless || ...) ) + if ( (vs.valueless_by_exception() || ...) ) + throw bad_variant_access{"swl::variant : Bad variant access in visit."}; + + if constexpr (sizeof...(Vs) == 1) + return vimpl::visit( SWL_FWD(fn), SWL_FWD(vs)...); + else + return vimpl::multi_visit( SWL_FWD(fn), SWL_FWD(vs)...); +} + +template +constexpr decltype(auto) visit(Fn&& fn){ + return SWL_FWD(fn)(); +} + +template + requires (is_variant && ...) +constexpr R visit(Fn&& fn, Vs&&... vars){ + return static_cast( swl::visit( SWL_FWD(fn), SWL_FWD(vars)...) ); +} + +// ============================== relational operators (20.7.6) + +template + requires ( vimpl::has_eq_comp && ... ) +constexpr bool operator==(const variant& v1, const variant& v2){ + if (v1.index() != v2.index()) + return false; + if constexpr (variant::can_be_valueless) + if (v1.valueless_by_exception()) return true; + return vimpl::visit_with_index( v2, [&v1] (auto& elem, auto index) -> bool { + return (v1.template unsafe_get() == elem); + }); +} + +template +constexpr bool operator!=(const variant& v1, const variant& v2) + requires requires { v1 == v2; } +{ + return not(v1 == v2); +} + +template + requires ( vimpl::has_lesser_comp && ... ) +constexpr bool operator<(const variant& v1, const variant& v2){ + if constexpr (variant::can_be_valueless){ + if (v2.valueless_by_exception()) return false; + if (v1.valueless_by_exception()) return true; + } + if ( v1.index() == v2.index() ){ + return vimpl::visit_with_index( v1, [&v2] (auto& elem, auto index) -> bool { + return (elem < v2.template unsafe_get()); + } ); + } + else + return (v1.index() < v2.index()); +} + +template +constexpr bool operator>(const variant& v1, const variant& v2) + requires requires { v2 < v1; } +{ + return v2 < v1; +} + +template + requires ( vimpl::has_less_or_eq_comp && ... ) +constexpr bool operator<=(const variant& v1, const variant& v2){ + if constexpr (variant::can_be_valueless){ + if (v1.valueless_by_exception()) return true; + if (v2.valueless_by_exception()) return false; + } + if ( v1.index() == v2.index() ){ + return vimpl::visit_with_index( v1, [&v2] (auto& elem, auto index) -> bool { + return (elem <= v2.template unsafe_get()); + }); + } + else + return (v1.index() < v2.index()); +} + +template +constexpr bool operator>=(const variant& v1, const variant& v2) + requires requires { v2 <= v1; } +{ + return v2 <= v1; +} + +// ===================================== monostate (20.7.8, 20.7.9) + +struct monostate{}; +constexpr bool operator==(monostate, monostate) noexcept { return true; } +constexpr bool operator> (monostate, monostate) noexcept { return false; } +constexpr bool operator< (monostate, monostate) noexcept { return false; } +constexpr bool operator<=(monostate, monostate) noexcept { return true; } +constexpr bool operator>=(monostate, monostate) noexcept { return true; } + +// ===================================== specialized algorithms (20.7.10) + +template +constexpr void swap(variant& a, variant& b) + noexcept (noexcept(a.swap(b))) + requires requires { a.swap(b); } +{ + a.swap(b); +} + +// ===================================== helper classes (20.7.4) + +template + requires is_variant +inline constexpr std::size_t variant_size_v = std::decay_t::size; + +// not sure why anyone would need this, i'm adding it anyway +template + requires is_variant +struct variant_size : std::integral_constant> {}; + +namespace vimpl { + // ugh, we have to take care of volatile here + template + struct var_alt_impl { + template + using type = std::remove_reference_t().template unsafe_get() )>; + }; + + template <> + struct var_alt_impl { + template + using type = volatile typename var_alt_impl::template type>; + }; +} + +template + requires (Idx < variant_size_v) +using variant_alternative_t = typename vimpl::var_alt_impl< std::is_volatile_v >::template type; + +template + requires is_variant +struct variant_alternative { + using type = variant_alternative_t; +}; + +// ===================================== extensions (unsafe_get) + +template + requires is_variant +constexpr auto&& unsafe_get(Var&& var) noexcept { + static_assert( Idx < std::decay_t::size, "Index exceeds the variant size." ); + return SWL_FWD(var).template unsafe_get(); +} + +template + requires is_variant +constexpr auto&& unsafe_get(Var&& var) noexcept { + return swl::unsafe_get< std::decay_t::template index_of >( SWL_FWD(var) ); +} + +} // SWL + +// ====================================== hash support (20.7.12) +#ifndef SWL_VARIANT_NO_STD_HASH + + namespace std { + template + requires (swl::vimpl::has_std_hash && ...) + struct hash> { + std::size_t operator()(const swl::variant& v) const { + if constexpr ( swl::variant::can_be_valueless ) + if (v.valueless_by_exception()) return -1; + + return swl::vimpl::visit_with_index( v, [] (auto& elem, auto index_) { + using type = std::remove_cvref_t; + return std::hash{}(elem) + index_; + }); + } + }; + + template <> + struct hash { + constexpr std::size_t operator()(swl::monostate) const noexcept { return -1; } + }; + } +#else + #undef SWL_VARIANT_NO_STD_HASH +#endif // std-hash + +#undef DebugAssert +#undef SWL_FWD +#undef SWL_MOV + +#ifdef SWL_VARIANT_NO_CONSTEXPR_EMPLACE + #undef SWL_VARIANT_NO_CONSTEXPR_EMPLACE +#endif + +#endif // eof diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/swl/variant_detail.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/swl/variant_detail.hpp new file mode 100644 index 0000000..b2c1126 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/swl/variant_detail.hpp @@ -0,0 +1,335 @@ +#ifdef SWL_CPP_LIBRARY_VARIANT_HPP + +template +constexpr int find_first_true(bool (&&arr)[N]){ + for (int k = 0; k < N; ++k) + if (arr[k]) + return k; + return -1; +} + +template +inline constexpr bool appears_exactly_once = (static_cast(std::is_same_v) + ...) == 1; + +// ============= type pack element + +#if __has_builtin(__type_pack_element) + +template +using type_pack_element = __type_pack_element; + +#else + +template +struct find_type_i; + +template <> +struct find_type_i<1> { + template + using f = typename find_type_i<(Idx != 1)>::template f; +}; + +template <> +struct find_type_i<0> { + template + using f = T; +}; + +template +using type_pack_element = typename find_type_i<(K != 0)>::template f; + +#endif + +// ============= overload match detector. to be used for variant generic assignment + +template +using arr1 = T[1]; + +template +struct overload_frag { + using type = A; + template + requires requires { arr1{std::declval()}; } + auto operator()(A, T&&) -> overload_frag; +}; + +template +struct make_overload; + +template +struct make_overload, Args...> + : overload_frag... { + using overload_frag::operator()...; +}; + +template +using best_overload_match = typename decltype( + make_overload, Ts...>{} + ( std::declval(), std::declval() ) +)::type; + +template +concept has_non_ambiguous_match = + requires { typename best_overload_match; }; + +// ================================== rel ops + +template +concept convertible = std::is_convertible_v; + +template +concept has_eq_comp = requires (T a, T b) { + { a == b } -> convertible; +}; + +template +concept has_lesser_comp = requires (T a, T b) { + { a < b } -> convertible; +}; + +template +concept has_less_or_eq_comp = requires (T a, T b) { + { a <= b } -> convertible; +}; + +template +struct emplace_no_dtor_from_elem { + template + constexpr void operator()(T&& elem, auto index_) const { + a.template emplace_no_dtor( static_cast(elem) ); + } + A& a; +}; + +template +constexpr void destruct(T& obj){ + if constexpr (not std::is_trivially_destructible_v) + obj.~E(); +} + +// =============================== variant union types + +// =================== base variant storage type +// this type is used to build a N-ary tree of union. + +struct dummy_type{ static constexpr int elem_size = 0; }; // used to fill the back of union nodes + +using union_index_t = unsigned; + +#define TRAIT(trait) ( std::is_##trait##_v && std::is_##trait##_v ) + +#define SFM(signature, trait) \ + signature = default; \ + signature requires (TRAIT(trait) and not TRAIT(trivially_##trait)) {} + +// given the two members of type A and B of an union X +// this create the proper conditionally trivial special members functions +#define INJECT_UNION_SFM(X) \ + SFM(constexpr X (const X &), copy_constructible) \ + SFM(constexpr X (X&&), move_constructible) \ + SFM(constexpr X& operator=(const X&), copy_assignable) \ + SFM(constexpr X& operator=(X&&), move_assignable) \ + SFM(constexpr ~X(), destructible) + +template +struct node_trait; + +template <> +struct node_trait { + + template + static constexpr auto elem_size = not( std::is_same_v ) ? 2 : 1; + + template + static constexpr char ctor_branch = 0; +}; + +template <> +struct node_trait { + template + static constexpr auto elem_size = A::elem_size + B::elem_size; + + template + static constexpr char ctor_branch = (Index < A::elem_size) ? 1 : 2; +}; + +template +struct union_node { + + union { + A a; + B b; + }; + + static constexpr auto elem_size = node_trait::template elem_size; + + constexpr union_node() = default; + + template + requires (node_trait::template ctor_branch == 1) + constexpr union_node(in_place_index_t, Args&&... args) + : a{ in_place_index, static_cast(args)... } + {} + + template + requires (node_trait::template ctor_branch == 2) + constexpr union_node(in_place_index_t, Args&&... args) + : b{ in_place_index, static_cast(args)... } + {} + + template + requires (IsLeaf) + constexpr union_node(in_place_index_t<0>, Args&&... args) + : a{static_cast(args)...} + {} + + template + requires (IsLeaf) + constexpr union_node(in_place_index_t<1>, Args&&... args) + : b{static_cast(args)...} + {} + + constexpr union_node(dummy_type) + requires (std::is_same_v) + : b{} + {} + + template + constexpr auto& get() + { + if constexpr (IsLeaf) + { + if constexpr ( Index == 0 ) + return a; + else + return b; + } + else + { + if constexpr ( Index < A::elem_size ) + return a.template get(); + else + return b.template get(); + } + } + + INJECT_UNION_SFM(union_node) +}; + +#undef INJECT_UNION_SFM +#undef SFM +#undef TRAIT + +// =================== algorithm to build the tree of unions +// take a sequence of types and perform an order preserving fold until only one type is left +// the first parameter is the numbers of types remaining for the current pass + +constexpr unsigned char pick_next(unsigned remaining){ + return remaining >= 2 ? 2 : remaining; +} + +template +struct make_tree; + +template +struct make_tree<2, 1, IsFirstPass> { + template + using f = typename make_tree + < + pick_next(Remaining - 2), + sizeof...(Ts) != 0, + IsFirstPass + > + ::template f + < + Remaining - 2, + Ts..., + union_node + >; +}; + +// only one type left, stop +template +struct make_tree<0, 0, F> { + template + using f = A; +}; + +// end of one pass, restart +template +struct make_tree<0, 1, IsFirstPass> { + template + using f = typename make_tree + < + pick_next(sizeof...(Ts)), + (sizeof...(Ts) != 1), + false // <- both first pass and tail call recurse into a tail call + > + ::template f; +}; + +// one odd type left in the pass, put it at the back to preserve the order +template <> +struct make_tree<1, 1, false> { + template + using f = typename make_tree<0, sizeof...(Ts) != 0, false> + ::template f<0, Ts..., A>; +}; + +// one odd type left in the first pass, wrap it in an union +template <> +struct make_tree<1, 1, true> { + template + using f = typename make_tree<0, sizeof...(Ts) != 0, false> + ::template f<0, Ts..., union_node>; +}; + +template +using make_tree_union = typename + make_tree::template f; + +// ============================================================ + +// Ts... must be sorted in ascending size +template +using smallest_suitable_integer_type = + type_pack_element<(static_cast(Num > std::numeric_limits::max()) + ...), + Ts... + >; + +// why do we need this again? i think something to do with GCC? +namespace swap_trait { + using std::swap; + + template + concept able = requires (A a, A b) { swap(a, b); }; + + template + inline constexpr bool nothrow = noexcept( swap(std::declval(), std::declval()) ); +} + +#ifndef SWL_VARIANT_NO_STD_HASH + template + inline constexpr bool has_std_hash = requires (T t) { + std::size_t( ::std::hash< std::remove_cvref_t >{}(t) ); + }; +#endif + +template +inline constexpr T* addressof( T& obj ) noexcept { + #if defined(__GNUC__) || defined( __clang__ ) + return __builtin_addressof(obj); + #elif defined (SWL_VARIANT_NO_CONSTEXPR_EMPLACE) + // if & is overloaded, use the ugly version + if constexpr ( requires { obj.operator&(); } ) + return reinterpret_cast + (&const_cast(reinterpret_cast(obj))); + else + return &obj; + #else + return std::address_of(obj); + #endif +} + +#endif // eof + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/swl/variant_visit.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/swl/variant_visit.hpp new file mode 100644 index 0000000..4081d30 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/swl/variant_visit.hpp @@ -0,0 +1,134 @@ +#ifdef SWL_CPP_LIBRARY_VARIANT_HPP + +// ========================= visit dispatcher + +template +using rtype_visit = decltype( ( std::declval()( std::declval().template unsafe_get<0>()... ) ) ); + +template +using rtype_index_visit = decltype( ( std::declval()( std::declval().template unsafe_get<0>(), + std::integral_constant{} ) ) + ); + +inline namespace v1 { + +#if defined(__GNUC__) || defined( __clang__ ) || defined( __INTEL_COMPILER ) + #define DeclareUnreachable() __builtin_unreachable() +#elif defined (_MSC_VER) + #define DeclareUnreachable() __assume(false) +#else + #error "Compiler not supported, please file an issue." +#endif + +#define DEC(N) X((N)) X((N) + 1) X((N) + 2) X((N) + 3) X((N) + 4) X((N) + 5) X((N) + 6) X((N) + 7) X((N) + 8) X((N) + 9) + +#define SEQ30(N) DEC( (N) + 0 ) DEC( (N) + 10 ) DEC( (N) + 20 ) +#define SEQ100(N) SEQ30((N) + 0) SEQ30((N) + 30) SEQ30((N) + 60) DEC((N) + 90) +#define SEQ200(N) SEQ100((N) + 0) SEQ100((N) + 100) +#define SEQ400(N) SEQ200((N) + 0) SEQ200((N) + 200) +#define CAT(M, N) M##N +#define CAT2(M, N) CAT(M, N) +#define INJECTSEQ(N) CAT2(SEQ, N)(0) + +// single-visitation + +template +constexpr Rtype single_visit_tail(Fn&& fn, V&& v){ + + constexpr auto RemainingIndex = std::decay_t::size - Offset; + + #define X(N) case (N + Offset) : \ + if constexpr (N < RemainingIndex) { \ + return static_cast(fn)( static_cast(v).template unsafe_get() ); \ + break; \ + } else DeclareUnreachable(); + + #define SEQSIZE 200 + + switch( v.index() ){ + + INJECTSEQ(SEQSIZE) + + default : + if constexpr (SEQSIZE < RemainingIndex) + return vimpl::single_visit_tail(static_cast(fn), static_cast(v)); + else + DeclareUnreachable(); + } + + #undef X + #undef SEQSIZE +} + +template +constexpr Rtype single_visit_w_index_tail(Fn&& fn, V&& v){ + + constexpr auto RemainingIndex = std::decay_t::size - Offset; + + #define X(N) case (N + Offset) : \ + if constexpr (N < RemainingIndex) { \ + return static_cast(fn)( static_cast(v).template unsafe_get(), std::integral_constant{} ); \ + break; \ + } else DeclareUnreachable(); + + #define SEQSIZE 200 + + switch( v.index() ){ + + INJECTSEQ(SEQSIZE) + + default : + if constexpr (SEQSIZE < RemainingIndex) + return vimpl::single_visit_w_index_tail(static_cast(fn), static_cast(v)); + else + DeclareUnreachable(); + } + + #undef X + #undef SEQSIZE +} + +template +constexpr decltype(auto) visit(Fn&& fn, V&& v){ + return vimpl::single_visit_tail<0, rtype_visit>(SWL_FWD(fn), SWL_FWD(v)); +} + +// unlike other visit functions, this takes the variant first! +// this is confusing, but make the client code easier to read +template +constexpr decltype(auto) visit_with_index(V&& v, Fn&& fn){ + return vimpl::single_visit_w_index_tail<0, rtype_index_visit>(SWL_FWD(fn), SWL_FWD(v)); +} + +template +constexpr decltype(auto) multi_visit(Fn&& fn, Head&& head, Tail&&... tail){ + + // visit them one by one, starting with the last + auto vis = [&fn, &head] (auto&&... args) -> decltype(auto) { + return vimpl::visit( [&fn, &args...] (auto&& elem) -> decltype(auto) { + return SWL_FWD(fn)( SWL_FWD(elem), SWL_FWD(args)... ); + }, SWL_FWD(head) ); + }; + + if constexpr (sizeof...(tail) == 0) + return SWL_FWD(vis)(); + else if constexpr (sizeof...(tail) == 1) + return vimpl::visit( SWL_FWD(vis), SWL_FWD(tail)... ); + else + return vimpl::multi_visit(SWL_FWD(vis), SWL_FWD(tail)...); +} + +#undef DEC +#undef SEQ30 +#undef SEQ100 +#undef SEQ200 +#undef SEQ400 +#undef DeclareUnreachable +#undef CAT +#undef CAT2 +#undef INJECTSEQ + +} + + +#endif \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidy.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidy.h new file mode 100644 index 0000000..0235636 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidy.h @@ -0,0 +1,2220 @@ +#ifndef __TIDY_H__ +#define __TIDY_H__ + +/***************************************************************************//** + * @file + * Defines HTML Tidy public API implemented by LibTidy. + * + * This public interface provides the entire public API for LibTidy, and + * is the sole interface that you should use when implementing LibTidy in + * your own applications. + * + * See tidy.c as an example application implementing the public API. + * + * This API is const-correct and doesn't explicitly depend on any globals. + * Thus, thread-safety may be introduced without changing the interface. + * + * The API limits all exposure to internal structures and provides only + * accessors that return simple types such as C strings and integers, which + * makes it quite suitable for integration with any number of other languages. + * + * @author Dave Raggett [dsr@w3.org] + * @author HTACG, et al (consult git log) + * + * @remarks The contributing author(s) would like to thank all those who + * helped with testing, bug fixes and suggestions for improvements. + * This wouldn't have been possible without your help. + * + * @copyright + * Copyright (c) 1998-2017 World Wide Web Consortium (Massachusetts + * Institute of Technology, European Research Consortium for Informatics + * and Mathematics, Keio University). + * @par + * All Rights Reserved. + * @par + * This software and documentation is provided "as is," and the copyright + * holders and contributing author(s) make no representations or warranties, + * express or implied, including but not limited to, warranties of + * merchantability or fitness for any particular purpose or that the use of + * the software or documentation will not infringe any third party patents, + * copyrights, trademarks or other rights. + * @par + * The copyright holders and contributing author(s) will not be held liable + * for any direct, indirect, special or consequential damages arising out of + * any use of the software or documentation, even if advised of the + * possibility of such damage. + * @par + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, documentation and executables, for any + * purpose, without fee, subject to the following restrictions: + * @par + * 1. The origin of this source code must not be misrepresented. + * 2. Altered versions must be plainly marked as such and must not be + * misrepresented as being the original source. + * 3. This Copyright notice may not be removed or altered from any source + * or altered source distribution. + * @par + * The copyright holders and contributing author(s) specifically permit, + * without fee, and encourage the use of this source code as a component for + * supporting the Hypertext Markup Language in commercial products. If you + * use this source code in a product, acknowledgment is not required but + * would be appreciated. + * + * @date Created 2001-05-20 by Charles Reitzel + * @date Updated 2002-07-01 by Charles Reitzel - 1st Implementation + * @date Updated 2015-06-09 by Geoff R. McLane - Add more doxygen syntax + * @date Additional updates: consult git log + ******************************************************************************/ + +#include "tidyplatform.h" +#include "tidyenum.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************//** + ** @defgroup internal_api Internal API + ** The Internal API is used exclusively within LibTidy. If you are an + ** HTML Tidy developer, then the internals API will be of especial + ** importance to you. + ** + ** @note Always check first to determine whether or not an internal API + ** representation exists for a public API function before invoking a + ** public API function internally. In most cases, the public API + ** functions simply call an internal function. + ** - - - + ** @note This documentation _is not_ a substitute for browsing the source + ** code. Although the public API is fairly well documented, the + ** internal API is a very long, very slow, work-in-progress. + ******************************************************************************/ + +/***************************************************************************//** + ** @defgroup public_api External Public API + ** The Public API is the API that LibTidy programmers must access in order + ** to harness HTML Tidy as a library. The API limits all exposure to internal + ** structures and provides only accessors that return simple types such as + ** C strings and integers, which makes it quite suitable for integration with + ** any number of other languages. + ** @{ + ******************************************************************************/ + + +/* MARK: - Opaque Types */ +/***************************************************************************//** + ** @defgroup Opaque Opaque Types + ** + ** Instances of these types are returned by LibTidy API functions, however + ** they are opaque; you cannot see into them, and must use accessor functions + ** to access the contents. This ensures that interfacing to LibTidy remains + ** as universal as possible. + ** + ** @note Internally LibTidy developers will cast these to internal + ** implementation types with access to all member fields. + ** @{ + ******************************************************************************/ + +/** @struct TidyDoc + ** Instances of this represent a Tidy document, which encapsulates everything + ** there is to know about a single Tidy session. Many of the API functions + ** return instance of TidyDoc, or expect instances as parameters. + */ + +/** @struct TidyOption + ** Instances of this represent a Tidy configuration option, which contains + ** useful data about these options. Functions related to configuration options + ** return or accept instances of this type. + */ + +/** @struct TidyNode + ** Single nodes of a TidyDocument are represented by this datatype. It can be + ** returned by various API functions, or accepted as a function argument. + */ + +/** @struct TidyAttr + ** Attributes of a TidyNode are represented by this data type. The public API + ** functions related to attributes work with this type. + */ + +/** @struct TidyMessage + ** Instances of this type represent messages generated by Tidy in reference + ** to your document. This API is available in some of Tidy's message callback + ** functions. +*/ + +/** @struct TidyMessageArgument + ** Instances of this type represent the arguments that compose part of the + ** message represented by TidyMessage. These arguments have an API to query + ** information about them. +*/ + +/* Prevent Doxygen from listing these as functions. */ +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +opaque_type( TidyDoc ); +opaque_type( TidyOption ); +opaque_type( TidyNode ); +opaque_type( TidyAttr ); +opaque_type( TidyMessage ); +opaque_type( TidyMessageArgument ); + +#endif + + +/** @} end Opaque group */ +/* MARK: - Memory Allocation */ +/***************************************************************************//** + ** @defgroup Memory Memory Allocation + ** + ** Tidy can use a user-provided allocator for all memory allocations. If this + ** allocator is not provided, then a default allocator is used which simply + ** wraps standard C malloc()/free() calls. These wrappers call the panic() + ** function upon any failure. The default panic function prints an out of + ** memory message to **stderr**, and calls `exit(2)`. + ** + ** For applications in which it is unacceptable to abort in the case of memory + ** allocation, then the panic function can be replaced with one which + ** `longjmps()` out of the LibTidy code. For this to clean up completely, you + ** should be careful not to use any Tidy methods that open files as these will + ** not be closed before `panic()` is called. + ** + ** Calling the `xxxWithAllocator()` family (`tidyCreateWithAllocator`, + ** `tidyBufInitWithAllocator`, `tidyBufAllocWithAllocator`) allow setting + ** custom allocators. + ** + ** All parts of the document use the same allocator. Calls that require a + ** user-provided buffer can optionally use a different allocator. + ** + ** For reference in designing a plug-in allocator, most allocations made by + ** LibTidy are less than 100 bytes, corresponding to attribute names and + ** values, etc. + ** + ** There is also an additional class of much larger allocations which are where + ** most of the data from the lexer is stored. It is not currently possible to + ** use a separate allocator for the lexer; this would be a useful extension. + ** + ** In general, approximately 1/3rd of the memory used by LibTidy is freed + ** during the parse, so if memory usage is an issue then an allocator that can + ** reuse this memory is a good idea. + ** + ** **To create your own allocator, do something like the following:** + ** @code{.c} + ** typedef struct _MyAllocator { + ** TidyAllocator base; + ** // ...other custom allocator state... + ** } MyAllocator; + ** + ** void* MyAllocator_alloc(TidyAllocator *base, void *block, size_t nBytes) { + ** MyAllocator *self = (MyAllocator*)base; + ** // ... + ** } + ** // etc. + ** + ** static const TidyAllocatorVtbl MyAllocatorVtbl = { + ** MyAllocator_alloc, + ** MyAllocator_realloc, + ** MyAllocator_free, + ** MyAllocator_panic + ** }; + ** + ** myAllocator allocator; + ** TidyDoc doc; + ** + ** allocator.base.vtbl = &MyAllocatorVtbl; + ** //...initialise allocator specific state... + ** doc = tidyCreateWithAllocator(&allocator); + ** @endcode + ** + ** Although this looks slightly long-winded, the advantage is that to create a + ** custom allocator you simply need to set the vtbl pointer correctly. The vtbl + ** itself can reside in static/global data, and hence does not need to be + ** initialised each time an allocator is created, and furthermore the memory + ** is shared amongst all created allocators. + ** + ** @{ + ******************************************************************************/ + +/* Forward declarations and typedefs. */ +struct _TidyAllocatorVtbl; +struct _TidyAllocator; + +typedef struct _TidyAllocatorVtbl TidyAllocatorVtbl; +typedef struct _TidyAllocator TidyAllocator; + + +/** Tidy's built-in default allocator. */ +struct _TidyAllocator { + const TidyAllocatorVtbl *vtbl; /**< The allocator's function table. */ +}; + + +/** This structure is the function table for an allocator. Note that all + functions in this table must be provided. */ +struct _TidyAllocatorVtbl +{ +/* Doxygen has no idea how to parse these. */ +#ifndef DOXYGEN_SHOULD_SKIP_THIS + void* (TIDY_CALL *alloc)( TidyAllocator *self, size_t nBytes ); + void* (TIDY_CALL *realloc)(TidyAllocator *self, void *block, size_t nBytes ); + void (TIDY_CALL *free)(TidyAllocator *self, void *block); + void (TIDY_CALL *panic)(TidyAllocator *self, ctmbstr msg); +#else + /** Called to allocate a block of nBytes of memory */ + void* *alloc(TidyAllocator *self, /**< The TidyAllocator to use to alloc memory. */ + size_t nBytes /**< The number of bytes to allocate. */ + ); + + /** Called to resize (grow, in general) a block of memory. + Must support being called with `NULL`. */ + void* *realloc(TidyAllocator *self, /**< The TidyAllocator to use to realloc memory. */ + void *block, /**< The pointer to the existing block. */ + size_t nBytes /**< The number of bytes to allocate. */ + ); + + /** Called to free a previously allocated block of memory. + */ + void *free(TidyAllocator *self, /**< The TidyAllocator to use to free memory. */ + void *block /**< The block to free. */ + ); + + /** Called when a panic condition is detected. Must support `block == NULL`. + This function is not called if either alloc() or realloc() fails; it is + up to the allocator to do this. Currently this function can only be + called if an error is detected in the tree integrity via the internal + function CheckNodeIntegrity(). This is a situation that can only arise + in the case of a programming error in LibTidy. You can turn off node + integrity checking by defining the constant `NO_NODE_INTEGRITY_CHECK` + during the build. + **/ + void *panic(TidyAllocator *self, /**< The TidyAllocator to use to panic. */ + ctmbstr msg /**< The panic message. */ + ); +#endif /* Doxygen Fix */ +}; + + +/** Callback for `malloc` replacement */ +typedef void* (TIDY_CALL *TidyMalloc)( size_t len ); + +/** Callback for `realloc` replacement */ +typedef void* (TIDY_CALL *TidyRealloc)( void* buf, size_t len ); + +/** Callback for `free` replacement */ +typedef void (TIDY_CALL *TidyFree)( void* buf ); + +/** Callback for out of memory panic state */ +typedef void (TIDY_CALL *TidyPanic)( ctmbstr mssg ); + + +/** Give Tidy a `malloc()` replacement */ +TIDY_EXPORT Bool TIDY_CALL tidySetMallocCall( TidyMalloc fmalloc ); + +/** Give Tidy a `realloc()` replacement */ +TIDY_EXPORT Bool TIDY_CALL tidySetReallocCall( TidyRealloc frealloc ); + +/** Give Tidy a `free()` replacement */ +TIDY_EXPORT Bool TIDY_CALL tidySetFreeCall( TidyFree ffree ); + +/** Give Tidy an "out of memory" handler */ +TIDY_EXPORT Bool TIDY_CALL tidySetPanicCall( TidyPanic fpanic ); + + +/** @} end Memory group */ +/* MARK: - Basic Operations */ +/***************************************************************************//** + ** @defgroup Basic Basic Operations + ** + ** For an excellent example of how to invoke LibTidy, please consult + ** `console/tidy.c:main()` for in-depth implementation details. A simplified + ** example can be seen on our site: https://www.html-tidy.org/developer/ + ** + ** @{ + ******************************************************************************/ + +/** @name Instantiation and Destruction + ** @{ + */ + +/** The primary creation of a document instance. Instances of a TidyDoc are used + ** throughout the API as a token to represent a particular document. You must + ** create at least one TidyDoc instance to initialize the library and begin + ** interaction with the API. When done using a TidyDoc instance, be sure to + ** `tidyRelease(myTidyDoc);` in order to free related memory. + ** @result Returns a TidyDoc instance. + */ +TIDY_EXPORT TidyDoc TIDY_CALL tidyCreate(void); + +/** Create a document supplying your own, custom TidyAllocator instead of using + ** the built-in default. See the @ref Memory module if you want to create and + ** use your own allocator. + ** @param allocator The allocator to use for creating the document. + ** @result Returns a TidyDoc instance. + */ +TIDY_EXPORT TidyDoc TIDY_CALL tidyCreateWithAllocator(TidyAllocator *allocator); + +/** Free all memory and release the TidyDoc. The TidyDoc can not be used after + ** this call. + ** @param tdoc The TidyDoc to free. + */ +TIDY_EXPORT void TIDY_CALL tidyRelease(TidyDoc tdoc); + + +/** @} + ** @name Host Application Data + ** @{ + */ + + +/** Allows the host application to store a chunk of data with each TidyDoc + ** instance. This can be useful for callbacks, such as saving a reference to + ** `self` within the document. + */ +TIDY_EXPORT void TIDY_CALL tidySetAppData(TidyDoc tdoc, /**< The document in which to store the data. */ + void* appData /**< The pointer to a block of data to store. */ + ); + +/** Returns the data previously stored with `tidySetAppData()`. + ** @param tdoc document where data has been stored. + ** @result The pointer to the data block previously stored. + */ +TIDY_EXPORT void* TIDY_CALL tidyGetAppData(TidyDoc tdoc); + + +/** @} + ** @name LibTidy Version Information + ** @{ + */ + + +/** Get the release date for the current library. + ** @result The string representing the release date. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyReleaseDate(void); + +/** Get the version number for the current library. + ** @result The string representing the version number. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyLibraryVersion(void); + +/** Get the platform for which Tidy was built. + ** @result The string representing the version number. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyPlatform(void); + + +/** @} + ** @name Diagnostics and Repair + ** @{ + */ + + +/** Get status of current document. + ** @param tdoc An instance of a TidyDoc to query. + ** @result Returns the highest of `2` indicating that errors were present in + ** the document, `1` indicating warnings, and `0` in the case of + ** everything being okay. + */ +TIDY_EXPORT int TIDY_CALL tidyStatus( TidyDoc tdoc ); + +/** Gets the version of HTML that was output, as an integer, times 100. For + ** example, HTML5 will return 500; HTML4.0.1 will return 401. + ** @param tdoc An instance of a TidyDoc to query. + ** @result Returns the HTML version number (x100). + */ +TIDY_EXPORT int TIDY_CALL tidyDetectedHtmlVersion( TidyDoc tdoc ); + +/** Indicates whether the output document is or isn't XHTML. + ** @param tdoc An instance of a TidyDoc to query. + ** @result Returns `yes` if the document is an XHTML type. + */ +TIDY_EXPORT Bool TIDY_CALL tidyDetectedXhtml( TidyDoc tdoc ); + +/** Indicates whether or not the input document was XML. If TidyXml tags is + ** true, or there was an XML declaration in the input document, then this + ** function will return yes. + ** @param tdoc An instance of a TidyDoc to query. + ** @result Returns `yes` if the input document was XML. + */ +TIDY_EXPORT Bool TIDY_CALL tidyDetectedGenericXml( TidyDoc tdoc ); + +/** Indicates the number of TidyError messages that were generated. For any + ** value greater than `0`, output is suppressed unless TidyForceOutput is set. + ** @param tdoc An instance of a TidyDoc to query. + ** @result Returns the number of TidyError messages that were generated. + */ +TIDY_EXPORT uint TIDY_CALL tidyErrorCount( TidyDoc tdoc ); + +/** Indicates the number of TidyWarning messages that were generated. + ** @param tdoc An instance of a TidyDoc to query. + ** @result Returns the number of TidyWarning messages that were generated. + */ +TIDY_EXPORT uint TIDY_CALL tidyWarningCount( TidyDoc tdoc ); + +/** Indicates the number of TidyAccess messages that were generated. + ** @param tdoc An instance of a TidyDoc to query. + ** @result Returns the number of TidyAccess messages that were generated. + */ +TIDY_EXPORT uint TIDY_CALL tidyAccessWarningCount( TidyDoc tdoc ); + +/** Indicates the number of configuration error messages that were generated. + ** @param tdoc An instance of a TidyDoc to query. + ** @result Returns the number of configuration error messages that were + ** generated. + */ +TIDY_EXPORT uint TIDY_CALL tidyConfigErrorCount( TidyDoc tdoc ); + +/** Write more complete information about errors to current error sink. + ** @param tdoc An instance of a TidyDoc to query. + */ +TIDY_EXPORT void TIDY_CALL tidyErrorSummary( TidyDoc tdoc ); + +/** Write more general information about markup to current error sink. + ** @param tdoc An instance of a TidyDoc to query. + */ +TIDY_EXPORT void TIDY_CALL tidyGeneralInfo( TidyDoc tdoc ); + + +/** @} + ** @name Configuration, File, and Encoding Operations + ** @{ + */ + + +/** Load an ASCII Tidy configuration file and set the configuration per its + ** contents. Reports config option errors, which can be filtered. + ** @result Returns 0 upon success, or any other value if there was an option error. + */ +TIDY_EXPORT int TIDY_CALL tidyLoadConfig(TidyDoc tdoc, /**< The TidyDoc to which to apply the configuration. */ + ctmbstr configFile /**< The complete path to the file to load. */ + ); + +/** Load a Tidy configuration file with the specified character encoding, and + ** set the configuration per its contents. Reports config option errors, which can be filtered. + ** @result Returns 0 upon success, or any other value if there was an option error. + */ +TIDY_EXPORT int TIDY_CALL tidyLoadConfigEnc(TidyDoc tdoc, /**< The TidyDoc to which to apply the configuration. */ + ctmbstr configFile, /**< The complete path to the file to load. */ + ctmbstr charenc /**< The encoding to use. See the _enc2iana struct for valid values. */ + ); + +/** Determine whether or not a particular file exists. On Unix systems, the use + ** of the tilde to represent the user's home directory is supported. + ** @result Returns `yes` or `no`, indicating whether or not the file exists. + */ +TIDY_EXPORT Bool TIDY_CALL tidyFileExists(TidyDoc tdoc, /**< The TidyDoc on whose behalf you are checking. */ + ctmbstr filename /**< The path to the file whose existence you wish to check. */ + ); + + +/** Set the input/output character encoding for parsing markup. Valid values + ** include `ascii`, `latin1`, `raw`, `utf8`, `iso2022`, `mac`, `win1252`, + ** `utf16le`, `utf16be`, `utf16`, `big5`, and `shiftjis`. These values are not + ** case sensitive. + ** @note This is the same as using TidySetInCharEncoding() and + ** TidySetOutCharEncoding() to set the same value. + ** @result Returns 0 upon success, or a system standard error number `EINVAL`. + */ +TIDY_EXPORT int TIDY_CALL tidySetCharEncoding(TidyDoc tdoc, /**< The TidyDoc for which you are setting the encoding. */ + ctmbstr encnam /**< The encoding name as described above. */ + ); + +/** Set the input encoding for parsing markup. Valid values include `ascii`, + ** `latin1`, `raw`, `utf8`, `iso2022`, `mac`, `win1252`, `utf16le`, `utf16be`, + ** `utf16`, `big5`, and `shiftjis`. These values are not case sensitive. + ** @result Returns 0 upon success, or a system standard error number `EINVAL`. + */ +TIDY_EXPORT int TIDY_CALL tidySetInCharEncoding(TidyDoc tdoc, /**< The TidyDoc for which you are setting the encoding. */ + ctmbstr encnam /**< The encoding name as described above. */ + ); + +/** Set the input encoding for writing markup. Valid values include `ascii`, + ** `latin1`, `raw`, `utf8`, `iso2022`, `mac`, `win1252`, `utf16le`, `utf16be`, + ** `utf16`, `big5`, and `shiftjis`. These values are not case sensitive. + ** @result Returns 0 upon success, or a system standard error number `EINVAL`. + */ +TIDY_EXPORT int TIDY_CALL tidySetOutCharEncoding(TidyDoc tdoc, /**< The TidyDoc for which you are setting the encoding. */ + ctmbstr encnam /**< The encoding name as described above. */ + ); + + +/** @} */ +/** @} end Basic group */ +/* MARK: - Configuration Options */ +/***************************************************************************//** + ** @defgroup Configuration Configuration Options + ** + ** Functions for getting and setting Tidy configuration options. + ** + ** @note In general, you should expect that options you set should stay set. + ** This isn't always the case, though, because Tidy will adjust options + ** for internal use during the lexing, parsing, cleaning, and printing + ** phases. If you require access to user configuration values at any + ** time after the tidyParseXXX() process, make sure to keep your own + ** copy, or use tidyOptResetToSnapshot() when you no longer need to + ** use any other tidy functions. + ** @{ + ******************************************************************************/ + +/** @name Option Callback Functions + ** @{ + */ + +/** This typedef represents the required signature for your provided callback + ** function should you wish to register one with tidySetOptionCallback(). + ** Your callback function will be provided with the following parameters. + ** Note that this is deprecated and you should instead migrate to + ** tidySetConfigCallback(). + ** @param option The option name that was provided. + ** @param value The option value that was provided + ** @return Your callback function will return `yes` if it handles the provided + ** option, or `no` if it does not. In the latter case, Tidy will issue + ** an unknown configuration option error. + */ +typedef Bool (TIDY_CALL *TidyOptCallback)(ctmbstr option, ctmbstr value); + +/** Applications using TidyLib may want to augment command-line and + ** configuration file options. Setting this callback allows a LibTidy + ** application developer to examine command-line and configuration file options + ** after LibTidy has examined them and failed to recognize them. + ** Note that this is deprecated and you should instead migrate to + ** tidySetConfigCallback(). + ** @result Returns `yes` upon success. + */ +TIDY_EXPORT Bool TIDY_CALL tidySetOptionCallback(TidyDoc tdoc, /**< The document to apply the callback to. */ + TidyOptCallback pOptCallback /**< The name of a function of type TidyOptCallback() to serve as your callback. */ + ); + +/** This typedef represents the required signature for your provided callback + ** function should you wish to register one with tidySetConfigCallback(). + ** Your callback function will be provided with the following parameters. + ** @param tdoc The document instance for which the callback was invoked. + ** @param option The option name that was provided. + ** @param value The option value that was provided + ** @return Your callback function will return `yes` if it handles the provided + ** option, or `no` if it does not. In the latter case, Tidy will issue + ** an unknown configuration option error. + */ +typedef Bool (TIDY_CALL *TidyConfigCallback)(TidyDoc tdoc, ctmbstr option, ctmbstr value); + +/** Applications using TidyLib may want to augment command-line and + ** configuration file options. Setting this callback allows a LibTidy + ** application developer to examine command-line and configuration file options + ** after LibTidy has examined them and failed to recognize them. + ** @result Returns `yes` upon success. + */ +TIDY_EXPORT Bool TIDY_CALL tidySetConfigCallback(TidyDoc tdoc, /**< The document to apply the callback to. */ + TidyConfigCallback pConfigCallback /**< The name of a function of type TidyConfigCallback() to serve as your callback. */ + ); + + +/** This typedef represents the required signature for your provided callback + ** function should you wish to register one with tidySetConfigChangeCallback(). + ** Your callback function will be provided with the following parameters. + ** @param tdoc The document instance for which the callback was invoked. + ** @param option The option that will be changed. + */ +typedef void (TIDY_CALL *TidyConfigChangeCallback)(TidyDoc tdoc, TidyOption option); + +/** Applications using TidyLib may want to be informed when changes to options + ** are made. Temporary changes made internally by Tidy are not reported, but + ** permanent changes made by Tidy (such as indent-spaces or output-encoding) + ** will be reported. + ** @note This callback is not currently implemented. + ** @result Returns `yes` upon success. + */ +TIDY_EXPORT Bool TIDY_CALL tidySetConfigChangeCallback(TidyDoc tdoc, /**< The document to apply the callback to. */ + TidyConfigChangeCallback pCallback /**< The name of a function of type TidyConfigChangeCallback() to serve as your callback. */ + ); + + +/** @} + ** @name Option ID Discovery + ** @{ + */ + +/** Get ID of given Option + ** @param opt An instance of a TidyOption to query. + ** @result The TidyOptionId of the given option. + */ +TIDY_EXPORT TidyOptionId TIDY_CALL tidyOptGetId( TidyOption opt ); + +/** Returns the TidyOptionId (enum value) by providing the name of a Tidy + ** configuration option. + ** @param optnam The name of the option ID to retrieve. + ** @result The TidyOptionId of the given `optname`. + */ +TIDY_EXPORT TidyOptionId TIDY_CALL tidyOptGetIdForName(ctmbstr optnam); + +/** @} + ** @name Getting Instances of Tidy Options + ** @{ + */ + +/** Initiates an iterator for a list of TidyOption instances, which allows you + ** to iterate through all of the available options. In order to iterate through + ** the available options, initiate the iterator with this function, and then + ** use tidyGetNextOption() to retrieve the first and subsequent options. For + ** example: + ** @code{.c} + ** TidyIterator itOpt = tidyGetOptionList( tdoc ); + ** while ( itOpt ) { + ** TidyOption opt = tidyGetNextOption( tdoc, &itOpt ); + ** // Use other API to query or set set option values + ** } + ** @endcode + ** @param tdoc An instance of a TidyDoc to query. + ** @result Returns a TidyIterator, which is a token used to represent the + ** current position in a list within LibTidy. + */ +TIDY_EXPORT TidyIterator TIDY_CALL tidyGetOptionList( TidyDoc tdoc ); + +/** Given a valid TidyIterator initiated with tidyGetOptionList(), returns + ** the instance of the next TidyOption. + ** @note This function will return internal-only option types including + ** `TidyInternalCategory`; you should *never* use these. Always ensure + ** that you use `tidyOptGetCategory()` before assuming that an option + ** is okay to use in your application. + ** @result An instance of TidyOption. + */ +TIDY_EXPORT TidyOption TIDY_CALL tidyGetNextOption(TidyDoc tdoc, /**< The document for which you are retrieving options. */ + TidyIterator* pos /**< The TidyIterator (initiated with tidyGetOptionList()) token. */ + ); + +/** Retrieves an instance of TidyOption given a valid TidyOptionId. + ** @result An instance of TidyOption matching the provided TidyOptionId. + */ +TIDY_EXPORT TidyOption TIDY_CALL tidyGetOption(TidyDoc tdoc, /**< The document for which you are retrieving the option. */ + TidyOptionId optId /**< The TidyOptionId to retrieve. */ + ); + +/** Returns an instance of TidyOption by providing the name of a Tidy + ** configuration option. + ** @result The TidyOption of the given `optname`. + */ +TIDY_EXPORT TidyOption TIDY_CALL tidyGetOptionByName(TidyDoc tdoc, /**< The document for which you are retrieving the option. */ + ctmbstr optnam /**< The name of the Tidy configuration option. */ + ); + +/** @} + ** @name Information About Options + ** @{ + */ + +/** Get name of given Option + ** @param opt An instance of a TidyOption to query. + ** @result The name of the given option. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyOptGetName( TidyOption opt ); + +/** Get datatype of given Option + ** @param opt An instance of a TidyOption to query. + ** @result The TidyOptionType of the given option. + */ +TIDY_EXPORT TidyOptionType TIDY_CALL tidyOptGetType( TidyOption opt ); + +/** Indicates that an option takes a list of items. + ** @param opt An instance of a TidyOption to query. + ** @result A bool indicating whether or not the option accepts a list. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptionIsList( TidyOption opt ); + +/** Is Option read-only? Some options (mainly internal use only options) are + ** read-only. + ** @deprecated This is no longer a valid test for the public API; instead + ** you should test an option's availability using `tidyOptGetCategory()` + ** against `TidyInternalCategory`. This API will be removed! + ** @param opt An instance of a TidyOption to query. + ** @result Returns `yes` or `no` depending on whether or not the specified + ** option is read-only. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptIsReadOnly( TidyOption opt ); + +/** Get category of given Option + ** @param opt An instance of a TidyOption to query. + ** @result The TidyConfigCategory of the specified option. + */ +TIDY_EXPORT TidyConfigCategory TIDY_CALL tidyOptGetCategory( TidyOption opt ); + +/** Get default value of given Option as a string + ** @param opt An instance of a TidyOption to query. + ** @result A string indicating the default value of the specified option. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyOptGetDefault( TidyOption opt ); + +/** Get default value of given Option as an unsigned integer + ** @param opt An instance of a TidyOption to query. + ** @result An unsigned integer indicating the default value of the specified + ** option. + */ +TIDY_EXPORT ulong TIDY_CALL tidyOptGetDefaultInt( TidyOption opt ); + +/** Get default value of given Option as a Boolean value + ** @param opt An instance of a TidyOption to query. + ** @result A boolean indicating the default value of the specified option. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptGetDefaultBool( TidyOption opt ); + +/** Initiates an iterator for a list of TidyOption pick-list values, which + ** allows you iterate through all of the available option values. In order to + ** iterate through the available values, initiate the iterator with this + ** function, and then use tidyOptGetNextPick() to retrieve the first and + ** subsequent option values. For example: + ** @code{.c} + ** TidyIterator itOpt = tidyOptGetPickList( opt ); + ** while ( itOpt ) { + ** printf("%s", tidyOptGetNextPick( opt, &itOpt )); + ** } + ** @endcode + ** @param opt An instance of a TidyOption to query. + ** @result Returns a TidyIterator, which is a token used to represent the + ** current position in a list within LibTidy. + */ +TIDY_EXPORT TidyIterator TIDY_CALL tidyOptGetPickList( TidyOption opt ); + +/** Given a valid TidyIterator initiated with tidyOptGetPickList(), returns a + ** string representing a possible option value. + ** @result A string containing the next pick-list option value. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyOptGetNextPick(TidyOption opt, /**< An instance of a TidyOption to query. */ + TidyIterator* pos /**< The TidyIterator (initiated with tidyOptGetPickList()) token. */ + ); + +/** @} + ** @name Option Value Functions + ** @{ + */ + +/** Get the current value of the option ID for the given document. + ** @remark The optId *must* have a @ref TidyOptionType of @ref TidyString! + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyOptGetValue(TidyDoc tdoc, /**< The tidy document whose option value you wish to check. */ + TidyOptionId optId /**< The option ID whose value you wish to check. */ + ); + +/** Set the option value as a string. + ** @remark The optId *must* have a @ref TidyOptionType of @ref TidyString! + ** @result Returns a bool indicating success or failure. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptSetValue(TidyDoc tdoc, /**< The tidy document for which to set the value. */ + TidyOptionId optId, /**< The option ID of the value to set. */ + ctmbstr val /**< The string value to set. */ + ); + +/** Set named option value as a string, regardless of the @ref TidyOptionType. + ** @remark This is good setter if you are unsure of the type. + ** @result Returns a bool indicating success or failure. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptParseValue(TidyDoc tdoc, /**< The tidy document for which to set the value. */ + ctmbstr optnam, /**< The name of the option to set; this is the string value from the UI, e.g., `error-file`. */ + ctmbstr val /**< The value to set, as a string. */ + ); + +/** Get current option value as an integer. + ** @result Returns the integer value of the specified option. + */ +TIDY_EXPORT ulong TIDY_CALL tidyOptGetInt(TidyDoc tdoc, /**< The tidy document for which to get the value. */ + TidyOptionId optId /**< The option ID to get. */ + ); + +/** Set option value as an integer. + ** @result Returns a bool indicating success or failure. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptSetInt(TidyDoc tdoc, /**< The tidy document for which to set the value. */ + TidyOptionId optId, /**< The option ID to set. */ + ulong val /**< The value to set. */ + ); + +/** Get current option value as a Boolean flag. + ** @result Returns a bool indicating the value. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptGetBool(TidyDoc tdoc, /**< The tidy document for which to get the value. */ + TidyOptionId optId /**< The option ID to get. */ + ); + +/** Set option value as a Boolean flag. + ** @result Returns a bool indicating success or failure. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptSetBool(TidyDoc tdoc, /**< The tidy document for which to set the value. */ + TidyOptionId optId, /**< The option ID to set. */ + Bool val /**< The value to set. */ + ); + +/** Reset option to default value by ID. + ** @result Returns a bool indicating success or failure. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptResetToDefault(TidyDoc tdoc, /**< The tidy document for which to reset the value. */ + TidyOptionId opt /**< The option ID to reset. */ + ); + +/** Reset all options to their default values. + ** @param tdoc The tidy document for which to reset all values. + ** @result Returns a bool indicating success or failure. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptResetAllToDefault( TidyDoc tdoc ); + +/** Take a snapshot of current config settings. These settings are stored + ** within the tidy document. Note, however, that snapshots do not reliably + ** survive the tidyParseXXX() process, as Tidy uses the snapshot mechanism + ** in order to store the current configuration right at the beginning of the + ** parsing process. + ** @param tdoc The tidy document for which to take a snapshot. + ** @result Returns a bool indicating success or failure. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptSnapshot( TidyDoc tdoc ); + +/** Apply a snapshot of config settings to a document. + ** @param tdoc The tidy document for which to apply a snapshot. + ** @result Returns a bool indicating success or failure. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptResetToSnapshot( TidyDoc tdoc ); + +/** Any settings different than default? + ** @param tdoc The tidy document to check. + ** @result Returns a bool indicating whether or not a difference exists. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptDiffThanDefault( TidyDoc tdoc ); + +/** Any settings different than snapshot? + ** @param tdoc The tidy document to check. + ** @result Returns a bool indicating whether or not a difference exists. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptDiffThanSnapshot( TidyDoc tdoc ); + +/** Copy current configuration settings from one document to another. Note + ** that the destination document's existing settings will be stored as that + ** document's snapshot prior to having its option values overwritten by the + ** source document's settings. + ** @result Returns a bool indicating success or failure. + */ +TIDY_EXPORT Bool TIDY_CALL tidyOptCopyConfig(TidyDoc tdocTo, /**< The destination tidy document. */ + TidyDoc tdocFrom /**< The source tidy document. */ + ); + +/** Get character encoding name. Used with @ref TidyCharEncoding, + ** @ref TidyOutCharEncoding, and @ref TidyInCharEncoding. + ** @result The encoding name as a string for the specified option. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyOptGetEncName(TidyDoc tdoc, /**< The tidy document to query. */ + TidyOptionId optId /**< The option ID whose value to check. */ + ); + +/** Get the current pick list value for the option ID, which can be useful for + ** enum types. + ** @result Returns a string indicating the current value of the specified + ** option. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyOptGetCurrPick(TidyDoc tdoc, /**< The tidy document to query. */ + TidyOptionId optId /**< The option ID whose value to check. */ + ); + +/** Initiates an iterator for a list of user-declared tags, including autonomous + ** custom tags detected in the document if @ref TidyUseCustomTags is not set to + ** **no**. This iterator allows you to iterate through all of the custom tags. + ** In order to iterate through the tags, initiate the iterator with this + ** function, and then use tidyOptGetNextDeclTag() to retrieve the first and + ** subsequent tags. For example: + ** @code{.c} + ** TidyIterator itTag = tidyOptGetDeclTagList( tdoc ); + ** while ( itTag ) { + ** printf("%s", tidyOptGetNextDeclTag( tdoc, TidyBlockTags, &itTag )); + ** } + ** @endcode + ** @param tdoc An instance of a TidyDoc to query. + ** @result Returns a TidyIterator, which is a token used to represent the + ** current position in a list within LibTidy. + */ +TIDY_EXPORT TidyIterator TIDY_CALL tidyOptGetDeclTagList( TidyDoc tdoc ); + +/** Given a valid TidyIterator initiated with tidyOptGetDeclTagList(), returns a + ** string representing a user-declared or autonomous custom tag. + ** @remark Specifying optId limits the scope of the tags to one of + ** @ref TidyInlineTags, @ref TidyBlockTags, @ref TidyEmptyTags, or + ** @ref TidyPreTags. Note that autonomous custom tags (if used) are + ** added to one of these option types, depending on the value of + ** @ref TidyUseCustomTags. + ** @result A string containing the next tag. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyOptGetNextDeclTag(TidyDoc tdoc, /**< The tidy document to query. */ + TidyOptionId optId, /**< The option ID matching the type of tag to retrieve. */ + TidyIterator* iter /**< The TidyIterator (initiated with tidyOptGetDeclTagList()) token. */ + ); + +/** Initiates an iterator for a list of priority attributes. This iterator + ** allows you to iterate through all of the priority attributes defined with + ** the `priority-attributes` configuration option. In order to iterate through + ** the attributes, initiate the iterator with this function, and then use + ** tidyOptGetNextPriorityAttr() to retrieve the first and subsequent attributes. + ** For example: + ** @code{.c} + ** TidyIterator itAttr = tidyOptGetPriorityAttrList( tdoc ); + ** while ( itAttr ) { + ** printf("%s", tidyOptGetNextPriorityAttr( tdoc, &itAttr )); + ** } + ** @endcode + ** @param tdoc An instance of a TidyDoc to query. + ** @result Returns a TidyIterator, which is a token used to represent the + ** current position in a list within LibTidy. + */ +TIDY_EXPORT TidyIterator TIDY_CALL tidyOptGetPriorityAttrList( TidyDoc tdoc ); + +/** Given a valid TidyIterator initiated with tidyOptGetPriorityAttrList(), + ** returns a string representing a priority attribute. + ** @result A string containing the next tag. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyOptGetNextPriorityAttr(TidyDoc tdoc, /**< The tidy document to query. */ + TidyIterator* iter /**< The TidyIterator (initiated with tidyOptGetPriorityAttrList()) token. */ + ); + +/** Initiates an iterator for a list of muted messages. This iterator allows + ** you to iterate through all of the priority attributes defined with the + ** `mute` configuration option. In order to iterate through the list, initiate + ** with this function, and then use tidyOptGetNextMutedMessage() to retrieve + ** the first and subsequent attributes. + ** For example: + ** @code{.c} + ** TidyIterator itAttr = tidyOptGetMutedMessageList( tdoc ); + ** while ( itAttr ) { + ** printf("%s", tidyOptGetNextMutedMessage( tdoc, &itAttr )); + ** } + ** @endcode + ** @param tdoc An instance of a TidyDoc to query. + ** @result Returns a TidyIterator, which is a token used to represent the + ** current position in a list within LibTidy. + */ +TIDY_EXPORT TidyIterator TIDY_CALL tidyOptGetMutedMessageList( TidyDoc tdoc ); + +/** Given a valid TidyIterator initiated with tidyOptGetMutedMessageList(), + ** returns a string representing a muted message. + ** @result A string containing the next tag. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyOptGetNextMutedMessage(TidyDoc tdoc, /**< The tidy document to query. */ + TidyIterator* iter /**< The TidyIterator (initiated with tidyOptGetMutedMessageList()) token. */ + ); + +/** @} + ** @name Option Documentation + ** @{ + */ + +/** Get the description of the specified option. + ** @result Returns a string containing a description of the given option. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyOptGetDoc(TidyDoc tdoc, /**< The tidy document to query. */ + TidyOption opt /**< The option ID of the option. */ + ); + +/** Initiates an iterator for a list of options related to a given option. This + ** iterator allows you to iterate through all of the related options, if any. + ** In order to iterate through the options, initiate the iterator with this + ** function, and then use tidyOptGetNextDocLinks() to retrieve the first and + ** subsequent options. For example: + ** @code{.c} + ** TidyIterator itOpt = tidyOptGetDocLinksList( tdoc, TidyJoinStyles ); + ** while ( itOpt ) { + ** TidyOption my_option = tidyOptGetNextDocLinks( tdoc, &itOpt ); + ** // do something with my_option + ** } + ** @endcode + ** @result Returns a TidyIterator, which is a token used to represent the + ** current position in a list within LibTidy. + */ +TIDY_EXPORT TidyIterator TIDY_CALL tidyOptGetDocLinksList(TidyDoc tdoc, /**< The tidy document to query. */ + TidyOption opt /**< The option whose related options you wish to find. */ + ); + +/** Given a valid TidyIterator initiated with tidyOptGetDocLinksList(), returns + ** a TidyOption instance. + ** @result Returns in instance of TidyOption. + */ +TIDY_EXPORT TidyOption TIDY_CALL tidyOptGetNextDocLinks(TidyDoc tdoc, /**< The tidy document to query. */ + TidyIterator* pos /**< The TidyIterator (initiated with tidyOptGetDocLinksList()) token. */ + ); + +/** @} */ +/** @} end Configuration group */ +/* MARK: - I/O and Messages */ +/***************************************************************************//** + ** @defgroup IO I/O and Messages + ** + ** Tidy provides flexible I/O. By default, Tidy will define, create and use + ** instances of input and output handlers for standard C buffered I/O (i.e., + ** `FILE* stdin`, `FILE* stdout`, and `FILE* stderr` for content input, + ** content output and diagnostic output, respectively. A `FILE* cfgFile` + ** input handler will be used for config files. Command line options will + ** just be set directly. + ** + ** @{ + ******************************************************************************/ + +/** @name Forward declarations and typedefs. + ** @{ + */ + +TIDY_STRUCT struct _TidyBuffer; +typedef struct _TidyBuffer TidyBuffer; + +/** @} + ** @name Input Source + ** If you wish to write to your own input sources, then these types, structs, + ** and functions will allow them to work seamlessly with Tidy. + ** @{ + */ + +/** End of input "character" */ +#define EndOfStream (~0u) + +/** Input Callback: get next byte of input */ +typedef int (TIDY_CALL *TidyGetByteFunc)( void* sourceData ); + +/** Input Callback: unget a byte of input */ +typedef void (TIDY_CALL *TidyUngetByteFunc)( void* sourceData, byte bt ); + +/** Input Callback: is end of input? */ +typedef Bool (TIDY_CALL *TidyEOFFunc)( void* sourceData ); + +/** This type defines an input source capable of delivering raw bytes of input. + */ +TIDY_STRUCT +typedef struct _TidyInputSource +{ + void* sourceData; /**< Input context. Passed to callbacks. */ + + TidyGetByteFunc getByte; /**< Pointer to "get byte" callback. */ + TidyUngetByteFunc ungetByte; /**< Pointer to "unget" callback. */ + TidyEOFFunc eof; /**< Pointer to "eof" callback. */ +} TidyInputSource; + +/** Facilitates user defined source by providing an entry point to marshal + ** pointers-to-functions. This is needed by .NET, and possibly other language + ** bindings. + ** @result Returns a bool indicating success or failure. + */ +TIDY_EXPORT Bool TIDY_CALL tidyInitSource(TidyInputSource* source, /**< The source to populate with data. */ + void* srcData, /**< The input context. */ + TidyGetByteFunc gbFunc, /**< Pointer to the "get byte" callback. */ + TidyUngetByteFunc ugbFunc, /**< Pointer to the "unget" callback. */ + TidyEOFFunc endFunc /**< Pointer to the "eof" callback. */ + ); + +/** Helper: get next byte from input source. + ** @param source A pointer to your input source. + ** @result Returns a byte as an unsigned integer. + */ +TIDY_EXPORT uint TIDY_CALL tidyGetByte( TidyInputSource* source ); + +/** Helper: unget byte back to input source. */ +TIDY_EXPORT void TIDY_CALL tidyUngetByte(TidyInputSource* source, /**< The input source. */ + uint byteValue /**< The byte to push back. */ + ); + +/** Helper: check if input source at end. + ** @param source The input source. + ** @result Returns a bool indicating whether or not the source is at EOF. + */ +TIDY_EXPORT Bool TIDY_CALL tidyIsEOF( TidyInputSource* source ); + +/** @} + ** @name Output Sink + ** @{ + */ + +/** Output callback: send a byte to output */ +typedef void (TIDY_CALL *TidyPutByteFunc)( void* sinkData, byte bt ); + +/** This type defines an output destination capable of accepting raw bytes + ** of output + */ +TIDY_STRUCT +typedef struct _TidyOutputSink +{ + void* sinkData; /**< Output context. Passed to callbacks. */ + + TidyPutByteFunc putByte; /**< Pointer to "put byte" callback */ +} TidyOutputSink; + +/** Facilitates user defined sinks by providing an entry point to marshal + ** pointers-to-functions. This is needed by .NET, and possibly other language + ** bindings. + ** @result Returns a bool indicating success or failure. + */ +TIDY_EXPORT Bool TIDY_CALL tidyInitSink(TidyOutputSink* sink, /**< The sink to populate with data. */ + void* snkData, /**< The output context. */ + TidyPutByteFunc pbFunc /**< Pointer to the "put byte" callback function. */ + ); + +/** Helper: send a byte to output. */ +TIDY_EXPORT void TIDY_CALL tidyPutByte(TidyOutputSink* sink, /**< The output sink to send a byte. */ + uint byteValue /**< The byte to be sent. */ + ); + +/** @} + ** @name Emacs-compatible reporting support. + ** If you work with Emacs and prefer Tidy's report output to be in a form + ** that is easy for Emacs to parse, then these functions may be valuable. + ** @{ + */ + +/** Set the file path to use for reports when `TidyEmacs` is being used. This + ** function provides a proper interface for using the hidden, internal-only + ** `TidyEmacsFile` configuration option. + */ +TIDY_EXPORT void TIDY_CALL tidySetEmacsFile(TidyDoc tdoc, /**< The tidy document for which you are setting the filePath. */ + ctmbstr filePath /**< The path of the document that should be reported. */ + ); + +/** Get the file path to use for reports when `TidyEmacs` is being used. This + ** function provides a proper interface for using the hidden, internal-only + ** `TidyEmacsFile` configuration option. + ** @param tdoc The tidy document for which you want to fetch the file path. + ** @result Returns a string indicating the file path. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetEmacsFile( TidyDoc tdoc ); + +/** @} + ** @name Error Sink + ** Send Tidy's output to any of several destinations with these functions. + ** @{ + */ + +/** Set error sink to named file. + ** @result Returns a file handle. + */ +TIDY_EXPORT FILE* TIDY_CALL tidySetErrorFile(TidyDoc tdoc, /**< The document to set. */ + ctmbstr errfilnam /**< The file path to send output. */ + ); + +/** Set error sink to given buffer. + ** @result Returns 0 upon success or a standard error number. + */ +TIDY_EXPORT int TIDY_CALL tidySetErrorBuffer(TidyDoc tdoc, /**< The document to set. */ + TidyBuffer* errbuf /**< The TidyBuffer to collect output. */ + ); + +/** Set error sink to given generic sink. + ** @result Returns 0 upon success or a standard error number. + */ +TIDY_EXPORT int TIDY_CALL tidySetErrorSink(TidyDoc tdoc, /**< The document to set. */ + TidyOutputSink* sink /**< The TidyOutputSink to collect output. */ + ); + +/** @} + ** @name Error and Message Callbacks - TidyReportFilter + ** A simple callback to filter or collect messages by diagnostic level, + ** for example, TidyInfo, TidyWarning, etc. Its name reflects its original + ** purpose as a filter, by which your application can inform LibTidy whether + ** or not to output a particular report. + ** + ** @{ + */ + +/** This typedef represents the required signature for your provided callback + ** function should you wish to register one with tidySetReportFilter(). + ** Your callback function will be provided with the following parameters. + ** @param tdoc Indicates the tidy document the message comes from. + ** @param lvl Specifies the TidyReportLevel of the message. + ** @param line Indicates the line number in the source document the message applies to. + ** @param col Indicates the column in the source document the message applies to. + ** @param mssg Specifies the complete message as Tidy would emit it. + ** @return Your callback function will return `yes` if Tidy should include the + ** report in its own output sink, or `no` if Tidy should suppress it. + */ +typedef Bool (TIDY_CALL *TidyReportFilter)( TidyDoc tdoc, TidyReportLevel lvl, uint line, uint col, ctmbstr mssg ); + +/** This function informs Tidy to use the specified callback to send reports. */ +TIDY_EXPORT Bool TIDY_CALL tidySetReportFilter(TidyDoc tdoc, /**< The tidy document for which the callback applies. */ + TidyReportFilter filtCallback /**< A pointer to your callback function of type TidyReportFilter. */ + ); + +/** @} + ** @name Error and Message Callbacks - TidyReportCallback + ** A simple callback to filter or collect messages reported by Tidy. + ** Unlike TidyReportFilter, more data are provided (including a `va_list`), + ** making this callback suitable for applications that provide more + ** sophisticated handling of reports. + ** @remark The use of a `va_list` may preclude using this callback from + ** non-C-like languages, which is uncharacteristic of Tidy. For more + ** flexibility, consider using TidyMessageCallback instead. + ** @note This callback was previously `TidyMessageFilter3` in older versions + ** of LibTidy. + ** @{ + */ + +/** This typedef represents the required signature for your provided callback + ** function should you wish to register one with tidySetReportCallback(). + ** Your callback function will be provided with the following parameters. + ** @param tdoc Indicates the tidy document the message comes from. + ** @param lvl Specifies the TidyReportLevel of the message. + ** @param line Indicates the line number in the source document the message applies to. + ** @param col Indicates the column in the source document the message applies to. + ** @param code Specifies the message code representing the message. Note that + ** this code is a string value that the API promises to hold constant, + ** as opposed to an enum value that can change at any time. Although + ** this is intended so that you can look up your own application's + ** strings, you can retrieve Tidy's format string with this code by + ** using tidyErrorCodeFromKey() and then the tidyLocalizedString() + ** family of functions. + ** @param args Is a `va_list` of arguments used to fill Tidy's message format string. + ** @return Your callback function will return `yes` if Tidy should include the + ** report in its own output sink, or `no` if Tidy should suppress it. + */ +typedef Bool (TIDY_CALL *TidyReportCallback)( TidyDoc tdoc, TidyReportLevel lvl, + uint line, uint col, ctmbstr code, va_list args ); + +/** This function informs Tidy to use the specified callback to send reports. */ +TIDY_EXPORT Bool TIDY_CALL tidySetReportCallback(TidyDoc tdoc, /**< The tidy document for which the callback applies. */ + TidyReportCallback filtCallback /**< A pointer to your callback function of type TidyReportCallback. */ + ); + +/** @} + ** @name Error and Message Callbacks - TidyMessageCallback + ** A sophisticated and extensible callback to filter or collect messages + ** reported by Tidy. It returns only an opaque type `TidyMessage` for every + ** report and dialogue message, and this message can be queried with the +** TidyMessageCallback API, below. Note that unlike the older filters, this +** callback exposes *all* output that LibTidy emits (excluding the console +** application, which is a client of LibTidy). +*/ + +/** This typedef represents the required signature for your provided callback + ** function should you wish to register one with tidySetMessageCallback(). + ** Your callback function will be provided with the following parameters. + ** @param tmessage An opaque type used as a token against which other API + ** calls can be made. + ** @return Your callback function will return `yes` if Tidy should include the + ** report in its own output sink, or `no` if Tidy should suppress it. + */ +typedef Bool (TIDY_CALL *TidyMessageCallback)( TidyMessage tmessage ); + +/** This function informs Tidy to use the specified callback to send reports. */ +TIDY_EXPORT Bool TIDY_CALL tidySetMessageCallback(TidyDoc tdoc, /**< The tidy document for which the callback applies. */ + TidyMessageCallback filtCallback /**< A pointer to your callback function of type TidyMessageCallback. */ + ); + +/** @name TidyMessageCallback API + ** When using `TidyMessageCallback` you will be supplied with a TidyMessage + ** object, which is used as a token to be interrogated with the following + ** API before the callback returns. + ** @remark Upon returning from the callback, this object is destroyed so do + ** not attempt to copy it, or keep it around, or use it in any way. + ** + ** @{ + */ + +/** Get the tidy document this message comes from. + ** @param tmessage Specify the message that you are querying. + ** @result Returns the TidyDoc that generated the message. + */ +TIDY_EXPORT TidyDoc TIDY_CALL tidyGetMessageDoc( TidyMessage tmessage ); + +/** Get the message code. + ** @param tmessage Specify the message that you are querying. + ** @result Returns a code representing the message. This code can be used + ** directly with the localized strings API; however we never make + ** any guarantees about the value of these codes. For code stability + ** don't store this value in your own application. Instead use the + ** enum field or use the message key string value. + */ +TIDY_EXPORT uint TIDY_CALL tidyGetMessageCode( TidyMessage tmessage ); + +/** Get the message key string. + ** @param tmessage Specify the message that you are querying. + ** @result Returns a string representing the message. This string is intended + ** to be stable by the LibTidy API, and is suitable for use as a key + ** in your own applications. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessageKey( TidyMessage tmessage ); + +/** Get the line number the message applies to. + ** @param tmessage Specify the message that you are querying. + ** @result Returns the line number, if any, that generated the message. + */ +TIDY_EXPORT int TIDY_CALL tidyGetMessageLine( TidyMessage tmessage ); + +/** Get the column the message applies to. + ** @param tmessage Specify the message that you are querying. + ** @result Returns the column number, if any, that generated the message. + */ +TIDY_EXPORT int TIDY_CALL tidyGetMessageColumn( TidyMessage tmessage ); + +/** Get the TidyReportLevel of the message. + ** @param tmessage Specify the message that you are querying. + ** @result Returns a TidyReportLevel indicating the severity or status of the + ** message. + */ +TIDY_EXPORT TidyReportLevel TIDY_CALL tidyGetMessageLevel( TidyMessage tmessage ); + + +/** Get the muted status of the message, that is, whether or not the + ** current configuration indicated that this message should be muted. + ** @param tmessage Specify the message that you are querying. + ** @result Returns a Bool indicating that the config indicates muting this + ** message. + */ +TIDY_EXPORT Bool TIDY_CALL tidyGetMessageIsMuted( TidyMessage tmessage ); + +/** Get the default format string, which is the format string for the message + ** in Tidy's default localization (en_us). + ** @param tmessage Specify the message that you are querying. + ** @result Returns the default localization format string of the message. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessageFormatDefault( TidyMessage tmessage ); + +/** Get the localized format string. If a localized version of the format string + ** doesn't exist, then the default version will be returned. + ** @param tmessage Specify the message that you are querying. + ** @result Returns the localized format string of the message. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessageFormat( TidyMessage tmessage ); + +/** Get the message with the format string already completed, in Tidy's + ** default localization. + ** @param tmessage Specify the message that you are querying. + ** @result Returns the message in the default localization. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessageDefault( TidyMessage tmessage ); + +/** Get the message with the format string already completed, in Tidy's + ** current localization. + ** @param tmessage Specify the message that you are querying. + ** @result Returns the message in the current localization. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessage( TidyMessage tmessage ); + +/** Get the position part part of the message in the default language. + ** @param tmessage Specify the message that you are querying. + ** @result Returns the positional part of a string as Tidy would display it + ** in the console application. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessagePosDefault( TidyMessage tmessage ); + +/** Get the position part part of the message in the current language. + ** @param tmessage Specify the message that you are querying. + ** @result Returns the positional part of a string as Tidy would display it + ** in the console application. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessagePos( TidyMessage tmessage ); + +/** Get the prefix part of a message in the default language. + ** @param tmessage Specify the message that you are querying. + ** @result Returns the message prefix part of a string as Tidy would display + ** it in the console application. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessagePrefixDefault( TidyMessage tmessage ); + +/** Get the prefix part of a message in the current language. + ** @param tmessage Specify the message that you are querying. + ** @result Returns the message prefix part of a string as Tidy would display + ** it in the console application. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessagePrefix( TidyMessage tmessage ); + +/** Get the complete message as Tidy would emit it in the default localization. + ** @param tmessage Specify the message that you are querying. + ** @result Returns the complete message just as Tidy would display it on the + ** console. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessageOutputDefault( TidyMessage tmessage ); + +/** Get the complete message as Tidy would emit it in the current localization. + ** @param tmessage Specify the message that you are querying. + ** @result Returns the complete message just as Tidy would display it on the + ** console. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessageOutput( TidyMessage tmessage ); + +/** @} end subgroup TidyMessageCallback API */ + +/** @name TidyMessageCallback Arguments API + ** When using `TidyMessageCallback` you will be supplied with a TidyMessage + ** object which can be used as a token against which to query using this API. + ** This API deals strictly with _arguments_ that a message may or may not have; + ** these are the same arguments that Tidy would apply to a format string in + ** order to fill in the placeholder fields and deliver a complete report or + ** dialogue string to you. + ** + ** @{ + */ + +/** Initiates an iterator for a list of arguments related to a given message. + ** This iterator allows you to iterate through all of the arguments, if any. + ** In order to iterate through the arguments, initiate the iterator with this + ** function, and then use tidyGetNextMessageArgument() to retrieve the first + ** and subsequent arguments. For example: + ** @code{.c} + ** TidyIterator itArg = tidyGetMessageArguments( tmessage ); + ** while ( itArg ) { + ** TidyMessageArgument my_arg = tidyGetNextMessageArgument( tmessage, &itArg ); + ** // do something with my_arg, such as inspect its value or format + ** } + ** @endcode + ** @param tmessage The message about whose arguments you wish to query. + ** @result Returns a TidyIterator, which is a token used to represent the + ** current position in a list within LibTidy. + */ +TIDY_EXPORT TidyIterator TIDY_CALL tidyGetMessageArguments( TidyMessage tmessage ); + +/** Given a valid TidyIterator initiated with tidyGetMessageArguments(), returns + ** an instance of the opaque type TidyMessageArgument, which serves as a token + ** against which the remaining argument API functions may be used to query + ** information. + ** @result Returns an instance of TidyMessageArgument. + */ +TIDY_EXPORT TidyMessageArgument TIDY_CALL tidyGetNextMessageArgument(TidyMessage tmessage, /**< The message whose arguments you want to access. */ + TidyIterator* iter /**< The TidyIterator (initiated with tidyOptGetDocLinksList()) token. */ + ); + +/** Returns the `TidyFormatParameterType` of the given message argument. + ** @result Returns the type of parameter of type TidyFormatParameterType. + */ +TIDY_EXPORT TidyFormatParameterType TIDY_CALL tidyGetArgType(TidyMessage tmessage, /**< The message whose arguments you want to access. */ + TidyMessageArgument* arg /**< The argument that you are querying. */ + ); + +/** Returns the format specifier of the given message argument. The memory for + ** this string is cleared upon termination of the callback, so do be sure to + ** make your own copy. + ** @result Returns the format specifier string of the given argument. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetArgFormat(TidyMessage tmessage, /**< The message whose arguments you want to access. */ + TidyMessageArgument* arg /**< The argument that you are querying. */ + ); + +/** Returns the string value of the given message argument. An assertion + ** will be generated if the argument type is not a string. + ** @result Returns the string value of the given argument. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetArgValueString(TidyMessage tmessage, /**< The message whose arguments you want to access. */ + TidyMessageArgument* arg /**< The argument that you are querying. */ + ); + +/** Returns the unsigned integer value of the given message argument. An + ** assertion will be generated if the argument type is not an unsigned int. + ** @result Returns the unsigned integer value of the given argument. + */ +TIDY_EXPORT uint TIDY_CALL tidyGetArgValueUInt(TidyMessage tmessage, /**< The message whose arguments you want to access. */ + TidyMessageArgument* arg /**< The argument that you are querying. */ + ); + +/** Returns the integer value of the given message argument. An assertion + ** will be generated if the argument type is not an integer. + ** @result Returns the integer value of the given argument. + */ +TIDY_EXPORT int TIDY_CALL tidyGetArgValueInt(TidyMessage tmessage, /**< The message whose arguments you want to access. */ + TidyMessageArgument* arg /**< The argument that you are querying. */ + ); + +/** + * Returns the double value of the given message argument. An assertion + * will be generated if the argument type is not a double. + ** @result Returns the double value of the given argument. + */ +TIDY_EXPORT double TIDY_CALL tidyGetArgValueDouble(TidyMessage tmessage, /**< The message whose arguments you want to access. */ + TidyMessageArgument* arg /**< The argument that you are querying. */ + ); + +/** @} end subgroup TidyMessageCallback Arguments API */ + +/** @name Printing + ** LibTidy applications can somewhat track the progress of the tidying process + ** by using this provided callback. It relates where something in the source + ** document ended up in the output. + ** @{ + */ + +/** This typedef represents the required signature for your provided callback + ** function should you wish to register one with tidySetMessageCallback(). + ** Your callback function will be provided with the following parameters. + ** @param tdoc Indicates the source tidy document. + ** @param line Indicates the line in the source document at this point in the process. + ** @param col Indicates the column in the source document at this point in the process. + ** @param destLine Indicates the line number in the output document at this point in the process. + */ +typedef void (TIDY_CALL *TidyPPProgress)( TidyDoc tdoc, uint line, uint col, uint destLine ); + +/** This function informs Tidy to use the specified callback for tracking the + ** pretty-printing process progress. + */ +TIDY_EXPORT Bool TIDY_CALL tidySetPrettyPrinterCallback(TidyDoc tdoc, + TidyPPProgress callback + ); + +/** @} */ +/** @} end IO group */ +/* MARK: - Document Parse */ +/***************************************************************************//** + ** @defgroup Parse Document Parse + ** + ** Functions for parsing markup from a given input source, as well as string + ** and filename functions for added convenience. HTML/XHTML version determined + ** from input. + ** + ** @{ + ******************************************************************************/ + +/** Parse markup in named file. + ** @result Returns the highest of `2` indicating that errors were present in + ** the document, `1` indicating warnings, and `0` in the case of + ** everything being okay. + */ +TIDY_EXPORT int TIDY_CALL tidyParseFile(TidyDoc tdoc, /**< The tidy document to use for parsing. */ + ctmbstr filename /**< The filename to parse. */ + ); + +/** Parse markup from the standard input. + ** @param tdoc The tidy document to use for parsing. + ** @result Returns the highest of `2` indicating that errors were present in + ** the document, `1` indicating warnings, and `0` in the case of + ** everything being okay. + */ +TIDY_EXPORT int TIDY_CALL tidyParseStdin( TidyDoc tdoc ); + +/** Parse markup in given string. Note that the supplied string is of type + ** `ctmbstr` based on `char` and therefore doesn't support the use of + ** UTF-16 strings. Use `tidyParseBuffer()` if parsing multibyte strings. + ** @result Returns the highest of `2` indicating that errors were present in + ** the document, `1` indicating warnings, and `0` in the case of + ** everything being okay. + */ +TIDY_EXPORT int TIDY_CALL tidyParseString(TidyDoc tdoc, /**< The tidy document to use for parsing. */ + ctmbstr content /**< The string to parse. */ + ); + +/** Parse markup in given buffer. + ** @result Returns the highest of `2` indicating that errors were present in + ** the document, `1` indicating warnings, and `0` in the case of + ** everything being okay. + */ +TIDY_EXPORT int TIDY_CALL tidyParseBuffer(TidyDoc tdoc, /**< The tidy document to use for parsing. */ + TidyBuffer* buf /**< The TidyBuffer containing data to parse. */ + ); + +/** Parse markup in given generic input source. + ** @result Returns the highest of `2` indicating that errors were present in + ** the document, `1` indicating warnings, and `0` in the case of + ** everything being okay. + */ +TIDY_EXPORT int TIDY_CALL tidyParseSource(TidyDoc tdoc, /**< The tidy document to use for parsing. */ + TidyInputSource* source /**< A TidyInputSource containing data to parse. */ + ); + + +/** @} End Parse group */ +/* MARK: - Diagnostics and Repair */ +/***************************************************************************//** + ** @defgroup Clean Diagnostics and Repair + ** + ** After parsing the document, you can use these functions to attempt cleanup, + ** repair, get additional diagnostics, and determine the document type. + ** @{ + ******************************************************************************/ + +/** Execute configured cleanup and repair operations on parsed markup. + ** @param tdoc The tidy document to use. + ** @result An integer representing the status. + */ +TIDY_EXPORT int TIDY_CALL tidyCleanAndRepair( TidyDoc tdoc ); + +/** Reports the document type and diagnostic statistics on parsed and repaired + ** markup. You must call tidyCleanAndRepair() before using this function. + ** @param tdoc The tidy document to use. + ** @result An integer representing the status. + */ +TIDY_EXPORT int TIDY_CALL tidyRunDiagnostics( TidyDoc tdoc ); + +/** Reports the document type into the output sink. + ** @param tdoc The tidy document to use. + ** @result An integer representing the status. + */ +TIDY_EXPORT int TIDY_CALL tidyReportDoctype( TidyDoc tdoc ); + + +/** @} end Clean group */ +/* MARK: - Document Save Functions */ +/***************************************************************************//** + ** @defgroup Save Document Save Functions + ** + ** Save currently parsed document to the given output sink. File name + ** and string/buffer functions provided for convenience. + ** + ** @{ + ******************************************************************************/ + +/** Save the tidy document to the named file. + ** @result An integer representing the status. + */ +TIDY_EXPORT int TIDY_CALL tidySaveFile(TidyDoc tdoc, /**< The tidy document to save. */ + ctmbstr filename /**< The destination file name. */ + ); + +/** Save the tidy document to standard output (FILE*). + ** @param tdoc The tidy document to save. + ** @result An integer representing the status. + */ +TIDY_EXPORT int TIDY_CALL tidySaveStdout( TidyDoc tdoc ); + +/** Save the tidy document to given TidyBuffer object. + ** @result An integer representing the status. + */ +TIDY_EXPORT int TIDY_CALL tidySaveBuffer(TidyDoc tdoc, /**< The tidy document to save. */ + TidyBuffer* buf /**< The buffer to place the output. */ + ); + +/** Save the tidy document to an application buffer. If TidyShowMarkup and the + ** document has no errors, or TidyForceOutput, then the current document (per + ** the current configuration) will be pretty printed to this application + ** buffer. The document byte length (not character length) will be placed into + ** *buflen. The document will not be null terminated. If the buffer is not big + ** enough, ENOMEM will be returned, else the actual document status. + ** @result An integer representing the status. + */ +TIDY_EXPORT int TIDY_CALL tidySaveString(TidyDoc tdoc, /**< The tidy document to save. */ + tmbstr buffer, /**< The buffer to save to. */ + uint* buflen /**< [out] The byte length written. */ + ); + +/** Save to given generic output sink. + ** @result An integer representing the status. + */ +TIDY_EXPORT int TIDY_CALL tidySaveSink(TidyDoc tdoc, /**< The tidy document to save. */ + TidyOutputSink* sink /**< The output sink to save to. */ + ); + +/** Save current settings to named file. Only writes non-default values. + ** @result An integer representing the status. + */ +TIDY_EXPORT int TIDY_CALL tidyOptSaveFile(TidyDoc tdoc, /**< The tidy document to save. */ + ctmbstr cfgfil /**< The filename to save the configuration to. */ + ); + +/** Save current settings to given output sink. Only non-default values are + ** written. + ** @result An integer representing the status. + */ +TIDY_EXPORT int TIDY_CALL tidyOptSaveSink(TidyDoc tdoc, /**< The tidy document to save. */ + TidyOutputSink* sink /**< The output sink to save the configuration to. */ + ); + + +/** @} end Save group */ +/* MARK: - Document Tree */ +/***************************************************************************//** + ** @defgroup Tree Document Tree + ** + ** A parsed (and optionally repaired) document is represented by Tidy as a + ** tree, much like a W3C DOM. This tree may be traversed using these + ** functions. The following snippet gives a basic idea how these functions + ** can be used. + ** + ** @code{.c} + ** void dumpNode( TidyNode tnod, int indent ) { + ** TidyNode child; + ** + ** for ( child = tidyGetChild(tnod); child; child = tidyGetNext(child) ) { + ** ctmbstr name; + ** switch ( tidyNodeGetType(child) ) { + ** case TidyNode_Root: name = "Root"; break; + ** case TidyNode_DocType: name = "DOCTYPE"; break; + ** case TidyNode_Comment: name = "Comment"; break; + ** case TidyNode_ProcIns: name = "Processing Instruction"; break; + ** case TidyNode_Text: name = "Text"; break; + ** case TidyNode_CDATA: name = "CDATA"; break; + ** case TidyNode_Section: name = "XML Section"; break; + ** case TidyNode_Asp: name = "ASP"; break; + ** case TidyNode_Jste: name = "JSTE"; break; + ** case TidyNode_Php: name = "PHP"; break; + ** case TidyNode_XmlDecl: name = "XML Declaration"; break; + ** + ** case TidyNode_Start: + ** case TidyNode_End: + ** case TidyNode_StartEnd: + ** default: + ** name = tidyNodeGetName( child ); + ** break; + ** } + ** assert( name != NULL ); + ** printf( "\%*.*sNode: \%s\\n", indent, indent, " ", name ); + ** dumpNode( child, indent + 4 ); + ** } + ** } + ** + ** void dumpDoc( TidyDoc tdoc ) { + ** dumpNode( tidyGetRoot(tdoc), 0 ); + ** } + ** + ** void dumpBody( TidyDoc tdoc ) { + ** dumpNode( tidyGetBody(tdoc), 0 ); + ** } + ** @endcode + ** + ** @{ + ******************************************************************************/ + +/** @name Nodes for Document Sections + ** @{ + */ + +/** Get the root node. + ** @param tdoc The document to query. + ** @result Returns a tidy node. + */ +TIDY_EXPORT TidyNode TIDY_CALL tidyGetRoot( TidyDoc tdoc ); + +/** Get the HTML node. + ** @param tdoc The document to query. + ** @result Returns a tidy node. + */ +TIDY_EXPORT TidyNode TIDY_CALL tidyGetHtml( TidyDoc tdoc ); + +/** Get the HEAD node. + ** @param tdoc The document to query. + ** @result Returns a tidy node. + */ +TIDY_EXPORT TidyNode TIDY_CALL tidyGetHead( TidyDoc tdoc ); + +/** Get the BODY node. + ** @param tdoc The document to query. + ** @result Returns a tidy node. + */ +TIDY_EXPORT TidyNode TIDY_CALL tidyGetBody( TidyDoc tdoc ); + +/** @} + ** @name Relative Nodes + ** @{ + */ + +/** Get the parent of the indicated node. + ** @param tnod The node to query. + ** @result Returns a tidy node. + */ +TIDY_EXPORT TidyNode TIDY_CALL tidyGetParent( TidyNode tnod ); + +/** Get the child of the indicated node. + ** @param tnod The node to query. + ** @result Returns a tidy node. + */ +TIDY_EXPORT TidyNode TIDY_CALL tidyGetChild( TidyNode tnod ); + +/** Get the next sibling node. + ** @param tnod The node to query. + ** @result Returns a tidy node. + */ +TIDY_EXPORT TidyNode TIDY_CALL tidyGetNext( TidyNode tnod ); + +/** Get the previous sibling node. + ** @param tnod The node to query. + ** @result Returns a tidy node. + */ +TIDY_EXPORT TidyNode TIDY_CALL tidyGetPrev( TidyNode tnod ); + +/** @} + ** @name Miscellaneous Node Functions + ** @{ + */ + +/** Remove the indicated node. + ** @result Returns the next tidy node. + */ +TIDY_EXPORT TidyNode TIDY_CALL tidyDiscardElement(TidyDoc tdoc, /**< The tidy document from which to remove the node. */ + TidyNode tnod /**< The node to remove */ + ); + +/** @} + ** @name Node Attribute Functions + ** @{ + */ + +/** Get the first attribute. + ** @param tnod The node for which to get attributes. + ** @result Returns an instance of TidyAttr. + */ +TIDY_EXPORT TidyAttr TIDY_CALL tidyAttrFirst( TidyNode tnod ); + +/** Get the next attribute. + ** @param tattr The current attribute, so the next one can be returned. + ** @result Returns and instance of TidyAttr. + */ +TIDY_EXPORT TidyAttr TIDY_CALL tidyAttrNext( TidyAttr tattr ); + +/** Get the name of a TidyAttr instance. + ** @param tattr The tidy attribute to query. + ** @result Returns a string indicating the name of the attribute. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyAttrName( TidyAttr tattr ); + +/** Get the value of a TidyAttr instance. + ** @param tattr The tidy attribute to query. + ** @result Returns a string indicating the value of the attribute. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyAttrValue( TidyAttr tattr ); + +/** Discard an attribute. */ +TIDY_EXPORT void TIDY_CALL tidyAttrDiscard(TidyDoc itdoc, /**< The tidy document from which to discard the attribute. */ + TidyNode tnod, /**< The node from which to discard the attribute. */ + TidyAttr tattr /**< The attribute to discard. */ + ); + +/** Get the attribute ID given a tidy attribute. + ** @param tattr The attribute to query. + ** @result Returns the TidyAttrId of the given attribute. + **/ +TIDY_EXPORT TidyAttrId TIDY_CALL tidyAttrGetId( TidyAttr tattr ); + +/** Indicates whether or not a given attribute is an event attribute. + ** @param tattr The attribute to query. + ** @result Returns a bool indicating whether or not the attribute is an event. + **/ +TIDY_EXPORT Bool TIDY_CALL tidyAttrIsEvent( TidyAttr tattr ); + +/** Get an instance of TidyAttr by specifying an attribute ID. + ** @result Returns a TidyAttr instance. + */ +TIDY_EXPORT TidyAttr TIDY_CALL tidyAttrGetById(TidyNode tnod, /**< The node to query. */ + TidyAttrId attId /**< The attribute ID to find. */ + ); + +/** @} + ** @name Additional Node Interrogation + ** @{ + */ + +/** Get the type of node. + ** @param tnod The node to query. + ** @result Returns the type of node as TidyNodeType. + */ +TIDY_EXPORT TidyNodeType TIDY_CALL tidyNodeGetType( TidyNode tnod ); + +/** Get the name of the node. + ** @param tnod The node to query. + ** @result Returns a string indicating the name of the node. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyNodeGetName( TidyNode tnod ); + +/** Indicates whether or not a node is a text node. + ** @param tnod The node to query. + ** @result Returns a bool indicating whether or not the node is a text node. + */ +TIDY_EXPORT Bool TIDY_CALL tidyNodeIsText( TidyNode tnod ); + +/** Indicates whether or not the node is a propriety type. + ** @result Returns a bool indicating whether or not the node is a proprietary type. + */ +TIDY_EXPORT Bool TIDY_CALL tidyNodeIsProp(TidyDoc tdoc, /**< The document to query. */ + TidyNode tnod /**< The node to query */ + ); + +/** Indicates whether or not a node represents and HTML header element, such + ** as h1, h2, etc. + ** @param tnod The node to query. + ** @result Returns a bool indicating whether or not the node is an HTML header. + */ +TIDY_EXPORT Bool TIDY_CALL tidyNodeIsHeader( TidyNode tnod ); + +/** Indicates whether or not the node has text. + ** @result Returns the type of node as TidyNodeType. + */ +TIDY_EXPORT Bool TIDY_CALL tidyNodeHasText(TidyDoc tdoc, /**< The document to query. */ + TidyNode tnod /**< The node to query. */ + ); + +/** Gets the text of a node and places it into the given TidyBuffer. The text will be terminated with a `TidyNewline`. + ** If you want the raw utf-8 stream see `tidyNodeGetValue()`. + ** @result Returns a bool indicating success or not. + */ +TIDY_EXPORT Bool TIDY_CALL tidyNodeGetText(TidyDoc tdoc, /**< The document to query. */ + TidyNode tnod, /**< The node to query. */ + TidyBuffer* buf /**< [out] A TidyBuffer used to receive the node's text. */ + ); + +/** Get the value of the node. This copies the unescaped value of this node into + ** the given TidyBuffer at UTF-8. + ** @result Returns a bool indicating success or not. + */ +TIDY_EXPORT Bool TIDY_CALL tidyNodeGetValue(TidyDoc tdoc, /**< The document to query */ + TidyNode tnod, /**< The node to query */ + TidyBuffer* buf /**< [out] A TidyBuffer used to receive the node's value. */ + ); + +/** Get the tag ID of the node. + ** @param tnod The node to query. + ** @result Returns the tag ID of the node as TidyTagId. + */ +TIDY_EXPORT TidyTagId TIDY_CALL tidyNodeGetId( TidyNode tnod ); + +/** Get the line number where the node occurs. + ** @param tnod The node to query. + ** @result Returns the line number. + */ +TIDY_EXPORT uint TIDY_CALL tidyNodeLine( TidyNode tnod ); + +/** Get the column location of the node. + ** @param tnod The node to query. + ** @result Returns the column location of the node. + */ +TIDY_EXPORT uint TIDY_CALL tidyNodeColumn( TidyNode tnod ); + + +/** @} */ +/** @} end Tree group */ +/* MARK: - Message Key Management */ +/***************************************************************************//** + ** @defgroup MessagesKeys Message Key Management + ** + ** These functions serve to manage message codes, i.e., codes that are used + ** Tidy and communicated via its callback filters to represent reports and + ** dialogue that Tidy emits. + ** + ** @remark These codes only reflect complete messages, and are specifically + ** distinct from the internal codes that are used to lookup individual + ** strings for localization purposes. + ** + ** @{ + ******************************************************************************/ + +/** + ** Given a message code, return the text key that represents it. + ** @param code The error code to lookup. + ** @result The string representing the error code. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyErrorCodeAsKey(uint code); + +/** + ** Given a text key representing a message code, return the uint that + ** represents it. + ** + ** @remark We establish that for external purposes, the API will ensure that + ** string keys remain consistent. *Never* count on the integer value + ** of a message code. Always use this function to ensure that the + ** integer is valid if you need one. + ** @param code The string representing the error code. + ** @result Returns an integer that represents the error code, which can be + ** used to lookup Tidy's built-in strings. If the provided string does + ** not have a matching message code, then UINT_MAX will be returned. + */ +TIDY_EXPORT uint TIDY_CALL tidyErrorCodeFromKey(ctmbstr code); + +/** Initiates an iterator for a list of message codes available in Tidy. + ** This iterator allows you to iterate through all of the code. In orde to + ** iterate through the codes, initiate the iterator with this function, and + ** then use getNextErrorCode() to retrieve the first and subsequent codes. + ** For example: + ** @code{.c} + ** TidyIterator itMessage = getErrorCodeList(); + ** while ( itMessage ) { + ** uint code = getNextErrorCode( &itMessage ); + ** // do something with the code, such as lookup a string. + ** } + ** @endcode + ** @result Returns a TidyIterator, which is a token used to represent the + ** current position in a list within LibTidy. + */ +TIDY_EXPORT TidyIterator TIDY_CALL getErrorCodeList(void); + +/** Given a valid TidyIterator initiated with getErrorCodeList(), returns + ** an instance of the opaque type TidyMessageArgument, which serves as a token + ** against which the remaining argument API functions may be used to query + ** information. + ** @param iter The TidyIterator (initiated with getErrorCodeList()) token. + ** @result Returns a message code. + */ +TIDY_EXPORT uint TIDY_CALL getNextErrorCode( TidyIterator* iter ); + + +/** @} end MessagesKeys group */ +/* MARK: - Localization Support */ +/***************************************************************************//** + ** @defgroup Localization Localization Support + ** + ** These functions help manage localization in Tidy. + ** + ** @{ + ******************************************************************************/ + + +/** @name Tidy's Locale + ** @{ + */ + +/** Tells Tidy to use a different language for output. + ** @param languageCode A Windows or POSIX language code, and must match + ** a TIDY_LANGUAGE for an installed language. + ** @result Indicates that a setting was applied, but not necessarily the + ** specific request, i.e., true indicates a language and/or region + ** was applied. If es_mx is requested but not installed, and es is + ** installed, then es will be selected and this function will return + ** true. However the opposite is not true; if es is requested but + ** not present, Tidy will not try to select from the es_XX variants. + */ +TIDY_EXPORT Bool TIDY_CALL tidySetLanguage( ctmbstr languageCode ); + +/** Gets the current language used by Tidy. + ** @result Returns a string indicating the currently set language. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyGetLanguage(void); + +/** @} + ** @name Locale Mappings + ** @{ + */ + +/** @struct tidyLocaleMapItem + ** Represents an opaque type we can use for tidyLocaleMapItem, which + ** is used to iterate through the language list, and used to access + ** the windowsName() and the posixName(). + */ +/* Prevent Doxygen from listing this as a function. */ +#ifndef DOXYGEN_SHOULD_SKIP_THIS +opaque_type(tidyLocaleMapItem); +#endif + +/** Initiates an iterator for a list of Tidy's Windows<->POSIX locale mappings. + ** This iterator allows you to iterate through this list. In order to + ** iterate through the list, initiate the iterator with this function, and then + ** use getNextWindowsLanguage() to retrieve the first and subsequent codes. + ** For example: + ** @code{.c} + ** TidyIterator itList = getWindowsLanguageList(); + ** while ( itList ) { + ** tidyLocaleMapItem *item = getNextWindowsLanguage( &itList ); + ** // do something such as get the TidyLangWindowsName(item). + ** } + ** @endcode + ** @result Returns a TidyIterator, which is a token used to represent the + ** current position in a list within LibTidy. + */ +TIDY_EXPORT TidyIterator TIDY_CALL getWindowsLanguageList(void); + +/** Given a valid TidyIterator initiated with getWindowsLanguageList(), returns + ** a pointer to a tidyLocaleMapItem, which can be further interrogated with + ** TidyLangWindowsName() or TidyLangPosixName(). + ** @param iter The TidyIterator (initiated with getWindowsLanguageList()) token. + ** @result Returns a pointer to a tidyLocaleMapItem. + */ +TIDY_EXPORT const tidyLocaleMapItem* TIDY_CALL getNextWindowsLanguage( TidyIterator* iter ); + +/** Given a `tidyLocaleMapItem`, return the Windows name. + ** @param item An instance of tidyLocaleMapItem to query. + ** @result Returns a string with the Windows name of the mapping. + */ +TIDY_EXPORT ctmbstr TIDY_CALL TidyLangWindowsName( const tidyLocaleMapItem *item ); + +/** Given a `tidyLocaleMapItem`, return the POSIX name. + ** @param item An instance of tidyLocaleMapItem to query. + ** @result Returns a string with the POSIX name of the mapping. + */ +TIDY_EXPORT ctmbstr TIDY_CALL TidyLangPosixName( const tidyLocaleMapItem *item ); + +/** @} + ** @name Getting Localized Strings + ** @{ + */ + +/** Provides a string given `messageType` in the current localization for + ** `quantity`. Some strings have one or more plural forms, and this function + ** will ensure that the correct singular or plural form is returned for the + ** specified quantity. + ** @result Returns the desired string. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyLocalizedStringN(uint messageType, /**< The message type. */ + uint quantity /**< The quantity. */ + ); + +/** Provides a string given `messageType` in the current localization for the + ** single case. + ** @param messageType The message type. + ** @result Returns the desired string. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyLocalizedString( uint messageType ); + +/** Provides a string given `messageType` in the default localization for + ** `quantity`. Some strings have one or more plural forms, and this function + ** will ensure that the correct singular or plural form is returned for the + ** specified quantity. + ** @result Returns the desired string. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyDefaultStringN(uint messageType, /**< The message type. */ + uint quantity /**< The quantity. */ + ); + +/** Provides a string given `messageType` in the default localization (which + ** is `en`). + ** @param messageType The message type. + ** @result Returns the desired string. + */ +TIDY_EXPORT ctmbstr TIDY_CALL tidyDefaultString( uint messageType ); + +/** Initiates an iterator for a list of string key codes available in Tidy. + ** This iterator allows you to iterate through all of the codes. In order to + ** iterate through the codes, initiate the iterator with this function, and + ** then use getNextStringKey() to retrieve the first and subsequent codes. + ** For example: + ** @code{.c} + ** TidyIterator itKey = getErrorCodeList(); + ** while ( itKey ) { + ** uint code = getNextStringKey( &itKey ); + ** // do something with the code, such as lookup a string. + ** } + ** @endcode + ** @remark These are provided for documentation generation purposes, and + ** probably aren't of much use to the average LibTidy implementor. + ** @result Returns a TidyIterator, which is a token used to represent the + ** current position in a list within LibTidy. + */ +TIDY_EXPORT TidyIterator TIDY_CALL getStringKeyList(void); + +/** Given a valid TidyIterator initiated with getStringKeyList(), returns + ** an unsigned integer representing the next key value. + ** @remark These are provided for documentation generation purposes, and + ** probably aren't of much use to the average LibTidy implementor. + ** @param iter The TidyIterator (initiated with getStringKeyList()) token. + ** @result Returns a message code. + */ +TIDY_EXPORT uint TIDY_CALL getNextStringKey( TidyIterator* iter ); + +/** @} + ** @name Available Languages + ** @{ + */ + +/** Initiates an iterator for a list of Tidy's installed languages. This + ** iterator allows you to iterate through this list. In order to iterate + ** through the list, initiate the iterator with this function, and then use + ** use getNextInstalledLanguage() to retrieve the first and subsequent strings. + ** For example: + ** @code{.c} + ** TidyIterator itList = getInstalledLanguageList(); + ** while ( itList ) { + ** printf("%s", getNextInstalledLanguage( &itList )); + ** } + ** @endcode + ** @result Returns a TidyIterator, which is a token used to represent the + ** current position in a list within LibTidy. + */ +TIDY_EXPORT TidyIterator TIDY_CALL getInstalledLanguageList(void); + +/** Given a valid TidyIterator initiated with getInstalledLanguageList(), + ** returns a string representing a language name that is installed in Tidy. + ** @param iter The TidyIterator (initiated with getInstalledLanguageList()) + ** token. + ** @result Returns a string indicating the installed language. + */ +TIDY_EXPORT ctmbstr TIDY_CALL getNextInstalledLanguage( TidyIterator* iter ); + +/** @} */ + +/** @} end MessagesKeys group */ +/** @} end public_api group */ + + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* __TIDY_H__ */ + +/* + * local variables: + * mode: c + * indent-tabs-mode: nil + * c-basic-offset: 4 + * eval: (c-set-offset 'substatement-open 0) + * end: + */ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidybuffio.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidybuffio.h new file mode 100644 index 0000000..1c1b017 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidybuffio.h @@ -0,0 +1,125 @@ +#ifndef __TIDY_BUFFIO_H__ +#define __TIDY_BUFFIO_H__ + +/**************************************************************************//** + * @file + * Treat buffer as a stream that Tidy can use for I/O operations. It offers + * the ability for the buffer to grow as bytes are added, and keeps track + * of current read and write points. + * + * @author + * HTACG, et al (consult git log) + * + * @copyright + * Copyright (c) 1998-2017 World Wide Web Consortium (Massachusetts + * Institute of Technology, European Research Consortium for Informatics + * and Mathematics, Keio University). + * @copyright + * See tidy.h for license. + * + * @date + * Consult git log. + ******************************************************************************/ + +#include "tidyplatform.h" +#include "tidy.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** A TidyBuffer is chunk of memory that can be used for multiple I/O purposes + ** within Tidy. + ** @ingroup IO + */ +TIDY_STRUCT +struct _TidyBuffer +{ + TidyAllocator* allocator; /**< Memory allocator */ + byte* bp; /**< Pointer to bytes */ + uint size; /**< Number of bytes currently in use */ + uint allocated; /**< Number of bytes allocated */ + uint next; /**< Offset of current input position */ +}; + +/** Initialize data structure using the default allocator */ +TIDY_EXPORT void TIDY_CALL tidyBufInit( TidyBuffer* buf ); + +/** Initialize data structure using the given custom allocator */ +TIDY_EXPORT void TIDY_CALL tidyBufInitWithAllocator( TidyBuffer* buf, TidyAllocator* allocator ); + +/** Free current buffer, allocate given amount, reset input pointer, + use the default allocator */ +TIDY_EXPORT void TIDY_CALL tidyBufAlloc( TidyBuffer* buf, uint allocSize ); + +/** Free current buffer, allocate given amount, reset input pointer, + use the given custom allocator */ +TIDY_EXPORT void TIDY_CALL tidyBufAllocWithAllocator( TidyBuffer* buf, + TidyAllocator* allocator, + uint allocSize ); + +/** Expand buffer to given size. +** Chunk size is minimum growth. Pass 0 for default of 256 bytes. +*/ +TIDY_EXPORT void TIDY_CALL tidyBufCheckAlloc( TidyBuffer* buf, + uint allocSize, uint chunkSize ); + +/** Free current contents and zero out */ +TIDY_EXPORT void TIDY_CALL tidyBufFree( TidyBuffer* buf ); + +/** Set buffer bytes to 0 */ +TIDY_EXPORT void TIDY_CALL tidyBufClear( TidyBuffer* buf ); + +/** Attach to existing buffer */ +TIDY_EXPORT void TIDY_CALL tidyBufAttach( TidyBuffer* buf, byte* bp, uint size ); + +/** Detach from buffer. Caller must free. */ +TIDY_EXPORT void TIDY_CALL tidyBufDetach( TidyBuffer* buf ); + + +/** Append bytes to buffer. Expand if necessary. */ +TIDY_EXPORT void TIDY_CALL tidyBufAppend( TidyBuffer* buf, void* vp, uint size ); + +/** Append one byte to buffer. Expand if necessary. */ +TIDY_EXPORT void TIDY_CALL tidyBufPutByte( TidyBuffer* buf, byte bv ); + +/** Get byte from end of buffer */ +TIDY_EXPORT int TIDY_CALL tidyBufPopByte( TidyBuffer* buf ); + + +/** Get byte from front of buffer. Increment input offset. */ +TIDY_EXPORT int TIDY_CALL tidyBufGetByte( TidyBuffer* buf ); + +/** At end of buffer? */ +TIDY_EXPORT Bool TIDY_CALL tidyBufEndOfInput( TidyBuffer* buf ); + +/** Put a byte back into the buffer. Decrement input offset. */ +TIDY_EXPORT void TIDY_CALL tidyBufUngetByte( TidyBuffer* buf, byte bv ); + + +/************** + TIDY +**************/ + +/* Forward declarations +*/ + +/** Initialize a buffer input source */ +TIDY_EXPORT void TIDY_CALL tidyInitInputBuffer( TidyInputSource* inp, TidyBuffer* buf ); + +/** Initialize a buffer output sink */ +TIDY_EXPORT void TIDY_CALL tidyInitOutputBuffer( TidyOutputSink* outp, TidyBuffer* buf ); + +#ifdef __cplusplus +} +#endif +#endif /* __TIDY_BUFFIO_H__ */ + +/* + * local variables: + * mode: c + * indent-tabs-mode: nil + * c-basic-offset: 4 + * eval: (c-set-offset 'substatement-open 0) + * end: + */ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidyenum.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidyenum.h new file mode 100644 index 0000000..36407c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidyenum.h @@ -0,0 +1,1471 @@ +#ifndef __TIDYENUM_H__ +#define __TIDYENUM_H__ + +/**************************************************************************//** + * @file + * Separated public enumerations header providing important indentifiers for + * LibTidy and internal users, as well as code-generator macros used to + * generate many of them. + * + * The use of enums simplifies enum re-use in various wrappers, e.g. SWIG, + * generated wrappers, and COM IDL files. + * + * This file also contains macros to generate additional enums for use in + * Tidy's language localizations and/or to access Tidy's strings via the API. + * See detailed information elsewhere in this file's documentation. + * + * @note LibTidy does *not* guarantee the value of any enumeration member, + * including the starting integer value, except where noted. Always use enum + * members rather than their values! + * + * Enums that have starting values have starting values for a good reason, + * mainly to prevent string key overlap. + * + * @author Dave Raggett [dsr@w3.org] + * @author HTACG, et al (consult git log) + * + * @copyright + * Copyright (c) 1998-2017 World Wide Web Consortium (Massachusetts + * Institute of Technology, European Research Consortium for Informatics + * and Mathematics, Keio University). + * @copyright + * See tidy.h for license. + * + * @date Created 2001-05-20 by Charles Reitzel + * @date Updated 2002-07-01 by Charles Reitzel + * @date Further modifications: consult git log. + ******************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************//** + ** @defgroup public_enum_gen Tidy Strings Generation Macros + ** @ingroup internal_api + ** + ** Tidy aims to provide a consistent API for library users, and so we go to + ** some lengths to provide a `tidyStrings` enum that consists of the message + ** code for every string that Tidy can emit (used internally), and the array + ** `tidyStringsKeys[]` containing string representations of each message code. + ** + ** In order to keep code maintainable and make it simple to add new messages, + ** the message code enums and `tidyStringsKeys[]` are generated dynamically + ** with preprocessor macros defined below. + ** + ** Any visible FOREACH_MSG_* macro (including new ones) must be applied to the + ** `tidyStrings` enum with the `MAKE_ENUM()` macro in this file, and to the + ** `tidyStringsKeys[]` (in `messages.c`) with `MAKE_STRUCT` in this file. + ** + ** Modern IDE's will dynamically pre-process all of these macros, enabling + ** code-completion of these enums and array of structs. + ** + ** @{ + ******************************************************************************/ + +/* MARK: - Code Generation Macros */ +/** @name Code Generation Macros + ** These macros generate the enums and arrays from the Content Generation + ** Macros defined below. + ** @{ + */ + +/** Used to populate the contents of an enumerator, such as `tidyStrings`. */ +#define MAKE_ENUM(MESSAGE) MESSAGE, + +/** Used to populate the contents of a structure, such as tidyStringsKeys[]. */ +#define MAKE_STRUCT(MESSAGE) {#MESSAGE, MESSAGE}, + + +/** @} */ +/* MARK: - Content Generation Macros */ +/** @name Content Generation Macros + ** These macros generate the individual entries in the enums and structs used + ** to manage strings in Tidy. + ** @{ + */ + +/** Codes for populating TidyConfigCategory enumeration. */ +#define FOREACH_TIDYCONFIGCATEGORY(FN) \ + FN(TidyDiagnostics) /**< Diagnostics */ \ + FN(TidyDisplay) /**< Affecting screen display */ \ + FN(TidyDocumentIO) /**< Pertaining to document I/O */ \ + FN(TidyEncoding) /**< Relating to encoding */ \ + FN(TidyFileIO) /**< Pertaining to file I/O */ \ + FN(TidyMarkupCleanup) /**< Cleanup related options */ \ + FN(TidyMarkupEntities) /**< Entity related options */ \ + FN(TidyMarkupRepair) /**< Document repair related options */ \ + FN(TidyMarkupTeach) /**< Teach tidy new things */ \ + FN(TidyMarkupXForm) /**< Transform HTML one way or another */ \ + FN(TidyPrettyPrint) /**< Pretty printing options */ \ + FN(TidyInternalCategory) /**< Option is internal only. */ \ + + +/** These message codes comprise every possible message that can be output by + ** Tidy that are *not* diagnostic style messages, and are *not* console + ** application specific messages. + */ +#define FOREACH_MSG_MISC(FN) \ +/** line %d column %d */ FN(LINE_COLUMN_STRING) \ +/** %s: line %d column %d */ FN(FN_LINE_COLUMN_STRING) \ +/** discarding */ FN(STRING_DISCARDING) \ +/** error and errors */ FN(STRING_ERROR_COUNT_ERROR) \ +/** warning and warnings */ FN(STRING_ERROR_COUNT_WARNING) \ +/** Accessibility hello message */ FN(STRING_HELLO_ACCESS) \ +/** HTML Proprietary */ FN(STRING_HTML_PROPRIETARY) \ +/** plain text */ FN(STRING_PLAIN_TEXT) \ +/** replacing */ FN(STRING_REPLACING) \ +/** specified */ FN(STRING_SPECIFIED) \ +/** XML declaration */ FN(STRING_XML_DECLARATION) \ +/** no */ FN(TIDYCUSTOMNO_STRING) \ +/** block level */ FN(TIDYCUSTOMBLOCKLEVEL_STRING) \ +/** empty */ FN(TIDYCUSTOMEMPTY_STRING) \ +/** inline */ FN(TIDYCUSTOMINLINE_STRING) \ +/** pre */ FN(TIDYCUSTOMPRE_STRING) \ + + +/** These messages are used to generate additional dialogue style output from + ** Tidy when certain conditions exist, and provide more verbose explanations + ** than the short report. + */ +#define FOREACH_FOOTNOTE_MSG(FN) \ + FN(FOOTNOTE_TRIM_EMPTY_ELEMENT) \ + FN(TEXT_ACCESS_ADVICE1) \ + FN(TEXT_ACCESS_ADVICE2) \ + FN(TEXT_BAD_FORM) \ + FN(TEXT_BAD_MAIN) \ + FN(TEXT_HTML_T_ALGORITHM) \ + FN(TEXT_INVALID_URI) \ + FN(TEXT_INVALID_UTF16) \ + FN(TEXT_INVALID_UTF8) \ + FN(TEXT_M_IMAGE_ALT) \ + FN(TEXT_M_IMAGE_MAP) \ + FN(TEXT_M_LINK_ALT) \ + FN(TEXT_M_SUMMARY) \ + FN(TEXT_SGML_CHARS) \ + FN(TEXT_USING_BODY) \ + FN(TEXT_USING_FONT) \ + FN(TEXT_USING_FRAMES) \ + FN(TEXT_USING_LAYER) \ + FN(TEXT_USING_NOBR) \ + FN(TEXT_USING_SPACER) \ + FN(TEXT_VENDOR_CHARS) \ + FN(TEXT_WINDOWS_CHARS) + + +/** These messages are used to generate additional dialogue style output from + ** Tidy when certain conditions exist, and provide more verbose explanations + ** than the short report. + */ +#define FOREACH_DIALOG_MSG(FN) \ +/* TidyDialogueSummary */ FN(STRING_ERROR_COUNT) \ +/* TidyDialogueSummary */ FN(STRING_NEEDS_INTERVENTION) \ +/* TidyDialogueSummary */ FN(STRING_NO_ERRORS) \ +/* TidyDialogueSummary */ FN(STRING_NOT_ALL_SHOWN) \ +/* TidyDialogueInfo */ FN(TEXT_GENERAL_INFO_PLEA) \ +/* TidyDialogueInfo */ FN(TEXT_GENERAL_INFO) + + +/** These are report messages, i.e., messages that appear in Tidy's table + ** of errors and warnings. + */ +#define FOREACH_REPORT_MSG(FN) \ + FN(ADDED_MISSING_CHARSET) \ + FN(ANCHOR_NOT_UNIQUE) \ + FN(ANCHOR_DUPLICATED) \ + FN(APOS_UNDEFINED) \ + FN(ATTR_VALUE_NOT_LCASE) \ + FN(ATTRIBUTE_IS_NOT_ALLOWED) \ + FN(ATTRIBUTE_VALUE_REPLACED) \ + FN(BACKSLASH_IN_URI) \ + FN(BAD_ATTRIBUTE_VALUE_REPLACED) \ + FN(BAD_ATTRIBUTE_VALUE) \ + FN(BAD_CDATA_CONTENT) \ + FN(BAD_SUMMARY_HTML5) \ + FN(BAD_SURROGATE_LEAD) \ + FN(BAD_SURROGATE_PAIR) \ + FN(BAD_SURROGATE_TAIL) \ + FN(CANT_BE_NESTED) \ + FN(COERCE_TO_ENDTAG) \ + FN(CONTENT_AFTER_BODY) \ + FN(CUSTOM_TAG_DETECTED) \ + FN(DISCARDING_UNEXPECTED) \ + FN(DOCTYPE_AFTER_TAGS) \ + FN(DUPLICATE_FRAMESET) \ + FN(ELEMENT_NOT_EMPTY) \ + FN(ELEMENT_VERS_MISMATCH_ERROR) \ + FN(ELEMENT_VERS_MISMATCH_WARN) \ + FN(ENCODING_MISMATCH) \ + FN(ESCAPED_ILLEGAL_URI) \ + FN(FILE_CANT_OPEN) \ + FN(FILE_CANT_OPEN_CFG) \ + FN(FILE_NOT_FILE) \ + FN(FIXED_BACKSLASH) \ + FN(FOUND_STYLE_IN_BODY) \ + FN(ID_NAME_MISMATCH) \ + FN(ILLEGAL_NESTING) \ + FN(ILLEGAL_URI_CODEPOINT) \ + FN(ILLEGAL_URI_REFERENCE) \ + FN(INSERTING_AUTO_ATTRIBUTE) \ + FN(INSERTING_TAG) \ + FN(INVALID_ATTRIBUTE) \ + FN(INVALID_NCR) \ + FN(INVALID_SGML_CHARS) \ + FN(INVALID_UTF8) \ + FN(INVALID_UTF16) \ + FN(INVALID_XML_ID) \ + FN(JOINING_ATTRIBUTE) \ + FN(MALFORMED_COMMENT) \ + FN(MALFORMED_COMMENT_DROPPING) \ + FN(MALFORMED_COMMENT_EOS) \ + FN(MALFORMED_COMMENT_WARN) \ + FN(MALFORMED_DOCTYPE) \ + FN(MISMATCHED_ATTRIBUTE_ERROR) \ + FN(MISMATCHED_ATTRIBUTE_WARN) \ + FN(MISSING_ATTR_VALUE) \ + FN(MISSING_ATTRIBUTE) \ + FN(MISSING_DOCTYPE) \ + FN(MISSING_ENDTAG_BEFORE) \ + FN(MISSING_ENDTAG_FOR) \ + FN(MISSING_ENDTAG_OPTIONAL) \ + FN(MISSING_IMAGEMAP) \ + FN(MISSING_QUOTEMARK) \ + FN(MISSING_QUOTEMARK_OPEN) \ + FN(MISSING_SEMICOLON_NCR) \ + FN(MISSING_SEMICOLON) \ + FN(MISSING_STARTTAG) \ + FN(MISSING_TITLE_ELEMENT) \ + FN(MOVED_STYLE_TO_HEAD) \ + FN(NESTED_EMPHASIS) \ + FN(NESTED_QUOTATION) \ + FN(NEWLINE_IN_URI) \ + FN(NOFRAMES_CONTENT) \ + FN(NON_MATCHING_ENDTAG) \ + FN(OBSOLETE_ELEMENT) \ + FN(OPTION_REMOVED) \ + FN(OPTION_REMOVED_APPLIED) \ + FN(OPTION_REMOVED_UNAPPLIED) \ + FN(PREVIOUS_LOCATION) \ + FN(PROPRIETARY_ATTR_VALUE) \ + FN(PROPRIETARY_ATTRIBUTE) \ + FN(PROPRIETARY_ELEMENT) \ + FN(REMOVED_HTML5) \ + FN(REPEATED_ATTRIBUTE) \ + FN(REPLACING_ELEMENT) \ + FN(REPLACING_UNEX_ELEMENT) \ + FN(SPACE_PRECEDING_XMLDECL) \ + FN(STRING_CONTENT_LOOKS) \ + FN(STRING_ARGUMENT_BAD) \ + FN(STRING_DOCTYPE_GIVEN) \ + FN(STRING_MISSING_MALFORMED) \ + FN(STRING_MUTING_TYPE) \ + FN(STRING_NO_SYSID) \ + FN(STRING_UNKNOWN_OPTION) \ + FN(SUSPECTED_MISSING_QUOTE) \ + FN(TAG_NOT_ALLOWED_IN) \ + FN(TOO_MANY_ELEMENTS_IN) \ + FN(TOO_MANY_ELEMENTS) \ + FN(TRIM_EMPTY_ELEMENT) \ + FN(UNESCAPED_AMPERSAND) \ + FN(UNEXPECTED_END_OF_FILE_ATTR) \ + FN(UNEXPECTED_END_OF_FILE) \ + FN(UNEXPECTED_ENDTAG_ERR) \ + FN(UNEXPECTED_ENDTAG_IN) \ + FN(UNEXPECTED_ENDTAG) \ + FN(UNEXPECTED_EQUALSIGN) \ + FN(UNEXPECTED_GT) \ + FN(UNEXPECTED_QUOTEMARK) \ + FN(UNKNOWN_ELEMENT_LOOKS_CUSTOM) \ + FN(UNKNOWN_ELEMENT) \ + FN(UNKNOWN_ENTITY) \ + FN(USING_BR_INPLACE_OF) \ + FN(VENDOR_SPECIFIC_CHARS) \ + FN(WHITE_IN_URI) \ + FN(XML_DECLARATION_DETECTED) \ + FN(XML_ID_SYNTAX) \ + FN(BLANK_TITLE_ELEMENT) + + +/** These are report messages added by Tidy's accessibility module. + ** Note that commented out items don't have checks for them at this time, + ** and it was probably intended that some test would eventually be written. + */ +#define FOREACH_ACCESS_MSG(FN) \ +/** [1.1.1.1] */ FN(IMG_MISSING_ALT) \ +/** [1.1.1.2] */ FN(IMG_ALT_SUSPICIOUS_FILENAME) \ +/** [1.1.1.3] */ FN(IMG_ALT_SUSPICIOUS_FILE_SIZE) \ +/** [1.1.1.4] */ FN(IMG_ALT_SUSPICIOUS_PLACEHOLDER) \ +/** [1.1.1.10] */ FN(IMG_ALT_SUSPICIOUS_TOO_LONG) \ +/** [1.1.1.11] */ /* FN(IMG_MISSING_ALT_BULLET) */ \ +/** [1.1.1.12] */ /* FN(IMG_MISSING_ALT_H_RULE) */ \ +/** [1.1.2.1] */ FN(IMG_MISSING_LONGDESC_DLINK) \ +/** [1.1.2.2] */ FN(IMG_MISSING_DLINK) \ +/** [1.1.2.3] */ FN(IMG_MISSING_LONGDESC) \ +/** [1.1.2.5] */ /* FN(LONGDESC_NOT_REQUIRED) */ \ +/** [1.1.3.1] */ FN(IMG_BUTTON_MISSING_ALT) \ +/** [1.1.4.1] */ FN(APPLET_MISSING_ALT) \ +/** [1.1.5.1] */ FN(OBJECT_MISSING_ALT) \ +/** [1.1.6.1] */ FN(AUDIO_MISSING_TEXT_WAV) \ +/** [1.1.6.2] */ FN(AUDIO_MISSING_TEXT_AU) \ +/** [1.1.6.3] */ FN(AUDIO_MISSING_TEXT_AIFF) \ +/** [1.1.6.4] */ FN(AUDIO_MISSING_TEXT_SND) \ +/** [1.1.6.5] */ FN(AUDIO_MISSING_TEXT_RA) \ +/** [1.1.6.6] */ FN(AUDIO_MISSING_TEXT_RM) \ +/** [1.1.8.1] */ FN(FRAME_MISSING_LONGDESC) \ +/** [1.1.9.1] */ FN(AREA_MISSING_ALT) \ +/** [1.1.10.1] */ FN(SCRIPT_MISSING_NOSCRIPT) \ +/** [1.1.12.1] */ FN(ASCII_REQUIRES_DESCRIPTION) \ +/** [1.2.1.1] */ FN(IMG_MAP_SERVER_REQUIRES_TEXT_LINKS) \ +/** [1.4.1.1] */ FN(MULTIMEDIA_REQUIRES_TEXT) \ +/** [1.5.1.1] */ FN(IMG_MAP_CLIENT_MISSING_TEXT_LINKS) \ +/** [2.1.1.1] */ FN(INFORMATION_NOT_CONVEYED_IMAGE) \ +/** [2.1.1.2] */ FN(INFORMATION_NOT_CONVEYED_APPLET) \ +/** [2.1.1.3] */ FN(INFORMATION_NOT_CONVEYED_OBJECT) \ +/** [2.1.1.4] */ FN(INFORMATION_NOT_CONVEYED_SCRIPT) \ +/** [2.1.1.5] */ FN(INFORMATION_NOT_CONVEYED_INPUT) \ +/** [2.2.1.1] */ FN(COLOR_CONTRAST_TEXT) \ +/** [2.2.1.2] */ FN(COLOR_CONTRAST_LINK) \ +/** [2.2.1.3] */ FN(COLOR_CONTRAST_ACTIVE_LINK) \ +/** [2.2.1.4] */ FN(COLOR_CONTRAST_VISITED_LINK) \ +/** [3.2.1.1] */ FN(DOCTYPE_MISSING) \ +/** [3.3.1.1] */ FN(STYLE_SHEET_CONTROL_PRESENTATION) \ +/** [3.5.1.1] */ FN(HEADERS_IMPROPERLY_NESTED) \ +/** [3.5.2.1] */ FN(POTENTIAL_HEADER_BOLD) \ +/** [3.5.2.2] */ FN(POTENTIAL_HEADER_ITALICS) \ +/** [3.5.2.3] */ FN(POTENTIAL_HEADER_UNDERLINE) \ +/** [3.5.3.1] */ FN(HEADER_USED_FORMAT_TEXT) \ +/** [3.6.1.1] */ FN(LIST_USAGE_INVALID_UL) \ +/** [3.6.1.2] */ FN(LIST_USAGE_INVALID_OL) \ +/** [3.6.1.4] */ FN(LIST_USAGE_INVALID_LI) \ +/** [4.1.1.1] */ /* FN(INDICATE_CHANGES_IN_LANGUAGE) */ \ +/** [4.3.1.1] */ FN(LANGUAGE_NOT_IDENTIFIED) \ +/** [4.3.1.1] */ FN(LANGUAGE_INVALID) \ +/** [5.1.2.1] */ FN(DATA_TABLE_MISSING_HEADERS) \ +/** [5.1.2.2] */ FN(DATA_TABLE_MISSING_HEADERS_COLUMN) \ +/** [5.1.2.3] */ FN(DATA_TABLE_MISSING_HEADERS_ROW) \ +/** [5.2.1.1] */ FN(DATA_TABLE_REQUIRE_MARKUP_COLUMN_HEADERS) \ +/** [5.2.1.2] */ FN(DATA_TABLE_REQUIRE_MARKUP_ROW_HEADERS) \ +/** [5.3.1.1] */ FN(LAYOUT_TABLES_LINEARIZE_PROPERLY) \ +/** [5.4.1.1] */ FN(LAYOUT_TABLE_INVALID_MARKUP) \ +/** [5.5.1.1] */ FN(TABLE_MISSING_SUMMARY) \ +/** [5.5.1.2] */ FN(TABLE_SUMMARY_INVALID_NULL) \ +/** [5.5.1.3] */ FN(TABLE_SUMMARY_INVALID_SPACES) \ +/** [5.5.1.6] */ FN(TABLE_SUMMARY_INVALID_PLACEHOLDER) \ +/** [5.5.2.1] */ FN(TABLE_MISSING_CAPTION) \ +/** [5.6.1.1] */ FN(TABLE_MAY_REQUIRE_HEADER_ABBR) \ +/** [5.6.1.2] */ FN(TABLE_MAY_REQUIRE_HEADER_ABBR_NULL) \ +/** [5.6.1.3] */ FN(TABLE_MAY_REQUIRE_HEADER_ABBR_SPACES) \ +/** [6.1.1.1] */ FN(STYLESHEETS_REQUIRE_TESTING_LINK) \ +/** [6.1.1.2] */ FN(STYLESHEETS_REQUIRE_TESTING_STYLE_ELEMENT) \ +/** [6.1.1.3] */ FN(STYLESHEETS_REQUIRE_TESTING_STYLE_ATTR) \ +/** [6.2.1.1] */ FN(FRAME_SRC_INVALID) \ +/** [6.2.2.1] */ FN(TEXT_EQUIVALENTS_REQUIRE_UPDATING_APPLET) \ +/** [6.2.2.2] */ FN(TEXT_EQUIVALENTS_REQUIRE_UPDATING_SCRIPT) \ +/** [6.2.2.3] */ FN(TEXT_EQUIVALENTS_REQUIRE_UPDATING_OBJECT) \ +/** [6.3.1.1] */ FN(PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_SCRIPT) \ +/** [6.3.1.2] */ FN(PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_OBJECT) \ +/** [6.3.1.3] */ FN(PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_EMBED) \ +/** [6.3.1.4] */ FN(PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_APPLET) \ +/** [6.5.1.1] */ FN(FRAME_MISSING_NOFRAMES) \ +/** [6.5.1.2] */ FN(NOFRAMES_INVALID_NO_VALUE) \ +/** [6.5.1.3] */ FN(NOFRAMES_INVALID_CONTENT) \ +/** [6.5.1.4] */ FN(NOFRAMES_INVALID_LINK) \ +/** [7.1.1.1] */ FN(REMOVE_FLICKER_SCRIPT) \ +/** [7.1.1.2] */ FN(REMOVE_FLICKER_OBJECT) \ +/** [7.1.1.3] */ FN(REMOVE_FLICKER_EMBED) \ +/** [7.1.1.4] */ FN(REMOVE_FLICKER_APPLET) \ +/** [7.1.1.5] */ FN(REMOVE_FLICKER_ANIMATED_GIF) \ +/** [7.2.1.1] */ FN(REMOVE_BLINK_MARQUEE) \ +/** [7.4.1.1] */ FN(REMOVE_AUTO_REFRESH) \ +/** [7.5.1.1] */ FN(REMOVE_AUTO_REDIRECT) \ +/** [8.1.1.1] */ FN(ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_SCRIPT) \ +/** [8.1.1.2] */ FN(ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_OBJECT) \ +/** [8.1.1.3] */ FN(ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_APPLET) \ +/** [8.1.1.4] */ FN(ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_EMBED) \ +/** [9.1.1.1] */ FN(IMAGE_MAP_SERVER_SIDE_REQUIRES_CONVERSION) \ +/** [9.3.1.1] */ FN(SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_DOWN) \ +/** [9.3.1.2] */ FN(SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_UP) \ +/** [9.3.1.3] */ FN(SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_CLICK) \ +/** [9.3.1.4] */ FN(SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_OVER) \ +/** [9.3.1.5] */ FN(SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_OUT) \ +/** [9.3.1.6] */ FN(SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_MOVE) \ +/** [10.1.1.1] */ FN(NEW_WINDOWS_REQUIRE_WARNING_NEW) \ +/** [10.1.1.2] */ FN(NEW_WINDOWS_REQUIRE_WARNING_BLANK) \ +/** [10.2.1.1] */ /* FN(LABEL_NEEDS_REPOSITIONING_BEFORE_INPUT) */ \ +/** [10.2.1.2] */ /* FN(LABEL_NEEDS_REPOSITIONING_AFTER_INPUT) */ \ +/** [10.4.1.1] */ /* FN(FORM_CONTROL_REQUIRES_DEFAULT_TEXT) */ \ +/** [10.4.1.2] */ /* FN(FORM_CONTROL_DEFAULT_TEXT_INVALID_NULL) */ \ +/** [10.4.1.3] */ /* FN(FORM_CONTROL_DEFAULT_TEXT_INVALID_SPACES) */ \ +/** [11.2.1.1] */ FN(REPLACE_DEPRECATED_HTML_APPLET) \ +/** [11.2.1.2] */ FN(REPLACE_DEPRECATED_HTML_BASEFONT) \ +/** [11.2.1.3] */ FN(REPLACE_DEPRECATED_HTML_CENTER) \ +/** [11.2.1.4] */ FN(REPLACE_DEPRECATED_HTML_DIR) \ +/** [11.2.1.5] */ FN(REPLACE_DEPRECATED_HTML_FONT) \ +/** [11.2.1.6] */ FN(REPLACE_DEPRECATED_HTML_ISINDEX) \ +/** [11.2.1.7] */ FN(REPLACE_DEPRECATED_HTML_MENU) \ +/** [11.2.1.8] */ FN(REPLACE_DEPRECATED_HTML_S) \ +/** [11.2.1.9] */ FN(REPLACE_DEPRECATED_HTML_STRIKE) \ +/** [11.2.1.10] */ FN(REPLACE_DEPRECATED_HTML_U) \ +/** [12.1.1.1] */ FN(FRAME_MISSING_TITLE) \ +/** [12.1.1.2] */ FN(FRAME_TITLE_INVALID_NULL) \ +/** [12.1.1.3] */ FN(FRAME_TITLE_INVALID_SPACES) \ +/** [12.4.1.1] */ FN(ASSOCIATE_LABELS_EXPLICITLY) \ +/** [12.4.1.2] */ FN(ASSOCIATE_LABELS_EXPLICITLY_FOR) \ +/** [12.4.1.3] */ FN(ASSOCIATE_LABELS_EXPLICITLY_ID) \ +/** [13.1.1.1] */ FN(LINK_TEXT_NOT_MEANINGFUL) \ +/** [13.1.1.2] */ FN(LINK_TEXT_MISSING) \ +/** [13.1.1.3] */ FN(LINK_TEXT_TOO_LONG) \ +/** [13.1.1.4] */ FN(LINK_TEXT_NOT_MEANINGFUL_CLICK_HERE) \ +/** [13.1.1.5] */ /* FN(LINK_TEXT_NOT_MEANINGFUL_MORE) */ \ +/** [13.1.1.6] */ /* FN(LINK_TEXT_NOT_MEANINGFUL_FOLLOW_THIS) */ \ +/** [13.2.1.1] */ FN(METADATA_MISSING) \ +/** [13.2.1.2] */ /* FN(METADATA_MISSING_LINK) */ \ +/** [13.2.1.3] */ FN(METADATA_MISSING_REDIRECT_AUTOREFRESH) \ +/** [13.10.1.1] */ FN(SKIPOVER_ASCII_ART) + + +/** These message codes comprise every message is exclusive to theTidy console + ** application. It it possible to build LibTidy without these strings. + */ +#if SUPPORT_CONSOLE_APP +#define FOREACH_MSG_CONSOLE(FN) \ + FN(TC_LABEL_COL) \ + FN(TC_LABEL_FILE) \ + FN(TC_LABEL_LANG) \ + FN(TC_LABEL_LEVL) \ + FN(TC_LABEL_OPT) \ + FN(TC_MAIN_ERROR_LOAD_CONFIG) \ + FN(TC_OPT_ACCESS) \ + FN(TC_OPT_ASCII) \ + FN(TC_OPT_ASHTML) \ + FN(TC_OPT_ASXML) \ + FN(TC_OPT_BARE) \ + FN(TC_OPT_BIG5) \ + FN(TC_OPT_CLEAN) \ + FN(TC_OPT_CONFIG) \ + FN(TC_OPT_ERRORS) \ + FN(TC_OPT_FILE) \ + FN(TC_OPT_GDOC) \ + FN(TC_OPT_HELP) \ + FN(TC_OPT_HELPCFG) \ + FN(TC_OPT_HELPENV) \ + FN(TC_OPT_HELPOPT) \ + FN(TC_OPT_IBM858) \ + FN(TC_OPT_INDENT) \ + FN(TC_OPT_ISO2022) \ + FN(TC_OPT_LANGUAGE) \ + FN(TC_OPT_LATIN0) \ + FN(TC_OPT_LATIN1) \ + FN(TC_OPT_MAC) \ + FN(TC_OPT_MODIFY) \ + FN(TC_OPT_NUMERIC) \ + FN(TC_OPT_OMIT) \ + FN(TC_OPT_OUTPUT) \ + FN(TC_OPT_QUIET) \ + FN(TC_OPT_RAW) \ + FN(TC_OPT_SHIFTJIS) \ + FN(TC_OPT_SHOWCFG) \ + FN(TC_OPT_EXP_CFG) \ + FN(TC_OPT_EXP_DEF) \ + FN(TC_OPT_UPPER) \ + FN(TC_OPT_UTF16) \ + FN(TC_OPT_UTF16BE) \ + FN(TC_OPT_UTF16LE) \ + FN(TC_OPT_UTF8) \ + FN(TC_OPT_VERSION) \ + FN(TC_OPT_WIN1252) \ + FN(TC_OPT_WRAP) \ + FN(TC_OPT_XML) \ + FN(TC_OPT_XMLCFG) \ + FN(TC_OPT_XMLSTRG) \ + FN(TC_OPT_XMLERRS) \ + FN(TC_OPT_XMLOPTS) \ + FN(TC_OPT_XMLHELP) \ + FN(TC_STRING_CONF_HEADER) \ + FN(TC_STRING_CONF_NAME) \ + FN(TC_STRING_CONF_TYPE) \ + FN(TC_STRING_CONF_VALUE) \ + FN(TC_STRING_CONF_NOTE) \ + FN(TC_STRING_OPT_NOT_DOCUMENTED) \ + FN(TC_STRING_OUT_OF_MEMORY) \ + FN(TC_STRING_FATAL_ERROR) \ + FN(TC_STRING_FILE_MANIP) \ + FN(TC_STRING_LANG_MUST_SPECIFY) \ + FN(TC_STRING_LANG_NOT_FOUND) \ + FN(TC_STRING_MUST_SPECIFY) \ + FN(TC_STRING_PROCESS_DIRECTIVES) \ + FN(TC_STRING_CHAR_ENCODING) \ + FN(TC_STRING_MISC) \ + FN(TC_STRING_XML) \ + FN(TC_STRING_UNKNOWN_OPTION) \ + FN(TC_STRING_UNKNOWN_OPTION_B) \ + FN(TC_STRING_VERS_A) \ + FN(TC_STRING_VERS_B) \ + FN(TC_TXT_HELP_1) \ + FN(TC_TXT_HELP_2A) \ + FN(TC_TXT_HELP_2B) \ + FN(TC_TXT_HELP_3) \ + FN(TC_TXT_HELP_3A) \ + FN(TC_TXT_HELP_CONFIG) \ + FN(TC_TXT_HELP_CONFIG_NAME) \ + FN(TC_TXT_HELP_CONFIG_TYPE) \ + FN(TC_TXT_HELP_CONFIG_ALLW) \ + FN(TC_TXT_HELP_ENV_1) \ + FN(TC_TXT_HELP_ENV_1A) \ + FN(TC_TXT_HELP_ENV_1B) \ + FN(TC_TXT_HELP_ENV_1C) \ + FN(TC_TXT_HELP_LANG_1) \ + FN(TC_TXT_HELP_LANG_2) \ + FN(TC_TXT_HELP_LANG_3) +#endif /* SUPPORT_CONSOLE_APP */ + +/** @} */ + +/** @} end group public_enum_gen */ + + +/* MARK: - Public Enumerations */ +/***************************************************************************//** + ** @defgroup public_enumerations Public Enumerations + ** @ingroup public_api + ** + ** @copybrief tidyenum.h + ******************************************************************************/ + +/** @addtogroup public_enumerations + ** @{ */ + +/** @name Configuration Options Enumerations + ** + ** These enumerators are used to define available configuration options and + ** their option categories. + ** + ** @{ */ + + +/** Option IDs are used used to get and/or set configuration option values and + ** retrieve their descriptions. + ** + ** @remark These enum members all have associated localized strings available + ** which describe the purpose of the option. These descriptions are + ** available via their enum values only. + ** + ** @sa `config.c:option_defs[]` for internal implementation details; that + ** array is where you will implement options defined in this enum; and + ** it's important to add a string describing the option to + ** `language_en.h`, too. + */ +typedef enum +{ + TidyUnknownOption = 0, /**< Unknown option! */ + + TidyAccessibilityCheckLevel, /**< Accessibility check level */ + TidyAltText, /**< Default text for alt attribute */ + TidyAnchorAsName, /**< Define anchors as name attributes */ + TidyAsciiChars, /**< Convert quotes and dashes to nearest ASCII char */ + TidyBlockTags, /**< Declared block tags */ + TidyBodyOnly, /**< Output BODY content only */ + TidyBreakBeforeBR, /**< Output newline before
or not? */ + TidyCharEncoding, /**< In/out character encoding */ + TidyCoerceEndTags, /**< Coerce end tags from start tags where probably intended */ + TidyCSSPrefix, /**< CSS class naming for clean option */ +#ifndef DOXYGEN_SHOULD_SKIP_THIS + TidyCustomTags, /**< Internal use ONLY */ +#endif + TidyDecorateInferredUL, /**< Mark inferred UL elements with no indent CSS */ + TidyDoctype, /**< User specified doctype */ +#ifndef DOXYGEN_SHOULD_SKIP_THIS + TidyDoctypeMode, /**< Internal use ONLY */ +#endif + TidyDropEmptyElems, /**< Discard empty elements */ + TidyDropEmptyParas, /**< Discard empty p elements */ + TidyDropPropAttrs, /**< Discard proprietary attributes */ + TidyDuplicateAttrs, /**< Keep first or last duplicate attribute */ + TidyEmacs, /**< If true, format error output for GNU Emacs */ +#ifndef DOXYGEN_SHOULD_SKIP_THIS + TidyEmacsFile, /**< Internal use ONLY */ +#endif + TidyEmptyTags, /**< Declared empty tags */ + TidyEncloseBlockText, /**< If yes text in blocks is wrapped in P's */ + TidyEncloseBodyText, /**< If yes text at body is wrapped in P's */ + TidyErrFile, /**< File name to write errors to */ + TidyEscapeCdata, /**< Replace sections with escaped text */ + TidyEscapeScripts, /**< Escape items that look like closing tags in script tags */ + TidyFixBackslash, /**< Fix URLs by replacing \ with / */ + TidyFixComments, /**< Fix comments with adjacent hyphens */ + TidyFixUri, /**< Applies URI encoding if necessary */ + TidyForceOutput, /**< Output document even if errors were found */ + TidyGDocClean, /**< Clean up HTML exported from Google Docs */ + TidyHideComments, /**< Hides all (real) comments in output */ + TidyHtmlOut, /**< Output plain HTML, even for XHTML input.*/ + TidyInCharEncoding, /**< Input character encoding (if different) */ + TidyIndentAttributes, /**< Newline+indent before each attribute */ + TidyIndentCdata, /**< Indent section */ + TidyIndentContent, /**< Indent content of appropriate tags */ + TidyIndentSpaces, /**< Indentation n spaces/tabs */ + TidyInlineTags, /**< Declared inline tags */ + TidyJoinClasses, /**< Join multiple class attributes */ + TidyJoinStyles, /**< Join multiple style attributes */ + TidyKeepFileTimes, /**< If yes last modied time is preserved */ + TidyKeepTabs, /**< If yes keep input source tabs */ + TidyLiteralAttribs, /**< If true attributes may use newlines */ + TidyLogicalEmphasis, /**< Replace i by em and b by strong */ + TidyLowerLiterals, /**< Folds known attribute values to lower case */ + TidyMakeBare, /**< Replace smart quotes, em dashes, etc with ASCII */ + TidyMakeClean, /**< Replace presentational clutter by style rules */ + TidyMark, /**< Add meta element indicating tidied doc */ + TidyMergeDivs, /**< Merge multiple DIVs */ + TidyMergeEmphasis, /**< Merge nested B and I elements */ + TidyMergeSpans, /**< Merge multiple SPANs */ + TidyMetaCharset, /**< Adds/checks/fixes meta charset in the head, based on document type */ + TidyMuteReports, /**< Filter these messages from output. */ + TidyMuteShow, /**< Show message ID's in the error table */ + TidyNCR, /**< Allow numeric character references */ + TidyNewline, /**< Output line ending (default to platform) */ + TidyNumEntities, /**< Use numeric entities */ + TidyOmitOptionalTags, /**< Suppress optional start tags and end tags */ + TidyOutCharEncoding, /**< Output character encoding (if different) */ + TidyOutFile, /**< File name to write markup to */ + TidyOutputBOM, /**< Output a Byte Order Mark (BOM) for UTF-16 encodings */ + TidyPPrintTabs, /**< Indent using tabs instead of spaces */ + TidyPreserveEntities, /**< Preserve entities */ + TidyPreTags, /**< Declared pre tags */ + TidyPriorityAttributes, /**< Attributes to place first in an element */ + TidyPunctWrap, /**< consider punctuation and breaking spaces for wrapping */ + TidyQuiet, /**< No 'Parsing X', guessed DTD or summary */ + TidyQuoteAmpersand, /**< Output naked ampersand as & */ + TidyQuoteMarks, /**< Output " marks as " */ + TidyQuoteNbsp, /**< Output non-breaking space as entity */ + TidyReplaceColor, /**< Replace hex color attribute values with names */ + TidyShowErrors, /**< Number of errors to put out */ + TidyShowFilename, /**< If true, the input filename is displayed with the error messages */ + TidyShowInfo, /**< If true, info-level messages are shown */ + TidyShowMarkup, /**< If false, normal output is suppressed */ + TidyShowMetaChange, /**< show when meta http-equiv content charset was changed - compatibility */ + TidyShowWarnings, /**< However errors are always shown */ + TidySkipNested, /**< Skip nested tags in script and style CDATA */ + TidySortAttributes, /**< Sort attributes */ + TidyStrictTagsAttr, /**< Ensure tags and attributes match output HTML version */ + TidyStyleTags, /**< Move style to head */ + TidyTabSize, /**< Expand tabs to n spaces */ + TidyUpperCaseAttrs, /**< Output attributes in upper not lower case */ + TidyUpperCaseTags, /**< Output tags in upper not lower case */ + TidyUseCustomTags, /**< Enable Tidy to use autonomous custom tags */ + TidyVertSpace, /**< degree to which markup is spread out vertically */ + TidyWarnPropAttrs, /**< Warns on proprietary attributes */ + TidyWord2000, /**< Draconian cleaning for Word2000 */ + TidyWrapAsp, /**< Wrap within ASP pseudo elements */ + TidyWrapAttVals, /**< Wrap within attribute values */ + TidyWrapJste, /**< Wrap within JSTE pseudo elements */ + TidyWrapLen, /**< Wrap margin */ + TidyWrapPhp, /**< Wrap consecutive PHP pseudo elements */ + TidyWrapScriptlets, /**< Wrap within JavaScript string literals */ + TidyWrapSection, /**< Wrap within section tags */ + TidyWriteBack, /**< If true then output tidied markup */ + TidyXhtmlOut, /**< Output extensible HTML */ + TidyXmlDecl, /**< Add for XML docs */ + TidyXmlOut, /**< Create output as XML */ + TidyXmlPIs, /**< If set to yes PIs must end with ?> */ + TidyXmlSpace, /**< If set to yes adds xml:space attr as needed */ + TidyXmlTags, /**< Treat input as XML */ + N_TIDY_OPTIONS /**< Must be last */ +} TidyOptionId; + + +/** Categories of Tidy configuration options, which are used mostly by user + ** interfaces to sort Tidy options into related groups. + ** + ** @remark These enum members all have associated localized strings available + ** suitable for use as a category label, and are available with either + ** the enum value, or a string version of the name. + ** + ** @sa `config.c:option_defs[]` for internal implementation details. + */ +typedef enum +{ + TidyUnknownCategory = 300, /**< Unknown Category! */ + FOREACH_TIDYCONFIGCATEGORY(MAKE_ENUM) +} TidyConfigCategory; + + +/** A Tidy configuration option can have one of these data types. */ +typedef enum +{ + TidyString, /**< String */ + TidyInteger, /**< Integer or enumeration */ + TidyBoolean /**< Boolean */ +} TidyOptionType; + + +/** @} + ** @name Configuration Options Pick List and Parser Enumerations + ** + ** These enums define enumerated states for the configuration options that + ** take values that are not simple yes/no, strings, or simple integers. + ** + ** @{ */ + +/** AutoBool values used by ParseBool, ParseTriState, ParseIndent, ParseBOM + ** @remark This enum's starting value is guaranteed to remain stable. + */ +typedef enum +{ + TidyNoState = 0, /**< maps to 'no' */ + TidyYesState, /**< maps to 'yes' */ + TidyAutoState /**< Automatic */ +} TidyTriState; + + +/** Values used by ParseUseCustomTags, which describes how Autonomous Custom + ** tags (ACT's) found by Tidy are treated. + ** + ** @remark These enum members all have associated localized strings available + ** for internal LibTidy use, and also have public string keys in the + ** form MEMBER_STRING, e.g., TIDYCUSTOMBLOCKLEVEL_STRING + ** + ** @remark This enum's starting value is guaranteed to remain stable. + */ +typedef enum +{ + TidyCustomNo = 0, /**< Do not allow autonomous custom tags */ + TidyCustomBlocklevel, /**< ACT's treated as blocklevel */ + TidyCustomEmpty, /**< ACT's treated as empty tags */ + TidyCustomInline, /**< ACT's treated as inline tags */ + TidyCustomPre /**< ACT's treated as pre tags */ +} TidyUseCustomTagsState; + + +/** TidyNewline option values to control output line endings. + ** @remark This enum's starting value is guaranteed to remain stable. + */ +typedef enum +{ + TidyLF = 0, /**< Use Unix style: LF */ + TidyCRLF, /**< Use DOS/Windows style: CR+LF */ + TidyCR /**< Use Macintosh style: CR */ +} TidyLineEnding; + + +/** TidyEncodingOptions option values specify the input and/or output encoding. + ** @remark This enum's starting value is guaranteed to remain stable. + */ +typedef enum +{ + TidyEncRaw = 0, + TidyEncAscii, + TidyEncLatin0, + TidyEncLatin1, + TidyEncUtf8, +#ifndef NO_NATIVE_ISO2022_SUPPORT + TidyEncIso2022, +#endif + TidyEncMac, + TidyEncWin1252, + TidyEncIbm858, + TidyEncUtf16le, + TidyEncUtf16be, + TidyEncUtf16, + TidyEncBig5, + TidyEncShiftjis +} TidyEncodingOptions; + + +/** Mode controlling treatment of doctype + ** @remark This enum's starting value is guaranteed to remain stable. + */ +typedef enum +{ + TidyDoctypeHtml5 = 0, /**< */ + TidyDoctypeOmit, /**< Omit DOCTYPE altogether */ + TidyDoctypeAuto, /**< Keep DOCTYPE in input. Set version to content */ + TidyDoctypeStrict, /**< Convert document to HTML 4 strict content model */ + TidyDoctypeLoose, /**< Convert document to HTML 4 transitional content model */ + TidyDoctypeUser /**< Set DOCTYPE FPI explicitly */ +} TidyDoctypeModes; + +/** Mode controlling treatment of duplicate Attributes + ** @remark This enum's starting value is guaranteed to remain stable. + */ +typedef enum +{ + TidyKeepFirst = 0, /**< Keep the first instance of an attribute */ + TidyKeepLast /**< Keep the last instance of an attribute */ +} TidyDupAttrModes; + +/** Mode controlling treatment of sorting attributes + ** @remark This enum's starting value is guaranteed to remain stable. + */ +typedef enum +{ + TidySortAttrNone = 0, /**< Don't sort attributes */ + TidySortAttrAlpha /**< Sort attributes alphabetically */ +} TidyAttrSortStrategy; + +/** Mode controlling capitalization of things, such as attributes. + ** @remark This enum's starting value is guaranteed to remain stable. + */ +typedef enum +{ + TidyUppercaseNo = 0, /**< Don't uppercase. */ + TidyUppercaseYes, /**< Do uppercase. */ + TidyUppercasePreserve /**< Preserve case. */ +} TidyUppercase; + + +/** @} + ** @name Document Tree + ** @{ + */ + +/** Node types + */ +typedef enum +{ + TidyNode_Root, /**< Root */ + TidyNode_DocType, /**< DOCTYPE */ + TidyNode_Comment, /**< Comment */ + TidyNode_ProcIns, /**< Processing Instruction */ + TidyNode_Text, /**< Text */ + TidyNode_Start, /**< Start Tag */ + TidyNode_End, /**< End Tag */ + TidyNode_StartEnd, /**< Start/End (empty) Tag */ + TidyNode_CDATA, /**< Unparsed Text */ + TidyNode_Section, /**< XML Section */ + TidyNode_Asp, /**< ASP Source */ + TidyNode_Jste, /**< JSTE Source */ + TidyNode_Php, /**< PHP Source */ + TidyNode_XmlDecl /**< XML Declaration */ +} TidyNodeType; + + +/** Known HTML element types + */ +typedef enum +{ + TidyTag_UNKNOWN, /**< Unknown tag! Must be first */ + TidyTag_A, /**< A */ + TidyTag_ABBR, /**< ABBR */ + TidyTag_ACRONYM, /**< ACRONYM */ + TidyTag_ADDRESS, /**< ADDRESS */ + TidyTag_ALIGN, /**< ALIGN */ + TidyTag_APPLET, /**< APPLET */ + TidyTag_AREA, /**< AREA */ + TidyTag_B, /**< B */ + TidyTag_BASE, /**< BASE */ + TidyTag_BASEFONT, /**< BASEFONT */ + TidyTag_BDO, /**< BDO */ + TidyTag_BGSOUND, /**< BGSOUND */ + TidyTag_BIG, /**< BIG */ + TidyTag_BLINK, /**< BLINK */ + TidyTag_BLOCKQUOTE, /**< BLOCKQUOTE */ + TidyTag_BODY, /**< BODY */ + TidyTag_BR, /**< BR */ + TidyTag_BUTTON, /**< BUTTON */ + TidyTag_CAPTION, /**< CAPTION */ + TidyTag_CENTER, /**< CENTER */ + TidyTag_CITE, /**< CITE */ + TidyTag_CODE, /**< CODE */ + TidyTag_COL, /**< COL */ + TidyTag_COLGROUP, /**< COLGROUP */ + TidyTag_COMMENT, /**< COMMENT */ + TidyTag_DD, /**< DD */ + TidyTag_DEL, /**< DEL */ + TidyTag_DFN, /**< DFN */ + TidyTag_DIR, /**< DIR */ + TidyTag_DIV, /**< DIF */ + TidyTag_DL, /**< DL */ + TidyTag_DT, /**< DT */ + TidyTag_EM, /**< EM */ + TidyTag_EMBED, /**< EMBED */ + TidyTag_FIELDSET, /**< FIELDSET */ + TidyTag_FONT, /**< FONT */ + TidyTag_FORM, /**< FORM */ + TidyTag_FRAME, /**< FRAME */ + TidyTag_FRAMESET, /**< FRAMESET */ + TidyTag_H1, /**< H1 */ + TidyTag_H2, /**< H2 */ + TidyTag_H3, /**< H3 */ + TidyTag_H4, /**< H4 */ + TidyTag_H5, /**< H5 */ + TidyTag_H6, /**< H6 */ + TidyTag_HEAD, /**< HEAD */ + TidyTag_HR, /**< HR */ + TidyTag_HTML, /**< HTML */ + TidyTag_I, /**< I */ + TidyTag_IFRAME, /**< IFRAME */ + TidyTag_ILAYER, /**< ILAYER */ + TidyTag_IMG, /**< IMG */ + TidyTag_INPUT, /**< INPUT */ + TidyTag_INS, /**< INS */ + TidyTag_ISINDEX, /**< ISINDEX */ + TidyTag_KBD, /**< KBD */ + TidyTag_KEYGEN, /**< KEYGEN */ + TidyTag_LABEL, /**< LABEL */ + TidyTag_LAYER, /**< LAYER */ + TidyTag_LEGEND, /**< LEGEND */ + TidyTag_LI, /**< LI */ + TidyTag_LINK, /**< LINK */ + TidyTag_LISTING, /**< LISTING */ + TidyTag_MAP, /**< MAP */ + TidyTag_MATHML, /**< MATH (HTML5) [i_a]2 MathML embedded in [X]HTML */ + TidyTag_MARQUEE, /**< MARQUEE */ + TidyTag_MENU, /**< MENU */ + TidyTag_META, /**< META */ + TidyTag_MULTICOL, /**< MULTICOL */ + TidyTag_NOBR, /**< NOBR */ + TidyTag_NOEMBED, /**< NOEMBED */ + TidyTag_NOFRAMES, /**< NOFRAMES */ + TidyTag_NOLAYER, /**< NOLAYER */ + TidyTag_NOSAVE, /**< NOSAVE */ + TidyTag_NOSCRIPT, /**< NOSCRIPT */ + TidyTag_OBJECT, /**< OBJECT */ + TidyTag_OL, /**< OL */ + TidyTag_OPTGROUP, /**< OPTGROUP */ + TidyTag_OPTION, /**< OPTION */ + TidyTag_P, /**< P */ + TidyTag_PARAM, /**< PARAM */ + TidyTag_PICTURE, /**< PICTURE (HTML5) */ + TidyTag_PLAINTEXT, /**< PLAINTEXT */ + TidyTag_PRE, /**< PRE */ + TidyTag_Q, /**< Q */ + TidyTag_RB, /**< RB */ + TidyTag_RBC, /**< RBC */ + TidyTag_RP, /**< RP */ + TidyTag_RT, /**< RT */ + TidyTag_RTC, /**< RTC */ + TidyTag_RUBY, /**< RUBY */ + TidyTag_S, /**< S */ + TidyTag_SAMP, /**< SAMP */ + TidyTag_SCRIPT, /**< SCRIPT */ + TidyTag_SELECT, /**< SELECT */ + TidyTag_SERVER, /**< SERVER */ + TidyTag_SERVLET, /**< SERVLET */ + TidyTag_SMALL, /**< SMALL */ + TidyTag_SPACER, /**< SPACER */ + TidyTag_SPAN, /**< SPAN */ + TidyTag_STRIKE, /**< STRIKE */ + TidyTag_STRONG, /**< STRONG */ + TidyTag_STYLE, /**< STYLE */ + TidyTag_SUB, /**< SUB */ + TidyTag_SUP, /**< SUP */ + TidyTag_SVG, /**< SVG (HTML5) */ + TidyTag_TABLE, /**< TABLE */ + TidyTag_TBODY, /**< TBODY */ + TidyTag_TD, /**< TD */ + TidyTag_TEXTAREA, /**< TEXTAREA */ + TidyTag_TFOOT, /**< TFOOT */ + TidyTag_TH, /**< TH */ + TidyTag_THEAD, /**< THEAD */ + TidyTag_TITLE, /**< TITLE */ + TidyTag_TR, /**< TR */ + TidyTag_TT, /**< TT */ + TidyTag_U, /**< U */ + TidyTag_UL, /**< UL */ + TidyTag_VAR, /**< VAR */ + TidyTag_WBR, /**< WBR */ + TidyTag_XMP, /**< XMP */ + TidyTag_NEXTID, /**< NEXTID */ + + TidyTag_ARTICLE, /**< ARTICLE */ + TidyTag_ASIDE, /**< ASIDE */ + TidyTag_AUDIO, /**< AUDIO */ + TidyTag_BDI, /**< BDI */ + TidyTag_CANVAS, /**< CANVAS */ + TidyTag_COMMAND, /**< COMMAND */ + TidyTag_DATA, /**< DATA */ + TidyTag_DATALIST, /**< DATALIST */ + TidyTag_DETAILS, /**< DETAILS */ + TidyTag_DIALOG, /**< DIALOG */ + TidyTag_FIGCAPTION, /**< FIGCAPTION */ + TidyTag_FIGURE, /**< FIGURE */ + TidyTag_FOOTER, /**< FOOTER */ + TidyTag_HEADER, /**< HEADER */ + TidyTag_HGROUP, /**< HGROUP */ + TidyTag_MAIN, /**< MAIN */ + TidyTag_MARK, /**< MARK */ + TidyTag_MENUITEM, /**< MENUITEM */ + TidyTag_METER, /**< METER */ + TidyTag_NAV, /**< NAV */ + TidyTag_OUTPUT, /**< OUTPUT */ + TidyTag_PROGRESS, /**< PROGRESS */ + TidyTag_SECTION, /**< SECTION */ + TidyTag_SOURCE, /**< SOURCE */ + TidyTag_SUMMARY, /**< SUMMARY */ + TidyTag_TEMPLATE, /**< TEMPLATE */ + TidyTag_TIME, /**< TIME */ + TidyTag_TRACK, /**< TRACK */ + TidyTag_VIDEO, /**< VIDEO */ + TidyTag_SLOT, /**< SLOT */ + + N_TIDY_TAGS /**< Must be last */ +} TidyTagId; + + +/** Known HTML attributes + */ +typedef enum +{ + TidyAttr_UNKNOWN, /**< UNKNOWN= */ + TidyAttr_ABBR, /**< ABBR= */ + TidyAttr_ACCEPT, /**< ACCEPT= */ + TidyAttr_ACCEPT_CHARSET, /**< ACCEPT_CHARSET= */ + TidyAttr_ACCESSKEY, /**< ACCESSKEY= */ + TidyAttr_ACTION, /**< ACTION= */ + TidyAttr_ADD_DATE, /**< ADD_DATE= */ + TidyAttr_ALIGN, /**< ALIGN= */ + TidyAttr_ALINK, /**< ALINK= */ + TidyAttr_ALLOWFULLSCREEN, /**< ALLOWFULLSCREEN= */ + TidyAttr_ALT, /**< ALT= */ + TidyAttr_ARCHIVE, /**< ARCHIVE= */ + TidyAttr_AXIS, /**< AXIS= */ + TidyAttr_BACKGROUND, /**< BACKGROUND= */ + TidyAttr_BGCOLOR, /**< BGCOLOR= */ + TidyAttr_BGPROPERTIES, /**< BGPROPERTIES= */ + TidyAttr_BORDER, /**< BORDER= */ + TidyAttr_BORDERCOLOR, /**< BORDERCOLOR= */ + TidyAttr_BOTTOMMARGIN, /**< BOTTOMMARGIN= */ + TidyAttr_CELLPADDING, /**< CELLPADDING= */ + TidyAttr_CELLSPACING, /**< CELLSPACING= */ + TidyAttr_CHAR, /**< CHAR= */ + TidyAttr_CHAROFF, /**< CHAROFF= */ + TidyAttr_CHARSET, /**< CHARSET= */ + TidyAttr_CHECKED, /**< CHECKED= */ + TidyAttr_CITE, /**< CITE= */ + TidyAttr_CLASS, /**< CLASS= */ + TidyAttr_CLASSID, /**< CLASSID= */ + TidyAttr_CLEAR, /**< CLEAR= */ + TidyAttr_CODE, /**< CODE= */ + TidyAttr_CODEBASE, /**< CODEBASE= */ + TidyAttr_CODETYPE, /**< CODETYPE= */ + TidyAttr_COLOR, /**< COLOR= */ + TidyAttr_COLS, /**< COLS= */ + TidyAttr_COLSPAN, /**< COLSPAN= */ + TidyAttr_COMPACT, /**< COMPACT= */ + TidyAttr_CONTENT, /**< CONTENT= */ + TidyAttr_COORDS, /**< COORDS= */ + TidyAttr_DATA, /**< DATA= */ + TidyAttr_DATAFLD, /**< DATAFLD= */ + TidyAttr_DATAFORMATAS, /**< DATAFORMATAS= */ + TidyAttr_DATAPAGESIZE, /**< DATAPAGESIZE= */ + TidyAttr_DATASRC, /**< DATASRC= */ + TidyAttr_DATETIME, /**< DATETIME= */ + TidyAttr_DECLARE, /**< DECLARE= */ + TidyAttr_DEFER, /**< DEFER= */ + TidyAttr_DIR, /**< DIR= */ + TidyAttr_DISABLED, /**< DISABLED= */ + TidyAttr_DOWNLOAD, /**< DOWNLOAD= */ + TidyAttr_ENCODING, /**< ENCODING= */ + TidyAttr_ENCTYPE, /**< ENCTYPE= */ + TidyAttr_FACE, /**< FACE= */ + TidyAttr_FOR, /**< FOR= */ + TidyAttr_FRAME, /**< FRAME= */ + TidyAttr_FRAMEBORDER, /**< FRAMEBORDER= */ + TidyAttr_FRAMESPACING, /**< FRAMESPACING= */ + TidyAttr_GRIDX, /**< GRIDX= */ + TidyAttr_GRIDY, /**< GRIDY= */ + TidyAttr_HEADERS, /**< HEADERS= */ + TidyAttr_HEIGHT, /**< HEIGHT= */ + TidyAttr_HREF, /**< HREF= */ + TidyAttr_HREFLANG, /**< HREFLANG= */ + TidyAttr_HSPACE, /**< HSPACE= */ + TidyAttr_HTTP_EQUIV, /**< HTTP_EQUIV= */ + TidyAttr_ID, /**< ID= */ + TidyAttr_IS, /**< IS= */ + TidyAttr_ISMAP, /**< ISMAP= */ + TidyAttr_ITEMID, /**< ITEMID= */ + TidyAttr_ITEMPROP, /**< ITEMPROP= */ + TidyAttr_ITEMREF, /**< ITEMREF= */ + TidyAttr_ITEMSCOPE, /**< ITEMSCOPE= */ + TidyAttr_ITEMTYPE, /**< ITEMTYPE= */ + TidyAttr_LABEL, /**< LABEL= */ + TidyAttr_LANG, /**< LANG= */ + TidyAttr_LANGUAGE, /**< LANGUAGE= */ + TidyAttr_LAST_MODIFIED, /**< LAST_MODIFIED= */ + TidyAttr_LAST_VISIT, /**< LAST_VISIT= */ + TidyAttr_LEFTMARGIN, /**< LEFTMARGIN= */ + TidyAttr_LINK, /**< LINK= */ + TidyAttr_LONGDESC, /**< LONGDESC= */ + TidyAttr_LOWSRC, /**< LOWSRC= */ + TidyAttr_MARGINHEIGHT, /**< MARGINHEIGHT= */ + TidyAttr_MARGINWIDTH, /**< MARGINWIDTH= */ + TidyAttr_MAXLENGTH, /**< MAXLENGTH= */ + TidyAttr_MEDIA, /**< MEDIA= */ + TidyAttr_METHOD, /**< METHOD= */ + TidyAttr_MULTIPLE, /**< MULTIPLE= */ + TidyAttr_NAME, /**< NAME= */ + TidyAttr_NOHREF, /**< NOHREF= */ + TidyAttr_NORESIZE, /**< NORESIZE= */ + TidyAttr_NOSHADE, /**< NOSHADE= */ + TidyAttr_NOWRAP, /**< NOWRAP= */ + TidyAttr_OBJECT, /**< OBJECT= */ + TidyAttr_OnAFTERUPDATE, /**< OnAFTERUPDATE= */ + TidyAttr_OnBEFOREUNLOAD, /**< OnBEFOREUNLOAD= */ + TidyAttr_OnBEFOREUPDATE, /**< OnBEFOREUPDATE= */ + TidyAttr_OnBLUR, /**< OnBLUR= */ + TidyAttr_OnCHANGE, /**< OnCHANGE= */ + TidyAttr_OnCLICK, /**< OnCLICK= */ + TidyAttr_OnDATAAVAILABLE, /**< OnDATAAVAILABLE= */ + TidyAttr_OnDATASETCHANGED, /**< OnDATASETCHANGED= */ + TidyAttr_OnDATASETCOMPLETE, /**< OnDATASETCOMPLETE= */ + TidyAttr_OnDBLCLICK, /**< OnDBLCLICK= */ + TidyAttr_OnERRORUPDATE, /**< OnERRORUPDATE= */ + TidyAttr_OnFOCUS, /**< OnFOCUS= */ + TidyAttr_OnKEYDOWN, /**< OnKEYDOWN= */ + TidyAttr_OnKEYPRESS, /**< OnKEYPRESS= */ + TidyAttr_OnKEYUP, /**< OnKEYUP= */ + TidyAttr_OnLOAD, /**< OnLOAD= */ + TidyAttr_OnMOUSEDOWN, /**< OnMOUSEDOWN= */ + TidyAttr_OnMOUSEMOVE, /**< OnMOUSEMOVE= */ + TidyAttr_OnMOUSEOUT, /**< OnMOUSEOUT= */ + TidyAttr_OnMOUSEOVER, /**< OnMOUSEOVER= */ + TidyAttr_OnMOUSEUP, /**< OnMOUSEUP= */ + TidyAttr_OnRESET, /**< OnRESET= */ + TidyAttr_OnROWENTER, /**< OnROWENTER= */ + TidyAttr_OnROWEXIT, /**< OnROWEXIT= */ + TidyAttr_OnSELECT, /**< OnSELECT= */ + TidyAttr_OnSUBMIT, /**< OnSUBMIT= */ + TidyAttr_OnUNLOAD, /**< OnUNLOAD= */ + TidyAttr_PROFILE, /**< PROFILE= */ + TidyAttr_PROMPT, /**< PROMPT= */ + TidyAttr_RBSPAN, /**< RBSPAN= */ + TidyAttr_READONLY, /**< READONLY= */ + TidyAttr_REL, /**< REL= */ + TidyAttr_REV, /**< REV= */ + TidyAttr_RIGHTMARGIN, /**< RIGHTMARGIN= */ + TidyAttr_ROLE, /**< ROLE= */ + TidyAttr_ROWS, /**< ROWS= */ + TidyAttr_ROWSPAN, /**< ROWSPAN= */ + TidyAttr_RULES, /**< RULES= */ + TidyAttr_SCHEME, /**< SCHEME= */ + TidyAttr_SCOPE, /**< SCOPE= */ + TidyAttr_SCROLLING, /**< SCROLLING= */ + TidyAttr_SELECTED, /**< SELECTED= */ + TidyAttr_SHAPE, /**< SHAPE= */ + TidyAttr_SHOWGRID, /**< SHOWGRID= */ + TidyAttr_SHOWGRIDX, /**< SHOWGRIDX= */ + TidyAttr_SHOWGRIDY, /**< SHOWGRIDY= */ + TidyAttr_SIZE, /**< SIZE= */ + TidyAttr_SPAN, /**< SPAN= */ + TidyAttr_SRC, /**< SRC= */ + TidyAttr_SRCSET, /**< SRCSET= (HTML5) */ + TidyAttr_STANDBY, /**< STANDBY= */ + TidyAttr_START, /**< START= */ + TidyAttr_STYLE, /**< STYLE= */ + TidyAttr_SUMMARY, /**< SUMMARY= */ + TidyAttr_TABINDEX, /**< TABINDEX= */ + TidyAttr_TARGET, /**< TARGET= */ + TidyAttr_TEXT, /**< TEXT= */ + TidyAttr_TITLE, /**< TITLE= */ + TidyAttr_TOPMARGIN, /**< TOPMARGIN= */ + TidyAttr_TRANSLATE, /**< TRANSLATE= */ + TidyAttr_TYPE, /**< TYPE= */ + TidyAttr_USEMAP, /**< USEMAP= */ + TidyAttr_VALIGN, /**< VALIGN= */ + TidyAttr_VALUE, /**< VALUE= */ + TidyAttr_VALUETYPE, /**< VALUETYPE= */ + TidyAttr_VERSION, /**< VERSION= */ + TidyAttr_VLINK, /**< VLINK= */ + TidyAttr_VSPACE, /**< VSPACE= */ + TidyAttr_WIDTH, /**< WIDTH= */ + TidyAttr_WRAP, /**< WRAP= */ + TidyAttr_XML_LANG, /**< XML_LANG= */ + TidyAttr_XML_SPACE, /**< XML_SPACE= */ + TidyAttr_XMLNS, /**< XMLNS= */ + + TidyAttr_EVENT, /**< EVENT= */ + TidyAttr_METHODS, /**< METHODS= */ + TidyAttr_N, /**< N= */ + TidyAttr_SDAFORM, /**< SDAFORM= */ + TidyAttr_SDAPREF, /**< SDAPREF= */ + TidyAttr_SDASUFF, /**< SDASUFF= */ + TidyAttr_URN, /**< URN= */ + + TidyAttr_ASYNC, /**< ASYNC= */ + TidyAttr_AUTOCOMPLETE, /**< AUTOCOMPLETE= */ + TidyAttr_AUTOFOCUS, /**< AUTOFOCUS= */ + TidyAttr_AUTOPLAY, /**< AUTOPLAY= */ + TidyAttr_CHALLENGE, /**< CHALLENGE= */ + TidyAttr_CONTENTEDITABLE, /**< CONTENTEDITABLE= */ + TidyAttr_CONTEXTMENU, /**< CONTEXTMENU= */ + TidyAttr_CONTROLS, /**< CONTROLS= */ + TidyAttr_CROSSORIGIN, /**< CROSSORIGIN= */ + TidyAttr_DEFAULT, /**< DEFAULT= */ + TidyAttr_DIRNAME, /**< DIRNAME= */ + TidyAttr_DRAGGABLE, /**< DRAGGABLE= */ + TidyAttr_DROPZONE, /**< DROPZONE= */ + TidyAttr_FORM, /**< FORM= */ + TidyAttr_FORMACTION, /**< FORMACTION= */ + TidyAttr_FORMENCTYPE, /**< FORMENCTYPE= */ + TidyAttr_FORMMETHOD, /**< FORMMETHOD= */ + TidyAttr_FORMNOVALIDATE, /**< FORMNOVALIDATE= */ + TidyAttr_FORMTARGET, /**< FORMTARGET= */ + TidyAttr_HIDDEN, /**< HIDDEN= */ + TidyAttr_HIGH, /**< HIGH= */ + TidyAttr_ICON, /**< ICON= */ + TidyAttr_KEYTYPE, /**< KEYTYPE= */ + TidyAttr_KIND, /**< KIND= */ + TidyAttr_LIST, /**< LIST= */ + TidyAttr_LOOP, /**< LOOP= */ + TidyAttr_LOW, /**< LOW= */ + TidyAttr_MANIFEST, /**< MANIFEST= */ + TidyAttr_MAX, /**< MAX= */ + TidyAttr_MEDIAGROUP, /**< MEDIAGROUP= */ + TidyAttr_MIN, /**< MIN= */ + TidyAttr_MUTED, /**< MUTED= */ + TidyAttr_NOVALIDATE, /**< NOVALIDATE= */ + TidyAttr_OPEN, /**< OPEN= */ + TidyAttr_OPTIMUM, /**< OPTIMUM= */ + TidyAttr_OnABORT, /**< OnABORT= */ + TidyAttr_OnAFTERPRINT, /**< OnAFTERPRINT= */ + TidyAttr_OnBEFOREPRINT, /**< OnBEFOREPRINT= */ + TidyAttr_OnCANPLAY, /**< OnCANPLAY= */ + TidyAttr_OnCANPLAYTHROUGH, /**< OnCANPLAYTHROUGH= */ + TidyAttr_OnCONTEXTMENU, /**< OnCONTEXTMENU= */ + TidyAttr_OnCUECHANGE, /**< OnCUECHANGE= */ + TidyAttr_OnDRAG, /**< OnDRAG= */ + TidyAttr_OnDRAGEND, /**< OnDRAGEND= */ + TidyAttr_OnDRAGENTER, /**< OnDRAGENTER= */ + TidyAttr_OnDRAGLEAVE, /**< OnDRAGLEAVE= */ + TidyAttr_OnDRAGOVER, /**< OnDRAGOVER= */ + TidyAttr_OnDRAGSTART, /**< OnDRAGSTART= */ + TidyAttr_OnDROP, /**< OnDROP= */ + TidyAttr_OnDURATIONCHANGE, /**< OnDURATIONCHANGE= */ + TidyAttr_OnEMPTIED, /**< OnEMPTIED= */ + TidyAttr_OnENDED, /**< OnENDED= */ + TidyAttr_OnERROR, /**< OnERROR= */ + TidyAttr_OnHASHCHANGE, /**< OnHASHCHANGE= */ + TidyAttr_OnINPUT, /**< OnINPUT= */ + TidyAttr_OnINVALID, /**< OnINVALID= */ + TidyAttr_OnLOADEDDATA, /**< OnLOADEDDATA= */ + TidyAttr_OnLOADEDMETADATA, /**< OnLOADEDMETADATA= */ + TidyAttr_OnLOADSTART, /**< OnLOADSTART= */ + TidyAttr_OnMESSAGE, /**< OnMESSAGE= */ + TidyAttr_OnMOUSEWHEEL, /**< OnMOUSEWHEEL= */ + TidyAttr_OnOFFLINE, /**< OnOFFLINE= */ + TidyAttr_OnONLINE, /**< OnONLINE= */ + TidyAttr_OnPAGEHIDE, /**< OnPAGEHIDE= */ + TidyAttr_OnPAGESHOW, /**< OnPAGESHOW= */ + TidyAttr_OnPAUSE, /**< OnPAUSE= */ + TidyAttr_OnPLAY, /**< OnPLAY= */ + TidyAttr_OnPLAYING, /**< OnPLAYING= */ + TidyAttr_OnPOPSTATE, /**< OnPOPSTATE= */ + TidyAttr_OnPROGRESS, /**< OnPROGRESS= */ + TidyAttr_OnRATECHANGE, /**< OnRATECHANGE= */ + TidyAttr_OnREADYSTATECHANGE, /**< OnREADYSTATECHANGE= */ + TidyAttr_OnREDO, /**< OnREDO= */ + TidyAttr_OnRESIZE, /**< OnRESIZE= */ + TidyAttr_OnSCROLL, /**< OnSCROLL= */ + TidyAttr_OnSEEKED, /**< OnSEEKED= */ + TidyAttr_OnSEEKING, /**< OnSEEKING= */ + TidyAttr_OnSHOW, /**< OnSHOW= */ + TidyAttr_OnSTALLED, /**< OnSTALLED= */ + TidyAttr_OnSTORAGE, /**< OnSTORAGE= */ + TidyAttr_OnSUSPEND, /**< OnSUSPEND= */ + TidyAttr_OnTIMEUPDATE, /**< OnTIMEUPDATE= */ + TidyAttr_OnUNDO, /**< OnUNDO= */ + TidyAttr_OnVOLUMECHANGE, /**< OnVOLUMECHANGE= */ + TidyAttr_OnWAITING, /**< OnWAITING= */ + TidyAttr_PATTERN, /**< PATTERN= */ + TidyAttr_PLACEHOLDER, /**< PLACEHOLDER= */ + TidyAttr_PLAYSINLINE, /**< PLAYSINLINE= */ + TidyAttr_POSTER, /**< POSTER= */ + TidyAttr_PRELOAD, /**< PRELOAD= */ + TidyAttr_PUBDATE, /**< PUBDATE= */ + TidyAttr_RADIOGROUP, /**< RADIOGROUP= */ + TidyAttr_REQUIRED, /**< REQUIRED= */ + TidyAttr_REVERSED, /**< REVERSED= */ + TidyAttr_SANDBOX, /**< SANDBOX= */ + TidyAttr_SCOPED, /**< SCOPED= */ + TidyAttr_SEAMLESS, /**< SEAMLESS= */ + TidyAttr_SIZES, /**< SIZES= */ + TidyAttr_SPELLCHECK, /**< SPELLCHECK= */ + TidyAttr_SRCDOC, /**< SRCDOC= */ + TidyAttr_SRCLANG, /**< SRCLANG= */ + TidyAttr_STEP, /**< STEP= */ + TidyAttr_ARIA_ACTIVEDESCENDANT, /**< ARIA_ACTIVEDESCENDANT */ + TidyAttr_ARIA_ATOMIC, /**< ARIA_ATOMIC= */ + TidyAttr_ARIA_AUTOCOMPLETE, /**< ARIA_AUTOCOMPLETE= */ + TidyAttr_ARIA_BUSY, /**< ARIA_BUSY= */ + TidyAttr_ARIA_CHECKED, /**< ARIA_CHECKED= */ + TidyAttr_ARIA_CONTROLS, /**< ARIA_CONTROLS= */ + TidyAttr_ARIA_DESCRIBEDBY, /**< ARIA_DESCRIBEDBY= */ + TidyAttr_ARIA_DISABLED, /**< ARIA_DISABLED= */ + TidyAttr_ARIA_DROPEFFECT, /**< ARIA_DROPEFFECT= */ + TidyAttr_ARIA_EXPANDED, /**< ARIA_EXPANDED= */ + TidyAttr_ARIA_FLOWTO, /**< ARIA_FLOWTO= */ + TidyAttr_ARIA_GRABBED, /**< ARIA_GRABBED= */ + TidyAttr_ARIA_HASPOPUP, /**< ARIA_HASPOPUP= */ + TidyAttr_ARIA_HIDDEN, /**< ARIA_HIDDEN= */ + TidyAttr_ARIA_INVALID, /**< ARIA_INVALID= */ + TidyAttr_ARIA_LABEL, /**< ARIA_LABEL= */ + TidyAttr_ARIA_LABELLEDBY, /**< ARIA_LABELLEDBY= */ + TidyAttr_ARIA_LEVEL, /**< ARIA_LEVEL= */ + TidyAttr_ARIA_LIVE, /**< ARIA_LIVE= */ + TidyAttr_ARIA_MULTILINE, /**< ARIA_MULTILINE= */ + TidyAttr_ARIA_MULTISELECTABLE, /**< ARIA_MULTISELECTABLE= */ + TidyAttr_ARIA_ORIENTATION, /**< ARIA_ORIENTATION= */ + TidyAttr_ARIA_OWNS, /**< ARIA_OWNS= */ + TidyAttr_ARIA_POSINSET, /**< ARIA_POSINSET= */ + TidyAttr_ARIA_PRESSED, /**< ARIA_PRESSED= */ + TidyAttr_ARIA_READONLY, /**< ARIA_READONLY= */ + TidyAttr_ARIA_RELEVANT, /**< ARIA_RELEVANT= */ + TidyAttr_ARIA_REQUIRED, /**< ARIA_REQUIRED= */ + TidyAttr_ARIA_SELECTED, /**< ARIA_SELECTED= */ + TidyAttr_ARIA_SETSIZE, /**< ARIA_SETSIZE= */ + TidyAttr_ARIA_SORT, /**< ARIA_SORT= */ + TidyAttr_ARIA_VALUEMAX, /**< ARIA_VALUEMAX= */ + TidyAttr_ARIA_VALUEMIN, /**< ARIA_VALUEMIN= */ + TidyAttr_ARIA_VALUENOW, /**< ARIA_VALUENOW= */ + TidyAttr_ARIA_VALUETEXT, /**< ARIA_VALUETEXT= */ + + /* SVG attributes (SVG 1.1) */ + TidyAttr_X, /**< X= */ + TidyAttr_Y, /**< Y= */ + TidyAttr_VIEWBOX, /**< VIEWBOX= */ + TidyAttr_PRESERVEASPECTRATIO, /**< PRESERVEASPECTRATIO= */ + TidyAttr_ZOOMANDPAN, /**< ZOOMANDPAN= */ + TidyAttr_BASEPROFILE, /**< BASEPROFILE= */ + TidyAttr_CONTENTSCRIPTTYPE, /**< CONTENTSCRIPTTYPE= */ + TidyAttr_CONTENTSTYLETYPE, /**< CONTENTSTYLETYPE= */ + + /* MathML attributes */ + TidyAttr_DISPLAY, /**< DISPLAY= (html5) */ + + /* RDFa global attributes */ + TidyAttr_ABOUT, /**< ABOUT= */ + TidyAttr_DATATYPE, /**< DATATYPE= */ + TidyAttr_INLIST, /**< INLIST= */ + TidyAttr_PREFIX, /**< PREFIX= */ + TidyAttr_PROPERTY, /**< PROPERTY= */ + TidyAttr_RESOURCE, /**< RESOURCE= */ + TidyAttr_TYPEOF, /**< TYPEOF= */ + TidyAttr_VOCAB, /**< VOCAB= */ + + TidyAttr_INTEGRITY, /**< INTEGRITY= */ + + TidyAttr_AS, /**< AS= */ + + TidyAttr_XMLNSXLINK, /**< svg xmls:xlink="url" */ + TidyAttr_SLOT, /**< SLOT= */ + TidyAttr_LOADING, /**< LOADING= */ + + /* SVG paint attributes (SVG 1.1) */ + TidyAttr_FILL, /**< FILL= */ + TidyAttr_FILLRULE, /**< FILLRULE= */ + TidyAttr_STROKE, /**< STROKE= */ + TidyAttr_STROKEDASHARRAY, /**< STROKEDASHARRAY= */ + TidyAttr_STROKEDASHOFFSET, /**< STROKEDASHOFFSET= */ + TidyAttr_STROKELINECAP, /**< STROKELINECAP= */ + TidyAttr_STROKELINEJOIN, /**< STROKELINEJOIN= */ + TidyAttr_STROKEMITERLIMIT, /**< STROKEMITERLIMIT= */ + TidyAttr_STROKEWIDTH, /**< STROKEWIDTH= */ + TidyAttr_COLORINTERPOLATION, /**< COLORINTERPOLATION= */ + TidyAttr_COLORRENDERING, /**< COLORRENDERING= */ + TidyAttr_OPACITY, /**< OPACITY= */ + TidyAttr_STROKEOPACITY, /**< STROKEOPACITY= */ + TidyAttr_FILLOPACITY, /**< FILLOPACITY= */ + + N_TIDY_ATTRIBS /**< Must be last */ +} TidyAttrId; + + +/** @} + ** @name I/O and Message Handling Interface + ** + ** Messages used throughout LibTidy and exposed to the public API have + ** attributes which are communicated with these enumerations. + ** + ** @{ + */ + + +/** Message severity level, used throughout LibTidy to indicate the severity + ** or status of a message + ** + ** @remark These enum members all have associated localized strings available + ** via their enum values. These strings are suitable for use as labels. + */ +typedef enum +{ + TidyInfo = 350, /**< Report: Information about markup usage */ + TidyWarning, /**< Report: Warning message */ + TidyConfig, /**< Report: Configuration error */ + TidyAccess, /**< Report: Accessibility message */ + TidyError, /**< Report: Error message - output suppressed */ + TidyBadDocument, /**< Report: I/O or file system error */ + TidyFatal, /**< Report: Crash! */ + TidyDialogueSummary, /**< Dialogue: Summary-related information */ + TidyDialogueInfo, /**< Dialogue: Non-document related information */ + TidyDialogueFootnote, /**< Dialogue: Footnote */ + TidyDialogueDoc = TidyDialogueFootnote, /**< Dialogue: Deprecated (renamed) */ +} TidyReportLevel; + + +/** Indicates the data type of a format string parameter used when Tidy + ** emits reports and dialogue as part of the messaging callback functions. + ** See `messageobj.h` for more information on this API. + */ +typedef enum +{ + tidyFormatType_INT = 0, /**< Argument is signed integer. */ + tidyFormatType_UINT, /**< Argument is unsigned integer. */ + tidyFormatType_STRING, /**< Argument is a string. */ + tidyFormatType_DOUBLE, /**< Argument is a double. */ + tidyFormatType_UNKNOWN = 20 /**< Argument type is unknown! */ +} TidyFormatParameterType; + + +/** @} */ +/** @} end group public_enumerations*/ + + +/* MARK: - Public Enumerations (con't) */ +/** @addtogroup public_enumerations + ** @{ */ + +/** @name Messages + ** @{ */ + +/** The enumeration contains a list of every possible string that Tidy and the + ** console application can output, _except_ for strings from the following + ** enumerations: + ** - `TidyOptionId` + ** - `TidyConfigCategory` + ** - `TidyReportLevel` + ** + ** They are used as keys internally within Tidy, and have corresponding text + ** keys that are used in message callback filters (these are defined in + ** `tidyStringsKeys[]`, but API users don't require access to it directly). + */ +typedef enum +{ + /* This MUST be present and first. */ + TIDYSTRINGS_FIRST = 500, + + FOREACH_MSG_MISC(MAKE_ENUM) + FOREACH_FOOTNOTE_MSG(MAKE_ENUM) + FOREACH_DIALOG_MSG(MAKE_ENUM) + REPORT_MESSAGE_FIRST, + FOREACH_REPORT_MSG(MAKE_ENUM) + REPORT_MESSAGE_LAST, + FOREACH_ACCESS_MSG(MAKE_ENUM) + +#if SUPPORT_CONSOLE_APP + FOREACH_MSG_CONSOLE(MAKE_ENUM) +#endif + + /* This MUST be present and last. */ + TIDYSTRINGS_LAST + +} tidyStrings; + + +/** @} */ +/** @} end group public_enumerations */ + + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* __TIDYENUM_H__ */ + diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidyplatform.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidyplatform.h new file mode 100644 index 0000000..2fca4c4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidyplatform.h @@ -0,0 +1,707 @@ +#ifndef __TIDY_PLATFORM_H__ +#define __TIDY_PLATFORM_H__ + +/**************************************************************************//** + * @file + * Platform specific definitions, specifics, and headers. This file is + * included by `tidy.h` already, and need not be included separately. Among + * other things, the PLATFORM_NAME is defined and the most common systems + * headers are included. + * + * @note It should be largely unnecessary to modify this file unless adding + * support for a completely new architecture. Most options defined in this + * file specify defaults that can be overridden by the build system; for + * example, passing -D flags to CMake. + * + * @author Charles Reitzel [creitzel@rcn.com] + * @author HTACG, et al (consult git log) + * + * @copyright + * Copyright (c) 1998-2017 World Wide Web Consortium (Massachusetts + * Institute of Technology, European Research Consortium for Informatics + * and Mathematics, Keio University). + * @copyright + * See tidy.h for license. + * + * @date Created 2001-05-20 by Charles Reitzel + * @date Updated 2002-07-01 by Charles Reitzel + * @date Further modifications: consult git log. + ******************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/*============================================================================= + * Unix console application features + * By default on Unix-like systems when building for the console program, + * support runtime configuration files in /etc/ and in ~/. To prevent this, + * set ENABLE_CONFIG_FILES to NO. Specify -DTIDY_CONFIG_FILE and/or + * -DTIDY_USER_CONFIG_FILE to override the default paths in tidyplatform.h. + * @note: this section refactored to support #584. + *===========================================================================*/ + +/* #define ENABLE_CONFIG_FILES */ + +#if defined(TIDY_ENABLE_CONFIG_FILES) +# if !defined(TIDY_CONFIG_FILE) +# define TIDY_CONFIG_FILE "/etc/tidy.conf" +# endif +# if !defined(TIDY_USER_CONFIG_FILE) +# define TIDY_USER_CONFIG_FILE "~/.tidyrc" +# endif +#else +# if defined(TIDY_CONFIG_FILE) +# undef TIDY_CONFIG_FILE +# endif +# if defined(TIDY_USER_CONFIG_FILE) +# undef TIDY_USER_CONFIG_FILE +# endif +#endif + + +/*============================================================================= + * Unix tilde expansion support + * By default on Unix-like systems when building for the console program, + * this flag is set so that Tidy knows getpwname() is available. It allows + * tidy to find files named ~your/foo for use in the HTML_TIDY environment + * variable or TIDY_CONFIG_FILE or TIDY_USER_CONFIG_FILE or on the command + * command line: -config ~joebob/tidy.cfg + * Contributed by Todd Lewis. + *===========================================================================*/ + +/* #define SUPPORT_GETPWNAM */ + + +/*============================================================================= + * Optional Tidy features support + *===========================================================================*/ + +/* Enable/disable support for additional languages */ +#ifndef SUPPORT_LOCALIZATIONS +# define SUPPORT_LOCALIZATIONS 1 +#endif + +/* Enable/disable support for console */ +#ifndef SUPPORT_CONSOLE_APP +# define SUPPORT_CONSOLE_APP 1 +#endif + + +/*============================================================================= + * Platform specific convenience definitions + *===========================================================================*/ + +/* === Convenience defines for Mac platforms === */ + +#if defined(macintosh) +/* Mac OS 6.x/7.x/8.x/9.x, with or without CarbonLib - MPW or Metrowerks 68K/PPC compilers */ +# define MAC_OS_CLASSIC +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "Mac OS" +# endif + +/* needed for access() */ +# if !defined(_POSIX) && !defined(NO_ACCESS_SUPPORT) +# define NO_ACCESS_SUPPORT +# endif + +# ifdef SUPPORT_GETPWNAM +# undef SUPPORT_GETPWNAM +# endif + +#elif defined(__APPLE__) && defined(__MACH__) + /* Mac OS X (client) 10.x (or server 1.x/10.x) - gcc or Metrowerks MachO compilers */ +# define MAC_OS_X +# ifndef PLATFORM_NAME +# include "TargetConditionals.h" +# if TARGET_OS_IOS +# define PLATFORM_NAME "Apple iOS" +# elif TARGET_OS_MAC +# define PLATFORM_NAME "Apple macOS" +# elif TARGET_OS_TV +# define PLATFORM_NAME "Apple tvOS" +# elif TARGET_OS_WATCH +# define PLATFORM_NAME "Apple watchOS" +# else +# define PLATFORM_NAME "Apple Unknown OS" +# endif +# endif +#endif + +#if defined(MAC_OS_CLASSIC) || defined(MAC_OS_X) +/* Any OS on Mac platform */ +# define MAC_OS +# define FILENAMES_CASE_SENSITIVE 0 +# define strcasecmp strcmp +#endif + +/* === Convenience defines for BSD-like platforms === */ + +#if defined(__FreeBSD__) +# define BSD_BASED_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "FreeBSD" +# endif + +#elif defined(__NetBSD__) +# define BSD_BASED_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "NetBSD" +# endif + +#elif defined(__OpenBSD__) +# define BSD_BASED_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "OpenBSD" +# endif + +#elif defined(__DragonFly__) +# define BSD_BASED_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "DragonFly" +# endif + +#elif defined(__MINT__) +# define BSD_BASED_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "FreeMiNT" +# endif + +#elif defined(__bsdi__) +# define BSD_BASED_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "BSD/OS" +# endif +#endif + +/* === Convenience defines for Windows platforms === */ + +#if defined(WINDOWS) || defined(_WIN32) + +# define WINDOWS_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "Windows" +# endif + +# if defined(__MWERKS__) || defined(__MSL__) + /* not available with Metrowerks Standard Library */ +# ifdef SUPPORT_GETPWNAM +# undef SUPPORT_GETPWNAM +# endif + /* needed for setmode() */ +# if !defined(NO_SETMODE_SUPPORT) +# define NO_SETMODE_SUPPORT +# endif +# define strcasecmp _stricmp +# endif + +# if defined(__BORLANDC__) +# define strcasecmp stricmp +# endif + +# define FILENAMES_CASE_SENSITIVE 0 +# define SUPPORT_POSIX_MAPPED_FILES 0 + +#endif /* WINDOWS */ + +/* === Convenience defines for Linux platforms === */ + +#if defined(linux) && defined(__alpha__) + /* Linux on Alpha - gcc compiler */ +# define LINUX_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "Linux/Alpha" +# endif + +#elif defined(linux) && defined(__sparc__) + /* Linux on Sparc - gcc compiler */ +# define LINUX_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "Linux/Sparc" +# endif + +#elif defined(linux) && (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) + /* Linux on x86 - gcc compiler */ +# define LINUX_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "Linux/x86" +# endif + +#elif defined(linux) && defined(__powerpc__) + /* Linux on PPC - gcc compiler */ +# define LINUX_OS +# if defined(__linux__) && defined(__powerpc__) +# ifndef PLATFORM_NAME + /* MkLinux on PPC - gcc (egcs) compiler */ +# define PLATFORM_NAME "MkLinux" +# endif +# else +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "Linux/PPC" +# endif +# endif + +#elif defined(linux) || defined(__linux__) + /* generic Linux */ +# define LINUX_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "Linux" +# endif +#endif + +/* === Convenience defines for Solaris platforms === */ + +#if defined(sun) +# define SOLARIS_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "Solaris" +# endif +#endif + +/* === Convenience defines for HPUX + gcc platforms === */ + +#if defined(__hpux) +# define HPUX_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "HPUX" +# endif +#endif + +/* === Convenience defines for RISCOS + gcc platforms === */ + +#if defined(__riscos__) +# define RISC_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "RISC OS" +# endif +#endif + +/* === Convenience defines for OS/2 + icc/gcc platforms === */ + +#if defined(__OS2__) || defined(__EMX__) +# define OS2_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "OS/2" +# endif +# define FILENAMES_CASE_SENSITIVE 0 +# define strcasecmp stricmp +#endif + +/* === Convenience defines for IRIX === */ + +#if defined(__sgi) +# define IRIX_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "SGI IRIX" +# endif +#endif + +/* === Convenience defines for AIX === */ + +#if defined(_AIX) +# define AIX_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "IBM AIX" +# endif +#endif + +/* === Convenience defines for BeOS platforms === */ + +#if defined(__BEOS__) +# define BE_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "BeOS" +# endif +#endif + +/* === Convenience defines for Haiku platforms === */ + +#if defined(__HAIKU__) +# define HAIKU +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "Haiku" +# endif +#endif + +/* === Convenience defines for Cygwin platforms === */ + +#if defined(__CYGWIN__) +# define CYGWIN_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "Cygwin" +# endif +# define FILENAMES_CASE_SENSITIVE 0 +#endif + +/* === Convenience defines for OpenVMS === */ + +#if defined(__VMS) +# define OPENVMS_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "OpenVMS" +# endif +# define FILENAMES_CASE_SENSITIVE 0 +#endif + +/* === Convenience defines for DEC Alpha OSF + gcc platforms === */ + +#if defined(__osf__) +# define OSF_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "DEC Alpha OSF" +# endif +#endif + +/* === Convenience defines for ARM platforms === */ + +#if defined(__arm) +# define ARM_OS +# if defined(forARM) && defined(__NEWTON_H) + /* Using Newton C++ Tools ARMCpp compiler */ +# define NEWTON_OS +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "Newton" +# endif +# else +# ifndef PLATFORM_NAME +# define PLATFORM_NAME "ARM" +# endif +# endif +#endif + + +/*============================================================================= + * Standard Library Includes + *===========================================================================*/ + +#include +#include +#include /* for longjmp on error exit */ +#include +#include /* may need for Unix V */ +#include +#include + +#ifdef NEEDS_MALLOC_H +# include +#endif + +#ifdef SUPPORT_GETPWNAM +# include +#endif + +#ifdef NEEDS_UNISTD_H +# include /* needed for unlink on some Unix systems */ +#endif + + +/*============================================================================= + * Case sensitive file systems + *===========================================================================*/ + +/* By default, use case-sensitive filename comparison. */ +#ifndef FILENAMES_CASE_SENSITIVE +# define FILENAMES_CASE_SENSITIVE 1 +#endif + + +/*============================================================================= + * Last modified time preservation + * Tidy preserves the last modified time for the files it cleans up. + * + * If your platform doesn't support and the utime() function, or + * and the futime() function then set PRESERVE_FILE_TIMES to 0. + * + * If your platform doesn't support and the futime() function, + * then set HAS_FUTIME to 0. + * + * If your platform supports and the utime() function requires the + * file to be closed first, then set UTIME_NEEDS_CLOSED_FILE to 1. + *===========================================================================*/ + +/* Keep old PRESERVEFILETIMES define for compatibility */ +#ifdef PRESERVEFILETIMES +# undef PRESERVE_FILE_TIMES +# define PRESERVE_FILE_TIMES PRESERVEFILETIMES +#endif + +#ifndef PRESERVE_FILE_TIMES +# if defined(RISC_OS) || defined(OPENVMS_OS) || defined(OSF_OS) +# define PRESERVE_FILE_TIMES 0 +# else +# define PRESERVE_FILE_TIMES 1 +# endif +#endif + +#if PRESERVE_FILE_TIMES + +# ifndef HAS_FUTIME +# if defined(CYGWIN_OS) || defined(BE_OS) || defined(OS2_OS) || defined(HPUX_OS) || defined(SOLARIS_OS) || defined(LINUX_OS) || defined(BSD_BASED_OS) || defined(MAC_OS) || defined(__MSL__) || defined(IRIX_OS) || defined(AIX_OS) || defined(__BORLANDC__) || defined(__GLIBC__) || defined(__HAIKU__) +# define HAS_FUTIME 0 +# else +# define HAS_FUTIME 1 +# endif +# endif + +# ifndef UTIME_NEEDS_CLOSED_FILE +# if defined(SOLARIS_OS) || defined(BSD_BASED_OS) || defined(MAC_OS) || defined(__MSL__) || defined(LINUX_OS) +# define UTIME_NEEDS_CLOSED_FILE 1 +# else +# define UTIME_NEEDS_CLOSED_FILE 0 +# endif +# endif + +# if defined(MAC_OS_X) || (!defined(MAC_OS_CLASSIC) && !defined(__MSL__)) +# include +# include +# else +# include +# endif + +# if HAS_FUTIME +# include +# else +# include +# endif + +#if defined(__HAIKU__) +#ifndef va_copy +#define va_copy(dest, src) (dest = src) +#endif +#endif + +/* MS Windows needs _ prefix for Unix file functions. + Not required by Metrowerks Standard Library (MSL). + + Tidy uses following for preserving the last modified time. + + WINDOWS automatically set by Win16 compilers. + _WIN32 automatically set by Win32 compilers. +*/ +# if defined(_WIN32) && !defined(__MSL__) && !defined(__BORLANDC__) +# define futime _futime +# define fstat _fstat +# define utimbuf _utimbuf /* Windows seems to want utimbuf */ +# define stat _stat +# define utime _utime +# define vsnprintf _vsnprintf +# endif + +#endif + + +/*============================================================================= + * Windows file functions + * Windows needs _ prefix for Unix file functions. + * Not required by Metrowerks Standard Library (MSL). + * + * WINDOWS automatically set by Win16 compilers. + * _WIN32 automatically set by Win32 compilers. + *===========================================================================*/ + +#if defined(_WIN32) && !defined(__MSL__) && !defined(__BORLANDC__) + +# if !(defined(__WATCOMC__) || defined(__MINGW32__)) +# define fileno _fileno +# define setmode _setmode +# endif + +# if defined(_MSC_VER) +# define fileno _fileno +# if !defined(NDEBUG) && !defined(ENABLE_DEBUG_LOG) && !defined(DISABLE_DEBUG_LOG) +# define ENABLE_DEBUG_LOG +# endif +# endif + +# define access _access +# define strcasecmp _stricmp + +# ifndef va_copy +# define va_copy(dest, src) (dest = src) +# endif + +# if _MSC_VER > 1000 +# pragma warning( disable : 4189 ) /* local variable is initialized but not referenced */ +# pragma warning( disable : 4100 ) /* unreferenced formal parameter */ +# pragma warning( disable : 4706 ) /* assignment within conditional expression */ +# endif + +# if _MSC_VER > 1300 +# pragma warning( disable : 4996 ) /* disable depreciation warning */ +# endif + +#endif /* _WIN32 */ + +#if defined(_WIN32) + +# if (defined(_USRDLL) || defined(_WINDLL) || defined(BUILD_SHARED_LIB)) && !defined(TIDY_EXPORT) && !defined(TIDY_STATIC) +# ifdef BUILDING_SHARED_LIB +# define TIDY_EXPORT __declspec( dllexport ) +# else +# define TIDY_EXPORT __declspec( dllimport ) +# endif +# else +# define TIDY_EXPORT extern +# endif + +# ifndef TIDY_CALL +# ifdef _WIN64 +# define TIDY_CALL __fastcall +# else +# define TIDY_CALL __stdcall +# endif +# endif + +# ifndef TIDY_THREAD_LOCAL +# ifdef _MSC_VER +# define TIDY_THREAD_LOCAL __declspec( thread ) +# endif +# endif + + +#endif /* _WIN32 */ + + +/*============================================================================= + * Hack for gnu sys/types.h file which defines uint and ulong + *===========================================================================*/ + +#if defined(BE_OS) || defined(SOLARIS_OS) || defined(BSD_BASED_OS) || defined(OSF_OS) || defined(IRIX_OS) || defined(AIX_OS) +# include +#endif + +#if !defined(HPUX_OS) && !defined(CYGWIN_OS) && !defined(MAC_OS_X) && !defined(BE_OS) && !defined(SOLARIS_OS) && !defined(BSD_BASED_OS) && !defined(OSF_OS) && !defined(IRIX_OS) && !defined(AIX_OS) && !defined(LINUX_OS) && !defined(__HAIKU__) +# undef uint + typedef unsigned int uint; +#endif + +#if defined(HPUX_OS) || defined(CYGWIN_OS) || defined(MAC_OS) || defined(BSD_BASED_OS) || defined(_WIN32) || defined(__ANDROID__) +# undef ulong + typedef unsigned long ulong; +#endif + + +/*============================================================================= + * Visibility support + * With GCC 4, __attribute__ ((visibility("default"))) can be used + * along compiling with tidylib with "-fvisibility=hidden". See + * https://gcc.gnu.org/wiki/Visibility and build/gmake/Makefile. + *===========================================================================*/ +/* +#if defined(__GNUC__) && __GNUC__ >= 4 +# define TIDY_EXPORT __attribute__ ((visibility("default"))) +#endif +*/ + + +/*============================================================================= + * Other definitions + *===========================================================================*/ + +#ifndef TIDY_EXPORT /* Define it away for most builds */ +# define TIDY_EXPORT +#endif + +#ifndef TIDY_STRUCT +# define TIDY_STRUCT +#endif + +#ifndef TIDY_THREAD_LOCAL +# define TIDY_THREAD_LOCAL __thread +#endif + +#ifndef TIDY_INDENTATION_LIMIT +# define TIDY_INDENTATION_LIMIT 50 +#endif + +typedef unsigned char byte; + +typedef uint tchar; /* single, full character */ +typedef char tmbchar; /* single, possibly partial character */ +#ifndef TMBSTR_DEFINED + typedef tmbchar* tmbstr; /* pointer to buffer of possibly partial chars */ + typedef const tmbchar* ctmbstr; /* Ditto, but const */ +# define NULLSTR (tmbstr)"" +# define TMBSTR_DEFINED +#endif + +#ifndef TIDY_CALL +# define TIDY_CALL +#endif + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) +# define ARG_UNUSED(x) x __attribute__((unused)) +# define FUNC_UNUSED __attribute__((unused)) +#else +# define ARG_UNUSED(x) x +# define FUNC_UNUSED +#endif + +/* HAS_VSNPRINTF triggers the use of "vsnprintf", which is safe related to + buffer overflow. Therefore, we make it the default unless HAS_VSNPRINTF + has been defined. */ +#ifndef HAS_VSNPRINTF +# define HAS_VSNPRINTF 1 +#endif + +#ifndef SUPPORT_POSIX_MAPPED_FILES +# define SUPPORT_POSIX_MAPPED_FILES 1 +#endif + +/* `bool` is a reserved word in some but not all C++ compilers depending on age. + age. Work around is to avoid bool by introducing a new enum called `Bool`. +*/ + +/* We could use the C99 definition where supported +typedef _Bool Bool; +#define no (_Bool)0 +#define yes (_Bool)1 +*/ +typedef enum +{ + no, + yes +} Bool; + +/* for NULL pointers +#define null ((const void*)0) +extern void* null; +*/ + +#if defined(DMALLOC) +# include "dmalloc.h" +#endif + +/* Opaque data structure. +* Cast to implementation type struct within lib. +* This will reduce inter-dependencies/conflicts w/ application code. +*/ +#if 1 +#define opaque_type( typenam )\ +struct _##typenam { int _opaque; };\ +typedef struct _##typenam const * typenam +#else +#define opaque_type(typenam) typedef const void* typenam +#endif + +/* Opaque data structure used to pass back +** and forth to keep current position in a +** list or other collection. +*/ +opaque_type( TidyIterator ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __TIDY_PLATFORM_H__ */ + +/* + * local variables: + * mode: c + * indent-tabs-mode: nil + * c-basic-offset: 4 + * eval: (c-set-offset 'substatement-open 0) + * end: + */ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/Uri.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/Uri.h new file mode 100644 index 0000000..b80ac6c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/Uri.h @@ -0,0 +1,1146 @@ +/* e8e2c75d033ddfe256fe87c3fd5a330a6f2c9cbb376ebd83a1b3263e804c766a (0.9.8+) + * + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song + * Copyright (C) 2007, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file Uri.h + * Holds the RFC 3986 %URI parser interface. + * NOTE: This header includes itself twice. + */ + +#if (defined(URI_PASS_ANSI) && !defined(URI_H_ANSI)) \ + || (defined(URI_PASS_UNICODE) && !defined(URI_H_UNICODE)) \ + || (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* What encodings are enabled? */ +#include "UriDefsConfig.h" +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "Uri.h" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "Uri.h" +# undef URI_PASS_UNICODE +# endif +/* Only one pass for each encoding */ +#elif (defined(URI_PASS_ANSI) && !defined(URI_H_ANSI) \ + && defined(URI_ENABLE_ANSI)) || (defined(URI_PASS_UNICODE) \ + && !defined(URI_H_UNICODE) && defined(URI_ENABLE_UNICODE)) +# ifdef URI_PASS_ANSI +# define URI_H_ANSI 1 +# include "UriDefsAnsi.h" +# else +# define URI_H_UNICODE 1 +# include "UriDefsUnicode.h" +# endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifndef URI_DOXYGEN +# include "UriBase.h" +#endif + + + +/** + * Specifies a range of characters within a string. + * The range includes all characters from first + * to one before afterLast. So if both are + * non-NULL the difference is the length of the text range. + * + * @see UriUriA + * @see UriPathSegmentA + * @see UriHostDataA + * @since 0.3.0 + */ +typedef struct URI_TYPE(TextRangeStruct) { + const URI_CHAR * first; /**< Pointer to first character */ + const URI_CHAR * afterLast; /**< Pointer to character after the last one still in */ +} URI_TYPE(TextRange); /**< @copydoc UriTextRangeStructA */ + + + +/** + * Represents a path segment within a %URI path. + * More precisely it is a node in a linked + * list of path segments. + * + * @see UriUriA + * @since 0.3.0 + */ +typedef struct URI_TYPE(PathSegmentStruct) { + URI_TYPE(TextRange) text; /**< Path segment name */ + struct URI_TYPE(PathSegmentStruct) * next; /**< Pointer to the next path segment in the list, can be NULL if last already */ + + void * reserved; /**< Reserved to the parser */ +} URI_TYPE(PathSegment); /**< @copydoc UriPathSegmentStructA */ + + + +/** + * Holds structured host information. + * This is either a IPv4, IPv6, plain + * text for IPvFuture or all zero for + * a registered name. + * + * @see UriUriA + * @since 0.3.0 + */ +typedef struct URI_TYPE(HostDataStruct) { + UriIp4 * ip4; /**< IPv4 address */ + UriIp6 * ip6; /**< IPv6 address */ + URI_TYPE(TextRange) ipFuture; /**< IPvFuture address */ +} URI_TYPE(HostData); /**< @copydoc UriHostDataStructA */ + + + +/** + * Represents an RFC 3986 %URI. + * Missing components can be {NULL, NULL} ranges. + * + * @see uriFreeUriMembersA + * @see uriFreeUriMembersMmA + * @see UriParserStateA + * @since 0.3.0 + */ +typedef struct URI_TYPE(UriStruct) { + URI_TYPE(TextRange) scheme; /**< Scheme (e.g. "http") */ + URI_TYPE(TextRange) userInfo; /**< User info (e.g. "user:pass") */ + URI_TYPE(TextRange) hostText; /**< Host text (set for all hosts, excluding square brackets) */ + URI_TYPE(HostData) hostData; /**< Structured host type specific data */ + URI_TYPE(TextRange) portText; /**< Port (e.g. "80") */ + URI_TYPE(PathSegment) * pathHead; /**< Head of a linked list of path segments */ + URI_TYPE(PathSegment) * pathTail; /**< Tail of the list behind pathHead */ + URI_TYPE(TextRange) query; /**< Query without leading "?" */ + URI_TYPE(TextRange) fragment; /**< Query without leading "#" */ + UriBool absolutePath; /**< Absolute path flag, distincting "a" and "/a"; + always URI_FALSE for URIs with host */ + UriBool owner; /**< Memory owner flag */ + + void * reserved; /**< Reserved to the parser */ +} URI_TYPE(Uri); /**< @copydoc UriUriStructA */ + + + +/** + * Represents a state of the %URI parser. + * Missing components can be NULL to reflect + * a components absence. + * + * @see uriFreeUriMembersA + * @see uriFreeUriMembersMmA + * @since 0.3.0 + */ +typedef struct URI_TYPE(ParserStateStruct) { + URI_TYPE(Uri) * uri; /**< Plug in the %URI structure to be filled while parsing here */ + int errorCode; /**< Code identifying the error which occurred */ + const URI_CHAR * errorPos; /**< Pointer to position in case of a syntax error */ + + void * reserved; /**< Reserved to the parser */ +} URI_TYPE(ParserState); /**< @copydoc UriParserStateStructA */ + + + +/** + * Represents a query element. + * More precisely it is a node in a linked + * list of query elements. + * + * @since 0.7.0 + */ +typedef struct URI_TYPE(QueryListStruct) { + const URI_CHAR * key; /**< Key of the query element */ + const URI_CHAR * value; /**< Value of the query element, can be NULL */ + + struct URI_TYPE(QueryListStruct) * next; /**< Pointer to the next key/value pair in the list, can be NULL if last already */ +} URI_TYPE(QueryList); /**< @copydoc UriQueryListStructA */ + + + +/** + * Parses a RFC 3986 %URI. + * Uses default libc-based memory manager. + * + * @param state INOUT: Parser state with set output %URI, must not be NULL + * @param first IN: Pointer to the first character to parse, must not be NULL + * @param afterLast IN: Pointer to the character after the last to parse, must not be NULL + * @return 0 on success, error code otherwise + * + * @see uriParseUriA + * @see uriParseSingleUriA + * @see uriParseSingleUriExA + * @see uriToStringA + * @since 0.3.0 + * @deprecated Deprecated since 0.9.0, please migrate to uriParseSingleUriExA (with "Single"). + */ +URI_PUBLIC int URI_FUNC(ParseUriEx)(URI_TYPE(ParserState) * state, + const URI_CHAR * first, const URI_CHAR * afterLast); + + + +/** + * Parses a RFC 3986 %URI. + * Uses default libc-based memory manager. + * + * @param state INOUT: Parser state with set output %URI, must not be NULL + * @param text IN: Text to parse, must not be NULL + * @return 0 on success, error code otherwise + * + * @see uriParseUriExA + * @see uriParseSingleUriA + * @see uriParseSingleUriExA + * @see uriToStringA + * @since 0.3.0 + * @deprecated Deprecated since 0.9.0, please migrate to uriParseSingleUriA (with "Single"). + */ +URI_PUBLIC int URI_FUNC(ParseUri)(URI_TYPE(ParserState) * state, + const URI_CHAR * text); + + + +/** + * Parses a single RFC 3986 %URI. + * Uses default libc-based memory manager. + * + * @param uri OUT: Output %URI, must not be NULL + * @param text IN: Pointer to the first character to parse, + * must not be NULL + * @param errorPos OUT: Pointer to a pointer to the first character + * causing a syntax error, can be NULL; + * only set when URI_ERROR_SYNTAX was returned + * @return 0 on success, error code otherwise + * + * @see uriParseSingleUriExA + * @see uriParseSingleUriExMmA + * @see uriToStringA + * @since 0.9.0 + */ +URI_PUBLIC int URI_FUNC(ParseSingleUri)(URI_TYPE(Uri) * uri, + const URI_CHAR * text, const URI_CHAR ** errorPos); + + + +/** + * Parses a single RFC 3986 %URI. + * Uses default libc-based memory manager. + * + * @param uri OUT: Output %URI, must not be NULL + * @param first IN: Pointer to the first character to parse, + * must not be NULL + * @param afterLast IN: Pointer to the character after the last to + * parse, can be NULL + * (to use first + strlen(first)) + * @param errorPos OUT: Pointer to a pointer to the first character + * causing a syntax error, can be NULL; + * only set when URI_ERROR_SYNTAX was returned + * @return 0 on success, error code otherwise + * + * @see uriParseSingleUriA + * @see uriParseSingleUriExMmA + * @see uriToStringA + * @since 0.9.0 + */ +URI_PUBLIC int URI_FUNC(ParseSingleUriEx)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, const URI_CHAR * afterLast, + const URI_CHAR ** errorPos); + + + +/** + * Parses a single RFC 3986 %URI. + * + * @param uri OUT: Output %URI, must not be NULL + * @param first IN: Pointer to the first character to parse, + * must not be NULL + * @param afterLast IN: Pointer to the character after the last to + * parse, can be NULL + * (to use first + strlen(first)) + * @param errorPos OUT: Pointer to a pointer to the first character + * causing a syntax error, can be NULL; + * only set when URI_ERROR_SYNTAX was returned + * @param memory IN: Memory manager to use, NULL for default libc + * @return 0 on success, error code otherwise + * + * @see uriParseSingleUriA + * @see uriParseSingleUriExA + * @see uriToStringA + * @since 0.9.0 + */ +URI_PUBLIC int URI_FUNC(ParseSingleUriExMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, const URI_CHAR * afterLast, + const URI_CHAR ** errorPos, UriMemoryManager * memory); + + + +/** + * Frees all memory associated with the members + * of the %URI structure. Note that the structure + * itself is not freed, only its members. + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI structure whose members should be freed + * + * @see uriFreeUriMembersMmA + * @since 0.3.0 + */ +URI_PUBLIC void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri); + + + +/** + * Frees all memory associated with the members + * of the %URI structure. Note that the structure + * itself is not freed, only its members. + * + * @param uri INOUT: %URI structure whose members should be freed + * @param memory IN: Memory manager to use, NULL for default libc + * @return 0 on success, error code otherwise + * + * @see uriFreeUriMembersA + * @since 0.9.0 + */ +URI_PUBLIC int URI_FUNC(FreeUriMembersMm)(URI_TYPE(Uri) * uri, + UriMemoryManager * memory); + + + +/** + * Percent-encodes all unreserved characters from the input string and + * writes the encoded version to the output string. + * + * NOTE: Be sure to allocate 3 times the space of the input buffer for + * the output buffer for normalizeBreaks == URI_FALSE and 6 times + * the space for normalizeBreaks == URI_TRUE + * (since e.g. "\x0d" becomes "%0D%0A" in that case). + * + * NOTE: The implementation treats (both char and) wchar_t units + * as code point integers, which works well for code points U+0001 to U+00ff + * in host-native endianness but nothing more; + * in particular, using uriEscapeExW with arbitrary Unicode input will + * not produce healthy results. + * Passing UTF-8 input to uriEscapeExA may be useful in some scenarios. + * Keep in mind that uriparser is about %URI (RFC 3986) not %IRI (RFC 3987). + * + * @param inFirst IN: Pointer to first character of the input text + * @param inAfterLast IN: Pointer after the last character of the input text + * @param out OUT: Encoded text destination + * @param spaceToPlus IN: Whether to convert ' ' to '+' or not + * @param normalizeBreaks IN: Whether to convert CR and LF to CR-LF or not. + * @return Position of terminator in output string + * + * @see uriEscapeA + * @see uriUnescapeInPlaceExA + * @since 0.5.2 + */ +URI_PUBLIC URI_CHAR * URI_FUNC(EscapeEx)(const URI_CHAR * inFirst, + const URI_CHAR * inAfterLast, URI_CHAR * out, + UriBool spaceToPlus, UriBool normalizeBreaks); + + + +/** + * Percent-encodes all unreserved characters from the input string and + * writes the encoded version to the output string. + * + * NOTE: Be sure to allocate 3 times the space of the input buffer for + * the output buffer for normalizeBreaks == URI_FALSE and 6 times + * the space for normalizeBreaks == URI_TRUE + * (since e.g. "\x0d" becomes "%0D%0A" in that case). + * + * NOTE: The implementation treats (both char and) wchar_t units + * as code point integers, which works well for code points U+0001 to U+00ff + * in host-native endianness but nothing more; + * in particular, using uriEscapeW with arbitrary Unicode input will + * not produce healthy results. + * Passing UTF-8 input to uriEscapeA may be useful in some scenarios. + * Keep in mind that uriparser is about %URI (RFC 3986) not %IRI (RFC 3987). + * + * @param in IN: Text source + * @param out OUT: Encoded text destination + * @param spaceToPlus IN: Whether to convert ' ' to '+' or not + * @param normalizeBreaks IN: Whether to convert CR and LF to CR-LF or not. + * @return Position of terminator in output string + * + * @see uriEscapeExA + * @see uriUnescapeInPlaceA + * @since 0.5.0 + */ +URI_PUBLIC URI_CHAR * URI_FUNC(Escape)(const URI_CHAR * in, URI_CHAR * out, + UriBool spaceToPlus, UriBool normalizeBreaks); + + + +/** + * Unescapes percent-encoded groups in a given string. + * E.g. "%20" will become " ". Unescaping is done in place. + * The return value will be point to the new position + * of the terminating zero. Use this value to get the new + * length of the string. NULL is only returned if inout + * is NULL. + * + * @param inout INOUT: Text to unescape/decode + * @param plusToSpace IN: Whether to convert '+' to ' ' or not + * @param breakConversion IN: Line break conversion mode + * @return Pointer to new position of the terminating zero + * + * @see uriUnescapeInPlaceA + * @see uriEscapeExA + * @since 0.5.0 + */ +URI_PUBLIC const URI_CHAR * URI_FUNC(UnescapeInPlaceEx)(URI_CHAR * inout, + UriBool plusToSpace, UriBreakConversion breakConversion); + + + +/** + * Unescapes percent-encoded groups in a given string. + * E.g. "%20" will become " ". Unescaping is done in place. + * The return value will be point to the new position + * of the terminating zero. Use this value to get the new + * length of the string. NULL is only returned if inout + * is NULL. + * + * NOTE: '+' is not decoded to ' ' and line breaks are not converted. + * Use the more advanced UnescapeInPlaceEx for that features instead. + * + * @param inout INOUT: Text to unescape/decode + * @return Pointer to new position of the terminating zero + * + * @see uriUnescapeInPlaceExA + * @see uriEscapeA + * @since 0.3.0 + */ +URI_PUBLIC const URI_CHAR * URI_FUNC(UnescapeInPlace)(URI_CHAR * inout); + + + +/** + * Performs reference resolution as described in + *
section 5.2.2 of RFC 3986. + * Uses default libc-based memory manager. + * NOTE: On success you have to call uriFreeUriMembersA on \p absoluteDest manually later. + * + * @param absoluteDest OUT: Result %URI + * @param relativeSource IN: Reference to resolve + * @param absoluteBase IN: Base %URI to apply + * @return Error code or 0 on success + * + * @see uriRemoveBaseUriA + * @see uriRemoveBaseUriMmA + * @see uriAddBaseUriExA + * @see uriAddBaseUriExMmA + * @since 0.4.0 + */ +URI_PUBLIC int URI_FUNC(AddBaseUri)(URI_TYPE(Uri) * absoluteDest, + const URI_TYPE(Uri) * relativeSource, + const URI_TYPE(Uri) * absoluteBase); + + + +/** + * Performs reference resolution as described in + * section 5.2.2 of RFC 3986. + * Uses default libc-based memory manager. + * NOTE: On success you have to call uriFreeUriMembersA on \p absoluteDest manually later. + * + * @param absoluteDest OUT: Result %URI + * @param relativeSource IN: Reference to resolve + * @param absoluteBase IN: Base %URI to apply + * @param options IN: Configuration to apply + * @return Error code or 0 on success + * + * @see uriRemoveBaseUriA + * @see uriAddBaseUriA + * @see uriAddBaseUriExMmA + * @since 0.8.1 + */ +URI_PUBLIC int URI_FUNC(AddBaseUriEx)(URI_TYPE(Uri) * absoluteDest, + const URI_TYPE(Uri) * relativeSource, + const URI_TYPE(Uri) * absoluteBase, + UriResolutionOptions options); + + + +/** + * Performs reference resolution as described in + * section 5.2.2 of RFC 3986. + * NOTE: On success you have to call uriFreeUriMembersMmA on \p absoluteDest manually later. + * + * @param absoluteDest OUT: Result %URI + * @param relativeSource IN: Reference to resolve + * @param absoluteBase IN: Base %URI to apply + * @param options IN: Configuration to apply + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriRemoveBaseUriA + * @see uriRemoveBaseUriMmA + * @see uriAddBaseUriA + * @see uriAddBaseUriExA + * @since 0.9.0 + */ +URI_PUBLIC int URI_FUNC(AddBaseUriExMm)(URI_TYPE(Uri) * absoluteDest, + const URI_TYPE(Uri) * relativeSource, + const URI_TYPE(Uri) * absoluteBase, + UriResolutionOptions options, UriMemoryManager * memory); + + + +/** + * Tries to make a relative %URI (a reference) from an + * absolute %URI and a given base %URI. The resulting %URI is going to be + * relative if the absolute %URI and base %UI share both scheme and authority. + * If that is not the case, the result will still be + * an absolute URI (with scheme part if necessary). + * Uses default libc-based memory manager. + * NOTE: On success you have to call uriFreeUriMembersA on + * \p dest manually later. + * + * @param dest OUT: Result %URI + * @param absoluteSource IN: Absolute %URI to make relative + * @param absoluteBase IN: Base %URI + * @param domainRootMode IN: Create %URI with path relative to domain root + * @return Error code or 0 on success + * + * @see uriRemoveBaseUriMmA + * @see uriAddBaseUriA + * @see uriAddBaseUriExA + * @see uriAddBaseUriExMmA + * @since 0.5.2 + */ +URI_PUBLIC int URI_FUNC(RemoveBaseUri)(URI_TYPE(Uri) * dest, + const URI_TYPE(Uri) * absoluteSource, + const URI_TYPE(Uri) * absoluteBase, + UriBool domainRootMode); + + + +/** + * Tries to make a relative %URI (a reference) from an + * absolute %URI and a given base %URI. The resulting %URI is going to be + * relative if the absolute %URI and base %UI share both scheme and authority. + * If that is not the case, the result will still be + * an absolute URI (with scheme part if necessary). + * NOTE: On success you have to call uriFreeUriMembersMmA on + * \p dest manually later. + * + * @param dest OUT: Result %URI + * @param absoluteSource IN: Absolute %URI to make relative + * @param absoluteBase IN: Base %URI + * @param domainRootMode IN: Create %URI with path relative to domain root + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriRemoveBaseUriA + * @see uriAddBaseUriA + * @see uriAddBaseUriExA + * @see uriAddBaseUriExMmA + * @since 0.9.0 + */ +URI_PUBLIC int URI_FUNC(RemoveBaseUriMm)(URI_TYPE(Uri) * dest, + const URI_TYPE(Uri) * absoluteSource, + const URI_TYPE(Uri) * absoluteBase, + UriBool domainRootMode, UriMemoryManager * memory); + + + +/** + * Checks two URIs for equivalence. Comparison is done + * the naive way, without prior normalization. + * NOTE: Two NULL URIs are equal as well. + * + * @param a IN: First %URI + * @param b IN: Second %URI + * @return URI_TRUE when equal, URI_FAlSE else + * + * @since 0.4.0 + */ +URI_PUBLIC UriBool URI_FUNC(EqualsUri)(const URI_TYPE(Uri) * a, + const URI_TYPE(Uri) * b); + + + +/** + * Calculates the number of characters needed to store the + * string representation of the given %URI excluding the + * terminator. + * + * @param uri IN: %URI to measure + * @param charsRequired OUT: Length of the string representation in characters excluding terminator + * @return Error code or 0 on success + * + * @see uriToStringA + * @since 0.5.0 + */ +URI_PUBLIC int URI_FUNC(ToStringCharsRequired)(const URI_TYPE(Uri) * uri, + int * charsRequired); + + + +/** + * Converts a %URI structure back to text as described in + * section 5.3 of RFC 3986. + * + * NOTE: Scheme-based normalization + * (section 6.2.3 of RFC 3986) + * is not applied and is considered a responsibility of the application using uriparser. + * + * @param dest OUT: Output destination + * @param uri IN: %URI to convert + * @param maxChars IN: Maximum number of characters to copy including terminator + * @param charsWritten OUT: Number of characters written, can be lower than maxChars even if the %URI is too long! + * @return Error code or 0 on success + * + * @see uriToStringCharsRequiredA + * @since 0.4.0 + */ +URI_PUBLIC int URI_FUNC(ToString)(URI_CHAR * dest, const URI_TYPE(Uri) * uri, + int maxChars, int * charsWritten); + + + +/** + * Determines the components of a %URI that are not normalized. + * + * @param uri IN: %URI to check + * @return Normalization job mask + * + * @see uriNormalizeSyntaxA + * @see uriNormalizeSyntaxExA + * @see uriNormalizeSyntaxExMmA + * @see uriNormalizeSyntaxMaskRequiredExA + * @since 0.5.0 + * @deprecated Deprecated since 0.9.0, please migrate to uriNormalizeSyntaxMaskRequiredExA (with "Ex"). + */ +URI_PUBLIC unsigned int URI_FUNC(NormalizeSyntaxMaskRequired)( + const URI_TYPE(Uri) * uri); + + + +/** + * Determines the components of a %URI that are not normalized. + * + * @param uri IN: %URI to check + * @param outMask OUT: Normalization job mask + * @return Error code or 0 on success + * + * @see uriNormalizeSyntaxA + * @see uriNormalizeSyntaxExA + * @see uriNormalizeSyntaxExMmA + * @see uriNormalizeSyntaxMaskRequiredA + * @since 0.9.0 + */ +URI_PUBLIC int URI_FUNC(NormalizeSyntaxMaskRequiredEx)( + const URI_TYPE(Uri) * uri, unsigned int * outMask); + + + +/** + * Normalizes a %URI using a normalization mask. + * The normalization mask decides what components are normalized. + * + * NOTE: If necessary the %URI becomes owner of all memory + * behind the text pointed to. Text is duplicated in that case. + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to normalize + * @param mask IN: Normalization mask + * @return Error code or 0 on success + * + * @see uriNormalizeSyntaxA + * @see uriNormalizeSyntaxExMmA + * @see uriNormalizeSyntaxMaskRequiredA + * @since 0.5.0 + */ +URI_PUBLIC int URI_FUNC(NormalizeSyntaxEx)(URI_TYPE(Uri) * uri, + unsigned int mask); + + + +/** + * Normalizes a %URI using a normalization mask. + * The normalization mask decides what components are normalized. + * + * NOTE: If necessary the %URI becomes owner of all memory + * behind the text pointed to. Text is duplicated in that case. + * + * @param uri INOUT: %URI to normalize + * @param mask IN: Normalization mask + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriNormalizeSyntaxA + * @see uriNormalizeSyntaxExA + * @see uriNormalizeSyntaxMaskRequiredA + * @since 0.9.0 + */ +URI_PUBLIC int URI_FUNC(NormalizeSyntaxExMm)(URI_TYPE(Uri) * uri, + unsigned int mask, UriMemoryManager * memory); + + + +/** + * Normalizes all components of a %URI. + * + * NOTE: If necessary the %URI becomes owner of all memory + * behind the text pointed to. Text is duplicated in that case. + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to normalize + * @return Error code or 0 on success + * + * @see uriNormalizeSyntaxExA + * @see uriNormalizeSyntaxExMmA + * @see uriNormalizeSyntaxMaskRequiredA + * @since 0.5.0 + */ +URI_PUBLIC int URI_FUNC(NormalizeSyntax)(URI_TYPE(Uri) * uri); + + + +/** + * Converts a Unix filename to a %URI string. + * The destination buffer must be large enough to hold 7 + 3 * len(filename) + 1 + * characters in case of an absolute filename or 3 * len(filename) + 1 in case + * of a relative filename. + * + * EXAMPLE + * Input: "/bin/bash" + * Output: "file:///bin/bash" + * + * @param filename IN: Unix filename to convert + * @param uriString OUT: Destination to write %URI string to + * @return Error code or 0 on success + * + * @see uriUriStringToUnixFilenameA + * @see uriWindowsFilenameToUriStringA + * @since 0.5.2 + */ +URI_PUBLIC int URI_FUNC(UnixFilenameToUriString)(const URI_CHAR * filename, + URI_CHAR * uriString); + + + +/** + * Converts a Windows filename to a %URI string. + * The destination buffer must be large enough to hold 8 + 3 * len(filename) + 1 + * characters in case of an absolute filename or 3 * len(filename) + 1 in case + * of a relative filename. + * + * EXAMPLE + * Input: "E:\\Documents and Settings" + * Output: "file:///E:/Documents%20and%20Settings" + * + * @param filename IN: Windows filename to convert + * @param uriString OUT: Destination to write %URI string to + * @return Error code or 0 on success + * + * @see uriUriStringToWindowsFilenameA + * @see uriUnixFilenameToUriStringA + * @since 0.5.2 + */ +URI_PUBLIC int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename, + URI_CHAR * uriString); + + + +/** + * Extracts a Unix filename from a %URI string. + * The destination buffer must be large enough to hold len(uriString) + 1 - 5 + * characters in case of an absolute %URI or len(uriString) + 1 in case + * of a relative %URI. + * + * @param uriString IN: %URI string to convert + * @param filename OUT: Destination to write filename to + * @return Error code or 0 on success + * + * @see uriUnixFilenameToUriStringA + * @see uriUriStringToWindowsFilenameA + * @since 0.5.2 + */ +URI_PUBLIC int URI_FUNC(UriStringToUnixFilename)(const URI_CHAR * uriString, + URI_CHAR * filename); + + + +/** + * Extracts a Windows filename from a %URI string. + * The destination buffer must be large enough to hold len(uriString) + 1 - 5 + * characters in case of an absolute %URI or len(uriString) + 1 in case + * of a relative %URI. + * + * @param uriString IN: %URI string to convert + * @param filename OUT: Destination to write filename to + * @return Error code or 0 on success + * + * @see uriWindowsFilenameToUriStringA + * @see uriUriStringToUnixFilenameA + * @since 0.5.2 + */ +URI_PUBLIC int URI_FUNC(UriStringToWindowsFilename)(const URI_CHAR * uriString, + URI_CHAR * filename); + + + +/** + * Calculates the number of characters needed to store the + * string representation of the given query list excluding the + * terminator. It is assumed that line breaks are will be + * normalized to "%0D%0A". + * + * @param queryList IN: Query list to measure + * @param charsRequired OUT: Length of the string representation in characters excluding terminator + * @return Error code or 0 on success + * + * @see uriComposeQueryCharsRequiredExA + * @see uriComposeQueryA + * @since 0.7.0 + */ +URI_PUBLIC int URI_FUNC(ComposeQueryCharsRequired)( + const URI_TYPE(QueryList) * queryList, int * charsRequired); + + + +/** + * Calculates the number of characters needed to store the + * string representation of the given query list excluding the + * terminator. + * + * @param queryList IN: Query list to measure + * @param charsRequired OUT: Length of the string representation in characters excluding terminator + * @param spaceToPlus IN: Whether to convert ' ' to '+' or not + * @param normalizeBreaks IN: Whether to convert CR and LF to CR-LF or not. + * @return Error code or 0 on success + * + * @see uriComposeQueryCharsRequiredA + * @see uriComposeQueryExA + * @since 0.7.0 + */ +URI_PUBLIC int URI_FUNC(ComposeQueryCharsRequiredEx)( + const URI_TYPE(QueryList) * queryList, + int * charsRequired, UriBool spaceToPlus, UriBool normalizeBreaks); + + + +/** + * Converts a query list structure back to a query string. + * The composed string does not start with '?', + * on the way ' ' is converted to '+' and line breaks are + * normalized to "%0D%0A". + * + * @param dest OUT: Output destination + * @param queryList IN: Query list to convert + * @param maxChars IN: Maximum number of characters to copy including terminator + * @param charsWritten OUT: Number of characters written, can be lower than maxChars even if the query list is too long! + * @return Error code or 0 on success + * + * @see uriComposeQueryExA + * @see uriComposeQueryMallocA + * @see uriComposeQueryMallocExA + * @see uriComposeQueryMallocExMmA + * @see uriComposeQueryCharsRequiredA + * @see uriDissectQueryMallocA + * @see uriDissectQueryMallocExA + * @see uriDissectQueryMallocExMmA + * @since 0.7.0 + */ +URI_PUBLIC int URI_FUNC(ComposeQuery)(URI_CHAR * dest, + const URI_TYPE(QueryList) * queryList, int maxChars, int * charsWritten); + + + +/** + * Converts a query list structure back to a query string. + * The composed string does not start with '?'. + * + * @param dest OUT: Output destination + * @param queryList IN: Query list to convert + * @param maxChars IN: Maximum number of characters to copy including terminator + * @param charsWritten OUT: Number of characters written, can be lower than maxChars even if the query list is too long! + * @param spaceToPlus IN: Whether to convert ' ' to '+' or not + * @param normalizeBreaks IN: Whether to convert CR and LF to CR-LF or not. + * @return Error code or 0 on success + * + * @see uriComposeQueryA + * @see uriComposeQueryMallocA + * @see uriComposeQueryMallocExA + * @see uriComposeQueryMallocExMmA + * @see uriComposeQueryCharsRequiredExA + * @see uriDissectQueryMallocA + * @see uriDissectQueryMallocExA + * @see uriDissectQueryMallocExMmA + * @since 0.7.0 + */ +URI_PUBLIC int URI_FUNC(ComposeQueryEx)(URI_CHAR * dest, + const URI_TYPE(QueryList) * queryList, int maxChars, int * charsWritten, + UriBool spaceToPlus, UriBool normalizeBreaks); + + + +/** + * Converts a query list structure back to a query string. + * Memory for this string is allocated internally. + * The composed string does not start with '?', + * on the way ' ' is converted to '+' and line breaks are + * normalized to "%0D%0A". + * Uses default libc-based memory manager. + * + * @param dest OUT: Output destination + * @param queryList IN: Query list to convert + * @return Error code or 0 on success + * + * @see uriComposeQueryMallocExA + * @see uriComposeQueryMallocExMmA + * @see uriComposeQueryA + * @see uriDissectQueryMallocA + * @see uriDissectQueryMallocExA + * @see uriDissectQueryMallocExMmA + * @since 0.7.0 + */ +URI_PUBLIC int URI_FUNC(ComposeQueryMalloc)(URI_CHAR ** dest, + const URI_TYPE(QueryList) * queryList); + + + +/** + * Converts a query list structure back to a query string. + * Memory for this string is allocated internally. + * The composed string does not start with '?'. + * Uses default libc-based memory manager. + * + * @param dest OUT: Output destination + * @param queryList IN: Query list to convert + * @param spaceToPlus IN: Whether to convert ' ' to '+' or not + * @param normalizeBreaks IN: Whether to convert CR and LF to CR-LF or not. + * @return Error code or 0 on success + * + * @see uriComposeQueryMallocA + * @see uriComposeQueryMallocExMmA + * @see uriComposeQueryExA + * @see uriDissectQueryMallocA + * @see uriDissectQueryMallocExA + * @see uriDissectQueryMallocExMmA + * @since 0.7.0 + */ +URI_PUBLIC int URI_FUNC(ComposeQueryMallocEx)(URI_CHAR ** dest, + const URI_TYPE(QueryList) * queryList, + UriBool spaceToPlus, UriBool normalizeBreaks); + + + +/** + * Converts a query list structure back to a query string. + * Memory for this string is allocated internally. + * The composed string does not start with '?'. + * + * @param dest OUT: Output destination + * @param queryList IN: Query list to convert + * @param spaceToPlus IN: Whether to convert ' ' to '+' or not + * @param normalizeBreaks IN: Whether to convert CR and LF to CR-LF or not. + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriComposeQueryMallocA + * @see uriComposeQueryMallocExA + * @see uriComposeQueryExA + * @see uriDissectQueryMallocA + * @see uriDissectQueryMallocExA + * @see uriDissectQueryMallocExMmA + * @since 0.9.0 + */ +URI_PUBLIC int URI_FUNC(ComposeQueryMallocExMm)(URI_CHAR ** dest, + const URI_TYPE(QueryList) * queryList, + UriBool spaceToPlus, UriBool normalizeBreaks, + UriMemoryManager * memory); + + + +/** + * Constructs a query list from the raw query string of a given URI. + * On the way '+' is converted back to ' ', line breaks are not modified. + * Uses default libc-based memory manager. + * + * @param dest OUT: Output destination + * @param itemCount OUT: Number of items found, can be NULL + * @param first IN: Pointer to first character after '?' + * @param afterLast IN: Pointer to character after the last one still in + * @return Error code or 0 on success + * + * @see uriDissectQueryMallocExA + * @see uriDissectQueryMallocExMmA + * @see uriComposeQueryA + * @see uriFreeQueryListA + * @see uriFreeQueryListMmA + * @since 0.7.0 + */ +URI_PUBLIC int URI_FUNC(DissectQueryMalloc)(URI_TYPE(QueryList) ** dest, + int * itemCount, const URI_CHAR * first, const URI_CHAR * afterLast); + + + +/** + * Constructs a query list from the raw query string of a given URI. + * Uses default libc-based memory manager. + * + * @param dest OUT: Output destination + * @param itemCount OUT: Number of items found, can be NULL + * @param first IN: Pointer to first character after '?' + * @param afterLast IN: Pointer to character after the last one still in + * @param plusToSpace IN: Whether to convert '+' to ' ' or not + * @param breakConversion IN: Line break conversion mode + * @return Error code or 0 on success + * + * @see uriDissectQueryMallocA + * @see uriDissectQueryMallocExMmA + * @see uriComposeQueryExA + * @see uriFreeQueryListA + * @since 0.7.0 + */ +URI_PUBLIC int URI_FUNC(DissectQueryMallocEx)(URI_TYPE(QueryList) ** dest, + int * itemCount, const URI_CHAR * first, const URI_CHAR * afterLast, + UriBool plusToSpace, UriBreakConversion breakConversion); + + + +/** + * Constructs a query list from the raw query string of a given URI. + * + * @param dest OUT: Output destination + * @param itemCount OUT: Number of items found, can be NULL + * @param first IN: Pointer to first character after '?' + * @param afterLast IN: Pointer to character after the last one still in + * @param plusToSpace IN: Whether to convert '+' to ' ' or not + * @param breakConversion IN: Line break conversion mode + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriDissectQueryMallocA + * @see uriDissectQueryMallocExA + * @see uriComposeQueryExA + * @see uriFreeQueryListA + * @see uriFreeQueryListMmA + * @since 0.9.0 + */ +URI_PUBLIC int URI_FUNC(DissectQueryMallocExMm)(URI_TYPE(QueryList) ** dest, + int * itemCount, const URI_CHAR * first, const URI_CHAR * afterLast, + UriBool plusToSpace, UriBreakConversion breakConversion, + UriMemoryManager * memory); + + + +/** + * Frees all memory associated with the given query list. + * The structure itself is freed as well. + * + * @param queryList INOUT: Query list to free + * + * @see uriFreeQueryListMmA + * @since 0.7.0 + */ +URI_PUBLIC void URI_FUNC(FreeQueryList)(URI_TYPE(QueryList) * queryList); + + + +/** + * Frees all memory associated with the given query list. + * The structure itself is freed as well. + * + * @param queryList INOUT: Query list to free + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriFreeQueryListA + * @since 0.9.0 + */ +URI_PUBLIC int URI_FUNC(FreeQueryListMm)(URI_TYPE(QueryList) * queryList, + UriMemoryManager * memory); + + + +/** + * Makes the %URI hold copies of strings so that it no longer depends + * on the original %URI string. If the %URI is already owner of copies, + * this function returns URI_TRUE and does not modify the %URI further. + * + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to make independent + * @return Error code or 0 on success + * + * @see uriMakeOwnerMmA + * @since 0.9.4 + */ +URI_PUBLIC int URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri); + + + +/** + * Makes the %URI hold copies of strings so that it no longer depends + * on the original %URI string. If the %URI is already owner of copies, + * this function returns URI_TRUE and does not modify the %URI further. + * + * @param uri INOUT: %URI to make independent + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriMakeOwnerA + * @since 0.9.4 + */ +URI_PUBLIC int URI_FUNC(MakeOwnerMm)(URI_TYPE(Uri) * uri, + UriMemoryManager * memory); + + + +#ifdef __cplusplus +} +#endif + + + +#endif +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriBase.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriBase.h new file mode 100644 index 0000000..6415406 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriBase.h @@ -0,0 +1,373 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song + * Copyright (C) 2007, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file UriBase.h + * Holds definitions independent of the encoding pass. + */ + +#ifndef URI_BASE_H +#define URI_BASE_H 1 + + + +/* Version helper macro */ +#define URI_ANSI_TO_UNICODE(x) L##x + + + +/* Version */ +#define URI_VER_MAJOR 0 +#define URI_VER_MINOR 9 +#define URI_VER_RELEASE 8 +#define URI_VER_SUFFIX_ANSI "" +#define URI_VER_SUFFIX_UNICODE URI_ANSI_TO_UNICODE(URI_VER_SUFFIX_ANSI) + + + +/* More version helper macros */ +#define URI_INT_TO_ANSI_HELPER(x) #x +#define URI_INT_TO_ANSI(x) URI_INT_TO_ANSI_HELPER(x) + +#define URI_INT_TO_UNICODE_HELPER(x) URI_ANSI_TO_UNICODE(#x) +#define URI_INT_TO_UNICODE(x) URI_INT_TO_UNICODE_HELPER(x) + +#define URI_VER_ANSI_HELPER(ma, mi, r, s) \ + URI_INT_TO_ANSI(ma) "." \ + URI_INT_TO_ANSI(mi) "." \ + URI_INT_TO_ANSI(r) \ + s + +#define URI_VER_UNICODE_HELPER(ma, mi, r, s) \ + URI_INT_TO_UNICODE(ma) L"." \ + URI_INT_TO_UNICODE(mi) L"." \ + URI_INT_TO_UNICODE(r) \ + s + + + +/* Full version strings */ +#define URI_VER_ANSI URI_VER_ANSI_HELPER(URI_VER_MAJOR, URI_VER_MINOR, URI_VER_RELEASE, URI_VER_SUFFIX_ANSI) +#define URI_VER_UNICODE URI_VER_UNICODE_HELPER(URI_VER_MAJOR, URI_VER_MINOR, URI_VER_RELEASE, URI_VER_SUFFIX_UNICODE) + + + +/* Unused parameter macro */ +#ifdef __GNUC__ +# define URI_UNUSED(x) unused_##x __attribute__((unused)) +#else +# define URI_UNUSED(x) x +#endif + + + +/* Import/export decorator */ +#if defined(_MSC_VER) +# if 1 // defined(URI_STATIC_BUILD) +# define URI_PUBLIC +# elif defined(URI_LIBRARY_BUILD) +# define URI_PUBLIC __declspec(dllexport) +# else +# define URI_PUBLIC __declspec(dllimport) +# endif +#else +# if ! defined(URI_LIBRARY_BUILD) || ! defined(URI_VISIBILITY) +# define URI_PUBLIC +# else +# define URI_PUBLIC __attribute__ ((visibility("default"))) +# endif +#endif + + + +typedef int UriBool; /**< Boolean type */ + +#define URI_TRUE 1 +#define URI_FALSE 0 + + + +/* Shared errors */ +#define URI_SUCCESS 0 +#define URI_ERROR_SYNTAX 1 /* Parsed text violates expected format */ +#define URI_ERROR_NULL 2 /* One of the params passed was NULL + although it mustn't be */ +#define URI_ERROR_MALLOC 3 /* Requested memory could not be allocated */ +#define URI_ERROR_OUTPUT_TOO_LARGE 4 /* Some output is to large for the receiving buffer */ +#define URI_ERROR_NOT_IMPLEMENTED 8 /* The called function is not implemented yet */ +#define URI_ERROR_RANGE_INVALID 9 /* The parameters passed contained invalid ranges */ +#define URI_ERROR_MEMORY_MANAGER_INCOMPLETE 10 /* [>=0.9.0] The UriMemoryManager passed does not implement all needed functions */ + + +/* Errors specific to ToString */ +#define URI_ERROR_TOSTRING_TOO_LONG URI_ERROR_OUTPUT_TOO_LARGE /* Deprecated, test for URI_ERROR_OUTPUT_TOO_LARGE instead */ + +/* Errors specific to AddBaseUri */ +#define URI_ERROR_ADDBASE_REL_BASE 5 /* Given base is not absolute */ + +/* Errors specific to RemoveBaseUri */ +#define URI_ERROR_REMOVEBASE_REL_BASE 6 /* Given base is not absolute */ +#define URI_ERROR_REMOVEBASE_REL_SOURCE 7 /* Given base is not absolute */ + +/* Error specific to uriTestMemoryManager */ +#define URI_ERROR_MEMORY_MANAGER_FAULTY 11 /* [>=0.9.0] The UriMemoryManager given did not pass the test suite */ + + +#ifndef URI_DOXYGEN +# include /* For NULL, snprintf */ +# include /* For wchar_t */ +# include /* For strlen, memset, memcpy */ +# include /* For malloc */ +#endif /* URI_DOXYGEN */ + + + +/** + * Holds an IPv4 address. + */ +typedef struct UriIp4Struct { + unsigned char data[4]; /**< Each octet in one byte */ +} UriIp4; /**< @copydoc UriIp4Struct */ + + + +/** + * Holds an IPv6 address. + */ +typedef struct UriIp6Struct { + unsigned char data[16]; /**< Each quad in two bytes */ +} UriIp6; /**< @copydoc UriIp6Struct */ + + +struct UriMemoryManagerStruct; /* foward declaration to break loop */ + + +/** + * Function signature that custom malloc(3) functions must conform to + * + * @since 0.9.0 + */ +typedef void * (*UriFuncMalloc)(struct UriMemoryManagerStruct *, size_t); + +/** + * Function signature that custom calloc(3) functions must conform to + * + * @since 0.9.0 + */ +typedef void * (*UriFuncCalloc)(struct UriMemoryManagerStruct *, size_t, size_t); + +/** + * Function signature that custom realloc(3) functions must conform to + * + * @since 0.9.0 + */ +typedef void * (*UriFuncRealloc)(struct UriMemoryManagerStruct *, void *, size_t); + +/** + * Function signature that custom reallocarray(3) functions must conform to + * + * @since 0.9.0 + */ +typedef void * (*UriFuncReallocarray)(struct UriMemoryManagerStruct *, void *, size_t, size_t); + +/** + * Function signature that custom free(3) functions must conform to + * + * @since 0.9.0 + */ +typedef void (*UriFuncFree)(struct UriMemoryManagerStruct *, void *); + + +/** + * Class-like interface of custom memory managers + * + * @see uriCompleteMemoryManager + * @see uriEmulateCalloc + * @see uriEmulateReallocarray + * @see uriTestMemoryManager + * @since 0.9.0 + */ +typedef struct UriMemoryManagerStruct { + UriFuncMalloc malloc; /**< Pointer to custom malloc(3) */ + UriFuncCalloc calloc; /**< Pointer to custom calloc(3); to emulate using malloc and memset see uriEmulateCalloc */ + UriFuncRealloc realloc; /**< Pointer to custom realloc(3) */ + UriFuncReallocarray reallocarray; /**< Pointer to custom reallocarray(3); to emulate using realloc see uriEmulateReallocarray */ + UriFuncFree free; /**< Pointer to custom free(3) */ + void * userData; /**< Pointer to data that the other function members need access to */ +} UriMemoryManager; /**< @copydoc UriMemoryManagerStruct */ + + +/** + * Specifies a line break conversion mode. + */ +typedef enum UriBreakConversionEnum { + URI_BR_TO_LF, /**< Convert to Unix line breaks ("\\x0a") */ + URI_BR_TO_CRLF, /**< Convert to Windows line breaks ("\\x0d\\x0a") */ + URI_BR_TO_CR, /**< Convert to Macintosh line breaks ("\\x0d") */ + URI_BR_TO_UNIX = URI_BR_TO_LF, /**< @copydoc UriBreakConversionEnum::URI_BR_TO_LF */ + URI_BR_TO_WINDOWS = URI_BR_TO_CRLF, /**< @copydoc UriBreakConversionEnum::URI_BR_TO_CRLF */ + URI_BR_TO_MAC = URI_BR_TO_CR, /**< @copydoc UriBreakConversionEnum::URI_BR_TO_CR */ + URI_BR_DONT_TOUCH /**< Copy line breaks unmodified */ +} UriBreakConversion; /**< @copydoc UriBreakConversionEnum */ + + + +/** + * Specifies which component of a %URI has to be normalized. + */ +typedef enum UriNormalizationMaskEnum { + URI_NORMALIZED = 0, /**< Do not normalize anything */ + URI_NORMALIZE_SCHEME = 1 << 0, /**< Normalize scheme (fix uppercase letters) */ + URI_NORMALIZE_USER_INFO = 1 << 1, /**< Normalize user info (fix uppercase percent-encodings) */ + URI_NORMALIZE_HOST = 1 << 2, /**< Normalize host (fix uppercase letters) */ + URI_NORMALIZE_PATH = 1 << 3, /**< Normalize path (fix uppercase percent-encodings and redundant dot segments) */ + URI_NORMALIZE_QUERY = 1 << 4, /**< Normalize query (fix uppercase percent-encodings) */ + URI_NORMALIZE_FRAGMENT = 1 << 5 /**< Normalize fragment (fix uppercase percent-encodings) */ +} UriNormalizationMask; /**< @copydoc UriNormalizationMaskEnum */ + + + +/** + * Specifies how to resolve %URI references. + */ +typedef enum UriResolutionOptionsEnum { + URI_RESOLVE_STRICTLY = 0, /**< Full RFC conformance */ + URI_RESOLVE_IDENTICAL_SCHEME_COMPAT = 1 << 0 /**< Treat %URI to resolve with identical scheme as having no scheme */ +} UriResolutionOptions; /**< @copydoc UriResolutionOptionsEnum */ + + + +/** + * Wraps a memory manager backend that only provides malloc and free + * to make a complete memory manager ready to be used. + * + * The core feature of this wrapper is that you don't need to implement + * realloc if you don't want to. The wrapped memory manager uses + * backend->malloc, memcpy, and backend->free and soieof(size_t) extra + * bytes per allocation to emulate fallback realloc for you. + * + * memory->calloc is uriEmulateCalloc. + * memory->free uses backend->free and handles the size header. + * memory->malloc uses backend->malloc and adds a size header. + * memory->realloc uses memory->malloc, memcpy, and memory->free and reads + * the size header. + * memory->reallocarray is uriEmulateReallocarray. + * + * The internal workings behind memory->free, memory->malloc, and + * memory->realloc may change so the functions exposed by these function + * pointer sshould be consided internal and not public API. + * + * @param memory OUT: Where to write the wrapped memory manager to + * @param backend IN: Memory manager to use as a backend + * @return Error code or 0 on success + * + * @see uriEmulateCalloc + * @see uriEmulateReallocarray + * @see UriMemoryManager + * @since 0.9.0 + */ +URI_PUBLIC int uriCompleteMemoryManager(UriMemoryManager * memory, + UriMemoryManager * backend); + + + +/** + * Offers emulation of calloc(3) based on memory->malloc and memset. + * See "man 3 calloc" as well. + * + * @param memory IN: Memory manager to use, should not be NULL + * @param nmemb IN: Number of elements to allocate + * @param size IN: Size in bytes per element + * @return Pointer to allocated memory or NULL + * + * @see uriCompleteMemoryManager + * @see uriEmulateReallocarray + * @see UriMemoryManager + * @since 0.9.0 + */ +URI_PUBLIC void * uriEmulateCalloc(UriMemoryManager * memory, + size_t nmemb, size_t size); + + + +/** + * Offers emulation of reallocarray(3) based on memory->realloc. + * See "man 3 reallocarray" as well. + * + * @param memory IN: Memory manager to use, should not be NULL + * @param ptr IN: Pointer allocated using memory->malloc/... or NULL + * @param nmemb IN: Number of elements to allocate + * @param size IN: Size in bytes per element + * @return Pointer to allocated memory or NULL + * + * @see uriCompleteMemoryManager + * @see uriEmulateCalloc + * @see UriMemoryManager + * @since 0.9.0 + */ +URI_PUBLIC void * uriEmulateReallocarray(UriMemoryManager * memory, + void * ptr, size_t nmemb, size_t size); + + + +/** + * Run multiple tests against a given memory manager. + * For example, one test + * 1. allocates a small amount of memory, + * 2. writes some magic bytes to it, + * 3. reallocates it, + * 4. checks that previous values are still present, + * 5. and frees that memory. + * + * It is recommended to compile with AddressSanitizer enabled + * to take full advantage of uriTestMemoryManager. + * + * @param memory IN: Memory manager to use, should not be NULL + * @return Error code or 0 on success + * + * @see uriEmulateCalloc + * @see uriEmulateReallocarray + * @see UriMemoryManager + * @since 0.9.0 + */ +URI_PUBLIC int uriTestMemoryManager(UriMemoryManager * memory); + + + +#endif /* URI_BASE_H */ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriDefsAnsi.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriDefsAnsi.h new file mode 100644 index 0000000..af581b9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriDefsAnsi.h @@ -0,0 +1,82 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song + * Copyright (C) 2007, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file UriDefsAnsi.h + * Holds definitions for the ANSI pass. + * NOTE: This header is included N times, not once. + */ + +/* Allow multi inclusion */ +#include "UriDefsConfig.h" + + + +#undef URI_CHAR +#define URI_CHAR char + +#undef _UT +#define _UT(x) x + + + +#undef URI_FUNC +#define URI_FUNC(x) uri##x##A + +#undef URI_TYPE +#define URI_TYPE(x) Uri##x##A + + + +#undef URI_STRLEN +#define URI_STRLEN strlen +#undef URI_STRCPY +#define URI_STRCPY strcpy +#undef URI_STRCMP +#define URI_STRCMP strcmp +#undef URI_STRNCMP +#define URI_STRNCMP strncmp + +/* TODO Remove on next source-compatibility break */ +#undef URI_SNPRINTF +#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32)) +# define URI_SNPRINTF _snprintf +#else +# define URI_SNPRINTF snprintf +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriDefsConfig.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriDefsConfig.h new file mode 100644 index 0000000..51bc93e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriDefsConfig.h @@ -0,0 +1,101 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song + * Copyright (C) 2007, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file UriDefsConfig.h + * Adjusts the internal configuration after processing external definitions. + */ + +#ifndef URI_DEFS_CONFIG_H +#define URI_DEFS_CONFIG_H 1 + + + +/* Deny external overriding */ +#undef URI_ENABLE_ANSI /* Internal for !URI_NO_ANSI */ +#undef URI_ENABLE_UNICODE /* Internal for !URI_NO_UNICODE */ + + + +/* Encoding */ +#ifdef URI_NO_ANSI +# ifdef URI_NO_UNICODE +/* No encoding at all */ +# error URI_NO_ANSI and URI_NO_UNICODE cannot go together. +# else +/* Wide strings only */ +# define URI_ENABLE_UNICODE 1 +# endif +#else +# ifdef URI_NO_UNICODE +/* Narrow strings only */ +# define URI_ENABLE_ANSI 1 +# else +/* Both narrow and wide strings */ +# define URI_ENABLE_ANSI 1 +# define URI_ENABLE_UNICODE 1 +# endif +#endif + + + +/* Function inlining, not ANSI/ISO C! */ +#if defined(URI_DOXYGEN) +# define URI_INLINE +#elif defined(__INTEL_COMPILER) +/* Intel C/C++ */ +/* http://predef.sourceforge.net/precomp.html#sec20 */ +/* http://www.intel.com/support/performancetools/c/windows/sb/CS-007751.htm#2 */ +# define URI_INLINE __forceinline +#elif defined(_MSC_VER) +/* Microsoft Visual C++ */ +/* http://predef.sourceforge.net/precomp.html#sec32 */ +/* http://msdn2.microsoft.com/en-us/library/ms882281.aspx */ +# define URI_INLINE __forceinline +#elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) +/* C99, "inline" is a keyword */ +# define URI_INLINE inline +#else +/* No inlining */ +# define URI_INLINE +#endif + + + +#endif /* URI_DEFS_CONFIG_H */ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriDefsUnicode.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriDefsUnicode.h new file mode 100644 index 0000000..01421f5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriDefsUnicode.h @@ -0,0 +1,82 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song + * Copyright (C) 2007, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file UriDefsUnicode.h + * Holds definitions for the wide string pass. + * NOTE: This header is included N times, not once. + */ + +/* Allow multi inclusion */ +#include "UriDefsConfig.h" + + + +#undef URI_CHAR +#define URI_CHAR wchar_t + +#undef _UT +#define _UT(x) L##x + + + +#undef URI_FUNC +#define URI_FUNC(x) uri##x##W + +#undef URI_TYPE +#define URI_TYPE(x) Uri##x##W + + + +#undef URI_STRLEN +#define URI_STRLEN wcslen +#undef URI_STRCPY +#define URI_STRCPY wcscpy +#undef URI_STRCMP +#define URI_STRCMP wcscmp +#undef URI_STRNCMP +#define URI_STRNCMP wcsncmp + +/* TODO Remove on next source-compatibility break */ +#undef URI_SNPRINTF +#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32)) +# define URI_SNPRINTF _snwprintf +#else +# define URI_SNPRINTF swprintf +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriIp4.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriIp4.h new file mode 100644 index 0000000..c2e59a6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/uriparser/UriIp4.h @@ -0,0 +1,110 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song + * Copyright (C) 2007, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file UriIp4.h + * Holds the IPv4 parser interface. + * NOTE: This header includes itself twice. + */ + +#if (defined(URI_PASS_ANSI) && !defined(URI_IP4_TWICE_H_ANSI)) \ + || (defined(URI_PASS_UNICODE) && !defined(URI_IP4_TWICE_H_UNICODE)) \ + || (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* What encodings are enabled? */ +#include "UriDefsConfig.h" +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriIp4.h" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriIp4.h" +# undef URI_PASS_UNICODE +# endif +/* Only one pass for each encoding */ +#elif (defined(URI_PASS_ANSI) && !defined(URI_IP4_TWICE_H_ANSI) \ + && defined(URI_ENABLE_ANSI)) || (defined(URI_PASS_UNICODE) \ + && !defined(URI_IP4_TWICE_H_UNICODE) && defined(URI_ENABLE_UNICODE)) +# ifdef URI_PASS_ANSI +# define URI_IP4_TWICE_H_ANSI 1 +# include "UriDefsAnsi.h" +# else +# define URI_IP4_TWICE_H_UNICODE 1 +# include "UriDefsUnicode.h" +# include +# endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifndef URI_DOXYGEN +# include "UriBase.h" +#endif + + + +/** + * Converts a IPv4 text representation into four bytes. + * + * @param octetOutput Output destination + * @param first First character of IPv4 text to parse + * @param afterLast Position to stop parsing at + * @return Error code or 0 on success + */ +URI_PUBLIC int URI_FUNC(ParseIpFourAddress)(unsigned char * octetOutput, + const URI_CHAR * first, const URI_CHAR * afterLast); + + + +#ifdef __cplusplus +} +#endif + + + +#endif +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/cmake/zlib-ng/zlib-ng-release.cmake b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/cmake/zlib-ng/zlib-ng-release.cmake new file mode 100644 index 0000000..4c7457e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/cmake/zlib-ng/zlib-ng-release.cmake @@ -0,0 +1,19 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "zlib-ng::zlib" for configuration "Release" +set_property(TARGET zlib-ng::zlib APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(zlib-ng::zlib PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libz-ng.a" + ) + +list(APPEND _cmake_import_check_targets zlib-ng::zlib ) +list(APPEND _cmake_import_check_files_for_zlib-ng::zlib "${_IMPORT_PREFIX}/lib/libz-ng.a" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/cmake/zlib-ng/zlib-ng.cmake b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/cmake/zlib-ng/zlib-ng.cmake new file mode 100644 index 0000000..034b039 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/cmake/zlib-ng/zlib-ng.cmake @@ -0,0 +1,107 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.3") + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.3...3.29) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS zlib-ng::zlib) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target zlib-ng::zlib +add_library(zlib-ng::zlib STATIC IMPORTED) + +set_target_properties(zlib-ng::zlib PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "ZLIBNG_NATIVE_API" + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" +) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/zlib-ng-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + if(CMAKE_VERSION VERSION_LESS "3.28" + OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} + OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + endif() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/RapidJSON.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/RapidJSON.pc new file mode 100644 index 0000000..70a293c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/RapidJSON.pc @@ -0,0 +1,9 @@ +prefix=${pcfiledir}/../.. +includedir=${prefix}/include + +Name: RapidJSON +Description: A fast JSON parser/generator for C++ with both SAX/DOM style API +Version: 1.1.0 +URL: https://github.com/Tencent/rapidjson + +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_absl_check.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_absl_check.pc new file mode 100644 index 0000000..2a3f96a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_absl_check.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_absl_check +Description: Abseil absl_check library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_check_impl = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_absl_log.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_absl_log.pc new file mode 100644 index 0000000..cd4d88d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_absl_log.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_absl_log +Description: Abseil absl_log library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_log_impl = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_absl_vlog_is_on.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_absl_vlog_is_on.pc new file mode 100644 index 0000000..fcfb211 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_absl_vlog_is_on.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_absl_vlog_is_on +Description: Abseil absl_vlog_is_on library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_vlog_config_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_algorithm.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_algorithm.pc new file mode 100644 index 0000000..2699e89 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_algorithm.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_algorithm +Description: Abseil algorithm library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_algorithm_container.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_algorithm_container.pc new file mode 100644 index 0000000..1ef0909 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_algorithm_container.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_algorithm_container +Description: Abseil algorithm_container library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_algorithm = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_meta = 20240722, absl_nullability = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_any.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_any.pc new file mode 100644 index 0000000..69034ca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_any.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_any +Description: Abseil any library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_any_cast = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_fast_type_id = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_any_invocable.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_any_invocable.pc new file mode 100644 index 0000000..5a8c0d5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_any_invocable.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_any_invocable +Description: Abseil any_invocable library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_atomic_hook.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_atomic_hook.pc new file mode 100644 index 0000000..617f0f5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_atomic_hook.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_atomic_hook +Description: Abseil atomic_hook library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bad_any_cast.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bad_any_cast.pc new file mode 100644 index 0000000..3b5b029 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bad_any_cast.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_any_cast +Description: Abseil bad_any_cast library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_any_cast_impl = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bad_any_cast_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bad_any_cast_impl.pc new file mode 100644 index 0000000..ea27e16 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bad_any_cast_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_any_cast_impl +Description: Abseil bad_any_cast_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_bad_any_cast_impl +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bad_optional_access.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bad_optional_access.pc new file mode 100644 index 0000000..4659ea9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bad_optional_access.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_optional_access +Description: Abseil bad_optional_access library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_bad_optional_access +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bad_variant_access.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bad_variant_access.pc new file mode 100644 index 0000000..787f27e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bad_variant_access.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_variant_access +Description: Abseil bad_variant_access library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_bad_variant_access +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_base.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_base.pc new file mode 100644 index 0000000..1e6062c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_base.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_base +Description: Abseil base library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_base +Requires: absl_atomic_hook = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_log_severity = 20240722, absl_nullability = 20240722, absl_raw_logging_internal = 20240722, absl_spinlock_wait = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_base_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_base_internal.pc new file mode 100644 index 0000000..0d5e854 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_base_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_base_internal +Description: Abseil base_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bind_front.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bind_front.pc new file mode 100644 index 0000000..43ba4f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bind_front.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bind_front +Description: Abseil bind_front library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_compressed_tuple = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bits.pc new file mode 100644 index 0000000..85ab7f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bits +Description: Abseil bits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bounded_utf8_length_sequence.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bounded_utf8_length_sequence.pc new file mode 100644 index 0000000..fe4d6b4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_bounded_utf8_length_sequence.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bounded_utf8_length_sequence +Description: Abseil bounded_utf8_length_sequence library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_btree.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_btree.pc new file mode 100644 index 0000000..2fffd58 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_btree.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_btree +Description: Abseil btree library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_common_policy_traits = 20240722, absl_compare = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_container_common = 20240722, absl_container_memory = 20240722, absl_cord = 20240722, absl_core_headers = 20240722, absl_layout = 20240722, absl_memory = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_charset.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_charset.pc new file mode 100644 index 0000000..18ecd6b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_charset.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_charset +Description: Abseil charset library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_string_view = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_check.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_check.pc new file mode 100644 index 0000000..e39177d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_check.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_check +Description: Abseil check library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_check_impl = 20240722, absl_core_headers = 20240722, absl_log_internal_check_op = 20240722, absl_log_internal_conditions = 20240722, absl_log_internal_message = 20240722, absl_log_internal_strip = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_city.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_city.pc new file mode 100644 index 0000000..a4f43bf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_city.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_city +Description: Abseil city library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_city +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_civil_time.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_civil_time.pc new file mode 100644 index 0000000..a660426 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_civil_time.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_civil_time +Description: Abseil civil_time library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_civil_time +Requires: +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cleanup.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cleanup.pc new file mode 100644 index 0000000..958bbe6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cleanup.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cleanup +Description: Abseil cleanup library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_cleanup_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cleanup_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cleanup_internal.pc new file mode 100644 index 0000000..738d222 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cleanup_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cleanup_internal +Description: Abseil cleanup_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_core_headers = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_common_policy_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_common_policy_traits.pc new file mode 100644 index 0000000..ea0451a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_common_policy_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_common_policy_traits +Description: Abseil common_policy_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_compare.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_compare.pc new file mode 100644 index 0000000..75426b5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_compare.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_compare +Description: Abseil compare library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_compressed_tuple.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_compressed_tuple.pc new file mode 100644 index 0000000..70079e6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_compressed_tuple.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_compressed_tuple +Description: Abseil compressed_tuple library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_config.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_config.pc new file mode 100644 index 0000000..d439766 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_config.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_config +Description: Abseil config library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_container_common.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_container_common.pc new file mode 100644 index 0000000..87783eb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_container_common.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_container_common +Description: Abseil container_common library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_container_memory.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_container_memory.pc new file mode 100644 index 0000000..b14fd4e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_container_memory.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_container_memory +Description: Abseil container_memory library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_memory = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cord.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cord.pc new file mode 100644 index 0000000..9ba4365 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cord.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cord +Description: Abseil cord library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cord +Requires: absl_base = 20240722, absl_config = 20240722, absl_cord_internal = 20240722, absl_cordz_functions = 20240722, absl_cordz_info = 20240722, absl_cordz_update_scope = 20240722, absl_cordz_update_tracker = 20240722, absl_core_headers = 20240722, absl_crc32c = 20240722, absl_crc_cord_state = 20240722, absl_endian = 20240722, absl_function_ref = 20240722, absl_inlined_vector = 20240722, absl_nullability = 20240722, absl_optional = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722, absl_strings = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cord_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cord_internal.pc new file mode 100644 index 0000000..4c68ba2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cord_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cord_internal +Description: Abseil cord_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cord_internal +Requires: absl_base_internal = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_container_memory = 20240722, absl_compare = 20240722, absl_core_headers = 20240722, absl_crc_cord_state = 20240722, absl_endian = 20240722, absl_inlined_vector = 20240722, absl_layout = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_functions.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_functions.pc new file mode 100644 index 0000000..8fa4c86 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_functions.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_functions +Description: Abseil cordz_functions library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_functions +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_exponential_biased = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_handle.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_handle.pc new file mode 100644 index 0000000..3a0cee3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_handle.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_handle +Description: Abseil cordz_handle library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_handle +Requires: absl_base = 20240722, absl_config = 20240722, absl_no_destructor = 20240722, absl_raw_logging_internal = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_info.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_info.pc new file mode 100644 index 0000000..765e2b6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_info.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_info +Description: Abseil cordz_info library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_info +Requires: absl_base = 20240722, absl_config = 20240722, absl_cord_internal = 20240722, absl_cordz_functions = 20240722, absl_cordz_handle = 20240722, absl_cordz_statistics = 20240722, absl_cordz_update_tracker = 20240722, absl_core_headers = 20240722, absl_inlined_vector = 20240722, absl_span = 20240722, absl_raw_logging_internal = 20240722, absl_stacktrace = 20240722, absl_synchronization = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_sample_token.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_sample_token.pc new file mode 100644 index 0000000..9fc4e9d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_sample_token.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_sample_token +Description: Abseil cordz_sample_token library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_sample_token +Requires: absl_config = 20240722, absl_cordz_handle = 20240722, absl_cordz_info = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_statistics.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_statistics.pc new file mode 100644 index 0000000..30a9e87 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_statistics.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_statistics +Description: Abseil cordz_statistics library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_cordz_update_tracker = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_update_scope.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_update_scope.pc new file mode 100644 index 0000000..d999f44 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_update_scope.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_update_scope +Description: Abseil cordz_update_scope library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_cord_internal = 20240722, absl_cordz_info = 20240722, absl_cordz_update_tracker = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_update_tracker.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_update_tracker.pc new file mode 100644 index 0000000..9884960 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_cordz_update_tracker.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_update_tracker +Description: Abseil cordz_update_tracker library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_core_headers.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_core_headers.pc new file mode 100644 index 0000000..9650f37 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_core_headers.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_core_headers +Description: Abseil core_headers library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_crc32c.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_crc32c.pc new file mode 100644 index 0000000..69b6592 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_crc32c.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc32c +Description: Abseil crc32c library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc32c +Requires: absl_crc_cpu_detect = 20240722, absl_crc_internal = 20240722, absl_non_temporal_memcpy = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_prefetch = 20240722, absl_str_format = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_crc_cord_state.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_crc_cord_state.pc new file mode 100644 index 0000000..8ea2b59 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_crc_cord_state.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc_cord_state +Description: Abseil crc_cord_state library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc_cord_state +Requires: absl_crc32c = 20240722, absl_config = 20240722, absl_strings = 20240722, absl_no_destructor = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_crc_cpu_detect.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_crc_cpu_detect.pc new file mode 100644 index 0000000..04dfb78 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_crc_cpu_detect.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc_cpu_detect +Description: Abseil crc_cpu_detect library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc_cpu_detect +Requires: absl_base = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_crc_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_crc_internal.pc new file mode 100644 index 0000000..e13a8f6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_crc_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc_internal +Description: Abseil crc_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc_internal +Requires: absl_crc_cpu_detect = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_prefetch = 20240722, absl_raw_logging_internal = 20240722, absl_memory = 20240722, absl_bits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_debugging.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_debugging.pc new file mode 100644 index 0000000..62304ae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_debugging.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_debugging +Description: Abseil debugging library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_stacktrace = 20240722, absl_leak_check = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_debugging_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_debugging_internal.pc new file mode 100644 index 0000000..1ca2457 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_debugging_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_debugging_internal +Description: Abseil debugging_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_debugging_internal +Requires: absl_core_headers = 20240722, absl_config = 20240722, absl_dynamic_annotations = 20240722, absl_errno_saver = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_decode_rust_punycode.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_decode_rust_punycode.pc new file mode 100644 index 0000000..ae5d976 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_decode_rust_punycode.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_decode_rust_punycode +Description: Abseil decode_rust_punycode library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_decode_rust_punycode +Requires: absl_bounded_utf8_length_sequence = 20240722, absl_config = 20240722, absl_nullability = 20240722, absl_utf8_for_code_point = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_demangle_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_demangle_internal.pc new file mode 100644 index 0000000..0ec9fa6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_demangle_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_demangle_internal +Description: Abseil demangle_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_demangle_internal +Requires: absl_config = 20240722, absl_demangle_rust = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_demangle_rust.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_demangle_rust.pc new file mode 100644 index 0000000..51ce133 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_demangle_rust.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_demangle_rust +Description: Abseil demangle_rust library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_demangle_rust +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_decode_rust_punycode = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_die_if_null.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_die_if_null.pc new file mode 100644 index 0000000..acf5b4d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_die_if_null.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_die_if_null +Description: Abseil die_if_null library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_die_if_null +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_dynamic_annotations.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_dynamic_annotations.pc new file mode 100644 index 0000000..f7f3815 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_dynamic_annotations.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_dynamic_annotations +Description: Abseil dynamic_annotations library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_endian.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_endian.pc new file mode 100644 index 0000000..3d00574 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_endian.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_endian +Description: Abseil endian library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_errno_saver.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_errno_saver.pc new file mode 100644 index 0000000..65c2ffb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_errno_saver.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_errno_saver +Description: Abseil errno_saver library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_examine_stack.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_examine_stack.pc new file mode 100644 index 0000000..9c9a61b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_examine_stack.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_examine_stack +Description: Abseil examine_stack library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_examine_stack +Requires: absl_stacktrace = 20240722, absl_symbolize = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_exponential_biased.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_exponential_biased.pc new file mode 100644 index 0000000..edcf6f7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_exponential_biased.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_exponential_biased +Description: Abseil exponential_biased library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_exponential_biased +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_failure_signal_handler.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_failure_signal_handler.pc new file mode 100644 index 0000000..73b3af7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_failure_signal_handler.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_failure_signal_handler +Description: Abseil failure_signal_handler library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_failure_signal_handler +Requires: absl_examine_stack = 20240722, absl_stacktrace = 20240722, absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_fast_type_id.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_fast_type_id.pc new file mode 100644 index 0000000..00bee9f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_fast_type_id.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_fast_type_id +Description: Abseil fast_type_id library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_fixed_array.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_fixed_array.pc new file mode 100644 index 0000000..bc11248 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_fixed_array.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_fixed_array +Description: Abseil fixed_array library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_compressed_tuple = 20240722, absl_algorithm = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_throw_delegate = 20240722, absl_memory = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags.pc new file mode 100644 index 0000000..2e7aecd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags +Description: Abseil flags library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_config = 20240722, absl_flags_internal = 20240722, absl_flags_reflection = 20240722, absl_core_headers = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_commandlineflag.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_commandlineflag.pc new file mode 100644 index 0000000..5e61657 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_commandlineflag.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_commandlineflag +Description: Abseil flags_commandlineflag library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_commandlineflag +Requires: absl_config = 20240722, absl_fast_type_id = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_optional = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_commandlineflag_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_commandlineflag_internal.pc new file mode 100644 index 0000000..1436671 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_commandlineflag_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_commandlineflag_internal +Description: Abseil flags_commandlineflag_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_commandlineflag_internal +Requires: absl_config = 20240722, absl_dynamic_annotations = 20240722, absl_fast_type_id = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_config.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_config.pc new file mode 100644 index 0000000..90d32aa --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_config.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_config +Description: Abseil flags_config library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_config +Requires: absl_config = 20240722, absl_flags_path_util = 20240722, absl_flags_program_name = 20240722, absl_core_headers = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_internal.pc new file mode 100644 index 0000000..9ac5cde --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_internal +Description: Abseil flags_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_internal +Requires: absl_base = 20240722, absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_flags_config = 20240722, absl_flags_marshalling = 20240722, absl_synchronization = 20240722, absl_meta = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_marshalling.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_marshalling.pc new file mode 100644 index 0000000..86c8076 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_marshalling.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_marshalling +Description: Abseil flags_marshalling library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_marshalling +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_severity = 20240722, absl_int128 = 20240722, absl_optional = 20240722, absl_strings = 20240722, absl_str_format = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_parse.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_parse.pc new file mode 100644 index 0000000..0c399ae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_parse.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_parse +Description: Abseil flags_parse library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_parse +Requires: absl_algorithm_container = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_flags_config = 20240722, absl_flags = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_flags_internal = 20240722, absl_flags_private_handle_accessor = 20240722, absl_flags_program_name = 20240722, absl_flags_reflection = 20240722, absl_flags_usage = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_path_util.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_path_util.pc new file mode 100644 index 0000000..9adbb6c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_path_util.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_path_util +Description: Abseil flags_path_util library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_private_handle_accessor.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_private_handle_accessor.pc new file mode 100644 index 0000000..2a57aab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_private_handle_accessor.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_private_handle_accessor +Description: Abseil flags_private_handle_accessor library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_private_handle_accessor +Requires: absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_program_name.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_program_name.pc new file mode 100644 index 0000000..1b3370c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_program_name.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_program_name +Description: Abseil flags_program_name library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_program_name +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_flags_path_util = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_reflection.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_reflection.pc new file mode 100644 index 0000000..e373dbb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_reflection.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_reflection +Description: Abseil flags_reflection library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_reflection +Requires: absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_private_handle_accessor = 20240722, absl_flags_config = 20240722, absl_strings = 20240722, absl_synchronization = 20240722, absl_flat_hash_map = 20240722, absl_no_destructor = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_usage.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_usage.pc new file mode 100644 index 0000000..27e5dcf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_usage.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_usage +Description: Abseil flags_usage library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_usage +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_flags_usage_internal = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_usage_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_usage_internal.pc new file mode 100644 index 0000000..e93d28d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flags_usage_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_usage_internal +Description: Abseil flags_usage_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_usage_internal +Requires: absl_config = 20240722, absl_flags_config = 20240722, absl_flags = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_internal = 20240722, absl_flags_path_util = 20240722, absl_flags_private_handle_accessor = 20240722, absl_flags_program_name = 20240722, absl_flags_reflection = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flat_hash_map.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flat_hash_map.pc new file mode 100644 index 0000000..bab2f5e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flat_hash_map.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flat_hash_map +Description: Abseil flat_hash_map library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_core_headers = 20240722, absl_hash_container_defaults = 20240722, absl_raw_hash_map = 20240722, absl_algorithm_container = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flat_hash_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flat_hash_set.pc new file mode 100644 index 0000000..71c94e2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_flat_hash_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flat_hash_set +Description: Abseil flat_hash_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_hash_container_defaults = 20240722, absl_raw_hash_set = 20240722, absl_algorithm_container = 20240722, absl_core_headers = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_function_ref.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_function_ref.pc new file mode 100644 index 0000000..c88a5e3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_function_ref.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_function_ref +Description: Abseil function_ref library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_core_headers = 20240722, absl_any_invocable = 20240722, absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_graphcycles_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_graphcycles_internal.pc new file mode 100644 index 0000000..8de827e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_graphcycles_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_graphcycles_internal +Description: Abseil graphcycles_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_graphcycles_internal +Requires: absl_base = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_malloc_internal = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_has_ostream_operator.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_has_ostream_operator.pc new file mode 100644 index 0000000..843c0c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_has_ostream_operator.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_has_ostream_operator +Description: Abseil has_ostream_operator library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hash.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hash.pc new file mode 100644 index 0000000..f80f599 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hash.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash +Description: Abseil hash library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_hash +Requires: absl_bits = 20240722, absl_city = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_fixed_array = 20240722, absl_function_ref = 20240722, absl_meta = 20240722, absl_int128 = 20240722, absl_strings = 20240722, absl_optional = 20240722, absl_variant = 20240722, absl_utility = 20240722, absl_low_level_hash = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hash_container_defaults.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hash_container_defaults.pc new file mode 100644 index 0000000..5e1ded4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hash_container_defaults.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash_container_defaults +Description: Abseil hash_container_defaults library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_hash_function_defaults = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hash_function_defaults.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hash_function_defaults.pc new file mode 100644 index 0000000..04a4e3b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hash_function_defaults.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash_function_defaults +Description: Abseil hash_function_defaults library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_container_common = 20240722, absl_cord = 20240722, absl_hash = 20240722, absl_strings = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hash_policy_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hash_policy_traits.pc new file mode 100644 index 0000000..e25c47c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hash_policy_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash_policy_traits +Description: Abseil hash_policy_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_common_policy_traits = 20240722, absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hashtable_debug.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hashtable_debug.pc new file mode 100644 index 0000000..5b1ed5f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hashtable_debug.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hashtable_debug +Description: Abseil hashtable_debug library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_hashtable_debug_hooks = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hashtable_debug_hooks.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hashtable_debug_hooks.pc new file mode 100644 index 0000000..9010454 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hashtable_debug_hooks.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hashtable_debug_hooks +Description: Abseil hashtable_debug_hooks library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hashtablez_sampler.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hashtablez_sampler.pc new file mode 100644 index 0000000..2cbd02a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_hashtablez_sampler.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hashtablez_sampler +Description: Abseil hashtablez_sampler library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_hashtablez_sampler +Requires: absl_base = 20240722, absl_config = 20240722, absl_exponential_biased = 20240722, absl_no_destructor = 20240722, absl_raw_logging_internal = 20240722, absl_sample_recorder = 20240722, absl_synchronization = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_if_constexpr.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_if_constexpr.pc new file mode 100644 index 0000000..815d293 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_if_constexpr.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_if_constexpr +Description: Abseil if_constexpr library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_inlined_vector.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_inlined_vector.pc new file mode 100644 index 0000000..aabfd71 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_inlined_vector.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_inlined_vector +Description: Abseil inlined_vector library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_algorithm = 20240722, absl_core_headers = 20240722, absl_inlined_vector_internal = 20240722, absl_throw_delegate = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_inlined_vector_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_inlined_vector_internal.pc new file mode 100644 index 0000000..79e087c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_inlined_vector_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_inlined_vector_internal +Description: Abseil inlined_vector_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_memory = 20240722, absl_span = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_int128.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_int128.pc new file mode 100644 index 0000000..6f26a5a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_int128.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_int128 +Description: Abseil int128 library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_int128 +Requires: absl_compare = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_bits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_kernel_timeout_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_kernel_timeout_internal.pc new file mode 100644 index 0000000..77ff9b9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_kernel_timeout_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_kernel_timeout_internal +Description: Abseil kernel_timeout_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_kernel_timeout_internal +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_layout.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_layout.pc new file mode 100644 index 0000000..dcea300 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_layout.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_layout +Description: Abseil layout library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_debugging_internal = 20240722, absl_meta = 20240722, absl_strings = 20240722, absl_span = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_leak_check.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_leak_check.pc new file mode 100644 index 0000000..797e863 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_leak_check.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_leak_check +Description: Abseil leak_check library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_leak_check +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log.pc new file mode 100644 index 0000000..0b7065c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log +Description: Abseil log library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_log_impl = 20240722, absl_vlog_is_on = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_entry.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_entry.pc new file mode 100644 index 0000000..de7ff9e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_entry.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_entry +Description: Abseil log_entry library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_entry +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_config = 20240722, absl_log_severity = 20240722, absl_span = 20240722, absl_strings = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_flags.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_flags.pc new file mode 100644 index 0000000..8d8b63a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_flags.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_flags +Description: Abseil log_flags library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_flags +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_globals = 20240722, absl_log_severity = 20240722, absl_log_internal_config = 20240722, absl_log_internal_flags = 20240722, absl_flags = 20240722, absl_flags_marshalling = 20240722, absl_strings = 20240722, absl_vlog_config_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_globals.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_globals.pc new file mode 100644 index 0000000..caaa704 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_globals.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_globals +Description: Abseil log_globals library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_globals +Requires: absl_atomic_hook = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_hash = 20240722, absl_log_severity = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_vlog_config_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_initialize.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_initialize.pc new file mode 100644 index 0000000..ec34a72 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_initialize.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_initialize +Description: Abseil log_initialize library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_initialize +Requires: absl_config = 20240722, absl_log_globals = 20240722, absl_log_internal_globals = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_append_truncated.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_append_truncated.pc new file mode 100644 index 0000000..935856d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_append_truncated.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_append_truncated +Description: Abseil log_internal_append_truncated library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_strings = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_check_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_check_impl.pc new file mode 100644 index 0000000..85896c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_check_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_check_impl +Description: Abseil log_internal_check_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_log_internal_check_op = 20240722, absl_log_internal_conditions = 20240722, absl_log_internal_message = 20240722, absl_log_internal_strip = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_check_op.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_check_op.pc new file mode 100644 index 0000000..53d79b5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_check_op.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_check_op +Description: Abseil log_internal_check_op library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_check_op +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_nullguard = 20240722, absl_log_internal_nullstream = 20240722, absl_log_internal_strip = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_conditions.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_conditions.pc new file mode 100644 index 0000000..daccc6a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_conditions.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_conditions +Description: Abseil log_internal_conditions library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_conditions +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_voidify = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_config.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_config.pc new file mode 100644 index 0000000..5566d96 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_config.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_config +Description: Abseil log_internal_config library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_flags.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_flags.pc new file mode 100644 index 0000000..0fa576a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_flags.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_flags +Description: Abseil log_internal_flags library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_flags = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_fnmatch.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_fnmatch.pc new file mode 100644 index 0000000..b42e687 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_fnmatch.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_fnmatch +Description: Abseil log_internal_fnmatch library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_fnmatch +Requires: absl_config = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_format.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_format.pc new file mode 100644 index 0000000..80c370e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_format.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_format +Description: Abseil log_internal_format library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_format +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_append_truncated = 20240722, absl_log_internal_config = 20240722, absl_log_internal_globals = 20240722, absl_log_severity = 20240722, absl_strings = 20240722, absl_str_format = 20240722, absl_time = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_globals.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_globals.pc new file mode 100644 index 0000000..645100f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_globals.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_globals +Description: Abseil log_internal_globals library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_globals +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_severity = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_log_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_log_impl.pc new file mode 100644 index 0000000..0fd3d7b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_log_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_log_impl +Description: Abseil log_internal_log_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_conditions = 20240722, absl_log_internal_message = 20240722, absl_log_internal_strip = 20240722, absl_absl_vlog_is_on = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_log_sink_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_log_sink_set.pc new file mode 100644 index 0000000..e9e6f95 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_log_sink_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_log_sink_set +Description: Abseil log_internal_log_sink_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_log_sink_set -llog +Requires: absl_base = 20240722, absl_cleanup = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_config = 20240722, absl_log_internal_globals = 20240722, absl_log_globals = 20240722, absl_log_entry = 20240722, absl_log_severity = 20240722, absl_log_sink = 20240722, absl_no_destructor = 20240722, absl_raw_logging_internal = 20240722, absl_synchronization = 20240722, absl_span = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_message.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_message.pc new file mode 100644 index 0000000..189cb4e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_message.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_message +Description: Abseil log_internal_message library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_message +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722, absl_inlined_vector = 20240722, absl_examine_stack = 20240722, absl_log_internal_append_truncated = 20240722, absl_log_internal_format = 20240722, absl_log_internal_globals = 20240722, absl_log_internal_proto = 20240722, absl_log_internal_log_sink_set = 20240722, absl_log_internal_nullguard = 20240722, absl_log_globals = 20240722, absl_log_entry = 20240722, absl_log_severity = 20240722, absl_log_sink = 20240722, absl_log_sink_registry = 20240722, absl_memory = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_strerror = 20240722, absl_time = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_nullguard.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_nullguard.pc new file mode 100644 index 0000000..462b13e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_nullguard.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_nullguard +Description: Abseil log_internal_nullguard library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_nullguard +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_nullstream.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_nullstream.pc new file mode 100644 index 0000000..c4a5d12 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_nullstream.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_nullstream +Description: Abseil log_internal_nullstream library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_severity = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_proto.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_proto.pc new file mode 100644 index 0000000..a09bdd9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_proto.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_proto +Description: Abseil log_internal_proto library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_proto +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_strings = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_strip.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_strip.pc new file mode 100644 index 0000000..09b1f90 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_strip.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_strip +Description: Abseil log_internal_strip library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_log_internal_message = 20240722, absl_log_internal_nullstream = 20240722, absl_log_severity = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_structured.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_structured.pc new file mode 100644 index 0000000..166e689 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_structured.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_structured +Description: Abseil log_internal_structured library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_log_internal_message = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_voidify.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_voidify.pc new file mode 100644 index 0000000..081c074 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_internal_voidify.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_voidify +Description: Abseil log_internal_voidify library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_severity.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_severity.pc new file mode 100644 index 0000000..b3aae9c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_severity.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_severity +Description: Abseil log_severity library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_severity +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_sink.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_sink.pc new file mode 100644 index 0000000..a9c5fd3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_sink.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_sink +Description: Abseil log_sink library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_sink +Requires: absl_config = 20240722, absl_log_entry = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_sink_registry.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_sink_registry.pc new file mode 100644 index 0000000..fcb7a02 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_sink_registry.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_sink_registry +Description: Abseil log_sink_registry library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_log_sink = 20240722, absl_log_internal_log_sink_set = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_streamer.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_streamer.pc new file mode 100644 index 0000000..1de593e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_streamer.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_streamer +Description: Abseil log_streamer library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_absl_log = 20240722, absl_log_severity = 20240722, absl_optional = 20240722, absl_strings = 20240722, absl_strings_internal = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_structured.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_structured.pc new file mode 100644 index 0000000..491549b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_log_structured.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_structured +Description: Abseil log_structured library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_log_internal_structured = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_low_level_hash.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_low_level_hash.pc new file mode 100644 index 0000000..c57f9dd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_low_level_hash.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_low_level_hash +Description: Abseil low_level_hash library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_low_level_hash +Requires: absl_config = 20240722, absl_endian = 20240722, absl_int128 = 20240722, absl_prefetch = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_malloc_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_malloc_internal.pc new file mode 100644 index 0000000..63f5bc9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_malloc_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_malloc_internal +Description: Abseil malloc_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_malloc_internal +Requires: absl_base = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_memory.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_memory.pc new file mode 100644 index 0000000..760c159 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_memory.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_memory +Description: Abseil memory library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_meta.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_meta.pc new file mode 100644 index 0000000..47c6e33 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_meta.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_meta +Description: Abseil meta library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_no_destructor.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_no_destructor.pc new file mode 100644 index 0000000..61b4ced --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_no_destructor.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_no_destructor +Description: Abseil no_destructor library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_nullability = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_node_hash_map.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_node_hash_map.pc new file mode 100644 index 0000000..7290e95 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_node_hash_map.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_node_hash_map +Description: Abseil node_hash_map library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_core_headers = 20240722, absl_hash_container_defaults = 20240722, absl_node_slot_policy = 20240722, absl_raw_hash_map = 20240722, absl_algorithm_container = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_node_hash_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_node_hash_set.pc new file mode 100644 index 0000000..d25eb82 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_node_hash_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_node_hash_set +Description: Abseil node_hash_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_core_headers = 20240722, absl_hash_container_defaults = 20240722, absl_node_slot_policy = 20240722, absl_raw_hash_set = 20240722, absl_algorithm_container = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_node_slot_policy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_node_slot_policy.pc new file mode 100644 index 0000000..a76d24a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_node_slot_policy.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_node_slot_policy +Description: Abseil node_slot_policy library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_non_temporal_arm_intrinsics.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_non_temporal_arm_intrinsics.pc new file mode 100644 index 0000000..8867793 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_non_temporal_arm_intrinsics.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_non_temporal_arm_intrinsics +Description: Abseil non_temporal_arm_intrinsics library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_non_temporal_memcpy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_non_temporal_memcpy.pc new file mode 100644 index 0000000..cead8e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_non_temporal_memcpy.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_non_temporal_memcpy +Description: Abseil non_temporal_memcpy library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_non_temporal_arm_intrinsics = 20240722, absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_nullability.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_nullability.pc new file mode 100644 index 0000000..1ad40e5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_nullability.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_nullability +Description: Abseil nullability library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_numeric.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_numeric.pc new file mode 100644 index 0000000..f2ccd5b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_numeric.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_numeric +Description: Abseil numeric library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_int128 = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_numeric_representation.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_numeric_representation.pc new file mode 100644 index 0000000..bff418a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_numeric_representation.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_numeric_representation +Description: Abseil numeric_representation library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_optional.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_optional.pc new file mode 100644 index 0000000..1137364 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_optional.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_optional +Description: Abseil optional library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_optional_access = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_memory = 20240722, absl_nullability = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_overload.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_overload.pc new file mode 100644 index 0000000..23c8e6d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_overload.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_overload +Description: Abseil overload library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_periodic_sampler.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_periodic_sampler.pc new file mode 100644 index 0000000..eac6e1f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_periodic_sampler.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_periodic_sampler +Description: Abseil periodic_sampler library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_periodic_sampler +Requires: absl_core_headers = 20240722, absl_exponential_biased = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_poison.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_poison.pc new file mode 100644 index 0000000..51554cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_poison.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_poison +Description: Abseil poison library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_poison +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_malloc_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_prefetch.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_prefetch.pc new file mode 100644 index 0000000..db2731d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_prefetch.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_prefetch +Description: Abseil prefetch library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_pretty_function.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_pretty_function.pc new file mode 100644 index 0000000..a77d50d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_pretty_function.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_pretty_function +Description: Abseil pretty_function library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_bit_gen_ref.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_bit_gen_ref.pc new file mode 100644 index 0000000..0d833bb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_bit_gen_ref.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_bit_gen_ref +Description: Abseil random_bit_gen_ref library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_random_internal_distribution_caller = 20240722, absl_random_internal_fast_uniform_bits = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_distributions.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_distributions.pc new file mode 100644 index 0000000..720d7b0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_distributions.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_distributions +Description: Abseil random_distributions library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_distributions +Requires: absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_random_internal_generate_real = 20240722, absl_random_internal_distribution_caller = 20240722, absl_random_internal_fast_uniform_bits = 20240722, absl_random_internal_fastmath = 20240722, absl_random_internal_iostream_state_saver = 20240722, absl_random_internal_traits = 20240722, absl_random_internal_uniform_helper = 20240722, absl_random_internal_wide_multiply = 20240722, absl_strings = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_distribution_caller.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_distribution_caller.pc new file mode 100644 index 0000000..66a5375 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_distribution_caller.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_distribution_caller +Description: Abseil random_internal_distribution_caller library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_utility = 20240722, absl_fast_type_id = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_distribution_test_util.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_distribution_test_util.pc new file mode 100644 index 0000000..70fe5c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_distribution_test_util.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_distribution_test_util +Description: Abseil random_internal_distribution_test_util library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_distribution_test_util +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_str_format = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_fast_uniform_bits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_fast_uniform_bits.pc new file mode 100644 index 0000000..e6a97b4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_fast_uniform_bits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_fast_uniform_bits +Description: Abseil random_internal_fast_uniform_bits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_fastmath.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_fastmath.pc new file mode 100644 index 0000000..c7e9a6a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_fastmath.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_fastmath +Description: Abseil random_internal_fastmath library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_generate_real.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_generate_real.pc new file mode 100644 index 0000000..1a9dd95 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_generate_real.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_generate_real +Description: Abseil random_internal_generate_real library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722, absl_random_internal_fastmath = 20240722, absl_random_internal_traits = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_iostream_state_saver.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_iostream_state_saver.pc new file mode 100644 index 0000000..cefa15a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_iostream_state_saver.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_iostream_state_saver +Description: Abseil random_internal_iostream_state_saver library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_int128 = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_mock_helpers.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_mock_helpers.pc new file mode 100644 index 0000000..1868f39 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_mock_helpers.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_mock_helpers +Description: Abseil random_internal_mock_helpers library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_fast_type_id = 20240722, absl_optional = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_nonsecure_base.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_nonsecure_base.pc new file mode 100644 index 0000000..d16f277 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_nonsecure_base.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_nonsecure_base +Description: Abseil random_internal_nonsecure_base library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_inlined_vector = 20240722, absl_random_internal_pool_urbg = 20240722, absl_random_internal_salted_seed_seq = 20240722, absl_random_internal_seed_material = 20240722, absl_span = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_pcg_engine.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_pcg_engine.pc new file mode 100644 index 0000000..c388c97 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_pcg_engine.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_pcg_engine +Description: Abseil random_internal_pcg_engine library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_int128 = 20240722, absl_random_internal_fastmath = 20240722, absl_random_internal_iostream_state_saver = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_platform.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_platform.pc new file mode 100644 index 0000000..c034993 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_platform.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_platform +Description: Abseil random_internal_platform library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_platform +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_pool_urbg.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_pool_urbg.pc new file mode 100644 index 0000000..8c44151 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_pool_urbg.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_pool_urbg +Description: Abseil random_internal_pool_urbg library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_pool_urbg +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_random_internal_randen = 20240722, absl_random_internal_seed_material = 20240722, absl_random_internal_traits = 20240722, absl_random_seed_gen_exception = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen.pc new file mode 100644 index 0000000..a48ee09 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen +Description: Abseil random_internal_randen library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen +Requires: absl_random_internal_platform = 20240722, absl_random_internal_randen_hwaes = 20240722, absl_random_internal_randen_slow = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen_engine.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen_engine.pc new file mode 100644 index 0000000..7157894 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen_engine.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_engine +Description: Abseil random_internal_randen_engine library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_endian = 20240722, absl_random_internal_iostream_state_saver = 20240722, absl_random_internal_randen = 20240722, absl_raw_logging_internal = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen_hwaes.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen_hwaes.pc new file mode 100644 index 0000000..07f3bc1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen_hwaes.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_hwaes +Description: Abseil random_internal_randen_hwaes library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen_hwaes +Requires: absl_random_internal_platform = 20240722, absl_random_internal_randen_hwaes_impl = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen_hwaes_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen_hwaes_impl.pc new file mode 100644 index 0000000..ff47df1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen_hwaes_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_hwaes_impl +Description: Abseil random_internal_randen_hwaes_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen_hwaes_impl +Requires: absl_random_internal_platform = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen_slow.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen_slow.pc new file mode 100644 index 0000000..feb3902 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_randen_slow.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_slow +Description: Abseil random_internal_randen_slow library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen_slow +Requires: absl_random_internal_platform = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_salted_seed_seq.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_salted_seed_seq.pc new file mode 100644 index 0000000..94e4378 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_salted_seed_seq.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_salted_seed_seq +Description: Abseil random_internal_salted_seed_seq library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_inlined_vector = 20240722, absl_optional = 20240722, absl_span = 20240722, absl_random_internal_seed_material = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_seed_material.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_seed_material.pc new file mode 100644 index 0000000..644704d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_seed_material.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_seed_material +Description: Abseil random_internal_seed_material library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_seed_material +Requires: absl_core_headers = 20240722, absl_optional = 20240722, absl_random_internal_fast_uniform_bits = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_traits.pc new file mode 100644 index 0000000..a33e4ea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_traits +Description: Abseil random_internal_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_uniform_helper.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_uniform_helper.pc new file mode 100644 index 0000000..0e7f376 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_uniform_helper.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_uniform_helper +Description: Abseil random_internal_uniform_helper library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_random_internal_traits = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_wide_multiply.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_wide_multiply.pc new file mode 100644 index 0000000..988ee11 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_internal_wide_multiply.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_wide_multiply +Description: Abseil random_internal_wide_multiply library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722, absl_config = 20240722, absl_int128 = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_random.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_random.pc new file mode 100644 index 0000000..5bfb93d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_random.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_random +Description: Abseil random_random library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_random_distributions = 20240722, absl_random_internal_nonsecure_base = 20240722, absl_random_internal_pcg_engine = 20240722, absl_random_internal_pool_urbg = 20240722, absl_random_internal_randen_engine = 20240722, absl_random_seed_sequences = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_seed_gen_exception.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_seed_gen_exception.pc new file mode 100644 index 0000000..6c78196 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_seed_gen_exception.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_seed_gen_exception +Description: Abseil random_seed_gen_exception library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_seed_gen_exception +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_seed_sequences.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_seed_sequences.pc new file mode 100644 index 0000000..1998470 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_random_seed_sequences.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_seed_sequences +Description: Abseil random_seed_sequences library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_seed_sequences +Requires: absl_config = 20240722, absl_inlined_vector = 20240722, absl_nullability = 20240722, absl_random_internal_pool_urbg = 20240722, absl_random_internal_salted_seed_seq = 20240722, absl_random_internal_seed_material = 20240722, absl_random_seed_gen_exception = 20240722, absl_span = 20240722, absl_string_view = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_raw_hash_map.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_raw_hash_map.pc new file mode 100644 index 0000000..77f1e3f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_raw_hash_map.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_raw_hash_map +Description: Abseil raw_hash_map library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_container_memory = 20240722, absl_core_headers = 20240722, absl_raw_hash_set = 20240722, absl_throw_delegate = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_raw_hash_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_raw_hash_set.pc new file mode 100644 index 0000000..ed4f83c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_raw_hash_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_raw_hash_set +Description: Abseil raw_hash_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_raw_hash_set +Requires: absl_bits = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_container_common = 20240722, absl_container_memory = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_endian = 20240722, absl_hash = 20240722, absl_hash_policy_traits = 20240722, absl_hashtable_debug_hooks = 20240722, absl_hashtablez_sampler = 20240722, absl_memory = 20240722, absl_meta = 20240722, absl_optional = 20240722, absl_prefetch = 20240722, absl_raw_logging_internal = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_raw_logging_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_raw_logging_internal.pc new file mode 100644 index 0000000..a120546 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_raw_logging_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_raw_logging_internal +Description: Abseil raw_logging_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_raw_logging_internal +Requires: absl_atomic_hook = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722, absl_log_severity = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_sample_recorder.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_sample_recorder.pc new file mode 100644 index 0000000..3025734 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_sample_recorder.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_sample_recorder +Description: Abseil sample_recorder library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_scoped_set_env.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_scoped_set_env.pc new file mode 100644 index 0000000..5799969 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_scoped_set_env.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_scoped_set_env +Description: Abseil scoped_set_env library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_scoped_set_env +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_span.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_span.pc new file mode 100644 index 0000000..654b8d0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_span.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_span +Description: Abseil span library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_algorithm = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_spinlock_wait.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_spinlock_wait.pc new file mode 100644 index 0000000..3f3d495 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_spinlock_wait.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_spinlock_wait +Description: Abseil spinlock_wait library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_spinlock_wait +Requires: absl_base_internal = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_stacktrace.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_stacktrace.pc new file mode 100644 index 0000000..9375890 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_stacktrace.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_stacktrace +Description: Abseil stacktrace library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_stacktrace +Requires: absl_debugging_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_status.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_status.pc new file mode 100644 index 0000000..5a32ee5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_status.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_status +Description: Abseil status library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_status +Requires: absl_atomic_hook = 20240722, absl_config = 20240722, absl_cord = 20240722, absl_core_headers = 20240722, absl_function_ref = 20240722, absl_inlined_vector = 20240722, absl_memory = 20240722, absl_no_destructor = 20240722, absl_nullability = 20240722, absl_optional = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722, absl_stacktrace = 20240722, absl_strerror = 20240722, absl_str_format = 20240722, absl_strings = 20240722, absl_symbolize = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_statusor.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_statusor.pc new file mode 100644 index 0000000..e70bd45 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_statusor.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_statusor +Description: Abseil statusor library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_statusor +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_has_ostream_operator = 20240722, absl_nullability = 20240722, absl_raw_logging_internal = 20240722, absl_status = 20240722, absl_str_format = 20240722, absl_strings = 20240722, absl_type_traits = 20240722, absl_utility = 20240722, absl_variant = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_str_format.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_str_format.pc new file mode 100644 index 0000000..bfe84a5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_str_format.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_str_format +Description: Abseil str_format library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722, absl_span = 20240722, absl_str_format_internal = 20240722, absl_string_view = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_str_format_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_str_format_internal.pc new file mode 100644 index 0000000..8c95e7d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_str_format_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_str_format_internal +Description: Abseil str_format_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_str_format_internal +Requires: absl_bits = 20240722, absl_strings = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_fixed_array = 20240722, absl_inlined_vector = 20240722, absl_numeric_representation = 20240722, absl_type_traits = 20240722, absl_utility = 20240722, absl_int128 = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_strerror.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_strerror.pc new file mode 100644 index 0000000..a595aa1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_strerror.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_strerror +Description: Abseil strerror library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_strerror +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_string_view.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_string_view.pc new file mode 100644 index 0000000..93dd126 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_string_view.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_string_view +Description: Abseil string_view library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_string_view +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722, absl_throw_delegate = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_strings.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_strings.pc new file mode 100644 index 0000000..1b1a9f1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_strings.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_strings +Description: Abseil strings library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_strings +Requires: absl_string_view = 20240722, absl_strings_internal = 20240722, absl_base = 20240722, absl_bits = 20240722, absl_charset = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_int128 = 20240722, absl_memory = 20240722, absl_nullability = 20240722, absl_raw_logging_internal = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_strings_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_strings_internal.pc new file mode 100644 index 0000000..08a65cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_strings_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_strings_internal +Description: Abseil strings_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_strings_internal +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_raw_logging_internal = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_symbolize.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_symbolize.pc new file mode 100644 index 0000000..41275af --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_symbolize.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_symbolize +Description: Abseil symbolize library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_symbolize +Requires: absl_debugging_internal = 20240722, absl_demangle_internal = 20240722, absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_malloc_internal = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_synchronization.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_synchronization.pc new file mode 100644 index 0000000..7f17cde --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_synchronization.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_synchronization +Description: Abseil synchronization library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_synchronization +Requires: absl_graphcycles_internal = 20240722, absl_kernel_timeout_internal = 20240722, absl_atomic_hook = 20240722, absl_base = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_malloc_internal = 20240722, absl_raw_logging_internal = 20240722, absl_stacktrace = 20240722, absl_symbolize = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_throw_delegate.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_throw_delegate.pc new file mode 100644 index 0000000..57aa119 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_throw_delegate.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_throw_delegate +Description: Abseil throw_delegate library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_throw_delegate +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_time.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_time.pc new file mode 100644 index 0000000..5e094a1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_time.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_time +Description: Abseil time library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_time +Requires: absl_base = 20240722, absl_civil_time = 20240722, absl_core_headers = 20240722, absl_int128 = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_time_zone = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_time_zone.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_time_zone.pc new file mode 100644 index 0000000..eb3857a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_time_zone.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_time_zone +Description: Abseil time_zone library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_time_zone +Requires: +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_type_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_type_traits.pc new file mode 100644 index 0000000..44e060c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_type_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_type_traits +Description: Abseil type_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_utf8_for_code_point.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_utf8_for_code_point.pc new file mode 100644 index 0000000..c53dcb7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_utf8_for_code_point.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_utf8_for_code_point +Description: Abseil utf8_for_code_point library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_utf8_for_code_point +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_utility.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_utility.pc new file mode 100644 index 0000000..503991f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_utility.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_utility +Description: Abseil utility library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_config = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_variant.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_variant.pc new file mode 100644 index 0000000..84303ae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_variant.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_variant +Description: Abseil variant library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_variant_access = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_vlog_config_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_vlog_config_internal.pc new file mode 100644 index 0000000..94abf70 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_vlog_config_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_vlog_config_internal +Description: Abseil vlog_config_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_vlog_config_internal +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_fnmatch = 20240722, absl_memory = 20240722, absl_no_destructor = 20240722, absl_strings = 20240722, absl_synchronization = 20240722, absl_optional = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_vlog_is_on.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_vlog_is_on.pc new file mode 100644 index 0000000..b55ea5f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/absl_vlog_is_on.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_vlog_is_on +Description: Abseil vlog_is_on library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_absl_vlog_is_on = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/draco.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/draco.pc new file mode 100644 index 0000000..a5120c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/draco.pc @@ -0,0 +1,7 @@ +prefix=${pcfiledir}/../.. +Name: draco +Description: Draco geometry de(com)pression library. +Version: 1.5.7 + +Libs: "-L${prefix}/lib" -ldraco +Cflags: "-I${prefix}/include" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/fmt.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/fmt.pc new file mode 100644 index 0000000..9650070 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/fmt.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: fmt +Description: A modern formatting library +Version: 11.0.2 + + +Libs: "-L${libdir}" -lfmt +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libjpeg.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libjpeg.pc new file mode 100644 index 0000000..bef720f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libjpeg.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: libjpeg +Description: A SIMD-accelerated JPEG codec that provides the libjpeg API +Version: 3.0.4 + +Libs: "-L${libdir}" -ljpeg +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libsharpyuv.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libsharpyuv.pc new file mode 100644 index 0000000..6951840 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libsharpyuv.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/webp + +Name: libsharpyuv +Description: Library for sharp RGB to YUV conversion +Version: 1.4.0 + +Libs: "-L${libdir}" -lsharpyuv -pthread +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libturbojpeg.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libturbojpeg.pc new file mode 100644 index 0000000..eeee26d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libturbojpeg.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: libturbojpeg +Description: A SIMD-accelerated JPEG codec that provides the TurboJPEG API +Version: 3.0.4 + +Libs: "-L${libdir}" -lturbojpeg +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/liburiparser.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/liburiparser.pc new file mode 100644 index 0000000..75afa89 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/liburiparser.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: liburiparser +Description: URI parsing and handling library + +Version: 0.9.8 +URL: https://uriparser.github.io/ + +Libs: "-L${libdir}" -luriparser +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libwebp.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libwebp.pc new file mode 100644 index 0000000..c9b1ddd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libwebp.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebp +Description: Library for the WebP graphics format +Version: 1.4.0 + +Libs: "-L${libdir}" -lwebp -pthread +Requires: libsharpyuv +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libwebpdecoder.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libwebpdecoder.pc new file mode 100644 index 0000000..3fa5457 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libwebpdecoder.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebpdecoder +Description: Library for the WebP graphics format (decode only) +Version: 1.4.0 + +Libs: "-L${libdir}" -lwebpdecoder -pthread +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libwebpdemux.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libwebpdemux.pc new file mode 100644 index 0000000..5730238 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libwebpdemux.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebpdemux +Description: Library for parsing the WebP graphics format container +Version: 1.4.0 + +Libs: "-L${libdir}" -lwebpdemux +Requires: libwebp >= 0.2.0 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libwebpmux.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libwebpmux.pc new file mode 100644 index 0000000..5270237 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libwebpmux.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebpmux +Description: Library for manipulating the WebP graphics format container +Version: 1.4.0 + +Libs: "-L${libdir}" -lwebpmux +Requires: libwebp >= 0.2.0 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libzstd.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libzstd.pc new file mode 100644 index 0000000..f44d725 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/libzstd.pc @@ -0,0 +1,16 @@ +prefix=${pcfiledir}/../.. +# ZSTD - standard compression algorithm +# Copyright (c) Meta Platforms, Inc. and affiliates. +# BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +Name: zstd +Description: fast lossless compression algorithm library +URL: https://facebook.github.io/zstd/ +Version: 1.5.6 + +Libs: "-L${libdir}" -lzstd -pthread -pthread +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/spdlog.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/spdlog.pc new file mode 100644 index 0000000..3b2aab0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/spdlog.pc @@ -0,0 +1,14 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +Name: libspdlog +Description: Fast C++ logging library. +URL: https://github.com/gabime/spdlog +Version: 1.15.0 +CFlags: "-I${includedir}" -DSPDLOG_COMPILED_LIB -DSPDLOG_FMT_EXTERNAL + + +Libs: "-L${libdir}" -lspdlog -pthread +Requires: fmt diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/sqlite3.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/sqlite3.pc new file mode 100644 index 0000000..951d72c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/sqlite3.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: SQLite +Description: SQL database engine +Version: 3.45.0 + +Libs: "-L${libdir}" -lsqlite3 -pthread -ldl +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/tidy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/tidy.pc new file mode 100644 index 0000000..016c802 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/tidy.pc @@ -0,0 +1,11 @@ +prefix=D:/a/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty +exec_prefix=${prefix} +libdir=${exec_prefix}/D:/a/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty/lib/Android-aarch64-$,Debug,Release> +includedir=${prefix}/include + +Name: tidy +Description: tidy - HTML syntax checker +URL: https://www.html-tidy.org +Version: 5.9.14 +Libs: -L${libdir} -ltidy +Cflags: -I${includedir} diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/tinyxml2.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/tinyxml2.pc new file mode 100644 index 0000000..24bbedf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/tinyxml2.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: TinyXML2 +Description: simple, small, C++ XML parser +Version: 10.0.0 + +Libs: "-L${libdir}" -ltinyxml2 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/zlib-ng.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/zlib-ng.pc new file mode 100644 index 0000000..9a4a354 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-aarch64-Release/pkgconfig/zlib-ng.pc @@ -0,0 +1,15 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +symbol_prefix= +libdir=${exec_prefix}/lib +sharedlibdir=${libdir} +includedir=${prefix}/include + +Name: zlib-ng +Description: zlib-ng compression library +Version: 2.1.6 + + +Libs: "-L${libdir}" "-L${sharedlibdir}" -lz-ng +Requires: +Cflags: "-I${includedir}" -DWITH_GZFILEOP diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/cmake/zlib-ng/zlib-ng-release.cmake b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/cmake/zlib-ng/zlib-ng-release.cmake new file mode 100644 index 0000000..4c7457e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/cmake/zlib-ng/zlib-ng-release.cmake @@ -0,0 +1,19 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "zlib-ng::zlib" for configuration "Release" +set_property(TARGET zlib-ng::zlib APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(zlib-ng::zlib PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libz-ng.a" + ) + +list(APPEND _cmake_import_check_targets zlib-ng::zlib ) +list(APPEND _cmake_import_check_files_for_zlib-ng::zlib "${_IMPORT_PREFIX}/lib/libz-ng.a" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/cmake/zlib-ng/zlib-ng.cmake b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/cmake/zlib-ng/zlib-ng.cmake new file mode 100644 index 0000000..034b039 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/cmake/zlib-ng/zlib-ng.cmake @@ -0,0 +1,107 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.3") + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.3...3.29) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS zlib-ng::zlib) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target zlib-ng::zlib +add_library(zlib-ng::zlib STATIC IMPORTED) + +set_target_properties(zlib-ng::zlib PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "ZLIBNG_NATIVE_API" + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" +) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/zlib-ng-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + if(CMAKE_VERSION VERSION_LESS "3.28" + OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} + OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + endif() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/RapidJSON.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/RapidJSON.pc new file mode 100644 index 0000000..70a293c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/RapidJSON.pc @@ -0,0 +1,9 @@ +prefix=${pcfiledir}/../.. +includedir=${prefix}/include + +Name: RapidJSON +Description: A fast JSON parser/generator for C++ with both SAX/DOM style API +Version: 1.1.0 +URL: https://github.com/Tencent/rapidjson + +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_absl_check.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_absl_check.pc new file mode 100644 index 0000000..2a3f96a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_absl_check.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_absl_check +Description: Abseil absl_check library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_check_impl = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_absl_log.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_absl_log.pc new file mode 100644 index 0000000..cd4d88d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_absl_log.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_absl_log +Description: Abseil absl_log library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_log_impl = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_absl_vlog_is_on.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_absl_vlog_is_on.pc new file mode 100644 index 0000000..fcfb211 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_absl_vlog_is_on.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_absl_vlog_is_on +Description: Abseil absl_vlog_is_on library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_vlog_config_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_algorithm.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_algorithm.pc new file mode 100644 index 0000000..2699e89 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_algorithm.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_algorithm +Description: Abseil algorithm library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_algorithm_container.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_algorithm_container.pc new file mode 100644 index 0000000..1ef0909 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_algorithm_container.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_algorithm_container +Description: Abseil algorithm_container library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_algorithm = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_meta = 20240722, absl_nullability = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_any.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_any.pc new file mode 100644 index 0000000..69034ca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_any.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_any +Description: Abseil any library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_any_cast = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_fast_type_id = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_any_invocable.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_any_invocable.pc new file mode 100644 index 0000000..5a8c0d5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_any_invocable.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_any_invocable +Description: Abseil any_invocable library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_atomic_hook.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_atomic_hook.pc new file mode 100644 index 0000000..617f0f5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_atomic_hook.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_atomic_hook +Description: Abseil atomic_hook library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bad_any_cast.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bad_any_cast.pc new file mode 100644 index 0000000..3b5b029 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bad_any_cast.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_any_cast +Description: Abseil bad_any_cast library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_any_cast_impl = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bad_any_cast_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bad_any_cast_impl.pc new file mode 100644 index 0000000..ea27e16 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bad_any_cast_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_any_cast_impl +Description: Abseil bad_any_cast_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_bad_any_cast_impl +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bad_optional_access.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bad_optional_access.pc new file mode 100644 index 0000000..4659ea9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bad_optional_access.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_optional_access +Description: Abseil bad_optional_access library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_bad_optional_access +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bad_variant_access.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bad_variant_access.pc new file mode 100644 index 0000000..787f27e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bad_variant_access.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_variant_access +Description: Abseil bad_variant_access library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_bad_variant_access +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_base.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_base.pc new file mode 100644 index 0000000..df88224 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_base.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_base +Description: Abseil base library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_base -lrt +Requires: absl_atomic_hook = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_log_severity = 20240722, absl_nullability = 20240722, absl_raw_logging_internal = 20240722, absl_spinlock_wait = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_base_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_base_internal.pc new file mode 100644 index 0000000..0d5e854 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_base_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_base_internal +Description: Abseil base_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bind_front.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bind_front.pc new file mode 100644 index 0000000..43ba4f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bind_front.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bind_front +Description: Abseil bind_front library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_compressed_tuple = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bits.pc new file mode 100644 index 0000000..85ab7f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bits +Description: Abseil bits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bounded_utf8_length_sequence.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bounded_utf8_length_sequence.pc new file mode 100644 index 0000000..fe4d6b4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_bounded_utf8_length_sequence.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bounded_utf8_length_sequence +Description: Abseil bounded_utf8_length_sequence library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_btree.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_btree.pc new file mode 100644 index 0000000..2fffd58 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_btree.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_btree +Description: Abseil btree library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_common_policy_traits = 20240722, absl_compare = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_container_common = 20240722, absl_container_memory = 20240722, absl_cord = 20240722, absl_core_headers = 20240722, absl_layout = 20240722, absl_memory = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_charset.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_charset.pc new file mode 100644 index 0000000..18ecd6b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_charset.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_charset +Description: Abseil charset library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_string_view = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_check.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_check.pc new file mode 100644 index 0000000..e39177d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_check.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_check +Description: Abseil check library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_check_impl = 20240722, absl_core_headers = 20240722, absl_log_internal_check_op = 20240722, absl_log_internal_conditions = 20240722, absl_log_internal_message = 20240722, absl_log_internal_strip = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_city.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_city.pc new file mode 100644 index 0000000..a4f43bf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_city.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_city +Description: Abseil city library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_city +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_civil_time.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_civil_time.pc new file mode 100644 index 0000000..a660426 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_civil_time.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_civil_time +Description: Abseil civil_time library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_civil_time +Requires: +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cleanup.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cleanup.pc new file mode 100644 index 0000000..958bbe6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cleanup.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cleanup +Description: Abseil cleanup library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_cleanup_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cleanup_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cleanup_internal.pc new file mode 100644 index 0000000..738d222 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cleanup_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cleanup_internal +Description: Abseil cleanup_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_core_headers = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_common_policy_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_common_policy_traits.pc new file mode 100644 index 0000000..ea0451a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_common_policy_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_common_policy_traits +Description: Abseil common_policy_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_compare.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_compare.pc new file mode 100644 index 0000000..75426b5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_compare.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_compare +Description: Abseil compare library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_compressed_tuple.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_compressed_tuple.pc new file mode 100644 index 0000000..70079e6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_compressed_tuple.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_compressed_tuple +Description: Abseil compressed_tuple library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_config.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_config.pc new file mode 100644 index 0000000..d439766 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_config.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_config +Description: Abseil config library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_container_common.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_container_common.pc new file mode 100644 index 0000000..87783eb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_container_common.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_container_common +Description: Abseil container_common library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_container_memory.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_container_memory.pc new file mode 100644 index 0000000..b14fd4e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_container_memory.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_container_memory +Description: Abseil container_memory library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_memory = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cord.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cord.pc new file mode 100644 index 0000000..9ba4365 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cord.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cord +Description: Abseil cord library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cord +Requires: absl_base = 20240722, absl_config = 20240722, absl_cord_internal = 20240722, absl_cordz_functions = 20240722, absl_cordz_info = 20240722, absl_cordz_update_scope = 20240722, absl_cordz_update_tracker = 20240722, absl_core_headers = 20240722, absl_crc32c = 20240722, absl_crc_cord_state = 20240722, absl_endian = 20240722, absl_function_ref = 20240722, absl_inlined_vector = 20240722, absl_nullability = 20240722, absl_optional = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722, absl_strings = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cord_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cord_internal.pc new file mode 100644 index 0000000..4c68ba2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cord_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cord_internal +Description: Abseil cord_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cord_internal +Requires: absl_base_internal = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_container_memory = 20240722, absl_compare = 20240722, absl_core_headers = 20240722, absl_crc_cord_state = 20240722, absl_endian = 20240722, absl_inlined_vector = 20240722, absl_layout = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_functions.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_functions.pc new file mode 100644 index 0000000..8fa4c86 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_functions.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_functions +Description: Abseil cordz_functions library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_functions +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_exponential_biased = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_handle.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_handle.pc new file mode 100644 index 0000000..3a0cee3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_handle.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_handle +Description: Abseil cordz_handle library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_handle +Requires: absl_base = 20240722, absl_config = 20240722, absl_no_destructor = 20240722, absl_raw_logging_internal = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_info.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_info.pc new file mode 100644 index 0000000..765e2b6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_info.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_info +Description: Abseil cordz_info library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_info +Requires: absl_base = 20240722, absl_config = 20240722, absl_cord_internal = 20240722, absl_cordz_functions = 20240722, absl_cordz_handle = 20240722, absl_cordz_statistics = 20240722, absl_cordz_update_tracker = 20240722, absl_core_headers = 20240722, absl_inlined_vector = 20240722, absl_span = 20240722, absl_raw_logging_internal = 20240722, absl_stacktrace = 20240722, absl_synchronization = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_sample_token.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_sample_token.pc new file mode 100644 index 0000000..9fc4e9d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_sample_token.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_sample_token +Description: Abseil cordz_sample_token library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_sample_token +Requires: absl_config = 20240722, absl_cordz_handle = 20240722, absl_cordz_info = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_statistics.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_statistics.pc new file mode 100644 index 0000000..30a9e87 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_statistics.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_statistics +Description: Abseil cordz_statistics library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_cordz_update_tracker = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_update_scope.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_update_scope.pc new file mode 100644 index 0000000..d999f44 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_update_scope.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_update_scope +Description: Abseil cordz_update_scope library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_cord_internal = 20240722, absl_cordz_info = 20240722, absl_cordz_update_tracker = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_update_tracker.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_update_tracker.pc new file mode 100644 index 0000000..9884960 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_cordz_update_tracker.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_update_tracker +Description: Abseil cordz_update_tracker library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_core_headers.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_core_headers.pc new file mode 100644 index 0000000..9650f37 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_core_headers.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_core_headers +Description: Abseil core_headers library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_crc32c.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_crc32c.pc new file mode 100644 index 0000000..69b6592 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_crc32c.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc32c +Description: Abseil crc32c library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc32c +Requires: absl_crc_cpu_detect = 20240722, absl_crc_internal = 20240722, absl_non_temporal_memcpy = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_prefetch = 20240722, absl_str_format = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_crc_cord_state.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_crc_cord_state.pc new file mode 100644 index 0000000..8ea2b59 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_crc_cord_state.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc_cord_state +Description: Abseil crc_cord_state library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc_cord_state +Requires: absl_crc32c = 20240722, absl_config = 20240722, absl_strings = 20240722, absl_no_destructor = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_crc_cpu_detect.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_crc_cpu_detect.pc new file mode 100644 index 0000000..04dfb78 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_crc_cpu_detect.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc_cpu_detect +Description: Abseil crc_cpu_detect library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc_cpu_detect +Requires: absl_base = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_crc_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_crc_internal.pc new file mode 100644 index 0000000..e13a8f6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_crc_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc_internal +Description: Abseil crc_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc_internal +Requires: absl_crc_cpu_detect = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_prefetch = 20240722, absl_raw_logging_internal = 20240722, absl_memory = 20240722, absl_bits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_debugging.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_debugging.pc new file mode 100644 index 0000000..62304ae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_debugging.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_debugging +Description: Abseil debugging library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_stacktrace = 20240722, absl_leak_check = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_debugging_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_debugging_internal.pc new file mode 100644 index 0000000..1ca2457 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_debugging_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_debugging_internal +Description: Abseil debugging_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_debugging_internal +Requires: absl_core_headers = 20240722, absl_config = 20240722, absl_dynamic_annotations = 20240722, absl_errno_saver = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_decode_rust_punycode.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_decode_rust_punycode.pc new file mode 100644 index 0000000..ae5d976 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_decode_rust_punycode.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_decode_rust_punycode +Description: Abseil decode_rust_punycode library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_decode_rust_punycode +Requires: absl_bounded_utf8_length_sequence = 20240722, absl_config = 20240722, absl_nullability = 20240722, absl_utf8_for_code_point = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_demangle_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_demangle_internal.pc new file mode 100644 index 0000000..0ec9fa6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_demangle_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_demangle_internal +Description: Abseil demangle_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_demangle_internal +Requires: absl_config = 20240722, absl_demangle_rust = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_demangle_rust.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_demangle_rust.pc new file mode 100644 index 0000000..51ce133 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_demangle_rust.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_demangle_rust +Description: Abseil demangle_rust library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_demangle_rust +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_decode_rust_punycode = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_die_if_null.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_die_if_null.pc new file mode 100644 index 0000000..acf5b4d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_die_if_null.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_die_if_null +Description: Abseil die_if_null library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_die_if_null +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_dynamic_annotations.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_dynamic_annotations.pc new file mode 100644 index 0000000..f7f3815 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_dynamic_annotations.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_dynamic_annotations +Description: Abseil dynamic_annotations library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_endian.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_endian.pc new file mode 100644 index 0000000..3d00574 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_endian.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_endian +Description: Abseil endian library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_errno_saver.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_errno_saver.pc new file mode 100644 index 0000000..65c2ffb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_errno_saver.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_errno_saver +Description: Abseil errno_saver library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_examine_stack.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_examine_stack.pc new file mode 100644 index 0000000..9c9a61b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_examine_stack.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_examine_stack +Description: Abseil examine_stack library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_examine_stack +Requires: absl_stacktrace = 20240722, absl_symbolize = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_exponential_biased.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_exponential_biased.pc new file mode 100644 index 0000000..edcf6f7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_exponential_biased.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_exponential_biased +Description: Abseil exponential_biased library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_exponential_biased +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_failure_signal_handler.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_failure_signal_handler.pc new file mode 100644 index 0000000..73b3af7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_failure_signal_handler.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_failure_signal_handler +Description: Abseil failure_signal_handler library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_failure_signal_handler +Requires: absl_examine_stack = 20240722, absl_stacktrace = 20240722, absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_fast_type_id.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_fast_type_id.pc new file mode 100644 index 0000000..00bee9f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_fast_type_id.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_fast_type_id +Description: Abseil fast_type_id library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_fixed_array.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_fixed_array.pc new file mode 100644 index 0000000..bc11248 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_fixed_array.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_fixed_array +Description: Abseil fixed_array library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_compressed_tuple = 20240722, absl_algorithm = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_throw_delegate = 20240722, absl_memory = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags.pc new file mode 100644 index 0000000..2e7aecd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags +Description: Abseil flags library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_config = 20240722, absl_flags_internal = 20240722, absl_flags_reflection = 20240722, absl_core_headers = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_commandlineflag.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_commandlineflag.pc new file mode 100644 index 0000000..5e61657 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_commandlineflag.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_commandlineflag +Description: Abseil flags_commandlineflag library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_commandlineflag +Requires: absl_config = 20240722, absl_fast_type_id = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_optional = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_commandlineflag_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_commandlineflag_internal.pc new file mode 100644 index 0000000..1436671 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_commandlineflag_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_commandlineflag_internal +Description: Abseil flags_commandlineflag_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_commandlineflag_internal +Requires: absl_config = 20240722, absl_dynamic_annotations = 20240722, absl_fast_type_id = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_config.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_config.pc new file mode 100644 index 0000000..90d32aa --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_config.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_config +Description: Abseil flags_config library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_config +Requires: absl_config = 20240722, absl_flags_path_util = 20240722, absl_flags_program_name = 20240722, absl_core_headers = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_internal.pc new file mode 100644 index 0000000..9ac5cde --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_internal +Description: Abseil flags_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_internal +Requires: absl_base = 20240722, absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_flags_config = 20240722, absl_flags_marshalling = 20240722, absl_synchronization = 20240722, absl_meta = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_marshalling.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_marshalling.pc new file mode 100644 index 0000000..86c8076 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_marshalling.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_marshalling +Description: Abseil flags_marshalling library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_marshalling +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_severity = 20240722, absl_int128 = 20240722, absl_optional = 20240722, absl_strings = 20240722, absl_str_format = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_parse.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_parse.pc new file mode 100644 index 0000000..0c399ae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_parse.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_parse +Description: Abseil flags_parse library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_parse +Requires: absl_algorithm_container = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_flags_config = 20240722, absl_flags = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_flags_internal = 20240722, absl_flags_private_handle_accessor = 20240722, absl_flags_program_name = 20240722, absl_flags_reflection = 20240722, absl_flags_usage = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_path_util.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_path_util.pc new file mode 100644 index 0000000..9adbb6c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_path_util.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_path_util +Description: Abseil flags_path_util library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_private_handle_accessor.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_private_handle_accessor.pc new file mode 100644 index 0000000..2a57aab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_private_handle_accessor.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_private_handle_accessor +Description: Abseil flags_private_handle_accessor library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_private_handle_accessor +Requires: absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_program_name.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_program_name.pc new file mode 100644 index 0000000..1b3370c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_program_name.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_program_name +Description: Abseil flags_program_name library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_program_name +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_flags_path_util = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_reflection.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_reflection.pc new file mode 100644 index 0000000..e373dbb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_reflection.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_reflection +Description: Abseil flags_reflection library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_reflection +Requires: absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_private_handle_accessor = 20240722, absl_flags_config = 20240722, absl_strings = 20240722, absl_synchronization = 20240722, absl_flat_hash_map = 20240722, absl_no_destructor = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_usage.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_usage.pc new file mode 100644 index 0000000..27e5dcf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_usage.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_usage +Description: Abseil flags_usage library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_usage +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_flags_usage_internal = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_usage_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_usage_internal.pc new file mode 100644 index 0000000..e93d28d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flags_usage_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_usage_internal +Description: Abseil flags_usage_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_usage_internal +Requires: absl_config = 20240722, absl_flags_config = 20240722, absl_flags = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_internal = 20240722, absl_flags_path_util = 20240722, absl_flags_private_handle_accessor = 20240722, absl_flags_program_name = 20240722, absl_flags_reflection = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flat_hash_map.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flat_hash_map.pc new file mode 100644 index 0000000..bab2f5e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flat_hash_map.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flat_hash_map +Description: Abseil flat_hash_map library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_core_headers = 20240722, absl_hash_container_defaults = 20240722, absl_raw_hash_map = 20240722, absl_algorithm_container = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flat_hash_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flat_hash_set.pc new file mode 100644 index 0000000..71c94e2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_flat_hash_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flat_hash_set +Description: Abseil flat_hash_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_hash_container_defaults = 20240722, absl_raw_hash_set = 20240722, absl_algorithm_container = 20240722, absl_core_headers = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_function_ref.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_function_ref.pc new file mode 100644 index 0000000..c88a5e3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_function_ref.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_function_ref +Description: Abseil function_ref library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_core_headers = 20240722, absl_any_invocable = 20240722, absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_graphcycles_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_graphcycles_internal.pc new file mode 100644 index 0000000..8de827e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_graphcycles_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_graphcycles_internal +Description: Abseil graphcycles_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_graphcycles_internal +Requires: absl_base = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_malloc_internal = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_has_ostream_operator.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_has_ostream_operator.pc new file mode 100644 index 0000000..843c0c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_has_ostream_operator.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_has_ostream_operator +Description: Abseil has_ostream_operator library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hash.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hash.pc new file mode 100644 index 0000000..f80f599 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hash.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash +Description: Abseil hash library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_hash +Requires: absl_bits = 20240722, absl_city = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_fixed_array = 20240722, absl_function_ref = 20240722, absl_meta = 20240722, absl_int128 = 20240722, absl_strings = 20240722, absl_optional = 20240722, absl_variant = 20240722, absl_utility = 20240722, absl_low_level_hash = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hash_container_defaults.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hash_container_defaults.pc new file mode 100644 index 0000000..5e1ded4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hash_container_defaults.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash_container_defaults +Description: Abseil hash_container_defaults library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_hash_function_defaults = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hash_function_defaults.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hash_function_defaults.pc new file mode 100644 index 0000000..04a4e3b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hash_function_defaults.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash_function_defaults +Description: Abseil hash_function_defaults library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_container_common = 20240722, absl_cord = 20240722, absl_hash = 20240722, absl_strings = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hash_policy_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hash_policy_traits.pc new file mode 100644 index 0000000..e25c47c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hash_policy_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash_policy_traits +Description: Abseil hash_policy_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_common_policy_traits = 20240722, absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hashtable_debug.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hashtable_debug.pc new file mode 100644 index 0000000..5b1ed5f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hashtable_debug.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hashtable_debug +Description: Abseil hashtable_debug library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_hashtable_debug_hooks = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hashtable_debug_hooks.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hashtable_debug_hooks.pc new file mode 100644 index 0000000..9010454 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hashtable_debug_hooks.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hashtable_debug_hooks +Description: Abseil hashtable_debug_hooks library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hashtablez_sampler.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hashtablez_sampler.pc new file mode 100644 index 0000000..2cbd02a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_hashtablez_sampler.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hashtablez_sampler +Description: Abseil hashtablez_sampler library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_hashtablez_sampler +Requires: absl_base = 20240722, absl_config = 20240722, absl_exponential_biased = 20240722, absl_no_destructor = 20240722, absl_raw_logging_internal = 20240722, absl_sample_recorder = 20240722, absl_synchronization = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_if_constexpr.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_if_constexpr.pc new file mode 100644 index 0000000..815d293 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_if_constexpr.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_if_constexpr +Description: Abseil if_constexpr library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_inlined_vector.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_inlined_vector.pc new file mode 100644 index 0000000..aabfd71 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_inlined_vector.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_inlined_vector +Description: Abseil inlined_vector library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_algorithm = 20240722, absl_core_headers = 20240722, absl_inlined_vector_internal = 20240722, absl_throw_delegate = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_inlined_vector_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_inlined_vector_internal.pc new file mode 100644 index 0000000..79e087c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_inlined_vector_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_inlined_vector_internal +Description: Abseil inlined_vector_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_memory = 20240722, absl_span = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_int128.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_int128.pc new file mode 100644 index 0000000..6f26a5a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_int128.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_int128 +Description: Abseil int128 library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_int128 +Requires: absl_compare = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_bits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_kernel_timeout_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_kernel_timeout_internal.pc new file mode 100644 index 0000000..77ff9b9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_kernel_timeout_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_kernel_timeout_internal +Description: Abseil kernel_timeout_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_kernel_timeout_internal +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_layout.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_layout.pc new file mode 100644 index 0000000..dcea300 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_layout.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_layout +Description: Abseil layout library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_debugging_internal = 20240722, absl_meta = 20240722, absl_strings = 20240722, absl_span = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_leak_check.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_leak_check.pc new file mode 100644 index 0000000..797e863 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_leak_check.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_leak_check +Description: Abseil leak_check library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_leak_check +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log.pc new file mode 100644 index 0000000..0b7065c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log +Description: Abseil log library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_log_impl = 20240722, absl_vlog_is_on = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_entry.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_entry.pc new file mode 100644 index 0000000..de7ff9e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_entry.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_entry +Description: Abseil log_entry library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_entry +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_config = 20240722, absl_log_severity = 20240722, absl_span = 20240722, absl_strings = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_flags.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_flags.pc new file mode 100644 index 0000000..8d8b63a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_flags.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_flags +Description: Abseil log_flags library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_flags +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_globals = 20240722, absl_log_severity = 20240722, absl_log_internal_config = 20240722, absl_log_internal_flags = 20240722, absl_flags = 20240722, absl_flags_marshalling = 20240722, absl_strings = 20240722, absl_vlog_config_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_globals.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_globals.pc new file mode 100644 index 0000000..caaa704 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_globals.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_globals +Description: Abseil log_globals library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_globals +Requires: absl_atomic_hook = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_hash = 20240722, absl_log_severity = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_vlog_config_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_initialize.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_initialize.pc new file mode 100644 index 0000000..ec34a72 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_initialize.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_initialize +Description: Abseil log_initialize library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_initialize +Requires: absl_config = 20240722, absl_log_globals = 20240722, absl_log_internal_globals = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_append_truncated.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_append_truncated.pc new file mode 100644 index 0000000..935856d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_append_truncated.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_append_truncated +Description: Abseil log_internal_append_truncated library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_strings = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_check_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_check_impl.pc new file mode 100644 index 0000000..85896c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_check_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_check_impl +Description: Abseil log_internal_check_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_log_internal_check_op = 20240722, absl_log_internal_conditions = 20240722, absl_log_internal_message = 20240722, absl_log_internal_strip = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_check_op.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_check_op.pc new file mode 100644 index 0000000..53d79b5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_check_op.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_check_op +Description: Abseil log_internal_check_op library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_check_op +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_nullguard = 20240722, absl_log_internal_nullstream = 20240722, absl_log_internal_strip = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_conditions.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_conditions.pc new file mode 100644 index 0000000..daccc6a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_conditions.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_conditions +Description: Abseil log_internal_conditions library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_conditions +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_voidify = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_config.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_config.pc new file mode 100644 index 0000000..5566d96 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_config.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_config +Description: Abseil log_internal_config library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_flags.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_flags.pc new file mode 100644 index 0000000..0fa576a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_flags.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_flags +Description: Abseil log_internal_flags library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_flags = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_fnmatch.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_fnmatch.pc new file mode 100644 index 0000000..b42e687 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_fnmatch.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_fnmatch +Description: Abseil log_internal_fnmatch library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_fnmatch +Requires: absl_config = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_format.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_format.pc new file mode 100644 index 0000000..80c370e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_format.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_format +Description: Abseil log_internal_format library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_format +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_append_truncated = 20240722, absl_log_internal_config = 20240722, absl_log_internal_globals = 20240722, absl_log_severity = 20240722, absl_strings = 20240722, absl_str_format = 20240722, absl_time = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_globals.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_globals.pc new file mode 100644 index 0000000..645100f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_globals.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_globals +Description: Abseil log_internal_globals library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_globals +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_severity = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_log_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_log_impl.pc new file mode 100644 index 0000000..0fd3d7b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_log_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_log_impl +Description: Abseil log_internal_log_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_conditions = 20240722, absl_log_internal_message = 20240722, absl_log_internal_strip = 20240722, absl_absl_vlog_is_on = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_log_sink_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_log_sink_set.pc new file mode 100644 index 0000000..584c9db --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_log_sink_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_log_sink_set +Description: Abseil log_internal_log_sink_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_log_sink_set +Requires: absl_base = 20240722, absl_cleanup = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_config = 20240722, absl_log_internal_globals = 20240722, absl_log_globals = 20240722, absl_log_entry = 20240722, absl_log_severity = 20240722, absl_log_sink = 20240722, absl_no_destructor = 20240722, absl_raw_logging_internal = 20240722, absl_synchronization = 20240722, absl_span = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_message.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_message.pc new file mode 100644 index 0000000..189cb4e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_message.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_message +Description: Abseil log_internal_message library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_message +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722, absl_inlined_vector = 20240722, absl_examine_stack = 20240722, absl_log_internal_append_truncated = 20240722, absl_log_internal_format = 20240722, absl_log_internal_globals = 20240722, absl_log_internal_proto = 20240722, absl_log_internal_log_sink_set = 20240722, absl_log_internal_nullguard = 20240722, absl_log_globals = 20240722, absl_log_entry = 20240722, absl_log_severity = 20240722, absl_log_sink = 20240722, absl_log_sink_registry = 20240722, absl_memory = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_strerror = 20240722, absl_time = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_nullguard.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_nullguard.pc new file mode 100644 index 0000000..462b13e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_nullguard.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_nullguard +Description: Abseil log_internal_nullguard library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_nullguard +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_nullstream.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_nullstream.pc new file mode 100644 index 0000000..c4a5d12 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_nullstream.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_nullstream +Description: Abseil log_internal_nullstream library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_severity = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_proto.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_proto.pc new file mode 100644 index 0000000..a09bdd9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_proto.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_proto +Description: Abseil log_internal_proto library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_proto +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_strings = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_strip.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_strip.pc new file mode 100644 index 0000000..09b1f90 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_strip.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_strip +Description: Abseil log_internal_strip library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_log_internal_message = 20240722, absl_log_internal_nullstream = 20240722, absl_log_severity = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_structured.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_structured.pc new file mode 100644 index 0000000..166e689 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_structured.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_structured +Description: Abseil log_internal_structured library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_log_internal_message = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_voidify.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_voidify.pc new file mode 100644 index 0000000..081c074 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_internal_voidify.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_voidify +Description: Abseil log_internal_voidify library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_severity.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_severity.pc new file mode 100644 index 0000000..b3aae9c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_severity.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_severity +Description: Abseil log_severity library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_severity +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_sink.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_sink.pc new file mode 100644 index 0000000..a9c5fd3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_sink.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_sink +Description: Abseil log_sink library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_sink +Requires: absl_config = 20240722, absl_log_entry = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_sink_registry.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_sink_registry.pc new file mode 100644 index 0000000..fcb7a02 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_sink_registry.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_sink_registry +Description: Abseil log_sink_registry library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_log_sink = 20240722, absl_log_internal_log_sink_set = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_streamer.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_streamer.pc new file mode 100644 index 0000000..1de593e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_streamer.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_streamer +Description: Abseil log_streamer library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_absl_log = 20240722, absl_log_severity = 20240722, absl_optional = 20240722, absl_strings = 20240722, absl_strings_internal = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_structured.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_structured.pc new file mode 100644 index 0000000..491549b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_log_structured.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_structured +Description: Abseil log_structured library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_log_internal_structured = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_low_level_hash.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_low_level_hash.pc new file mode 100644 index 0000000..c57f9dd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_low_level_hash.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_low_level_hash +Description: Abseil low_level_hash library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_low_level_hash +Requires: absl_config = 20240722, absl_endian = 20240722, absl_int128 = 20240722, absl_prefetch = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_malloc_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_malloc_internal.pc new file mode 100644 index 0000000..63f5bc9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_malloc_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_malloc_internal +Description: Abseil malloc_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_malloc_internal +Requires: absl_base = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_memory.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_memory.pc new file mode 100644 index 0000000..760c159 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_memory.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_memory +Description: Abseil memory library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_meta.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_meta.pc new file mode 100644 index 0000000..47c6e33 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_meta.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_meta +Description: Abseil meta library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_no_destructor.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_no_destructor.pc new file mode 100644 index 0000000..61b4ced --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_no_destructor.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_no_destructor +Description: Abseil no_destructor library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_nullability = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_node_hash_map.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_node_hash_map.pc new file mode 100644 index 0000000..7290e95 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_node_hash_map.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_node_hash_map +Description: Abseil node_hash_map library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_core_headers = 20240722, absl_hash_container_defaults = 20240722, absl_node_slot_policy = 20240722, absl_raw_hash_map = 20240722, absl_algorithm_container = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_node_hash_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_node_hash_set.pc new file mode 100644 index 0000000..d25eb82 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_node_hash_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_node_hash_set +Description: Abseil node_hash_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_core_headers = 20240722, absl_hash_container_defaults = 20240722, absl_node_slot_policy = 20240722, absl_raw_hash_set = 20240722, absl_algorithm_container = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_node_slot_policy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_node_slot_policy.pc new file mode 100644 index 0000000..a76d24a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_node_slot_policy.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_node_slot_policy +Description: Abseil node_slot_policy library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_non_temporal_arm_intrinsics.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_non_temporal_arm_intrinsics.pc new file mode 100644 index 0000000..8867793 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_non_temporal_arm_intrinsics.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_non_temporal_arm_intrinsics +Description: Abseil non_temporal_arm_intrinsics library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_non_temporal_memcpy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_non_temporal_memcpy.pc new file mode 100644 index 0000000..cead8e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_non_temporal_memcpy.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_non_temporal_memcpy +Description: Abseil non_temporal_memcpy library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_non_temporal_arm_intrinsics = 20240722, absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_nullability.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_nullability.pc new file mode 100644 index 0000000..1ad40e5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_nullability.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_nullability +Description: Abseil nullability library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_numeric.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_numeric.pc new file mode 100644 index 0000000..f2ccd5b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_numeric.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_numeric +Description: Abseil numeric library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_int128 = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_numeric_representation.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_numeric_representation.pc new file mode 100644 index 0000000..bff418a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_numeric_representation.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_numeric_representation +Description: Abseil numeric_representation library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_optional.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_optional.pc new file mode 100644 index 0000000..1137364 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_optional.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_optional +Description: Abseil optional library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_optional_access = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_memory = 20240722, absl_nullability = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_overload.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_overload.pc new file mode 100644 index 0000000..23c8e6d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_overload.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_overload +Description: Abseil overload library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_periodic_sampler.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_periodic_sampler.pc new file mode 100644 index 0000000..eac6e1f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_periodic_sampler.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_periodic_sampler +Description: Abseil periodic_sampler library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_periodic_sampler +Requires: absl_core_headers = 20240722, absl_exponential_biased = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_poison.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_poison.pc new file mode 100644 index 0000000..51554cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_poison.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_poison +Description: Abseil poison library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_poison +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_malloc_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_prefetch.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_prefetch.pc new file mode 100644 index 0000000..db2731d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_prefetch.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_prefetch +Description: Abseil prefetch library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_pretty_function.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_pretty_function.pc new file mode 100644 index 0000000..a77d50d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_pretty_function.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_pretty_function +Description: Abseil pretty_function library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_bit_gen_ref.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_bit_gen_ref.pc new file mode 100644 index 0000000..0d833bb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_bit_gen_ref.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_bit_gen_ref +Description: Abseil random_bit_gen_ref library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_random_internal_distribution_caller = 20240722, absl_random_internal_fast_uniform_bits = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_distributions.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_distributions.pc new file mode 100644 index 0000000..720d7b0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_distributions.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_distributions +Description: Abseil random_distributions library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_distributions +Requires: absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_random_internal_generate_real = 20240722, absl_random_internal_distribution_caller = 20240722, absl_random_internal_fast_uniform_bits = 20240722, absl_random_internal_fastmath = 20240722, absl_random_internal_iostream_state_saver = 20240722, absl_random_internal_traits = 20240722, absl_random_internal_uniform_helper = 20240722, absl_random_internal_wide_multiply = 20240722, absl_strings = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_distribution_caller.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_distribution_caller.pc new file mode 100644 index 0000000..66a5375 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_distribution_caller.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_distribution_caller +Description: Abseil random_internal_distribution_caller library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_utility = 20240722, absl_fast_type_id = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_distribution_test_util.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_distribution_test_util.pc new file mode 100644 index 0000000..70fe5c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_distribution_test_util.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_distribution_test_util +Description: Abseil random_internal_distribution_test_util library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_distribution_test_util +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_str_format = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_fast_uniform_bits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_fast_uniform_bits.pc new file mode 100644 index 0000000..e6a97b4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_fast_uniform_bits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_fast_uniform_bits +Description: Abseil random_internal_fast_uniform_bits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_fastmath.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_fastmath.pc new file mode 100644 index 0000000..c7e9a6a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_fastmath.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_fastmath +Description: Abseil random_internal_fastmath library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_generate_real.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_generate_real.pc new file mode 100644 index 0000000..1a9dd95 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_generate_real.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_generate_real +Description: Abseil random_internal_generate_real library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722, absl_random_internal_fastmath = 20240722, absl_random_internal_traits = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_iostream_state_saver.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_iostream_state_saver.pc new file mode 100644 index 0000000..cefa15a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_iostream_state_saver.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_iostream_state_saver +Description: Abseil random_internal_iostream_state_saver library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_int128 = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_mock_helpers.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_mock_helpers.pc new file mode 100644 index 0000000..1868f39 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_mock_helpers.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_mock_helpers +Description: Abseil random_internal_mock_helpers library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_fast_type_id = 20240722, absl_optional = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_nonsecure_base.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_nonsecure_base.pc new file mode 100644 index 0000000..d16f277 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_nonsecure_base.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_nonsecure_base +Description: Abseil random_internal_nonsecure_base library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_inlined_vector = 20240722, absl_random_internal_pool_urbg = 20240722, absl_random_internal_salted_seed_seq = 20240722, absl_random_internal_seed_material = 20240722, absl_span = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_pcg_engine.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_pcg_engine.pc new file mode 100644 index 0000000..c388c97 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_pcg_engine.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_pcg_engine +Description: Abseil random_internal_pcg_engine library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_int128 = 20240722, absl_random_internal_fastmath = 20240722, absl_random_internal_iostream_state_saver = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_platform.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_platform.pc new file mode 100644 index 0000000..c034993 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_platform.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_platform +Description: Abseil random_internal_platform library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_platform +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_pool_urbg.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_pool_urbg.pc new file mode 100644 index 0000000..8c44151 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_pool_urbg.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_pool_urbg +Description: Abseil random_internal_pool_urbg library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_pool_urbg +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_random_internal_randen = 20240722, absl_random_internal_seed_material = 20240722, absl_random_internal_traits = 20240722, absl_random_seed_gen_exception = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen.pc new file mode 100644 index 0000000..a48ee09 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen +Description: Abseil random_internal_randen library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen +Requires: absl_random_internal_platform = 20240722, absl_random_internal_randen_hwaes = 20240722, absl_random_internal_randen_slow = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen_engine.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen_engine.pc new file mode 100644 index 0000000..7157894 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen_engine.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_engine +Description: Abseil random_internal_randen_engine library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_endian = 20240722, absl_random_internal_iostream_state_saver = 20240722, absl_random_internal_randen = 20240722, absl_raw_logging_internal = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen_hwaes.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen_hwaes.pc new file mode 100644 index 0000000..07f3bc1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen_hwaes.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_hwaes +Description: Abseil random_internal_randen_hwaes library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen_hwaes +Requires: absl_random_internal_platform = 20240722, absl_random_internal_randen_hwaes_impl = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen_hwaes_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen_hwaes_impl.pc new file mode 100644 index 0000000..ff47df1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen_hwaes_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_hwaes_impl +Description: Abseil random_internal_randen_hwaes_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen_hwaes_impl +Requires: absl_random_internal_platform = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen_slow.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen_slow.pc new file mode 100644 index 0000000..feb3902 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_randen_slow.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_slow +Description: Abseil random_internal_randen_slow library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen_slow +Requires: absl_random_internal_platform = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_salted_seed_seq.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_salted_seed_seq.pc new file mode 100644 index 0000000..94e4378 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_salted_seed_seq.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_salted_seed_seq +Description: Abseil random_internal_salted_seed_seq library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_inlined_vector = 20240722, absl_optional = 20240722, absl_span = 20240722, absl_random_internal_seed_material = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_seed_material.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_seed_material.pc new file mode 100644 index 0000000..644704d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_seed_material.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_seed_material +Description: Abseil random_internal_seed_material library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_seed_material +Requires: absl_core_headers = 20240722, absl_optional = 20240722, absl_random_internal_fast_uniform_bits = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_traits.pc new file mode 100644 index 0000000..a33e4ea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_traits +Description: Abseil random_internal_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_uniform_helper.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_uniform_helper.pc new file mode 100644 index 0000000..0e7f376 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_uniform_helper.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_uniform_helper +Description: Abseil random_internal_uniform_helper library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_random_internal_traits = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_wide_multiply.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_wide_multiply.pc new file mode 100644 index 0000000..988ee11 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_internal_wide_multiply.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_wide_multiply +Description: Abseil random_internal_wide_multiply library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722, absl_config = 20240722, absl_int128 = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_random.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_random.pc new file mode 100644 index 0000000..5bfb93d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_random.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_random +Description: Abseil random_random library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_random_distributions = 20240722, absl_random_internal_nonsecure_base = 20240722, absl_random_internal_pcg_engine = 20240722, absl_random_internal_pool_urbg = 20240722, absl_random_internal_randen_engine = 20240722, absl_random_seed_sequences = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_seed_gen_exception.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_seed_gen_exception.pc new file mode 100644 index 0000000..6c78196 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_seed_gen_exception.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_seed_gen_exception +Description: Abseil random_seed_gen_exception library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_seed_gen_exception +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_seed_sequences.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_seed_sequences.pc new file mode 100644 index 0000000..1998470 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_random_seed_sequences.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_seed_sequences +Description: Abseil random_seed_sequences library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_seed_sequences +Requires: absl_config = 20240722, absl_inlined_vector = 20240722, absl_nullability = 20240722, absl_random_internal_pool_urbg = 20240722, absl_random_internal_salted_seed_seq = 20240722, absl_random_internal_seed_material = 20240722, absl_random_seed_gen_exception = 20240722, absl_span = 20240722, absl_string_view = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_raw_hash_map.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_raw_hash_map.pc new file mode 100644 index 0000000..77f1e3f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_raw_hash_map.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_raw_hash_map +Description: Abseil raw_hash_map library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_container_memory = 20240722, absl_core_headers = 20240722, absl_raw_hash_set = 20240722, absl_throw_delegate = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_raw_hash_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_raw_hash_set.pc new file mode 100644 index 0000000..ed4f83c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_raw_hash_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_raw_hash_set +Description: Abseil raw_hash_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_raw_hash_set +Requires: absl_bits = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_container_common = 20240722, absl_container_memory = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_endian = 20240722, absl_hash = 20240722, absl_hash_policy_traits = 20240722, absl_hashtable_debug_hooks = 20240722, absl_hashtablez_sampler = 20240722, absl_memory = 20240722, absl_meta = 20240722, absl_optional = 20240722, absl_prefetch = 20240722, absl_raw_logging_internal = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_raw_logging_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_raw_logging_internal.pc new file mode 100644 index 0000000..a120546 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_raw_logging_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_raw_logging_internal +Description: Abseil raw_logging_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_raw_logging_internal +Requires: absl_atomic_hook = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722, absl_log_severity = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_sample_recorder.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_sample_recorder.pc new file mode 100644 index 0000000..3025734 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_sample_recorder.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_sample_recorder +Description: Abseil sample_recorder library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_scoped_set_env.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_scoped_set_env.pc new file mode 100644 index 0000000..5799969 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_scoped_set_env.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_scoped_set_env +Description: Abseil scoped_set_env library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_scoped_set_env +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_span.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_span.pc new file mode 100644 index 0000000..654b8d0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_span.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_span +Description: Abseil span library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_algorithm = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_spinlock_wait.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_spinlock_wait.pc new file mode 100644 index 0000000..3f3d495 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_spinlock_wait.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_spinlock_wait +Description: Abseil spinlock_wait library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_spinlock_wait +Requires: absl_base_internal = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_stacktrace.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_stacktrace.pc new file mode 100644 index 0000000..9375890 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_stacktrace.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_stacktrace +Description: Abseil stacktrace library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_stacktrace +Requires: absl_debugging_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_status.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_status.pc new file mode 100644 index 0000000..5a32ee5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_status.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_status +Description: Abseil status library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_status +Requires: absl_atomic_hook = 20240722, absl_config = 20240722, absl_cord = 20240722, absl_core_headers = 20240722, absl_function_ref = 20240722, absl_inlined_vector = 20240722, absl_memory = 20240722, absl_no_destructor = 20240722, absl_nullability = 20240722, absl_optional = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722, absl_stacktrace = 20240722, absl_strerror = 20240722, absl_str_format = 20240722, absl_strings = 20240722, absl_symbolize = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_statusor.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_statusor.pc new file mode 100644 index 0000000..e70bd45 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_statusor.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_statusor +Description: Abseil statusor library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_statusor +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_has_ostream_operator = 20240722, absl_nullability = 20240722, absl_raw_logging_internal = 20240722, absl_status = 20240722, absl_str_format = 20240722, absl_strings = 20240722, absl_type_traits = 20240722, absl_utility = 20240722, absl_variant = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_str_format.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_str_format.pc new file mode 100644 index 0000000..bfe84a5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_str_format.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_str_format +Description: Abseil str_format library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722, absl_span = 20240722, absl_str_format_internal = 20240722, absl_string_view = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_str_format_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_str_format_internal.pc new file mode 100644 index 0000000..8c95e7d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_str_format_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_str_format_internal +Description: Abseil str_format_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_str_format_internal +Requires: absl_bits = 20240722, absl_strings = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_fixed_array = 20240722, absl_inlined_vector = 20240722, absl_numeric_representation = 20240722, absl_type_traits = 20240722, absl_utility = 20240722, absl_int128 = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_strerror.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_strerror.pc new file mode 100644 index 0000000..a595aa1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_strerror.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_strerror +Description: Abseil strerror library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_strerror +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_string_view.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_string_view.pc new file mode 100644 index 0000000..93dd126 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_string_view.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_string_view +Description: Abseil string_view library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_string_view +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722, absl_throw_delegate = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_strings.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_strings.pc new file mode 100644 index 0000000..1b1a9f1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_strings.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_strings +Description: Abseil strings library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_strings +Requires: absl_string_view = 20240722, absl_strings_internal = 20240722, absl_base = 20240722, absl_bits = 20240722, absl_charset = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_int128 = 20240722, absl_memory = 20240722, absl_nullability = 20240722, absl_raw_logging_internal = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_strings_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_strings_internal.pc new file mode 100644 index 0000000..08a65cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_strings_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_strings_internal +Description: Abseil strings_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_strings_internal +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_raw_logging_internal = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_symbolize.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_symbolize.pc new file mode 100644 index 0000000..41275af --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_symbolize.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_symbolize +Description: Abseil symbolize library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_symbolize +Requires: absl_debugging_internal = 20240722, absl_demangle_internal = 20240722, absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_malloc_internal = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_synchronization.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_synchronization.pc new file mode 100644 index 0000000..7f17cde --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_synchronization.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_synchronization +Description: Abseil synchronization library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_synchronization +Requires: absl_graphcycles_internal = 20240722, absl_kernel_timeout_internal = 20240722, absl_atomic_hook = 20240722, absl_base = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_malloc_internal = 20240722, absl_raw_logging_internal = 20240722, absl_stacktrace = 20240722, absl_symbolize = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_throw_delegate.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_throw_delegate.pc new file mode 100644 index 0000000..57aa119 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_throw_delegate.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_throw_delegate +Description: Abseil throw_delegate library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_throw_delegate +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_time.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_time.pc new file mode 100644 index 0000000..5e094a1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_time.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_time +Description: Abseil time library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_time +Requires: absl_base = 20240722, absl_civil_time = 20240722, absl_core_headers = 20240722, absl_int128 = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_time_zone = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_time_zone.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_time_zone.pc new file mode 100644 index 0000000..eb3857a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_time_zone.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_time_zone +Description: Abseil time_zone library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_time_zone +Requires: +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_type_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_type_traits.pc new file mode 100644 index 0000000..44e060c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_type_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_type_traits +Description: Abseil type_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_utf8_for_code_point.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_utf8_for_code_point.pc new file mode 100644 index 0000000..c53dcb7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_utf8_for_code_point.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_utf8_for_code_point +Description: Abseil utf8_for_code_point library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_utf8_for_code_point +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_utility.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_utility.pc new file mode 100644 index 0000000..503991f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_utility.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_utility +Description: Abseil utility library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_config = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_variant.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_variant.pc new file mode 100644 index 0000000..84303ae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_variant.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_variant +Description: Abseil variant library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_variant_access = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_vlog_config_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_vlog_config_internal.pc new file mode 100644 index 0000000..94abf70 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_vlog_config_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_vlog_config_internal +Description: Abseil vlog_config_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_vlog_config_internal +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_fnmatch = 20240722, absl_memory = 20240722, absl_no_destructor = 20240722, absl_strings = 20240722, absl_synchronization = 20240722, absl_optional = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_vlog_is_on.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_vlog_is_on.pc new file mode 100644 index 0000000..b55ea5f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/absl_vlog_is_on.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_vlog_is_on +Description: Abseil vlog_is_on library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_absl_vlog_is_on = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/draco.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/draco.pc new file mode 100644 index 0000000..a5120c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/draco.pc @@ -0,0 +1,7 @@ +prefix=${pcfiledir}/../.. +Name: draco +Description: Draco geometry de(com)pression library. +Version: 1.5.7 + +Libs: "-L${prefix}/lib" -ldraco +Cflags: "-I${prefix}/include" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/fmt.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/fmt.pc new file mode 100644 index 0000000..9650070 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/fmt.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: fmt +Description: A modern formatting library +Version: 11.0.2 + + +Libs: "-L${libdir}" -lfmt +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libjpeg.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libjpeg.pc new file mode 100644 index 0000000..bef720f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libjpeg.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: libjpeg +Description: A SIMD-accelerated JPEG codec that provides the libjpeg API +Version: 3.0.4 + +Libs: "-L${libdir}" -ljpeg +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libsharpyuv.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libsharpyuv.pc new file mode 100644 index 0000000..9349c28 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libsharpyuv.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/webp + +Name: libsharpyuv +Description: Library for sharp RGB to YUV conversion +Version: 1.4.0 + +Libs: "-L${libdir}" -lsharpyuv +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libturbojpeg.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libturbojpeg.pc new file mode 100644 index 0000000..eeee26d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libturbojpeg.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: libturbojpeg +Description: A SIMD-accelerated JPEG codec that provides the TurboJPEG API +Version: 3.0.4 + +Libs: "-L${libdir}" -lturbojpeg +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/liburiparser.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/liburiparser.pc new file mode 100644 index 0000000..75afa89 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/liburiparser.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: liburiparser +Description: URI parsing and handling library + +Version: 0.9.8 +URL: https://uriparser.github.io/ + +Libs: "-L${libdir}" -luriparser +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libwebp.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libwebp.pc new file mode 100644 index 0000000..aa5e7c0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libwebp.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebp +Description: Library for the WebP graphics format +Version: 1.4.0 + +Libs: "-L${libdir}" -lwebp +Requires: libsharpyuv +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libwebpdecoder.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libwebpdecoder.pc new file mode 100644 index 0000000..7b170f7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libwebpdecoder.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebpdecoder +Description: Library for the WebP graphics format (decode only) +Version: 1.4.0 + +Libs: "-L${libdir}" -lwebpdecoder +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libwebpdemux.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libwebpdemux.pc new file mode 100644 index 0000000..5730238 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libwebpdemux.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebpdemux +Description: Library for parsing the WebP graphics format container +Version: 1.4.0 + +Libs: "-L${libdir}" -lwebpdemux +Requires: libwebp >= 0.2.0 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libwebpmux.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libwebpmux.pc new file mode 100644 index 0000000..5270237 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libwebpmux.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebpmux +Description: Library for manipulating the WebP graphics format container +Version: 1.4.0 + +Libs: "-L${libdir}" -lwebpmux +Requires: libwebp >= 0.2.0 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libzstd.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libzstd.pc new file mode 100644 index 0000000..6e08863 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/libzstd.pc @@ -0,0 +1,16 @@ +prefix=${pcfiledir}/../.. +# ZSTD - standard compression algorithm +# Copyright (c) Meta Platforms, Inc. and affiliates. +# BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +Name: zstd +Description: fast lossless compression algorithm library +URL: https://facebook.github.io/zstd/ +Version: 1.5.6 + +Libs: "-L${libdir}" -lzstd +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/spdlog.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/spdlog.pc new file mode 100644 index 0000000..3b2aab0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/spdlog.pc @@ -0,0 +1,14 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +Name: libspdlog +Description: Fast C++ logging library. +URL: https://github.com/gabime/spdlog +Version: 1.15.0 +CFlags: "-I${includedir}" -DSPDLOG_COMPILED_LIB -DSPDLOG_FMT_EXTERNAL + + +Libs: "-L${libdir}" -lspdlog -pthread +Requires: fmt diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/sqlite3.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/sqlite3.pc new file mode 100644 index 0000000..951d72c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/sqlite3.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: SQLite +Description: SQL database engine +Version: 3.45.0 + +Libs: "-L${libdir}" -lsqlite3 -pthread -ldl +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/tidy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/tidy.pc new file mode 100644 index 0000000..2fd9a7b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/tidy.pc @@ -0,0 +1,11 @@ +prefix=/home/runner/work/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty +exec_prefix=${prefix} +libdir=${exec_prefix}//home/runner/work/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty/lib/Linux-x86_64-$,Debug,Release> +includedir=${prefix}/include + +Name: tidy +Description: tidy - HTML syntax checker +URL: https://www.html-tidy.org +Version: 5.9.14 +Libs: -L${libdir} -ltidy +Cflags: -I${includedir} diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/tinyxml2.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/tinyxml2.pc new file mode 100644 index 0000000..24bbedf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/tinyxml2.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: TinyXML2 +Description: simple, small, C++ XML parser +Version: 10.0.0 + +Libs: "-L${libdir}" -ltinyxml2 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/zlib-ng.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/zlib-ng.pc new file mode 100644 index 0000000..9a4a354 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x86_64-Release/pkgconfig/zlib-ng.pc @@ -0,0 +1,15 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +symbol_prefix= +libdir=${exec_prefix}/lib +sharedlibdir=${libdir} +includedir=${prefix}/include + +Name: zlib-ng +Description: zlib-ng compression library +Version: 2.1.6 + + +Libs: "-L${libdir}" "-L${sharedlibdir}" -lz-ng +Requires: +Cflags: "-I${includedir}" -DWITH_GZFILEOP diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/cmake/zlib-ng/zlib-ng-release.cmake b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/cmake/zlib-ng/zlib-ng-release.cmake new file mode 100644 index 0000000..5259d10 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/cmake/zlib-ng/zlib-ng-release.cmake @@ -0,0 +1,19 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "zlib-ng::zlib" for configuration "Release" +set_property(TARGET zlib-ng::zlib APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(zlib-ng::zlib PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/zlibstatic-ng.lib" + ) + +list(APPEND _cmake_import_check_targets zlib-ng::zlib ) +list(APPEND _cmake_import_check_files_for_zlib-ng::zlib "${_IMPORT_PREFIX}/lib/zlibstatic-ng.lib" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/cmake/zlib-ng/zlib-ng.cmake b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/cmake/zlib-ng/zlib-ng.cmake new file mode 100644 index 0000000..034b039 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/cmake/zlib-ng/zlib-ng.cmake @@ -0,0 +1,107 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.3") + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.3...3.29) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS zlib-ng::zlib) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target zlib-ng::zlib +add_library(zlib-ng::zlib STATIC IMPORTED) + +set_target_properties(zlib-ng::zlib PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "ZLIBNG_NATIVE_API" + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" +) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/zlib-ng-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + if(CMAKE_VERSION VERSION_LESS "3.28" + OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} + OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + endif() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_absl_check.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_absl_check.pc new file mode 100644 index 0000000..8efe68f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_absl_check.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_absl_check +Description: Abseil absl_check library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_log_internal_check_impl = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_absl_log.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_absl_log.pc new file mode 100644 index 0000000..c62c44f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_absl_log.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_absl_log +Description: Abseil absl_log library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_log_internal_log_impl = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_absl_vlog_is_on.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_absl_vlog_is_on.pc new file mode 100644 index 0000000..2e9e510 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_absl_vlog_is_on.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_absl_vlog_is_on +Description: Abseil absl_vlog_is_on library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_vlog_config_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_algorithm.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_algorithm.pc new file mode 100644 index 0000000..dd18e57 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_algorithm.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_algorithm +Description: Abseil algorithm library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_algorithm_container.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_algorithm_container.pc new file mode 100644 index 0000000..f146c0d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_algorithm_container.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_algorithm_container +Description: Abseil algorithm_container library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_algorithm = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_meta = 20240722, absl_nullability = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_any.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_any.pc new file mode 100644 index 0000000..a2ded6a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_any.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_any +Description: Abseil any library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_any_cast = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_fast_type_id = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_any_invocable.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_any_invocable.pc new file mode 100644 index 0000000..c420f2a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_any_invocable.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_any_invocable +Description: Abseil any_invocable library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_atomic_hook.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_atomic_hook.pc new file mode 100644 index 0000000..ad36647 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_atomic_hook.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_atomic_hook +Description: Abseil atomic_hook library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bad_any_cast.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bad_any_cast.pc new file mode 100644 index 0000000..e2c86d3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bad_any_cast.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_any_cast +Description: Abseil bad_any_cast library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_any_cast_impl = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bad_any_cast_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bad_any_cast_impl.pc new file mode 100644 index 0000000..1faffb7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bad_any_cast_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_any_cast_impl +Description: Abseil bad_any_cast_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_bad_any_cast_impl +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bad_optional_access.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bad_optional_access.pc new file mode 100644 index 0000000..7cd2b3a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bad_optional_access.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_optional_access +Description: Abseil bad_optional_access library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_bad_optional_access +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bad_variant_access.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bad_variant_access.pc new file mode 100644 index 0000000..96d97b3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bad_variant_access.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_variant_access +Description: Abseil bad_variant_access library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_bad_variant_access +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_base.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_base.pc new file mode 100644 index 0000000..e8693cc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_base.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_base +Description: Abseil base library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_base -ignore:4221 +Requires: absl_atomic_hook = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_log_severity = 20240722, absl_nullability = 20240722, absl_raw_logging_internal = 20240722, absl_spinlock_wait = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_base_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_base_internal.pc new file mode 100644 index 0000000..8f1a4b2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_base_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_base_internal +Description: Abseil base_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bind_front.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bind_front.pc new file mode 100644 index 0000000..f4eaa1c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bind_front.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bind_front +Description: Abseil bind_front library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_compressed_tuple = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bits.pc new file mode 100644 index 0000000..e5a5fef --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bits +Description: Abseil bits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bounded_utf8_length_sequence.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bounded_utf8_length_sequence.pc new file mode 100644 index 0000000..047894c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_bounded_utf8_length_sequence.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bounded_utf8_length_sequence +Description: Abseil bounded_utf8_length_sequence library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_btree.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_btree.pc new file mode 100644 index 0000000..dd06bce --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_btree.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_btree +Description: Abseil btree library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_common_policy_traits = 20240722, absl_compare = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_container_common = 20240722, absl_container_memory = 20240722, absl_cord = 20240722, absl_core_headers = 20240722, absl_layout = 20240722, absl_memory = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_charset.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_charset.pc new file mode 100644 index 0000000..368676f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_charset.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_charset +Description: Abseil charset library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_string_view = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_check.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_check.pc new file mode 100644 index 0000000..9af2069 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_check.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_check +Description: Abseil check library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_log_internal_check_impl = 20240722, absl_core_headers = 20240722, absl_log_internal_check_op = 20240722, absl_log_internal_conditions = 20240722, absl_log_internal_message = 20240722, absl_log_internal_strip = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_city.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_city.pc new file mode 100644 index 0000000..8266431 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_city.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_city +Description: Abseil city library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_city +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_civil_time.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_civil_time.pc new file mode 100644 index 0000000..2580470 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_civil_time.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_civil_time +Description: Abseil civil_time library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_civil_time +Requires: +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cleanup.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cleanup.pc new file mode 100644 index 0000000..a30332d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cleanup.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cleanup +Description: Abseil cleanup library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_cleanup_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cleanup_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cleanup_internal.pc new file mode 100644 index 0000000..51f3d22 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cleanup_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cleanup_internal +Description: Abseil cleanup_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_core_headers = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_common_policy_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_common_policy_traits.pc new file mode 100644 index 0000000..b659d91 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_common_policy_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_common_policy_traits +Description: Abseil common_policy_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_meta = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_compare.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_compare.pc new file mode 100644 index 0000000..fdd0817 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_compare.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_compare +Description: Abseil compare library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_compressed_tuple.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_compressed_tuple.pc new file mode 100644 index 0000000..cb9f41e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_compressed_tuple.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_compressed_tuple +Description: Abseil compressed_tuple library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_utility = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_config.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_config.pc new file mode 100644 index 0000000..df338b9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_config.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_config +Description: Abseil config library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_container_common.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_container_common.pc new file mode 100644 index 0000000..387504e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_container_common.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_container_common +Description: Abseil container_common library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_container_memory.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_container_memory.pc new file mode 100644 index 0000000..7f1c39b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_container_memory.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_container_memory +Description: Abseil container_memory library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_memory = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cord.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cord.pc new file mode 100644 index 0000000..ab6d0e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cord.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cord +Description: Abseil cord library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cord +Requires: absl_base = 20240722, absl_config = 20240722, absl_cord_internal = 20240722, absl_cordz_functions = 20240722, absl_cordz_info = 20240722, absl_cordz_update_scope = 20240722, absl_cordz_update_tracker = 20240722, absl_core_headers = 20240722, absl_crc32c = 20240722, absl_crc_cord_state = 20240722, absl_endian = 20240722, absl_function_ref = 20240722, absl_inlined_vector = 20240722, absl_nullability = 20240722, absl_optional = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722, absl_strings = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cord_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cord_internal.pc new file mode 100644 index 0000000..79b69c7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cord_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cord_internal +Description: Abseil cord_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cord_internal +Requires: absl_base_internal = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_container_memory = 20240722, absl_compare = 20240722, absl_core_headers = 20240722, absl_crc_cord_state = 20240722, absl_endian = 20240722, absl_inlined_vector = 20240722, absl_layout = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_functions.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_functions.pc new file mode 100644 index 0000000..e465e2c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_functions.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_functions +Description: Abseil cordz_functions library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_functions +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_exponential_biased = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_handle.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_handle.pc new file mode 100644 index 0000000..cb37170 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_handle.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_handle +Description: Abseil cordz_handle library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_handle +Requires: absl_base = 20240722, absl_config = 20240722, absl_no_destructor = 20240722, absl_raw_logging_internal = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_info.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_info.pc new file mode 100644 index 0000000..d230b09 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_info.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_info +Description: Abseil cordz_info library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_info +Requires: absl_base = 20240722, absl_config = 20240722, absl_cord_internal = 20240722, absl_cordz_functions = 20240722, absl_cordz_handle = 20240722, absl_cordz_statistics = 20240722, absl_cordz_update_tracker = 20240722, absl_core_headers = 20240722, absl_inlined_vector = 20240722, absl_span = 20240722, absl_raw_logging_internal = 20240722, absl_stacktrace = 20240722, absl_synchronization = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_sample_token.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_sample_token.pc new file mode 100644 index 0000000..6e34ee3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_sample_token.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_sample_token +Description: Abseil cordz_sample_token library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_sample_token +Requires: absl_config = 20240722, absl_cordz_handle = 20240722, absl_cordz_info = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_statistics.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_statistics.pc new file mode 100644 index 0000000..cb11657 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_statistics.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_statistics +Description: Abseil cordz_statistics library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_cordz_update_tracker = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_update_scope.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_update_scope.pc new file mode 100644 index 0000000..1f0eb2d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_update_scope.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_update_scope +Description: Abseil cordz_update_scope library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_cord_internal = 20240722, absl_cordz_info = 20240722, absl_cordz_update_tracker = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_update_tracker.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_update_tracker.pc new file mode 100644 index 0000000..2996837 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_cordz_update_tracker.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_update_tracker +Description: Abseil cordz_update_tracker library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_core_headers.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_core_headers.pc new file mode 100644 index 0000000..cf0d099 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_core_headers.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_core_headers +Description: Abseil core_headers library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_crc32c.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_crc32c.pc new file mode 100644 index 0000000..9ecd3b1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_crc32c.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc32c +Description: Abseil crc32c library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc32c +Requires: absl_crc_cpu_detect = 20240722, absl_crc_internal = 20240722, absl_non_temporal_memcpy = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_prefetch = 20240722, absl_str_format = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_crc_cord_state.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_crc_cord_state.pc new file mode 100644 index 0000000..c455d8e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_crc_cord_state.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc_cord_state +Description: Abseil crc_cord_state library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc_cord_state +Requires: absl_crc32c = 20240722, absl_config = 20240722, absl_strings = 20240722, absl_no_destructor = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_crc_cpu_detect.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_crc_cpu_detect.pc new file mode 100644 index 0000000..ee7c0db --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_crc_cpu_detect.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc_cpu_detect +Description: Abseil crc_cpu_detect library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc_cpu_detect +Requires: absl_base = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_crc_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_crc_internal.pc new file mode 100644 index 0000000..3eb4e45 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_crc_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc_internal +Description: Abseil crc_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc_internal +Requires: absl_crc_cpu_detect = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_prefetch = 20240722, absl_raw_logging_internal = 20240722, absl_memory = 20240722, absl_bits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_debugging.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_debugging.pc new file mode 100644 index 0000000..328fcab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_debugging.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_debugging +Description: Abseil debugging library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_stacktrace = 20240722, absl_leak_check = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_debugging_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_debugging_internal.pc new file mode 100644 index 0000000..9e6d68e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_debugging_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_debugging_internal +Description: Abseil debugging_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_debugging_internal +Requires: absl_core_headers = 20240722, absl_config = 20240722, absl_dynamic_annotations = 20240722, absl_errno_saver = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_decode_rust_punycode.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_decode_rust_punycode.pc new file mode 100644 index 0000000..58246f3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_decode_rust_punycode.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_decode_rust_punycode +Description: Abseil decode_rust_punycode library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_decode_rust_punycode +Requires: absl_bounded_utf8_length_sequence = 20240722, absl_config = 20240722, absl_nullability = 20240722, absl_utf8_for_code_point = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_demangle_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_demangle_internal.pc new file mode 100644 index 0000000..28a5c2c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_demangle_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_demangle_internal +Description: Abseil demangle_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_demangle_internal +Requires: absl_config = 20240722, absl_demangle_rust = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_demangle_rust.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_demangle_rust.pc new file mode 100644 index 0000000..b28d4e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_demangle_rust.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_demangle_rust +Description: Abseil demangle_rust library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_demangle_rust +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_decode_rust_punycode = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_die_if_null.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_die_if_null.pc new file mode 100644 index 0000000..ad40569 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_die_if_null.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_die_if_null +Description: Abseil die_if_null library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_die_if_null -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_dynamic_annotations.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_dynamic_annotations.pc new file mode 100644 index 0000000..d816c24 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_dynamic_annotations.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_dynamic_annotations +Description: Abseil dynamic_annotations library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_endian.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_endian.pc new file mode 100644 index 0000000..6cab67c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_endian.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_endian +Description: Abseil endian library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_errno_saver.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_errno_saver.pc new file mode 100644 index 0000000..d6db5a2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_errno_saver.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_errno_saver +Description: Abseil errno_saver library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_examine_stack.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_examine_stack.pc new file mode 100644 index 0000000..ab11ef9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_examine_stack.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_examine_stack +Description: Abseil examine_stack library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_examine_stack +Requires: absl_stacktrace = 20240722, absl_symbolize = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_exponential_biased.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_exponential_biased.pc new file mode 100644 index 0000000..8d807a5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_exponential_biased.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_exponential_biased +Description: Abseil exponential_biased library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_exponential_biased +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_failure_signal_handler.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_failure_signal_handler.pc new file mode 100644 index 0000000..c38f40f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_failure_signal_handler.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_failure_signal_handler +Description: Abseil failure_signal_handler library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_failure_signal_handler +Requires: absl_examine_stack = 20240722, absl_stacktrace = 20240722, absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_fast_type_id.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_fast_type_id.pc new file mode 100644 index 0000000..f803688 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_fast_type_id.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_fast_type_id +Description: Abseil fast_type_id library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_fixed_array.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_fixed_array.pc new file mode 100644 index 0000000..8890150 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_fixed_array.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_fixed_array +Description: Abseil fixed_array library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_compressed_tuple = 20240722, absl_algorithm = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_throw_delegate = 20240722, absl_memory = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags.pc new file mode 100644 index 0000000..84c18bf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags +Description: Abseil flags library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_config = 20240722, absl_flags_internal = 20240722, absl_flags_reflection = 20240722, absl_core_headers = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_commandlineflag.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_commandlineflag.pc new file mode 100644 index 0000000..280aafd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_commandlineflag.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_commandlineflag +Description: Abseil flags_commandlineflag library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_commandlineflag -ignore:4221 +Requires: absl_config = 20240722, absl_fast_type_id = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_optional = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_commandlineflag_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_commandlineflag_internal.pc new file mode 100644 index 0000000..091ffcf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_commandlineflag_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_commandlineflag_internal +Description: Abseil flags_commandlineflag_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_commandlineflag_internal -ignore:4221 +Requires: absl_config = 20240722, absl_dynamic_annotations = 20240722, absl_fast_type_id = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_config.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_config.pc new file mode 100644 index 0000000..5762bd0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_config.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_config +Description: Abseil flags_config library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_config -ignore:4221 +Requires: absl_config = 20240722, absl_flags_path_util = 20240722, absl_flags_program_name = 20240722, absl_core_headers = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_internal.pc new file mode 100644 index 0000000..637e9e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_internal +Description: Abseil flags_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_internal -ignore:4221 +Requires: absl_base = 20240722, absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_flags_config = 20240722, absl_flags_marshalling = 20240722, absl_synchronization = 20240722, absl_meta = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_marshalling.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_marshalling.pc new file mode 100644 index 0000000..36cf40c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_marshalling.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_marshalling +Description: Abseil flags_marshalling library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_marshalling -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_severity = 20240722, absl_int128 = 20240722, absl_optional = 20240722, absl_strings = 20240722, absl_str_format = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_parse.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_parse.pc new file mode 100644 index 0000000..9c84983 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_parse.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_parse +Description: Abseil flags_parse library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_parse -ignore:4221 +Requires: absl_algorithm_container = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_flags_config = 20240722, absl_flags = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_flags_internal = 20240722, absl_flags_private_handle_accessor = 20240722, absl_flags_program_name = 20240722, absl_flags_reflection = 20240722, absl_flags_usage = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_path_util.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_path_util.pc new file mode 100644 index 0000000..cdd197e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_path_util.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_path_util +Description: Abseil flags_path_util library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_private_handle_accessor.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_private_handle_accessor.pc new file mode 100644 index 0000000..627e182 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_private_handle_accessor.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_private_handle_accessor +Description: Abseil flags_private_handle_accessor library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_private_handle_accessor -ignore:4221 +Requires: absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_program_name.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_program_name.pc new file mode 100644 index 0000000..69475d2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_program_name.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_program_name +Description: Abseil flags_program_name library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_program_name -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_flags_path_util = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_reflection.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_reflection.pc new file mode 100644 index 0000000..e75e080 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_reflection.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_reflection +Description: Abseil flags_reflection library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_reflection -ignore:4221 +Requires: absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_private_handle_accessor = 20240722, absl_flags_config = 20240722, absl_strings = 20240722, absl_synchronization = 20240722, absl_flat_hash_map = 20240722, absl_no_destructor = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_usage.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_usage.pc new file mode 100644 index 0000000..e5a0b9d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_usage.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_usage +Description: Abseil flags_usage library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_usage -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_flags_usage_internal = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_usage_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_usage_internal.pc new file mode 100644 index 0000000..4d17b1d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flags_usage_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_usage_internal +Description: Abseil flags_usage_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_usage_internal -ignore:4221 +Requires: absl_config = 20240722, absl_flags_config = 20240722, absl_flags = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_internal = 20240722, absl_flags_path_util = 20240722, absl_flags_private_handle_accessor = 20240722, absl_flags_program_name = 20240722, absl_flags_reflection = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flat_hash_map.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flat_hash_map.pc new file mode 100644 index 0000000..eafcede --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flat_hash_map.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flat_hash_map +Description: Abseil flat_hash_map library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_core_headers = 20240722, absl_hash_container_defaults = 20240722, absl_raw_hash_map = 20240722, absl_algorithm_container = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flat_hash_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flat_hash_set.pc new file mode 100644 index 0000000..e0dcc24 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_flat_hash_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flat_hash_set +Description: Abseil flat_hash_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_hash_container_defaults = 20240722, absl_raw_hash_set = 20240722, absl_algorithm_container = 20240722, absl_core_headers = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_function_ref.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_function_ref.pc new file mode 100644 index 0000000..f4a8321 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_function_ref.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_function_ref +Description: Abseil function_ref library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_core_headers = 20240722, absl_any_invocable = 20240722, absl_meta = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_graphcycles_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_graphcycles_internal.pc new file mode 100644 index 0000000..495671a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_graphcycles_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_graphcycles_internal +Description: Abseil graphcycles_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_graphcycles_internal +Requires: absl_base = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_malloc_internal = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_has_ostream_operator.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_has_ostream_operator.pc new file mode 100644 index 0000000..e95f9a3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_has_ostream_operator.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_has_ostream_operator +Description: Abseil has_ostream_operator library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hash.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hash.pc new file mode 100644 index 0000000..9883b14 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hash.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash +Description: Abseil hash library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_hash +Requires: absl_bits = 20240722, absl_city = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_fixed_array = 20240722, absl_function_ref = 20240722, absl_meta = 20240722, absl_int128 = 20240722, absl_strings = 20240722, absl_optional = 20240722, absl_variant = 20240722, absl_utility = 20240722, absl_low_level_hash = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hash_container_defaults.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hash_container_defaults.pc new file mode 100644 index 0000000..941fef5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hash_container_defaults.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash_container_defaults +Description: Abseil hash_container_defaults library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_hash_function_defaults = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hash_function_defaults.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hash_function_defaults.pc new file mode 100644 index 0000000..c712483 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hash_function_defaults.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash_function_defaults +Description: Abseil hash_function_defaults library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_container_common = 20240722, absl_cord = 20240722, absl_hash = 20240722, absl_strings = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hash_policy_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hash_policy_traits.pc new file mode 100644 index 0000000..ddb1713 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hash_policy_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash_policy_traits +Description: Abseil hash_policy_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_common_policy_traits = 20240722, absl_meta = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hashtable_debug.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hashtable_debug.pc new file mode 100644 index 0000000..7262125 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hashtable_debug.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hashtable_debug +Description: Abseil hashtable_debug library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_hashtable_debug_hooks = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hashtable_debug_hooks.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hashtable_debug_hooks.pc new file mode 100644 index 0000000..9855bab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hashtable_debug_hooks.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hashtable_debug_hooks +Description: Abseil hashtable_debug_hooks library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hashtablez_sampler.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hashtablez_sampler.pc new file mode 100644 index 0000000..f4d380a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_hashtablez_sampler.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hashtablez_sampler +Description: Abseil hashtablez_sampler library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_hashtablez_sampler +Requires: absl_base = 20240722, absl_config = 20240722, absl_exponential_biased = 20240722, absl_no_destructor = 20240722, absl_raw_logging_internal = 20240722, absl_sample_recorder = 20240722, absl_synchronization = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_if_constexpr.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_if_constexpr.pc new file mode 100644 index 0000000..327e01b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_if_constexpr.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_if_constexpr +Description: Abseil if_constexpr library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_inlined_vector.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_inlined_vector.pc new file mode 100644 index 0000000..0f6715d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_inlined_vector.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_inlined_vector +Description: Abseil inlined_vector library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_algorithm = 20240722, absl_core_headers = 20240722, absl_inlined_vector_internal = 20240722, absl_throw_delegate = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_inlined_vector_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_inlined_vector_internal.pc new file mode 100644 index 0000000..e137780 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_inlined_vector_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_inlined_vector_internal +Description: Abseil inlined_vector_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_memory = 20240722, absl_span = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_int128.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_int128.pc new file mode 100644 index 0000000..e0c8df8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_int128.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_int128 +Description: Abseil int128 library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_int128 +Requires: absl_compare = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_bits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_kernel_timeout_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_kernel_timeout_internal.pc new file mode 100644 index 0000000..2f01b12 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_kernel_timeout_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_kernel_timeout_internal +Description: Abseil kernel_timeout_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_kernel_timeout_internal +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_layout.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_layout.pc new file mode 100644 index 0000000..c60490a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_layout.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_layout +Description: Abseil layout library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_debugging_internal = 20240722, absl_meta = 20240722, absl_strings = 20240722, absl_span = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_leak_check.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_leak_check.pc new file mode 100644 index 0000000..6533ded --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_leak_check.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_leak_check +Description: Abseil leak_check library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_leak_check +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log.pc new file mode 100644 index 0000000..ce34ac3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log +Description: Abseil log library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_log_internal_log_impl = 20240722, absl_vlog_is_on = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_entry.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_entry.pc new file mode 100644 index 0000000..29323c2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_entry.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_entry +Description: Abseil log_entry library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_entry -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_config = 20240722, absl_log_severity = 20240722, absl_span = 20240722, absl_strings = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_flags.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_flags.pc new file mode 100644 index 0000000..76afec9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_flags.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_flags +Description: Abseil log_flags library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_flags -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_globals = 20240722, absl_log_severity = 20240722, absl_log_internal_config = 20240722, absl_log_internal_flags = 20240722, absl_flags = 20240722, absl_flags_marshalling = 20240722, absl_strings = 20240722, absl_vlog_config_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_globals.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_globals.pc new file mode 100644 index 0000000..1a4862c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_globals.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_globals +Description: Abseil log_globals library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_globals -ignore:4221 +Requires: absl_atomic_hook = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_hash = 20240722, absl_log_severity = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_vlog_config_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_initialize.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_initialize.pc new file mode 100644 index 0000000..935f378 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_initialize.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_initialize +Description: Abseil log_initialize library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_initialize -ignore:4221 +Requires: absl_config = 20240722, absl_log_globals = 20240722, absl_log_internal_globals = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_append_truncated.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_append_truncated.pc new file mode 100644 index 0000000..141fa28 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_append_truncated.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_append_truncated +Description: Abseil log_internal_append_truncated library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_strings = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_check_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_check_impl.pc new file mode 100644 index 0000000..9fb176f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_check_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_check_impl +Description: Abseil log_internal_check_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_core_headers = 20240722, absl_log_internal_check_op = 20240722, absl_log_internal_conditions = 20240722, absl_log_internal_message = 20240722, absl_log_internal_strip = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_check_op.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_check_op.pc new file mode 100644 index 0000000..958e432 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_check_op.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_check_op +Description: Abseil log_internal_check_op library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_check_op -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_nullguard = 20240722, absl_log_internal_nullstream = 20240722, absl_log_internal_strip = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_conditions.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_conditions.pc new file mode 100644 index 0000000..b4ed47b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_conditions.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_conditions +Description: Abseil log_internal_conditions library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_conditions -ignore:4221 +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_voidify = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_config.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_config.pc new file mode 100644 index 0000000..a60c801 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_config.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_config +Description: Abseil log_internal_config library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_flags.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_flags.pc new file mode 100644 index 0000000..3062c7f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_flags.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_flags +Description: Abseil log_internal_flags library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_flags = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_fnmatch.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_fnmatch.pc new file mode 100644 index 0000000..b4c3851 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_fnmatch.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_fnmatch +Description: Abseil log_internal_fnmatch library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_fnmatch -ignore:4221 +Requires: absl_config = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_format.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_format.pc new file mode 100644 index 0000000..08155f6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_format.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_format +Description: Abseil log_internal_format library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_format -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_append_truncated = 20240722, absl_log_internal_config = 20240722, absl_log_internal_globals = 20240722, absl_log_severity = 20240722, absl_strings = 20240722, absl_str_format = 20240722, absl_time = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_globals.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_globals.pc new file mode 100644 index 0000000..b77cf35 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_globals.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_globals +Description: Abseil log_internal_globals library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_globals -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_severity = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_log_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_log_impl.pc new file mode 100644 index 0000000..f728742 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_log_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_log_impl +Description: Abseil log_internal_log_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_log_internal_conditions = 20240722, absl_log_internal_message = 20240722, absl_log_internal_strip = 20240722, absl_absl_vlog_is_on = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_log_sink_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_log_sink_set.pc new file mode 100644 index 0000000..a4dc981 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_log_sink_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_log_sink_set +Description: Abseil log_internal_log_sink_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_log_sink_set -ignore:4221 +Requires: absl_base = 20240722, absl_cleanup = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_config = 20240722, absl_log_internal_globals = 20240722, absl_log_globals = 20240722, absl_log_entry = 20240722, absl_log_severity = 20240722, absl_log_sink = 20240722, absl_no_destructor = 20240722, absl_raw_logging_internal = 20240722, absl_synchronization = 20240722, absl_span = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_message.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_message.pc new file mode 100644 index 0000000..298ff94 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_message.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_message +Description: Abseil log_internal_message library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_message -ignore:4221 +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722, absl_inlined_vector = 20240722, absl_examine_stack = 20240722, absl_log_internal_append_truncated = 20240722, absl_log_internal_format = 20240722, absl_log_internal_globals = 20240722, absl_log_internal_proto = 20240722, absl_log_internal_log_sink_set = 20240722, absl_log_internal_nullguard = 20240722, absl_log_globals = 20240722, absl_log_entry = 20240722, absl_log_severity = 20240722, absl_log_sink = 20240722, absl_log_sink_registry = 20240722, absl_memory = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_strerror = 20240722, absl_time = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_nullguard.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_nullguard.pc new file mode 100644 index 0000000..7856000 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_nullguard.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_nullguard +Description: Abseil log_internal_nullguard library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_nullguard -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_nullstream.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_nullstream.pc new file mode 100644 index 0000000..e522d52 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_nullstream.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_nullstream +Description: Abseil log_internal_nullstream library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_severity = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_proto.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_proto.pc new file mode 100644 index 0000000..1d3d349 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_proto.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_proto +Description: Abseil log_internal_proto library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_proto -ignore:4221 +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_strings = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_strip.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_strip.pc new file mode 100644 index 0000000..e04f812 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_strip.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_strip +Description: Abseil log_internal_strip library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_core_headers = 20240722, absl_log_internal_message = 20240722, absl_log_internal_nullstream = 20240722, absl_log_severity = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_structured.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_structured.pc new file mode 100644 index 0000000..3b1ac4f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_structured.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_structured +Description: Abseil log_internal_structured library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_log_internal_message = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_voidify.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_voidify.pc new file mode 100644 index 0000000..a88c2e9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_internal_voidify.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_voidify +Description: Abseil log_internal_voidify library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_severity.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_severity.pc new file mode 100644 index 0000000..949757f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_severity.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_severity +Description: Abseil log_severity library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_severity +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_sink.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_sink.pc new file mode 100644 index 0000000..6cc07a0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_sink.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_sink +Description: Abseil log_sink library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_sink -ignore:4221 +Requires: absl_config = 20240722, absl_log_entry = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_sink_registry.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_sink_registry.pc new file mode 100644 index 0000000..de9febf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_sink_registry.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_sink_registry +Description: Abseil log_sink_registry library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_log_sink = 20240722, absl_log_internal_log_sink_set = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_streamer.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_streamer.pc new file mode 100644 index 0000000..3350298 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_streamer.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_streamer +Description: Abseil log_streamer library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_absl_log = 20240722, absl_log_severity = 20240722, absl_optional = 20240722, absl_strings = 20240722, absl_strings_internal = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_structured.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_structured.pc new file mode 100644 index 0000000..8659b72 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_log_structured.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_structured +Description: Abseil log_structured library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_log_internal_structured = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_low_level_hash.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_low_level_hash.pc new file mode 100644 index 0000000..2b73937 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_low_level_hash.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_low_level_hash +Description: Abseil low_level_hash library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_low_level_hash +Requires: absl_config = 20240722, absl_endian = 20240722, absl_int128 = 20240722, absl_prefetch = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_malloc_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_malloc_internal.pc new file mode 100644 index 0000000..22d8292 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_malloc_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_malloc_internal +Description: Abseil malloc_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_malloc_internal +Requires: absl_base = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_memory.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_memory.pc new file mode 100644 index 0000000..7248bfc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_memory.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_memory +Description: Abseil memory library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_meta = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_meta.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_meta.pc new file mode 100644 index 0000000..1df1500 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_meta.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_meta +Description: Abseil meta library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_no_destructor.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_no_destructor.pc new file mode 100644 index 0000000..5d10b91 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_no_destructor.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_no_destructor +Description: Abseil no_destructor library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_nullability = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_node_hash_map.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_node_hash_map.pc new file mode 100644 index 0000000..e905c31 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_node_hash_map.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_node_hash_map +Description: Abseil node_hash_map library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_core_headers = 20240722, absl_hash_container_defaults = 20240722, absl_node_slot_policy = 20240722, absl_raw_hash_map = 20240722, absl_algorithm_container = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_node_hash_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_node_hash_set.pc new file mode 100644 index 0000000..14935da --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_node_hash_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_node_hash_set +Description: Abseil node_hash_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_core_headers = 20240722, absl_hash_container_defaults = 20240722, absl_node_slot_policy = 20240722, absl_raw_hash_set = 20240722, absl_algorithm_container = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_node_slot_policy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_node_slot_policy.pc new file mode 100644 index 0000000..6c98350 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_node_slot_policy.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_node_slot_policy +Description: Abseil node_slot_policy library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_non_temporal_arm_intrinsics.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_non_temporal_arm_intrinsics.pc new file mode 100644 index 0000000..9b89e56 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_non_temporal_arm_intrinsics.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_non_temporal_arm_intrinsics +Description: Abseil non_temporal_arm_intrinsics library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_non_temporal_memcpy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_non_temporal_memcpy.pc new file mode 100644 index 0000000..3956670 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_non_temporal_memcpy.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_non_temporal_memcpy +Description: Abseil non_temporal_memcpy library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_non_temporal_arm_intrinsics = 20240722, absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_nullability.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_nullability.pc new file mode 100644 index 0000000..433c157 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_nullability.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_nullability +Description: Abseil nullability library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_numeric.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_numeric.pc new file mode 100644 index 0000000..f149a01 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_numeric.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_numeric +Description: Abseil numeric library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_int128 = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_numeric_representation.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_numeric_representation.pc new file mode 100644 index 0000000..ccb7d9f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_numeric_representation.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_numeric_representation +Description: Abseil numeric_representation library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_optional.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_optional.pc new file mode 100644 index 0000000..60cf6df --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_optional.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_optional +Description: Abseil optional library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_optional_access = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_memory = 20240722, absl_nullability = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_overload.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_overload.pc new file mode 100644 index 0000000..9867307 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_overload.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_overload +Description: Abseil overload library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_meta = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_periodic_sampler.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_periodic_sampler.pc new file mode 100644 index 0000000..d81ca2c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_periodic_sampler.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_periodic_sampler +Description: Abseil periodic_sampler library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_periodic_sampler +Requires: absl_core_headers = 20240722, absl_exponential_biased = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_poison.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_poison.pc new file mode 100644 index 0000000..c2b4025 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_poison.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_poison +Description: Abseil poison library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_poison -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_malloc_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_prefetch.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_prefetch.pc new file mode 100644 index 0000000..bf64ca5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_prefetch.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_prefetch +Description: Abseil prefetch library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_pretty_function.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_pretty_function.pc new file mode 100644 index 0000000..957c2b6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_pretty_function.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_pretty_function +Description: Abseil pretty_function library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_bit_gen_ref.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_bit_gen_ref.pc new file mode 100644 index 0000000..d2eb3ee --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_bit_gen_ref.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_bit_gen_ref +Description: Abseil random_bit_gen_ref library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_core_headers = 20240722, absl_random_internal_distribution_caller = 20240722, absl_random_internal_fast_uniform_bits = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_distributions.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_distributions.pc new file mode 100644 index 0000000..a423024 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_distributions.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_distributions +Description: Abseil random_distributions library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_distributions -ignore:4221 +Requires: absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_random_internal_generate_real = 20240722, absl_random_internal_distribution_caller = 20240722, absl_random_internal_fast_uniform_bits = 20240722, absl_random_internal_fastmath = 20240722, absl_random_internal_iostream_state_saver = 20240722, absl_random_internal_traits = 20240722, absl_random_internal_uniform_helper = 20240722, absl_random_internal_wide_multiply = 20240722, absl_strings = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_distribution_caller.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_distribution_caller.pc new file mode 100644 index 0000000..4d368e9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_distribution_caller.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_distribution_caller +Description: Abseil random_internal_distribution_caller library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_utility = 20240722, absl_fast_type_id = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_distribution_test_util.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_distribution_test_util.pc new file mode 100644 index 0000000..3543c94 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_distribution_test_util.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_distribution_test_util +Description: Abseil random_internal_distribution_test_util library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_distribution_test_util -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_str_format = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_fast_uniform_bits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_fast_uniform_bits.pc new file mode 100644 index 0000000..a2f13dc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_fast_uniform_bits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_fast_uniform_bits +Description: Abseil random_internal_fast_uniform_bits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_fastmath.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_fastmath.pc new file mode 100644 index 0000000..7ebec45 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_fastmath.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_fastmath +Description: Abseil random_internal_fastmath library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_bits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_generate_real.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_generate_real.pc new file mode 100644 index 0000000..c0ec8a6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_generate_real.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_generate_real +Description: Abseil random_internal_generate_real library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_bits = 20240722, absl_random_internal_fastmath = 20240722, absl_random_internal_traits = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_iostream_state_saver.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_iostream_state_saver.pc new file mode 100644 index 0000000..d5db7d0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_iostream_state_saver.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_iostream_state_saver +Description: Abseil random_internal_iostream_state_saver library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_int128 = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_mock_helpers.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_mock_helpers.pc new file mode 100644 index 0000000..6feadc0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_mock_helpers.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_mock_helpers +Description: Abseil random_internal_mock_helpers library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_fast_type_id = 20240722, absl_optional = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_nonsecure_base.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_nonsecure_base.pc new file mode 100644 index 0000000..84f4650 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_nonsecure_base.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_nonsecure_base +Description: Abseil random_internal_nonsecure_base library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_core_headers = 20240722, absl_inlined_vector = 20240722, absl_random_internal_pool_urbg = 20240722, absl_random_internal_salted_seed_seq = 20240722, absl_random_internal_seed_material = 20240722, absl_span = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_pcg_engine.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_pcg_engine.pc new file mode 100644 index 0000000..61a2fd0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_pcg_engine.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_pcg_engine +Description: Abseil random_internal_pcg_engine library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_int128 = 20240722, absl_random_internal_fastmath = 20240722, absl_random_internal_iostream_state_saver = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_platform.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_platform.pc new file mode 100644 index 0000000..c16fa45 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_platform.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_platform +Description: Abseil random_internal_platform library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_platform -ignore:4221 +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_pool_urbg.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_pool_urbg.pc new file mode 100644 index 0000000..2f635b1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_pool_urbg.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_pool_urbg +Description: Abseil random_internal_pool_urbg library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_pool_urbg -ignore:4221 +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_random_internal_randen = 20240722, absl_random_internal_seed_material = 20240722, absl_random_internal_traits = 20240722, absl_random_seed_gen_exception = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen.pc new file mode 100644 index 0000000..5b411e5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen +Description: Abseil random_internal_randen library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen -ignore:4221 +Requires: absl_random_internal_platform = 20240722, absl_random_internal_randen_hwaes = 20240722, absl_random_internal_randen_slow = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen_engine.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen_engine.pc new file mode 100644 index 0000000..ecd93e1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen_engine.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_engine +Description: Abseil random_internal_randen_engine library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_endian = 20240722, absl_random_internal_iostream_state_saver = 20240722, absl_random_internal_randen = 20240722, absl_raw_logging_internal = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen_hwaes.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen_hwaes.pc new file mode 100644 index 0000000..68076b4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen_hwaes.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_hwaes +Description: Abseil random_internal_randen_hwaes library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen_hwaes -ignore:4221 +Requires: absl_random_internal_platform = 20240722, absl_random_internal_randen_hwaes_impl = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen_hwaes_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen_hwaes_impl.pc new file mode 100644 index 0000000..83e1045 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen_hwaes_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_hwaes_impl +Description: Abseil random_internal_randen_hwaes_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen_hwaes_impl -ignore:4221 +Requires: absl_random_internal_platform = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen_slow.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen_slow.pc new file mode 100644 index 0000000..b1fc826 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_randen_slow.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_slow +Description: Abseil random_internal_randen_slow library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen_slow -ignore:4221 +Requires: absl_random_internal_platform = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_salted_seed_seq.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_salted_seed_seq.pc new file mode 100644 index 0000000..7901c56 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_salted_seed_seq.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_salted_seed_seq +Description: Abseil random_internal_salted_seed_seq library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_inlined_vector = 20240722, absl_optional = 20240722, absl_span = 20240722, absl_random_internal_seed_material = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_seed_material.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_seed_material.pc new file mode 100644 index 0000000..ff5f243 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_seed_material.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_seed_material +Description: Abseil random_internal_seed_material library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_seed_material -ignore:4221 +Requires: absl_core_headers = 20240722, absl_optional = 20240722, absl_random_internal_fast_uniform_bits = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_traits.pc new file mode 100644 index 0000000..ab213f9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_traits +Description: Abseil random_internal_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_uniform_helper.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_uniform_helper.pc new file mode 100644 index 0000000..3f1cb31 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_uniform_helper.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_uniform_helper +Description: Abseil random_internal_uniform_helper library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_config = 20240722, absl_random_internal_traits = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_wide_multiply.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_wide_multiply.pc new file mode 100644 index 0000000..db93123 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_internal_wide_multiply.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_wide_multiply +Description: Abseil random_internal_wide_multiply library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_bits = 20240722, absl_config = 20240722, absl_int128 = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_random.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_random.pc new file mode 100644 index 0000000..03bf533 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_random.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_random +Description: Abseil random_random library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_random_distributions = 20240722, absl_random_internal_nonsecure_base = 20240722, absl_random_internal_pcg_engine = 20240722, absl_random_internal_pool_urbg = 20240722, absl_random_internal_randen_engine = 20240722, absl_random_seed_sequences = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_seed_gen_exception.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_seed_gen_exception.pc new file mode 100644 index 0000000..d3a5f42 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_seed_gen_exception.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_seed_gen_exception +Description: Abseil random_seed_gen_exception library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_seed_gen_exception -ignore:4221 +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_seed_sequences.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_seed_sequences.pc new file mode 100644 index 0000000..907bcc7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_random_seed_sequences.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_seed_sequences +Description: Abseil random_seed_sequences library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_seed_sequences -ignore:4221 +Requires: absl_config = 20240722, absl_inlined_vector = 20240722, absl_nullability = 20240722, absl_random_internal_pool_urbg = 20240722, absl_random_internal_salted_seed_seq = 20240722, absl_random_internal_seed_material = 20240722, absl_random_seed_gen_exception = 20240722, absl_span = 20240722, absl_string_view = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_raw_hash_map.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_raw_hash_map.pc new file mode 100644 index 0000000..074a446 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_raw_hash_map.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_raw_hash_map +Description: Abseil raw_hash_map library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_container_memory = 20240722, absl_core_headers = 20240722, absl_raw_hash_set = 20240722, absl_throw_delegate = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_raw_hash_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_raw_hash_set.pc new file mode 100644 index 0000000..8d5fe86 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_raw_hash_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_raw_hash_set +Description: Abseil raw_hash_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_raw_hash_set +Requires: absl_bits = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_container_common = 20240722, absl_container_memory = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_endian = 20240722, absl_hash = 20240722, absl_hash_policy_traits = 20240722, absl_hashtable_debug_hooks = 20240722, absl_hashtablez_sampler = 20240722, absl_memory = 20240722, absl_meta = 20240722, absl_optional = 20240722, absl_prefetch = 20240722, absl_raw_logging_internal = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_raw_logging_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_raw_logging_internal.pc new file mode 100644 index 0000000..e680b1f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_raw_logging_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_raw_logging_internal +Description: Abseil raw_logging_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_raw_logging_internal +Requires: absl_atomic_hook = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722, absl_log_severity = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_sample_recorder.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_sample_recorder.pc new file mode 100644 index 0000000..4039e59 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_sample_recorder.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_sample_recorder +Description: Abseil sample_recorder library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_scoped_set_env.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_scoped_set_env.pc new file mode 100644 index 0000000..0fefd64 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_scoped_set_env.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_scoped_set_env +Description: Abseil scoped_set_env library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_scoped_set_env +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_span.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_span.pc new file mode 100644 index 0000000..30e3e5d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_span.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_span +Description: Abseil span library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_algorithm = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_spinlock_wait.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_spinlock_wait.pc new file mode 100644 index 0000000..f1b2664 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_spinlock_wait.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_spinlock_wait +Description: Abseil spinlock_wait library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_spinlock_wait +Requires: absl_base_internal = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_stacktrace.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_stacktrace.pc new file mode 100644 index 0000000..1906478 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_stacktrace.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_stacktrace +Description: Abseil stacktrace library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_stacktrace +Requires: absl_debugging_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_status.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_status.pc new file mode 100644 index 0000000..a5b4cdb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_status.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_status +Description: Abseil status library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_status +Requires: absl_atomic_hook = 20240722, absl_config = 20240722, absl_cord = 20240722, absl_core_headers = 20240722, absl_function_ref = 20240722, absl_inlined_vector = 20240722, absl_memory = 20240722, absl_no_destructor = 20240722, absl_nullability = 20240722, absl_optional = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722, absl_stacktrace = 20240722, absl_strerror = 20240722, absl_str_format = 20240722, absl_strings = 20240722, absl_symbolize = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_statusor.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_statusor.pc new file mode 100644 index 0000000..249f801 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_statusor.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_statusor +Description: Abseil statusor library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_statusor +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_has_ostream_operator = 20240722, absl_nullability = 20240722, absl_raw_logging_internal = 20240722, absl_status = 20240722, absl_str_format = 20240722, absl_strings = 20240722, absl_type_traits = 20240722, absl_utility = 20240722, absl_variant = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_str_format.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_str_format.pc new file mode 100644 index 0000000..a96ec28 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_str_format.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_str_format +Description: Abseil str_format library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722, absl_span = 20240722, absl_str_format_internal = 20240722, absl_string_view = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_str_format_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_str_format_internal.pc new file mode 100644 index 0000000..ab681ac --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_str_format_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_str_format_internal +Description: Abseil str_format_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_str_format_internal +Requires: absl_bits = 20240722, absl_strings = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_fixed_array = 20240722, absl_inlined_vector = 20240722, absl_numeric_representation = 20240722, absl_type_traits = 20240722, absl_utility = 20240722, absl_int128 = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_strerror.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_strerror.pc new file mode 100644 index 0000000..ca59f5a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_strerror.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_strerror +Description: Abseil strerror library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_strerror -ignore:4221 +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_string_view.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_string_view.pc new file mode 100644 index 0000000..b7a3680 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_string_view.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_string_view +Description: Abseil string_view library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_string_view +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722, absl_throw_delegate = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_strings.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_strings.pc new file mode 100644 index 0000000..ee0ba93 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_strings.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_strings +Description: Abseil strings library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_strings +Requires: absl_string_view = 20240722, absl_strings_internal = 20240722, absl_base = 20240722, absl_bits = 20240722, absl_charset = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_int128 = 20240722, absl_memory = 20240722, absl_nullability = 20240722, absl_raw_logging_internal = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_strings_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_strings_internal.pc new file mode 100644 index 0000000..7818030 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_strings_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_strings_internal +Description: Abseil strings_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_strings_internal +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_raw_logging_internal = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_symbolize.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_symbolize.pc new file mode 100644 index 0000000..4ff1ebf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_symbolize.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_symbolize +Description: Abseil symbolize library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_symbolize -ignore:4221 +Requires: absl_debugging_internal = 20240722, absl_demangle_internal = 20240722, absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_malloc_internal = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_synchronization.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_synchronization.pc new file mode 100644 index 0000000..c02a969 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_synchronization.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_synchronization +Description: Abseil synchronization library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_synchronization +Requires: absl_graphcycles_internal = 20240722, absl_kernel_timeout_internal = 20240722, absl_atomic_hook = 20240722, absl_base = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_malloc_internal = 20240722, absl_raw_logging_internal = 20240722, absl_stacktrace = 20240722, absl_symbolize = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_throw_delegate.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_throw_delegate.pc new file mode 100644 index 0000000..a1dd15c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_throw_delegate.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_throw_delegate +Description: Abseil throw_delegate library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_throw_delegate +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_time.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_time.pc new file mode 100644 index 0000000..e5ea140 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_time.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_time +Description: Abseil time library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_time +Requires: absl_base = 20240722, absl_civil_time = 20240722, absl_core_headers = 20240722, absl_int128 = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_time_zone = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_time_zone.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_time_zone.pc new file mode 100644 index 0000000..0d7c72b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_time_zone.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_time_zone +Description: Abseil time_zone library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_time_zone +Requires: +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_type_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_type_traits.pc new file mode 100644 index 0000000..e4f02cb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_type_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_type_traits +Description: Abseil type_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_utf8_for_code_point.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_utf8_for_code_point.pc new file mode 100644 index 0000000..847cb44 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_utf8_for_code_point.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_utf8_for_code_point +Description: Abseil utf8_for_code_point library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_utf8_for_code_point +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_utility.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_utility.pc new file mode 100644 index 0000000..0a067a0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_utility.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_utility +Description: Abseil utility library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_config = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_variant.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_variant.pc new file mode 100644 index 0000000..2e02dcb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_variant.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_variant +Description: Abseil variant library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_variant_access = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_vlog_config_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_vlog_config_internal.pc new file mode 100644 index 0000000..8b2b785 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_vlog_config_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_vlog_config_internal +Description: Abseil vlog_config_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_vlog_config_internal -ignore:4221 +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_fnmatch = 20240722, absl_memory = 20240722, absl_no_destructor = 20240722, absl_strings = 20240722, absl_synchronization = 20240722, absl_optional = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_vlog_is_on.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_vlog_is_on.pc new file mode 100644 index 0000000..34449f5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/absl_vlog_is_on.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_vlog_is_on +Description: Abseil vlog_is_on library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -ignore:4221 +Requires: absl_absl_vlog_is_on = 20240722 +Cflags: "-I${includedir}" /W3 /bigobj /wd4005 /wd4068 /wd4180 /wd4244 /wd4267 /wd4503 /wd4800 /DNOMINMAX /DWIN32_LEAN_AND_MEAN /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS /D_ENABLE_EXTENDED_ALIGNED_STORAGE diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/draco.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/draco.pc new file mode 100644 index 0000000..a5120c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/draco.pc @@ -0,0 +1,7 @@ +prefix=${pcfiledir}/../.. +Name: draco +Description: Draco geometry de(com)pression library. +Version: 1.5.7 + +Libs: "-L${prefix}/lib" -ldraco +Cflags: "-I${prefix}/include" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/fmt.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/fmt.pc new file mode 100644 index 0000000..9650070 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/fmt.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: fmt +Description: A modern formatting library +Version: 11.0.2 + + +Libs: "-L${libdir}" -lfmt +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libjpeg.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libjpeg.pc new file mode 100644 index 0000000..bef720f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libjpeg.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: libjpeg +Description: A SIMD-accelerated JPEG codec that provides the libjpeg API +Version: 3.0.4 + +Libs: "-L${libdir}" -ljpeg +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libsharpyuv.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libsharpyuv.pc new file mode 100644 index 0000000..d54fcc7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libsharpyuv.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/webp + +Name: libsharpyuv +Description: Library for sharp RGB to YUV conversion +Version: 1.4.0 + +Libs: "-L${libdir}" -llibsharpyuv +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libturbojpeg.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libturbojpeg.pc new file mode 100644 index 0000000..eeee26d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libturbojpeg.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: libturbojpeg +Description: A SIMD-accelerated JPEG codec that provides the TurboJPEG API +Version: 3.0.4 + +Libs: "-L${libdir}" -lturbojpeg +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libwebp.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libwebp.pc new file mode 100644 index 0000000..184ef04 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libwebp.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebp +Description: Library for the WebP graphics format +Version: 1.4.0 + +Libs: "-L${libdir}" -llibwebp +Requires: libsharpyuv +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libwebpdecoder.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libwebpdecoder.pc new file mode 100644 index 0000000..7e3b1d1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libwebpdecoder.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebpdecoder +Description: Library for the WebP graphics format (decode only) +Version: 1.4.0 + +Libs: "-L${libdir}" -llibwebpdecoder +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libwebpdemux.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libwebpdemux.pc new file mode 100644 index 0000000..411dd08 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libwebpdemux.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebpdemux +Description: Library for parsing the WebP graphics format container +Version: 1.4.0 + +Libs: "-L${libdir}" -llibwebpdemux +Requires: libwebp >= 0.2.0 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libwebpmux.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libwebpmux.pc new file mode 100644 index 0000000..a56d19c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libwebpmux.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebpmux +Description: Library for manipulating the WebP graphics format container +Version: 1.4.0 + +Libs: "-L${libdir}" -llibwebpmux +Requires: libwebp >= 0.2.0 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libzstd.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libzstd.pc new file mode 100644 index 0000000..6e08863 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/libzstd.pc @@ -0,0 +1,16 @@ +prefix=${pcfiledir}/../.. +# ZSTD - standard compression algorithm +# Copyright (c) Meta Platforms, Inc. and affiliates. +# BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +Name: zstd +Description: fast lossless compression algorithm library +URL: https://facebook.github.io/zstd/ +Version: 1.5.6 + +Libs: "-L${libdir}" -lzstd +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/spdlog.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/spdlog.pc new file mode 100644 index 0000000..3b2aab0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/spdlog.pc @@ -0,0 +1,14 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +Name: libspdlog +Description: Fast C++ logging library. +URL: https://github.com/gabime/spdlog +Version: 1.15.0 +CFlags: "-I${includedir}" -DSPDLOG_COMPILED_LIB -DSPDLOG_FMT_EXTERNAL + + +Libs: "-L${libdir}" -lspdlog -pthread +Requires: fmt diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/sqlite3.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/sqlite3.pc new file mode 100644 index 0000000..c8725e0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/sqlite3.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: SQLite +Description: SQL database engine +Version: 3.45.0 + +Libs: "-L${libdir}" -lsqlite3 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/tidy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/tidy.pc new file mode 100644 index 0000000..ada5363 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/tidy.pc @@ -0,0 +1,11 @@ +prefix=D:/a/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty +exec_prefix=${prefix} +libdir=${exec_prefix}/D:/a/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty/lib/Windows-AMD64-$,Debug,Release> +includedir=${prefix}/include + +Name: tidy +Description: tidy - HTML syntax checker +URL: https://www.html-tidy.org +Version: 5.9.14 +Libs: -L${libdir} -ltidy +Cflags: -I${includedir} diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/tinyxml2.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/tinyxml2.pc new file mode 100644 index 0000000..24bbedf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/tinyxml2.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: TinyXML2 +Description: simple, small, C++ XML parser +Version: 10.0.0 + +Libs: "-L${libdir}" -ltinyxml2 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/zlib-ng.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/zlib-ng.pc new file mode 100644 index 0000000..9a4a354 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-AMD64-Release/pkgconfig/zlib-ng.pc @@ -0,0 +1,15 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +symbol_prefix= +libdir=${exec_prefix}/lib +sharedlibdir=${libdir} +includedir=${prefix}/include + +Name: zlib-ng +Description: zlib-ng compression library +Version: 2.1.6 + + +Libs: "-L${libdir}" "-L${sharedlibdir}" -lz-ng +Requires: +Cflags: "-I${includedir}" -DWITH_GZFILEOP diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/cmake/zlib-ng/zlib-ng-release.cmake b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/cmake/zlib-ng/zlib-ng-release.cmake new file mode 100644 index 0000000..4c7457e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/cmake/zlib-ng/zlib-ng-release.cmake @@ -0,0 +1,19 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "zlib-ng::zlib" for configuration "Release" +set_property(TARGET zlib-ng::zlib APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(zlib-ng::zlib PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libz-ng.a" + ) + +list(APPEND _cmake_import_check_targets zlib-ng::zlib ) +list(APPEND _cmake_import_check_files_for_zlib-ng::zlib "${_IMPORT_PREFIX}/lib/libz-ng.a" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/cmake/zlib-ng/zlib-ng.cmake b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/cmake/zlib-ng/zlib-ng.cmake new file mode 100644 index 0000000..034b039 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/cmake/zlib-ng/zlib-ng.cmake @@ -0,0 +1,107 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.3") + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.3...3.29) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS zlib-ng::zlib) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target zlib-ng::zlib +add_library(zlib-ng::zlib STATIC IMPORTED) + +set_target_properties(zlib-ng::zlib PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "ZLIBNG_NATIVE_API" + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" +) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/zlib-ng-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + if(CMAKE_VERSION VERSION_LESS "3.28" + OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} + OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + endif() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/RapidJSON.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/RapidJSON.pc new file mode 100644 index 0000000..70a293c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/RapidJSON.pc @@ -0,0 +1,9 @@ +prefix=${pcfiledir}/../.. +includedir=${prefix}/include + +Name: RapidJSON +Description: A fast JSON parser/generator for C++ with both SAX/DOM style API +Version: 1.1.0 +URL: https://github.com/Tencent/rapidjson + +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_absl_check.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_absl_check.pc new file mode 100644 index 0000000..2a3f96a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_absl_check.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_absl_check +Description: Abseil absl_check library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_check_impl = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_absl_log.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_absl_log.pc new file mode 100644 index 0000000..cd4d88d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_absl_log.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_absl_log +Description: Abseil absl_log library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_log_impl = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_absl_vlog_is_on.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_absl_vlog_is_on.pc new file mode 100644 index 0000000..fcfb211 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_absl_vlog_is_on.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_absl_vlog_is_on +Description: Abseil absl_vlog_is_on library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_vlog_config_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_algorithm.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_algorithm.pc new file mode 100644 index 0000000..2699e89 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_algorithm.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_algorithm +Description: Abseil algorithm library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_algorithm_container.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_algorithm_container.pc new file mode 100644 index 0000000..1ef0909 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_algorithm_container.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_algorithm_container +Description: Abseil algorithm_container library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_algorithm = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_meta = 20240722, absl_nullability = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_any.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_any.pc new file mode 100644 index 0000000..69034ca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_any.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_any +Description: Abseil any library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_any_cast = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_fast_type_id = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_any_invocable.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_any_invocable.pc new file mode 100644 index 0000000..5a8c0d5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_any_invocable.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_any_invocable +Description: Abseil any_invocable library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_atomic_hook.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_atomic_hook.pc new file mode 100644 index 0000000..617f0f5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_atomic_hook.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_atomic_hook +Description: Abseil atomic_hook library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bad_any_cast.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bad_any_cast.pc new file mode 100644 index 0000000..3b5b029 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bad_any_cast.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_any_cast +Description: Abseil bad_any_cast library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_any_cast_impl = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bad_any_cast_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bad_any_cast_impl.pc new file mode 100644 index 0000000..ea27e16 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bad_any_cast_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_any_cast_impl +Description: Abseil bad_any_cast_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_bad_any_cast_impl +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bad_optional_access.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bad_optional_access.pc new file mode 100644 index 0000000..4659ea9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bad_optional_access.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_optional_access +Description: Abseil bad_optional_access library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_bad_optional_access +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bad_variant_access.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bad_variant_access.pc new file mode 100644 index 0000000..787f27e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bad_variant_access.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bad_variant_access +Description: Abseil bad_variant_access library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_bad_variant_access +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_base.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_base.pc new file mode 100644 index 0000000..1e6062c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_base.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_base +Description: Abseil base library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_base +Requires: absl_atomic_hook = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_log_severity = 20240722, absl_nullability = 20240722, absl_raw_logging_internal = 20240722, absl_spinlock_wait = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_base_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_base_internal.pc new file mode 100644 index 0000000..0d5e854 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_base_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_base_internal +Description: Abseil base_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bind_front.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bind_front.pc new file mode 100644 index 0000000..43ba4f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bind_front.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bind_front +Description: Abseil bind_front library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_compressed_tuple = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bits.pc new file mode 100644 index 0000000..85ab7f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bits +Description: Abseil bits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bounded_utf8_length_sequence.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bounded_utf8_length_sequence.pc new file mode 100644 index 0000000..fe4d6b4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_bounded_utf8_length_sequence.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_bounded_utf8_length_sequence +Description: Abseil bounded_utf8_length_sequence library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_btree.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_btree.pc new file mode 100644 index 0000000..2fffd58 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_btree.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_btree +Description: Abseil btree library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_common_policy_traits = 20240722, absl_compare = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_container_common = 20240722, absl_container_memory = 20240722, absl_cord = 20240722, absl_core_headers = 20240722, absl_layout = 20240722, absl_memory = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_charset.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_charset.pc new file mode 100644 index 0000000..18ecd6b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_charset.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_charset +Description: Abseil charset library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_string_view = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_check.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_check.pc new file mode 100644 index 0000000..e39177d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_check.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_check +Description: Abseil check library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_check_impl = 20240722, absl_core_headers = 20240722, absl_log_internal_check_op = 20240722, absl_log_internal_conditions = 20240722, absl_log_internal_message = 20240722, absl_log_internal_strip = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_city.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_city.pc new file mode 100644 index 0000000..a4f43bf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_city.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_city +Description: Abseil city library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_city +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_civil_time.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_civil_time.pc new file mode 100644 index 0000000..a660426 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_civil_time.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_civil_time +Description: Abseil civil_time library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_civil_time +Requires: +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cleanup.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cleanup.pc new file mode 100644 index 0000000..958bbe6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cleanup.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cleanup +Description: Abseil cleanup library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_cleanup_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cleanup_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cleanup_internal.pc new file mode 100644 index 0000000..738d222 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cleanup_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cleanup_internal +Description: Abseil cleanup_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_core_headers = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_common_policy_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_common_policy_traits.pc new file mode 100644 index 0000000..ea0451a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_common_policy_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_common_policy_traits +Description: Abseil common_policy_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_compare.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_compare.pc new file mode 100644 index 0000000..75426b5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_compare.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_compare +Description: Abseil compare library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_compressed_tuple.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_compressed_tuple.pc new file mode 100644 index 0000000..70079e6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_compressed_tuple.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_compressed_tuple +Description: Abseil compressed_tuple library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_config.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_config.pc new file mode 100644 index 0000000..d439766 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_config.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_config +Description: Abseil config library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_container_common.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_container_common.pc new file mode 100644 index 0000000..87783eb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_container_common.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_container_common +Description: Abseil container_common library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_container_memory.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_container_memory.pc new file mode 100644 index 0000000..b14fd4e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_container_memory.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_container_memory +Description: Abseil container_memory library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_memory = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cord.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cord.pc new file mode 100644 index 0000000..9ba4365 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cord.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cord +Description: Abseil cord library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cord +Requires: absl_base = 20240722, absl_config = 20240722, absl_cord_internal = 20240722, absl_cordz_functions = 20240722, absl_cordz_info = 20240722, absl_cordz_update_scope = 20240722, absl_cordz_update_tracker = 20240722, absl_core_headers = 20240722, absl_crc32c = 20240722, absl_crc_cord_state = 20240722, absl_endian = 20240722, absl_function_ref = 20240722, absl_inlined_vector = 20240722, absl_nullability = 20240722, absl_optional = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722, absl_strings = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cord_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cord_internal.pc new file mode 100644 index 0000000..4c68ba2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cord_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cord_internal +Description: Abseil cord_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cord_internal +Requires: absl_base_internal = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_container_memory = 20240722, absl_compare = 20240722, absl_core_headers = 20240722, absl_crc_cord_state = 20240722, absl_endian = 20240722, absl_inlined_vector = 20240722, absl_layout = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_functions.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_functions.pc new file mode 100644 index 0000000..8fa4c86 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_functions.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_functions +Description: Abseil cordz_functions library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_functions +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_exponential_biased = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_handle.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_handle.pc new file mode 100644 index 0000000..3a0cee3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_handle.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_handle +Description: Abseil cordz_handle library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_handle +Requires: absl_base = 20240722, absl_config = 20240722, absl_no_destructor = 20240722, absl_raw_logging_internal = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_info.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_info.pc new file mode 100644 index 0000000..765e2b6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_info.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_info +Description: Abseil cordz_info library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_info +Requires: absl_base = 20240722, absl_config = 20240722, absl_cord_internal = 20240722, absl_cordz_functions = 20240722, absl_cordz_handle = 20240722, absl_cordz_statistics = 20240722, absl_cordz_update_tracker = 20240722, absl_core_headers = 20240722, absl_inlined_vector = 20240722, absl_span = 20240722, absl_raw_logging_internal = 20240722, absl_stacktrace = 20240722, absl_synchronization = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_sample_token.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_sample_token.pc new file mode 100644 index 0000000..9fc4e9d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_sample_token.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_sample_token +Description: Abseil cordz_sample_token library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_cordz_sample_token +Requires: absl_config = 20240722, absl_cordz_handle = 20240722, absl_cordz_info = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_statistics.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_statistics.pc new file mode 100644 index 0000000..30a9e87 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_statistics.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_statistics +Description: Abseil cordz_statistics library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_cordz_update_tracker = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_update_scope.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_update_scope.pc new file mode 100644 index 0000000..d999f44 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_update_scope.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_update_scope +Description: Abseil cordz_update_scope library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_cord_internal = 20240722, absl_cordz_info = 20240722, absl_cordz_update_tracker = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_update_tracker.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_update_tracker.pc new file mode 100644 index 0000000..9884960 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_cordz_update_tracker.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_cordz_update_tracker +Description: Abseil cordz_update_tracker library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_core_headers.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_core_headers.pc new file mode 100644 index 0000000..9650f37 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_core_headers.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_core_headers +Description: Abseil core_headers library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_crc32c.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_crc32c.pc new file mode 100644 index 0000000..69b6592 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_crc32c.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc32c +Description: Abseil crc32c library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc32c +Requires: absl_crc_cpu_detect = 20240722, absl_crc_internal = 20240722, absl_non_temporal_memcpy = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_prefetch = 20240722, absl_str_format = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_crc_cord_state.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_crc_cord_state.pc new file mode 100644 index 0000000..8ea2b59 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_crc_cord_state.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc_cord_state +Description: Abseil crc_cord_state library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc_cord_state +Requires: absl_crc32c = 20240722, absl_config = 20240722, absl_strings = 20240722, absl_no_destructor = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_crc_cpu_detect.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_crc_cpu_detect.pc new file mode 100644 index 0000000..04dfb78 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_crc_cpu_detect.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc_cpu_detect +Description: Abseil crc_cpu_detect library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc_cpu_detect +Requires: absl_base = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_crc_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_crc_internal.pc new file mode 100644 index 0000000..e13a8f6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_crc_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_crc_internal +Description: Abseil crc_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_crc_internal +Requires: absl_crc_cpu_detect = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_prefetch = 20240722, absl_raw_logging_internal = 20240722, absl_memory = 20240722, absl_bits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_debugging.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_debugging.pc new file mode 100644 index 0000000..62304ae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_debugging.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_debugging +Description: Abseil debugging library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_stacktrace = 20240722, absl_leak_check = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_debugging_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_debugging_internal.pc new file mode 100644 index 0000000..1ca2457 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_debugging_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_debugging_internal +Description: Abseil debugging_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_debugging_internal +Requires: absl_core_headers = 20240722, absl_config = 20240722, absl_dynamic_annotations = 20240722, absl_errno_saver = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_decode_rust_punycode.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_decode_rust_punycode.pc new file mode 100644 index 0000000..ae5d976 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_decode_rust_punycode.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_decode_rust_punycode +Description: Abseil decode_rust_punycode library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_decode_rust_punycode +Requires: absl_bounded_utf8_length_sequence = 20240722, absl_config = 20240722, absl_nullability = 20240722, absl_utf8_for_code_point = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_demangle_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_demangle_internal.pc new file mode 100644 index 0000000..0ec9fa6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_demangle_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_demangle_internal +Description: Abseil demangle_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_demangle_internal +Requires: absl_config = 20240722, absl_demangle_rust = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_demangle_rust.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_demangle_rust.pc new file mode 100644 index 0000000..51ce133 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_demangle_rust.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_demangle_rust +Description: Abseil demangle_rust library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_demangle_rust +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_decode_rust_punycode = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_die_if_null.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_die_if_null.pc new file mode 100644 index 0000000..acf5b4d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_die_if_null.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_die_if_null +Description: Abseil die_if_null library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_die_if_null +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_dynamic_annotations.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_dynamic_annotations.pc new file mode 100644 index 0000000..f7f3815 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_dynamic_annotations.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_dynamic_annotations +Description: Abseil dynamic_annotations library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_endian.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_endian.pc new file mode 100644 index 0000000..3d00574 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_endian.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_endian +Description: Abseil endian library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_errno_saver.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_errno_saver.pc new file mode 100644 index 0000000..65c2ffb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_errno_saver.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_errno_saver +Description: Abseil errno_saver library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_examine_stack.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_examine_stack.pc new file mode 100644 index 0000000..9c9a61b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_examine_stack.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_examine_stack +Description: Abseil examine_stack library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_examine_stack +Requires: absl_stacktrace = 20240722, absl_symbolize = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_exponential_biased.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_exponential_biased.pc new file mode 100644 index 0000000..edcf6f7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_exponential_biased.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_exponential_biased +Description: Abseil exponential_biased library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_exponential_biased +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_failure_signal_handler.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_failure_signal_handler.pc new file mode 100644 index 0000000..73b3af7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_failure_signal_handler.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_failure_signal_handler +Description: Abseil failure_signal_handler library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_failure_signal_handler +Requires: absl_examine_stack = 20240722, absl_stacktrace = 20240722, absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_fast_type_id.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_fast_type_id.pc new file mode 100644 index 0000000..00bee9f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_fast_type_id.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_fast_type_id +Description: Abseil fast_type_id library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_fixed_array.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_fixed_array.pc new file mode 100644 index 0000000..bc11248 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_fixed_array.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_fixed_array +Description: Abseil fixed_array library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_compressed_tuple = 20240722, absl_algorithm = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_throw_delegate = 20240722, absl_memory = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags.pc new file mode 100644 index 0000000..2e7aecd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags +Description: Abseil flags library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_config = 20240722, absl_flags_internal = 20240722, absl_flags_reflection = 20240722, absl_core_headers = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_commandlineflag.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_commandlineflag.pc new file mode 100644 index 0000000..5e61657 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_commandlineflag.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_commandlineflag +Description: Abseil flags_commandlineflag library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_commandlineflag +Requires: absl_config = 20240722, absl_fast_type_id = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_optional = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_commandlineflag_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_commandlineflag_internal.pc new file mode 100644 index 0000000..1436671 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_commandlineflag_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_commandlineflag_internal +Description: Abseil flags_commandlineflag_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_commandlineflag_internal +Requires: absl_config = 20240722, absl_dynamic_annotations = 20240722, absl_fast_type_id = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_config.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_config.pc new file mode 100644 index 0000000..90d32aa --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_config.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_config +Description: Abseil flags_config library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_config +Requires: absl_config = 20240722, absl_flags_path_util = 20240722, absl_flags_program_name = 20240722, absl_core_headers = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_internal.pc new file mode 100644 index 0000000..9ac5cde --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_internal +Description: Abseil flags_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_internal +Requires: absl_base = 20240722, absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_flags_config = 20240722, absl_flags_marshalling = 20240722, absl_synchronization = 20240722, absl_meta = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_marshalling.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_marshalling.pc new file mode 100644 index 0000000..86c8076 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_marshalling.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_marshalling +Description: Abseil flags_marshalling library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_marshalling +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_severity = 20240722, absl_int128 = 20240722, absl_optional = 20240722, absl_strings = 20240722, absl_str_format = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_parse.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_parse.pc new file mode 100644 index 0000000..0c399ae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_parse.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_parse +Description: Abseil flags_parse library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_parse +Requires: absl_algorithm_container = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_flags_config = 20240722, absl_flags = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_flags_internal = 20240722, absl_flags_private_handle_accessor = 20240722, absl_flags_program_name = 20240722, absl_flags_reflection = 20240722, absl_flags_usage = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_path_util.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_path_util.pc new file mode 100644 index 0000000..9adbb6c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_path_util.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_path_util +Description: Abseil flags_path_util library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_private_handle_accessor.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_private_handle_accessor.pc new file mode 100644 index 0000000..2a57aab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_private_handle_accessor.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_private_handle_accessor +Description: Abseil flags_private_handle_accessor library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_private_handle_accessor +Requires: absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_commandlineflag_internal = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_program_name.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_program_name.pc new file mode 100644 index 0000000..1b3370c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_program_name.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_program_name +Description: Abseil flags_program_name library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_program_name +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_flags_path_util = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_reflection.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_reflection.pc new file mode 100644 index 0000000..e373dbb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_reflection.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_reflection +Description: Abseil flags_reflection library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_reflection +Requires: absl_config = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_private_handle_accessor = 20240722, absl_flags_config = 20240722, absl_strings = 20240722, absl_synchronization = 20240722, absl_flat_hash_map = 20240722, absl_no_destructor = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_usage.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_usage.pc new file mode 100644 index 0000000..27e5dcf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_usage.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_usage +Description: Abseil flags_usage library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_usage +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_flags_usage_internal = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_usage_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_usage_internal.pc new file mode 100644 index 0000000..e93d28d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flags_usage_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flags_usage_internal +Description: Abseil flags_usage_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_flags_usage_internal +Requires: absl_config = 20240722, absl_flags_config = 20240722, absl_flags = 20240722, absl_flags_commandlineflag = 20240722, absl_flags_internal = 20240722, absl_flags_path_util = 20240722, absl_flags_private_handle_accessor = 20240722, absl_flags_program_name = 20240722, absl_flags_reflection = 20240722, absl_strings = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flat_hash_map.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flat_hash_map.pc new file mode 100644 index 0000000..bab2f5e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flat_hash_map.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flat_hash_map +Description: Abseil flat_hash_map library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_core_headers = 20240722, absl_hash_container_defaults = 20240722, absl_raw_hash_map = 20240722, absl_algorithm_container = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flat_hash_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flat_hash_set.pc new file mode 100644 index 0000000..71c94e2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_flat_hash_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_flat_hash_set +Description: Abseil flat_hash_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_hash_container_defaults = 20240722, absl_raw_hash_set = 20240722, absl_algorithm_container = 20240722, absl_core_headers = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_function_ref.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_function_ref.pc new file mode 100644 index 0000000..c88a5e3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_function_ref.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_function_ref +Description: Abseil function_ref library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_core_headers = 20240722, absl_any_invocable = 20240722, absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_graphcycles_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_graphcycles_internal.pc new file mode 100644 index 0000000..8de827e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_graphcycles_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_graphcycles_internal +Description: Abseil graphcycles_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_graphcycles_internal +Requires: absl_base = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_malloc_internal = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_has_ostream_operator.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_has_ostream_operator.pc new file mode 100644 index 0000000..843c0c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_has_ostream_operator.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_has_ostream_operator +Description: Abseil has_ostream_operator library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hash.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hash.pc new file mode 100644 index 0000000..f80f599 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hash.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash +Description: Abseil hash library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_hash +Requires: absl_bits = 20240722, absl_city = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_fixed_array = 20240722, absl_function_ref = 20240722, absl_meta = 20240722, absl_int128 = 20240722, absl_strings = 20240722, absl_optional = 20240722, absl_variant = 20240722, absl_utility = 20240722, absl_low_level_hash = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hash_container_defaults.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hash_container_defaults.pc new file mode 100644 index 0000000..5e1ded4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hash_container_defaults.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash_container_defaults +Description: Abseil hash_container_defaults library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_hash_function_defaults = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hash_function_defaults.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hash_function_defaults.pc new file mode 100644 index 0000000..04a4e3b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hash_function_defaults.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash_function_defaults +Description: Abseil hash_function_defaults library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_container_common = 20240722, absl_cord = 20240722, absl_hash = 20240722, absl_strings = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hash_policy_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hash_policy_traits.pc new file mode 100644 index 0000000..e25c47c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hash_policy_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hash_policy_traits +Description: Abseil hash_policy_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_common_policy_traits = 20240722, absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hashtable_debug.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hashtable_debug.pc new file mode 100644 index 0000000..5b1ed5f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hashtable_debug.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hashtable_debug +Description: Abseil hashtable_debug library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_hashtable_debug_hooks = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hashtable_debug_hooks.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hashtable_debug_hooks.pc new file mode 100644 index 0000000..9010454 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hashtable_debug_hooks.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hashtable_debug_hooks +Description: Abseil hashtable_debug_hooks library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hashtablez_sampler.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hashtablez_sampler.pc new file mode 100644 index 0000000..2cbd02a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_hashtablez_sampler.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_hashtablez_sampler +Description: Abseil hashtablez_sampler library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_hashtablez_sampler +Requires: absl_base = 20240722, absl_config = 20240722, absl_exponential_biased = 20240722, absl_no_destructor = 20240722, absl_raw_logging_internal = 20240722, absl_sample_recorder = 20240722, absl_synchronization = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_if_constexpr.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_if_constexpr.pc new file mode 100644 index 0000000..815d293 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_if_constexpr.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_if_constexpr +Description: Abseil if_constexpr library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_inlined_vector.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_inlined_vector.pc new file mode 100644 index 0000000..aabfd71 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_inlined_vector.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_inlined_vector +Description: Abseil inlined_vector library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_algorithm = 20240722, absl_core_headers = 20240722, absl_inlined_vector_internal = 20240722, absl_throw_delegate = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_inlined_vector_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_inlined_vector_internal.pc new file mode 100644 index 0000000..79e087c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_inlined_vector_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_inlined_vector_internal +Description: Abseil inlined_vector_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_memory = 20240722, absl_span = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_int128.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_int128.pc new file mode 100644 index 0000000..6f26a5a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_int128.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_int128 +Description: Abseil int128 library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_int128 +Requires: absl_compare = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_bits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_kernel_timeout_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_kernel_timeout_internal.pc new file mode 100644 index 0000000..77ff9b9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_kernel_timeout_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_kernel_timeout_internal +Description: Abseil kernel_timeout_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_kernel_timeout_internal +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_layout.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_layout.pc new file mode 100644 index 0000000..dcea300 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_layout.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_layout +Description: Abseil layout library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_debugging_internal = 20240722, absl_meta = 20240722, absl_strings = 20240722, absl_span = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_leak_check.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_leak_check.pc new file mode 100644 index 0000000..797e863 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_leak_check.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_leak_check +Description: Abseil leak_check library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_leak_check +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log.pc new file mode 100644 index 0000000..0b7065c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log +Description: Abseil log library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_log_impl = 20240722, absl_vlog_is_on = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_entry.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_entry.pc new file mode 100644 index 0000000..de7ff9e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_entry.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_entry +Description: Abseil log_entry library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_entry +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_config = 20240722, absl_log_severity = 20240722, absl_span = 20240722, absl_strings = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_flags.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_flags.pc new file mode 100644 index 0000000..8d8b63a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_flags.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_flags +Description: Abseil log_flags library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_flags +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_globals = 20240722, absl_log_severity = 20240722, absl_log_internal_config = 20240722, absl_log_internal_flags = 20240722, absl_flags = 20240722, absl_flags_marshalling = 20240722, absl_strings = 20240722, absl_vlog_config_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_globals.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_globals.pc new file mode 100644 index 0000000..caaa704 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_globals.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_globals +Description: Abseil log_globals library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_globals +Requires: absl_atomic_hook = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_hash = 20240722, absl_log_severity = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_vlog_config_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_initialize.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_initialize.pc new file mode 100644 index 0000000..ec34a72 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_initialize.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_initialize +Description: Abseil log_initialize library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_initialize +Requires: absl_config = 20240722, absl_log_globals = 20240722, absl_log_internal_globals = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_append_truncated.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_append_truncated.pc new file mode 100644 index 0000000..935856d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_append_truncated.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_append_truncated +Description: Abseil log_internal_append_truncated library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_strings = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_check_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_check_impl.pc new file mode 100644 index 0000000..85896c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_check_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_check_impl +Description: Abseil log_internal_check_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_log_internal_check_op = 20240722, absl_log_internal_conditions = 20240722, absl_log_internal_message = 20240722, absl_log_internal_strip = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_check_op.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_check_op.pc new file mode 100644 index 0000000..53d79b5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_check_op.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_check_op +Description: Abseil log_internal_check_op library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_check_op +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_nullguard = 20240722, absl_log_internal_nullstream = 20240722, absl_log_internal_strip = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_conditions.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_conditions.pc new file mode 100644 index 0000000..daccc6a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_conditions.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_conditions +Description: Abseil log_internal_conditions library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_conditions +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_voidify = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_config.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_config.pc new file mode 100644 index 0000000..5566d96 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_config.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_config +Description: Abseil log_internal_config library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_flags.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_flags.pc new file mode 100644 index 0000000..0fa576a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_flags.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_flags +Description: Abseil log_internal_flags library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_flags = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_fnmatch.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_fnmatch.pc new file mode 100644 index 0000000..b42e687 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_fnmatch.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_fnmatch +Description: Abseil log_internal_fnmatch library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_fnmatch +Requires: absl_config = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_format.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_format.pc new file mode 100644 index 0000000..80c370e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_format.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_format +Description: Abseil log_internal_format library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_format +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_append_truncated = 20240722, absl_log_internal_config = 20240722, absl_log_internal_globals = 20240722, absl_log_severity = 20240722, absl_strings = 20240722, absl_str_format = 20240722, absl_time = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_globals.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_globals.pc new file mode 100644 index 0000000..645100f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_globals.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_globals +Description: Abseil log_internal_globals library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_globals +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_severity = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_log_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_log_impl.pc new file mode 100644 index 0000000..0fd3d7b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_log_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_log_impl +Description: Abseil log_internal_log_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_log_internal_conditions = 20240722, absl_log_internal_message = 20240722, absl_log_internal_strip = 20240722, absl_absl_vlog_is_on = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_log_sink_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_log_sink_set.pc new file mode 100644 index 0000000..584c9db --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_log_sink_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_log_sink_set +Description: Abseil log_internal_log_sink_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_log_sink_set +Requires: absl_base = 20240722, absl_cleanup = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_config = 20240722, absl_log_internal_globals = 20240722, absl_log_globals = 20240722, absl_log_entry = 20240722, absl_log_severity = 20240722, absl_log_sink = 20240722, absl_no_destructor = 20240722, absl_raw_logging_internal = 20240722, absl_synchronization = 20240722, absl_span = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_message.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_message.pc new file mode 100644 index 0000000..189cb4e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_message.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_message +Description: Abseil log_internal_message library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_message +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722, absl_inlined_vector = 20240722, absl_examine_stack = 20240722, absl_log_internal_append_truncated = 20240722, absl_log_internal_format = 20240722, absl_log_internal_globals = 20240722, absl_log_internal_proto = 20240722, absl_log_internal_log_sink_set = 20240722, absl_log_internal_nullguard = 20240722, absl_log_globals = 20240722, absl_log_entry = 20240722, absl_log_severity = 20240722, absl_log_sink = 20240722, absl_log_sink_registry = 20240722, absl_memory = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_strerror = 20240722, absl_time = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_nullguard.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_nullguard.pc new file mode 100644 index 0000000..462b13e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_nullguard.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_nullguard +Description: Abseil log_internal_nullguard library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_nullguard +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_nullstream.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_nullstream.pc new file mode 100644 index 0000000..c4a5d12 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_nullstream.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_nullstream +Description: Abseil log_internal_nullstream library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_log_severity = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_proto.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_proto.pc new file mode 100644 index 0000000..a09bdd9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_proto.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_proto +Description: Abseil log_internal_proto library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_internal_proto +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_strings = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_strip.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_strip.pc new file mode 100644 index 0000000..09b1f90 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_strip.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_strip +Description: Abseil log_internal_strip library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_log_internal_message = 20240722, absl_log_internal_nullstream = 20240722, absl_log_severity = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_structured.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_structured.pc new file mode 100644 index 0000000..166e689 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_structured.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_structured +Description: Abseil log_internal_structured library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_log_internal_message = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_voidify.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_voidify.pc new file mode 100644 index 0000000..081c074 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_internal_voidify.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_internal_voidify +Description: Abseil log_internal_voidify library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_severity.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_severity.pc new file mode 100644 index 0000000..b3aae9c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_severity.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_severity +Description: Abseil log_severity library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_severity +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_sink.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_sink.pc new file mode 100644 index 0000000..a9c5fd3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_sink.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_sink +Description: Abseil log_sink library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_log_sink +Requires: absl_config = 20240722, absl_log_entry = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_sink_registry.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_sink_registry.pc new file mode 100644 index 0000000..fcb7a02 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_sink_registry.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_sink_registry +Description: Abseil log_sink_registry library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_log_sink = 20240722, absl_log_internal_log_sink_set = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_streamer.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_streamer.pc new file mode 100644 index 0000000..1de593e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_streamer.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_streamer +Description: Abseil log_streamer library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_absl_log = 20240722, absl_log_severity = 20240722, absl_optional = 20240722, absl_strings = 20240722, absl_strings_internal = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_structured.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_structured.pc new file mode 100644 index 0000000..491549b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_log_structured.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_log_structured +Description: Abseil log_structured library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_log_internal_structured = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_low_level_hash.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_low_level_hash.pc new file mode 100644 index 0000000..c57f9dd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_low_level_hash.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_low_level_hash +Description: Abseil low_level_hash library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_low_level_hash +Requires: absl_config = 20240722, absl_endian = 20240722, absl_int128 = 20240722, absl_prefetch = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_malloc_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_malloc_internal.pc new file mode 100644 index 0000000..63f5bc9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_malloc_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_malloc_internal +Description: Abseil malloc_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_malloc_internal +Requires: absl_base = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_memory.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_memory.pc new file mode 100644 index 0000000..760c159 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_memory.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_memory +Description: Abseil memory library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_meta.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_meta.pc new file mode 100644 index 0000000..47c6e33 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_meta.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_meta +Description: Abseil meta library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_no_destructor.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_no_destructor.pc new file mode 100644 index 0000000..61b4ced --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_no_destructor.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_no_destructor +Description: Abseil no_destructor library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_nullability = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_node_hash_map.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_node_hash_map.pc new file mode 100644 index 0000000..7290e95 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_node_hash_map.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_node_hash_map +Description: Abseil node_hash_map library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_core_headers = 20240722, absl_hash_container_defaults = 20240722, absl_node_slot_policy = 20240722, absl_raw_hash_map = 20240722, absl_algorithm_container = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_node_hash_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_node_hash_set.pc new file mode 100644 index 0000000..d25eb82 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_node_hash_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_node_hash_set +Description: Abseil node_hash_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_container_memory = 20240722, absl_core_headers = 20240722, absl_hash_container_defaults = 20240722, absl_node_slot_policy = 20240722, absl_raw_hash_set = 20240722, absl_algorithm_container = 20240722, absl_memory = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_node_slot_policy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_node_slot_policy.pc new file mode 100644 index 0000000..a76d24a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_node_slot_policy.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_node_slot_policy +Description: Abseil node_slot_policy library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_non_temporal_arm_intrinsics.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_non_temporal_arm_intrinsics.pc new file mode 100644 index 0000000..8867793 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_non_temporal_arm_intrinsics.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_non_temporal_arm_intrinsics +Description: Abseil non_temporal_arm_intrinsics library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_non_temporal_memcpy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_non_temporal_memcpy.pc new file mode 100644 index 0000000..cead8e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_non_temporal_memcpy.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_non_temporal_memcpy +Description: Abseil non_temporal_memcpy library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_non_temporal_arm_intrinsics = 20240722, absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_nullability.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_nullability.pc new file mode 100644 index 0000000..1ad40e5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_nullability.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_nullability +Description: Abseil nullability library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_numeric.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_numeric.pc new file mode 100644 index 0000000..f2ccd5b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_numeric.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_numeric +Description: Abseil numeric library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_int128 = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_numeric_representation.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_numeric_representation.pc new file mode 100644 index 0000000..bff418a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_numeric_representation.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_numeric_representation +Description: Abseil numeric_representation library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_optional.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_optional.pc new file mode 100644 index 0000000..1137364 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_optional.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_optional +Description: Abseil optional library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_optional_access = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_memory = 20240722, absl_nullability = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_overload.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_overload.pc new file mode 100644 index 0000000..23c8e6d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_overload.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_overload +Description: Abseil overload library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_meta = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_periodic_sampler.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_periodic_sampler.pc new file mode 100644 index 0000000..eac6e1f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_periodic_sampler.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_periodic_sampler +Description: Abseil periodic_sampler library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_periodic_sampler +Requires: absl_core_headers = 20240722, absl_exponential_biased = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_poison.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_poison.pc new file mode 100644 index 0000000..51554cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_poison.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_poison +Description: Abseil poison library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_poison +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_malloc_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_prefetch.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_prefetch.pc new file mode 100644 index 0000000..db2731d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_prefetch.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_prefetch +Description: Abseil prefetch library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_pretty_function.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_pretty_function.pc new file mode 100644 index 0000000..a77d50d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_pretty_function.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_pretty_function +Description: Abseil pretty_function library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_bit_gen_ref.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_bit_gen_ref.pc new file mode 100644 index 0000000..0d833bb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_bit_gen_ref.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_bit_gen_ref +Description: Abseil random_bit_gen_ref library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_random_internal_distribution_caller = 20240722, absl_random_internal_fast_uniform_bits = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_distributions.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_distributions.pc new file mode 100644 index 0000000..720d7b0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_distributions.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_distributions +Description: Abseil random_distributions library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_distributions +Requires: absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_random_internal_generate_real = 20240722, absl_random_internal_distribution_caller = 20240722, absl_random_internal_fast_uniform_bits = 20240722, absl_random_internal_fastmath = 20240722, absl_random_internal_iostream_state_saver = 20240722, absl_random_internal_traits = 20240722, absl_random_internal_uniform_helper = 20240722, absl_random_internal_wide_multiply = 20240722, absl_strings = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_distribution_caller.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_distribution_caller.pc new file mode 100644 index 0000000..66a5375 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_distribution_caller.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_distribution_caller +Description: Abseil random_internal_distribution_caller library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_utility = 20240722, absl_fast_type_id = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_distribution_test_util.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_distribution_test_util.pc new file mode 100644 index 0000000..70fe5c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_distribution_test_util.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_distribution_test_util +Description: Abseil random_internal_distribution_test_util library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_distribution_test_util +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_str_format = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_fast_uniform_bits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_fast_uniform_bits.pc new file mode 100644 index 0000000..e6a97b4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_fast_uniform_bits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_fast_uniform_bits +Description: Abseil random_internal_fast_uniform_bits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_fastmath.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_fastmath.pc new file mode 100644 index 0000000..c7e9a6a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_fastmath.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_fastmath +Description: Abseil random_internal_fastmath library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_generate_real.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_generate_real.pc new file mode 100644 index 0000000..1a9dd95 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_generate_real.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_generate_real +Description: Abseil random_internal_generate_real library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722, absl_random_internal_fastmath = 20240722, absl_random_internal_traits = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_iostream_state_saver.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_iostream_state_saver.pc new file mode 100644 index 0000000..cefa15a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_iostream_state_saver.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_iostream_state_saver +Description: Abseil random_internal_iostream_state_saver library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_int128 = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_mock_helpers.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_mock_helpers.pc new file mode 100644 index 0000000..1868f39 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_mock_helpers.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_mock_helpers +Description: Abseil random_internal_mock_helpers library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_fast_type_id = 20240722, absl_optional = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_nonsecure_base.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_nonsecure_base.pc new file mode 100644 index 0000000..d16f277 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_nonsecure_base.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_nonsecure_base +Description: Abseil random_internal_nonsecure_base library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_core_headers = 20240722, absl_inlined_vector = 20240722, absl_random_internal_pool_urbg = 20240722, absl_random_internal_salted_seed_seq = 20240722, absl_random_internal_seed_material = 20240722, absl_span = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_pcg_engine.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_pcg_engine.pc new file mode 100644 index 0000000..c388c97 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_pcg_engine.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_pcg_engine +Description: Abseil random_internal_pcg_engine library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_int128 = 20240722, absl_random_internal_fastmath = 20240722, absl_random_internal_iostream_state_saver = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_platform.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_platform.pc new file mode 100644 index 0000000..c034993 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_platform.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_platform +Description: Abseil random_internal_platform library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_platform +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_pool_urbg.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_pool_urbg.pc new file mode 100644 index 0000000..8c44151 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_pool_urbg.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_pool_urbg +Description: Abseil random_internal_pool_urbg library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_pool_urbg +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_random_internal_randen = 20240722, absl_random_internal_seed_material = 20240722, absl_random_internal_traits = 20240722, absl_random_seed_gen_exception = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen.pc new file mode 100644 index 0000000..a48ee09 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen +Description: Abseil random_internal_randen library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen +Requires: absl_random_internal_platform = 20240722, absl_random_internal_randen_hwaes = 20240722, absl_random_internal_randen_slow = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen_engine.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen_engine.pc new file mode 100644 index 0000000..7157894 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen_engine.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_engine +Description: Abseil random_internal_randen_engine library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_endian = 20240722, absl_random_internal_iostream_state_saver = 20240722, absl_random_internal_randen = 20240722, absl_raw_logging_internal = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen_hwaes.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen_hwaes.pc new file mode 100644 index 0000000..5b1e80d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen_hwaes.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_hwaes +Description: Abseil random_internal_randen_hwaes library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen_hwaes +Requires: absl_random_internal_platform = 20240722, absl_random_internal_randen_hwaes_impl = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX SHELL:-Xarch_x86_64 -maes SHELL:-Xarch_x86_64 -msse4.1 SHELL:-Xarch_arm64 -march=armv8-a+crypto -Wno-unused-command-line-argument diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen_hwaes_impl.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen_hwaes_impl.pc new file mode 100644 index 0000000..da7f75b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen_hwaes_impl.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_hwaes_impl +Description: Abseil random_internal_randen_hwaes_impl library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen_hwaes_impl +Requires: absl_random_internal_platform = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX SHELL:-Xarch_x86_64 -maes SHELL:-Xarch_x86_64 -msse4.1 SHELL:-Xarch_arm64 -march=armv8-a+crypto -Wno-unused-command-line-argument diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen_slow.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen_slow.pc new file mode 100644 index 0000000..feb3902 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_randen_slow.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_randen_slow +Description: Abseil random_internal_randen_slow library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_randen_slow +Requires: absl_random_internal_platform = 20240722, absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_salted_seed_seq.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_salted_seed_seq.pc new file mode 100644 index 0000000..94e4378 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_salted_seed_seq.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_salted_seed_seq +Description: Abseil random_internal_salted_seed_seq library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_inlined_vector = 20240722, absl_optional = 20240722, absl_span = 20240722, absl_random_internal_seed_material = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_seed_material.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_seed_material.pc new file mode 100644 index 0000000..644704d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_seed_material.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_seed_material +Description: Abseil random_internal_seed_material library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_internal_seed_material +Requires: absl_core_headers = 20240722, absl_optional = 20240722, absl_random_internal_fast_uniform_bits = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_traits.pc new file mode 100644 index 0000000..a33e4ea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_traits +Description: Abseil random_internal_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_uniform_helper.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_uniform_helper.pc new file mode 100644 index 0000000..0e7f376 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_uniform_helper.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_uniform_helper +Description: Abseil random_internal_uniform_helper library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_random_internal_traits = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_wide_multiply.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_wide_multiply.pc new file mode 100644 index 0000000..988ee11 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_internal_wide_multiply.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_internal_wide_multiply +Description: Abseil random_internal_wide_multiply library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bits = 20240722, absl_config = 20240722, absl_int128 = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_random.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_random.pc new file mode 100644 index 0000000..5bfb93d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_random.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_random +Description: Abseil random_random library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_random_distributions = 20240722, absl_random_internal_nonsecure_base = 20240722, absl_random_internal_pcg_engine = 20240722, absl_random_internal_pool_urbg = 20240722, absl_random_internal_randen_engine = 20240722, absl_random_seed_sequences = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_seed_gen_exception.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_seed_gen_exception.pc new file mode 100644 index 0000000..6c78196 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_seed_gen_exception.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_seed_gen_exception +Description: Abseil random_seed_gen_exception library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_seed_gen_exception +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_seed_sequences.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_seed_sequences.pc new file mode 100644 index 0000000..1998470 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_random_seed_sequences.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_random_seed_sequences +Description: Abseil random_seed_sequences library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_random_seed_sequences +Requires: absl_config = 20240722, absl_inlined_vector = 20240722, absl_nullability = 20240722, absl_random_internal_pool_urbg = 20240722, absl_random_internal_salted_seed_seq = 20240722, absl_random_internal_seed_material = 20240722, absl_random_seed_gen_exception = 20240722, absl_span = 20240722, absl_string_view = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_raw_hash_map.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_raw_hash_map.pc new file mode 100644 index 0000000..77f1e3f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_raw_hash_map.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_raw_hash_map +Description: Abseil raw_hash_map library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_container_memory = 20240722, absl_core_headers = 20240722, absl_raw_hash_set = 20240722, absl_throw_delegate = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_raw_hash_set.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_raw_hash_set.pc new file mode 100644 index 0000000..ed4f83c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_raw_hash_set.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_raw_hash_set +Description: Abseil raw_hash_set library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_raw_hash_set +Requires: absl_bits = 20240722, absl_compressed_tuple = 20240722, absl_config = 20240722, absl_container_common = 20240722, absl_container_memory = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_endian = 20240722, absl_hash = 20240722, absl_hash_policy_traits = 20240722, absl_hashtable_debug_hooks = 20240722, absl_hashtablez_sampler = 20240722, absl_memory = 20240722, absl_meta = 20240722, absl_optional = 20240722, absl_prefetch = 20240722, absl_raw_logging_internal = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_raw_logging_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_raw_logging_internal.pc new file mode 100644 index 0000000..a120546 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_raw_logging_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_raw_logging_internal +Description: Abseil raw_logging_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_raw_logging_internal +Requires: absl_atomic_hook = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722, absl_log_severity = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_sample_recorder.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_sample_recorder.pc new file mode 100644 index 0000000..3025734 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_sample_recorder.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_sample_recorder +Description: Abseil sample_recorder library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base = 20240722, absl_synchronization = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_scoped_set_env.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_scoped_set_env.pc new file mode 100644 index 0000000..5799969 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_scoped_set_env.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_scoped_set_env +Description: Abseil scoped_set_env library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_scoped_set_env +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_span.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_span.pc new file mode 100644 index 0000000..654b8d0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_span.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_span +Description: Abseil span library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_algorithm = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_spinlock_wait.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_spinlock_wait.pc new file mode 100644 index 0000000..3f3d495 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_spinlock_wait.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_spinlock_wait +Description: Abseil spinlock_wait library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_spinlock_wait +Requires: absl_base_internal = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_stacktrace.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_stacktrace.pc new file mode 100644 index 0000000..9375890 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_stacktrace.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_stacktrace +Description: Abseil stacktrace library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_stacktrace +Requires: absl_debugging_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_status.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_status.pc new file mode 100644 index 0000000..5a32ee5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_status.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_status +Description: Abseil status library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_status +Requires: absl_atomic_hook = 20240722, absl_config = 20240722, absl_cord = 20240722, absl_core_headers = 20240722, absl_function_ref = 20240722, absl_inlined_vector = 20240722, absl_memory = 20240722, absl_no_destructor = 20240722, absl_nullability = 20240722, absl_optional = 20240722, absl_raw_logging_internal = 20240722, absl_span = 20240722, absl_stacktrace = 20240722, absl_strerror = 20240722, absl_str_format = 20240722, absl_strings = 20240722, absl_symbolize = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_statusor.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_statusor.pc new file mode 100644 index 0000000..e70bd45 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_statusor.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_statusor +Description: Abseil statusor library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_statusor +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_has_ostream_operator = 20240722, absl_nullability = 20240722, absl_raw_logging_internal = 20240722, absl_status = 20240722, absl_str_format = 20240722, absl_strings = 20240722, absl_type_traits = 20240722, absl_utility = 20240722, absl_variant = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_str_format.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_str_format.pc new file mode 100644 index 0000000..bfe84a5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_str_format.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_str_format +Description: Abseil str_format library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722, absl_span = 20240722, absl_str_format_internal = 20240722, absl_string_view = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_str_format_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_str_format_internal.pc new file mode 100644 index 0000000..8c95e7d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_str_format_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_str_format_internal +Description: Abseil str_format_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_str_format_internal +Requires: absl_bits = 20240722, absl_strings = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_fixed_array = 20240722, absl_inlined_vector = 20240722, absl_numeric_representation = 20240722, absl_type_traits = 20240722, absl_utility = 20240722, absl_int128 = 20240722, absl_span = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_strerror.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_strerror.pc new file mode 100644 index 0000000..a595aa1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_strerror.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_strerror +Description: Abseil strerror library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_strerror +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_errno_saver = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_string_view.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_string_view.pc new file mode 100644 index 0000000..93dd126 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_string_view.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_string_view +Description: Abseil string_view library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_string_view +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_nullability = 20240722, absl_throw_delegate = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_strings.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_strings.pc new file mode 100644 index 0000000..1b1a9f1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_strings.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_strings +Description: Abseil strings library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_strings +Requires: absl_string_view = 20240722, absl_strings_internal = 20240722, absl_base = 20240722, absl_bits = 20240722, absl_charset = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_int128 = 20240722, absl_memory = 20240722, absl_nullability = 20240722, absl_raw_logging_internal = 20240722, absl_throw_delegate = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_strings_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_strings_internal.pc new file mode 100644 index 0000000..08a65cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_strings_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_strings_internal +Description: Abseil strings_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_strings_internal +Requires: absl_config = 20240722, absl_core_headers = 20240722, absl_endian = 20240722, absl_raw_logging_internal = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_symbolize.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_symbolize.pc new file mode 100644 index 0000000..41275af --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_symbolize.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_symbolize +Description: Abseil symbolize library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_symbolize +Requires: absl_debugging_internal = 20240722, absl_demangle_internal = 20240722, absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_malloc_internal = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_synchronization.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_synchronization.pc new file mode 100644 index 0000000..7f17cde --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_synchronization.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_synchronization +Description: Abseil synchronization library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_synchronization +Requires: absl_graphcycles_internal = 20240722, absl_kernel_timeout_internal = 20240722, absl_atomic_hook = 20240722, absl_base = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_dynamic_annotations = 20240722, absl_malloc_internal = 20240722, absl_raw_logging_internal = 20240722, absl_stacktrace = 20240722, absl_symbolize = 20240722, absl_time = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_throw_delegate.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_throw_delegate.pc new file mode 100644 index 0000000..57aa119 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_throw_delegate.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_throw_delegate +Description: Abseil throw_delegate library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_throw_delegate +Requires: absl_config = 20240722, absl_raw_logging_internal = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_time.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_time.pc new file mode 100644 index 0000000..5e094a1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_time.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_time +Description: Abseil time library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_time +Requires: absl_base = 20240722, absl_civil_time = 20240722, absl_core_headers = 20240722, absl_int128 = 20240722, absl_raw_logging_internal = 20240722, absl_strings = 20240722, absl_time_zone = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_time_zone.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_time_zone.pc new file mode 100644 index 0000000..eb3857a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_time_zone.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_time_zone +Description: Abseil time_zone library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_time_zone +Requires: +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_type_traits.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_type_traits.pc new file mode 100644 index 0000000..44e060c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_type_traits.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_type_traits +Description: Abseil type_traits library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_config = 20240722, absl_core_headers = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_utf8_for_code_point.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_utf8_for_code_point.pc new file mode 100644 index 0000000..c53dcb7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_utf8_for_code_point.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_utf8_for_code_point +Description: Abseil utf8_for_code_point library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_utf8_for_code_point +Requires: absl_config = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_utility.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_utility.pc new file mode 100644 index 0000000..503991f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_utility.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_utility +Description: Abseil utility library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_base_internal = 20240722, absl_config = 20240722, absl_type_traits = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_variant.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_variant.pc new file mode 100644 index 0000000..84303ae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_variant.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_variant +Description: Abseil variant library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_bad_variant_access = 20240722, absl_base_internal = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_type_traits = 20240722, absl_utility = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_vlog_config_internal.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_vlog_config_internal.pc new file mode 100644 index 0000000..94abf70 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_vlog_config_internal.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_vlog_config_internal +Description: Abseil vlog_config_internal library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" -labsl_vlog_config_internal +Requires: absl_base = 20240722, absl_config = 20240722, absl_core_headers = 20240722, absl_log_internal_fnmatch = 20240722, absl_memory = 20240722, absl_no_destructor = 20240722, absl_strings = 20240722, absl_synchronization = 20240722, absl_optional = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_vlog_is_on.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_vlog_is_on.pc new file mode 100644 index 0000000..b55ea5f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/absl_vlog_is_on.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: absl_vlog_is_on +Description: Abseil vlog_is_on library +URL: https://abseil.io/ +Version: 20240722 + +Libs: "-L${libdir}" +Requires: absl_absl_vlog_is_on = 20240722 +Cflags: "-I${includedir}" -Wno-float-conversion -Wno-implicit-float-conversion -Wno-implicit-int-float-conversion -Wno-unknown-warning-option -DNOMINMAX diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/draco.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/draco.pc new file mode 100644 index 0000000..a5120c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/draco.pc @@ -0,0 +1,7 @@ +prefix=${pcfiledir}/../.. +Name: draco +Description: Draco geometry de(com)pression library. +Version: 1.5.7 + +Libs: "-L${prefix}/lib" -ldraco +Cflags: "-I${prefix}/include" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/fmt.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/fmt.pc new file mode 100644 index 0000000..9650070 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/fmt.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: fmt +Description: A modern formatting library +Version: 11.0.2 + + +Libs: "-L${libdir}" -lfmt +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libjpeg.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libjpeg.pc new file mode 100644 index 0000000..bef720f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libjpeg.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: libjpeg +Description: A SIMD-accelerated JPEG codec that provides the libjpeg API +Version: 3.0.4 + +Libs: "-L${libdir}" -ljpeg +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libsharpyuv.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libsharpyuv.pc new file mode 100644 index 0000000..9349c28 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libsharpyuv.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/webp + +Name: libsharpyuv +Description: Library for sharp RGB to YUV conversion +Version: 1.4.0 + +Libs: "-L${libdir}" -lsharpyuv +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libturbojpeg.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libturbojpeg.pc new file mode 100644 index 0000000..eeee26d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libturbojpeg.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: libturbojpeg +Description: A SIMD-accelerated JPEG codec that provides the TurboJPEG API +Version: 3.0.4 + +Libs: "-L${libdir}" -lturbojpeg +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/liburiparser.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/liburiparser.pc new file mode 100644 index 0000000..75afa89 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/liburiparser.pc @@ -0,0 +1,13 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: liburiparser +Description: URI parsing and handling library + +Version: 0.9.8 +URL: https://uriparser.github.io/ + +Libs: "-L${libdir}" -luriparser +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libwebp.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libwebp.pc new file mode 100644 index 0000000..aa5e7c0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libwebp.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebp +Description: Library for the WebP graphics format +Version: 1.4.0 + +Libs: "-L${libdir}" -lwebp +Requires: libsharpyuv +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libwebpdecoder.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libwebpdecoder.pc new file mode 100644 index 0000000..7b170f7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libwebpdecoder.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebpdecoder +Description: Library for the WebP graphics format (decode only) +Version: 1.4.0 + +Libs: "-L${libdir}" -lwebpdecoder +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libwebpdemux.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libwebpdemux.pc new file mode 100644 index 0000000..5730238 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libwebpdemux.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebpdemux +Description: Library for parsing the WebP graphics format container +Version: 1.4.0 + +Libs: "-L${libdir}" -lwebpdemux +Requires: libwebp >= 0.2.0 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libwebpmux.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libwebpmux.pc new file mode 100644 index 0000000..5270237 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libwebpmux.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libwebpmux +Description: Library for manipulating the WebP graphics format container +Version: 1.4.0 + +Libs: "-L${libdir}" -lwebpmux +Requires: libwebp >= 0.2.0 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libzstd.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libzstd.pc new file mode 100644 index 0000000..6e08863 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/libzstd.pc @@ -0,0 +1,16 @@ +prefix=${pcfiledir}/../.. +# ZSTD - standard compression algorithm +# Copyright (c) Meta Platforms, Inc. and affiliates. +# BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +Name: zstd +Description: fast lossless compression algorithm library +URL: https://facebook.github.io/zstd/ +Version: 1.5.6 + +Libs: "-L${libdir}" -lzstd +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/spdlog.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/spdlog.pc new file mode 100644 index 0000000..3b2aab0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/spdlog.pc @@ -0,0 +1,14 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +Name: libspdlog +Description: Fast C++ logging library. +URL: https://github.com/gabime/spdlog +Version: 1.15.0 +CFlags: "-I${includedir}" -DSPDLOG_COMPILED_LIB -DSPDLOG_FMT_EXTERNAL + + +Libs: "-L${libdir}" -lspdlog -pthread +Requires: fmt diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/sqlite3.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/sqlite3.pc new file mode 100644 index 0000000..afa467b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/sqlite3.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: SQLite +Description: SQL database engine +Version: 3.45.0 + +Libs: "-L${libdir}" -lsqlite3 -pthread +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/tidy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/tidy.pc new file mode 100644 index 0000000..7ad2384 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/tidy.pc @@ -0,0 +1,11 @@ +prefix=/Users/runner/work/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty +exec_prefix=${prefix} +libdir=${exec_prefix}//Users/runner/work/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty/lib/iOS-arm64-$,Debug,Release> +includedir=${prefix}/include + +Name: tidy +Description: tidy - HTML syntax checker +URL: https://www.html-tidy.org +Version: 5.9.14 +Libs: -L${libdir} -ltidy +Cflags: -I${includedir} diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/tinyxml2.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/tinyxml2.pc new file mode 100644 index 0000000..24bbedf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/tinyxml2.pc @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: TinyXML2 +Description: simple, small, C++ XML parser +Version: 10.0.0 + +Libs: "-L${libdir}" -ltinyxml2 +Cflags: "-I${includedir}" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/zlib-ng.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/zlib-ng.pc new file mode 100644 index 0000000..9a4a354 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-arm64-Release/pkgconfig/zlib-ng.pc @@ -0,0 +1,15 @@ +prefix=${pcfiledir}/../.. +exec_prefix=${prefix} +symbol_prefix= +libdir=${exec_prefix}/lib +sharedlibdir=${libdir} +includedir=${prefix}/include + +Name: zlib-ng +Description: zlib-ng compression library +Version: 2.1.6 + + +Libs: "-L${libdir}" "-L${sharedlibdir}" -lz-ng +Requires: +Cflags: "-I${includedir}" -DWITH_GZFILEOP diff --git a/Plugins/CesiumForUnreal/ThirdParty.json b/Plugins/CesiumForUnreal/ThirdParty.json new file mode 100644 index 0000000..c22712d --- /dev/null +++ b/Plugins/CesiumForUnreal/ThirdParty.json @@ -0,0 +1,25 @@ +[ + { + "name": "cesium-native", + "url": "https://github.com/CesiumGS/cesium-native", + "version": "Latest", + "license": ["Apache 2.0"] + }, + { + "name": "Font Awesome Icons", + "url": "https://fontawesome.com/", + "version": "N/A", + "license": ["CC BY 4.0 License"], + "notes": "See Content/FontAwesome/attribution.txt" + }, + { + "name": "MikkTSpace", + "url": "https://github.com/mmikk/MikkTSpace", + "license": ["Zlib"] + }, + { + "name": "HTML Tidy", + "url": "https://github.com/htacg/tidy-html5", + "license": ["HTML Tidy License"] + } +] diff --git a/Source/BXSSP.Target.cs b/Source/BXSSP.Target.cs new file mode 100644 index 0000000..98506ec --- /dev/null +++ b/Source/BXSSP.Target.cs @@ -0,0 +1,16 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class BXSSPTarget : TargetRules +{ + public BXSSPTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Game; + DefaultBuildSettings = BuildSettingsVersion.V4; + IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_3; + ExtraModuleNames.Add("BXSSP"); + ExtraModuleNames.AddRange(new string[] { "BXSSP", "CesiumRuntime" }); + } +} diff --git a/Source/BXSSP/BXSSP.Build.cs b/Source/BXSSP/BXSSP.Build.cs new file mode 100644 index 0000000..f94dc2e --- /dev/null +++ b/Source/BXSSP/BXSSP.Build.cs @@ -0,0 +1,23 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class BXSSP : ModuleRules +{ + public BXSSP(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "CesiumRuntime","Engine", "InputCore", "EnhancedInput", "UMG", "Slate", "Json", "JsonUtilities", "HTTP", "XmlParser", "SlateCore", "Niagara", "ProceduralMeshComponent", "WebSockets", "GeometryFramework", "CableComponent", }); + + PrivateDependencyModuleNames.AddRange(new string[] { }); + + // Uncomment if you are using Slate UI + // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); + + // Uncomment if you are using online features + // PrivateDependencyModuleNames.Add("OnlineSubsystem"); + + // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true + } +} diff --git a/Source/BXSSP/BXSSP.cpp b/Source/BXSSP/BXSSP.cpp new file mode 100644 index 0000000..aa53895 --- /dev/null +++ b/Source/BXSSP/BXSSP.cpp @@ -0,0 +1,6 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "BXSSP.h" +#include "Modules/ModuleManager.h" + +IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, BXSSP, "BXSSP" ); diff --git a/Source/BXSSP/BXSSP.h b/Source/BXSSP/BXSSP.h new file mode 100644 index 0000000..677c8e2 --- /dev/null +++ b/Source/BXSSP/BXSSP.h @@ -0,0 +1,6 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" + diff --git a/Source/BXSSP/Private/MainHUD.cpp b/Source/BXSSP/Private/MainHUD.cpp new file mode 100644 index 0000000..aed6a98 --- /dev/null +++ b/Source/BXSSP/Private/MainHUD.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MainHUD.h" + diff --git a/Source/BXSSP/Private/Rover.cpp b/Source/BXSSP/Private/Rover.cpp new file mode 100644 index 0000000..354269d --- /dev/null +++ b/Source/BXSSP/Private/Rover.cpp @@ -0,0 +1,1073 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Rover.h" +#include "InputAction.h" +#include "InputActionValue.h" +#include "InputMappingContext.h" +#include "EnhancedInputSubsystems.h" +#include "EnhancedInputComponent.h" +#include "RoverController.h" +#include "Kismet/GameplayStatics.h" +#include "CesiumGlobeAnchorComponent.h" +#include "Kismet/KismetMathLibrary.h" +#include "CesiumGeoreference.h" +#include "Camera/CameraComponent.h" +#include "GameFramework/SpringArmComponent.h" +#include "DrawDebugHelpers.h" +#include "Blueprint/UserWidget.h" +#include "CesiumFlyToComponent.h" +#include "GameFramework/PawnMovementComponent.h" +#include "Blueprint/WidgetLayoutLibrary.h" +#include "Engine/StaticMeshActor.h" +#include "Components/SceneCaptureComponent2D.h" +#include "ConvexVolume.h" + +ARover* ARover::PlayerPawn = nullptr; + +ARover::ARover(): + bPressMouseMiddleKey(false), + SelfBaseTurnRate(10), + SelfBaseLookUpRate(10), + ZoomRollSpeed(5.f), + RotateAngle(0.1f), + bPressMouseRightKey(false), + bPressMouseLeftKey(false), + BaseMouseLeftMoveRate(50.f), + MoveToLocation(FVector(0)), + MaxDistance(1.f), + bMoveForward(false), + bMoveRight(false), + bLimitViewport(false), + bAllowMouseLeftMove(true), + ControlHeightMulitiplier(0.1f), + LongitudeLatitudeControlHeightMulitiplier(0.01), + MouseMoveOffsetMulitiplier(0.01), + bAllowUpdataMove(false), + SlowStopMoveSpeed(0), + TotalSlowStopMoveOffsetTime(0), + CurrentSlowStopMoveOffsetTime(0), + ChangeHeightThreshold(100000), + bFlying(false), + ZoomOffsetMulitiplier(0.1f), + ZoomOffsetHeightValue(1000000), + bFollowSportTrace(false), + CurrentMoveDistance(0), + MoveSpeedMultiplier(1.5f), + bAllowInertialMove(false), + CheckMoveCollisionChannel(ECollisionChannel::ECC_Visibility), + SelecteItemMode(ESelecteItemMode::ESM_Default), + LastSelecteItemMode(ESelecteItemMode::ESM_Default), + bTempStopAutoRotate(false) +{ + PlayerPawn = this; + FlyComp = CreateDefaultSubobject(TEXT("FlyComp")); + FlyComp->RotationToUse = ECesiumFlyToRotation::ControlRotationInUnreal; + FlyComp->Duration = 3.f; + SpringArm = CreateDefaultSubobject(TEXT("SpringArmComp")); + SpringArm->SetupAttachment(RootComponent); + Camera = CreateDefaultSubobject(TEXT("CameraComp")); + Camera->SetupAttachment(SpringArm); + AutoPossessPlayer = EAutoReceiveInput::Player0; +} + +void ARover::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + + PlayerLongitudeLatitudeHeight = GlobeAnchor->GetLongitudeLatitudeHeight(); + LastMousePosition = MousePosition; + PlayerController->GetMousePosition(MousePosition.X, MousePosition.Y); + UpdataMoveToLocation(DeltaTime); + if (GlobeAnchor->GetHeight() > 100000) { + if (PlayerController) { + //PlayerController->GetMainHUD()->CloseWeatherSystem(); + } + } + UpdateSlideRotation(DeltaTime); + InertialMove(DeltaTime); + //GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::White, TEXT("Tick正在执行")); +} + +void ARover::BeginPlay() +{ + Super::BeginPlay(); + PlayerController = Cast(UGameplayStatics::GetPlayerController(GetWorld(), 0)); + if (Georeference) { + FVector Location = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(FVector(106.405113, 29.720642, 7000000.0)); + CurrentHeight = 7000000.0; + SetActorLocation(Location); + PlayerController->SetControlRotation(FRotator(-88.f, -90, 0)); + Georeference->SetOriginLongitudeLatitudeHeight(FVector(106, 30, 1000.0)); + } +} + +void ARover::SetupPlayerInputComponent(UInputComponent* InInputComponent) +{ + if (APlayerController* ThePlayerController = Cast(GetController())) { + if (UEnhancedInputLocalPlayerSubsystem* LocalPlayerSubsystem = ULocalPlayer::GetSubsystem(ThePlayerController->GetLocalPlayer())) { + LocalPlayerSubsystem->AddMappingContext(BaseInputAction, 0); + } + } + if (UEnhancedInputComponent* EnhancedInputComponent = Cast(InInputComponent)) { + if (MouseMiddleAxisAsset) { + EnhancedInputComponent->BindAction(MouseMiddleAxisAsset, ETriggerEvent::Started, this, &ARover::PressMouseMiddleButton); + EnhancedInputComponent->BindAction(MouseMiddleAxisAsset, ETriggerEvent::Completed, this, &ARover::ReleaseMouseMiddleButton); + } + + if (MouseLeftAsset) { + EnhancedInputComponent->BindAction(MouseLeftAsset, ETriggerEvent::Started, this, &ARover::PressMouseLeftButton); + EnhancedInputComponent->BindAction(MouseLeftAsset, ETriggerEvent::Completed, this, &ARover::ReleaseMouseLeftButton); + EnhancedInputComponent->BindAction(MouseLeftAsset, ETriggerEvent::Triggered, this, &ARover::MouseLeftMovePawn); + } + + if (TurnAsset) { + EnhancedInputComponent->BindAction(TurnAsset, ETriggerEvent::Triggered, this, &ARover::_TurnAtRate); + } + + if (LookUpAsset) { + EnhancedInputComponent->BindAction(LookUpAsset, ETriggerEvent::Triggered, this, &ARover::_LookUpAtRate); + } + + if (GamePadTurnAsset) { + EnhancedInputComponent->BindAction(GamePadTurnAsset, ETriggerEvent::Triggered, this, &ARover::GamePadTurnAtRate); + } + + if (GamePadLookUPAsset) { + EnhancedInputComponent->BindAction(GamePadLookUPAsset, ETriggerEvent::Triggered, this, &ARover::GamePadLookUpAtRate); + } + + if (MouseRollAxisAsset) { + EnhancedInputComponent->BindAction(MouseRollAxisAsset, ETriggerEvent::Triggered, this, &ARover::MouseRollDistance); + } + + if (MouseRightAsset) { + EnhancedInputComponent->BindAction(MouseRightAsset, ETriggerEvent::Started, this, &ARover::PressMouseRightButton); + EnhancedInputComponent->BindAction(MouseRightAsset, ETriggerEvent::Completed, this, &ARover::ReleaseMouseRightButton); + } + + if (MoveForwardAsset) { + EnhancedInputComponent->BindAction(MoveForwardAsset, ETriggerEvent::Triggered, this, &ARover::_MoveForward); + EnhancedInputComponent->BindAction(MoveForwardAsset, ETriggerEvent::Completed, this, &ARover::ReleaseMoveButton); + } + + if (MoveRightAsset) { + EnhancedInputComponent->BindAction(MoveRightAsset, ETriggerEvent::Triggered, this, &ARover::_MoveRight); + EnhancedInputComponent->BindAction(MoveRightAsset, ETriggerEvent::Completed, this, &ARover::ReleaseMoveButton); + } + + if (TS_TwoTouchAsset) { + EnhancedInputComponent->BindAction(TS_TwoTouchAsset, ETriggerEvent::Triggered, this, &ARover::TS_TriggeredTwoTouch); + EnhancedInputComponent->BindAction(TS_TwoTouchAsset, ETriggerEvent::Started, this, &ARover::TS_PressTwoTouch); + EnhancedInputComponent->BindAction(TS_TwoTouchAsset, ETriggerEvent::Completed, this, &ARover::TS_ReleaseTwoTouch); + } + + } +} + +void ARover::PressMouseMiddleButton() +{ + if (bPressMouseLeftKey || bPressMouseRightKey)return; + bPressMouseMiddleKey = true; +} + +void ARover::ReleaseMouseMiddleButton() +{ + bPressMouseMiddleKey = false; +} + +void ARover::PressMouseLeftButton() +{ + FHitResult _ClickObject; + + if ( bPressMouseMiddleKey)return; + if (bCurrentLookingup) { + ReleaseMouseMiddleButton(); + bCurrentLookingup = false; + } + if (bHDRIMode) { + PressMouseMiddleButton(); + return; + } + PlayerController->GetMousePosition(TestMousePosition.X, TestMousePosition.Y); + FHitResult _HitResult; + if (PlayerController->GetUnderMouseHitPosition(_HitResult)) { + MouseClickLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(_HitResult.Location); + if (GlobeAnchor->GetHeight() < 20000) { + AssistMouseLeftMoveActor->SetActorLocation(_HitResult.Location); + float _Distance = (AssistMouseLeftMoveActor->GetActorLocation() - GetActorLocation()).Length() * 0.1; + AssistMouseLeftMoveActor->SetActorScale3D(FVector(_Distance)); + CheckMoveCollisionChannel = ECollisionChannel::ECC_GameTraceChannel1; + } + else { + CheckMoveCollisionChannel = ECollisionChannel::ECC_Visibility; + } + } + + bPressMouseLeftKey = true; + +} + +void ARover::ReleaseMouseLeftButton() +{ + if (bHDRIMode) { + ReleaseMouseMiddleButton(); + return; + } + bPressMouseLeftKey = false; + if (!bAllowUpdataMove)bAllowInertialMove = true; +} + +void ARover::PressMouseRightButton() +{ + if (bPressMouseLeftKey || bPressMouseMiddleKey)return; + if (bHDRIMode) { + PressMouseMiddleButton(); + return; + } + bTempStopAutoRotate = true; + bPressMouseRightKey = true; + // 用于判断当前右键是拖动还是点击 + //FTimerHandle ClearSelectedResourceItemTimer; + //GetWorldTimerManager().SetTimer(ClearSelectedResourceItemTimer, this, &ARover::ClearSelectedResourceItemSets, 0.2f, false); + StopMouseLeftMove(); + UpdatascreenCenterPointLocation(); + +} + +void ARover::ReleaseMouseRightButton() +{ + bTempStopAutoRotate = false; + bPressMouseRightKey = false; + //PlayerController->SetMouseShowStatus(true); + bLimitViewport = false; + AdjustSpeedByHeight(); + if (LastMousePosition != MousePosition) { + SlideTime = (MousePosition - LastMousePosition).Length() * MouseMoveOffsetMulitiplier * 0.1;; + TotalSlideTime = SlideTime; + GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::SanitizeFloat(SlideTime)); + } +} + +void ARover::_TurnAtRate(const FInputActionValue& Value) +{ + if (bPressMouseRightKey) { + AroundPointRotation(Value.GetMagnitude(), EAxis::X); + } + if (!bPressMouseMiddleKey)return; + AddControllerYawInput(Value.GetMagnitude() * GetWorld()->GetDeltaSeconds() * SelfBaseTurnRate * -0.15 * Camera->FieldOfView / 80); +} + +void ARover::GamePadTurnAtRate(const FInputActionValue& Value) +{ + if (bFollowSportTrace)return; + AddControllerYawInput(Value.GetMagnitude() * GetWorld()->GetDeltaSeconds() * SelfBaseTurnRate * -0.15 * Camera->FieldOfView / 80); +} + +void ARover::_LookUpAtRate(const FInputActionValue& Value) +{ + if (bPressMouseRightKey) { + AroundPointRotation(Value.GetMagnitude(), EAxis::Y); + } + if (!bPressMouseMiddleKey)return; + AddControllerPitchInput(Value.GetMagnitude() * GetWorld()->GetDeltaSeconds() * SelfBaseLookUpRate * 0.15 * Camera->FieldOfView / 80); +} + +void ARover::GamePadLookUpAtRate(const FInputActionValue& Value) +{ + AddControllerPitchInput(Value.GetMagnitude() * GetWorld()->GetDeltaSeconds() * SelfBaseLookUpRate * 0.15 * Camera->FieldOfView / 80); +} + +void ARover::MouseRollDistance(const FInputActionValue& Value) +{ + if (!bHDRIMode) + { + AssistMouseRollDistance(Value.GetMagnitude()); + } + else + { + //输出鼠标滚轮值 + MiddleKeyValue = Value.GetMagnitude(); + } +} + +void ARover::TS_TriggeredTwoTouch(const FInputActionValue& Value) +{ + if (!bTS_StartAction)return; + LastTouch1 = Touch1; + LastTouch2 = Touch2; + PlayerController->GetInputTouchState(ETouchIndex::Touch1, Touch1.X, Touch1.Y, bPressTouch1); + PlayerController->GetInputTouchState(ETouchIndex::Touch2, Touch2.X, Touch2.Y, bPressTouch2); + if (LastTouch1 == Touch1 && LastTouch2 == Touch2)return; + FVector2D CurTwoTouchDirection = (Touch1 - LastTouch1).GetSafeNormal(); + FVector2D LastTwoTouchDirection = (Touch2 - LastTouch2).GetSafeNormal(); + double Delta = UKismetMathLibrary::DotProduct2D(CurTwoTouchDirection, LastTwoTouchDirection); + + + if (Delta <= 0) { + TS_MouseRollDistance(Value); + TS_FOVRotation(Value); + } + else if (Delta > 0) { + TS_UpDownPitch(Value); + } +} + +void ARover::TS_MouseRollDistance(const FInputActionValue& Value) +{ + if (!bPressTouch1 || !bPressTouch1)return; + float TheValue = ((Touch1 - Touch2).Length() - ((LastTouch1 - LastTouch2).Length())) * 0.05; + AssistMouseRollDistance(TheValue, TS_ZoomHitResult); +} + +void ARover::TS_PressTwoTouch() +{ + if (GetWorldTimerManager().IsTimerActive(TS_DelayReleaseTimer)) { + GetWorldTimerManager().ClearTimer(TS_DelayReleaseTimer); + } + bTS_PressTwoTouch = true; + PlayerController->GetInputTouchState(ETouchIndex::Touch1, Touch1.X, Touch1.Y, bPressTouch1); + PlayerController->GetInputTouchState(ETouchIndex::Touch2, Touch2.X, Touch2.Y, bPressTouch2); + if (TS_ZoomHitResult == std::nullopt) { + FVector2D TS_ZoomPoint = (Touch1 + Touch2) * 0.5f; + FHitResult HitResult; + PlayerController->GetUnderScreenHitPosition(TS_ZoomPoint, HitResult); + TS_ZoomHitResult = HitResult; + } + GetWorldTimerManager().SetTimer(TS_ActionTimer, this, &ARover::TS_StartAction, TS_DelayTime, false); +} + +void ARover::TS_ReleaseTwoTouch() +{ + if (GetWorldTimerManager().IsTimerActive(TS_DelayReleaseTimer)) { + GetWorldTimerManager().ClearTimer(TS_DelayReleaseTimer); + } + FTimerDelegate _TimerDelegate; + _TimerDelegate.BindLambda([this]() { + this->bTS_PressTwoTouch = false; + this->bLimitViewport = false; + this->bTS_StartAction = false; + this->TS_ZoomHitResult = std::nullopt; + this->TS_ActionStatus = ETSAction::ETS_Default; + }); + GetWorldTimerManager().SetTimer(TS_DelayReleaseTimer, _TimerDelegate, 0.05f, false); +} + +void ARover::TS_FOVRotation(const FInputActionValue& Value) +{ + FVector2D CurTwoTouchDirection = (Touch2 - Touch1).GetSafeNormal(); + FVector2D LastTwoTouchDirection = (LastTouch2 - LastTouch1).GetSafeNormal(); + if (LastTouch1 == Touch1 && LastTouch2 == Touch2)return; + if (!bPressTouch1 || !bPressTouch2)return; + float Angle = FMath::RadiansToDegrees(FMath::Acos(UKismetMathLibrary::DotProduct2D(CurTwoTouchDirection, LastTwoTouchDirection) / (CurTwoTouchDirection.Length() * LastTwoTouchDirection.Length()))); + float Alpha = SelfBaseTurnRate * 0.5 * Angle; + if (UKismetMathLibrary::CrossProduct2D(CurTwoTouchDirection, LastTwoTouchDirection) <= 0) { + Alpha *= -1; + } + AroundPointRotation(Alpha, EAxis::X, TS_ZoomHitResult->Location); +} + +void ARover::TS_UpDownPitch(const FInputActionValue& Value) +{ + if (LastTouch1 == Touch1 && LastTouch2 == Touch2)return; + if (!bPressTouch1 || !bPressTouch2)return; + FVector2D CurTwoTouchDirection = (Touch2 - Touch1).GetSafeNormal(); + FVector2D LastTwoTouchDirection = (LastTouch2 - LastTouch1).GetSafeNormal(); + float Alpha = Value.GetMagnitude() * GetWorld()->GetDeltaSeconds() * 0.4; + if (LastTouch1.Y - Touch1.Y <= 0) { + Alpha *= -1; + } + AroundPointRotation(Alpha, EAxis::Y, TS_ZoomHitResult->Location); +} + +void ARover::ModifyMaxRollCoefficient(float Coefficient) +{ + MaxRollCoefficient = Coefficient; + AssistMouseRollDistance(1); +} + +void ARover::_MoveRight(const FInputActionValue& TheValue) +{ + float Value = TheValue.GetMagnitude(); + if (Value && GetController()) { + StopMouseLeftMove(); + AdjustSpeedByHeight(); + FRotator ControlRotation = GetControlRotation(); + FRotator Rotation(ControlRotation.Pitch, ControlRotation.Yaw, 0); + FVector Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::Y); + float Height = GlobeAnchor->GetHeight(); + if (Height < 50)Height = 50; + AddMovementInput(Direction, Value * Height * 0.000001); + UpdateOrignLongitudeLatitude(); + bPressMoveButton = true; + UpdateCurrentHeight(); + } +} + +void ARover::UpdateCurrentHeight() +{ + this->CurrentHeight = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(this->GetActorLocation()).Z; + +} + +void ARover::ResetPlayerProperty() +{ + bPressMoveButton = false; +} + +void ARover::MoveToLongitudeLatitudeHeight(const FVector& LongitudeLatitudeHeight) +{ + if (bFlying)return; + GlobeAnchor->MoveToLongitudeLatitudeHeight(LongitudeLatitudeHeight); + UpdateOrignLongitudeLatitude(); + UpdateCurrentHeight(); +} + +void ARover::EnableCameraLag(bool bOpen) +{ + if (bOpen) { + SpringArm->bEnableCameraLag = true; + SpringArm->bEnableCameraRotationLag = true; + } + else { + SpringArm->bEnableCameraLag = false; + SpringArm->bEnableCameraRotationLag = false; + } +} + +void ARover::SetMaxRollDistance(float _MaxDistance) +{ + CurrentMaxRollDistance = _MaxDistance; + FVector SelfLocation = GetActorLocation(); + if (SelfLocation.Z < CurrentMaxRollDistance)return; + FHitResult HitResult; + if (ARoverController::PlayerController->GetUnderscreenCenterHitPosition(HitResult)) { + FVector Direction = (SelfLocation - HitResult.Location).GetSafeNormal(); + SelfLocation = HitResult.Location + Direction * CurrentMaxRollDistance; + SetActorLocation(SelfLocation); + UpdateCurrentHeight(); + } +} + +FConvexVolume ARover::GetViewFrustum() +{ + FMinimalViewInfo CameraViewInfo; + Camera->GetCameraView(GetWorld()->GetDeltaSeconds(), CameraViewInfo); + FMatrix ProjectionMatrix; + FMatrix ViewMatrix; + FMatrix ViewProjectionMatrix; + UGameplayStatics::GetViewProjectionMatrix(CameraViewInfo, ViewMatrix, ProjectionMatrix, ViewProjectionMatrix); + FConvexVolume ViewFrustum; + GetViewFrustumBounds(ViewFrustum, ViewProjectionMatrix, true, true); + return ViewFrustum; +} + +bool ARover::CheckPointInViewFrustum(const FVector& Point) +{ + FConvexVolume ViewFrustum = GetViewFrustum(); + TArray Vertices; + return ViewFrustum.IntersectPoint(Point); +} + +void ARover::StopKeyMove() +{ + bKeyMove = false; +} + +void ARover::StartKeyMove() +{ + bKeyMove = true; +} + +void ARover::ClearCurrentSlowStopMoveOffsetTime() +{ + CurrentSlowStopMoveOffsetTime = 0; + MoveToLocation = FVector(0); +} + +void ARover::TS_StartAction() +{ + UpdatascreenCenterPointLocation(); + bTS_StartAction = true; +} + +void ARover::MouseLeftMovePawn(const FInputActionValue& Value) +{ + if (!bPressMouseLeftKey || !bAllowMouseLeftMove || bFollowSportTrace || bTS_PressTwoTouch)return; + + if (LastMousePosition == MousePosition)return; + if (!bCurrentLookingup) { + + float MouseOffset = (MousePosition - LastMousePosition).Length(); + FVector MouseDirection; + FVector MousePositionWorldLocation; + FVector LastMouseDirection; + FVector LastMousePositionWorldLocation; + PlayerController->DeprojectScreenPositionToWorld(MousePosition.X, MousePosition.Y, MousePositionWorldLocation, MouseDirection); + PlayerController->DeprojectScreenPositionToWorld(LastMousePosition.X, LastMousePosition.Y, LastMousePositionWorldLocation, LastMouseDirection); + + + FVector Location = GetActorLocation(); + float Height = FMath::Abs(GlobeAnchor->GetHeight()); + if (Height < 200)Height = 200; + FHitResult _MouseHitResult; + GetWorld()->LineTraceSingleByChannel(_MouseHitResult, MousePositionWorldLocation, MousePositionWorldLocation + MouseDirection * 100000000000, CheckMoveCollisionChannel); + + if (_MouseHitResult.bBlockingHit) { + if (bAllowUpdateSlide) { + MouseClickLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(_MouseHitResult.Location); + bAllowUpdateSlide = false; + bAllowSlowStopMove = false; + return; + } + bAllowUpdataMove = false; + FVector _MouseLocation = _MouseHitResult.Location; + FVector _FirstMouseClickPosition = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(MouseClickLongitudeLatitude); + + FVector2D _MousescreenPosition; + FVector2D _FirstMousescreenPosition; + PlayerController->ProjectWorldLocationToScreen(_MouseLocation, _MousescreenPosition); + PlayerController->ProjectWorldLocationToScreen(_FirstMouseClickPosition, _FirstMousescreenPosition); + _MouseLocation.Z = 0; + _FirstMouseClickPosition.Z = 0; + MoveDirectionLast = (_MouseLocation - _FirstMouseClickPosition).GetSafeNormal() * -1; + + CurrentMoveDistance = (_MouseLocation - _FirstMouseClickPosition).Length(); + FVector MoveToDistance = MoveDirectionLast * CurrentMoveDistance; + MoveToDistance.Z = 0; + MoveToLocation = Location + MoveToDistance; + FVector TargetLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(MoveToLocation); + float Latitude = TargetLongitudeLatitude.Y; + if (Latitude > MaxCrossingLatitude || Latitude < -MaxCrossingLatitude) { + FInputActionValue InputActionValue(-10.f); + _MoveRight(InputActionValue); + } + else { + TargetLongitudeLatitude.Z = CurrentHeight; + MoveToLocation = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(TargetLongitudeLatitude); + GlobeAnchor->MoveToLongitudeLatitudeHeight(TargetLongitudeLatitude); + } + UpdateOrignLongitudeLatitude(); + + TotalSlowStopMoveOffsetTime = MouseOffset * MouseMoveOffsetMulitiplier * 0.1; + } + else if (GlobeAnchor->GetHeight() > LimitValueOfRotateAroundPoint) { + bAllowSlowStopMove = true; + bAllowUpdateSlide = true; + MoveDirectionLast = (MousePositionWorldLocation - LastMousePositionWorldLocation).GetSafeNormal() * -1; + + FVector MoveToDistance = MoveDirectionLast * (MousePositionWorldLocation - LastMousePositionWorldLocation).Length() * Height * BaseMouseLeftMoveRate * 10; + Location += MoveToDistance; + FVector MoveToLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(Location); + MoveToLongitudeLatitude.Z = Height; + MoveToLocation = MoveToLongitudeLatitude; + + + TotalSlowStopMoveOffsetTime = FMath::Clamp(MouseOffset * MouseMoveOffsetMulitiplier, 0.f, 1.f); + if (GetWorldTimerManager().IsTimerActive(SlowStopMoveTimer))GetWorldTimerManager().ClearTimer(SlowStopMoveTimer); + GetWorld()->GetTimerManager().SetTimer(SlowStopMoveTimer, this, &ARover::StartSlowStopMove, CurrentSlowStopMoveOffsetTime, false); + bAllowUpdataMove = true; + } + else { + bCurrentLookingup = true; + PressMouseMiddleButton(); + } + if (!bCurrentLookingup) { + CurrentSlowStopMoveOffsetTime = TotalSlowStopMoveOffsetTime; + } + } +} + +void ARover::TouchMovePawn(FVector2D CurScreenPosition, FVector2D LastScreenPosition) +{ + if (CurScreenPosition == LastScreenPosition)return; + MousePosition = CurScreenPosition; + LastMousePosition = LastScreenPosition; + float MouseOffset = (CurScreenPosition - LastScreenPosition).Length(); + FVector MouseDirection; + FVector MousePositionWorldLocation; + FVector LastMouseDirection; + FVector LastMousePositionWorldLocation; + PlayerController->DeprojectScreenPositionToWorld(CurScreenPosition.X, CurScreenPosition.Y, MousePositionWorldLocation, MouseDirection); + PlayerController->DeprojectScreenPositionToWorld(LastScreenPosition.X, LastScreenPosition.Y, LastMousePositionWorldLocation, LastMouseDirection); + + + FVector Location = GetActorLocation(); + float Height = FMath::Abs(GlobeAnchor->GetHeight()); + if (Height < 200)Height = 200; + FHitResult _MouseHitResult; + GetWorld()->LineTraceSingleByChannel(_MouseHitResult, MousePositionWorldLocation, MousePositionWorldLocation + MouseDirection * 100000000000, CheckMoveCollisionChannel); + + if (_MouseHitResult.bBlockingHit) { + if (bAllowUpdateSlide) { + MouseClickLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(_MouseHitResult.Location); + bAllowUpdateSlide = false; + bAllowSlowStopMove = false; + return; + } + bAllowUpdataMove = false; + FVector _MouseLocation = _MouseHitResult.Location; + FVector _FirstMouseClickPosition = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(MouseClickLongitudeLatitude); + + FVector2D _MousescreenPosition; + FVector2D _FirstMousescreenPosition; + PlayerController->ProjectWorldLocationToScreen(_MouseLocation, _MousescreenPosition); + PlayerController->ProjectWorldLocationToScreen(_FirstMouseClickPosition, _FirstMousescreenPosition); + _MouseLocation.Z = 0; + _FirstMouseClickPosition.Z = 0; + MoveDirectionLast = (_MouseLocation - _FirstMouseClickPosition).GetSafeNormal() * -1; + + CurrentMoveDistance = (_MouseLocation - _FirstMouseClickPosition).Length(); + FVector MoveToDistance = MoveDirectionLast * CurrentMoveDistance; + MoveToDistance.Z = 0; + MoveToLocation = Location + MoveToDistance; + FVector TargetLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(MoveToLocation); + float Latitude = TargetLongitudeLatitude.Y; + if (Latitude > MaxCrossingLatitude || Latitude < -MaxCrossingLatitude) { + FInputActionValue InputActionValue(-10.f); + _MoveRight(InputActionValue); + } + else { + TargetLongitudeLatitude.Z = CurrentHeight; + MoveToLocation = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(TargetLongitudeLatitude); + GlobeAnchor->MoveToLongitudeLatitudeHeight(TargetLongitudeLatitude); + } + UpdateOrignLongitudeLatitude(); + + TotalSlowStopMoveOffsetTime = MouseOffset * MouseMoveOffsetMulitiplier * 0.1; + } + else if (GlobeAnchor->GetHeight() > LimitValueOfRotateAroundPoint) { + bAllowSlowStopMove = true; + bAllowUpdateSlide = true; + MoveDirectionLast = (MousePositionWorldLocation - LastMousePositionWorldLocation).GetSafeNormal() * -1; + + FVector MoveToDistance = MoveDirectionLast * (MousePositionWorldLocation - LastMousePositionWorldLocation).Length() * Height * BaseMouseLeftMoveRate * 10; + Location += MoveToDistance; + FVector MoveToLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(Location); + MoveToLongitudeLatitude.Z = Height; + MoveToLocation = MoveToLongitudeLatitude; + + + TotalSlowStopMoveOffsetTime = FMath::Clamp(MouseOffset * MouseMoveOffsetMulitiplier, 0.f, 1.f); + if (GetWorldTimerManager().IsTimerActive(SlowStopMoveTimer))GetWorldTimerManager().ClearTimer(SlowStopMoveTimer); + GetWorld()->GetTimerManager().SetTimer(SlowStopMoveTimer, this, &ARover::StartSlowStopMove, CurrentSlowStopMoveOffsetTime, false); + bAllowUpdataMove = true; + } + else { + bCurrentLookingup = true; + PressMouseMiddleButton(); + } + if (!bCurrentLookingup) { + CurrentSlowStopMoveOffsetTime = TotalSlowStopMoveOffsetTime; + } +} + +void ARover::UpdataMoveToLocation(float DeltaTime) +{ + static FVector LastTargetLocation = FVector(0); + if (MoveToLocation == FVector(0))return; + if (bAllowUpdataMove) { + FVector TargetLocation = FVector(0); + if (!bAllowInertialMove) { + FVector Location = GlobeAnchor->GetLongitudeLatitudeHeight(); + if (Location.X > 90) { + if (MoveToLocation.X < 0) { + MoveToLocation.X = 180 + (180 + MoveToLocation.X); + } + } + else if (Location.X < -90) { + if (MoveToLocation.X > 0) { + MoveToLocation.X = MoveToLocation.X - 360; + } + } + + TargetLocation = UKismetMathLibrary::VInterpTo(Location, MoveToLocation, DeltaTime, 3.f); + + /*if (TargetLocation.X > 180) { + TargetLocation.X = TargetLocation.X - 360; + } + else if (TargetLocation.X < -180) { + TargetLocation.X = 180 + (TargetLocation.X + 180); + }*/ + TargetLocation.Z = CurrentHeight; + GlobeAnchor->MoveToLongitudeLatitudeHeight(TargetLocation); + if (LastTargetLocation != FVector(0)) { + MoveDirectionLast = (TargetLocation - LastTargetLocation).GetSafeNormal(); + } + if (!GetWorldTimerManager().IsTimerActive(UpdateOriginLongitudeLatitdeTimer)) { + DelayUpdateOrigin(); + } + SlowStopMoveSpeed = (TargetLocation - LastTargetLocation).Length(); + } + LastTargetLocation = TargetLocation; + } + else if (!bAllowInertialMove && bAllowSlowStopMove) { + //return; + if (CurrentSlowStopMoveOffsetTime <= 0) { + MoveToLocation = FVector(0); + SlowStopMoveSpeed = 0; + MoveDirectionLast = FVector(0); + LastTargetLocation = FVector(0); + bAllowSlowStopMove = false; + return; + } + float SpeedMulityplier = UKismetMathLibrary::NormalizeToRange(CurrentSlowStopMoveOffsetTime, 0, TotalSlowStopMoveOffsetTime); + CurrentSlowStopMoveOffsetTime -= DeltaTime; + FVector Location = GlobeAnchor->GetLongitudeLatitudeHeight(); + FVector TargetLocation = Location + MoveDirectionLast * SlowStopMoveSpeed * SpeedMulityplier; + /*if (TargetLocation.X > 180) { + TargetLocation.X = TargetLocation.X - 360; + } + else if (TargetLocation.X < -180) { + TargetLocation.X = TargetLocation.X + 360; + }*/ + + /*if (TargetLocation.Y > 90) { + TargetLocation.Y = TargetLocation.Y - 180; + } + else if (TargetLocation.Y < -90) { + TargetLocation.Y = TargetLocation.Y + 180; + }*/ + TargetLocation.Z = CurrentHeight; + GlobeAnchor->MoveToLongitudeLatitudeHeight(TargetLocation); + if (!GetWorldTimerManager().IsTimerActive(UpdateOriginLongitudeLatitdeTimer)) { + DelayUpdateOrigin(); + } + } +} + +void ARover::_MoveForward(const FInputActionValue& TheValue) +{ + float Value = TheValue.GetMagnitude(); + if (Value && GetController()) { + StopMouseLeftMove(); + AdjustSpeedByHeight(); + FRotator ControlRotation = GetControlRotation(); + FRotator Rotation(ControlRotation.Pitch, ControlRotation.Yaw, 0); + FVector Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::X); + float Height = GlobeAnchor->GetHeight(); + if (Height < 50)Height = 50; + else if (Height > 10001620 && Value < 0)Height = 0; + AddMovementInput(Direction, Value * Height * 0.000001); + if ((GetActorLocation() - screenMiddleLocation).Length() > 8000000)return; + UpdateOrignLongitudeLatitude(); + bPressMoveButton = true; + UpdateCurrentHeight(); + } +} + +void ARover::ReleaseMoveButton() +{ + bPressMoveButton = false; +} + +void ARover::StopMoveForward() +{ + bMoveForward = false; + ForwardDirection = FVector(0); +} + +void ARover::StopMoveRight() +{ + bMoveRight = false; + RightDirection = FVector(0); +} + +void ARover::AllowLeftMouseMovePlayer(bool bAllow) +{ + bAllowMouseLeftMove = bAllow; + if (!bAllowMouseLeftMove)MoveToLocation = FVector(0); +} + +bool ARover::GetKeyMoveState() +{ + return bKeyMove; +} + +void ARover::UpdateSlideRotation(float DeltaTime) +{ + if (bPressMouseRightKey) return; + if (SlideTime <= 0)return; + GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::White, TEXT("正在Tick旋转")); + SlideTime -= DeltaTime; + float ScaleValue = UKismetMathLibrary::NormalizeToRange(SlideTime, 0, TotalSlideTime); + + float _SlideSpeed = SlideSpeed * ScaleValue; + AroundPointRotation(_SlideSpeed, EAxis::X); +} + + +void ARover::UpdateOrignLongitudeLatitude(float Time) +{ + CheckUpdateOrignLongitudeLatitude(); +} + +void ARover::FlyTo(const FVector& LongitudeLatitude, double YawAtDestination, double PitchAtDestination) +{ + if (bFlying) { + FlyComp->InterruptFlight(); + } + StopMouseLeftMove(); + OnFlyStart(LongitudeLatitude, YawAtDestination, PitchAtDestination); + FlyComp->FlyToLocationLongitudeLatitudeHeight(LongitudeLatitude, YawAtDestination, PitchAtDestination, true); + //CheckUpdateOrignLongitudeLatitude(); + if (GetWorldTimerManager().IsTimerActive(UpdateFlyOriginTimer))GetWorldTimerManager().ClearTimer(UpdateFlyOriginTimer); + GetWorldTimerManager().SetTimer(UpdateFlyOriginTimer, this, &ARover::CheckUpdateOrignLongitudeLatitude, 0.01f, true); + bFlying = true; +} + +void ARover::AssistMouseRollDistance(float Value, const FVector2D& ZoomScreenPosition) +{ + std::optional< FVector2D> _ZoomScreenPosition; + if (ZoomScreenPosition != FVector2D(-1)) { + _ZoomScreenPosition = ZoomScreenPosition; + } + AssistMouseRollDistance(Value, std::nullopt, _ZoomScreenPosition); +} + +void ARover::AssistMouseRollDistance(float Value, std::optional _TS_ZoomHitResult, std::optional ZoomScreenPosition) +{ + StopMouseLeftMove(); + FVector2D ZoomRollPosition; + if (ZoomScreenPosition.has_value()) { + ZoomRollPosition = ZoomScreenPosition.value(); + } + else { + PlayerController->GetMousePosition(ZoomRollPosition.X, ZoomRollPosition.Y); + } + FVector ActorLocation = GetActorLocation(); + float Height = GlobeAnchor->GetHeight(); + FVector WorldLocation; + FVector WorldDirection; + if (bFollowSportTrace) { + FVector2D screenCenter = ARoverController::GetScreenCenterPosition(); + PlayerController->DeprojectScreenPositionToWorld(screenCenter.X, screenCenter.Y, WorldLocation, WorldDirection); + } + else { + + if (_TS_ZoomHitResult == std::nullopt) { + PlayerController->DeprojectScreenPositionToWorld(ZoomRollPosition.X, ZoomRollPosition.Y, WorldLocation, WorldDirection); + } + else if (_TS_ZoomHitResult->bBlockingHit) { + WorldDirection = (_TS_ZoomHitResult->Location - GetActorLocation()).GetSafeNormal(); + } + } + if (Value < 0) { + if (ActorLocation.Z >= CurrentMaxRollDistance * MaxRollCoefficient)return; + WorldDirection *= -1; + } + float Speed = 0; + + FHitResult UnderMouseHitResult; + if (_TS_ZoomHitResult == std::nullopt) { + PlayerController->GetHitResultAtScreenPosition(ZoomRollPosition, ECollisionChannel::ECC_Visibility, true, UnderMouseHitResult); + } + else { + UnderMouseHitResult.bBlockingHit = _TS_ZoomHitResult->bBlockingHit; + UnderMouseHitResult.Location = _TS_ZoomHitResult->Location; + } + if (UnderMouseHitResult.bBlockingHit) { + float TargetPointWithSelfDistance = (UnderMouseHitResult.Location - GetActorLocation()).Length(); + Speed = TargetPointWithSelfDistance * ZoomRollSpeed * 0.01; + if (Value > 0 && (UnderMouseHitResult.Location - GetActorLocation()).Length() < 50)return; + } + else { + Speed = Height * ZoomRollSpeed; + } + ActorLocation += WorldDirection * Speed * FMath::Abs(Value); + if (ActorLocation.Z > CurrentMaxRollDistance * MaxRollCoefficient) { + ActorLocation.Z = CurrentMaxRollDistance * MaxRollCoefficient; + } + if (Value > 0) { + FVector2D screenCenterPosition = ARoverController::GetScreenCenterPosition(); + if ((screenCenterPosition - ZoomRollPosition).Length() > 300) { + if (Height > ZoomOffsetHeightValue) { + FHitResult MouseHitResult; + if (PlayerController->GetUnderScreenHitPosition(ZoomRollPosition, MouseHitResult)) { + FHitResult screenHitResult; + if (PlayerController->GetUnderscreenCenterHitPosition(screenHitResult)) { + float Distance = (MouseHitResult.Location - screenHitResult.Location).Length(); + FVector Direction = (MouseHitResult.Location - screenHitResult.Location).GetSafeNormal(); + ActorLocation += Direction * Distance * ZoomOffsetMulitiplier; + } + } + } + } + } + if (GetWorldTimerManager().IsTimerActive(PlayerController->RotateCameraTimer)) { + if ((ActorLocation - screenMiddleLocation).Length() > 5000000 && Value < 0)return; + } + SetActorLocation(ActorLocation); + CurrentHeight = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(ActorLocation).Z; + AdjustSpeedByHeight(); + UpdateOrignLongitudeLatitude(); +} + +FVector ARover::GetCurrentLongitudeLatitude() +{ + return FVector(); +} + +void ARover::CheckUpdateOrignLongitudeLatitude() +{ + if (!IsUpdateOrignLongitudeLatitude)return; + if (GetWorldTimerManager().IsTimerActive(PlayerController->RotateCameraTimer) || Georeference == nullptr)return; + FVector OriginLongitudeLatitude = Georeference->GetOriginLongitudeLatitudeHeight(); + FVector SelfLongitudeLatitude = GlobeAnchor->GetLongitudeLatitudeHeight(); + SelfLongitudeLatitude.Z = OriginLongitudeLatitude.Z; + if (FMath::FloorToInt32(OriginLongitudeLatitude.X) != FMath::FloorToInt32(SelfLongitudeLatitude.X) || + FMath::FloorToInt32(OriginLongitudeLatitude.Y) != FMath::FloorToInt32(SelfLongitudeLatitude.Y)) { + int32 Lon = FMath::FloorToInt32(SelfLongitudeLatitude.X / 1.f); + int32 Lat = FMath::FloorToInt32(SelfLongitudeLatitude.Y / 1.f); + + Georeference->SetOriginLongitudeLatitudeHeight(FVector(Lon * 1, Lat * 1, SelfLongitudeLatitude.Z)); + UpdateOriginCoordinate(); + } +} + +float ARover::GetHeight() const +{ + return GlobeAnchor->GetHeight(); +} + +void ARover::AroundPointRotation(float TheValue, EAxis::Type AxisType, FVector _RotationPoint) +{ + if (!IsEnabledAroundPointRotation)return; + if (GlobeAnchor->GetHeight() > LimitValueOfRotateAroundPoint || bPressMoveButton) { + if (bPressMoveButton) { + if (GetWorldTimerManager().IsTimerActive(ReleaseMoveButtonTimer)) { + GetWorldTimerManager().ClearTimer(ReleaseMoveButtonTimer); + } + FTimerDelegate Delegate; + Delegate.BindLambda([this]() { + bPressMoveButton = false; + }); + GetWorldTimerManager().SetTimer(ReleaseMoveButtonTimer, Delegate, 0.1f, false); + } + return; + } + // 停止移动 + MoveToLocation = FVector(0); + FVector MovePoint = FVector(0); + FRotator ViewRotation(0); + FVector RotationPointLocation = + _RotationPoint != FVector(-1) ? + _RotationPoint : + screenMiddleLocation; + if (AxisType == EAxis::X) { + FVector Vector = GetActorLocation() - RotationPointLocation; + + float Angle = RotateAngle * TheValue; + FVector p = Vector.RotateAngleAxis(Angle, FVector::UpVector); + MovePoint = (p + RotationPointLocation); + ViewRotation = GetControlRotation(); + ViewRotation.Pitch = FMath::UnwindDegrees(ViewRotation.Pitch); + ViewRotation.Yaw += Angle; + //PlayerController->SetControlRotation(Rotation); + + } + else { + + FVector ActorLocation = GetActorLocation(); + FVector CurrentMoveAixs = ActorLocation - RotationPointLocation; + ActorLocation.Z = RotationPointLocation.Z; + FVector BaseAxis = ActorLocation - RotationPointLocation; + FVector RotateAxis = BaseAxis.RotateAngleAxis(90.f, FVector::UpVector); + float Angle = RotateAngle * TheValue; + FVector FinishAxis = CurrentMoveAixs.RotateAngleAxis(Angle, RotateAxis.GetSafeNormal()); + + FVector FinishDirectionAixs = FinishAxis.GetSafeNormal(); + // 判断是否是同方向 + float SameDirection = UKismetMathLibrary::Dot_VectorVector(FinishDirectionAixs, RotationPointLocation.UpVector); + if (SameDirection >= 0.999 && SameDirection <= 1.f) { + if (bLimitViewport) { + return; + } + } + else { + bLimitViewport = true; + } + MovePoint = FinishAxis + RotationPointLocation; + ViewRotation = (RotationPointLocation - MovePoint).Rotation(); + if (FMath::Abs(ViewRotation.Pitch) > FMath::Abs(GetControlRotation().Pitch)) { + if (FMath::Abs(ViewRotation.Pitch) >= 89)return; + } + + } + FVector SelfActorLocation = GetActorLocation(); + FHitResult HitResult; + FCollisionQueryParams QueryParam; + QueryParam.AddIgnoredActor(this); + if (GetWorld()->LineTraceSingleByChannel(HitResult, SelfActorLocation, MovePoint, ECollisionChannel::ECC_Visibility, QueryParam)) { + return; + //MovePoint =HitResult.Location + HitResult.Location.UpVector.GetSafeNormal() * 100; + } + if (ViewRotation.Pitch > 0)return; + SetActorLocation(MovePoint); + PlayerController->SetControlRotation(ViewRotation); + UpdateCurrentHeight(); +} + +void ARover::UpdatascreenCenterPointLocation() +{ + FHitResult HitResult; + FVector ScreenCenterLocation; + FVector ScreenCenterDirection; + FVector2D ScreenCenterPosition = ARoverController::GetScreenCenterPosition(); + + PlayerController->DeprojectScreenPositionToWorld(ScreenCenterPosition.X, ScreenCenterPosition.Y, ScreenCenterLocation, ScreenCenterDirection); + FVector End = ScreenCenterLocation + ScreenCenterDirection * 100000000; + if (GetWorld()->LineTraceSingleByChannel(HitResult, ScreenCenterLocation, End, ECollisionChannel::ECC_Visibility)) { + screenMiddleLocation = HitResult.Location; + } +} + +void ARover::AdjustSpeedByHeight() +{ + UpdateCurrentHeight(); + BaseMouseLeftMoveRate = GlobeAnchor->GetHeight() * LongitudeLatitudeControlHeightMulitiplier; + BaseMouseLeftMoveRate = FMath::Clamp(BaseMouseLeftMoveRate, 200, 3000); +} + +void ARover::StartSlowStopMove() +{ + bAllowUpdataMove = false; +} + +void ARover::StopMouseLeftMove() +{ + bAllowUpdataMove = false; + CurrentSlowStopMoveOffsetTime = 0; + bAllowInertialMove = false; +} + +void ARover::DelayUpdateOrigin(float DelayTime) +{ + if (!GetWorldTimerManager().IsTimerActive(UpdateOriginLongitudeLatitdeTimer)) { + FTimerDelegate TimerDelegate; + TimerDelegate.BindUFunction(this, TEXT("UpdateOrignLongitudeLatitude"), 0.01f); + GetWorld()->GetTimerManager().SetTimer(UpdateOriginLongitudeLatitdeTimer, TimerDelegate, DelayTime, false); + } +} + +void ARover::InertialMove(float DeltaTime) +{ + if (!bAllowInertialMove || GlobeAnchor->GetHeight() > ChangeHeightThreshold)return; + if (CurrentSlowStopMoveOffsetTime <= 0) { + CurrentSlowStopMoveOffsetTime = 0; + bAllowInertialMove = false; + return; + } + CurrentSlowStopMoveOffsetTime -= DeltaTime; + float SpeedMulityplier = UKismetMathLibrary::NormalizeToRange(CurrentSlowStopMoveOffsetTime, 0, TotalSlowStopMoveOffsetTime); + FVector Location = GetActorLocation(); + FVector TargetLocation = Location + MoveDirectionLast * CurrentMoveDistance * 0.3 * SpeedMulityplier; + FVector TargetLontitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(TargetLocation); + float Latitude = TargetLontitudeLatitude.Y; + if (!(Latitude > MaxCrossingLatitude || Latitude < -MaxCrossingLatitude)) { + TargetLontitudeLatitude.Z = CurrentHeight; + TargetLocation = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(TargetLontitudeLatitude); + SetActorLocation(TargetLocation); + } + UpdateOrignLongitudeLatitude(); +} diff --git a/Source/BXSSP/Private/RoverController.cpp b/Source/BXSSP/Private/RoverController.cpp new file mode 100644 index 0000000..0ca6fcf --- /dev/null +++ b/Source/BXSSP/Private/RoverController.cpp @@ -0,0 +1,99 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "RoverController.h" +#include "Rover.h" +#include "RoverGameModeBase.h" +#include "Kismet/GameplayStatics.h" +#include "Kismet/KismetMathLibrary.h" + +ARoverController* ARoverController::PlayerController = nullptr; + +ARoverController::ARoverController() +{ + PlayerController = this; +} +void ARoverController::BeginPlay() +{ + + Super::BeginPlay(); + ARoverGameModeBase::Init(); + if (UGameplayStatics::GetPlayerController(GetWorld(), 0) == this) { + + SetShowMouseCursor(true); + Rover = Cast(UGameplayStatics::GetPlayerPawn(GetWorld(), 0)); + + UE_LOG(LogTemp, Log, TEXT("Init Successful")); + } +} + + +void ARoverController::SetMouseShowStatus(bool bStatus) +{ + if (bStatus) { + GetWorldTimerManager().ClearTimer(ResetMousePositionTimer); + } + else { + GetMousePosition(ClickMousePosition.X, ClickMousePosition.Y); + GetWorldTimerManager().ClearTimer(ResetMousePositionTimer); + GetWorldTimerManager().SetTimer(ResetMousePositionTimer, this, &ARoverController::ResetMousePositionToClickPoint, 0.05f, true); + } + SetShowMouseCursor(bStatus); +} + +bool ARoverController::GetUnderMouseHitPosition(FHitResult& HitResult) +{ + FVector2D MousePosition; + GetMousePosition(MousePosition.X, MousePosition.Y); + return GetUnderScreenHitPosition(MousePosition, HitResult); +} + +bool ARoverController::GetUnderScreenHitPosition(const FVector2D& ScreenPosition, FHitResult& HitResult) +{ + FVector WorldLocation; + FVector WorldDirection; + DeprojectScreenPositionToWorld(ScreenPosition.X, ScreenPosition.Y, WorldLocation, WorldDirection); + FVector End = WorldLocation + WorldDirection * 10000000000; + if (GetWorld()->LineTraceSingleByChannel(HitResult, WorldLocation, End, ECollisionChannel::ECC_Visibility)) { + return true; + } + return false; +} + +bool ARoverController::GetUnderscreenCenterHitPosition(FHitResult& HitResult) +{ + FVector WorldLocation; + FVector WorldDirection; + FVector2D ScreenCenter = GetScreenCenterPosition(); + DeprojectScreenPositionToWorld(ScreenCenter.X, ScreenCenter.Y, WorldLocation, WorldDirection); + FVector End = WorldLocation + WorldDirection * 10000000000; + if (GetWorld()->LineTraceSingleByChannel(HitResult, WorldLocation, End, ECollisionChannel::ECC_Visibility)) { + return true; + } + return false; +} + +FVector2D ARoverController::GetScreenCenterPosition() +{ + FVector2D ScreenCenter; + GEngine->GameViewport->GetViewportSize(ScreenCenter); + ScreenCenter *= 0.5; + return ScreenCenter; +} + + +void ARoverController::ResetMousePositionToClickPoint() +{ + SetMouseLocation(ClickMousePosition.X, ClickMousePosition.Y); +} + +void ARoverController::RotateCameraToTargetPoint(FRotator Rotation) +{ + FRotator SelfRotation = GetControlRotation(); + if (UKismetMathLibrary::Dot_VectorVector(SelfRotation.Vector(), Rotation.Vector()) >= 0.999999) { + SetControlRotation(Rotation); + Rover->UpdatascreenCenterPointLocation(); + GetWorldTimerManager().ClearTimer(RotateCameraTimer); + return; + } + SetControlRotation(UKismetMathLibrary::RInterpTo(SelfRotation, Rotation, GetWorld()->GetDeltaSeconds(), 5.f)); +} diff --git a/Source/BXSSP/Private/RoverGameModeBase.cpp b/Source/BXSSP/Private/RoverGameModeBase.cpp new file mode 100644 index 0000000..48c8018 --- /dev/null +++ b/Source/BXSSP/Private/RoverGameModeBase.cpp @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "RoverGameModeBase.h" + +ARoverGameModeBase* ARoverGameModeBase::BaseGameMode = nullptr; + +ARoverGameModeBase::ARoverGameModeBase() +{ + BaseGameMode = this; +} + +void ARoverGameModeBase::Init() +{ +} diff --git a/Source/BXSSP/Public/MainHUD.h b/Source/BXSSP/Public/MainHUD.h new file mode 100644 index 0000000..1ca3307 --- /dev/null +++ b/Source/BXSSP/Public/MainHUD.h @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/HUD.h" +#include "MainHUD.generated.h" + +/** + * + */ +UCLASS() +class BXSSP_API AMainHUD : public AHUD +{ + GENERATED_BODY() + +}; diff --git a/Source/BXSSP/Public/Rover.h b/Source/BXSSP/Public/Rover.h new file mode 100644 index 0000000..cbc4e1f --- /dev/null +++ b/Source/BXSSP/Public/Rover.h @@ -0,0 +1,467 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GlobeAwareDefaultPawn.h" +#include "Interfaces/IHttpRequest.h" +#include "Rover.generated.h" + +class UInputAction; +struct FInputActionValue; +class UInputMappingContext; +class ADefaultPawnController; +class UCesiumFlyToComponent; +class ARoverController; +class UCameraComponent; +class USpringArmComponent; + +enum class ESelecteItemMode :uint8 { + ESM_Single, + ESM_Multiple, + ESM_Default +}; +enum class ETSAction :uint8 { + ETS_Default, + ETS_RotationOrZoom, + ETS_UPDown +}; +/** + * + */ +UCLASS() +class BXSSP_API ARover : public AGlobeAwareDefaultPawn +{ + GENERATED_BODY() + +public: + + ARover(); + + virtual void Tick(float DeltaTime)override; + UFUNCTION(BlueprintCallable) + void UpdateOrignLongitudeLatitude(float Time = 0.01f); + + UFUNCTION(BlueprintCallable) + void FlyTo(const FVector& LongitudeLatitude, double YawAtDestination, double PitchAtDestination); + + /*UFUNCTION(BlueprintCallable) + void FlyTo(const FVector& LongitudeLatitude, double YawAtDestination, double PitchAtDestination);*/ + UFUNCTION(BlueprintCallable) + void AssistMouseRollDistance(float Value, const FVector2D& ZoomScreenPosition = FVector2D(-1, -1)); + // 辅助通过滚动轴缩进距离 + void AssistMouseRollDistance(float Value, std::optional _TS_ZoomHitResult, std::optional ZoomScreenPosition = std::nullopt); + FVector GetCurrentLongitudeLatitude(); + + bool IsPressMouseLeft() { return bPressMouseLeftKey; } + + //检测是否更新原点经纬度 + UFUNCTION(BlueprintCallable) + void CheckUpdateOrignLongitudeLatitude(); + + float GetHeight()const; + + FORCEINLINE ARoverController* GetPlayerController()const { return PlayerController; } + + FORCEINLINE TSoftObjectPtr GetGeoreference() { return Georeference; } + + FORCEINLINE bool IsPressRightKey()const { return bPressMouseRightKey; } + + UFUNCTION(BlueprintCallable) + FORCEINLINE void SetAssistMouseLeftMoveActor(TSoftObjectPtr Object) { AssistMouseLeftMoveActor = Object; } + + FORCEINLINE void SetSelectedModeStatus(ESelecteItemMode Mode) { + LastSelecteItemMode = SelecteItemMode; + SelecteItemMode = Mode; + } + FORCEINLINE ESelecteItemMode GetSelectedModeStatus()const { return SelecteItemMode; } + FORCEINLINE ESelecteItemMode GetLastSelectedModeStatus()const { return LastSelecteItemMode; } + + //绕中心点旋转视角 + UFUNCTION(BlueprintCallable) + void AroundPointRotation(float TheValue, EAxis::Type AxisType = EAxis::Y, FVector _RotationPoint = FVector(-1)); + + FORCEINLINE bool IsTempStopAutoRotate()const { return bTempStopAutoRotate; } + // 更新屏幕中心点位置 + UFUNCTION(BlueprintCallable) + void UpdatascreenCenterPointLocation(); + + //通过高度调整速度 + void AdjustSpeedByHeight(); + + // fly开始时调用 + UFUNCTION(BlueprintImplementableEvent) + void OnFlyStart(const FVector& LongitudeLatitudeHeightDestination, + double YawAtDestination, + double PitchAtDestination); + + + UFUNCTION(BlueprintCallable) + void ModifyMaxRollCoefficient(float Coefficient); + UCameraComponent* GetFollowCamera()const { return Camera; } + void _MoveRight(const FInputActionValue& TheValue); + UFUNCTION(BlueprintCallable) + void UpdateCurrentHeight(); + FORCEINLINE float GetCurrentHeight()const { return CurrentHeight; } + // 重置玩家对象属性,用于因某些原因导致的系统事件失效情况 + UFUNCTION(BlueprintCallable) + void ResetPlayerProperty(); + UFUNCTION(BlueprintCallable) + void MoveToLongitudeLatitudeHeight(const FVector& LongitudeLatitudeHeight); + UFUNCTION(BlueprintPure) + bool IsFlying() { return bFlying; } + UFUNCTION(BlueprintCallable) + void EnableCameraLag(bool bOpen); + UFUNCTION(BlueprintCallable) + void SetMaxRollDistance(float _MaxDistance); + + FConvexVolume GetViewFrustum(); + bool CheckPointInViewFrustum(const FVector& Point); + + // 停止按键移动 + UFUNCTION(BlueprintCallable) + void StopKeyMove(); + // 允许按键移动 + UFUNCTION(BlueprintCallable) + void StartKeyMove(); + UFUNCTION(BlueprintCallable) + void SetEnabledAroundPointRotation(bool bEnabled) { IsEnabledAroundPointRotation = bEnabled; } + UFUNCTION(BlueprintCallable) + void ClearCurrentSlowStopMoveOffsetTime(); +public: + //正在创建对象 + UPROPERTY(BlueprintReadWrite) + bool IsCreatingActor; +protected: + + virtual void BeginPlay()override; + + virtual void SetupPlayerInputComponent(UInputComponent* InInputComponent) override; + + void PressMouseMiddleButton(); + void ReleaseMouseMiddleButton(); + UFUNCTION(BlueprintCallable) + void PressMouseLeftButton(); + UFUNCTION(BlueprintCallable) + void ReleaseMouseLeftButton(); + UFUNCTION(BlueprintCallable) + void PressMouseRightButton(); + UFUNCTION(BlueprintCallable) + void ReleaseMouseRightButton(); + void _TurnAtRate(const FInputActionValue& Value); + void GamePadTurnAtRate(const FInputActionValue& Value); + void _LookUpAtRate(const FInputActionValue& Value); + void GamePadLookUpAtRate(const FInputActionValue& Value); + // 通过滚动轴缩进距离 + void MouseRollDistance(const FInputActionValue& Value); + void TS_TriggeredTwoTouch(const FInputActionValue& Value); + void TS_MouseRollDistance(const FInputActionValue& Value); + void TS_PressTwoTouch(); + void TS_ReleaseTwoTouch(); + void TS_FOVRotation(const FInputActionValue& Value); + void TS_UpDownPitch(const FInputActionValue& Value); + void TS_StartAction(); + void MouseLeftMovePawn(const FInputActionValue& Value); + UFUNCTION(BlueprintCallable) + void TouchMovePawn(FVector2D CurScreenPosition, FVector2D LastScreenPosition); + + void UpdataMoveToLocation(float DeltaTime); + + UFUNCTION(BlueprintCallable) + FORCEINLINE void SetGeoreference(TSoftObjectPtr TheGeoreference) { Georeference = TheGeoreference; } + + void _MoveForward(const FInputActionValue& TheValue); + + void ReleaseMoveButton(); + + void StopMoveForward(); + void StopMoveRight(); + UFUNCTION(BlueprintImplementableEvent) + void UpdateOriginCoordinate(); + + // 设置是否允许鼠标左键移动 + UFUNCTION(BlueprintCallable) + void AllowLeftMouseMovePlayer(bool bAllow); + UFUNCTION(BlueprintCallable) + bool GetKeyMoveState(); + + UFUNCTION(BlueprintCallable) + bool GetPressLeftMouseKey() { return bPressMouseLeftKey; }; + + // 自动更新,通过鼠标右键进行旋转时产生的滑动效果 + void UpdateSlideRotation(float DeltaTime); +protected: + //鼠标中键值 + UPROPERTY(BlueprintReadOnly) + float MiddleKeyValue; +private: + + void StartSlowStopMove(); + + + // 停止通过鼠标左键移动 + void StopMouseLeftMove(); + // 延迟更新原点 + void DelayUpdateOrigin(float DelayTime = 0.1); + + // 当鼠标左键移动以后的缓冲惯性移动 + void InertialMove(float DeltaTime); +private: + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UInputAction* MouseLeftAsset; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UInputAction* MouseRightAsset; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UInputAction* TurnAsset; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UInputAction* LookUpAsset; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UInputAction* MouseRollAxisAsset; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UInputAction* MouseMiddleAxisAsset; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UInputAction* MoveForwardAsset; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UInputAction* MoveRightAsset; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UInputAction* TS_TwoTouchAsset; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UInputAction* GamePadTurnAsset; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UInputAction* GamePadLookUPAsset; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UInputMappingContext* BaseInputAction; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Controller, meta = (AllowPrivateAccess = "true")) + ARoverController* PlayerController; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UCesiumFlyToComponent* FlyComp; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + UCameraComponent* Camera; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + USpringArmComponent* SpringArm; + // 是否按下鼠标中键 + bool bPressMouseMiddleKey; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + float SelfBaseTurnRate; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputAction, meta = (AllowPrivateAccess = "true")) + float SelfBaseLookUpRate; + + // 滚动中键时的缩放速度 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + float ZoomRollSpeed; + + // 当绕中间旋转时保存的屏幕中间位置 + FVector screenMiddleLocation; + + // 按下中键旋转的角度 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + float RotateAngle; + + // 是否按下鼠标右键 + bool bPressMouseRightKey; + // 是否按下鼠标左键 + bool bPressMouseLeftKey; + + FVector2D MousePosition; + FVector2D LastMousePosition; + + FVector2D TestMousePosition; + FVector2D TestLastMousePosition; + + // 鼠标左键基础移动速率 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + float BaseMouseLeftMoveRate; + + // 通过鼠标左键移动到的位置 + FVector MoveToLocation; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, BlueprintSetter = SetGeoreference, Category = Property, meta = (AllowPrivateAccess = "true")) + TSoftObjectPtr Georeference; + + // 刷新当前原点经纬度 + FTimerHandle RefreshOriginLongitudeLatitudeTimer; + + // 当超过最大距离时刷新原点经纬度 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + float MaxDistance; + + // 当前是否在向(前/后)移动 + bool bMoveForward; + // 当前是否在向(左/右)移动 + bool bMoveRight; + + FVector ForwardDirection; + FVector RightDirection; + + // 按键移动速度 + float MoveSpeed; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Class, meta = (AllowPrivateAccess = "true")) + TSubclassOf QuitGameDialogClass; + + // 是否限制绕点旋转的视角 + bool bLimitViewport; + // 是否允许鼠标左键移动 + bool bAllowMouseLeftMove; + // 当使用左键移动时,控制高度来控制移动速度 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Move, meta = (AllowPrivateAccess = "true")) + float ControlHeightMulitiplier; + // 当使用左键移动时,控制高度来控制移动速度乘数 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Move, meta = (AllowPrivateAccess = "true")) + float LongitudeLatitudeControlHeightMulitiplier; + + // 鼠标左键移动时的缓慢停止移动计时器 + FTimerHandle SlowStopMoveTimer; + + + // 鼠标移动偏移乘数(用于多少时间停止移动的乘数) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Move, meta = (AllowPrivateAccess = "true")) + float MouseMoveOffsetMulitiplier; + + // 是否允许更新鼠标左键移动 + bool bAllowUpdataMove; + // 鼠标最后一次移动的方向 + FVector MoveDirectionLast; + // 缓慢停止时的移动速度 + float SlowStopMoveSpeed; + // 总的缓慢停止时的拖尾移动时间 + float TotalSlowStopMoveOffsetTime; + // 当前缓慢停止时的拖尾移动时间 + float CurrentSlowStopMoveOffsetTime; + // 高度转变鼠标移动方式的阈值 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Move, meta = (AllowPrivateAccess = "true")) + float ChangeHeightThreshold; + // 更新原点经纬度计时器 + FTimerHandle UpdateOriginLongitudeLatitdeTimer; + + // 当前是否正在飞行 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + bool bFlying; + + // 当进行滚动轴缩放时,滚动点离屏幕中心点远时的平移缩放偏移乘数 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + float ZoomOffsetMulitiplier; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + // 当高于该阈值时更新缩放偏移 + float ZoomOffsetHeightValue; + // 当前是否跟随运动轨迹 + bool bFollowSportTrace; + + + // 在飞行途中更新原点计时器 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Timer, meta = (AllowPrivateAccess = "true")) + FTimerHandle UpdateFlyOriginTimer; + + // 从当前位置到移动位置的距离 + double CurrentMoveDistance; + // 移动速度乘数 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + double MoveSpeedMultiplier; + + // 是否允许惯性移动 + bool bAllowInertialMove; + + FVector MouseClickLongitudeLatitude; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, BlueprintSetter = SetAssistMouseLeftMoveActor, Category = Move, meta = (AllowPrivateAccess = "true")) + TSoftObjectPtr< AStaticMeshActor> AssistMouseLeftMoveActor; + + ECollisionChannel CheckMoveCollisionChannel; + + // 当前选择的模式 + ESelecteItemMode SelecteItemMode; + // 上一次选择的模式 + ESelecteItemMode LastSelecteItemMode; + + // 当正在进行自动旋转时,如果按下鼠标右键自行选择角度时临时停止旋转 + bool bTempStopAutoRotate; + + // 当前高亮模型对象 + USkeletalMeshComponent* CurrentHightLightModel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + bool bHDRIMode = false; + + // 鼠标右键的滑动速度 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + float SlideSpeed = 1; + // 滑动时间 + float SlideTime = 0; + float TotalSlideTime = 0; + + // 滑动速度乘数 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Move, meta = (AllowPrivateAccess = "true")) + float SlideSpeedMulitiplier = 0.01f; + // 当前最大滚动距离 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Move, meta = (AllowPrivateAccess = "true")) + float CurrentMaxRollDistance = 1000000000.0f; + //最大滚动系数 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Move, meta = (AllowPrivateAccess = "true")) + float MaxRollCoefficient = 1.f; + // 是否按下移动按钮(W,S,A,D) + bool bPressMoveButton = false; + + // 绕一个点旋转的极限值 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rotate, meta = (AllowPrivateAccess = "true")) + float LimitValueOfRotateAroundPoint = 911352.5488545; + // 当前是否按下双指缩放 + bool bTS_PressTwoTouch = false; + + FVector2D Touch1, Touch2; + FVector2D LastTouch1, LastTouch2; + bool bPressTouch1, bPressTouch2; + FTimerHandle TS_ActionTimer; + bool bTS_StartAction = false; + ETSAction TS_ActionStatus = ETSAction::ETS_Default; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + float TS_DelayTime = 0.07f; + std::optional TS_ZoomHitResult = std::nullopt; + // 双指触摸延迟释放 + FTimerHandle TS_DelayReleaseTimer; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + float CurrentHeight = 0; + // 最大跨越纬度 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property, meta = (AllowPrivateAccess = "true")) + float MaxCrossingLatitude = 75.f; + // 当通过鼠标左键移动地球时,鼠标没有点到地形的情况下运行 + bool bAllowUpdateSlide = false; + // 当角色纬度超过正负MaxCrossingLatitude时,启用平滑过渡 + FTimerHandle CrossingLatitudeTimer; + // 更新高度计时器 + FTimerHandle UpdateHeightTimer; + // 用于更新在太空没有击中地面时是否使用缓慢滑行 + bool bAllowSlowStopMove = true; + // 当前是否在仰视天空,如果在仰视且点中天空就执行平移变旋转视角 + bool bCurrentLookingup = false; + // 当在旋转时释放移动操作 + FTimerHandle ReleaseMoveButtonTimer; + + std::atomic PlayerLongitudeLatitudeHeight = FVector(0); + + bool bKeyMove = true; + + bool IsEnabledAroundPointRotation = true; +public: + static ARover* PlayerPawn; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Property) + bool IsUpdateOrignLongitudeLatitude = true; +}; + diff --git a/Source/BXSSP/Public/RoverController.h b/Source/BXSSP/Public/RoverController.h new file mode 100644 index 0000000..a8af5ab --- /dev/null +++ b/Source/BXSSP/Public/RoverController.h @@ -0,0 +1,57 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerController.h" +#include "RoverController.generated.h" + +/** + * + */ +UCLASS() +class BXSSP_API ARoverController : public APlayerController +{ + GENERATED_BODY() +public: + ARoverController(); + + // 设置鼠标显示状态 + UFUNCTION(BlueprintCallable) + void SetMouseShowStatus(bool bStatus); + + // 获得鼠标下撞击点位置 + UFUNCTION(BlueprintCallable) + bool GetUnderMouseHitPosition(FHitResult& HitResult); + + // 获得屏幕中心撞击位置 + UFUNCTION(BlueprintPure) + bool GetUnderscreenCenterHitPosition(FHitResult& HitResult); + bool GetUnderScreenHitPosition(const FVector2D& ScreenPosition, FHitResult& HitResult); + UFUNCTION(BlueprintPure) + static FVector2D GetScreenCenterPosition(); +protected: + + virtual void BeginPlay()override; + +private: + // 重置鼠标位置到点击点 + void ResetMousePositionToClickPoint(); + UFUNCTION() + void RotateCameraToTargetPoint(FRotator Rotation); +private: + + // 把鼠标位置重置到屏幕开始点击时的位置(用于防止鼠标拖到屏幕边界出现不能拖动情况) + FTimerHandle ResetMousePositionTimer; + + FVector2D ClickMousePosition; + + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Player, meta = (AllowPrivateAccess = "true")) + class ARover* Rover; +public: + static ARoverController* PlayerController; + // (当开始自动旋转时,先让摄像机看向目标对象)时用的计时器 + FTimerHandle RotateCameraTimer; + +}; diff --git a/Source/BXSSP/Public/RoverGameModeBase.h b/Source/BXSSP/Public/RoverGameModeBase.h new file mode 100644 index 0000000..3817694 --- /dev/null +++ b/Source/BXSSP/Public/RoverGameModeBase.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/GameModeBase.h" +#include "RoverGameModeBase.generated.h" + + + +/** + * + */ +UCLASS() +class BXSSP_API ARoverGameModeBase : public AGameModeBase +{ + GENERATED_BODY() +public: + + ARoverGameModeBase(); + static void Init(); +public: + static ARoverGameModeBase* BaseGameMode; +}; diff --git a/Source/BXSSPEditor.Target.cs b/Source/BXSSPEditor.Target.cs new file mode 100644 index 0000000..cc2aa10 --- /dev/null +++ b/Source/BXSSPEditor.Target.cs @@ -0,0 +1,15 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class BXSSPEditorTarget : TargetRules +{ + public BXSSPEditorTarget( TargetInfo Target) : base(Target) + { + Type = TargetType.Editor; + DefaultBuildSettings = BuildSettingsVersion.V4; + IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_3; + ExtraModuleNames.Add("BXSSP"); + } +}